diff --git a/.editorconfig b/.editorconfig index 0b1cbd9..6bb2ed3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,5 +1,9 @@ +# noinspection EditorConfigKeyCorrectness [*.kt] ktlint_standard_filename = disabled -[**/build/generated/**] +# noinspection EditorConfigKeyCorrectness +[**/generated/**] ktlint = disabled +generated_code = true +ij_formatter_enabled = false diff --git a/.idea/misc.xml b/.idea/misc.xml index d1bfd10..63390b3 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/README.md b/README.md index 07cac28..010df89 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ Each integration lives in the `integrations/` directory and has its own README. - [IntelliJ Platform](integrations/intellij-platform/README.md) — interactive access to IntelliJ Platform APIs from a running IDE process. - [HTTP Utilities](integrations/http-util/README.md) — JSON/serialization helpers and Ktor HTTP client wrappers for notebooks. - [Database](integrations/database/README.md) — helpers for configuring JDBC DataSources and working with Databases. +- [Widgets](integrations/widgets/README.md) — ipywidgets API for Kotlin notebooks. ## Contributing diff --git a/build.gradle.kts b/build.gradle.kts index b57bbdd..f7422e5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,7 @@ plugins { alias(libs.plugins.publisher) alias(libs.plugins.buildconfig) alias(libs.plugins.kotlin.serialization) apply false - alias(libs.plugins.ktlint) apply false + alias(libs.plugins.ktlint) } version = @@ -16,6 +16,13 @@ allprojects { version = rootProject.version plugins.apply("org.jlleitschuh.gradle.ktlint") + ktlint { + filter { + exclude { entry -> + entry.file.toString().contains("generated") + } + } + } repositories { mavenCentral() @@ -23,6 +30,7 @@ allprojects { tasks.withType { useJUnitPlatform() + maxHeapSize = "4G" outputs.upToDateWhen { false } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 403a25a..dd93335 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ # https://intellij-support.jetbrains.com/hc/en-us/articles/206544879-Selecting-the-JDK-version-the-IDE-will-run-under jvmTarget = "17" kotlin = "2.2.20" -kotlin-jupyter = "0.15.1-668" +kotlin-jupyter = "0.15.3-779-1" publishPlugin = "2.2.0-dev-71" intellijPlatformGradlePlugin = "2.10.3" intellijPlatform = "253-EAP-SNAPSHOT" # TODO: lower to 2025.1.3 GA whenever released with required changes diff --git a/integrations/intellij-platform/build.gradle.kts b/integrations/intellij-platform/build.gradle.kts index 7683683..ff623d4 100644 --- a/integrations/intellij-platform/build.gradle.kts +++ b/integrations/intellij-platform/build.gradle.kts @@ -12,10 +12,6 @@ plugins { val spaceUsername: String by properties val spaceToken: String by properties -allprojects { - version = rootProject.version -} - tasks.processJupyterApiResources { libraryProducers = listOf("org.jetbrains.kotlinx.jupyter.intellij.IntelliJPlatformJupyterIntegration") } diff --git a/integrations/intellij-platform/src/main/kotlin/org/jetbrains/kotlinx/jupyter/intellij/IntelliJPlatformJupyterIntegration.kt b/integrations/intellij-platform/src/main/kotlin/org/jetbrains/kotlinx/jupyter/intellij/IntelliJPlatformJupyterIntegration.kt index 29623bf..d3f3128 100644 --- a/integrations/intellij-platform/src/main/kotlin/org/jetbrains/kotlinx/jupyter/intellij/IntelliJPlatformJupyterIntegration.kt +++ b/integrations/intellij-platform/src/main/kotlin/org/jetbrains/kotlinx/jupyter/intellij/IntelliJPlatformJupyterIntegration.kt @@ -3,7 +3,6 @@ package org.jetbrains.kotlinx.jupyter.intellij import com.intellij.jupyter.core.executor.JupyterExecutionListener -import com.intellij.jupyter.core.jupyter.connections.action.JupyterRestartKernelListener import com.intellij.jupyter.core.jupyter.connections.execution.core.JupyterNotebookSession import com.intellij.openapi.application.ApplicationInfo import com.intellij.openapi.application.ApplicationNamesInfo @@ -48,7 +47,7 @@ class IntelliJPlatformJupyterIntegration : JupyterIntegration() { val productVersion = ApplicationInfo.getInstance().run { "$majorVersion.$minorVersion" } if (productVersion.toVersion() >= MINIMAL_SUPPORTED_IDE_VERSION) { - initializeDisposable(notebook) + initializeDisposable() initializeIntelliJPlatformClassloader(notebook) } else { val productName = ApplicationNamesInfo.getInstance().fullProductName @@ -95,7 +94,7 @@ class IntelliJPlatformJupyterIntegration : JupyterIntegration() { }.excludeUnwantedClasspathEntries() } - private fun KotlinKernelHost.initializeDisposable(notebook: Notebook) { + private fun KotlinKernelHost.initializeDisposable() { fun disposeIntegration() { Disposer.dispose(notebookDisposable) displayText("IntelliJ Platform integration is disposed") @@ -112,16 +111,6 @@ class IntelliJPlatformJupyterIntegration : JupyterIntegration() { }, ) } catch (_: LinkageError) { - val topic = JupyterRestartKernelListener.TOPIC - requireNotNull(currentProjectFromNotebook(notebook)) - .messageBus - .connect(notebookDisposable) - .subscribe( - topic, - JupyterRestartKernelListener { - disposeIntegration() - }, - ) } } diff --git a/integrations/widgets/AGENTS.md b/integrations/widgets/AGENTS.md new file mode 100644 index 0000000..fc2734c --- /dev/null +++ b/integrations/widgets/AGENTS.md @@ -0,0 +1,84 @@ +### Kotlin Jupyter Widgets Project Requirements & Guidelines + +This document summarizes the key architectural decisions, requirements, and technical details discovered and implemented during the widget development session. This information is intended for other agents working on this project. + +#### 1. Core Architecture +- **Modules**: + - `widgets-api`: Core logic, protocol implementation, and base classes. + - `widgets-generator`: Automates code generation from `schema.json`. + - `widgets-jupyter`: Integration with Kotlin Jupyter Notebook. + - `widgets-tests`: Integration and REPL tests. +- **Comm Targets**: + - `jupyter.widget`: Main target for widget instance synchronization. + - `jupyter.widget.control`: Used for global control messages like `request_states`. +- **State Synchronization**: Bi-directional sync via Jupyter Comms. Properties use delegation to track changes and sync with the frontend. + - `echoUpdateEnabled`: (Default: `false`) Controls whether frontend-initiated updates are echoed back. Useful for multi-frontend sync or backend overrides. +- **Binary Data**: Handled via binary buffers, not JSON-encoded. `ByteArray` properties are serialized as `null` in JSON and transferred via binary buffers, with paths specified in `buffer_paths`. + +#### 2. Code Generation Guidelines +- **Naming Conventions**: + - Use `toPascalCase()` for class and file names. + - Use `toCamelCase()` for property and factory method names. + - Widgets should always end with the `Widget` suffix (e.g., `IntSliderWidget`). Use `String.toWidgetClassName()` from `StringUtil.kt`. + - Handle abbreviations correctly (e.g., `HtmlWidget`, `VBoxWidget`). + - **Splitting Logic**: `StringUtil.splitIntoParts()` handles underscores, hyphens, spaces, and CASE transitions. It specifically allows single-letter parts followed by lowercase (e.g., `V` + `Box` -> `VBox`). +- **Base Widgets**: + - Some widgets (e.g., `OutputWidget`) are generated as `abstract Base` classes (e.g., `OutputWidgetBase`) to allow manual extensions. + - Base widgets have `internal` visibility for their `WidgetSpec`. + - No factory or manager extension methods are generated for base widgets. +- **Trait-based Inheritance**: + - Use `traits` in `WidgetGenerator.kt` to match widgets by property names and types. + - This allows common logic for selection widgets to be moved to specialized base classes like `SingleNullableSelectionWidgetBase`. + +#### 3. Selection Widget System +- **Specialized Bases**: + - `OptionWidgetBase`: Core logic for mapping labels (frontend) to values (backend). + - `SingleSelectionWidgetBase`: Non-nullable single selection (`index: Int`). + - `SingleNullableSelectionWidgetBase`: Nullable single selection (`index: Int?`). + - `MultipleSelectionWidgetBase`: Multiple selection (`index: List`). + - `SelectionRangeWidgetBase`: Range selection (`index: IntRange?`). +- **Key Properties**: + - `options`: `List>`. + - `simpleOptions`: `List` (labels used as values). + - `value`: High-level selection value(s) (e.g., `Any?` or `Pair?`). + - `label` / `labels`: Frontend labels for selection. + +#### 4. Type System & Serialization +- **Custom Types**: + - `IntRange`, `ClosedRange`: Serialized as 2-element lists `[start, end]`. + - `Pair`: Serialized as 2-element lists. + - `WidgetModel`: Serialized as strings with `IPY_MODEL_` prefix. +- **Type Overrides**: + - Use `assignedPropertyTypes` in `PropertyType.kt` to override schema-defined types (e.g., changing an `array` type to `IntRange` for `IntRangeSliderWidget.value`). +- **Dates & Times**: + - `Instant`, `LocalDate`, `LocalTime`: Serialized as ISO-8601 strings. +- **Union Types**: + - Generated as sealed interfaces with inline value classes for different types. + - Handled by `UnionType` with multiple deserializers attempted in order. + +#### 5. Messaging & Lifecycle +- **Custom Messages**: + - Use `WidgetModel.sendCustomMessage(content, metadata, buffers)` for actions not covered by property sync. + - Register listeners via `WidgetModel.addCustomMessageListener { content, metadata, buffers -> ... }`. + - Example: `OutputWidget.clearOutput()` uses a custom message with `method = "clear_output"`. +- **Closing Widgets**: + - `WidgetManager.closeWidget(widget)` sends a `comm_close` message and removes the widget from the manager's internal maps. + +#### 6. Testing Requirements +- **Assertions**: EXCLUSIVELY use Kotest `should*` notation (e.g., `result shouldBe 42`). Do not use `assert*`. +- **Naming**: Test method names MUST NOT be in camelCase. Use descriptive names in backticks (e.g., ``fun `should have 42`()`` or ``fun `check that 42 is returned`()``). +- **REPL Tests**: Inherit from `AbstractWidgetReplTest`. Use `shouldHaveNextOpenEvent`, `shouldHaveNextUpdateEvent`, etc., to verify the sequence of Comm events. +- **Type Tests**: `TypesTest.kt` covers all property serialization/deserialization. Use `TestWidgetManager.INSTANCE` for tests that don't need real manager logic. +- **Gradle Tasks**: + - `:generateWidgets`: Regenerates all widgets from `schema.json`. + - `:compileKotlin`: Verifies that manual and generated code are compatible. + +#### 7. Documentation & Style +- **KDocs**: Always use multiline format: + ```kotlin + /** + * Description here. + */ + ``` +- **Thread Safety**: Property updates are generally safe as long as the underlying messaging protocol is thread-safe, but explicit concurrency guarantees are not provided. +- **Generated Code**: NEVER manually edit files in `src/generated`. Update the `WidgetGenerator` instead. diff --git a/integrations/widgets/README.md b/integrations/widgets/README.md new file mode 100644 index 0000000..ce6dc3b --- /dev/null +++ b/integrations/widgets/README.md @@ -0,0 +1,139 @@ +[![JetBrains official project](https://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) +[![Kotlin experimental stability](https://img.shields.io/badge/project-experimental-kotlin.svg?colorA=555555&colorB=AC29EC&label=&logo=kotlin&logoColor=ffffff&logoWidth=10)](https://kotlinlang.org/docs/components-stability.html) + +# Kotlin Notebook Widgets Integration + +This integration provides a collection of interactive widgets for Kotlin Notebooks, such as sliders, labels, and more. It allows you to create a richer, more interactive experience within your notebooks. + +## Usage + +Use this API through the `%use widgets` magic command in a Kotlin Notebook. + +### Basic Widgets + +```kotlin +%use widgets + +val slider = intSliderWidget { + min = 0 + max = 100 + value = 50 + description = "Select a value:" +} + +val label = labelWidget { + value = "Current value: ${slider.value}" +} + +// Display the slider +slider +``` + +### Layouts and Containers + +Arrange widgets using `hBox`, `vBox`, `accordion`, or `tab`: + +```kotlin +val slider = intSliderWidget { description = "Slider" } +val text = textWidget { description = "Text" } + +val accordion = accordionWidget { + children = listOf(slider, text) + titles = listOf("Controls", "Input") +} + +accordion +``` + +### Linking Widgets + +You can link properties of different widgets together: + +```kotlin +val play = playWidget { + min = 0 + max = 100 + step = 1 + interval = 500 +} + +val slider = intSliderWidget() + +linkWidget { + source = play to "value" + target = slider to "value" +} + +hBoxWidget { children = listOf(play, slider) } +``` + +### Output Widget + +The `OutputWidget` can capture and display standard output and rich results: + +```kotlin +val out = outputWidget() +out // Display the widget + +out.withScope { + println("This will be printed inside the output widget") + DISPLAY("Rich output works too") +} +``` + +### Selection Widgets + +Various selection widgets like `dropdown`, `selectMultiple`, and `radioButtons` are available: + +```kotlin +val dropdown = dropdownWidget { + options = listOf( + "Option 1" to 1, + "Option 2" to 2, + "Option 3" to 3 + ) + value = 2 + description = "Choose:" +} +``` + +### Event Listeners + +You can react to widget property changes or custom messages from the frontend: + +```kotlin +val slider = intSliderWidget { description = "Slider" } +val label = labelWidget { value = "Value is 0" } + +// Listen to all property changes +slider.addChangeListener { patch, fromFrontend -> + if ("value" in patch) { + label.value = "Value is ${slider.value}" + } +} + +// Listen to a specific property change +slider.getProperty("value")?.addChangeListener { newValue, fromFrontend -> + println("Value changed to $newValue") +} + +vBoxWidget { children = listOf(slider, label) } +``` + +## Module structure + +This project consists of the following modules: + +- `widgets-api`: Contains the core widget implementations, protocols, and model definitions. +- `widgets-jupyter`: Provides the integration logic and useful helpers for Kotlin Jupyter notebooks. +- `widgets-generator`: Generates widget models from `schema.json`. +- `widgets-tests`: Contains integration tests for widgets. + +## Development + +Most widgets are automatically generated from a schema. +To regenerate widgets after changing `schema.json` or the generator itself, run: + +```bash +./gradlew :integrations:widgets:widgets-generator:generateWidgets +``` diff --git a/integrations/widgets/build.gradle.kts b/integrations/widgets/build.gradle.kts new file mode 100644 index 0000000..929ff19 --- /dev/null +++ b/integrations/widgets/build.gradle.kts @@ -0,0 +1,24 @@ +import org.jetbrains.kotlinx.publisher.apache2 +import org.jetbrains.kotlinx.publisher.githubRepo + +plugins { + alias(libs.plugins.publisher) +} + +kotlinPublications { + pom { + githubRepo("Kotlin", "kotlin-notebook-integrations") + inceptionYear = "2025" + licenses { + apache2() + } + developers { + developer { + id.set("kotlin-jupyter-team") + name.set("Kotlin Jupyter Team") + organization.set("JetBrains") + organizationUrl.set("https://www.jetbrains.com") + } + } + } +} diff --git a/integrations/widgets/notebooks/WidgetArch.png b/integrations/widgets/notebooks/WidgetArch.png new file mode 100644 index 0000000..9fadae7 Binary files /dev/null and b/integrations/widgets/notebooks/WidgetArch.png differ diff --git a/integrations/widgets/notebooks/output.ipynb b/integrations/widgets/notebooks/output.ipynb new file mode 100644 index 0000000..c62b119 --- /dev/null +++ b/integrations/widgets/notebooks/output.ipynb @@ -0,0 +1,152 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "1dc6dfe0338edca7", + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-16T10:53:58.196356Z", + "start_time": "2026-01-16T10:53:57.656370Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_3_jupyter", + "Line_4_jupyter", + "Line_5_jupyter", + "Line_6_jupyter", + "Line_7_jupyter" + ] + }, + "tags": [ + "skiptest" + ] + }, + "outputs": [], + "source": [ + "USE {\n", + " repositories { mavenLocal() }\n", + " dependencies {\n", + " implementation(\"org.jetbrains.kotlinx:kotlin-jupyter-widgets-jupyter:0.3.0-1-SNAPSHOT\")\n", + " }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "fc0a3dd0f8d182da", + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-16T10:54:15.513572Z", + "start_time": "2026-01-16T10:54:15.442978Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_8_jupyter" + ] + } + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b3cd2c4b-33e9-4410-9dc4-863a95686d8b", + "version_major": 1, + "version_minor": 0 + }, + "text/html": [ + "OutputModel(id=b3cd2c4b-33e9-4410-9dc4-863a95686d8b)" + ] + }, + "metadata": {}, + "output_type": "display_data", + "jetTransient": {} + } + ], + "source": [ + "val out = outputWidget()\n", + "DISPLAY(out)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "b15d36a922b1c5cf", + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-16T10:54:41.738265Z", + "start_time": "2026-01-16T10:54:41.684457Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_9_jupyter" + ] + } + }, + "outputs": [], + "source": [ + "out.withScope {\n", + " DISPLAY(\"helloo\")\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a44f5399f0d67f60", + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-16T10:54:48.619173Z", + "start_time": "2026-01-16T10:54:48.572730Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_10_jupyter" + ] + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[{output_type=display_data, data={text/plain=helloo}, metadata={}}]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "out.outputs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90094eb07622bfb5", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Kotlin", + "language": "kotlin", + "name": "kotlin" + }, + "language_info": { + "codemirror_mode": "text/x-kotlin", + "file_extension": ".kt", + "mimetype": "text/x-kotlin", + "name": "kotlin", + "nbconvert_exporter": "", + "pygments_lexer": "kotlin", + "version": "2.2.20" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/integrations/widgets/notebooks/widgets.ipynb b/integrations/widgets/notebooks/widgets.ipynb new file mode 100644 index 0000000..7bf9ad4 --- /dev/null +++ b/integrations/widgets/notebooks/widgets.ipynb @@ -0,0 +1,2115 @@ +{ + "cells": [ + { + "cell_type": "code", + "metadata": { + "collapsed": true, + "tags": [ + "skiptest" + ], + "ExecuteTime": { + "end_time": "2026-01-18T22:13:44.409009Z", + "start_time": "2026-01-18T22:13:43.790007Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_3_jupyter", + "Line_4_jupyter", + "Line_5_jupyter", + "Line_6_jupyter", + "Line_7_jupyter" + ] + } + }, + "source": [ + "USE {\n", + " repositories { mavenLocal() }\n", + " dependencies {\n", + " implementation(\"org.jetbrains.kotlinx:kotlin-jupyter-widgets-jupyter:0.3.0-1-SNAPSHOT\")\n", + " }\n", + "}\n", + "// TODO should use %use widgets" + ], + "id": "6ab15dfc5a6675e5", + "outputs": [], + "execution_count": 1 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Int slider", + "id": "63fa34c201973f98" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:44.537519Z", + "start_time": "2026-01-18T22:13:44.411631Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_8_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "intSliderWidget {\n", + " value = 7\n", + " min = 0\n", + " max = 10\n", + " step = 1\n", + " description = \"Test:\"\n", + " disabled = false\n", + " continuousUpdate = false\n", + " orientation = Orientation.Horizontal\n", + " readout = true\n", + " readoutFormat = \"d\"\n", + "}" + ], + "id": "7d8980a6695140f2", + "outputs": [ + { + "data": { + "text/html": [ + "IntSliderModel(id=2beff9c2-a593-4884-8676-2c812692e96d)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "2beff9c2-a593-4884-8676-2c812692e96d" + } + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 2 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Float sliders", + "id": "d26fb9406897d05e" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:44.664769Z", + "start_time": "2026-01-18T22:13:44.561589Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_9_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "floatSliderWidget {\n", + " value = 7.5\n", + " min = 0.0\n", + " max = 10.0\n", + " step = 0.1\n", + " description = \"Test:\"\n", + " disabled = false\n", + " continuousUpdate = false\n", + " orientation = Orientation.Horizontal\n", + " readout = true\n", + " readoutFormat = \".1f\"\n", + "}" + ], + "id": "719e237baf9a7645", + "outputs": [ + { + "data": { + "text/html": [ + "FloatSliderModel(id=02cf7eaa-0536-40d9-9401-5f46e161fe91)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "02cf7eaa-0536-40d9-9401-5f46e161fe91" + } + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 3 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:44.769802Z", + "start_time": "2026-01-18T22:13:44.673546Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_10_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.floatSlider {\n", + " value = 7.5\n", + " min = 0.0\n", + " max = 10.0\n", + " step = 0.1\n", + " description = \"Test:\"\n", + " disabled = false\n", + " continuousUpdate = false\n", + " orientation = Orientation.Vertical\n", + " readout = true\n", + " readoutFormat = \".1f\"\n", + "}" + ], + "id": "465b6176acc93b39", + "outputs": [ + { + "data": { + "text/html": [ + "FloatSliderModel(id=17cfff46-3515-47ba-bcbc-2adc4b915e6e)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "17cfff46-3515-47ba-bcbc-2adc4b915e6e" + } + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 4 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:44.904526Z", + "start_time": "2026-01-18T22:13:44.806822Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_11_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.floatLogSlider {\n", + " value = 10.0\n", + " base = 10.0\n", + " min = -10.0\n", + " max = 10.0\n", + " step = 0.2\n", + " description = \"Log Slider\"\n", + "}" + ], + "id": "4e3b541642ba45fb", + "outputs": [ + { + "data": { + "text/html": [ + "FloatLogSliderModel(id=071b2966-1217-4fae-afd2-cdd6cdfe8f30)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "071b2966-1217-4fae-afd2-cdd6cdfe8f30" + } + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 5 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Range sliders and progress", + "id": "d5b3fcbb446aaaea" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:45.010888Z", + "start_time": "2026-01-18T22:13:44.919832Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_12_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.intRangeSlider {\n", + " value = 5..7\n", + " min = 0\n", + " max = 10\n", + " step = 1\n", + " description = \"Test:\"\n", + " disabled = false\n", + " continuousUpdate = false\n", + " orientation = Orientation.Horizontal\n", + " readout = true\n", + " readoutFormat = \"d\"\n", + "}" + ], + "id": "cfa7a6afe5a1cd8e", + "outputs": [ + { + "data": { + "text/html": [ + "IntRangeSliderModel(id=2b7a6895-6fd0-4aba-821a-19b6dbfdae68)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "2b7a6895-6fd0-4aba-821a-19b6dbfdae68" + } + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 6 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:45.150337Z", + "start_time": "2026-01-18T22:13:45.018304Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_13_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.floatRangeSlider {\n", + " value = 5.0..7.5\n", + " min = 0.0\n", + " max = 10.0\n", + " step = 0.1\n", + " description = \"Test:\"\n", + " disabled = false\n", + " continuousUpdate = false\n", + " orientation = Orientation.Horizontal\n", + " readout = true\n", + " readoutFormat = \".1f\"\n", + "}" + ], + "id": "c6c708d7d5dc0408", + "outputs": [ + { + "data": { + "text/html": [ + "FloatRangeSliderModel(id=b020ca20-b87b-46b6-a56c-03c4fd0dc471)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "b020ca20-b87b-46b6-a56c-03c4fd0dc471" + } + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 7 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:45.275831Z", + "start_time": "2026-01-18T22:13:45.151738Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_14_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.intProgress {\n", + " value = 7\n", + " min = 0\n", + " max = 10\n", + " description = \"Loading:\"\n", + " barStyle = BarStyle.Default\n", + " style = progressStyleWidget { barColor = \"maroon\" }\n", + " orientation = Orientation.Horizontal\n", + "}" + ], + "id": "b0a3e1d64136bd5f", + "outputs": [ + { + "data": { + "text/html": [ + "IntProgressModel(id=b8328c0e-ff0e-4019-bc21-f645ae1c5056)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "b8328c0e-ff0e-4019-bc21-f645ae1c5056" + } + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 8 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:45.383545Z", + "start_time": "2026-01-18T22:13:45.293128Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_15_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.floatProgress {\n", + " value = 7.5\n", + " min = 0.0\n", + " max = 10.0\n", + " description = \"Loading:\"\n", + " barStyle = BarStyle.Info\n", + " style = progressStyleWidget { barColor = \"#ffff00\" }\n", + " orientation = Orientation.Horizontal\n", + "}" + ], + "id": "b49509a1211a8cfa", + "outputs": [ + { + "data": { + "text/html": [ + "FloatProgressModel(id=18b9d44e-6737-4385-93f9-2be6016710ef)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "18b9d44e-6737-4385-93f9-2be6016710ef" + } + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 9 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Numeric text widgets", + "id": "a2af3067b942194c" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:45.489610Z", + "start_time": "2026-01-18T22:13:45.396652Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_16_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.boundedIntText {\n", + " value = 7\n", + " min = 0\n", + " max = 10\n", + " step = 1\n", + " description = \"Text:\"\n", + " disabled = false\n", + "}" + ], + "id": "f11a495a144fb1d5", + "outputs": [ + { + "data": { + "text/html": [ + "BoundedIntTextModel(id=f78de841-a05e-4eef-8fa7-24ccd3165dce)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "f78de841-a05e-4eef-8fa7-24ccd3165dce" + } + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 10 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:45.576228Z", + "start_time": "2026-01-18T22:13:45.501428Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_17_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.boundedFloatText {\n", + " value = 7.5\n", + " min = 0.0\n", + " max = 10.0\n", + " step = 0.1\n", + " description = \"Text:\"\n", + " disabled = false\n", + "}" + ], + "id": "1cd1107695839b6b", + "outputs": [ + { + "data": { + "text/html": [ + "BoundedFloatTextModel(id=18a18e6b-f010-4c35-a15c-23589b3eced0)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "18a18e6b-f010-4c35-a15c-23589b3eced0" + } + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:45.656626Z", + "start_time": "2026-01-18T22:13:45.585507Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_18_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.intText {\n", + " value = 7\n", + " description = \"Any:\"\n", + " disabled = false\n", + "}" + ], + "id": "3d14109c2231e5d6", + "outputs": [ + { + "data": { + "text/html": [ + "IntTextModel(id=1ccf7c5d-adf8-427e-9d58-ccd1348f7571)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "1ccf7c5d-adf8-427e-9d58-ccd1348f7571" + } + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 12 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:45.734466Z", + "start_time": "2026-01-18T22:13:45.661564Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_19_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.floatText {\n", + " value = 7.5\n", + " description = \"Any:\"\n", + " disabled = false\n", + "}" + ], + "id": "fe16e2446b324d07", + "outputs": [ + { + "data": { + "text/html": [ + "FloatTextModel(id=1120a735-d885-4a4e-890b-b2e81ac73a71)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "1120a735-d885-4a4e-890b-b2e81ac73a71" + } + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 13 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Toggles and indicators", + "id": "8708733dab4a1b59" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:45.841725Z", + "start_time": "2026-01-18T22:13:45.757363Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_20_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.toggleButton {\n", + " value = false\n", + " description = \"Click me\"\n", + " disabled = false\n", + " buttonStyle = ButtonStyle.Default\n", + " tooltip = \"Description\"\n", + " icon = \"check\"\n", + "}" + ], + "id": "37f7ecb542781ae4", + "outputs": [ + { + "data": { + "text/html": [ + "ToggleButtonModel(id=975f7a55-44cc-4fa3-8134-8cc9d87c31c7)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "975f7a55-44cc-4fa3-8134-8cc9d87c31c7" + } + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 14 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:45.916126Z", + "start_time": "2026-01-18T22:13:45.847366Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_21_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.checkbox {\n", + " value = false\n", + " description = \"Check me\"\n", + " disabled = false\n", + " indent = false\n", + "}" + ], + "id": "e552b6ba50a265d6", + "outputs": [ + { + "data": { + "text/html": [ + "CheckboxModel(id=66e4d792-969d-42aa-aa12-5284ad52b179)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "66e4d792-969d-42aa-aa12-5284ad52b179" + } + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 15 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:46.010032Z", + "start_time": "2026-01-18T22:13:45.923520Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_22_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.valid {\n", + " value = false\n", + " description = \"Valid!\"\n", + "}" + ], + "id": "34b9135d70d55416", + "outputs": [ + { + "data": { + "text/html": [ + "ValidModel(id=36285d8d-8b99-46f0-9833-45d4e8551f8f)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "36285d8d-8b99-46f0-9833-45d4e8551f8f" + } + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 16 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Dropdowns and radios", + "id": "944ae603572ca0d" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:46.113672Z", + "start_time": "2026-01-18T22:13:46.019102Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_23_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.dropdown {\n", + " simpleOptions = listOf(\"1\", \"2\", \"3\")\n", + " label = \"2\"\n", + " description = \"Number:\"\n", + " disabled = false\n", + "}" + ], + "id": "f3eee24176b49d65", + "outputs": [ + { + "data": { + "text/html": [ + "DropdownModel(id=8eee81f1-1535-4d3c-b1d0-2599435d4adf)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "8eee81f1-1535-4d3c-b1d0-2599435d4adf" + } + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 17 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:46.293740Z", + "start_time": "2026-01-18T22:13:46.115515Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_24_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.dropdown {\n", + " options = listOf(\n", + " \"One\" to 1,\n", + " \"Two\" to 2,\n", + " \"Three\" to 3\n", + " )\n", + " value = 2\n", + " description = \"Number:\"\n", + "}" + ], + "id": "66bd24565306e996", + "outputs": [ + { + "data": { + "text/html": [ + "DropdownModel(id=3fcc46de-9c26-47c3-b1a5-10d255cf1f13)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "3fcc46de-9c26-47c3-b1a5-10d255cf1f13" + } + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 18 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:46.475548Z", + "start_time": "2026-01-18T22:13:46.305372Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_25_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.radioButtons {\n", + " options = listOf(\"pepperoni\", \"pineapple\", \"anchovies\").mapIndexed { index, string -> string to index }\n", + " value = 1 // defaults to \"pineapple\"\n", + " // layout = layoutWidget { width = \"max-content\" } // If the items' names are long\n", + " description = \"Pizza topping:\"\n", + " disabled = false\n", + "}" + ], + "id": "8486485821a47409", + "outputs": [ + { + "data": { + "text/html": [ + "RadioButtonsModel(id=34ce08ca-70f0-4e8a-b0fb-5c72e65a62e4)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "34ce08ca-70f0-4e8a-b0fb-5c72e65a62e4" + } + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 19 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:46.575255Z", + "start_time": "2026-01-18T22:13:46.485658Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_26_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.box {\n", + " children = listOf(\n", + " labelWidget { value = \"Pizza topping with a very long label:\" },\n", + " radioButtonsWidget {\n", + " simpleOptions = listOf(\n", + " \"pepperoni\",\n", + " \"pineapple\",\n", + " \"anchovies\",\n", + " \"and the long name that will fit fine and the long name that will fit fine and the long name that will fit fine \"\n", + " )\n", + " layout = layoutWidget { width = \"max-content\" }\n", + " },\n", + " )\n", + "}" + ], + "id": "7074395b4f01df8e", + "outputs": [ + { + "data": { + "text/html": [ + "BoxModel(id=3472e4e8-0b36-4bdc-addf-d8296a0c7062)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "3472e4e8-0b36-4bdc-addf-d8296a0c7062" + } + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Selection widgets", + "id": "c90807bc3a1a6c55" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:46.680692Z", + "start_time": "2026-01-18T22:13:46.583604Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_27_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.select {\n", + " simpleOptions = listOf(\"Linux\", \"Windows\", \"OSX\")\n", + " value = \"OSX\"\n", + " // rows = 10\n", + " description = \"OS:\"\n", + " disabled = false\n", + "}" + ], + "id": "ebc7cfc1d931c989", + "outputs": [ + { + "data": { + "text/html": [ + "SelectModel(id=e4d2cb79-9af1-4481-85f7-a8bffd40415a)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "e4d2cb79-9af1-4481-85f7-a8bffd40415a" + } + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 21 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:46.802546Z", + "start_time": "2026-01-18T22:13:46.681704Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_28_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.selectionSlider {\n", + " simpleOptions = listOf(\"scrambled\", \"sunny side up\", \"poached\", \"over easy\")\n", + " value = \"poached\"\n", + " description = \"I like my eggs ...\"\n", + " disabled = false\n", + " continuousUpdate = false\n", + " orientation = Orientation.Horizontal\n", + " readout = true\n", + "}" + ], + "id": "122d78fe94761ed7", + "outputs": [ + { + "data": { + "text/html": [ + "SelectionSliderModel(id=13b5d59f-6c61-4543-b1fa-d5b63be15239)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "13b5d59f-6c61-4543-b1fa-d5b63be15239" + } + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 22 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:46.951425Z", + "start_time": "2026-01-18T22:13:46.839521Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_29_jupyter" + ] + } + }, + "cell_type": "code", + "source": "%use datetime", + "id": "58be58f6c94660d3", + "outputs": [], + "execution_count": 23 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:47.209563Z", + "start_time": "2026-01-18T22:13:46.966622Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_30_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "val dates = (1..12).map { LocalDate(2015, it, 1) }\n", + "val opts = dates.map { it.month.name.lowercase().replaceFirstChar(Char::titlecase) to it }\n", + "widgetManager.selectionRangeSlider {\n", + " options = opts\n", + " index = 3..11\n", + " description = \"Months (2015)\"\n", + " disabled = false\n", + "}" + ], + "id": "f38082b2530e9f48", + "outputs": [ + { + "data": { + "text/html": [ + "SelectionRangeSliderModel(id=c6c28cad-39e5-4aba-9813-e397aba1f89a)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "c6c28cad-39e5-4aba-9813-e397aba1f89a" + } + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 24 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:47.344599Z", + "start_time": "2026-01-18T22:13:47.210807Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_31_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.toggleButtons {\n", + " simpleOptions = listOf(\"Slow\", \"Regular\", \"Fast\")\n", + " description = \"Speed:\"\n", + " disabled = false\n", + " buttonStyle = ButtonStyle.Default\n", + " tooltips = listOf(\"Description of slow\", \"Description of regular\", \"Description of fast\")\n", + " icons = List(3) { \"check\" }\n", + "}" + ], + "id": "156574c3a11c494a", + "outputs": [ + { + "data": { + "text/html": [ + "ToggleButtonsModel(id=1c7b1a22-7879-4260-9b65-f63e4e58f22b)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "1c7b1a22-7879-4260-9b65-f63e4e58f22b" + } + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 25 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:47.469131Z", + "start_time": "2026-01-18T22:13:47.371549Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_32_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.selectMultiple {\n", + " simpleOptions = listOf(\"Apples\", \"Oranges\", \"Pears\")\n", + " value = listOf(\"Apples\", \"Pears\")\n", + " // rows = 10\n", + " description = \"Fruits\"\n", + " disabled = false\n", + "}" + ], + "id": "f6966f30072a8585", + "outputs": [ + { + "data": { + "text/html": [ + "SelectMultipleModel(id=55628fe2-1ce3-4078-bc11-ba4f75d4073d)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "55628fe2-1ce3-4078-bc11-ba4f75d4073d" + } + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 26 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Text inputs", + "id": "1fbe79704b88d2ae" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:47.578085Z", + "start_time": "2026-01-18T22:13:47.481173Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_33_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.text {\n", + " value = \"Hello World\"\n", + " placeholder = \"Type something\"\n", + " description = \"String:\"\n", + " disabled = false\n", + "}" + ], + "id": "182cf59aa6c69f6d", + "outputs": [ + { + "data": { + "text/html": [ + "TextModel(id=983b111d-6689-4edf-b0c4-0647309af6ab)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "983b111d-6689-4edf-b0c4-0647309af6ab" + } + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 27 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:47.672650Z", + "start_time": "2026-01-18T22:13:47.588850Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_34_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.textarea {\n", + " value = \"Hello World\"\n", + " placeholder = \"Type something\"\n", + " description = \"String:\"\n", + " disabled = false\n", + "}" + ], + "id": "7ba3e11760ce57d5", + "outputs": [ + { + "data": { + "text/html": [ + "TextareaModel(id=a3ae7dd3-7915-4c63-a262-9eac89970997)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "a3ae7dd3-7915-4c63-a262-9eac89970997" + } + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 28 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:47.768028Z", + "start_time": "2026-01-18T22:13:47.683382Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_35_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.combobox {\n", + " // value = \"John\"\n", + " options = listOf(\"Paul\", \"John\", \"George\", \"Ringo\")\n", + " placeholder = \"Choose Someone\"\n", + " description = \"Combobox:\"\n", + " ensureOption = true\n", + " disabled = false\n", + "}" + ], + "id": "5a6049d5c96b0faa", + "outputs": [ + { + "data": { + "text/html": [ + "ComboboxModel(id=1edda0f9-631f-4db0-a94c-85a30f44e9d8)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "1edda0f9-631f-4db0-a94c-85a30f44e9d8" + } + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 29 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:47.866596Z", + "start_time": "2026-01-18T22:13:47.772575Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_36_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.password {\n", + " value = \"password\"\n", + " placeholder = \"Enter password\"\n", + " description = \"Password:\"\n", + " disabled = false\n", + "}" + ], + "id": "227d7a996bd13bab", + "outputs": [ + { + "data": { + "text/html": [ + "PasswordModel(id=cd003eaf-4b67-4603-9141-3f66720e9b03)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "cd003eaf-4b67-4603-9141-3f66720e9b03" + } + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 30 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Layout helpers and HTML", + "id": "fed007d44a9f7de6" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:48.011475Z", + "start_time": "2026-01-18T22:13:47.896169Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_37_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.hBox {\n", + " children = listOf(\n", + " labelWidget { value = \"The label\" },\n", + " floatSliderWidget()\n", + " )\n", + "}" + ], + "id": "e5ecefad4cdb16a1", + "outputs": [ + { + "data": { + "text/html": [ + "HBoxModel(id=002598e1-b53f-4f0e-93a7-d990c61c8c64)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "002598e1-b53f-4f0e-93a7-d990c61c8c64" + } + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 31 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:48.107451Z", + "start_time": "2026-01-18T22:13:48.021879Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_38_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.html {\n", + " value = \"Hello World\"\n", + " placeholder = \"Some HTML\"\n", + " description = \"Some HTML\"\n", + "}" + ], + "id": "cabd831c9db4b4a9", + "outputs": [ + { + "data": { + "text/html": [ + "HTMLModel(id=a2a54670-56ba-4a65-96e4-c61e45dae00b)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "a2a54670-56ba-4a65-96e4-c61e45dae00b" + } + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 32 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:48.264844Z", + "start_time": "2026-01-18T22:13:48.120856Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_39_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.htmlMath {\n", + " value = \"SomeHTML\"\n", + " placeholder = \"Some HTML\"\n", + " description = \"Some HTML\"\n", + "}" + ], + "id": "2ddcc29c3f0f6b6d", + "outputs": [ + { + "data": { + "text/html": [ + "HTMLMathModel(id=c14d2ed3-5d7f-4792-bcf4-8a18137ad91e)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "c14d2ed3-5d7f-4792-bcf4-8a18137ad91e" + } + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 33 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:48.393896Z", + "start_time": "2026-01-18T22:13:48.269970Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_40_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "import java.io.File\n", + "val image = File(\"WidgetArch.png\").readBytes()\n", + "widgetManager.image {\n", + " value = image\n", + " format = \"png\"\n", + " width = \"25%\" // TODO should probably be Int\n", + " height = \"100%\"\n", + "}" + ], + "id": "dc4787e9b83175a0", + "outputs": [ + { + "data": { + "text/html": [ + "ImageModel(id=aa83aa34-fdc8-4040-a9c4-4dc8788a3aea)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "aa83aa34-fdc8-4040-a9c4-4dc8788a3aea" + } + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 34 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Buttons and links", + "id": "b7da8a77f3932bd6" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:48.479383Z", + "start_time": "2026-01-18T22:13:48.406272Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_41_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "val button = widgetManager.button {\n", + " description = \"Click me\"\n", + " disabled = false\n", + " buttonStyle = ButtonStyle.Default\n", + " tooltip = \"Click me\"\n", + " icon = \"check\" // FontAwesome names without the `fa-` prefix)\n", + "}\n", + "button" + ], + "id": "84b15e73fc086d7c", + "outputs": [ + { + "data": { + "text/html": [ + "ButtonModel(id=1eb97c6c-7177-4290-a2d4-ffbea7a72ac9)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "1eb97c6c-7177-4290-a2d4-ffbea7a72ac9" + } + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 35 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:48.633585Z", + "start_time": "2026-01-18T22:13:48.487053Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_42_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "val play = widgetManager.play {\n", + " value = 50\n", + " min = 0\n", + " max = 100\n", + " step = 1\n", + " interval = 500\n", + " description = \"Press play\"\n", + " disabled = false\n", + "}\n", + "val slider = widgetManager.intSlider()\n", + "\n", + "widgetManager.linkProperties(play, PlayWidget::value, slider, IntSliderWidget::value)\n", + "widgetManager.hBox { children = listOf(play, slider) }" + ], + "id": "f3f2a0075cb9f768", + "outputs": [ + { + "data": { + "text/html": [ + "HBoxModel(id=93170ac1-1e51-4f59-815b-9e5c3b661f87)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "93170ac1-1e51-4f59-815b-9e5c3b661f87" + } + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 36 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Pickers and upload", + "id": "3604ee1ffee0754e" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:48.737991Z", + "start_time": "2026-01-18T22:13:48.635425Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_43_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.datePicker {\n", + " description = \"Pick a Date\"\n", + " disabled = false\n", + "}" + ], + "id": "3103c8817b8cad", + "outputs": [ + { + "data": { + "text/html": [ + "DatePickerModel(id=4f33f11d-46dc-4b0c-ae67-24030a30e7d5)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "4f33f11d-46dc-4b0c-ae67-24030a30e7d5" + } + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 37 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:48.856995Z", + "start_time": "2026-01-18T22:13:48.754601Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_44_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.colorPicker {\n", + " concise = false\n", + " description = \"Pick a color\"\n", + " value = \"blue\"\n", + " disabled = false\n", + "}" + ], + "id": "524abb0ad2c65791", + "outputs": [ + { + "data": { + "text/html": [ + "ColorPickerModel(id=28ecf566-a1ff-437c-a1b4-31f82ab1d70e)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "28ecf566-a1ff-437c-a1b4-31f82ab1d70e" + } + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 38 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:48.958830Z", + "start_time": "2026-01-18T22:13:48.869420Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_45_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "widgetManager.fileUpload {\n", + " accept = \"\" // Accepted file extension e.g. '.txt', '.pdf', 'image/*', 'image/*,.pdf'\n", + " multiple = false // true to accept multiple files upload else false\n", + "}" + ], + "id": "ae665e6f4e1e087e", + "outputs": [ + { + "data": { + "text/html": [ + "FileUploadModel(id=17c89e21-53dc-4331-b22c-cfc6a8deb500)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "17c89e21-53dc-4331-b22c-cfc6a8deb500" + } + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 39 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:49.075660Z", + "start_time": "2026-01-18T22:13:48.977011Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_46_jupyter" + ] + } + }, + "cell_type": "code", + "source": "widgetManager.controller { index = 0 }", + "id": "1a5cb37612d9dfaf", + "outputs": [ + { + "data": { + "text/html": [ + "ControllerModel(id=665a2075-0423-4830-8ec7-c31a09e2b64d)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "665a2075-0423-4830-8ec7-c31a09e2b64d" + } + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 40 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Containers", + "id": "85985638d7934753" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:49.210587Z", + "start_time": "2026-01-18T22:13:49.077977Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_47_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "val itemsBox = List(4) { widgetManager.label { value = it.toString() } }\n", + "widgetManager.box {\n", + " children = itemsBox\n", + "}" + ], + "id": "8b3a0c4b6f75fc91", + "outputs": [ + { + "data": { + "text/html": [ + "BoxModel(id=4db56928-4e60-4571-b028-4b553a2038cd)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "4db56928-4e60-4571-b028-4b553a2038cd" + } + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 41 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:49.397449Z", + "start_time": "2026-01-18T22:13:49.225410Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_48_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "val itemsHBox = List(4) { widgetManager.label { value = it.toString() } }\n", + "widgetManager.hBox {\n", + " children = itemsHBox\n", + "}" + ], + "id": "82a5be299d770824", + "outputs": [ + { + "data": { + "text/html": [ + "HBoxModel(id=9cb0aa10-188e-4dc8-b88f-f1e276cdf509)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "9cb0aa10-188e-4dc8-b88f-f1e276cdf509" + } + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 42 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:49.649200Z", + "start_time": "2026-01-18T22:13:49.432858Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_49_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "val items = List(4) { widgetManager.label { value = it.toString()} }\n", + "val leftBox = widgetManager.vBox { children = listOf(items[0], items[1]) }\n", + "val rightBox = widgetManager.vBox { children = listOf(items[2], items[3]) }\n", + "widgetManager.hBox { children = listOf(leftBox, rightBox) }" + ], + "id": "a58e9ad4d7045767", + "outputs": [ + { + "data": { + "text/html": [ + "HBoxModel(id=6074d969-3734-4458-a591-b5d4126a90ea)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "6074d969-3734-4458-a591-b5d4126a90ea" + } + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 43 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:49.786575Z", + "start_time": "2026-01-18T22:13:49.664644Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_50_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "val gridItems = List(8) { widgetManager.label { value = it.toString() } }\n", + "widgetManager.gridBox {\n", + " children = gridItems\n", + " layout = layoutWidget { gridTemplateColumns = \"repeat(3, 100px)\" }\n", + "}" + ], + "id": "6dfe8d1005f5a4db", + "outputs": [ + { + "data": { + "text/html": [ + "GridBoxModel(id=6957578b-7078-4cd9-ba6f-69f96630aba1)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "6957578b-7078-4cd9-ba6f-69f96630aba1" + } + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 44 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:49.852137Z", + "start_time": "2026-01-18T22:13:49.788161Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_51_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "val accordion = widgetManager.accordion {\n", + " children = listOf(widgetManager.intSlider(), widgetManager.text())\n", + " titles = listOf(\"Slider\", \"Text\")\n", + "}\n", + "accordion" + ], + "id": "34115b127676780e", + "outputs": [ + { + "data": { + "text/html": [ + "AccordionModel(id=ca774091-8e8d-431c-9084-eeab840bb9c5)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "ca774091-8e8d-431c-9084-eeab840bb9c5" + } + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 45 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:49.982073Z", + "start_time": "2026-01-18T22:13:49.862972Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_52_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "val tabContents = listOf(\"P0\", \"P1\", \"P2\", \"P3\", \"P4\")\n", + "val _children = tabContents.map { widgetManager.text { description = it } }\n", + "val tab = widgetManager.tab {\n", + " this.children = _children\n", + " titles = _children.indices.map { it.toString() }\n", + "}\n", + "tab" + ], + "id": "186a75cace0fe4e0", + "outputs": [ + { + "data": { + "text/html": [ + "TabModel(id=715c57fb-a5c1-4fe4-ba08-1da35de0661b)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "715c57fb-a5c1-4fe4-ba08-1da35de0661b" + } + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 46 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:50.134009Z", + "start_time": "2026-01-18T22:13:50.010792Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_53_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "val tabNest = widgetManager.tab {\n", + " children = listOf(accordion, accordion)\n", + " titles = listOf(\"An accordion\", \"Copy of the accordion\")\n", + "}\n", + "tabNest\n" + ], + "id": "38d9ca87e8b67277", + "outputs": [ + { + "data": { + "text/html": [ + "TabModel(id=fdbdb01a-86c2-489e-8d0a-ab53b363dd9c)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "fdbdb01a-86c2-489e-8d0a-ab53b363dd9c" + } + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 47 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### Event listeners", + "id": "3adb73c3a78c541b" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:50.405434Z", + "start_time": "2026-01-18T22:13:50.174255Z" + }, + "executionRelatedData": { + "compiledClasses": [ + "Line_54_jupyter" + ] + } + }, + "cell_type": "code", + "source": [ + "val slider = intSliderWidget { description = \"Slider\" }\n", + "val label = labelWidget { value = \"Value is 0\" }\n", + "\n", + "// Listen to all property changes\n", + "slider.addChangeListener { patch, fromFrontend ->\n", + " if (\"value\" in patch) {\n", + " label.value = \"Value is ${slider.value}\"\n", + " }\n", + "}\n", + "\n", + "// Listen to a specific property change\n", + "slider.getProperty(\"value\")?.addChangeListener { newValue, fromFrontend ->\n", + " // This will be printed to the kernel log\n", + " println(\"Value changed to $newValue\")\n", + "}\n", + "\n", + "vBoxWidget { children = listOf(slider, label) }" + ], + "id": "65438dd5cac5b471", + "outputs": [ + { + "data": { + "text/html": [ + "VBoxModel(id=f65ac5d5-1b09-4779-bf1d-416696609bbb)" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "f65ac5d5-1b09-4779-bf1d-416696609bbb" + } + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 48 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-01-18T22:13:50.501048Z", + "start_time": "2026-01-18T22:13:50.472438Z" + } + }, + "cell_type": "code", + "source": "", + "id": "b101611ea5d4b4e0", + "outputs": [], + "execution_count": 49 + } + ], + "metadata": { + "kernelspec": { + "display_name": "Kotlin", + "language": "kotlin", + "name": "kotlin" + }, + "language_info": { + "name": "kotlin", + "version": "2.2.20", + "mimetype": "text/x-kotlin", + "file_extension": ".kt", + "pygments_lexer": "kotlin", + "codemirror_mode": "text/x-kotlin", + "nbconvert_exporter": "" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/integrations/widgets/widgets-api/build.gradle.kts b/integrations/widgets/widgets-api/build.gradle.kts new file mode 100644 index 0000000..00cbe8a --- /dev/null +++ b/integrations/widgets/widgets-api/build.gradle.kts @@ -0,0 +1,40 @@ +plugins { + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.publisher) + alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.kotlin.jupyter.api) +} + +dependencies { + api(libs.kotlinx.serialization.json) + implementation(libs.kotlin.reflect) + + testImplementation(libs.kotlin.test) + testImplementation(libs.test.kotlintest.assertions) + testImplementation(libs.kotlinx.serialization.json) +} + +tasks.test { + useJUnitPlatform() +} + +kotlin { + jvmToolchain( + libs.versions.jvm.toolchain + .get() + .toInt(), + ) + explicitApi() +} + +sourceSets { + main { + kotlin.srcDir("src/generated/kotlin") + } +} + +kotlinPublications { + publication { + description.set("Kotlin APIs for IPython Widgets") + } +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/AccordionWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/AccordionWidget.kt new file mode 100644 index 0000000..bc987af --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/AccordionWidget.kt @@ -0,0 +1,73 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.BoxStyle +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val accordionSpec = WidgetSpec( + modelName = "AccordionModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "AccordionView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.accordion(setup: AccordionWidget.() -> Unit = {}): AccordionWidget = + createAndRegisterWidget(AccordionWidget.Factory).apply(setup) + +public class AccordionWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(accordionSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(accordionSpec, ::AccordionWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Use a predefined styling for the box. + */ + public var boxStyle: WidgetEnumEntry by prop("box_style", WidgetEnumType(BoxStyle, BoxStyle.Default), BoxStyle.Default) + + /** + * List of widget children + */ + public var children: List by prop("children", ArrayType(NullableType(WidgetReferenceType())), emptyList()) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * The index of the selected page. This is either an integer selecting a particular sub-widget, or None to have no widgets selected. + */ + public var selectedIndex: Int? by nullableIntProp("selected_index", null) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * Titles of the pages + */ + public var titles: List by prop("titles", ArrayType(StringType), emptyList()) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/AudioWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/AudioWidget.kt new file mode 100644 index 0000000..3b7b786 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/AudioWidget.kt @@ -0,0 +1,74 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BytesType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val audioSpec = WidgetSpec( + modelName = "AudioModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "AudioView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.audio(setup: AudioWidget.() -> Unit = {}): AudioWidget = + createAndRegisterWidget(AudioWidget.Factory).apply(setup) + +public class AudioWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(audioSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(audioSpec, ::AudioWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * When true, the audio starts when it's displayed + */ + public var autoplay: Boolean by boolProp("autoplay", true) + + /** + * Specifies that audio controls should be displayed (such as a play/pause button etc) + */ + public var controls: Boolean by boolProp("controls", true) + + /** + * The format of the audio. + */ + public var format: String by stringProp("format", "mp3") + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * When true, the audio will start from the beginning after finishing + */ + public var loop: Boolean by boolProp("loop", true) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * The media data as a memory view of bytes. + */ + public var value: ByteArray by bytesProp("value", byteArrayOf()) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/BoundedFloatTextWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/BoundedFloatTextWidget.kt new file mode 100644 index 0000000..d509422 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/BoundedFloatTextWidget.kt @@ -0,0 +1,94 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.FloatType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val boundedFloatTextSpec = WidgetSpec( + modelName = "BoundedFloatTextModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "FloatTextView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.boundedFloatText(setup: BoundedFloatTextWidget.() -> Unit = {}): BoundedFloatTextWidget = + createAndRegisterWidget(BoundedFloatTextWidget.Factory).apply(setup) + +public class BoundedFloatTextWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(boundedFloatTextSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(boundedFloatTextSpec, ::BoundedFloatTextWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", false) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Max value + */ + public var max: Double by doubleProp("max", 100.0) + + /** + * Min value + */ + public var min: Double by doubleProp("min", 0.0) + + /** + * Minimum step to increment the value + */ + public var step: Double? by nullableDoubleProp("step", null) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Float value + */ + public var value: Double by doubleProp("value", 0.0) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/BoundedIntTextWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/BoundedIntTextWidget.kt new file mode 100644 index 0000000..bdd663b --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/BoundedIntTextWidget.kt @@ -0,0 +1,94 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val boundedIntTextSpec = WidgetSpec( + modelName = "BoundedIntTextModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "IntTextView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.boundedIntText(setup: BoundedIntTextWidget.() -> Unit = {}): BoundedIntTextWidget = + createAndRegisterWidget(BoundedIntTextWidget.Factory).apply(setup) + +public class BoundedIntTextWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(boundedIntTextSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(boundedIntTextSpec, ::BoundedIntTextWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", false) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Max value + */ + public var max: Int by intProp("max", 100) + + /** + * Min value + */ + public var min: Int by intProp("min", 0) + + /** + * Minimum step to increment the value + */ + public var step: Int by intProp("step", 1) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Int value + */ + public var value: Int by intProp("value", 0) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/BoxWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/BoxWidget.kt new file mode 100644 index 0000000..c8c1169 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/BoxWidget.kt @@ -0,0 +1,62 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.BoxStyle +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val boxSpec = WidgetSpec( + modelName = "BoxModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "BoxView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.box(setup: BoxWidget.() -> Unit = {}): BoxWidget = + createAndRegisterWidget(BoxWidget.Factory).apply(setup) + +public class BoxWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(boxSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(boxSpec, ::BoxWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Use a predefined styling for the box. + */ + public var boxStyle: WidgetEnumEntry by prop("box_style", WidgetEnumType(BoxStyle, BoxStyle.Default), BoxStyle.Default) + + /** + * List of widget children + */ + public var children: List by prop("children", ArrayType(NullableType(WidgetReferenceType())), emptyList()) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ButtonStyleWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ButtonStyleWidget.kt new file mode 100644 index 0000000..30a950e --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ButtonStyleWidget.kt @@ -0,0 +1,69 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType + +private val buttonStyleSpec = WidgetSpec( + modelName = "ButtonStyleModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "StyleView", + viewModule = "@jupyter-widgets/base", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.buttonStyle(setup: ButtonStyleWidget.() -> Unit = {}): ButtonStyleWidget = + createAndRegisterWidget(ButtonStyleWidget.Factory).apply(setup) + +public class ButtonStyleWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(buttonStyleSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(buttonStyleSpec, ::ButtonStyleWidget) + + /** + * Color of the button + */ + public var buttonColor: String? by nullableStringProp("button_color", null) + + /** + * Button text font family. + */ + public var fontFamily: String? by nullableStringProp("font_family", null) + + /** + * Button text font size. + */ + public var fontSize: String? by nullableStringProp("font_size", null) + + /** + * Button text font style. + */ + public var fontStyle: String? by nullableStringProp("font_style", null) + + /** + * Button text font variant. + */ + public var fontVariant: String? by nullableStringProp("font_variant", null) + + /** + * Button text font weight. + */ + public var fontWeight: String? by nullableStringProp("font_weight", null) + + /** + * Button text color. + */ + public var textColor: String? by nullableStringProp("text_color", null) + + /** + * Button text decoration. + */ + public var textDecoration: String? by nullableStringProp("text_decoration", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ButtonWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ButtonWidget.kt new file mode 100644 index 0000000..432c16d --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ButtonWidget.kt @@ -0,0 +1,72 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.ButtonStyle +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val buttonSpec = WidgetSpec( + modelName = "ButtonModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "ButtonView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.button(setup: ButtonWidget.() -> Unit = {}): ButtonWidget = + createAndRegisterWidget(ButtonWidget.Factory).apply(setup) + +public class ButtonWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(buttonSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(buttonSpec, ::ButtonWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Use a predefined styling for the button. + */ + public var buttonStyle: WidgetEnumEntry by prop("button_style", WidgetEnumType(ButtonStyle, ButtonStyle.Default), ButtonStyle.Default) + + /** + * Button label. + */ + public var description: String by stringProp("description", "") + + /** + * Enable or disable user changes. + */ + public var disabled: Boolean by boolProp("disabled", false) + + /** + * Font-awesome icon names, without the 'fa-' prefix. + */ + public var icon: String by stringProp("icon", "") + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + public var style: ButtonStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.buttonStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/CheckboxStyleWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/CheckboxStyleWidget.kt new file mode 100644 index 0000000..cfb9e8e --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/CheckboxStyleWidget.kt @@ -0,0 +1,39 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType + +private val checkboxStyleSpec = WidgetSpec( + modelName = "CheckboxStyleModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "StyleView", + viewModule = "@jupyter-widgets/base", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.checkboxStyle(setup: CheckboxStyleWidget.() -> Unit = {}): CheckboxStyleWidget = + createAndRegisterWidget(CheckboxStyleWidget.Factory).apply(setup) + +public class CheckboxStyleWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(checkboxStyleSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(checkboxStyleSpec, ::CheckboxStyleWidget) + + /** + * Background specifications. + */ + public var background: String? by nullableStringProp("background", null) + + /** + * Width of the description to the side of the control. + */ + public var descriptionWidth: String by stringProp("description_width", "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/CheckboxWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/CheckboxWidget.kt new file mode 100644 index 0000000..175d606 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/CheckboxWidget.kt @@ -0,0 +1,78 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val checkboxSpec = WidgetSpec( + modelName = "CheckboxModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "CheckboxView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.checkbox(setup: CheckboxWidget.() -> Unit = {}): CheckboxWidget = + createAndRegisterWidget(CheckboxWidget.Factory).apply(setup) + +public class CheckboxWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(checkboxSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(checkboxSpec, ::CheckboxWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes. + */ + public var disabled: Boolean by boolProp("disabled", false) + + /** + * Indent the control to align with other controls with a description. + */ + public var indent: Boolean by boolProp("indent", true) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Styling customizations + */ + public var style: CheckboxStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.checkboxStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Bool value + */ + public var value: Boolean by boolProp("value", false) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ColorPickerWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ColorPickerWidget.kt new file mode 100644 index 0000000..18e33fb --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ColorPickerWidget.kt @@ -0,0 +1,78 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val colorPickerSpec = WidgetSpec( + modelName = "ColorPickerModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "ColorPickerView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.colorPicker(setup: ColorPickerWidget.() -> Unit = {}): ColorPickerWidget = + createAndRegisterWidget(ColorPickerWidget.Factory).apply(setup) + +public class ColorPickerWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(colorPickerSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(colorPickerSpec, ::ColorPickerWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Display short version with just a color selector. + */ + public var concise: Boolean by boolProp("concise", false) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes. + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * The color value. + */ + public var value: String by stringProp("value", "black") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ColorsInputWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ColorsInputWidget.kt new file mode 100644 index 0000000..4009ef6 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ColorsInputWidget.kt @@ -0,0 +1,72 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.AnyType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val colorsInputSpec = WidgetSpec( + modelName = "ColorsInputModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "ColorsInputView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.colorsInput(setup: ColorsInputWidget.() -> Unit = {}): ColorsInputWidget = + createAndRegisterWidget(ColorsInputWidget.Factory).apply(setup) + +public class ColorsInputWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(colorsInputSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(colorsInputSpec, ::ColorsInputWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + public var allowDuplicates: Boolean by boolProp("allow_duplicates", true) + public var allowedTags: List by prop("allowed_tags", ArrayType(AnyType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + public var placeholder: String by stringProp("placeholder", "​") + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * List of string tags + */ + public var value: List by prop("value", ArrayType(AnyType), emptyList()) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ComboboxWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ComboboxWidget.kt new file mode 100644 index 0000000..bcc0e67 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ComboboxWidget.kt @@ -0,0 +1,89 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val comboboxSpec = WidgetSpec( + modelName = "ComboboxModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "ComboboxView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.combobox(setup: ComboboxWidget.() -> Unit = {}): ComboboxWidget = + createAndRegisterWidget(ComboboxWidget.Factory).apply(setup) + +public class ComboboxWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(comboboxSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(comboboxSpec, ::ComboboxWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", true) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + + /** + * If set, ensure value is in options. Implies continuous_update=False. + */ + public var ensureOption: Boolean by boolProp("ensure_option", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Dropdown options for the combobox + */ + public var options: List by prop("options", ArrayType(StringType), emptyList()) + + /** + * Placeholder text to display when nothing has been typed + */ + public var placeholder: String by stringProp("placeholder", "​") + public var style: TextStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.textStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * String value + */ + public var value: String by stringProp("value", "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ControllerAxisWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ControllerAxisWidget.kt new file mode 100644 index 0000000..b296c34 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ControllerAxisWidget.kt @@ -0,0 +1,54 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.FloatType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val controllerAxisSpec = WidgetSpec( + modelName = "ControllerAxisModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "ControllerAxisView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.controllerAxis(setup: ControllerAxisWidget.() -> Unit = {}): ControllerAxisWidget = + createAndRegisterWidget(ControllerAxisWidget.Factory).apply(setup) + +public class ControllerAxisWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(controllerAxisSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(controllerAxisSpec, ::ControllerAxisWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * The value of the axis. + */ + public var value: Double by doubleProp("value", 0.0) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ControllerButtonWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ControllerButtonWidget.kt new file mode 100644 index 0000000..0b9ec13 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ControllerButtonWidget.kt @@ -0,0 +1,59 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.FloatType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val controllerButtonSpec = WidgetSpec( + modelName = "ControllerButtonModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "ControllerButtonView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.controllerButton(setup: ControllerButtonWidget.() -> Unit = {}): ControllerButtonWidget = + createAndRegisterWidget(ControllerButtonWidget.Factory).apply(setup) + +public class ControllerButtonWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(controllerButtonSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(controllerButtonSpec, ::ControllerButtonWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Whether the button is pressed. + */ + public var pressed: Boolean by boolProp("pressed", false) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * The value of the button. + */ + public var value: Double by doubleProp("value", 0.0) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ControllerWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ControllerWidget.kt new file mode 100644 index 0000000..3ab68b5 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ControllerWidget.kt @@ -0,0 +1,85 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.FloatType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val controllerSpec = WidgetSpec( + modelName = "ControllerModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "ControllerView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.controller(setup: ControllerWidget.() -> Unit = {}): ControllerWidget = + createAndRegisterWidget(ControllerWidget.Factory).apply(setup) + +public class ControllerWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(controllerSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(controllerSpec, ::ControllerWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * The axes on the gamepad. + */ + public var axes: List by prop("axes", ArrayType(NullableType(WidgetReferenceType())), emptyList()) + + /** + * The buttons on the gamepad. + */ + public var buttons: List by prop("buttons", ArrayType(NullableType(WidgetReferenceType())), emptyList()) + + /** + * Whether the gamepad is connected. + */ + public var connected: Boolean by boolProp("connected", false) + + /** + * The id number of the controller. + */ + public var index: Int by intProp("index", 0) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * The name of the control mapping. + */ + public var mapping: String by stringProp("mapping", "") + + /** + * The name of the controller. + */ + public var name: String by stringProp("name", "") + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * The last time the data from this gamepad was updated. + */ + public var timestamp: Double by doubleProp("timestamp", 0.0) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DOMWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DOMWidget.kt new file mode 100644 index 0000000..8f84ee0 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DOMWidget.kt @@ -0,0 +1,54 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BytesType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val domWidgetSpec = WidgetSpec( + modelName = "DOMWidgetModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = null, + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.domWidget(setup: DomWidget.() -> Unit = {}): DomWidget = + createAndRegisterWidget(DomWidget.Factory).apply(setup) + +public class DomWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(domWidgetSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(domWidgetSpec, ::DomWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * The media data as a memory view of bytes. + */ + public var value: ByteArray by bytesProp("value", byteArrayOf()) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DatePickerWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DatePickerWidget.kt new file mode 100644 index 0000000..86ffe1a --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DatePickerWidget.kt @@ -0,0 +1,107 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.UnionType +import org.jetbrains.kotlinx.jupyter.widget.model.types.datetime.DateType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +public sealed interface DatePickerWidgetStep { + @JvmInline public value class IntValue(public val value: Int) : DatePickerWidgetStep + public object AnyStep : DatePickerWidgetStep +} + + +private val DatePickerWidgetStepType_Option0 = IntType + +private val DatePickerWidgetStepType = UnionType( + name = "step", + default = DatePickerWidgetStep.IntValue(1), + serializer = { value, widgetManager -> + when (value) { + is DatePickerWidgetStep.IntValue -> DatePickerWidgetStepType_Option0.serialize(value.value, widgetManager) + is DatePickerWidgetStep.AnyStep -> "any" + } + }, + deserializers = listOf( + { patch, widgetManager -> DatePickerWidgetStep.IntValue(DatePickerWidgetStepType_Option0.deserialize(patch, widgetManager)) }, + { patch, _ -> + when (patch) { + "any" -> DatePickerWidgetStep.AnyStep + else -> throw Exception("Unknown enum value: $patch") + } + } + ), +) + +private val datePickerSpec = WidgetSpec( + modelName = "DatePickerModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "DatePickerView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.datePicker(setup: DatePickerWidget.() -> Unit = {}): DatePickerWidget = + createAndRegisterWidget(DatePickerWidget.Factory).apply(setup) + +public class DatePickerWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(datePickerSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(datePickerSpec, ::DatePickerWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes. + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + public var max: java.time.LocalDate? by nullableDateProp("max", null) + public var min: java.time.LocalDate? by nullableDateProp("min", null) + + /** + * The date step to use for the picker, in days, or "any". + */ + public var step: DatePickerWidgetStep by prop("step", DatePickerWidgetStepType, DatePickerWidgetStep.IntValue(1)) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + public var value: java.time.LocalDate? by nullableDateProp("value", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DatetimeWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DatetimeWidget.kt new file mode 100644 index 0000000..a66d636 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DatetimeWidget.kt @@ -0,0 +1,72 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.datetime.DatetimeType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val datetimeSpec = WidgetSpec( + modelName = "DatetimeModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "DatetimeView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.datetime(setup: DatetimeWidget.() -> Unit = {}): DatetimeWidget = + createAndRegisterWidget(DatetimeWidget.Factory).apply(setup) + +public class DatetimeWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(datetimeSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(datetimeSpec, ::DatetimeWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes. + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + public var max: java.time.Instant? by nullableDateTimeProp("max", null) + public var min: java.time.Instant? by nullableDateTimeProp("min", null) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + public var value: java.time.Instant? by nullableDateTimeProp("value", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DescriptionStyleWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DescriptionStyleWidget.kt new file mode 100644 index 0000000..4a2e98b --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DescriptionStyleWidget.kt @@ -0,0 +1,33 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType + +private val descriptionStyleSpec = WidgetSpec( + modelName = "DescriptionStyleModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "StyleView", + viewModule = "@jupyter-widgets/base", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.descriptionStyle(setup: DescriptionStyleWidget.() -> Unit = {}): DescriptionStyleWidget = + createAndRegisterWidget(DescriptionStyleWidget.Factory).apply(setup) + +public class DescriptionStyleWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(descriptionStyleSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(descriptionStyleSpec, ::DescriptionStyleWidget) + + /** + * Width of the description to the side of the control. + */ + public var descriptionWidth: String by stringProp("description_width", "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DirectionalLinkWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DirectionalLinkWidget.kt new file mode 100644 index 0000000..67b427a --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DirectionalLinkWidget.kt @@ -0,0 +1,42 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.PairType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val directionalLinkSpec = WidgetSpec( + modelName = "DirectionalLinkModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = null, + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.directionalLink(setup: DirectionalLinkWidget.() -> Unit = {}): DirectionalLinkWidget = + createAndRegisterWidget(DirectionalLinkWidget.Factory).apply(setup) + +public class DirectionalLinkWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(directionalLinkSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(directionalLinkSpec, ::DirectionalLinkWidget) + + /** + * The source (widget, 'trait_name') pair + */ + public var source: Pair? by prop("source", NullableType(PairType(NullableType(WidgetReferenceType()), StringType)), null to "") + + /** + * The target (widget, 'trait_name') pair + */ + public var target: Pair? by prop("target", NullableType(PairType(NullableType(WidgetReferenceType()), StringType)), null to "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DropdownWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DropdownWidget.kt new file mode 100644 index 0000000..52e7a91 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/DropdownWidget.kt @@ -0,0 +1,69 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.options.SingleNullableSelectionWidgetBase +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val dropdownSpec = WidgetSpec( + modelName = "DropdownModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "DropdownView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.dropdown(setup: DropdownWidget.() -> Unit = {}): DropdownWidget = + createAndRegisterWidget(DropdownWidget.Factory).apply(setup) + +public class DropdownWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : SingleNullableSelectionWidgetBase(dropdownSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(dropdownSpec, ::DropdownWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FileUploadWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FileUploadWidget.kt new file mode 100644 index 0000000..4d53ea9 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FileUploadWidget.kt @@ -0,0 +1,98 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.ButtonStyle +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.RawObjectType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val fileUploadSpec = WidgetSpec( + modelName = "FileUploadModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "FileUploadView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.fileUpload(setup: FileUploadWidget.() -> Unit = {}): FileUploadWidget = + createAndRegisterWidget(FileUploadWidget.Factory).apply(setup) + +public class FileUploadWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(fileUploadSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(fileUploadSpec, ::FileUploadWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * File types to accept, empty string for all + */ + public var accept: String by stringProp("accept", "") + + /** + * Use a predefined styling for the button. + */ + public var buttonStyle: WidgetEnumEntry by prop("button_style", WidgetEnumType(ButtonStyle, ButtonStyle.Default), ButtonStyle.Default) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable button + */ + public var disabled: Boolean by boolProp("disabled", false) + + /** + * Error message + */ + public var error: String by stringProp("error", "") + + /** + * Font-awesome icon name, without the 'fa-' prefix. + */ + public var icon: String by stringProp("icon", "upload") + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * If True, allow for multiple files upload + */ + public var multiple: Boolean by boolProp("multiple", false) + public var style: ButtonStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.buttonStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * The file upload value + */ + public var value: List> by prop("value", ArrayType(RawObjectType), emptyList()) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatLogSliderWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatLogSliderWidget.kt new file mode 100644 index 0000000..6322355 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatLogSliderWidget.kt @@ -0,0 +1,119 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Behavior +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Orientation +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.FloatType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val floatLogSliderSpec = WidgetSpec( + modelName = "FloatLogSliderModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "FloatLogSliderView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.floatLogSlider(setup: FloatLogSliderWidget.() -> Unit = {}): FloatLogSliderWidget = + createAndRegisterWidget(FloatLogSliderWidget.Factory).apply(setup) + +public class FloatLogSliderWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(floatLogSliderSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(floatLogSliderSpec, ::FloatLogSliderWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Base for the logarithm + */ + public var base: Double by doubleProp("base", 10.0) + + /** + * Slider dragging behavior. + */ + public var behavior: WidgetEnumEntry by prop("behavior", WidgetEnumType(Behavior, Behavior.DragTap), Behavior.DragTap) + + /** + * Update the value of the widget as the user is holding the slider. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", true) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Max value for the exponent + */ + public var max: Double by doubleProp("max", 4.0) + + /** + * Min value for the exponent + */ + public var min: Double by doubleProp("min", 0.0) + + /** + * Vertical or horizontal. + */ + public var orientation: WidgetEnumEntry by prop("orientation", WidgetEnumType(Orientation, Orientation.Horizontal), Orientation.Horizontal) + + /** + * Display the current value of the slider next to it. + */ + public var readout: Boolean by boolProp("readout", true) + + /** + * Format for the readout + */ + public var readoutFormat: String by stringProp("readout_format", ".3g") + + /** + * Minimum step in the exponent to increment the value + */ + public var step: Double? by nullableDoubleProp("step", 0.1) + public var style: SliderStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.sliderStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Float value + */ + public var value: Double by doubleProp("value", 1.0) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatProgressWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatProgressWidget.kt new file mode 100644 index 0000000..0e76a3d --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatProgressWidget.kt @@ -0,0 +1,89 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.BarStyle +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Orientation +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.FloatType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val floatProgressSpec = WidgetSpec( + modelName = "FloatProgressModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "ProgressView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.floatProgress(setup: FloatProgressWidget.() -> Unit = {}): FloatProgressWidget = + createAndRegisterWidget(FloatProgressWidget.Factory).apply(setup) + +public class FloatProgressWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(floatProgressSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(floatProgressSpec, ::FloatProgressWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Use a predefined styling for the progress bar. + */ + public var barStyle: WidgetEnumEntry? by prop("bar_style", NullableType(WidgetEnumType(BarStyle, BarStyle.Default)), BarStyle.Default) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Max value + */ + public var max: Double by doubleProp("max", 100.0) + + /** + * Min value + */ + public var min: Double by doubleProp("min", 0.0) + + /** + * Vertical or horizontal. + */ + public var orientation: WidgetEnumEntry by prop("orientation", WidgetEnumType(Orientation, Orientation.Horizontal), Orientation.Horizontal) + public var style: ProgressStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.progressStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Float value + */ + public var value: Double by doubleProp("value", 0.0) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatRangeSliderWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatRangeSliderWidget.kt new file mode 100644 index 0000000..e94ea2d --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatRangeSliderWidget.kt @@ -0,0 +1,115 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Behavior +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Orientation +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.FloatType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.ranges.FloatRangeType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val floatRangeSliderSpec = WidgetSpec( + modelName = "FloatRangeSliderModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "FloatRangeSliderView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.floatRangeSlider(setup: FloatRangeSliderWidget.() -> Unit = {}): FloatRangeSliderWidget = + createAndRegisterWidget(FloatRangeSliderWidget.Factory).apply(setup) + +public class FloatRangeSliderWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(floatRangeSliderSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(floatRangeSliderSpec, ::FloatRangeSliderWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Slider dragging behavior. + */ + public var behavior: WidgetEnumEntry by prop("behavior", WidgetEnumType(Behavior, Behavior.DragTap), Behavior.DragTap) + + /** + * Update the value of the widget as the user is sliding the slider. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", true) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Max value + */ + public var max: Double by doubleProp("max", 100.0) + + /** + * Min value + */ + public var min: Double by doubleProp("min", 0.0) + + /** + * Vertical or horizontal. + */ + public var orientation: WidgetEnumEntry by prop("orientation", WidgetEnumType(Orientation, Orientation.Horizontal), Orientation.Horizontal) + + /** + * Display the current value of the slider next to it. + */ + public var readout: Boolean by boolProp("readout", true) + + /** + * Format for the readout + */ + public var readoutFormat: String by stringProp("readout_format", ".2f") + + /** + * Minimum step to increment the value + */ + public var step: Double? by nullableDoubleProp("step", 0.1) + public var style: SliderStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.sliderStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Tuple of (lower, upper) bounds + */ + public var value: ClosedRange? by prop("value", NullableType(FloatRangeType), 0.0..1.0) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatSliderWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatSliderWidget.kt new file mode 100644 index 0000000..e1c07d5 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatSliderWidget.kt @@ -0,0 +1,114 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Behavior +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Orientation +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.FloatType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val floatSliderSpec = WidgetSpec( + modelName = "FloatSliderModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "FloatSliderView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.floatSlider(setup: FloatSliderWidget.() -> Unit = {}): FloatSliderWidget = + createAndRegisterWidget(FloatSliderWidget.Factory).apply(setup) + +public class FloatSliderWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(floatSliderSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(floatSliderSpec, ::FloatSliderWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Slider dragging behavior. + */ + public var behavior: WidgetEnumEntry by prop("behavior", WidgetEnumType(Behavior, Behavior.DragTap), Behavior.DragTap) + + /** + * Update the value of the widget as the user is holding the slider. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", true) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Max value + */ + public var max: Double by doubleProp("max", 100.0) + + /** + * Min value + */ + public var min: Double by doubleProp("min", 0.0) + + /** + * Vertical or horizontal. + */ + public var orientation: WidgetEnumEntry by prop("orientation", WidgetEnumType(Orientation, Orientation.Horizontal), Orientation.Horizontal) + + /** + * Display the current value of the slider next to it. + */ + public var readout: Boolean by boolProp("readout", true) + + /** + * Format for the readout + */ + public var readoutFormat: String by stringProp("readout_format", ".2f") + + /** + * Minimum step to increment the value + */ + public var step: Double? by nullableDoubleProp("step", 0.1) + public var style: SliderStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.sliderStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Float value + */ + public var value: Double by doubleProp("value", 0.0) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatTextWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatTextWidget.kt new file mode 100644 index 0000000..71a1dad --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatTextWidget.kt @@ -0,0 +1,84 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.FloatType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val floatTextSpec = WidgetSpec( + modelName = "FloatTextModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "FloatTextView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.floatText(setup: FloatTextWidget.() -> Unit = {}): FloatTextWidget = + createAndRegisterWidget(FloatTextWidget.Factory).apply(setup) + +public class FloatTextWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(floatTextSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(floatTextSpec, ::FloatTextWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", false) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Minimum step to increment the value + */ + public var step: Double? by nullableDoubleProp("step", null) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Float value + */ + public var value: Double by doubleProp("value", 0.0) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatsInputWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatsInputWidget.kt new file mode 100644 index 0000000..26363f8 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/FloatsInputWidget.kt @@ -0,0 +1,84 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.TagStyle +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.AnyType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.FloatType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val floatsInputSpec = WidgetSpec( + modelName = "FloatsInputModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "FloatsInputView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.floatsInput(setup: FloatsInputWidget.() -> Unit = {}): FloatsInputWidget = + createAndRegisterWidget(FloatsInputWidget.Factory).apply(setup) + +public class FloatsInputWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(floatsInputSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(floatsInputSpec, ::FloatsInputWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + public var allowDuplicates: Boolean by boolProp("allow_duplicates", true) + public var allowedTags: List by prop("allowed_tags", ArrayType(AnyType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + public var format: String by stringProp("format", ".1f") + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + public var max: Double? by nullableDoubleProp("max", null) + public var min: Double? by nullableDoubleProp("min", null) + public var placeholder: String by stringProp("placeholder", "​") + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * Use a predefined styling for the tags. + */ + public var tagStyle: WidgetEnumEntry by prop("tag_style", WidgetEnumType(TagStyle, TagStyle.Default), TagStyle.Default) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * List of float tags + */ + public var value: List by prop("value", ArrayType(AnyType), emptyList()) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/GridBoxWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/GridBoxWidget.kt new file mode 100644 index 0000000..639b169 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/GridBoxWidget.kt @@ -0,0 +1,62 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.BoxStyle +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val gridBoxSpec = WidgetSpec( + modelName = "GridBoxModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "GridBoxView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.gridBox(setup: GridBoxWidget.() -> Unit = {}): GridBoxWidget = + createAndRegisterWidget(GridBoxWidget.Factory).apply(setup) + +public class GridBoxWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(gridBoxSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(gridBoxSpec, ::GridBoxWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Use a predefined styling for the box. + */ + public var boxStyle: WidgetEnumEntry by prop("box_style", WidgetEnumType(BoxStyle, BoxStyle.Default), BoxStyle.Default) + + /** + * List of widget children + */ + public var children: List by prop("children", ArrayType(NullableType(WidgetReferenceType())), emptyList()) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HBoxWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HBoxWidget.kt new file mode 100644 index 0000000..b81b1ef --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HBoxWidget.kt @@ -0,0 +1,62 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.BoxStyle +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val hBoxSpec = WidgetSpec( + modelName = "HBoxModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "HBoxView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.hBox(setup: HBoxWidget.() -> Unit = {}): HBoxWidget = + createAndRegisterWidget(HBoxWidget.Factory).apply(setup) + +public class HBoxWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(hBoxSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(hBoxSpec, ::HBoxWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Use a predefined styling for the box. + */ + public var boxStyle: WidgetEnumEntry by prop("box_style", WidgetEnumType(BoxStyle, BoxStyle.Default), BoxStyle.Default) + + /** + * List of widget children + */ + public var children: List by prop("children", ArrayType(NullableType(WidgetReferenceType())), emptyList()) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HTMLMathStyleWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HTMLMathStyleWidget.kt new file mode 100644 index 0000000..b84038a --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HTMLMathStyleWidget.kt @@ -0,0 +1,49 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType + +private val htmlMathStyleSpec = WidgetSpec( + modelName = "HTMLMathStyleModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "StyleView", + viewModule = "@jupyter-widgets/base", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.htmlMathStyle(setup: HtmlMathStyleWidget.() -> Unit = {}): HtmlMathStyleWidget = + createAndRegisterWidget(HtmlMathStyleWidget.Factory).apply(setup) + +public class HtmlMathStyleWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(htmlMathStyleSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(htmlMathStyleSpec, ::HtmlMathStyleWidget) + + /** + * Background specifications. + */ + public var background: String? by nullableStringProp("background", null) + + /** + * Width of the description to the side of the control. + */ + public var descriptionWidth: String by stringProp("description_width", "") + + /** + * Text font size. + */ + public var fontSize: String? by nullableStringProp("font_size", null) + + /** + * Text color + */ + public var textColor: String? by nullableStringProp("text_color", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HTMLMathWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HTMLMathWidget.kt new file mode 100644 index 0000000..737eb58 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HTMLMathWidget.kt @@ -0,0 +1,69 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val htmlMathSpec = WidgetSpec( + modelName = "HTMLMathModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "HTMLMathView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.htmlMath(setup: HtmlMathWidget.() -> Unit = {}): HtmlMathWidget = + createAndRegisterWidget(HtmlMathWidget.Factory).apply(setup) + +public class HtmlMathWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(htmlMathSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(htmlMathSpec, ::HtmlMathWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Placeholder text to display when nothing has been typed + */ + public var placeholder: String by stringProp("placeholder", "​") + public var style: HtmlMathStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.htmlMathStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * String value + */ + public var value: String by stringProp("value", "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HTMLStyleWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HTMLStyleWidget.kt new file mode 100644 index 0000000..94ec385 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HTMLStyleWidget.kt @@ -0,0 +1,49 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType + +private val htmlStyleSpec = WidgetSpec( + modelName = "HTMLStyleModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "StyleView", + viewModule = "@jupyter-widgets/base", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.htmlStyle(setup: HtmlStyleWidget.() -> Unit = {}): HtmlStyleWidget = + createAndRegisterWidget(HtmlStyleWidget.Factory).apply(setup) + +public class HtmlStyleWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(htmlStyleSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(htmlStyleSpec, ::HtmlStyleWidget) + + /** + * Background specifications. + */ + public var background: String? by nullableStringProp("background", null) + + /** + * Width of the description to the side of the control. + */ + public var descriptionWidth: String by stringProp("description_width", "") + + /** + * Text font size. + */ + public var fontSize: String? by nullableStringProp("font_size", null) + + /** + * Text color + */ + public var textColor: String? by nullableStringProp("text_color", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HTMLWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HTMLWidget.kt new file mode 100644 index 0000000..2e71f20 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/HTMLWidget.kt @@ -0,0 +1,69 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val htmlSpec = WidgetSpec( + modelName = "HTMLModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "HTMLView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.html(setup: HtmlWidget.() -> Unit = {}): HtmlWidget = + createAndRegisterWidget(HtmlWidget.Factory).apply(setup) + +public class HtmlWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(htmlSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(htmlSpec, ::HtmlWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Placeholder text to display when nothing has been typed + */ + public var placeholder: String by stringProp("placeholder", "​") + public var style: HtmlStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.htmlStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * String value + */ + public var value: String by stringProp("value", "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ImageWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ImageWidget.kt new file mode 100644 index 0000000..70a6aee --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ImageWidget.kt @@ -0,0 +1,69 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BytesType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val imageSpec = WidgetSpec( + modelName = "ImageModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "ImageView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.image(setup: ImageWidget.() -> Unit = {}): ImageWidget = + createAndRegisterWidget(ImageWidget.Factory).apply(setup) + +public class ImageWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(imageSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(imageSpec, ::ImageWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * The format of the image. + */ + public var format: String by stringProp("format", "png") + + /** + * Height of the image in pixels. Use layout.height for styling the widget. + */ + public var height: String by stringProp("height", "") + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * The media data as a memory view of bytes. + */ + public var value: ByteArray by bytesProp("value", byteArrayOf()) + + /** + * Width of the image in pixels. Use layout.width for styling the widget. + */ + public var width: String by stringProp("width", "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntProgressWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntProgressWidget.kt new file mode 100644 index 0000000..8f6842c --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntProgressWidget.kt @@ -0,0 +1,89 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.BarStyle +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Orientation +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val intProgressSpec = WidgetSpec( + modelName = "IntProgressModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "ProgressView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.intProgress(setup: IntProgressWidget.() -> Unit = {}): IntProgressWidget = + createAndRegisterWidget(IntProgressWidget.Factory).apply(setup) + +public class IntProgressWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(intProgressSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(intProgressSpec, ::IntProgressWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Use a predefined styling for the progress bar. + */ + public var barStyle: WidgetEnumEntry by prop("bar_style", WidgetEnumType(BarStyle, BarStyle.Default), BarStyle.Default) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Max value + */ + public var max: Int by intProp("max", 100) + + /** + * Min value + */ + public var min: Int by intProp("min", 0) + + /** + * Vertical or horizontal. + */ + public var orientation: WidgetEnumEntry by prop("orientation", WidgetEnumType(Orientation, Orientation.Horizontal), Orientation.Horizontal) + public var style: ProgressStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.progressStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Int value + */ + public var value: Int by intProp("value", 0) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntRangeSliderWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntRangeSliderWidget.kt new file mode 100644 index 0000000..6a988aa --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntRangeSliderWidget.kt @@ -0,0 +1,119 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Behavior +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Orientation +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.ranges.IntRangeType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val intRangeSliderSpec = WidgetSpec( + modelName = "IntRangeSliderModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "IntRangeSliderView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.intRangeSlider(setup: IntRangeSliderWidget.() -> Unit = {}): IntRangeSliderWidget = + createAndRegisterWidget(IntRangeSliderWidget.Factory).apply(setup) + +public class IntRangeSliderWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(intRangeSliderSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(intRangeSliderSpec, ::IntRangeSliderWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Slider dragging behavior. + */ + public var behavior: WidgetEnumEntry by prop("behavior", WidgetEnumType(Behavior, Behavior.DragTap), Behavior.DragTap) + + /** + * Update the value of the widget as the user is sliding the slider. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", true) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Max value + */ + public var max: Int by intProp("max", 100) + + /** + * Min value + */ + public var min: Int by intProp("min", 0) + + /** + * Vertical or horizontal. + */ + public var orientation: WidgetEnumEntry by prop("orientation", WidgetEnumType(Orientation, Orientation.Horizontal), Orientation.Horizontal) + + /** + * Display the current value of the slider next to it. + */ + public var readout: Boolean by boolProp("readout", true) + + /** + * Format for the readout + */ + public var readoutFormat: String by stringProp("readout_format", "d") + + /** + * Minimum step that the value can take + */ + public var step: Int by intProp("step", 1) + + /** + * Slider style customizations. + */ + public var style: SliderStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.sliderStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Tuple of (lower, upper) bounds + */ + public var value: IntRange? by prop("value", NullableType(IntRangeType), 0..1) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntSliderWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntSliderWidget.kt new file mode 100644 index 0000000..52ab5d0 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntSliderWidget.kt @@ -0,0 +1,114 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Behavior +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Orientation +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val intSliderSpec = WidgetSpec( + modelName = "IntSliderModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "IntSliderView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.intSlider(setup: IntSliderWidget.() -> Unit = {}): IntSliderWidget = + createAndRegisterWidget(IntSliderWidget.Factory).apply(setup) + +public class IntSliderWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(intSliderSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(intSliderSpec, ::IntSliderWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Slider dragging behavior. + */ + public var behavior: WidgetEnumEntry by prop("behavior", WidgetEnumType(Behavior, Behavior.DragTap), Behavior.DragTap) + + /** + * Update the value of the widget as the user is holding the slider. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", true) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Max value + */ + public var max: Int by intProp("max", 100) + + /** + * Min value + */ + public var min: Int by intProp("min", 0) + + /** + * Vertical or horizontal. + */ + public var orientation: WidgetEnumEntry by prop("orientation", WidgetEnumType(Orientation, Orientation.Horizontal), Orientation.Horizontal) + + /** + * Display the current value of the slider next to it. + */ + public var readout: Boolean by boolProp("readout", true) + + /** + * Format for the readout + */ + public var readoutFormat: String by stringProp("readout_format", "d") + + /** + * Minimum step to increment the value + */ + public var step: Int by intProp("step", 1) + public var style: SliderStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.sliderStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Int value + */ + public var value: Int by intProp("value", 0) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntTextWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntTextWidget.kt new file mode 100644 index 0000000..6b3c621 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntTextWidget.kt @@ -0,0 +1,84 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val intTextSpec = WidgetSpec( + modelName = "IntTextModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "IntTextView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.intText(setup: IntTextWidget.() -> Unit = {}): IntTextWidget = + createAndRegisterWidget(IntTextWidget.Factory).apply(setup) + +public class IntTextWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(intTextSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(intTextSpec, ::IntTextWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", false) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Minimum step to increment the value + */ + public var step: Int by intProp("step", 1) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Int value + */ + public var value: Int by intProp("value", 0) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntsInputWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntsInputWidget.kt new file mode 100644 index 0000000..a0cfdaa --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/IntsInputWidget.kt @@ -0,0 +1,84 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.TagStyle +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.AnyType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val intsInputSpec = WidgetSpec( + modelName = "IntsInputModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "IntsInputView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.intsInput(setup: IntsInputWidget.() -> Unit = {}): IntsInputWidget = + createAndRegisterWidget(IntsInputWidget.Factory).apply(setup) + +public class IntsInputWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(intsInputSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(intsInputSpec, ::IntsInputWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + public var allowDuplicates: Boolean by boolProp("allow_duplicates", true) + public var allowedTags: List by prop("allowed_tags", ArrayType(AnyType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + public var format: String by stringProp("format", "d") + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + public var max: Int? by nullableIntProp("max", null) + public var min: Int? by nullableIntProp("min", null) + public var placeholder: String by stringProp("placeholder", "​") + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * Use a predefined styling for the tags. + */ + public var tagStyle: WidgetEnumEntry by prop("tag_style", WidgetEnumType(TagStyle, TagStyle.Default), TagStyle.Default) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * List of int tags + */ + public var value: List by prop("value", ArrayType(AnyType), emptyList()) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/LabelStyleWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/LabelStyleWidget.kt new file mode 100644 index 0000000..61deb7d --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/LabelStyleWidget.kt @@ -0,0 +1,74 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType + +private val labelStyleSpec = WidgetSpec( + modelName = "LabelStyleModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "StyleView", + viewModule = "@jupyter-widgets/base", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.labelStyle(setup: LabelStyleWidget.() -> Unit = {}): LabelStyleWidget = + createAndRegisterWidget(LabelStyleWidget.Factory).apply(setup) + +public class LabelStyleWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(labelStyleSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(labelStyleSpec, ::LabelStyleWidget) + + /** + * Background specifications. + */ + public var background: String? by nullableStringProp("background", null) + + /** + * Width of the description to the side of the control. + */ + public var descriptionWidth: String by stringProp("description_width", "") + + /** + * Label text font family. + */ + public var fontFamily: String? by nullableStringProp("font_family", null) + + /** + * Text font size. + */ + public var fontSize: String? by nullableStringProp("font_size", null) + + /** + * Label text font style. + */ + public var fontStyle: String? by nullableStringProp("font_style", null) + + /** + * Label text font variant. + */ + public var fontVariant: String? by nullableStringProp("font_variant", null) + + /** + * Label text font weight. + */ + public var fontWeight: String? by nullableStringProp("font_weight", null) + + /** + * Text color + */ + public var textColor: String? by nullableStringProp("text_color", null) + + /** + * Label text decoration. + */ + public var textDecoration: String? by nullableStringProp("text_decoration", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/LabelWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/LabelWidget.kt new file mode 100644 index 0000000..6c20a79 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/LabelWidget.kt @@ -0,0 +1,69 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val labelSpec = WidgetSpec( + modelName = "LabelModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "LabelView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.label(setup: LabelWidget.() -> Unit = {}): LabelWidget = + createAndRegisterWidget(LabelWidget.Factory).apply(setup) + +public class LabelWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(labelSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(labelSpec, ::LabelWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Placeholder text to display when nothing has been typed + */ + public var placeholder: String by stringProp("placeholder", "​") + public var style: LabelStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.labelStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * String value + */ + public var value: String by stringProp("value", "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/LayoutWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/LayoutWidget.kt new file mode 100644 index 0000000..1447aff --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/LayoutWidget.kt @@ -0,0 +1,234 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.AlignContent +import org.jetbrains.kotlinx.jupyter.widget.library.enums.AlignItems +import org.jetbrains.kotlinx.jupyter.widget.library.enums.AlignSelf +import org.jetbrains.kotlinx.jupyter.widget.library.enums.GridAutoFlow +import org.jetbrains.kotlinx.jupyter.widget.library.enums.JustifyContent +import org.jetbrains.kotlinx.jupyter.widget.library.enums.JustifyItems +import org.jetbrains.kotlinx.jupyter.widget.library.enums.ObjectFit +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Visibility +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType + +private val layoutSpec = WidgetSpec( + modelName = "LayoutModel", + modelModule = "@jupyter-widgets/base", + modelModuleVersion = "2.0.0", + viewName = "LayoutView", + viewModule = "@jupyter-widgets/base", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.layout(setup: LayoutWidget.() -> Unit = {}): LayoutWidget = + createAndRegisterWidget(LayoutWidget.Factory).apply(setup) + +public class LayoutWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(layoutSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(layoutSpec, ::LayoutWidget) + + /** + * The align-content CSS attribute. + */ + public var alignContent: WidgetEnumEntry? by prop("align_content", NullableType(WidgetEnumType(AlignContent, AlignContent.FlexStart)), null) + + /** + * The align-items CSS attribute. + */ + public var alignItems: WidgetEnumEntry? by prop("align_items", NullableType(WidgetEnumType(AlignItems, AlignItems.FlexStart)), null) + + /** + * The align-self CSS attribute. + */ + public var alignSelf: WidgetEnumEntry? by prop("align_self", NullableType(WidgetEnumType(AlignSelf, AlignSelf.Auto)), null) + + /** + * The border bottom CSS attribute. + */ + public var borderBottom: String? by nullableStringProp("border_bottom", null) + + /** + * The border left CSS attribute. + */ + public var borderLeft: String? by nullableStringProp("border_left", null) + + /** + * The border right CSS attribute. + */ + public var borderRight: String? by nullableStringProp("border_right", null) + + /** + * The border top CSS attribute. + */ + public var borderTop: String? by nullableStringProp("border_top", null) + + /** + * The bottom CSS attribute. + */ + public var bottom: String? by nullableStringProp("bottom", null) + + /** + * The display CSS attribute. + */ + public var display: String? by nullableStringProp("display", null) + + /** + * The flex CSS attribute. + */ + public var flex: String? by nullableStringProp("flex", null) + + /** + * The flex-flow CSS attribute. + */ + public var flexFlow: String? by nullableStringProp("flex_flow", null) + + /** + * The grid-area CSS attribute. + */ + public var gridArea: String? by nullableStringProp("grid_area", null) + + /** + * The grid-auto-columns CSS attribute. + */ + public var gridAutoColumns: String? by nullableStringProp("grid_auto_columns", null) + + /** + * The grid-auto-flow CSS attribute. + */ + public var gridAutoFlow: WidgetEnumEntry? by prop("grid_auto_flow", NullableType(WidgetEnumType(GridAutoFlow, GridAutoFlow.Column)), null) + + /** + * The grid-auto-rows CSS attribute. + */ + public var gridAutoRows: String? by nullableStringProp("grid_auto_rows", null) + + /** + * The grid-column CSS attribute. + */ + public var gridColumn: String? by nullableStringProp("grid_column", null) + + /** + * The grid-gap CSS attribute. + */ + public var gridGap: String? by nullableStringProp("grid_gap", null) + + /** + * The grid-row CSS attribute. + */ + public var gridRow: String? by nullableStringProp("grid_row", null) + + /** + * The grid-template-areas CSS attribute. + */ + public var gridTemplateAreas: String? by nullableStringProp("grid_template_areas", null) + + /** + * The grid-template-columns CSS attribute. + */ + public var gridTemplateColumns: String? by nullableStringProp("grid_template_columns", null) + + /** + * The grid-template-rows CSS attribute. + */ + public var gridTemplateRows: String? by nullableStringProp("grid_template_rows", null) + + /** + * The height CSS attribute. + */ + public var height: String? by nullableStringProp("height", null) + + /** + * The justify-content CSS attribute. + */ + public var justifyContent: WidgetEnumEntry? by prop("justify_content", NullableType(WidgetEnumType(JustifyContent, JustifyContent.FlexStart)), null) + + /** + * The justify-items CSS attribute. + */ + public var justifyItems: WidgetEnumEntry? by prop("justify_items", NullableType(WidgetEnumType(JustifyItems, JustifyItems.FlexStart)), null) + + /** + * The left CSS attribute. + */ + public var left: String? by nullableStringProp("left", null) + + /** + * The margin CSS attribute. + */ + public var margin: String? by nullableStringProp("margin", null) + + /** + * The max-height CSS attribute. + */ + public var maxHeight: String? by nullableStringProp("max_height", null) + + /** + * The max-width CSS attribute. + */ + public var maxWidth: String? by nullableStringProp("max_width", null) + + /** + * The min-height CSS attribute. + */ + public var minHeight: String? by nullableStringProp("min_height", null) + + /** + * The min-width CSS attribute. + */ + public var minWidth: String? by nullableStringProp("min_width", null) + + /** + * The object-fit CSS attribute. + */ + public var objectFit: WidgetEnumEntry? by prop("object_fit", NullableType(WidgetEnumType(ObjectFit, ObjectFit.Contain)), null) + + /** + * The object-position CSS attribute. + */ + public var objectPosition: String? by nullableStringProp("object_position", null) + + /** + * The order CSS attribute. + */ + public var order: String? by nullableStringProp("order", null) + + /** + * The overflow CSS attribute. + */ + public var overflow: String? by nullableStringProp("overflow", null) + + /** + * The padding CSS attribute. + */ + public var padding: String? by nullableStringProp("padding", null) + + /** + * The right CSS attribute. + */ + public var right: String? by nullableStringProp("right", null) + + /** + * The top CSS attribute. + */ + public var top: String? by nullableStringProp("top", null) + + /** + * The visibility CSS attribute. + */ + public var visibility: WidgetEnumEntry? by prop("visibility", NullableType(WidgetEnumType(Visibility, Visibility.Visible)), null) + + /** + * The width CSS attribute. + */ + public var width: String? by nullableStringProp("width", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/LinkWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/LinkWidget.kt new file mode 100644 index 0000000..f73bd58 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/LinkWidget.kt @@ -0,0 +1,42 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.PairType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val linkSpec = WidgetSpec( + modelName = "LinkModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = null, + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.link(setup: LinkWidget.() -> Unit = {}): LinkWidget = + createAndRegisterWidget(LinkWidget.Factory).apply(setup) + +public class LinkWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(linkSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(linkSpec, ::LinkWidget) + + /** + * The source (widget, 'trait_name') pair + */ + public var source: Pair? by prop("source", NullableType(PairType(NullableType(WidgetReferenceType()), StringType)), null to "") + + /** + * The target (widget, 'trait_name') pair + */ + public var target: Pair? by prop("target", NullableType(PairType(NullableType(WidgetReferenceType()), StringType)), null to "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/NaiveDatetimeWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/NaiveDatetimeWidget.kt new file mode 100644 index 0000000..c6a2f97 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/NaiveDatetimeWidget.kt @@ -0,0 +1,72 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.datetime.DatetimeType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val naiveDatetimeSpec = WidgetSpec( + modelName = "NaiveDatetimeModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "DatetimeView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.naiveDatetime(setup: NaiveDatetimeWidget.() -> Unit = {}): NaiveDatetimeWidget = + createAndRegisterWidget(NaiveDatetimeWidget.Factory).apply(setup) + +public class NaiveDatetimeWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(naiveDatetimeSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(naiveDatetimeSpec, ::NaiveDatetimeWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes. + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + public var max: java.time.Instant? by nullableDateTimeProp("max", null) + public var min: java.time.Instant? by nullableDateTimeProp("min", null) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + public var value: java.time.Instant? by nullableDateTimeProp("value", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/OutputWidgetBase.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/OutputWidgetBase.kt new file mode 100644 index 0000000..cd076b0 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/OutputWidgetBase.kt @@ -0,0 +1,55 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.RawObjectType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +internal val outputSpec = WidgetSpec( + modelName = "OutputModel", + modelModule = "@jupyter-widgets/output", + modelModuleVersion = "1.0.0", + viewName = "OutputView", + viewModule = "@jupyter-widgets/output", + viewModuleVersion = "1.0.0", +) + +public abstract class OutputWidgetBase internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(outputSpec, widgetManager) { + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Parent message id of messages to capture + */ + public var msgId: String by stringProp("msg_id", "") + + /** + * The output messages synced from the frontend. + */ + public var outputs: List> by prop("outputs", ArrayType(RawObjectType), emptyList()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/PasswordWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/PasswordWidget.kt new file mode 100644 index 0000000..f86f541 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/PasswordWidget.kt @@ -0,0 +1,79 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val passwordSpec = WidgetSpec( + modelName = "PasswordModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "PasswordView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.password(setup: PasswordWidget.() -> Unit = {}): PasswordWidget = + createAndRegisterWidget(PasswordWidget.Factory).apply(setup) + +public class PasswordWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(passwordSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(passwordSpec, ::PasswordWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", true) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Placeholder text to display when nothing has been typed + */ + public var placeholder: String by stringProp("placeholder", "​") + public var style: TextStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.textStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * String value + */ + public var value: String by stringProp("value", "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/PlayWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/PlayWidget.kt new file mode 100644 index 0000000..4ff9483 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/PlayWidget.kt @@ -0,0 +1,109 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val playSpec = WidgetSpec( + modelName = "PlayModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "PlayView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.play(setup: PlayWidget.() -> Unit = {}): PlayWidget = + createAndRegisterWidget(PlayWidget.Factory).apply(setup) + +public class PlayWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(playSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(playSpec, ::PlayWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + + /** + * The time between two animation steps (ms). + */ + public var interval: Int by intProp("interval", 100) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Max value + */ + public var max: Int by intProp("max", 100) + + /** + * Min value + */ + public var min: Int by intProp("min", 0) + + /** + * Whether the control is currently playing. + */ + public var playing: Boolean by boolProp("playing", false) + + /** + * Whether the control will repeat in a continuous loop. + */ + public var repeat: Boolean by boolProp("repeat", false) + + /** + * Show the repeat toggle button in the widget. + */ + public var showRepeat: Boolean by boolProp("show_repeat", true) + + /** + * Increment step + */ + public var step: Int by intProp("step", 1) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Int value + */ + public var value: Int by intProp("value", 0) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ProgressStyleWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ProgressStyleWidget.kt new file mode 100644 index 0000000..21997e0 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ProgressStyleWidget.kt @@ -0,0 +1,39 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType + +private val progressStyleSpec = WidgetSpec( + modelName = "ProgressStyleModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "StyleView", + viewModule = "@jupyter-widgets/base", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.progressStyle(setup: ProgressStyleWidget.() -> Unit = {}): ProgressStyleWidget = + createAndRegisterWidget(ProgressStyleWidget.Factory).apply(setup) + +public class ProgressStyleWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(progressStyleSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(progressStyleSpec, ::ProgressStyleWidget) + + /** + * Color of the progress bar. + */ + public var barColor: String? by nullableStringProp("bar_color", null) + + /** + * Width of the description to the side of the control. + */ + public var descriptionWidth: String by stringProp("description_width", "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/RadioButtonsWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/RadioButtonsWidget.kt new file mode 100644 index 0000000..0943b6e --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/RadioButtonsWidget.kt @@ -0,0 +1,77 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Orientation +import org.jetbrains.kotlinx.jupyter.widget.library.options.SingleNullableSelectionWidgetBase +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val radioButtonsSpec = WidgetSpec( + modelName = "RadioButtonsModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "RadioButtonsView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.radioButtons(setup: RadioButtonsWidget.() -> Unit = {}): RadioButtonsWidget = + createAndRegisterWidget(RadioButtonsWidget.Factory).apply(setup) + +public class RadioButtonsWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : SingleNullableSelectionWidgetBase(radioButtonsSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(radioButtonsSpec, ::RadioButtonsWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Vertical or horizontal. + */ + public var orientation: WidgetEnumEntry by prop("orientation", WidgetEnumType(Orientation, Orientation.Vertical), Orientation.Vertical) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SelectMultipleWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SelectMultipleWidget.kt new file mode 100644 index 0000000..dbea1e7 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SelectMultipleWidget.kt @@ -0,0 +1,75 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.options.MultipleSelectionWidgetBase +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val selectMultipleSpec = WidgetSpec( + modelName = "SelectMultipleModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "SelectMultipleView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.selectMultiple(setup: SelectMultipleWidget.() -> Unit = {}): SelectMultipleWidget = + createAndRegisterWidget(SelectMultipleWidget.Factory).apply(setup) + +public class SelectMultipleWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : MultipleSelectionWidgetBase(selectMultipleSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(selectMultipleSpec, ::SelectMultipleWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * The number of rows to display. + */ + public var rows: Int by intProp("rows", 5) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SelectWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SelectWidget.kt new file mode 100644 index 0000000..596d2b9 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SelectWidget.kt @@ -0,0 +1,75 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.options.SingleNullableSelectionWidgetBase +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val selectSpec = WidgetSpec( + modelName = "SelectModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "SelectView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.select(setup: SelectWidget.() -> Unit = {}): SelectWidget = + createAndRegisterWidget(SelectWidget.Factory).apply(setup) + +public class SelectWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : SingleNullableSelectionWidgetBase(selectSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(selectSpec, ::SelectWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * The number of rows to display. + */ + public var rows: Int by intProp("rows", 5) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SelectionRangeSliderWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SelectionRangeSliderWidget.kt new file mode 100644 index 0000000..c5da385 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SelectionRangeSliderWidget.kt @@ -0,0 +1,89 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Behavior +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Orientation +import org.jetbrains.kotlinx.jupyter.widget.library.options.SelectionRangeWidgetBase +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val selectionRangeSliderSpec = WidgetSpec( + modelName = "SelectionRangeSliderModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "SelectionRangeSliderView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.selectionRangeSlider(setup: SelectionRangeSliderWidget.() -> Unit = {}): SelectionRangeSliderWidget = + createAndRegisterWidget(SelectionRangeSliderWidget.Factory).apply(setup) + +public class SelectionRangeSliderWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : SelectionRangeWidgetBase(selectionRangeSliderSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(selectionRangeSliderSpec, ::SelectionRangeSliderWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Slider dragging behavior. + */ + public var behavior: WidgetEnumEntry by prop("behavior", WidgetEnumType(Behavior, Behavior.DragTap), Behavior.DragTap) + + /** + * Update the value of the widget as the user is holding the slider. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", true) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Vertical or horizontal. + */ + public var orientation: WidgetEnumEntry by prop("orientation", WidgetEnumType(Orientation, Orientation.Horizontal), Orientation.Horizontal) + + /** + * Display the current selected label next to the slider + */ + public var readout: Boolean by boolProp("readout", true) + public var style: SliderStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.sliderStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SelectionSliderWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SelectionSliderWidget.kt new file mode 100644 index 0000000..920df65 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SelectionSliderWidget.kt @@ -0,0 +1,89 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Behavior +import org.jetbrains.kotlinx.jupyter.widget.library.enums.Orientation +import org.jetbrains.kotlinx.jupyter.widget.library.options.SingleSelectionWidgetBase +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val selectionSliderSpec = WidgetSpec( + modelName = "SelectionSliderModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "SelectionSliderView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.selectionSlider(setup: SelectionSliderWidget.() -> Unit = {}): SelectionSliderWidget = + createAndRegisterWidget(SelectionSliderWidget.Factory).apply(setup) + +public class SelectionSliderWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : SingleSelectionWidgetBase(selectionSliderSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(selectionSliderSpec, ::SelectionSliderWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Slider dragging behavior. + */ + public var behavior: WidgetEnumEntry by prop("behavior", WidgetEnumType(Behavior, Behavior.DragTap), Behavior.DragTap) + + /** + * Update the value of the widget as the user is holding the slider. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", true) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Vertical or horizontal. + */ + public var orientation: WidgetEnumEntry by prop("orientation", WidgetEnumType(Orientation, Orientation.Horizontal), Orientation.Horizontal) + + /** + * Display the current selected label next to the slider + */ + public var readout: Boolean by boolProp("readout", true) + public var style: SliderStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.sliderStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SliderStyleWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SliderStyleWidget.kt new file mode 100644 index 0000000..7ae67d7 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/SliderStyleWidget.kt @@ -0,0 +1,39 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType + +private val sliderStyleSpec = WidgetSpec( + modelName = "SliderStyleModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "StyleView", + viewModule = "@jupyter-widgets/base", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.sliderStyle(setup: SliderStyleWidget.() -> Unit = {}): SliderStyleWidget = + createAndRegisterWidget(SliderStyleWidget.Factory).apply(setup) + +public class SliderStyleWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(sliderStyleSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(sliderStyleSpec, ::SliderStyleWidget) + + /** + * Width of the description to the side of the control. + */ + public var descriptionWidth: String by stringProp("description_width", "") + + /** + * Color of the slider handle. + */ + public var handleColor: String? by nullableStringProp("handle_color", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/StackWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/StackWidget.kt new file mode 100644 index 0000000..cbc365b --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/StackWidget.kt @@ -0,0 +1,73 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.BoxStyle +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val stackSpec = WidgetSpec( + modelName = "StackModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "StackView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.stack(setup: StackWidget.() -> Unit = {}): StackWidget = + createAndRegisterWidget(StackWidget.Factory).apply(setup) + +public class StackWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(stackSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(stackSpec, ::StackWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Use a predefined styling for the box. + */ + public var boxStyle: WidgetEnumEntry by prop("box_style", WidgetEnumType(BoxStyle, BoxStyle.Default), BoxStyle.Default) + + /** + * List of widget children + */ + public var children: List by prop("children", ArrayType(NullableType(WidgetReferenceType())), emptyList()) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * The index of the selected page. This is either an integer selecting a particular sub-widget, or None to have no widgets selected. + */ + public var selectedIndex: Int? by nullableIntProp("selected_index", null) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * Titles of the pages + */ + public var titles: List by prop("titles", ArrayType(StringType), emptyList()) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TabWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TabWidget.kt new file mode 100644 index 0000000..7099b32 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TabWidget.kt @@ -0,0 +1,73 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.BoxStyle +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val tabSpec = WidgetSpec( + modelName = "TabModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "TabView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.tab(setup: TabWidget.() -> Unit = {}): TabWidget = + createAndRegisterWidget(TabWidget.Factory).apply(setup) + +public class TabWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(tabSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(tabSpec, ::TabWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Use a predefined styling for the box. + */ + public var boxStyle: WidgetEnumEntry by prop("box_style", WidgetEnumType(BoxStyle, BoxStyle.Default), BoxStyle.Default) + + /** + * List of widget children + */ + public var children: List by prop("children", ArrayType(NullableType(WidgetReferenceType())), emptyList()) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * The index of the selected page. This is either an integer selecting a particular sub-widget, or None to have no widgets selected. + */ + public var selectedIndex: Int? by nullableIntProp("selected_index", null) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * Titles of the pages + */ + public var titles: List by prop("titles", ArrayType(StringType), emptyList()) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TagsInputWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TagsInputWidget.kt new file mode 100644 index 0000000..647fa48 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TagsInputWidget.kt @@ -0,0 +1,80 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.TagStyle +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.AnyType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val tagsInputSpec = WidgetSpec( + modelName = "TagsInputModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "TagsInputView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.tagsInput(setup: TagsInputWidget.() -> Unit = {}): TagsInputWidget = + createAndRegisterWidget(TagsInputWidget.Factory).apply(setup) + +public class TagsInputWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(tagsInputSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(tagsInputSpec, ::TagsInputWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + public var allowDuplicates: Boolean by boolProp("allow_duplicates", true) + public var allowedTags: List by prop("allowed_tags", ArrayType(AnyType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + public var placeholder: String by stringProp("placeholder", "​") + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * Use a predefined styling for the tags. + */ + public var tagStyle: WidgetEnumEntry by prop("tag_style", WidgetEnumType(TagStyle, TagStyle.Default), TagStyle.Default) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * List of string tags + */ + public var value: List by prop("value", ArrayType(AnyType), emptyList()) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TextStyleWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TextStyleWidget.kt new file mode 100644 index 0000000..141baf4 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TextStyleWidget.kt @@ -0,0 +1,49 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType + +private val textStyleSpec = WidgetSpec( + modelName = "TextStyleModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "StyleView", + viewModule = "@jupyter-widgets/base", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.textStyle(setup: TextStyleWidget.() -> Unit = {}): TextStyleWidget = + createAndRegisterWidget(TextStyleWidget.Factory).apply(setup) + +public class TextStyleWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(textStyleSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(textStyleSpec, ::TextStyleWidget) + + /** + * Background specifications. + */ + public var background: String? by nullableStringProp("background", null) + + /** + * Width of the description to the side of the control. + */ + public var descriptionWidth: String by stringProp("description_width", "") + + /** + * Text font size. + */ + public var fontSize: String? by nullableStringProp("font_size", null) + + /** + * Text color + */ + public var textColor: String? by nullableStringProp("text_color", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TextWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TextWidget.kt new file mode 100644 index 0000000..e7c759b --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TextWidget.kt @@ -0,0 +1,79 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val textSpec = WidgetSpec( + modelName = "TextModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "TextView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.text(setup: TextWidget.() -> Unit = {}): TextWidget = + createAndRegisterWidget(TextWidget.Factory).apply(setup) + +public class TextWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(textSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(textSpec, ::TextWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", true) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Placeholder text to display when nothing has been typed + */ + public var placeholder: String by stringProp("placeholder", "​") + public var style: TextStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.textStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * String value + */ + public var value: String by stringProp("value", "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TextareaWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TextareaWidget.kt new file mode 100644 index 0000000..fde8e19 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TextareaWidget.kt @@ -0,0 +1,85 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val textareaSpec = WidgetSpec( + modelName = "TextareaModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "TextareaView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.textarea(setup: TextareaWidget.() -> Unit = {}): TextareaWidget = + createAndRegisterWidget(TextareaWidget.Factory).apply(setup) + +public class TextareaWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(textareaSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(textareaSpec, ::TextareaWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away. + */ + public var continuousUpdate: Boolean by boolProp("continuous_update", true) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Placeholder text to display when nothing has been typed + */ + public var placeholder: String by stringProp("placeholder", "​") + + /** + * The number of rows to display. + */ + public var rows: Int? by nullableIntProp("rows", null) + public var style: TextStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.textStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * String value + */ + public var value: String by stringProp("value", "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TimeWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TimeWidget.kt new file mode 100644 index 0000000..a828037 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/TimeWidget.kt @@ -0,0 +1,107 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.UnionType +import org.jetbrains.kotlinx.jupyter.widget.model.types.datetime.TimeType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.FloatType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +public sealed interface TimeWidgetStep { + @JvmInline public value class DoubleValue(public val value: Double) : TimeWidgetStep + public object AnyStep : TimeWidgetStep +} + + +private val TimeWidgetStepType_Option0 = FloatType + +private val TimeWidgetStepType = UnionType( + name = "step", + default = TimeWidgetStep.DoubleValue(60.0), + serializer = { value, widgetManager -> + when (value) { + is TimeWidgetStep.DoubleValue -> TimeWidgetStepType_Option0.serialize(value.value, widgetManager) + is TimeWidgetStep.AnyStep -> "any" + } + }, + deserializers = listOf( + { patch, widgetManager -> TimeWidgetStep.DoubleValue(TimeWidgetStepType_Option0.deserialize(patch, widgetManager)) }, + { patch, _ -> + when (patch) { + "any" -> TimeWidgetStep.AnyStep + else -> throw Exception("Unknown enum value: $patch") + } + } + ), +) + +private val timeSpec = WidgetSpec( + modelName = "TimeModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "TimeView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.time(setup: TimeWidget.() -> Unit = {}): TimeWidget = + createAndRegisterWidget(TimeWidget.Factory).apply(setup) + +public class TimeWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(timeSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(timeSpec, ::TimeWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes. + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + public var max: java.time.LocalTime? by nullableTimeProp("max", null) + public var min: java.time.LocalTime? by nullableTimeProp("min", null) + + /** + * The time step to use for the picker, in seconds, or "any". + */ + public var step: TimeWidgetStep by prop("step", TimeWidgetStepType, TimeWidgetStep.DoubleValue(60.0)) + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + public var value: java.time.LocalTime? by nullableTimeProp("value", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ToggleButtonStyleWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ToggleButtonStyleWidget.kt new file mode 100644 index 0000000..47229b9 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ToggleButtonStyleWidget.kt @@ -0,0 +1,69 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType + +private val toggleButtonStyleSpec = WidgetSpec( + modelName = "ToggleButtonStyleModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "StyleView", + viewModule = "@jupyter-widgets/base", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.toggleButtonStyle(setup: ToggleButtonStyleWidget.() -> Unit = {}): ToggleButtonStyleWidget = + createAndRegisterWidget(ToggleButtonStyleWidget.Factory).apply(setup) + +public class ToggleButtonStyleWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(toggleButtonStyleSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(toggleButtonStyleSpec, ::ToggleButtonStyleWidget) + + /** + * Width of the description to the side of the control. + */ + public var descriptionWidth: String by stringProp("description_width", "") + + /** + * Toggle button text font family. + */ + public var fontFamily: String? by nullableStringProp("font_family", null) + + /** + * Toggle button text font size. + */ + public var fontSize: String? by nullableStringProp("font_size", null) + + /** + * Toggle button text font style. + */ + public var fontStyle: String? by nullableStringProp("font_style", null) + + /** + * Toggle button text font variant. + */ + public var fontVariant: String? by nullableStringProp("font_variant", null) + + /** + * Toggle button text font weight. + */ + public var fontWeight: String? by nullableStringProp("font_weight", null) + + /** + * Toggle button text color + */ + public var textColor: String? by nullableStringProp("text_color", null) + + /** + * Toggle button text decoration. + */ + public var textDecoration: String? by nullableStringProp("text_decoration", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ToggleButtonWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ToggleButtonWidget.kt new file mode 100644 index 0000000..223fef5 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ToggleButtonWidget.kt @@ -0,0 +1,86 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.ButtonStyle +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val toggleButtonSpec = WidgetSpec( + modelName = "ToggleButtonModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "ToggleButtonView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.toggleButton(setup: ToggleButtonWidget.() -> Unit = {}): ToggleButtonWidget = + createAndRegisterWidget(ToggleButtonWidget.Factory).apply(setup) + +public class ToggleButtonWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(toggleButtonSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(toggleButtonSpec, ::ToggleButtonWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Use a predefined styling for the button. + */ + public var buttonStyle: WidgetEnumEntry by prop("button_style", WidgetEnumType(ButtonStyle, ButtonStyle.Default), ButtonStyle.Default) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes. + */ + public var disabled: Boolean by boolProp("disabled", false) + + /** + * Font-awesome icon. + */ + public var icon: String by stringProp("icon", "") + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Styling customizations + */ + public var style: ToggleButtonStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.toggleButtonStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Bool value + */ + public var value: Boolean by boolProp("value", false) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ToggleButtonsStyleWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ToggleButtonsStyleWidget.kt new file mode 100644 index 0000000..57cecce --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ToggleButtonsStyleWidget.kt @@ -0,0 +1,43 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType + +private val toggleButtonsStyleSpec = WidgetSpec( + modelName = "ToggleButtonsStyleModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "StyleView", + viewModule = "@jupyter-widgets/base", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.toggleButtonsStyle(setup: ToggleButtonsStyleWidget.() -> Unit = {}): ToggleButtonsStyleWidget = + createAndRegisterWidget(ToggleButtonsStyleWidget.Factory).apply(setup) + +public class ToggleButtonsStyleWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(toggleButtonsStyleSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(toggleButtonsStyleSpec, ::ToggleButtonsStyleWidget) + + /** + * The width of each button. + */ + public var buttonWidth: String by stringProp("button_width", "") + + /** + * Width of the description to the side of the control. + */ + public var descriptionWidth: String by stringProp("description_width", "") + + /** + * Text font weight of each button. + */ + public var fontWeight: String by stringProp("font_weight", "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ToggleButtonsWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ToggleButtonsWidget.kt new file mode 100644 index 0000000..871226c --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ToggleButtonsWidget.kt @@ -0,0 +1,83 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.ButtonStyle +import org.jetbrains.kotlinx.jupyter.widget.library.options.SingleNullableSelectionWidgetBase +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val toggleButtonsSpec = WidgetSpec( + modelName = "ToggleButtonsModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "ToggleButtonsView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.toggleButtons(setup: ToggleButtonsWidget.() -> Unit = {}): ToggleButtonsWidget = + createAndRegisterWidget(ToggleButtonsWidget.Factory).apply(setup) + +public class ToggleButtonsWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : SingleNullableSelectionWidgetBase(toggleButtonsSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(toggleButtonsSpec, ::ToggleButtonsWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Use a predefined styling for the buttons. + */ + public var buttonStyle: WidgetEnumEntry? by prop("button_style", NullableType(WidgetEnumType(ButtonStyle, ButtonStyle.Default)), ButtonStyle.Default) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes + */ + public var disabled: Boolean by boolProp("disabled", false) + + /** + * Icons names for each button (FontAwesome names without the fa- prefix). + */ + public var icons: List by prop("icons", ArrayType(StringType), emptyList()) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + public var style: ToggleButtonsStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.toggleButtonsStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Tooltips for each button. + */ + public var tooltips: List by prop("tooltips", ArrayType(StringType), emptyList()) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/VBoxWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/VBoxWidget.kt new file mode 100644 index 0000000..e040322 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/VBoxWidget.kt @@ -0,0 +1,62 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.library.enums.BoxStyle +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val vBoxSpec = WidgetSpec( + modelName = "VBoxModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "VBoxView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.vBox(setup: VBoxWidget.() -> Unit = {}): VBoxWidget = + createAndRegisterWidget(VBoxWidget.Factory).apply(setup) + +public class VBoxWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(vBoxSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(vBoxSpec, ::VBoxWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Use a predefined styling for the box. + */ + public var boxStyle: WidgetEnumEntry by prop("box_style", WidgetEnumType(BoxStyle, BoxStyle.Default), BoxStyle.Default) + + /** + * List of widget children + */ + public var children: List by prop("children", ArrayType(NullableType(WidgetReferenceType())), emptyList()) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ValidWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ValidWidget.kt new file mode 100644 index 0000000..2e24fe0 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ValidWidget.kt @@ -0,0 +1,78 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val validSpec = WidgetSpec( + modelName = "ValidModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "ValidView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.valid(setup: ValidWidget.() -> Unit = {}): ValidWidget = + createAndRegisterWidget(ValidWidget.Factory).apply(setup) + +public class ValidWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(validSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(validSpec, ::ValidWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * Description of the control. + */ + public var description: String by stringProp("description", "") + + /** + * Accept HTML in the description. + */ + public var descriptionAllowHtml: Boolean by boolProp("description_allow_html", false) + + /** + * Enable or disable user changes. + */ + public var disabled: Boolean by boolProp("disabled", false) + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * Message displayed when the value is False + */ + public var readout: String by stringProp("readout", "Invalid") + + /** + * Styling customizations + */ + public var style: DescriptionStyleWidget? by nullableWidgetProp("style", if (fromFrontend) null else widgetManager.descriptionStyle()) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * Bool value + */ + public var value: Boolean by boolProp("value", false) +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/VideoWidget.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/VideoWidget.kt new file mode 100644 index 0000000..8ec09c3 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/VideoWidget.kt @@ -0,0 +1,84 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BytesType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType + +private val videoSpec = WidgetSpec( + modelName = "VideoModel", + modelModule = "@jupyter-widgets/controls", + modelModuleVersion = "2.0.0", + viewName = "VideoView", + viewModule = "@jupyter-widgets/controls", + viewModuleVersion = "2.0.0", +) + +public fun WidgetManager.video(setup: VideoWidget.() -> Unit = {}): VideoWidget = + createAndRegisterWidget(VideoWidget.Factory).apply(setup) + +public class VideoWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : DefaultWidgetModel(videoSpec, widgetManager) { + internal object Factory : DefaultWidgetFactory(videoSpec, ::VideoWidget) + + /** + * CSS classes applied to widget DOM element + */ + public var domClasses: List by prop("_dom_classes", ArrayType(StringType), emptyList()) + + /** + * When true, the video starts when it's displayed + */ + public var autoplay: Boolean by boolProp("autoplay", true) + + /** + * Specifies that video controls should be displayed (such as a play/pause button etc) + */ + public var controls: Boolean by boolProp("controls", true) + + /** + * The format of the video. + */ + public var format: String by stringProp("format", "mp4") + + /** + * Height of the video in pixels. + */ + public var height: String by stringProp("height", "") + public var layout: LayoutWidget? by nullableWidgetProp("layout", if (fromFrontend) null else widgetManager.layout()) + + /** + * When true, the video will start from the beginning after finishing + */ + public var loop: Boolean by boolProp("loop", true) + + /** + * Is widget tabbable? + */ + public var tabbable: Boolean? by nullableBoolProp("tabbable", null) + + /** + * A tooltip caption. + */ + public var tooltip: String? by nullableStringProp("tooltip", null) + + /** + * The media data as a memory view of bytes. + */ + public var value: ByteArray by bytesProp("value", byteArrayOf()) + + /** + * Width of the video in pixels. + */ + public var width: String by stringProp("width", "") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/AlignContent.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/AlignContent.kt new file mode 100644 index 0000000..a052270 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/AlignContent.kt @@ -0,0 +1,18 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object AlignContent : WidgetEnum() { + public val FlexStart: WidgetEnumEntry by entry("flex-start") + public val FlexEnd: WidgetEnumEntry by entry("flex-end") + public val Center: WidgetEnumEntry by entry("center") + public val SpaceBetween: WidgetEnumEntry by entry("space-between") + public val SpaceAround: WidgetEnumEntry by entry("space-around") + public val SpaceEvenly: WidgetEnumEntry by entry("space-evenly") + public val Stretch: WidgetEnumEntry by entry("stretch") + public val Inherit: WidgetEnumEntry by entry("inherit") + public val Initial: WidgetEnumEntry by entry("initial") + public val Unset: WidgetEnumEntry by entry("unset") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/AlignItems.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/AlignItems.kt new file mode 100644 index 0000000..f8892c1 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/AlignItems.kt @@ -0,0 +1,16 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object AlignItems : WidgetEnum() { + public val FlexStart: WidgetEnumEntry by entry("flex-start") + public val FlexEnd: WidgetEnumEntry by entry("flex-end") + public val Center: WidgetEnumEntry by entry("center") + public val Baseline: WidgetEnumEntry by entry("baseline") + public val Stretch: WidgetEnumEntry by entry("stretch") + public val Inherit: WidgetEnumEntry by entry("inherit") + public val Initial: WidgetEnumEntry by entry("initial") + public val Unset: WidgetEnumEntry by entry("unset") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/AlignSelf.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/AlignSelf.kt new file mode 100644 index 0000000..4562aa5 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/AlignSelf.kt @@ -0,0 +1,17 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object AlignSelf : WidgetEnum() { + public val Auto: WidgetEnumEntry by entry("auto") + public val FlexStart: WidgetEnumEntry by entry("flex-start") + public val FlexEnd: WidgetEnumEntry by entry("flex-end") + public val Center: WidgetEnumEntry by entry("center") + public val Baseline: WidgetEnumEntry by entry("baseline") + public val Stretch: WidgetEnumEntry by entry("stretch") + public val Inherit: WidgetEnumEntry by entry("inherit") + public val Initial: WidgetEnumEntry by entry("initial") + public val Unset: WidgetEnumEntry by entry("unset") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/BarStyle.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/BarStyle.kt new file mode 100644 index 0000000..ff2378a --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/BarStyle.kt @@ -0,0 +1,13 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object BarStyle : WidgetEnum() { + public val Success: WidgetEnumEntry by entry("success") + public val Info: WidgetEnumEntry by entry("info") + public val Warning: WidgetEnumEntry by entry("warning") + public val Danger: WidgetEnumEntry by entry("danger") + public val Default: WidgetEnumEntry by entry("") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/Behavior.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/Behavior.kt new file mode 100644 index 0000000..49ff0ae --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/Behavior.kt @@ -0,0 +1,13 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object Behavior : WidgetEnum() { + public val DragTap: WidgetEnumEntry by entry("drag-tap") + public val DragSnap: WidgetEnumEntry by entry("drag-snap") + public val Tap: WidgetEnumEntry by entry("tap") + public val Drag: WidgetEnumEntry by entry("drag") + public val Snap: WidgetEnumEntry by entry("snap") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/BoxStyle.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/BoxStyle.kt new file mode 100644 index 0000000..35f67c4 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/BoxStyle.kt @@ -0,0 +1,13 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object BoxStyle : WidgetEnum() { + public val Success: WidgetEnumEntry by entry("success") + public val Info: WidgetEnumEntry by entry("info") + public val Warning: WidgetEnumEntry by entry("warning") + public val Danger: WidgetEnumEntry by entry("danger") + public val Default: WidgetEnumEntry by entry("") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/ButtonStyle.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/ButtonStyle.kt new file mode 100644 index 0000000..1447edc --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/ButtonStyle.kt @@ -0,0 +1,14 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object ButtonStyle : WidgetEnum() { + public val Primary: WidgetEnumEntry by entry("primary") + public val Success: WidgetEnumEntry by entry("success") + public val Info: WidgetEnumEntry by entry("info") + public val Warning: WidgetEnumEntry by entry("warning") + public val Danger: WidgetEnumEntry by entry("danger") + public val Default: WidgetEnumEntry by entry("") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/GridAutoFlow.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/GridAutoFlow.kt new file mode 100644 index 0000000..6c8a2b6 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/GridAutoFlow.kt @@ -0,0 +1,15 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object GridAutoFlow : WidgetEnum() { + public val Column: WidgetEnumEntry by entry("column") + public val Row: WidgetEnumEntry by entry("row") + public val RowDense: WidgetEnumEntry by entry("row dense") + public val ColumnDense: WidgetEnumEntry by entry("column dense") + public val Inherit: WidgetEnumEntry by entry("inherit") + public val Initial: WidgetEnumEntry by entry("initial") + public val Unset: WidgetEnumEntry by entry("unset") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/JustifyContent.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/JustifyContent.kt new file mode 100644 index 0000000..14a2a41 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/JustifyContent.kt @@ -0,0 +1,16 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object JustifyContent : WidgetEnum() { + public val FlexStart: WidgetEnumEntry by entry("flex-start") + public val FlexEnd: WidgetEnumEntry by entry("flex-end") + public val Center: WidgetEnumEntry by entry("center") + public val SpaceBetween: WidgetEnumEntry by entry("space-between") + public val SpaceAround: WidgetEnumEntry by entry("space-around") + public val Inherit: WidgetEnumEntry by entry("inherit") + public val Initial: WidgetEnumEntry by entry("initial") + public val Unset: WidgetEnumEntry by entry("unset") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/JustifyItems.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/JustifyItems.kt new file mode 100644 index 0000000..dd96745 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/JustifyItems.kt @@ -0,0 +1,14 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object JustifyItems : WidgetEnum() { + public val FlexStart: WidgetEnumEntry by entry("flex-start") + public val FlexEnd: WidgetEnumEntry by entry("flex-end") + public val Center: WidgetEnumEntry by entry("center") + public val Inherit: WidgetEnumEntry by entry("inherit") + public val Initial: WidgetEnumEntry by entry("initial") + public val Unset: WidgetEnumEntry by entry("unset") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/ObjectFit.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/ObjectFit.kt new file mode 100644 index 0000000..ea3b3c2 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/ObjectFit.kt @@ -0,0 +1,13 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object ObjectFit : WidgetEnum() { + public val Contain: WidgetEnumEntry by entry("contain") + public val Cover: WidgetEnumEntry by entry("cover") + public val Fill: WidgetEnumEntry by entry("fill") + public val ScaleDown: WidgetEnumEntry by entry("scale-down") + public val None: WidgetEnumEntry by entry("none") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/Orientation.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/Orientation.kt new file mode 100644 index 0000000..7b37cf1 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/Orientation.kt @@ -0,0 +1,10 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object Orientation : WidgetEnum() { + public val Horizontal: WidgetEnumEntry by entry("horizontal") + public val Vertical: WidgetEnumEntry by entry("vertical") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/TagStyle.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/TagStyle.kt new file mode 100644 index 0000000..3560dbc --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/TagStyle.kt @@ -0,0 +1,14 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object TagStyle : WidgetEnum() { + public val Primary: WidgetEnumEntry by entry("primary") + public val Success: WidgetEnumEntry by entry("success") + public val Info: WidgetEnumEntry by entry("info") + public val Warning: WidgetEnumEntry by entry("warning") + public val Danger: WidgetEnumEntry by entry("danger") + public val Default: WidgetEnumEntry by entry("") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/Visibility.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/Visibility.kt new file mode 100644 index 0000000..1850848 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/enums/Visibility.kt @@ -0,0 +1,13 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.enums + +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnum +import org.jetbrains.kotlinx.jupyter.widget.model.types.enums.WidgetEnumEntry + +public object Visibility : WidgetEnum() { + public val Visible: WidgetEnumEntry by entry("visible") + public val Hidden: WidgetEnumEntry by entry("hidden") + public val Inherit: WidgetEnumEntry by entry("inherit") + public val Initial: WidgetEnumEntry by entry("initial") + public val Unset: WidgetEnumEntry by entry("unset") +} diff --git a/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/registry/DefaultWidgetFactories.kt b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/registry/DefaultWidgetFactories.kt new file mode 100644 index 0000000..ebf5e86 --- /dev/null +++ b/integrations/widgets/widgets-api/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/registry/DefaultWidgetFactories.kt @@ -0,0 +1,143 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.library.registry + +import org.jetbrains.kotlinx.jupyter.widget.library.AccordionWidget +import org.jetbrains.kotlinx.jupyter.widget.library.AudioWidget +import org.jetbrains.kotlinx.jupyter.widget.library.BoundedFloatTextWidget +import org.jetbrains.kotlinx.jupyter.widget.library.BoundedIntTextWidget +import org.jetbrains.kotlinx.jupyter.widget.library.BoxWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ButtonStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ButtonWidget +import org.jetbrains.kotlinx.jupyter.widget.library.CheckboxStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.CheckboxWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ColorPickerWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ColorsInputWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ComboboxWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ControllerAxisWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ControllerButtonWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ControllerWidget +import org.jetbrains.kotlinx.jupyter.widget.library.DatePickerWidget +import org.jetbrains.kotlinx.jupyter.widget.library.DatetimeWidget +import org.jetbrains.kotlinx.jupyter.widget.library.DescriptionStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.DirectionalLinkWidget +import org.jetbrains.kotlinx.jupyter.widget.library.DomWidget +import org.jetbrains.kotlinx.jupyter.widget.library.DropdownWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FileUploadWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FloatLogSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FloatProgressWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FloatRangeSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FloatSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FloatTextWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FloatsInputWidget +import org.jetbrains.kotlinx.jupyter.widget.library.GridBoxWidget +import org.jetbrains.kotlinx.jupyter.widget.library.HBoxWidget +import org.jetbrains.kotlinx.jupyter.widget.library.HtmlMathStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.HtmlMathWidget +import org.jetbrains.kotlinx.jupyter.widget.library.HtmlStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.HtmlWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ImageWidget +import org.jetbrains.kotlinx.jupyter.widget.library.IntProgressWidget +import org.jetbrains.kotlinx.jupyter.widget.library.IntRangeSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.IntSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.IntTextWidget +import org.jetbrains.kotlinx.jupyter.widget.library.IntsInputWidget +import org.jetbrains.kotlinx.jupyter.widget.library.LabelStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.LabelWidget +import org.jetbrains.kotlinx.jupyter.widget.library.LayoutWidget +import org.jetbrains.kotlinx.jupyter.widget.library.LinkWidget +import org.jetbrains.kotlinx.jupyter.widget.library.NaiveDatetimeWidget +import org.jetbrains.kotlinx.jupyter.widget.library.PasswordWidget +import org.jetbrains.kotlinx.jupyter.widget.library.PlayWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ProgressStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.RadioButtonsWidget +import org.jetbrains.kotlinx.jupyter.widget.library.SelectMultipleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.SelectWidget +import org.jetbrains.kotlinx.jupyter.widget.library.SelectionRangeSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.SelectionSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.SliderStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.StackWidget +import org.jetbrains.kotlinx.jupyter.widget.library.TabWidget +import org.jetbrains.kotlinx.jupyter.widget.library.TagsInputWidget +import org.jetbrains.kotlinx.jupyter.widget.library.TextStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.TextWidget +import org.jetbrains.kotlinx.jupyter.widget.library.TextareaWidget +import org.jetbrains.kotlinx.jupyter.widget.library.TimeWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ToggleButtonStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ToggleButtonWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ToggleButtonsStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ToggleButtonsWidget +import org.jetbrains.kotlinx.jupyter.widget.library.VBoxWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ValidWidget +import org.jetbrains.kotlinx.jupyter.widget.library.VideoWidget +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetFactory + +internal val defaultWidgetFactories = listOf>( + AccordionWidget.Factory, + AudioWidget.Factory, + BoundedFloatTextWidget.Factory, + BoundedIntTextWidget.Factory, + BoxWidget.Factory, + ButtonStyleWidget.Factory, + ButtonWidget.Factory, + CheckboxStyleWidget.Factory, + CheckboxWidget.Factory, + ColorPickerWidget.Factory, + ColorsInputWidget.Factory, + ComboboxWidget.Factory, + ControllerAxisWidget.Factory, + ControllerButtonWidget.Factory, + ControllerWidget.Factory, + DatePickerWidget.Factory, + DatetimeWidget.Factory, + DescriptionStyleWidget.Factory, + DirectionalLinkWidget.Factory, + DomWidget.Factory, + DropdownWidget.Factory, + FileUploadWidget.Factory, + FloatLogSliderWidget.Factory, + FloatProgressWidget.Factory, + FloatRangeSliderWidget.Factory, + FloatSliderWidget.Factory, + FloatTextWidget.Factory, + FloatsInputWidget.Factory, + GridBoxWidget.Factory, + HBoxWidget.Factory, + HtmlMathStyleWidget.Factory, + HtmlMathWidget.Factory, + HtmlStyleWidget.Factory, + HtmlWidget.Factory, + ImageWidget.Factory, + IntProgressWidget.Factory, + IntRangeSliderWidget.Factory, + IntSliderWidget.Factory, + IntTextWidget.Factory, + IntsInputWidget.Factory, + LabelStyleWidget.Factory, + LabelWidget.Factory, + LayoutWidget.Factory, + LinkWidget.Factory, + NaiveDatetimeWidget.Factory, + PasswordWidget.Factory, + PlayWidget.Factory, + ProgressStyleWidget.Factory, + RadioButtonsWidget.Factory, + SelectMultipleWidget.Factory, + SelectWidget.Factory, + SelectionRangeSliderWidget.Factory, + SelectionSliderWidget.Factory, + SliderStyleWidget.Factory, + StackWidget.Factory, + TabWidget.Factory, + TagsInputWidget.Factory, + TextStyleWidget.Factory, + TextWidget.Factory, + TextareaWidget.Factory, + TimeWidget.Factory, + ToggleButtonStyleWidget.Factory, + ToggleButtonWidget.Factory, + ToggleButtonsStyleWidget.Factory, + ToggleButtonsWidget.Factory, + VBoxWidget.Factory, + ValidWidget.Factory, + VideoWidget.Factory, +) diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/WidgetManager.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/WidgetManager.kt new file mode 100644 index 0000000..29259f7 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/WidgetManager.kt @@ -0,0 +1,75 @@ +package org.jetbrains.kotlinx.jupyter.widget + +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import org.jetbrains.kotlinx.jupyter.api.DisplayResult +import org.jetbrains.kotlinx.jupyter.protocol.api.RawMessage +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetFactoryRegistry +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel + +/** + * Manages the lifecycle and communication of Jupyter widgets. + * Handles widget registration, state synchronization, and custom message passing. + */ +public interface WidgetManager { + /** + * Registry of available widget factories. + */ + public val factoryRegistry: WidgetFactoryRegistry + + /** + * If true, property updates received from the frontend are echoed back to the frontend. + * This is sometimes necessary to ensure the frontend state remains in sync with the backend, + * especially when the backend might override the requested change. + * + * In Jupyter Widgets 8, this is used for multiple frontend synchronization. + * In Kotlin Notebook, this is disabled by default to save bandwidth as it's not the primary use case. + */ + public var echoUpdateEnabled: Boolean + + /** + * The original Jupyter message that triggered the current execution. + * Used as a parent for outgoing widget messages. + */ + public val contextMessage: RawMessage? + + /** + * Retrieves a [WidgetModel] by its unique identifier. + */ + public fun getWidget(modelId: String): WidgetModel? + + /** + * Returns the unique identifier for a given [WidgetModel], or null if it's not registered. + */ + public fun getWidgetId(widget: WidgetModel): String? + + /** + * Registers a newly created widget with this manager. + * This usually triggers a 'comm_open' message to the frontend. + */ + public fun registerWidget(widget: WidgetModel) + + /** + * Closes the widget, both locally and on the frontend. + * This triggers a 'comm_close' message. + */ + public fun closeWidget(widget: WidgetModel) + + /** + * Returns a [DisplayResult] that allows displaying the widget in the notebook. + */ + public fun renderWidget(widget: WidgetModel): DisplayResult + + /** + * Sends a custom message to the frontend counterpart of the given widget. + * + * Custom messages are typically used for widget-specific actions that don't fit + * the standard property-sync model (e.g., clearing the output in OutputWidget). + */ + public fun sendCustomMessage( + widget: WidgetModel, + content: JsonObject, + metadata: JsonElement? = null, + buffers: List = emptyList(), + ) +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/WidgetManagerImpl.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/WidgetManagerImpl.kt new file mode 100644 index 0000000..a7bdd02 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/WidgetManagerImpl.kt @@ -0,0 +1,277 @@ +package org.jetbrains.kotlinx.jupyter.widget + +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.decodeFromJsonElement +import kotlinx.serialization.json.encodeToJsonElement +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive +import kotlinx.serialization.json.put +import org.jetbrains.kotlinx.jupyter.api.DisplayResult +import org.jetbrains.kotlinx.jupyter.api.MimeTypedResultEx +import org.jetbrains.kotlinx.jupyter.api.MimeTypes +import org.jetbrains.kotlinx.jupyter.api.libraries.Comm +import org.jetbrains.kotlinx.jupyter.api.libraries.CommManager +import org.jetbrains.kotlinx.jupyter.protocol.api.RawMessage +import org.jetbrains.kotlinx.jupyter.widget.model.DEFAULT_MAJOR_VERSION +import org.jetbrains.kotlinx.jupyter.widget.model.DEFAULT_MINOR_VERSION +import org.jetbrains.kotlinx.jupyter.widget.model.DEFAULT_PATCH_VERSION +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetFactoryRegistry +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.versionConstraintRegex +import org.jetbrains.kotlinx.jupyter.widget.protocol.CustomMessage +import org.jetbrains.kotlinx.jupyter.widget.protocol.Patch +import org.jetbrains.kotlinx.jupyter.widget.protocol.RequestStateMessage +import org.jetbrains.kotlinx.jupyter.widget.protocol.RequestStatesMessage +import org.jetbrains.kotlinx.jupyter.widget.protocol.UpdateStatesMessage +import org.jetbrains.kotlinx.jupyter.widget.protocol.WidgetEchoUpdateMessage +import org.jetbrains.kotlinx.jupyter.widget.protocol.WidgetMessage +import org.jetbrains.kotlinx.jupyter.widget.protocol.WidgetOpenMessage +import org.jetbrains.kotlinx.jupyter.widget.protocol.WidgetStateMessage +import org.jetbrains.kotlinx.jupyter.widget.protocol.WidgetUpdateMessage +import org.jetbrains.kotlinx.jupyter.widget.protocol.getWireMessage +import org.jetbrains.kotlinx.jupyter.widget.protocol.toPatch + +private val widgetOpenMetadataJson = + buildJsonObject { + put("version", "${DEFAULT_MAJOR_VERSION}.${DEFAULT_MINOR_VERSION}.${DEFAULT_PATCH_VERSION}") + } + +/** + * Implementation of [WidgetManager] that interfaces with the [CommManager] + * to provide real-time synchronization between Kotlin and Jupyter frontend. + */ +public class WidgetManagerImpl( + private val commManager: CommManager, + private val classLoaderProvider: () -> ClassLoader, +) : WidgetManager { + private val widgetTarget = "jupyter.widget" + private val widgetControlTarget = "jupyter.widget.control" + private val widgets = mutableMapOf() + private val widgetIdByWidget = mutableMapOf() + private val commByWidget = mutableMapOf() + + override val factoryRegistry: WidgetFactoryRegistry = WidgetFactoryRegistry() + + override val contextMessage: RawMessage? get() = commManager.contextMessage + + /** + * Echo update can be enabled via the `JUPYTER_WIDGETS_ECHO` environment variable. + */ + override var echoUpdateEnabled: Boolean = + System.getenv("JUPYTER_WIDGETS_ECHO")?.let { it.lowercase() == "true" } ?: false + + init { + commManager.registerCommTarget(widgetControlTarget) { comm, _, _, _ -> + comm.onMessage { msg, _, _ -> + when (Json.decodeFromJsonElement(msg)) { + is RequestStatesMessage -> { + val fullStates = + widgets.mapValues { (id, widget) -> + widget.getFullState() + } + + val wireMessage = getWireMessage(fullStates) + val message = UpdateStatesMessage(wireMessage.state, wireMessage.bufferPaths) + + val data = Json.encodeToJsonElement(message).jsonObject + comm.send(data, null, wireMessage.buffers) + } + + else -> {} + } + } + } + + commManager.registerCommTarget(widgetTarget) { comm, data, _, buffers -> + val openMessage = Json.decodeFromJsonElement(data) + val modelName = openMessage.state["_model_name"]?.jsonPrimitive?.content!! + val widgetFactory = factoryRegistry.loadWidgetFactory(modelName, classLoaderProvider()) + + val widget = widgetFactory.create(this, fromFrontend = true) + val patch = openMessage.toPatch(buffers) + widget.applyFrontendPatch(patch) + + initializeWidget(comm, widget) + } + } + + override fun getWidget(modelId: String): WidgetModel? = widgets[modelId] + + override fun getWidgetId(widget: WidgetModel): String? = widgetIdByWidget[widget] + + override fun registerWidget(widget: WidgetModel) { + if (getWidgetId(widget) != null) return + + val fullState = widget.getFullState() + val wireMessage = getWireMessage(fullState) + + val comm = + commManager.openComm( + widgetTarget, + Json + .encodeToJsonElement( + WidgetOpenMessage( + wireMessage.state, + wireMessage.bufferPaths, + ), + ).jsonObject, + widgetOpenMetadataJson, + wireMessage.buffers, + ) + + initializeWidget(comm, widget) + } + + override fun closeWidget(widget: WidgetModel) { + val comm = commByWidget[widget] ?: return + comm.close() + } + + override fun renderWidget(widget: WidgetModel): DisplayResult = + MimeTypedResultEx( + buildJsonObject { + val modelId = getWidgetId(widget) ?: error("Widget is not registered") + var versionMajor = DEFAULT_MAJOR_VERSION + var versionMinor = DEFAULT_MINOR_VERSION + var modelName: String? = null + if (widget is DefaultWidgetModel) { + modelName = widget.modelName + val version = widget.viewModuleVersion + val matchResult = versionConstraintRegex.find(version) + if (matchResult != null) { + versionMajor = matchResult.groupValues[1].toInt() + versionMinor = matchResult.groupValues[2].toInt() + } + } + if (modelName != null) { + put(MimeTypes.HTML, "$modelName(id=$modelId)") + } + put( + "application/vnd.jupyter.widget-view+json", + buildJsonObject { + put("version_major", versionMajor) + put("version_minor", versionMinor) + put("model_id", modelId) + }, + ) + }, + null, + ) + + override fun sendCustomMessage( + widget: WidgetModel, + content: JsonObject, + metadata: JsonElement?, + buffers: List, + ) { + val comm = commByWidget[widget] ?: error("Widget is not registered") + val message = CustomMessage(content) + val data = Json.encodeToJsonElement(message).jsonObject + comm.send(data, metadata, buffers) + } + + /** + * Initializes a widget and sets up bi-directional synchronization via Comms. + * + * @param comm The [Comm] instance for this widget. + * @param widget The [WidgetModel] to initialize. + */ + private fun initializeWidget( + comm: Comm, + widget: WidgetModel, + ) { + val modelId = comm.id + widgetIdByWidget[widget] = modelId + widgets[modelId] = widget + commByWidget[widget] = comm + + // Reflect kernel-side changes on the frontend + widget.addChangeListener { patch, fromFrontend -> + handleWidgetUpdate(comm, widget, patch, fromFrontend) + } + + // Reflect frontend-side changes on kernel + comm.onMessage { msg, metadata, buffers -> + when (val message = Json.decodeFromJsonElement(msg)) { + is WidgetStateMessage -> { + widget.applyFrontendPatch(message.toPatch(buffers)) + } + + is RequestStateMessage -> { + val fullState = widget.getFullState() + val wireMessage = getWireMessage(fullState) + val data = + Json + .encodeToJsonElement( + WidgetUpdateMessage( + wireMessage.state, + wireMessage.bufferPaths, + ), + ).jsonObject + comm.send(data, null, wireMessage.buffers) + } + + is CustomMessage -> { + widget.handleCustomMessage( + message.content, + metadata, + buffers, + ) + } + + else -> {} + } + } + + comm.onClose { _, _ -> + widgets.remove(modelId) + widgetIdByWidget.remove(widget) + commByWidget.remove(widget) + } + } + + private fun handleWidgetUpdate( + comm: Comm, + widget: WidgetModel, + patch: Patch, + fromFrontend: Boolean, + ) { + val updatePatch = + if (fromFrontend) { + if (!echoUpdateEnabled) return + val echoPatch = + patch.filterKeys { + widget.getProperty(it)?.echoUpdate != false + } + if (echoPatch.isEmpty()) return + echoPatch + } else { + patch + } + + val wireMessage = getWireMessage(updatePatch) + val updateMessage = + if (fromFrontend) { + WidgetEchoUpdateMessage( + wireMessage.state, + wireMessage.bufferPaths, + ) + } else { + WidgetUpdateMessage( + wireMessage.state, + wireMessage.bufferPaths, + ) + } + + val updateData = + Json + .encodeToJsonElement(updateMessage) + .jsonObject + + comm.send(updateData, null, wireMessage.buffers) + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ExtraWidgetFactories.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ExtraWidgetFactories.kt new file mode 100644 index 0000000..82e98cb --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/ExtraWidgetFactories.kt @@ -0,0 +1,9 @@ +package org.jetbrains.kotlinx.jupyter.widget.library + +/** + * List of manually implemented widget factories that are not covered by the automatic generator. + */ +internal val extraWidgetFactories = + listOf( + OutputWidget.Factory, + ) diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/Links.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/Links.kt new file mode 100644 index 0000000..07c7209 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/Links.kt @@ -0,0 +1,44 @@ +package org.jetbrains.kotlinx.jupyter.widget.library + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.getProperty +import kotlin.reflect.KProperty1 + +/** + * Creates a [LinkWidget] to link specified properties of two widgets. + * Created link is bidirectional. + */ +public fun WidgetManager.linkProperties( + sourceWidget: SourceT, + sourceProperty: KProperty1, + targetWidget: TargetT, + targetProperty: KProperty1, +): LinkWidget { + val sourcePropertyName = sourceWidget.getProperty(sourceProperty)?.name ?: error("Source property not found") + val targetPropertyName = targetWidget.getProperty(targetProperty)?.name ?: error("Target property not found") + + return link { + source = sourceWidget to sourcePropertyName + target = targetWidget to targetPropertyName + } +} + +/** + * Creates a [LinkWidget] to link specified properties of two widgets. + * Created link is one-way from source to target. + */ +public fun WidgetManager.linkPropertiesOneWay( + sourceWidget: SourceT, + sourceProperty: KProperty1, + targetWidget: TargetT, + targetProperty: KProperty1, +): DirectionalLinkWidget { + val sourcePropertyName = sourceWidget.getProperty(sourceProperty)?.name ?: error("Source property not found") + val targetPropertyName = targetWidget.getProperty(targetProperty)?.name ?: error("Target property not found") + + return directionalLink { + source = sourceWidget to sourcePropertyName + target = targetWidget to targetPropertyName + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/OutputWidget.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/OutputWidget.kt new file mode 100644 index 0000000..fdb7842 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/OutputWidget.kt @@ -0,0 +1,63 @@ +package org.jetbrains.kotlinx.jupyter.widget.library + +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.buildJsonObject +import org.jetbrains.kotlinx.jupyter.protocol.api.id +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetFactory +import org.jetbrains.kotlinx.jupyter.widget.model.createAndRegisterWidget + +public fun WidgetManager.output(setup: OutputWidget.() -> Unit = {}): OutputWidget = + createAndRegisterWidget(OutputWidget.Factory).apply(setup) + +/** + * A widget that can capture and display standard output, error, and rich results. + * Extends the generated [OutputWidgetBase] to add helper methods. + */ +public class OutputWidget internal constructor( + widgetManager: WidgetManager, + fromFrontend: Boolean, +) : OutputWidgetBase(widgetManager, fromFrontend) { + private var scopeCounter = 0 + + /** + * Factory for creating [OutputWidget] instances. + */ + internal object Factory : DefaultWidgetFactory(outputSpec, ::OutputWidget) + + /** + * Clears the current output of the widget. + * @param wait If true, wait to clear the output until new output is available. + */ + public fun clearOutput(wait: Boolean = false) { + sendCustomMessage( + buildJsonObject { + put("method", JsonPrimitive("clear_output")) + put("wait", JsonPrimitive(wait)) + }, + ) + } + + /** + * Executes the [action] and captures any output produced by it into this widget. + * This works by temporarily setting [msgId] to the current context message's ID. + * + * IMPORTANT: This only works for output produced via standard Jupyter messaging + * (e.g., `println`, `display`). + */ + public fun withScope(action: () -> Unit) { + scopeCounter++ + // Use the ID of the message that triggered the current execution + val parentId = widgetManager.contextMessage?.id + if (parentId != null) msgId = parentId + try { + action() + } finally { + scopeCounter-- + // Reset msgId only when the outermost scope finishes + if (scopeCounter == 0) { + msgId = "" + } + } + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/MultipleSelectionWidgetBase.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/MultipleSelectionWidgetBase.kt new file mode 100644 index 0000000..bae0412 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/MultipleSelectionWidgetBase.kt @@ -0,0 +1,47 @@ +package org.jetbrains.kotlinx.jupyter.widget.library.options + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType + +/** + * Base class for selection widgets with multiple selection. + */ +public abstract class MultipleSelectionWidgetBase( + spec: WidgetSpec, + widgetManager: WidgetManager, +) : OptionWidgetBase, List>(spec, widgetManager) { + /** + * Selected indices. + * Maps to `index` on the frontend. + */ + public override var index: List by prop("index", ArrayType(IntType), emptyList()) + + /** + * The labels of the selected options. + */ + public var labels: List + get() = index.mapNotNull { i -> optionsLabels.getOrNull(i) } + set(v) { + index = v.map { label -> optionsLabels.indexOf(label) } + } + + public override var value: List + get() = + index.map { i -> + optionsValues?.getOrNull(i) ?: optionsLabels.getOrNull(i) + } + set(v) { + index = findIndexByValue(v) + } + + override fun findIndexByValue(v: List): List { + val searchList = optionsValues ?: optionsLabels + return v.mapNotNull { item -> + searchList.indexOf(item).takeIf { it != -1 } + } + } + + override fun labelToValue(label: String): Any? = label +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/OptionWidgetBase.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/OptionWidgetBase.kt new file mode 100644 index 0000000..09c90fe --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/OptionWidgetBase.kt @@ -0,0 +1,87 @@ +package org.jetbrains.kotlinx.jupyter.widget.library.options + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.DefaultWidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType + +/** + * Base class for option-based widgets (like Dropdowns, Select, etc.). + * + * @param ValueT The type of a single option's value. + * @param ValueSelectionT The type representing the current selection (could be single value, list, pair, etc.). + * @param IndexSelectionT The type representing the frontend index selection (could be Int, List, IntRange, etc.). + */ +public abstract class OptionWidgetBase( + spec: WidgetSpec, + widgetManager: WidgetManager, +) : DefaultWidgetModel(spec, widgetManager) { + /** + * The labels for the options displayed in the UI. + * Maps to `_options_labels` on the frontend. + */ + public var optionsLabels: List by prop( + "_options_labels", + ArrayType( + StringType, + ), + emptyList(), + ) + + /** + * Internal storage for option values. + * Frontend only knows about labels and indices; values are kept on the backend. + */ + protected var optionsValues: List? = null + + /** + * Selected index(es). This is what's actually synced with the frontend's `index` property. + */ + public abstract var index: IndexSelectionT + + /** + * The options to choose from as a list of label-to-value pairs. + * Setting this updates [optionsLabels] and internal [optionsValues]. + * + * IMPORTANT: When options change, the implementation tries to preserve the current [value] + * by looking it up in the new options list. + */ + public var options: List> + get() = optionsLabels.zip(optionsValues ?: optionsLabels.map(::labelToValue)) + set(value) { + val currentValue = this.value + optionsLabels = value.map { it.first } + optionsValues = value.map { it.second } + // Try to maintain selection if the current value exists in the new options + index = findIndexByValue(currentValue) + } + + /** + * Convenience property to set options when labels and values are identical. + */ + public var simpleOptions: List + get() = optionsLabels + set(value) { + val currentValue = this.value + optionsLabels = value + optionsValues = value.map(::labelToValue) + index = findIndexByValue(currentValue) + } + + /** + * The current selection represented as a value (or values). + * This is a high-level abstraction over the [index] property. + */ + public abstract var value: ValueSelectionT + + /** + * Finds the index corresponding to the given value selection. + */ + protected abstract fun findIndexByValue(v: ValueSelectionT): IndexSelectionT + + /** + * Provides a default value for a label when [optionsValues] is not explicitly set. + */ + protected abstract fun labelToValue(label: String): ValueT +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/SelectionRangeWidgetBase.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/SelectionRangeWidgetBase.kt new file mode 100644 index 0000000..b3e8209 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/SelectionRangeWidgetBase.kt @@ -0,0 +1,65 @@ +package org.jetbrains.kotlinx.jupyter.widget.library.options + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.ranges.IntRangeType + +/** + * Base class for range-based selection widgets. + */ +public abstract class SelectionRangeWidgetBase( + spec: WidgetSpec, + widgetManager: WidgetManager, +) : OptionWidgetBase?, IntRange?>(spec, widgetManager) { + /** + * Selected range of indices. + * Maps to `index` on the frontend. + */ + public override var index: IntRange? by prop("index", NullableType(IntRangeType), 0..0) + + /** + * The labels of the selected range. + */ + public var labels: Pair? + get() = + index?.let { range -> + val startLabel = optionsLabels.getOrNull(range.first) ?: "" + val endLabel = optionsLabels.getOrNull(range.last) ?: "" + startLabel to endLabel + } + set(v) { + if (v == null) { + index = null + return + } + val start = optionsLabels.indexOf(v.first) + val end = optionsLabels.indexOf(v.second) + if (start != -1 && end != -1) { + index = start..end + } else { + index = null + } + } + + public override var value: Pair? + get() = + index?.let { range -> + val start = optionsValues?.getOrNull(range.first) ?: optionsLabels.getOrNull(range.first) + val end = optionsValues?.getOrNull(range.last) ?: optionsLabels.getOrNull(range.last) + start to end + } + set(v) { + index = findIndexByValue(v) + } + + override fun findIndexByValue(v: Pair?): IntRange? { + if (v == null) return null + val searchList = optionsValues ?: optionsLabels + val start = searchList.indexOf(v.first) + val end = searchList.indexOf(v.second) + return if (start != -1 && end != -1) start..end else null + } + + override fun labelToValue(label: String): Any? = label +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/SingleNullableSelectionWidgetBase.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/SingleNullableSelectionWidgetBase.kt new file mode 100644 index 0000000..9c0ba75 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/SingleNullableSelectionWidgetBase.kt @@ -0,0 +1,45 @@ +package org.jetbrains.kotlinx.jupyter.widget.library.options + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec + +/** + * Base class for selection widgets with possibly nullable single selection. + */ +public abstract class SingleNullableSelectionWidgetBase( + spec: WidgetSpec, + widgetManager: WidgetManager, +) : OptionWidgetBase(spec, widgetManager) { + /** + * Selected index. + * Maps to `index` on the frontend. + */ + public override var index: Int? by nullableIntProp("index", null) + + /** + * The label of the selected option. + */ + public var label: String? + get() = index?.let { i -> optionsLabels.getOrNull(i) } + set(v) { + index = if (v == null) null else optionsLabels.indexOf(v).takeIf { it != -1 } + } + + public override var value: Any? + get() = + index?.let { i -> + optionsValues?.getOrNull(i) ?: optionsLabels.getOrNull(i) + } + set(v) { + index = findIndexByValue(v) + } + + override fun findIndexByValue(v: Any?): Int? { + if (v == null) return null + val searchList = optionsValues ?: optionsLabels + val i = searchList.indexOf(v) + return if (i != -1) i else null + } + + override fun labelToValue(label: String): Any? = label +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/SingleSelectionWidgetBase.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/SingleSelectionWidgetBase.kt new file mode 100644 index 0000000..66a8bf4 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/library/options/SingleSelectionWidgetBase.kt @@ -0,0 +1,44 @@ +package org.jetbrains.kotlinx.jupyter.widget.library.options + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetSpec + +/** + * Base class for selection widgets with non-nullable single selection. + */ +public abstract class SingleSelectionWidgetBase( + spec: WidgetSpec, + widgetManager: WidgetManager, +) : OptionWidgetBase(spec, widgetManager) { + /** + * Selected index. + * Maps to `index` on the frontend. + */ + public override var index: Int by intProp("index", 0) + + /** + * The label of the selected option. + */ + public var label: String + get() = optionsLabels.getOrNull(index) ?: "" + set(v) { + val i = optionsLabels.indexOf(v) + if (i != -1) index = i + } + + public override var value: Any? + get() { + return optionsValues?.getOrNull(index) ?: optionsLabels.getOrNull(index) + } + set(v) { + index = findIndexByValue(v) + } + + override fun findIndexByValue(v: Any?): Int { + val searchList = optionsValues ?: optionsLabels + val i = searchList.indexOf(v) + return if (i != -1) i else index + } + + override fun labelToValue(label: String): Any = label +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/CustomMessageListener.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/CustomMessageListener.kt new file mode 100644 index 0000000..4ec16a1 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/CustomMessageListener.kt @@ -0,0 +1,10 @@ +package org.jetbrains.kotlinx.jupyter.widget.model + +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject + +public typealias CustomMessageListener = ( + content: JsonObject, + metadata: JsonElement?, + buffers: List, +) -> Unit diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/ModelCreation.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/ModelCreation.kt new file mode 100644 index 0000000..f271ebb --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/ModelCreation.kt @@ -0,0 +1,87 @@ +package org.jetbrains.kotlinx.jupyter.widget.model + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager + +/** + * Creates a widget instance and registers it with the [WidgetManager]. + */ +public fun WidgetManager.createAndRegisterWidget(widgetFactory: (widgetManager: WidgetManager) -> M): M = + widgetFactory(this).also { widget -> registerWidget(widget) } + +/** + * Creates a widget instance using the provided [factory] and registers it. + */ +public fun WidgetManager.createAndRegisterWidget(factory: WidgetFactory): M = createAndRegisterWidget(factory::create) + +/** + * Factory for creating [WidgetModel] instances. + */ +public interface WidgetFactory { + /** + * The specification of the widget this factory creates. + */ + public val spec: WidgetSpec + + /** + * Creates a new widget instance. + * @param fromFrontend If true, indicates the widget is being reconstructed from frontend state. + */ + public fun create( + widgetManager: WidgetManager, + fromFrontend: Boolean = false, + ): M +} + +/** + * Default implementation of [WidgetFactory] that uses a provided constructor function. + */ +public abstract class DefaultWidgetFactory( + override val spec: WidgetSpec, + private val factory: (widgetManager: WidgetManager, fromFrontend: Boolean) -> M, +) : WidgetFactory { + /** + * Creates a new widget instance using the provided constructor. + */ + override fun create( + widgetManager: WidgetManager, + fromFrontend: Boolean, + ): M = factory(widgetManager, fromFrontend) +} + +/** + * A [WidgetModel] that automatically includes standard [WidgetSpec] properties as synced properties. + */ +public open class DefaultWidgetModel( + spec: WidgetSpec, + widgetManager: WidgetManager, +) : WidgetModel(widgetManager) { + /** + * The name of the frontend model class. + */ + public val modelName: String by stringProp("_model_name", spec.modelName) + + /** + * The NPM module containing the model. + */ + public val modelModule: String by stringProp("_model_module", spec.modelModule) + + /** + * Semver requirement for the model module. + */ + public val modelModuleVersion: String by stringProp("_model_module_version", spec.modelModuleVersion) + + /** + * The name of the frontend view class. + */ + public val viewName: String? by nullableStringProp("_view_name", spec.viewName) + + /** + * The NPM module containing the view. + */ + public val viewModule: String by stringProp("_view_module", spec.viewModule) + + /** + * Semver requirement for the view module. + */ + public val viewModuleVersion: String by stringProp("_view_module_version", spec.viewModuleVersion) +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/WidgetFactoryRegistry.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/WidgetFactoryRegistry.kt new file mode 100644 index 0000000..1b0c762 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/WidgetFactoryRegistry.kt @@ -0,0 +1,45 @@ +package org.jetbrains.kotlinx.jupyter.widget.model + +import org.jetbrains.kotlinx.jupyter.widget.library.extraWidgetFactories +import org.jetbrains.kotlinx.jupyter.widget.library.registry.defaultWidgetFactories +import java.util.ServiceLoader +import java.util.concurrent.ConcurrentHashMap + +/** + * Keeps track of available [WidgetFactory] instances. + * Factories are used to reconstruct widgets from the state received from the frontend. + */ +public class WidgetFactoryRegistry { + private val factoryCache = ConcurrentHashMap>() + + init { + // Load factories provided by the library and extra ones added via registration + for (factory in extraWidgetFactories) { + registerWidgetFactory(factory) + } + for (factory in defaultWidgetFactories) { + registerWidgetFactory(factory) + } + } + + /** + * Finds a factory for the given [modelName]. + * If not found in cache, tries to load it using [ServiceLoader]. + */ + internal fun loadWidgetFactory( + modelName: String, + classLoader: ClassLoader, + ): WidgetFactory<*> = + factoryCache.getOrPut(modelName) { + ServiceLoader + .load(WidgetFactory::class.java, classLoader) + .firstOrNull { it.spec.modelName == modelName } ?: error("No factory for model $modelName") + } + + /** + * Registers a new widget factory. + */ + public fun registerWidgetFactory(factory: WidgetFactory<*>) { + factoryCache[factory.spec.modelName] = factory + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/WidgetModel.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/WidgetModel.kt new file mode 100644 index 0000000..4a56b82 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/WidgetModel.kt @@ -0,0 +1,355 @@ +package org.jetbrains.kotlinx.jupyter.widget.model + +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.types.WidgetModelPropertyType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.datetime.DateType +import org.jetbrains.kotlinx.jupyter.widget.model.types.datetime.DatetimeType +import org.jetbrains.kotlinx.jupyter.widget.model.types.datetime.TimeType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BooleanType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.BytesType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.FloatType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType +import org.jetbrains.kotlinx.jupyter.widget.protocol.Patch +import java.time.Instant +import java.time.LocalDate +import java.time.LocalTime +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +/** + * Base class for all widget models. + * Manages properties, state synchronization, and messaging. + */ +public abstract class WidgetModel( + protected val widgetManager: WidgetManager, +) { + private val properties = mutableMapOf>() + private val changeListeners = mutableListOf<(Patch, Boolean) -> Unit>() + private val customMessageListeners = mutableListOf() + + /** + * Retrieves a property by its Jupyter protocol name (e.g., `_dom_classes`). + */ + public fun getProperty(name: String): WidgetModelProperty<*>? = properties[name] + + /** + * Retrieves a property by the property delegate + */ + internal fun getPropertyByDelegate(delegate: Any?): WidgetModelProperty<*>? = (delegate as? WidgetKtPropertyDelegate<*>)?.property + + /** + * Returns the full serialized state of all properties. + */ + public fun getFullState(): Patch = properties.mapValues { (_, property) -> property.serializedValue } + + /** + * Sends a custom message to the frontend. + * @param content Message payload. + * @param metadata Optional message metadata. + * @param buffers Optional binary buffers. + */ + public fun sendCustomMessage( + content: JsonObject, + metadata: JsonElement? = null, + buffers: List = emptyList(), + ) { + widgetManager.sendCustomMessage(this, content, metadata, buffers) + } + + public fun addCustomMessageListener(listener: CustomMessageListener) { + customMessageListeners.add(listener) + } + + internal fun handleCustomMessage( + content: JsonObject, + metadata: JsonElement?, + buffers: List, + ) { + for (listener in customMessageListeners) { + listener(content, metadata, buffers) + } + } + + /** + * Applies a state update received from the frontend. + */ + public fun applyFrontendPatch(patch: Patch) { + applyPatchImpl(patch, fromFrontend = true) + } + + /** + * Applies a state update locally. + */ + public fun applyPatch(patch: Patch) { + applyPatchImpl(patch, fromFrontend = false) + } + + private fun applyPatchImpl( + patch: Patch, + fromFrontend: Boolean, + ) { + for ((key, value) in patch) { + val property = properties[key] ?: continue + property.applyPatch(value, fromFrontend) + } + } + + /** + * Adds a listener for state changes (both local and from frontend). + */ + public fun addChangeListener(listener: (Patch, fromFrontend: Boolean) -> Unit) { + changeListeners.add(listener) + } + + private fun addProperty(property: WidgetModelProperty<*>) { + properties[property.name] = property + property.addChangeListener { patch, fromFrontend -> + notifyChange(mapOf(property.name to patch), fromFrontend) + } + } + + private fun notifyChange( + patch: Patch, + fromFrontend: Boolean, + ) { + for (listener in changeListeners) { + listener(patch, fromFrontend) + } + } + + /** + * Creates a property delegate. + * @param echoUpdate If true, updates from frontend are echoed back. + * + * Note: While thread safety is not explicitly guaranteed, property updates + * from multiple threads should generally be safe as long as the underlying + * kernel messaging protocol is thread-safe. + */ + protected fun prop( + name: String, + type: WidgetModelPropertyType, + initialValue: T, + echoUpdate: Boolean = true, + ): ReadWriteProperty = WidgetKtPropertyDelegate(name, type, initialValue, echoUpdate) + + protected fun stringProp( + name: String, + initialValue: String = "", + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, StringType, initialValue, echoUpdate) + + protected fun nullableStringProp( + name: String, + initialValue: String? = null, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, NullableType(StringType), initialValue, echoUpdate) + + protected fun intProp( + name: String, + initialValue: Int = 0, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, IntType, initialValue, echoUpdate) + + protected fun nullableIntProp( + name: String, + initialValue: Int? = null, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, NullableType(IntType), initialValue, echoUpdate) + + protected fun doubleProp( + name: String, + initialValue: Double = 0.0, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, FloatType, initialValue, echoUpdate) + + protected fun nullableDoubleProp( + name: String, + initialValue: Double? = null, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, NullableType(FloatType), initialValue, echoUpdate) + + protected fun boolProp( + name: String, + initialValue: Boolean = false, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, BooleanType, initialValue, echoUpdate) + + protected fun nullableBoolProp( + name: String, + initialValue: Boolean? = null, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, NullableType(BooleanType), initialValue, echoUpdate) + + protected fun bytesProp( + name: String, + initialValue: ByteArray = byteArrayOf(), + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, BytesType, initialValue, echoUpdate) + + protected fun dateProp( + name: String, + initialValue: LocalDate, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, DateType, initialValue, echoUpdate) + + protected fun nullableDateProp( + name: String, + initialValue: LocalDate? = null, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, NullableType(DateType), initialValue, echoUpdate) + + protected fun dateTimeProp( + name: String, + initialValue: Instant, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, DatetimeType, initialValue, echoUpdate) + + protected fun nullableDateTimeProp( + name: String, + initialValue: Instant? = null, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, NullableType(DatetimeType), initialValue, echoUpdate) + + protected fun timeProp( + name: String, + initialValue: LocalTime, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, TimeType, initialValue, echoUpdate) + + protected fun nullableTimeProp( + name: String, + initialValue: LocalTime? = null, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, NullableType(TimeType), initialValue, echoUpdate) + + protected fun widgetProp( + name: String, + initialValue: M, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, WidgetReferenceType(), initialValue, echoUpdate) + + protected fun nullableWidgetProp( + name: String, + initialValue: M? = null, + echoUpdate: Boolean = true, + ): ReadWriteProperty = prop(name, NullableType(WidgetReferenceType()), initialValue, echoUpdate) + + protected inner class WidgetKtPropertyDelegate( + internal val property: WidgetModelProperty, + ) : ReadWriteProperty { + internal constructor(name: String, type: WidgetModelPropertyType, initialValue: T, echoUpdate: Boolean = true) : + this(WidgetModelPropertyImpl(name, type, initialValue, widgetManager, echoUpdate)) + + init { + addProperty(property) + } + + override fun getValue( + thisRef: WidgetModel, + property: KProperty<*>, + ): T = this.property.value + + override fun setValue( + thisRef: WidgetModel, + property: KProperty<*>, + value: T, + ) { + this.property.value = value + } + } +} + +/** + * Represents a single property of a widget model. + */ +public interface WidgetModelProperty { + /** + * Name of the property as it appears in the Jupyter protocol. + */ + public val name: String + + /** + * Type information for serialization and validation. + */ + public val type: WidgetModelPropertyType + + /** + * Current value of the property. + */ + public var value: T + + /** + * If true, updates from the frontend are echoed back. + */ + public var echoUpdate: Boolean + + /** + * Current value serialized for the Jupyter protocol. + */ + public val serializedValue: Any? + + /** + * Applies a new value received via the Jupyter protocol. + */ + public fun applyPatch( + patch: Any?, + fromFrontend: Boolean = false, + ) + + /** + * Adds a listener for changes to this property. + */ + public fun addChangeListener(listener: (Any?, fromFrontend: Boolean) -> Unit) +} + +internal class WidgetModelPropertyImpl( + override val name: String, + override val type: WidgetModelPropertyType, + initialValue: T, + private val widgetManager: WidgetManager, + override var echoUpdate: Boolean, +) : WidgetModelProperty { + private var _value: T = initialValue + private val listeners = mutableListOf<(newValue: Any?, fromFrontend: Boolean) -> Unit>() + + override var value: T + get() = _value + set(newValue) = setNewValue(newValue) + + override val serializedValue: Any? get() = type.serialize(value, widgetManager) + + override fun applyPatch( + patch: Any?, + fromFrontend: Boolean, + ) { + setNewValue(type.deserialize(patch, widgetManager), fromFrontend) + } + + override fun addChangeListener(listener: (Any?, Boolean) -> Unit) { + listeners.add(listener) + } + + private fun setNewValue( + newValue: T, + fromFrontend: Boolean = false, + ) { + if (newValue == _value) return + _value = newValue + notifyListeners(newValue, fromFrontend) + } + + private fun notifyListeners( + newValue: T, + fromFrontend: Boolean, + ) { + val serializedValue = type.serialize(newValue, widgetManager) + for (listener in listeners) { + listener(serializedValue, fromFrontend) + } + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/WidgetModelExtensions.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/WidgetModelExtensions.kt new file mode 100644 index 0000000..10a8269 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/WidgetModelExtensions.kt @@ -0,0 +1,30 @@ +package org.jetbrains.kotlinx.jupyter.widget.model + +import kotlin.reflect.KCallable +import kotlin.reflect.KProperty0 +import kotlin.reflect.KProperty1 +import kotlin.reflect.jvm.isAccessible + +/** + * Retrieves a property by the KProperty of the widget class instance. + */ +public fun T.getProperty(kProperty: KProperty0<*>): WidgetModelProperty<*>? = + getPropertyByDelegate(kProperty.withAccessibility { getDelegate() }) + +/** + * Retrieves a property by the KProperty of this class. + */ +public fun T.getProperty(kProperty: KProperty1): WidgetModelProperty<*>? = + getPropertyByDelegate(kProperty.withAccessibility { getDelegate(this@getProperty) }) + +private fun , R> T.withAccessibility(action: T.() -> R): R = + if (isAccessible) { + this.action() + } else { + isAccessible = true + try { + this.action() + } finally { + isAccessible = false + } + } diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/WidgetSpec.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/WidgetSpec.kt new file mode 100644 index 0000000..813561a --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/WidgetSpec.kt @@ -0,0 +1,43 @@ +package org.jetbrains.kotlinx.jupyter.widget.model + +import kotlinx.serialization.Serializable + +internal const val DEFAULT_MAJOR_VERSION = 2 +internal const val DEFAULT_MINOR_VERSION = 1 +internal const val DEFAULT_PATCH_VERSION = 0 + +internal val versionConstraintRegex = Regex("""\D*(\d+)\.(\d+)""") + +/** + * The set of six immutable properties that define a widget specification + * for the Jupyter Widgets protocol. + * These properties identify which frontend model and view should be used. + */ +@Serializable +public data class WidgetSpec( + /** + * The name of the frontend model class (e.g., "IntSliderModel"). + */ + val modelName: String, + /** + * The name of the NPM module containing the model (e.g., "@jupyter-widgets/controls"). + */ + val modelModule: String, + /** + * Semver requirement for the model module. + */ + val modelModuleVersion: String, + /** + * The name of the frontend view class (e.g., "IntSliderView"). + * Can be null for model-only widgets. + */ + val viewName: String?, + /** + * The name of the NPM module containing the view. + */ + val viewModule: String, + /** + * Semver requirement for the view module. + */ + val viewModuleVersion: String, +) diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/AbstractWidgetModelPropertyType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/AbstractWidgetModelPropertyType.kt new file mode 100644 index 0000000..251b19a --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/AbstractWidgetModelPropertyType.kt @@ -0,0 +1,11 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types + +/** + * Abstract base class for [WidgetModelPropertyType] implementations that + * provides a default [toString] implementation. + */ +public abstract class AbstractWidgetModelPropertyType( + override val name: String, +) : WidgetModelPropertyType { + override fun toString(): String = name +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/WidgetModelPropertyType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/WidgetModelPropertyType.kt new file mode 100644 index 0000000..f5a5317 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/WidgetModelPropertyType.kt @@ -0,0 +1,36 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager + +/** + * Defines how a widget property of type [T] is serialized and deserialized + * when communicating with the Jupyter frontend. + */ +public interface WidgetModelPropertyType { + /** + * Human-readable name of the type. + */ + public val name: String + + /** + * Default value for this property type. + */ + public val default: T + + /** + * Converts a Kotlin property value to a JSON-compatible representation. + * Some types (like widget references) may need the [widgetManager] for lookups. + */ + public fun serialize( + propertyValue: T, + widgetManager: WidgetManager, + ): Any? + + /** + * Converts a JSON-compatible representation back to a Kotlin property value. + */ + public fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): T +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/ArrayType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/ArrayType.kt new file mode 100644 index 0000000..28a338c --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/ArrayType.kt @@ -0,0 +1,39 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.compound + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.types.AbstractWidgetModelPropertyType +import org.jetbrains.kotlinx.jupyter.widget.model.types.WidgetModelPropertyType + +/** + * Property type representing a [List]. + * Serialized as a JSON array in the Jupyter protocol. + */ +public class ArrayType( + /** + * Type information for the elements of the list. + */ + public val elementType: WidgetModelPropertyType, +) : AbstractWidgetModelPropertyType>("array<${elementType.name}>") { + override val default: List = emptyList() + + override fun serialize( + propertyValue: List, + widgetManager: WidgetManager, + ): List = + propertyValue.map { + elementType.serialize(it, widgetManager) + } + + @Suppress("UNCHECKED_CAST") + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): List { + require(patchValue is List<*>) { + "Expected List for $name, got ${patchValue?.let { it::class.simpleName } ?: "null"}" + } + return patchValue.map { raw -> + elementType.deserialize(raw, widgetManager) + } + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/NullableType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/NullableType.kt new file mode 100644 index 0000000..2ad3b79 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/NullableType.kt @@ -0,0 +1,28 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.compound + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.types.AbstractWidgetModelPropertyType +import org.jetbrains.kotlinx.jupyter.widget.model.types.WidgetModelPropertyType + +/** + * Property type for nullable values. + * Wraps an [inner] type and handles `null` values by serializing them as `null` in JSON. + */ +public class NullableType( + private val inner: WidgetModelPropertyType, +) : AbstractWidgetModelPropertyType("${inner.name}?") { + override val default: T? = null + + override fun serialize( + propertyValue: T?, + widgetManager: WidgetManager, + ): Any? = + propertyValue?.let { + inner.serialize(it, widgetManager) + } + + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): T? = if (patchValue == null) null else inner.deserialize(patchValue, widgetManager) +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/PairType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/PairType.kt new file mode 100644 index 0000000..ecde76c --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/PairType.kt @@ -0,0 +1,42 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.compound + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.types.AbstractWidgetModelPropertyType +import org.jetbrains.kotlinx.jupyter.widget.model.types.WidgetModelPropertyType + +/** + * Property type representing a [Pair]. + * Serialized as a 2-element list in the Jupyter protocol. + */ +public class PairType( + /** + * Type information for the first element of the pair. + */ + public val firstType: WidgetModelPropertyType, + /** + * Type information for the second element of the pair. + */ + public val secondType: WidgetModelPropertyType, +) : AbstractWidgetModelPropertyType>("pair<${firstType.name}, ${secondType.name}>") { + override val default: Pair = firstType.default to secondType.default + + override fun serialize( + propertyValue: Pair, + widgetManager: WidgetManager, + ): List = + listOf( + firstType.serialize(propertyValue.first, widgetManager), + secondType.serialize(propertyValue.second, widgetManager), + ) + + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): Pair { + require(patchValue is List<*> && patchValue.size == 2) { + "Expected List of size 2 for $name, got $patchValue" + } + return firstType.deserialize(patchValue[0], widgetManager) to + secondType.deserialize(patchValue[1], widgetManager) + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/RawObjectType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/RawObjectType.kt new file mode 100644 index 0000000..8443874 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/RawObjectType.kt @@ -0,0 +1,26 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.compound + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.types.AbstractWidgetModelPropertyType + +/** + * Property type for generic JSON-like objects (represented as a [Map] in Kotlin). + */ +public object RawObjectType : AbstractWidgetModelPropertyType>("object") { + override val default: Map = emptyMap() + + override fun serialize( + propertyValue: Map, + widgetManager: WidgetManager, + ): Any = propertyValue + + @Suppress("UNCHECKED_CAST") + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): Map { + if (patchValue == null) return emptyMap() + require(patchValue is Map<*, *>) { "Expected Map for object, got ${patchValue::class.simpleName}" } + return patchValue as Map + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/UnionType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/UnionType.kt new file mode 100644 index 0000000..ea23eda --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/compound/UnionType.kt @@ -0,0 +1,47 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.compound + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.types.AbstractWidgetModelPropertyType + +/** + * Property type for values that can be of multiple different types (e.g., Int or String). + * + * It uses a list of [deserializers] and returns the result of the first one that completes without an exception. + */ +public class UnionType( + name: String, + override val default: T, + private val serializer: (T, WidgetManager) -> Any?, + private val deserializers: List<(Any?, WidgetManager) -> T>, +) : AbstractWidgetModelPropertyType(name) { + /** + * Serializes the value using the provided [serializer] function. + */ + override fun serialize( + propertyValue: T, + widgetManager: WidgetManager, + ): Any? = serializer(propertyValue, widgetManager) + + /** + * Attempts to deserialize the value by trying all provided [deserializers] in order. + * Throws an [IllegalStateException] if no deserializer succeeds. + */ + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): T { + val errors = mutableListOf() + for (deserializer in deserializers) { + try { + return deserializer(patchValue, widgetManager) + } catch (e: Exception) { + errors.add(e) + } + } + error( + "Unsupported value for property $name: '$patchValue'. " + + "Tried ${deserializers.size} deserializers. " + + "Errors: ${errors.joinToString { it.message ?: it.toString() }}", + ) + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/datetime/DateType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/datetime/DateType.kt new file mode 100644 index 0000000..670aebc --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/datetime/DateType.kt @@ -0,0 +1,39 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.datetime + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.types.AbstractWidgetModelPropertyType +import java.time.LocalDate +import java.time.format.DateTimeFormatter +import java.time.format.ResolverStyle + +/** + * Property type for [LocalDate]. + * Serialized as an ISO-8601 string, e.g., "2023-01-01". + */ +public object DateType : AbstractWidgetModelPropertyType("date") { + override val default: LocalDate = LocalDate.EPOCH + + private val formatter: DateTimeFormatter = + DateTimeFormatter + .ofPattern("uuuu-MM-dd") + .withResolverStyle(ResolverStyle.STRICT) + + override fun serialize( + propertyValue: LocalDate, + widgetManager: WidgetManager, + ): Any? = propertyValue.format(formatter) + + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): LocalDate { + require(patchValue is String) { + "Expected String for date, got ${patchValue?.let { it::class.simpleName } ?: "null"}" + } + return try { + LocalDate.parse(patchValue, formatter) + } catch (e: Exception) { + error("Invalid date format '$patchValue', expected uuuu-MM-dd: ${e.message}") + } + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/datetime/DatetimeType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/datetime/DatetimeType.kt new file mode 100644 index 0000000..d67e851 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/datetime/DatetimeType.kt @@ -0,0 +1,45 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.datetime + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.types.AbstractWidgetModelPropertyType +import java.time.Instant +import java.time.ZoneOffset +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter +import java.time.format.ResolverStyle + +/** + * Property type for [Instant]. + * Serialized as an ISO-8601 string in UTC, e.g., "2023-01-01T12:00:00Z". + */ +public object DatetimeType : AbstractWidgetModelPropertyType("datetime") { + /** + * Default value is [Instant.EPOCH]. + */ + override val default: Instant = Instant.EPOCH + + private val formatter: DateTimeFormatter = + DateTimeFormatter + .ofPattern("uuuu-MM-dd'T'HH:mm:ss'Z'") + .withResolverStyle(ResolverStyle.STRICT) + .withZone(ZoneOffset.UTC) + + override fun serialize( + propertyValue: Instant, + widgetManager: WidgetManager, + ): Any? = formatter.format(propertyValue) // respect 'Z' + + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): Instant { + require(patchValue is String) { + "Expected String for datetime, got ${patchValue?.let { it::class.simpleName } ?: "null"}" + } + return try { + ZonedDateTime.parse(patchValue, formatter).toInstant() + } catch (e: Exception) { + error("Invalid datetime format '$patchValue', expected uuuu-MM-dd'T'HH:mm:ss'Z': ${e.message}") + } + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/datetime/TimeType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/datetime/TimeType.kt new file mode 100644 index 0000000..803961d --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/datetime/TimeType.kt @@ -0,0 +1,39 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.datetime + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.types.AbstractWidgetModelPropertyType +import java.time.LocalTime +import java.time.format.DateTimeFormatter +import java.time.format.ResolverStyle + +/** + * Property type for [LocalTime]. + * Serialized as an ISO-8601 string, e.g., "12:00:00". + */ +public object TimeType : AbstractWidgetModelPropertyType("time") { + override val default: LocalTime = LocalTime.MIDNIGHT + + private val formatter: DateTimeFormatter = + DateTimeFormatter + .ofPattern("HH:mm:ss") + .withResolverStyle(ResolverStyle.STRICT) + + override fun serialize( + propertyValue: LocalTime, + widgetManager: WidgetManager, + ): Any? = propertyValue.format(formatter) + + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): LocalTime { + require(patchValue is String) { + "Expected String for time, got ${patchValue?.let { it::class.simpleName } ?: "null"}" + } + return try { + LocalTime.parse(patchValue, formatter) + } catch (e: Exception) { + error("Invalid time format '$patchValue', expected HH:mm:ss: ${e.message}") + } + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/enums/WidgetEnum.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/enums/WidgetEnum.kt new file mode 100644 index 0000000..e2bf4d5 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/enums/WidgetEnum.kt @@ -0,0 +1,16 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.enums + +import kotlin.properties.ReadOnlyProperty + +public abstract class WidgetEnum> { + private val _entries = mutableListOf>() + public val entries: List> get() = _entries + + public fun getEntry(name: String): WidgetEnumEntry? = entries.find { it.name == name } + + protected fun entry(name: String): ReadOnlyProperty, WidgetEnumEntry> { + val e = WidgetEnumEntry(name) + _entries.add(e) + return ReadOnlyProperty { _, _ -> e } + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/enums/WidgetEnumEntry.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/enums/WidgetEnumEntry.kt new file mode 100644 index 0000000..145d127 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/enums/WidgetEnumEntry.kt @@ -0,0 +1,5 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.enums + +public class WidgetEnumEntry> internal constructor( + public val name: String, +) diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/enums/WidgetEnumType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/enums/WidgetEnumType.kt new file mode 100644 index 0000000..563fbdc --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/enums/WidgetEnumType.kt @@ -0,0 +1,26 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.enums + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.types.AbstractWidgetModelPropertyType + +public class WidgetEnumType>( + private val widgetEnum: E, + override val default: WidgetEnumEntry, +) : AbstractWidgetModelPropertyType>("enum") { + override fun serialize( + propertyValue: WidgetEnumEntry, + widgetManager: WidgetManager, + ): String = propertyValue.name + + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): WidgetEnumEntry { + require(patchValue is String) { + "Expected String for enum, got ${patchValue?.let { it::class.simpleName } ?: "null"}" + } + return widgetEnum.entries.first { + it.name == patchValue + } + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/AnyType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/AnyType.kt new file mode 100644 index 0000000..2fe7ba9 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/AnyType.kt @@ -0,0 +1,18 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.primitive + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.types.AbstractWidgetModelPropertyType + +public object AnyType : AbstractWidgetModelPropertyType("any") { + override val default: Any? = null + + override fun serialize( + propertyValue: Any?, + widgetManager: WidgetManager, + ): Any? = propertyValue + + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): Any? = patchValue +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/BooleanType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/BooleanType.kt new file mode 100644 index 0000000..a10fc20 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/BooleanType.kt @@ -0,0 +1,3 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.primitive + +public object BooleanType : PrimitiveWidgetModelPropertyType("boolean", false) diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/BytesType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/BytesType.kt new file mode 100644 index 0000000..b5ddbda --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/BytesType.kt @@ -0,0 +1,3 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.primitive + +public object BytesType : PrimitiveWidgetModelPropertyType("bytes", byteArrayOf()) diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/FloatType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/FloatType.kt new file mode 100644 index 0000000..17652cb --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/FloatType.kt @@ -0,0 +1,10 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.primitive + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager + +public object FloatType : PrimitiveWidgetModelPropertyType("float", 0.0) { + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): Double = (patchValue as Number).toDouble() +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/IntType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/IntType.kt new file mode 100644 index 0000000..fff931f --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/IntType.kt @@ -0,0 +1,13 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.primitive + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager + +/** + * Property type for [Int]. + */ +public object IntType : PrimitiveWidgetModelPropertyType("int", 0) { + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): Int = (patchValue as Number).toInt() +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/PrimitiveWidgetModelPropertyType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/PrimitiveWidgetModelPropertyType.kt new file mode 100644 index 0000000..0e36c82 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/PrimitiveWidgetModelPropertyType.kt @@ -0,0 +1,23 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.primitive + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.types.AbstractWidgetModelPropertyType + +/** + * Base class for simple primitive property types. + */ +public abstract class PrimitiveWidgetModelPropertyType( + name: String, + override val default: T, +) : AbstractWidgetModelPropertyType(name) { + override fun serialize( + propertyValue: T, + widgetManager: WidgetManager, + ): Any? = propertyValue + + @Suppress("UNCHECKED_CAST") + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): T = patchValue as T +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/StringType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/StringType.kt new file mode 100644 index 0000000..b77897a --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/primitive/StringType.kt @@ -0,0 +1,3 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.primitive + +public object StringType : PrimitiveWidgetModelPropertyType("string", "") diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/ranges/AbstractRangeType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/ranges/AbstractRangeType.kt new file mode 100644 index 0000000..38bbb98 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/ranges/AbstractRangeType.kt @@ -0,0 +1,44 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.ranges + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.types.AbstractWidgetModelPropertyType + +/** + * Base class for property types representing a range (e.g., [IntRange]). + * In the Jupyter Widgets protocol, ranges are represented as a 2-element list [start, end]. + */ +public abstract class AbstractRangeType, R : ClosedRange>( + name: String, + override val default: R, +) : AbstractWidgetModelPropertyType(name) { + /** + * Converts a generic [Number] to the specific numeric type [T]. + */ + protected abstract fun fromNumber(n: Number): T + + /** + * Creates a range object of type [R] from start and end values. + */ + protected abstract fun createRange( + start: T, + end: T, + ): R + + override fun serialize( + propertyValue: R, + widgetManager: WidgetManager, + ): List = listOf(propertyValue.start, propertyValue.endInclusive) + + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): R { + require(patchValue is List<*> && patchValue.size == 2) { + "Expected List of size 2 for $name, got $patchValue" + } + return createRange( + fromNumber(patchValue[0] as Number), + fromNumber(patchValue[1] as Number), + ) + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/ranges/FloatRangeType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/ranges/FloatRangeType.kt new file mode 100644 index 0000000..d0cff77 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/ranges/FloatRangeType.kt @@ -0,0 +1,10 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.ranges + +public object FloatRangeType : AbstractRangeType>("floatRange", 0.0..0.0) { + override fun fromNumber(n: Number): Double = n.toDouble() + + override fun createRange( + start: Double, + end: Double, + ): ClosedRange = start..end +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/ranges/IntRangeType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/ranges/IntRangeType.kt new file mode 100644 index 0000000..eccfa81 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/ranges/IntRangeType.kt @@ -0,0 +1,10 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.ranges + +public object IntRangeType : AbstractRangeType("intRange", 0..0) { + override fun fromNumber(n: Number): Int = n.toInt() + + override fun createRange( + start: Int, + end: Int, + ): IntRange = start..end +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/widget/WidgetReferenceType.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/widget/WidgetReferenceType.kt new file mode 100644 index 0000000..1d4b0dd --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/model/types/widget/WidgetReferenceType.kt @@ -0,0 +1,52 @@ +package org.jetbrains.kotlinx.jupyter.widget.model.types.widget + +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.types.AbstractWidgetModelPropertyType + +private const val WIDGET_REF_PREFIX = "IPY_MODEL_" + +/** + * Property type for referencing other widgets. + * In the Jupyter protocol, widget references are strings prefixed with "IPY_MODEL_". + */ +public class WidgetReferenceType : AbstractWidgetModelPropertyType("widget-ref") { + /** + * References do not have a sensible default value. + */ + override val default: M get() = error("No default value for widget-ref") + + /** + * Serializes a [WidgetModel] into its string ID representation. + */ + override fun serialize( + propertyValue: M, + widgetManager: WidgetManager, + ): String { + val widgetId = + widgetManager.getWidgetId(propertyValue) + ?: error("Widget id for widget $propertyValue was not found") + return "$WIDGET_REF_PREFIX$widgetId" + } + + @Suppress("UNCHECKED_CAST") + override fun deserialize( + patchValue: Any?, + widgetManager: WidgetManager, + ): M { + requireNotNull(patchValue) { + "Widget reference cannot be null" + } + require(patchValue is String) { + "Expected String for widget-ref, got ${patchValue::class.simpleName}" + } + require(patchValue.startsWith(WIDGET_REF_PREFIX)) { + "Invalid widget ref format: $patchValue" + } + val id = patchValue.removePrefix(WIDGET_REF_PREFIX) + val model = + widgetManager.getWidget(id) + ?: error("Widget with id=$id not found") + return model as M + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/BufferPathsSerializer.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/BufferPathsSerializer.kt new file mode 100644 index 0000000..15f31de --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/BufferPathsSerializer.kt @@ -0,0 +1,77 @@ +package org.jetbrains.kotlinx.jupyter.widget.protocol + +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.descriptors.listSerialDescriptor +import kotlinx.serialization.descriptors.serialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonDecoder +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonEncoder +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.intOrNull + +/** + * Custom serializer for the `buffer_paths` field in the Jupyter Widgets protocol. + * `buffer_paths` is a list of paths, where each path is a list of strings (map keys) or integers (list indices). + */ +internal object BufferPathsSerializer : KSerializer>> { + /** + * Descriptor for the buffer paths structure. + */ + @OptIn(ExperimentalSerializationApi::class) + override val descriptor: SerialDescriptor = + listSerialDescriptor( + listSerialDescriptor( + serialDescriptor(), + ), + ) + + /** + * Serializes a list of buffer paths to JSON. + */ + override fun serialize( + encoder: Encoder, + value: List>, + ) { + val jsonEncoder = + encoder as? JsonEncoder + ?: error("BufferPathsSerializer can only be used with JSON") + jsonEncoder.encodeJsonElement( + JsonArray( + value.map { path -> + JsonArray( + path.map { el -> + when (el) { + is String -> JsonPrimitive(el) + is Int -> JsonPrimitive(el) + else -> error("Unsupported buffer path element: $el (${el::class.simpleName})") + } + }, + ) + }, + ), + ) + } + + override fun deserialize(decoder: Decoder): List> { + val jsonDecoder = + decoder as? JsonDecoder + ?: error("BufferPathsSerializer can only be used with JSON") + val element = jsonDecoder.decodeJsonElement() + + require(element is JsonArray) { "Expected JSON array for buffer_paths, got: $element" } + + return element.map { pathEl -> + require(pathEl is JsonArray) { "Expected JSON array inside buffer_paths, got: $pathEl" } + pathEl.map { element -> + element as? JsonPrimitive ?: error("Expected JSON primitive inside buffer_paths, got: $element") + if (element.isString) return@map element.content + element.intOrNull ?: error("Unsupported buffer path element: $element") + } + } + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/Conversion.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/Conversion.kt new file mode 100644 index 0000000..eb9aaa5 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/Conversion.kt @@ -0,0 +1,3 @@ +package org.jetbrains.kotlinx.jupyter.widget.protocol + +internal fun WidgetStateMessage.toPatch(buffers: List): Patch = getPatch(WireMessage(state, bufferPaths, buffers)) diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/JsonSerialization.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/JsonSerialization.kt new file mode 100644 index 0000000..1d5079b --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/JsonSerialization.kt @@ -0,0 +1,87 @@ +package org.jetbrains.kotlinx.jupyter.widget.protocol + +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonNull +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.booleanOrNull +import kotlinx.serialization.json.buildJsonArray +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.doubleOrNull +import kotlinx.serialization.json.intOrNull +import kotlin.collections.iterator + +/** + * Converts a [Patch] (Map) to its JSON representation. + * Note: [ByteArray] values are serialized as [JsonNull] because they should be handled via binary buffers. + */ +internal fun serializeJsonMap(map: Patch): JsonElement = serialize(map) + +private fun serializeAny(obj: Any?): JsonElement = + when (obj) { + null -> JsonNull + is Map<*, *> -> serialize(obj) + is List<*> -> serialize(obj) + is String -> JsonPrimitive(obj) + is Boolean -> JsonPrimitive(obj) + is Number -> JsonPrimitive(obj) + is ByteArray -> JsonNull // Binary data is sent separately in the 'buffers' field + else -> error("Don't know how to serialize object [$obj] of class ${obj::class}") + } + +private fun serialize(map: Map<*, *>): JsonObject = + buildJsonObject { + for ((key, value) in map) { + if (key !is String) error("Map key [$key] is of type ${key?.let { it::class }}. Don't know how to serialize it.") + put(key, serializeAny(value)) + } + } + +private fun serialize(list: List<*>): JsonArray = + buildJsonArray { + for (value in list) { + add(serializeAny(value)) + } + } + +/** + * Converts a JSON element back to a mutable map of property values. + */ +internal fun deserializeJsonMap(json: JsonElement): MutableMap { + if (json !is JsonObject) error("Input json should be a key-value object, but it's $json") + return deserializeMap(json) +} + +private fun deserializeAny(json: JsonElement): Any? = + when (json) { + is JsonObject -> deserializeMap(json) + is JsonArray -> deserializeList(json) + is JsonPrimitive -> deserializePrimitive(json) + } + +private fun deserializePrimitive(json: JsonPrimitive): Any? = + when { + json is JsonNull -> null + json.isString -> json.content + else -> { + json.booleanOrNull + ?: json.intOrNull + ?: json.doubleOrNull + ?: error("Unknown JSON primitive type: [$json]") + } + } + +private fun deserializeMap(json: JsonObject): MutableMap = + mutableMapOf().apply { + for ((key, value) in json) { + put(key, deserializeAny(value)) + } + } + +private fun deserializeList(jsonArray: JsonArray): MutableList = + mutableListOf().apply { + for (el in jsonArray) { + add(deserializeAny(el)) + } + } diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/PatchHydration.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/PatchHydration.kt new file mode 100644 index 0000000..d608895 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/PatchHydration.kt @@ -0,0 +1,113 @@ +package org.jetbrains.kotlinx.jupyter.widget.protocol + +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.jsonObject +import kotlin.collections.get +import kotlin.collections.iterator + +/** + * A "hydrated" patch containing widget state. + * Unlike the raw JSON representation, this can contain [ByteArray] values + * in place of binary data placeholders. + */ +public typealias Patch = Map + +/** + * Represents the raw message structure for Jupyter comm messages. + * In Jupyter Widgets protocol, binary data is sent separately from the JSON state. + */ +internal data class WireMessage( + /** + * The JSON-serializable part of the state. + */ + val state: JsonObject, + /** + * Paths within the [state] where binary buffers should be inserted. + */ + val bufferPaths: List>, + /** + * The actual binary data. + */ + val buffers: List, +) + +/** + * Combines [WireMessage]'s state and buffers into a single "hydrated" [Patch]. + */ +internal fun getPatch(wireMessage: WireMessage): Patch { + val dehydratedMap = deserializeJsonMap(wireMessage.state) + // Insert buffers into the map at specified paths + for ((path, buf) in wireMessage.bufferPaths.zip(wireMessage.buffers)) { + var obj: Any? = dehydratedMap + for (key in path.dropLast(1)) obj = getAt(obj, key) + setAt(obj, path.last(), buf) + } + return dehydratedMap +} + +/** + * Extracts binary buffers from a [Patch] and creates a [WireMessage]. + */ +internal fun getWireMessage(patch: Patch): WireMessage { + val pathStack = mutableListOf() + val bufferPaths = mutableListOf>() + val buffers = mutableListOf() + + // Recursively find all ByteArray values and their paths + fun traverse(obj: Any?) { + when (obj) { + is Map<*, *> -> { + for ((key, value) in obj) { + pathStack.add(key as Any) + traverse(value) + pathStack.removeLast() + } + } + is List<*> -> { + for (i in obj.indices) { + pathStack.add(i) + traverse(obj[i]) + pathStack.removeLast() + } + } + is ByteArray -> { + bufferPaths.add(pathStack.toList()) + buffers.add(obj) + } + } + } + + traverse(patch) + // Serialize to JSON, ByteArrays will be replaced with JsonNull during serialization + val state = serializeJsonMap(patch).jsonObject + return WireMessage(state, bufferPaths, buffers) +} + +private fun getAt( + obj: Any?, + key: Any, +): Any? = + when (obj) { + is Map<*, *> -> obj[key as String] + is List<*> -> obj[key as Int] + else -> error("Unexpected object type: $obj") + } + +private fun setAt( + obj: Any?, + key: Any?, + value: Any?, +) { + when (obj) { + is MutableMap<*, *> -> { + @Suppress("UNCHECKED_CAST") + (obj as MutableMap)[key] = value + } + + is MutableList<*> -> { + @Suppress("UNCHECKED_CAST") + (obj as MutableList)[key as Int] = value + } + else -> error("Unexpected object type: $obj") + } +} diff --git a/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/WidgetMessage.kt b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/WidgetMessage.kt new file mode 100644 index 0000000..e8680f3 --- /dev/null +++ b/integrations/widgets/widgets-api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/protocol/WidgetMessage.kt @@ -0,0 +1,88 @@ +package org.jetbrains.kotlinx.jupyter.widget.protocol + +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonClassDiscriminator +import kotlinx.serialization.json.JsonObject + +/** + * Base interface for messages exchanged between the frontend and backend via Comms. + * These follow the Jupyter Widgets protocol. + */ +@OptIn(ExperimentalSerializationApi::class) +@JsonClassDiscriminator("method") +@Serializable +internal sealed interface WidgetMessage + +/** + * Interface for messages that contain binary buffer path information. + */ +internal interface WithBufferPaths { + /** + * Paths where binary data should be inserted. + */ + val bufferPaths: List> +} + +/** + * Interface for messages that contain the widget's property state. + */ +internal interface WidgetStateMessage : WithBufferPaths { + /** + * The property state of the widget. + */ + val state: JsonObject +} + +@Serializable +internal class WidgetOpenMessage( + override val state: JsonObject, + @SerialName("buffer_paths") + @Serializable(with = BufferPathsSerializer::class) + override val bufferPaths: List>, +) : WidgetStateMessage + +@Serializable +@SerialName("update") +internal class WidgetUpdateMessage( + override val state: JsonObject, + @SerialName("buffer_paths") + @Serializable(with = BufferPathsSerializer::class) + override val bufferPaths: List>, +) : WidgetMessage, + WidgetStateMessage + +@Serializable +@SerialName("echo_update") +internal class WidgetEchoUpdateMessage( + override val state: JsonObject, + @SerialName("buffer_paths") + @Serializable(with = BufferPathsSerializer::class) + override val bufferPaths: List>, +) : WidgetMessage, + WidgetStateMessage + +@Serializable +@SerialName("request_state") +internal class RequestStateMessage : WidgetMessage + +@Serializable +@SerialName("custom") +internal class CustomMessage( + val content: JsonObject, +) : WidgetMessage + +@Serializable +@SerialName("request_states") +internal class RequestStatesMessage : WidgetMessage + +@Serializable +@SerialName("update_states") +internal class UpdateStatesMessage( + val states: JsonObject, + @SerialName("buffer_paths") + @Serializable(with = BufferPathsSerializer::class) + override val bufferPaths: List>, +) : WidgetMessage, + WithBufferPaths diff --git a/integrations/widgets/widgets-api/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/PatchHydrationTest.kt b/integrations/widgets/widgets-api/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/PatchHydrationTest.kt new file mode 100644 index 0000000..df7db29 --- /dev/null +++ b/integrations/widgets/widgets-api/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/PatchHydrationTest.kt @@ -0,0 +1,97 @@ +package org.jetbrains.kotlinx.jupyter.widget.test + +import io.kotest.matchers.shouldBe +import kotlinx.serialization.json.JsonNull +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put +import org.jetbrains.kotlinx.jupyter.widget.protocol.WireMessage +import org.jetbrains.kotlinx.jupyter.widget.protocol.getPatch +import org.jetbrains.kotlinx.jupyter.widget.protocol.getWireMessage +import org.junit.jupiter.api.Test +import kotlin.collections.get + +class PatchHydrationTest { + @Test + fun `getPatch should work for simple objects`() { + val bytes = byteArrayOf(1, 2, 3) + val state = + buildJsonObject { + put("v", null as String?) + } + val wire = + WireMessage( + state = state, + bufferPaths = listOf(listOf("v")), + buffers = listOf(bytes), + ) + + val patch = getPatch(wire) + patch["v"] shouldBe bytes + } + + @Test + fun `getPatch should work for nested objects`() { + val bytes = byteArrayOf(4, 5, 6) + val state = + buildJsonObject { + put( + "outer", + buildJsonObject { + put("inner", null as String?) + }, + ) + } + val wire = + WireMessage( + state = state, + bufferPaths = listOf(listOf("outer", "inner")), + buffers = listOf(bytes), + ) + + val patch = getPatch(wire) + val outer = patch["outer"] as Map<*, *> + outer["inner"] shouldBe bytes + } + + @Test + fun `getWireMessage should work`() { + val bytes1 = byteArrayOf(1) + val bytes2 = byteArrayOf(2) + val patch = + mapOf( + "a" to bytes1, + "b" to + mapOf( + "c" to bytes2, + "d" to "string", + ), + ) + + val wire = getWireMessage(patch) + wire.buffers shouldBe listOf(bytes1, bytes2) + wire.bufferPaths shouldBe listOf(listOf("a"), listOf("b", "c")) + + wire.state["a"] shouldBe JsonNull + } + + @Test + fun `getWireMessage and getPatch roundtrip should preserve state`() { + val patch = + mapOf( + "list" to + listOf( + 1, + byteArrayOf(10, 20), + mapOf("x" to byteArrayOf(30)), + ), + ) + + val wire = getWireMessage(patch) + val hydrated = getPatch(wire) + + val list = hydrated["list"] as List + list[0] shouldBe 1 + list[1] shouldBe byteArrayOf(10, 20) + (list[2] as Map<*, *>)["x"] shouldBe byteArrayOf(30) + } +} diff --git a/integrations/widgets/widgets-api/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/TestWidgetManager.kt b/integrations/widgets/widgets-api/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/TestWidgetManager.kt new file mode 100644 index 0000000..8cdbc0f --- /dev/null +++ b/integrations/widgets/widgets-api/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/TestWidgetManager.kt @@ -0,0 +1,40 @@ +package org.jetbrains.kotlinx.jupyter.widget.test + +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import org.jetbrains.kotlinx.jupyter.api.DisplayResult +import org.jetbrains.kotlinx.jupyter.protocol.api.RawMessage +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetFactoryRegistry +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel + +interface TestWidgetManager : WidgetManager { + override val factoryRegistry: WidgetFactoryRegistry get() = notImplemented() + override val contextMessage: RawMessage get() = notImplemented() + override var echoUpdateEnabled: Boolean + get() = false + set(_) {} + + override fun getWidget(modelId: String): WidgetModel? = notImplemented() + + override fun getWidgetId(widget: WidgetModel): String? = notImplemented() + + override fun registerWidget(widget: WidgetModel) {} + + override fun closeWidget(widget: WidgetModel) {} + + override fun renderWidget(widget: WidgetModel): DisplayResult = notImplemented() + + override fun sendCustomMessage( + widget: WidgetModel, + content: JsonObject, + metadata: JsonElement?, + buffers: List, + ) = notImplemented() + + companion object { + fun notImplemented(): Nothing = throw NotImplementedError("Not implemented") + + val INSTANCE = object : TestWidgetManager {} + } +} diff --git a/integrations/widgets/widgets-api/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/TypesTest.kt b/integrations/widgets/widgets-api/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/TypesTest.kt new file mode 100644 index 0000000..f2cb835 --- /dev/null +++ b/integrations/widgets/widgets-api/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/TypesTest.kt @@ -0,0 +1,184 @@ +package org.jetbrains.kotlinx.jupyter.widget.test + +import io.kotest.matchers.shouldBe +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.ArrayType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.NullableType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.PairType +import org.jetbrains.kotlinx.jupyter.widget.model.types.compound.RawObjectType +import org.jetbrains.kotlinx.jupyter.widget.model.types.datetime.DateType +import org.jetbrains.kotlinx.jupyter.widget.model.types.datetime.DatetimeType +import org.jetbrains.kotlinx.jupyter.widget.model.types.datetime.TimeType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.FloatType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.IntType +import org.jetbrains.kotlinx.jupyter.widget.model.types.primitive.StringType +import org.jetbrains.kotlinx.jupyter.widget.model.types.ranges.FloatRangeType +import org.jetbrains.kotlinx.jupyter.widget.model.types.ranges.IntRangeType +import org.jetbrains.kotlinx.jupyter.widget.model.types.widget.WidgetReferenceType +import org.junit.jupiter.api.Test +import java.time.Instant +import java.time.LocalDate +import java.time.LocalTime + +class TypesTest { + private val widgetManager = TestWidgetManager.INSTANCE + + @Test + fun `IntType should serialize to Int`() { + IntType.serialize(42, widgetManager) shouldBe 42 + } + + @Test + fun `IntType should deserialize from various numeric types`() { + IntType.deserialize(42, widgetManager) shouldBe 42 + IntType.deserialize(42L, widgetManager) shouldBe 42 + IntType.deserialize(42.0, widgetManager) shouldBe 42 + IntType.deserialize(42.7, widgetManager) shouldBe 42 + } + + @Test + fun `FloatType should serialize to Double`() { + FloatType.serialize(3.14, widgetManager) shouldBe 3.14 + } + + @Test + fun `FloatType should deserialize from various numeric types`() { + FloatType.deserialize(3.14, widgetManager) shouldBe 3.14 + FloatType.deserialize(3, widgetManager) shouldBe 3.0 + FloatType.deserialize(3L, widgetManager) shouldBe 3.0 + } + + @Test + fun `IntRangeType should serialize to list of bounds`() { + IntRangeType.serialize(1..10, widgetManager) shouldBe listOf(1, 10) + } + + @Test + fun `IntRangeType should deserialize from list of bounds`() { + IntRangeType.deserialize(listOf(1, 10), widgetManager) shouldBe 1..10 + IntRangeType.deserialize(listOf(1L, 10L), widgetManager) shouldBe 1..10 + } + + @Test + fun `FloatRangeType should serialize to list of bounds`() { + FloatRangeType.serialize(1.5..10.5, widgetManager) shouldBe listOf(1.5, 10.5) + } + + @Test + fun `FloatRangeType should deserialize from list of bounds`() { + FloatRangeType.deserialize(listOf(1.5, 10.5), widgetManager) shouldBe 1.5..10.5 + FloatRangeType.deserialize(listOf(1, 10), widgetManager) shouldBe 1.0..10.0 + } + + @Test + fun `PairType should serialize to list of elements`() { + val pairType = PairType(IntType, StringType) + pairType.serialize(42 to "hello", widgetManager) shouldBe listOf(42, "hello") + } + + @Test + fun `PairType should deserialize from list of elements`() { + val pairType = PairType(IntType, StringType) + pairType.deserialize(listOf(42, "hello"), widgetManager) shouldBe (42 to "hello") + } + + @Test + fun `ArrayType should serialize to list of elements`() { + val arrayType = ArrayType(IntType) + arrayType.serialize(listOf(1, 2, 3), widgetManager) shouldBe listOf(1, 2, 3) + } + + @Test + fun `ArrayType should deserialize from list of elements`() { + val arrayType = ArrayType(IntType) + arrayType.deserialize(listOf(1, 2, 3), widgetManager) shouldBe listOf(1, 2, 3) + arrayType.deserialize(listOf(1L, 2L, 3L), widgetManager) shouldBe listOf(1, 2, 3) + } + + @Test + fun `NullableType should serialize values or null`() { + val nullableType = NullableType(IntType) + nullableType.serialize(42, widgetManager) shouldBe 42 + nullableType.serialize(null, widgetManager) shouldBe null + } + + @Test + fun `NullableType should deserialize values or null`() { + val nullableType = NullableType(IntType) + nullableType.deserialize(42, widgetManager) shouldBe 42 + nullableType.deserialize(null, widgetManager) shouldBe null + } + + @Test + fun `RawObjectType should serialize map as is`() { + val obj = mapOf("a" to 1, "b" to "c") + RawObjectType.serialize(obj, widgetManager) shouldBe obj + } + + @Test + fun `RawObjectType should deserialize map or return emptyMap for null`() { + val obj = mapOf("a" to 1, "b" to "c") + RawObjectType.deserialize(obj, widgetManager) shouldBe obj + RawObjectType.deserialize(null, widgetManager) shouldBe emptyMap() + } + + @Test + fun `DatetimeType should serialize Instant to ISO-8601 string`() { + val instant = Instant.parse("2023-01-01T12:00:00Z") + DatetimeType.serialize(instant, widgetManager) shouldBe "2023-01-01T12:00:00Z" + } + + @Test + fun `DatetimeType should deserialize ISO-8601 string to Instant`() { + val instant = Instant.parse("2023-01-01T12:00:00Z") + DatetimeType.deserialize("2023-01-01T12:00:00Z", widgetManager) shouldBe instant + } + + @Test + fun `DateType should serialize LocalDate to ISO-8601 string`() { + val date = LocalDate.of(2023, 1, 1) + DateType.serialize(date, widgetManager) shouldBe "2023-01-01" + } + + @Test + fun `DateType should deserialize ISO-8601 string to LocalDate`() { + val date = LocalDate.of(2023, 1, 1) + DateType.deserialize("2023-01-01", widgetManager) shouldBe date + } + + @Test + fun `TimeType should serialize LocalTime to ISO-8601 string`() { + val time = LocalTime.of(12, 0, 0) + TimeType.serialize(time, widgetManager) shouldBe "12:00:00" + } + + @Test + fun `TimeType should deserialize ISO-8601 string to LocalTime`() { + val time = LocalTime.of(12, 0, 0) + TimeType.deserialize("12:00:00", widgetManager) shouldBe time + } + + @Test + fun `WidgetReferenceType should serialize widget to its IPY_MODEL_ prefixed ID`() { + val widgetId = "test-widget-id" + val myWidget = object : WidgetModel(widgetManager) {} + val manager = + object : TestWidgetManager { + override fun getWidgetId(widget: WidgetModel): String? = if (widget === myWidget) widgetId else null + } + val refType = WidgetReferenceType() + refType.serialize(myWidget, manager) shouldBe "IPY_MODEL_$widgetId" + } + + @Test + fun `WidgetReferenceType should deserialize IPY_MODEL_ prefixed ID to widget instance`() { + val widgetId = "test-widget-id" + val widget = object : WidgetModel(widgetManager) {} + val manager = + object : TestWidgetManager { + override fun getWidget(modelId: String): WidgetModel? = if (modelId == widgetId) widget else null + } + val refType = WidgetReferenceType() + refType.deserialize("IPY_MODEL_$widgetId", manager) shouldBe widget + } +} diff --git a/integrations/widgets/widgets-api/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/WidgetModelGetPropertyTest.kt b/integrations/widgets/widgets-api/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/WidgetModelGetPropertyTest.kt new file mode 100644 index 0000000..1949c03 --- /dev/null +++ b/integrations/widgets/widgets-api/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/WidgetModelGetPropertyTest.kt @@ -0,0 +1,38 @@ +package org.jetbrains.kotlinx.jupyter.widget.test + +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.shouldBe +import org.jetbrains.kotlinx.jupyter.widget.library.AccordionWidget +import org.jetbrains.kotlinx.jupyter.widget.model.getProperty +import org.junit.jupiter.api.Test + +class WidgetModelGetPropertyTest { + private val widgetManager = TestWidgetManager.INSTANCE + + @Test + fun `getProperty with KProperty1 should return the property`() { + val accordion = AccordionWidget(widgetManager, false) + val property = accordion.getProperty(AccordionWidget::selectedIndex) + + property.shouldNotBeNull() + property.name shouldBe "selected_index" + } + + @Test + fun `getProperty with KProperty0 should return the property`() { + val accordion = AccordionWidget(widgetManager, false) + val property = accordion.getProperty(accordion::selectedIndex) + + property.shouldNotBeNull() + property.name shouldBe "selected_index" + } + + @Test + fun `getProperty with String should return the property`() { + val accordion = AccordionWidget(widgetManager, false) + val property = accordion.getProperty("selected_index") + + property.shouldNotBeNull() + property.name shouldBe "selected_index" + } +} diff --git a/integrations/widgets/widgets-generator/build.gradle.kts b/integrations/widgets/widgets-generator/build.gradle.kts new file mode 100644 index 0000000..914e41d --- /dev/null +++ b/integrations/widgets/widgets-generator/build.gradle.kts @@ -0,0 +1,36 @@ +plugins { + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.kotlin.serialization) +} + +dependencies { + implementation(libs.kotlinx.serialization.json) + implementation(libs.kotlin.reflect) + testImplementation(libs.kotlin.test) + testImplementation(libs.test.kotlintest.assertions) +} + +tasks.withType { + useJUnitPlatform() +} + +kotlin { + jvmToolchain { + languageVersion.set( + JavaLanguageVersion.of( + JavaVersion + .current() + .majorVersion + .toInt(), + ), + ) + } + explicitApi() +} + +tasks.register("generateWidgets") { + group = "generation" + description = "Generate widget models from schema.json" + classpath = sourceSets.main.get().runtimeClasspath + mainClass.set("org.jetbrains.kotlinx.jupyter.widget.generator.WidgetGeneratorKt") +} diff --git a/integrations/widgets/widgets-generator/schema.json b/integrations/widgets/widgets-generator/schema.json new file mode 100644 index 0000000..0cefeb2 --- /dev/null +++ b/integrations/widgets/widgets-generator/schema.json @@ -0,0 +1,8291 @@ +[ + { + "attributes": [ + { + "default": "@jupyter-widgets/base", + "help": "The namespace for the model.", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "A semver requirement for namespace version containing the model.", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "LayoutModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/base", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "LayoutView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "enum": [ + "flex-start", + "flex-end", + "center", + "space-between", + "space-around", + "space-evenly", + "stretch", + "inherit", + "initial", + "unset" + ], + "help": "The align-content CSS attribute.", + "name": "align_content", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "enum": [ + "flex-start", + "flex-end", + "center", + "baseline", + "stretch", + "inherit", + "initial", + "unset" + ], + "help": "The align-items CSS attribute.", + "name": "align_items", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "enum": [ + "auto", + "flex-start", + "flex-end", + "center", + "baseline", + "stretch", + "inherit", + "initial", + "unset" + ], + "help": "The align-self CSS attribute.", + "name": "align_self", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The border bottom CSS attribute.", + "name": "border_bottom", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The border left CSS attribute.", + "name": "border_left", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The border right CSS attribute.", + "name": "border_right", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The border top CSS attribute.", + "name": "border_top", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The bottom CSS attribute.", + "name": "bottom", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The display CSS attribute.", + "name": "display", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The flex CSS attribute.", + "name": "flex", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The flex-flow CSS attribute.", + "name": "flex_flow", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The grid-area CSS attribute.", + "name": "grid_area", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The grid-auto-columns CSS attribute.", + "name": "grid_auto_columns", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "enum": [ + "column", + "row", + "row dense", + "column dense", + "inherit", + "initial", + "unset" + ], + "help": "The grid-auto-flow CSS attribute.", + "name": "grid_auto_flow", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The grid-auto-rows CSS attribute.", + "name": "grid_auto_rows", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The grid-column CSS attribute.", + "name": "grid_column", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The grid-gap CSS attribute.", + "name": "grid_gap", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The grid-row CSS attribute.", + "name": "grid_row", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The grid-template-areas CSS attribute.", + "name": "grid_template_areas", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The grid-template-columns CSS attribute.", + "name": "grid_template_columns", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The grid-template-rows CSS attribute.", + "name": "grid_template_rows", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The height CSS attribute.", + "name": "height", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "enum": [ + "flex-start", + "flex-end", + "center", + "space-between", + "space-around", + "inherit", + "initial", + "unset" + ], + "help": "The justify-content CSS attribute.", + "name": "justify_content", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "enum": [ + "flex-start", + "flex-end", + "center", + "inherit", + "initial", + "unset" + ], + "help": "The justify-items CSS attribute.", + "name": "justify_items", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The left CSS attribute.", + "name": "left", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The margin CSS attribute.", + "name": "margin", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The max-height CSS attribute.", + "name": "max_height", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The max-width CSS attribute.", + "name": "max_width", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The min-height CSS attribute.", + "name": "min_height", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The min-width CSS attribute.", + "name": "min_width", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "enum": ["contain", "cover", "fill", "scale-down", "none"], + "help": "The object-fit CSS attribute.", + "name": "object_fit", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The object-position CSS attribute.", + "name": "object_position", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The order CSS attribute.", + "name": "order", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The overflow CSS attribute.", + "name": "overflow", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The padding CSS attribute.", + "name": "padding", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The right CSS attribute.", + "name": "right", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The top CSS attribute.", + "name": "top", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "enum": ["visible", "hidden", "inherit", "initial", "unset"], + "help": "The visibility CSS attribute.", + "name": "visibility", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The width CSS attribute.", + "name": "width", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/base", + "name": "LayoutModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/base", + "name": "LayoutView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "AccordionModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "AccordionView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "enum": ["success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the box.", + "name": "box_style", + "type": "string" + }, + { + "default": [], + "help": "List of widget children", + "items": { + "type": "reference", + "widget": "Widget" + }, + "name": "children", + "type": "array" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "The index of the selected page. This is either an integer selecting a particular sub-widget, or None to have no widgets selected.", + "name": "selected_index", + "type": "int" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "default": [], + "help": "Titles of the pages", + "items": { + "type": "string" + }, + "name": "titles", + "type": "array" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "AccordionModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "AccordionView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "AudioModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "AudioView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": true, + "help": "When true, the audio starts when it's displayed", + "name": "autoplay", + "type": "bool" + }, + { + "default": true, + "help": "Specifies that audio controls should be displayed (such as a play/pause button etc)", + "name": "controls", + "type": "bool" + }, + { + "default": "mp3", + "help": "The format of the audio.", + "name": "format", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": true, + "help": "When true, the audio will start from the beginning after finishing", + "name": "loop", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": "b''", + "help": "The media data as a memory view of bytes.", + "name": "value", + "type": "bytes" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "AudioModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "AudioView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "BoundedFloatTextModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "FloatTextView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": false, + "help": "Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": 100.0, + "help": "Max value", + "name": "max", + "type": "float" + }, + { + "default": 0.0, + "help": "Min value", + "name": "min", + "type": "float" + }, + { + "allow_none": true, + "default": null, + "help": "Minimum step to increment the value", + "name": "step", + "type": "float" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": 0.0, + "help": "Float value", + "name": "value", + "type": "float" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "BoundedFloatTextModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "FloatTextView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "BoundedIntTextModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "IntTextView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": false, + "help": "Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": 100, + "help": "Max value", + "name": "max", + "type": "int" + }, + { + "default": 0, + "help": "Min value", + "name": "min", + "type": "int" + }, + { + "default": 1, + "help": "Minimum step to increment the value", + "name": "step", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": 0, + "help": "Int value", + "name": "value", + "type": "int" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "BoundedIntTextModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "IntTextView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "BoxModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "BoxView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "enum": ["success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the box.", + "name": "box_style", + "type": "string" + }, + { + "default": [], + "help": "List of widget children", + "items": { + "type": "reference", + "widget": "Widget" + }, + "name": "children", + "type": "array" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "BoxModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "BoxView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ButtonModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "ButtonView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "enum": ["primary", "success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the button.", + "name": "button_style", + "type": "string" + }, + { + "default": "", + "help": "Button label.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Enable or disable user changes.", + "name": "disabled", + "type": "bool" + }, + { + "default": "", + "help": "Font-awesome icon names, without the 'fa-' prefix.", + "name": "icon", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "ButtonStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ButtonModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "ButtonView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ButtonStyleModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/base", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "StyleView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Color of the button", + "name": "button_color", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Button text font family.", + "name": "font_family", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Button text font size.", + "name": "font_size", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Button text font style.", + "name": "font_style", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Button text font variant.", + "name": "font_variant", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Button text font weight.", + "name": "font_weight", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Button text color.", + "name": "text_color", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Button text decoration.", + "name": "text_decoration", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ButtonStyleModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/base", + "name": "StyleView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "CheckboxModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "CheckboxView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes.", + "name": "disabled", + "type": "bool" + }, + { + "default": true, + "help": "Indent the control to align with other controls with a description.", + "name": "indent", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "CheckboxStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": false, + "help": "Bool value", + "name": "value", + "type": "bool" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "CheckboxModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "CheckboxView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "CheckboxStyleModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/base", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "StyleView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Background specifications.", + "name": "background", + "type": "string" + }, + { + "default": "", + "help": "Width of the description to the side of the control.", + "name": "description_width", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "CheckboxStyleModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/base", + "name": "StyleView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ColorPickerModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "ColorPickerView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": false, + "help": "Display short version with just a color selector.", + "name": "concise", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes.", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": "black", + "help": "The color value.", + "name": "value", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ColorPickerModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "ColorPickerView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ColorsInputModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "ColorsInputView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": true, + "help": "", + "name": "allow_duplicates", + "type": "bool" + }, + { + "default": [], + "help": "", + "name": "allowed_tags", + "type": "array" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "\u200b", + "help": "", + "name": "placeholder", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": [], + "help": "List of string tags", + "name": "value", + "type": "array" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ColorsInputModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "ColorsInputView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ComboboxModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "ComboboxView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": true, + "help": "Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": false, + "help": "If set, ensure value is in options. Implies continuous_update=False.", + "name": "ensure_option", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": [], + "help": "Dropdown options for the combobox", + "items": { + "type": "string" + }, + "name": "options", + "type": "array" + }, + { + "default": "\u200b", + "help": "Placeholder text to display when nothing has been typed", + "name": "placeholder", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "TextStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": "", + "help": "String value", + "name": "value", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ComboboxModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "ComboboxView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ControllerAxisModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "ControllerAxisView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": 0.0, + "help": "The value of the axis.", + "name": "value", + "type": "float" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ControllerAxisModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "ControllerAxisView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ControllerButtonModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "ControllerButtonView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": false, + "help": "Whether the button is pressed.", + "name": "pressed", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": 0.0, + "help": "The value of the button.", + "name": "value", + "type": "float" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ControllerButtonModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "ControllerButtonView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ControllerModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "ControllerView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": [], + "help": "The axes on the gamepad.", + "items": { + "type": "reference", + "widget": "Axis" + }, + "name": "axes", + "type": "array" + }, + { + "default": [], + "help": "The buttons on the gamepad.", + "items": { + "type": "reference", + "widget": "Button" + }, + "name": "buttons", + "type": "array" + }, + { + "default": false, + "help": "Whether the gamepad is connected.", + "name": "connected", + "type": "bool" + }, + { + "default": 0, + "help": "The id number of the controller.", + "name": "index", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "", + "help": "The name of the control mapping.", + "name": "mapping", + "type": "string" + }, + { + "default": "", + "help": "The name of the controller.", + "name": "name", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "default": 0.0, + "help": "The last time the data from this gamepad was updated.", + "name": "timestamp", + "type": "float" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ControllerModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "ControllerView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "DOMWidgetModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Name of the view.", + "name": "_view_name", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": "b''", + "help": "The media data as a memory view of bytes.", + "name": "value", + "type": "bytes" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "DOMWidgetModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": null, + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "DatePickerModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "DatePickerView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes.", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "max", + "type": "Date" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "min", + "type": "Date" + }, + { + "default": 1, + "help": "The date step to use for the picker, in days, or \"any\".", + "name": "step", + "type": ["int", "string"], + "union_attributes": [ + { + "type": "int" + }, + { + "enum": ["any"], + "type": "string" + } + ] + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "value", + "type": "Date" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "DatePickerModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "DatePickerView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "DatetimeModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "DatetimeView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes.", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "max", + "type": "Datetime" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "min", + "type": "Datetime" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "value", + "type": "Datetime" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "DatetimeModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "DatetimeView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "DescriptionStyleModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/base", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "StyleView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Width of the description to the side of the control.", + "name": "description_width", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "DescriptionStyleModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/base", + "name": "StyleView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "DirectionalLinkModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Name of the view.", + "name": "_view_name", + "type": "string" + }, + { + "default": [], + "help": "The source (widget, 'trait_name') pair", + "name": "source", + "type": "array" + }, + { + "default": [], + "help": "The target (widget, 'trait_name') pair", + "name": "target", + "type": "array" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "DirectionalLinkModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": null, + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "DropdownModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": [], + "help": "The labels for the options.", + "items": { + "type": "string" + }, + "name": "_options_labels", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "DropdownView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "Selected index", + "name": "index", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "DropdownModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "DropdownView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "FileUploadModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "FileUploadView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "File types to accept, empty string for all", + "name": "accept", + "type": "string" + }, + { + "default": "", + "enum": ["primary", "success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the button.", + "name": "button_style", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable button", + "name": "disabled", + "type": "bool" + }, + { + "default": "", + "help": "Error message", + "name": "error", + "type": "string" + }, + { + "default": "upload", + "help": "Font-awesome icon name, without the 'fa-' prefix.", + "name": "icon", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": false, + "help": "If True, allow for multiple files upload", + "name": "multiple", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "ButtonStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": [], + "help": "The file upload value", + "items": { + "type": "object" + }, + "name": "value", + "type": "array" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "FileUploadModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "FileUploadView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "FloatLogSliderModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "FloatLogSliderView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": 10.0, + "help": "Base for the logarithm", + "name": "base", + "type": "float" + }, + { + "default": "drag-tap", + "enum": ["drag-tap", "drag-snap", "tap", "drag", "snap"], + "help": "Slider dragging behavior.", + "name": "behavior", + "type": "string" + }, + { + "default": true, + "help": "Update the value of the widget as the user is holding the slider.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": 4.0, + "help": "Max value for the exponent", + "name": "max", + "type": "float" + }, + { + "default": 0.0, + "help": "Min value for the exponent", + "name": "min", + "type": "float" + }, + { + "default": "horizontal", + "enum": ["horizontal", "vertical"], + "help": "Vertical or horizontal.", + "name": "orientation", + "type": "string" + }, + { + "default": true, + "help": "Display the current value of the slider next to it.", + "name": "readout", + "type": "bool" + }, + { + "default": ".3g", + "help": "Format for the readout", + "name": "readout_format", + "type": "string" + }, + { + "allow_none": true, + "default": 0.1, + "help": "Minimum step in the exponent to increment the value", + "name": "step", + "type": "float" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "SliderStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": 1.0, + "help": "Float value", + "name": "value", + "type": "float" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "FloatLogSliderModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "FloatLogSliderView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "FloatProgressModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "ProgressView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "allow_none": true, + "default": "", + "enum": ["success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the progress bar.", + "name": "bar_style", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": 100.0, + "help": "Max value", + "name": "max", + "type": "float" + }, + { + "default": 0.0, + "help": "Min value", + "name": "min", + "type": "float" + }, + { + "default": "horizontal", + "enum": ["horizontal", "vertical"], + "help": "Vertical or horizontal.", + "name": "orientation", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "ProgressStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": 0.0, + "help": "Float value", + "name": "value", + "type": "float" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "FloatProgressModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "ProgressView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "FloatRangeSliderModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "FloatRangeSliderView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "drag-tap", + "enum": ["drag-tap", "drag-snap", "tap", "drag", "snap"], + "help": "Slider dragging behavior.", + "name": "behavior", + "type": "string" + }, + { + "default": true, + "help": "Update the value of the widget as the user is sliding the slider.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": 100.0, + "help": "Max value", + "name": "max", + "type": "float" + }, + { + "default": 0.0, + "help": "Min value", + "name": "min", + "type": "float" + }, + { + "default": "horizontal", + "enum": ["horizontal", "vertical"], + "help": "Vertical or horizontal.", + "name": "orientation", + "type": "string" + }, + { + "default": true, + "help": "Display the current value of the slider next to it.", + "name": "readout", + "type": "bool" + }, + { + "default": ".2f", + "help": "Format for the readout", + "name": "readout_format", + "type": "string" + }, + { + "allow_none": true, + "default": 0.1, + "help": "Minimum step to increment the value", + "name": "step", + "type": "float" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "SliderStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": [0.0, 1.0], + "help": "Tuple of (lower, upper) bounds", + "name": "value", + "type": "array" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "FloatRangeSliderModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "FloatRangeSliderView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "FloatSliderModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "FloatSliderView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "drag-tap", + "enum": ["drag-tap", "drag-snap", "tap", "drag", "snap"], + "help": "Slider dragging behavior.", + "name": "behavior", + "type": "string" + }, + { + "default": true, + "help": "Update the value of the widget as the user is holding the slider.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": 100.0, + "help": "Max value", + "name": "max", + "type": "float" + }, + { + "default": 0.0, + "help": "Min value", + "name": "min", + "type": "float" + }, + { + "default": "horizontal", + "enum": ["horizontal", "vertical"], + "help": "Vertical or horizontal.", + "name": "orientation", + "type": "string" + }, + { + "default": true, + "help": "Display the current value of the slider next to it.", + "name": "readout", + "type": "bool" + }, + { + "default": ".2f", + "help": "Format for the readout", + "name": "readout_format", + "type": "string" + }, + { + "allow_none": true, + "default": 0.1, + "help": "Minimum step to increment the value", + "name": "step", + "type": "float" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "SliderStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": 0.0, + "help": "Float value", + "name": "value", + "type": "float" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "FloatSliderModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "FloatSliderView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "FloatTextModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "FloatTextView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": false, + "help": "Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "Minimum step to increment the value", + "name": "step", + "type": "float" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": 0.0, + "help": "Float value", + "name": "value", + "type": "float" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "FloatTextModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "FloatTextView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "FloatsInputModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "FloatsInputView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": true, + "help": "", + "name": "allow_duplicates", + "type": "bool" + }, + { + "default": [], + "help": "", + "name": "allowed_tags", + "type": "array" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": ".1f", + "help": "", + "name": "format", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "max", + "type": "float" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "min", + "type": "float" + }, + { + "default": "\u200b", + "help": "", + "name": "placeholder", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "default": "", + "enum": ["primary", "success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the tags.", + "name": "tag_style", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": [], + "help": "List of float tags", + "name": "value", + "type": "array" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "FloatsInputModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "FloatsInputView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "GridBoxModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "GridBoxView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "enum": ["success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the box.", + "name": "box_style", + "type": "string" + }, + { + "default": [], + "help": "List of widget children", + "items": { + "type": "reference", + "widget": "Widget" + }, + "name": "children", + "type": "array" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "GridBoxModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "GridBoxView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "HBoxModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "HBoxView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "enum": ["success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the box.", + "name": "box_style", + "type": "string" + }, + { + "default": [], + "help": "List of widget children", + "items": { + "type": "reference", + "widget": "Widget" + }, + "name": "children", + "type": "array" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "HBoxModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "HBoxView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "HTMLMathModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "HTMLMathView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "\u200b", + "help": "Placeholder text to display when nothing has been typed", + "name": "placeholder", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "HTMLMathStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": "", + "help": "String value", + "name": "value", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "HTMLMathModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "HTMLMathView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "HTMLMathStyleModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/base", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "StyleView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Background specifications.", + "name": "background", + "type": "string" + }, + { + "default": "", + "help": "Width of the description to the side of the control.", + "name": "description_width", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Text font size.", + "name": "font_size", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Text color", + "name": "text_color", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "HTMLMathStyleModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/base", + "name": "StyleView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "HTMLModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "HTMLView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "\u200b", + "help": "Placeholder text to display when nothing has been typed", + "name": "placeholder", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "HTMLStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": "", + "help": "String value", + "name": "value", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "HTMLModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "HTMLView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "HTMLStyleModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/base", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "StyleView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Background specifications.", + "name": "background", + "type": "string" + }, + { + "default": "", + "help": "Width of the description to the side of the control.", + "name": "description_width", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Text font size.", + "name": "font_size", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Text color", + "name": "text_color", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "HTMLStyleModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/base", + "name": "StyleView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ImageModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "ImageView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "png", + "help": "The format of the image.", + "name": "format", + "type": "string" + }, + { + "default": "", + "help": "Height of the image in pixels. Use layout.height for styling the widget.", + "name": "height", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": "b''", + "help": "The media data as a memory view of bytes.", + "name": "value", + "type": "bytes" + }, + { + "default": "", + "help": "Width of the image in pixels. Use layout.width for styling the widget.", + "name": "width", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ImageModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "ImageView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "IntProgressModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "ProgressView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "enum": ["success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the progress bar.", + "name": "bar_style", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": 100, + "help": "Max value", + "name": "max", + "type": "int" + }, + { + "default": 0, + "help": "Min value", + "name": "min", + "type": "int" + }, + { + "default": "horizontal", + "enum": ["horizontal", "vertical"], + "help": "Vertical or horizontal.", + "name": "orientation", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "ProgressStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": 0, + "help": "Int value", + "name": "value", + "type": "int" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "IntProgressModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "ProgressView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "IntRangeSliderModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "IntRangeSliderView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "drag-tap", + "enum": ["drag-tap", "drag-snap", "tap", "drag", "snap"], + "help": "Slider dragging behavior.", + "name": "behavior", + "type": "string" + }, + { + "default": true, + "help": "Update the value of the widget as the user is sliding the slider.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": 100, + "help": "Max value", + "name": "max", + "type": "int" + }, + { + "default": 0, + "help": "Min value", + "name": "min", + "type": "int" + }, + { + "default": "horizontal", + "enum": ["horizontal", "vertical"], + "help": "Vertical or horizontal.", + "name": "orientation", + "type": "string" + }, + { + "default": true, + "help": "Display the current value of the slider next to it.", + "name": "readout", + "type": "bool" + }, + { + "default": "d", + "help": "Format for the readout", + "name": "readout_format", + "type": "string" + }, + { + "default": 1, + "help": "Minimum step that the value can take", + "name": "step", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "Slider style customizations.", + "name": "style", + "type": "reference", + "widget": "SliderStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": [0, 1], + "help": "Tuple of (lower, upper) bounds", + "name": "value", + "type": "array" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "IntRangeSliderModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "IntRangeSliderView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "IntSliderModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "IntSliderView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "drag-tap", + "enum": ["drag-tap", "drag-snap", "tap", "drag", "snap"], + "help": "Slider dragging behavior.", + "name": "behavior", + "type": "string" + }, + { + "default": true, + "help": "Update the value of the widget as the user is holding the slider.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": 100, + "help": "Max value", + "name": "max", + "type": "int" + }, + { + "default": 0, + "help": "Min value", + "name": "min", + "type": "int" + }, + { + "default": "horizontal", + "enum": ["horizontal", "vertical"], + "help": "Vertical or horizontal.", + "name": "orientation", + "type": "string" + }, + { + "default": true, + "help": "Display the current value of the slider next to it.", + "name": "readout", + "type": "bool" + }, + { + "default": "d", + "help": "Format for the readout", + "name": "readout_format", + "type": "string" + }, + { + "default": 1, + "help": "Minimum step to increment the value", + "name": "step", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "SliderStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": 0, + "help": "Int value", + "name": "value", + "type": "int" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "IntSliderModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "IntSliderView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "IntTextModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "IntTextView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": false, + "help": "Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": 1, + "help": "Minimum step to increment the value", + "name": "step", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": 0, + "help": "Int value", + "name": "value", + "type": "int" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "IntTextModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "IntTextView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "IntsInputModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "IntsInputView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": true, + "help": "", + "name": "allow_duplicates", + "type": "bool" + }, + { + "default": [], + "help": "", + "name": "allowed_tags", + "type": "array" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": "d", + "help": "", + "name": "format", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "max", + "type": "int" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "min", + "type": "int" + }, + { + "default": "\u200b", + "help": "", + "name": "placeholder", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "default": "", + "enum": ["primary", "success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the tags.", + "name": "tag_style", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": [], + "help": "List of int tags", + "name": "value", + "type": "array" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "IntsInputModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "IntsInputView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "LabelModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "LabelView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "\u200b", + "help": "Placeholder text to display when nothing has been typed", + "name": "placeholder", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "LabelStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": "", + "help": "String value", + "name": "value", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "LabelModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "LabelView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "LabelStyleModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/base", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "StyleView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Background specifications.", + "name": "background", + "type": "string" + }, + { + "default": "", + "help": "Width of the description to the side of the control.", + "name": "description_width", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Label text font family.", + "name": "font_family", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Text font size.", + "name": "font_size", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Label text font style.", + "name": "font_style", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Label text font variant.", + "name": "font_variant", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Label text font weight.", + "name": "font_weight", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Text color", + "name": "text_color", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Label text decoration.", + "name": "text_decoration", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "LabelStyleModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/base", + "name": "StyleView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "LinkModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Name of the view.", + "name": "_view_name", + "type": "string" + }, + { + "default": [], + "help": "The source (widget, 'trait_name') pair", + "name": "source", + "type": "array" + }, + { + "default": [], + "help": "The target (widget, 'trait_name') pair", + "name": "target", + "type": "array" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "LinkModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": null, + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "NaiveDatetimeModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "DatetimeView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes.", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "max", + "type": "Datetime" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "min", + "type": "Datetime" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "value", + "type": "Datetime" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "NaiveDatetimeModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "DatetimeView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "PasswordModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "PasswordView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": true, + "help": "Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "\u200b", + "help": "Placeholder text to display when nothing has been typed", + "name": "placeholder", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "TextStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": "", + "help": "String value", + "name": "value", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "PasswordModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "PasswordView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "PlayModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "PlayView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": 100, + "help": "The time between two animation steps (ms).", + "name": "interval", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": 100, + "help": "Max value", + "name": "max", + "type": "int" + }, + { + "default": 0, + "help": "Min value", + "name": "min", + "type": "int" + }, + { + "default": false, + "help": "Whether the control is currently playing.", + "name": "playing", + "type": "bool" + }, + { + "default": false, + "help": "Whether the control will repeat in a continuous loop.", + "name": "repeat", + "type": "bool" + }, + { + "default": true, + "help": "Show the repeat toggle button in the widget.", + "name": "show_repeat", + "type": "bool" + }, + { + "default": 1, + "help": "Increment step", + "name": "step", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": 0, + "help": "Int value", + "name": "value", + "type": "int" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "PlayModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "PlayView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ProgressStyleModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/base", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "StyleView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Color of the progress bar.", + "name": "bar_color", + "type": "string" + }, + { + "default": "", + "help": "Width of the description to the side of the control.", + "name": "description_width", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ProgressStyleModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/base", + "name": "StyleView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "RadioButtonsModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": [], + "help": "The labels for the options.", + "items": { + "type": "string" + }, + "name": "_options_labels", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "RadioButtonsView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "Selected index", + "name": "index", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "vertical", + "enum": ["horizontal", "vertical"], + "help": "Vertical or horizontal.", + "name": "orientation", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "RadioButtonsModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "RadioButtonsView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "SelectModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": [], + "help": "The labels for the options.", + "items": { + "type": "string" + }, + "name": "_options_labels", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "SelectView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "Selected index", + "name": "index", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": 5, + "help": "The number of rows to display.", + "name": "rows", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "SelectModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "SelectView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "SelectMultipleModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": [], + "help": "The labels for the options.", + "items": { + "type": "string" + }, + "name": "_options_labels", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "SelectMultipleView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": [], + "help": "Selected indices", + "items": { + "type": "int" + }, + "name": "index", + "type": "array" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": 5, + "help": "The number of rows to display.", + "name": "rows", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "SelectMultipleModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "SelectMultipleView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "SelectionRangeSliderModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": [], + "help": "The labels for the options.", + "items": { + "type": "string" + }, + "name": "_options_labels", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "SelectionRangeSliderView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "drag-tap", + "enum": ["drag-tap", "drag-snap", "tap", "drag", "snap"], + "help": "Slider dragging behavior.", + "name": "behavior", + "type": "string" + }, + { + "default": true, + "help": "Update the value of the widget as the user is holding the slider.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": [0, 0], + "help": "Min and max selected indices", + "name": "index", + "type": "array" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "horizontal", + "enum": ["horizontal", "vertical"], + "help": "Vertical or horizontal.", + "name": "orientation", + "type": "string" + }, + { + "default": true, + "help": "Display the current selected label next to the slider", + "name": "readout", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "SliderStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "SelectionRangeSliderModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "SelectionRangeSliderView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "SelectionSliderModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": [], + "help": "The labels for the options.", + "items": { + "type": "string" + }, + "name": "_options_labels", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "SelectionSliderView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "drag-tap", + "enum": ["drag-tap", "drag-snap", "tap", "drag", "snap"], + "help": "Slider dragging behavior.", + "name": "behavior", + "type": "string" + }, + { + "default": true, + "help": "Update the value of the widget as the user is holding the slider.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": 0, + "help": "Selected index", + "name": "index", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "horizontal", + "enum": ["horizontal", "vertical"], + "help": "Vertical or horizontal.", + "name": "orientation", + "type": "string" + }, + { + "default": true, + "help": "Display the current selected label next to the slider", + "name": "readout", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "SliderStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "SelectionSliderModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "SelectionSliderView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "SliderStyleModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/base", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "StyleView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Width of the description to the side of the control.", + "name": "description_width", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Color of the slider handle.", + "name": "handle_color", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "SliderStyleModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/base", + "name": "StyleView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "StackModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "StackView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "enum": ["success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the box.", + "name": "box_style", + "type": "string" + }, + { + "default": [], + "help": "List of widget children", + "items": { + "type": "reference", + "widget": "Widget" + }, + "name": "children", + "type": "array" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "The index of the selected page. This is either an integer selecting a particular sub-widget, or None to have no widgets selected.", + "name": "selected_index", + "type": "int" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "default": [], + "help": "Titles of the pages", + "items": { + "type": "string" + }, + "name": "titles", + "type": "array" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "StackModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "StackView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "TabModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "TabView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "enum": ["success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the box.", + "name": "box_style", + "type": "string" + }, + { + "default": [], + "help": "List of widget children", + "items": { + "type": "reference", + "widget": "Widget" + }, + "name": "children", + "type": "array" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "The index of the selected page. This is either an integer selecting a particular sub-widget, or None to have no widgets selected.", + "name": "selected_index", + "type": "int" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "default": [], + "help": "Titles of the pages", + "items": { + "type": "string" + }, + "name": "titles", + "type": "array" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "TabModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "TabView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "TagsInputModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "TagsInputView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": true, + "help": "", + "name": "allow_duplicates", + "type": "bool" + }, + { + "default": [], + "help": "", + "name": "allowed_tags", + "type": "array" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "\u200b", + "help": "", + "name": "placeholder", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "default": "", + "enum": ["primary", "success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the tags.", + "name": "tag_style", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": [], + "help": "List of string tags", + "name": "value", + "type": "array" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "TagsInputModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "TagsInputView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "TextModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "TextView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": true, + "help": "Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "\u200b", + "help": "Placeholder text to display when nothing has been typed", + "name": "placeholder", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "TextStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": "", + "help": "String value", + "name": "value", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "TextModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "TextView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "TextStyleModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/base", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "StyleView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Background specifications.", + "name": "background", + "type": "string" + }, + { + "default": "", + "help": "Width of the description to the side of the control.", + "name": "description_width", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Text font size.", + "name": "font_size", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Text color", + "name": "text_color", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "TextStyleModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/base", + "name": "StyleView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "TextareaModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "TextareaView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": true, + "help": "Update the value as the user types. If False, update on submission, e.g., pressing Enter or navigating away.", + "name": "continuous_update", + "type": "bool" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "\u200b", + "help": "Placeholder text to display when nothing has been typed", + "name": "placeholder", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "The number of rows to display.", + "name": "rows", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "TextStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": "", + "help": "String value", + "name": "value", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "TextareaModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "TextareaView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "TimeModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "TimeView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes.", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "max", + "type": "Time" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "min", + "type": "Time" + }, + { + "default": 60, + "help": "The time step to use for the picker, in seconds, or \"any\".", + "name": "step", + "type": ["float", "string"], + "union_attributes": [ + { + "type": "float" + }, + { + "enum": ["any"], + "type": "string" + } + ] + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "value", + "type": "Time" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "TimeModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "TimeView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ToggleButtonModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "ToggleButtonView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "enum": ["primary", "success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the button.", + "name": "button_style", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes.", + "name": "disabled", + "type": "bool" + }, + { + "default": "", + "help": "Font-awesome icon.", + "name": "icon", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "ToggleButtonStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": false, + "help": "Bool value", + "name": "value", + "type": "bool" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ToggleButtonModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "ToggleButtonView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ToggleButtonStyleModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/base", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "StyleView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Width of the description to the side of the control.", + "name": "description_width", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Toggle button text font family.", + "name": "font_family", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Toggle button text font size.", + "name": "font_size", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Toggle button text font style.", + "name": "font_style", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Toggle button text font variant.", + "name": "font_variant", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Toggle button text font weight.", + "name": "font_weight", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Toggle button text color", + "name": "text_color", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "Toggle button text decoration.", + "name": "text_decoration", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ToggleButtonStyleModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/base", + "name": "StyleView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ToggleButtonsModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": [], + "help": "The labels for the options.", + "items": { + "type": "string" + }, + "name": "_options_labels", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "ToggleButtonsView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "allow_none": true, + "default": "", + "enum": ["primary", "success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the buttons.", + "name": "button_style", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes", + "name": "disabled", + "type": "bool" + }, + { + "default": [], + "help": "Icons names for each button (FontAwesome names without the fa- prefix).", + "items": { + "type": "string" + }, + "name": "icons", + "type": "array" + }, + { + "allow_none": true, + "default": null, + "help": "Selected index", + "name": "index", + "type": "int" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "reference to new instance", + "help": "", + "name": "style", + "type": "reference", + "widget": "ToggleButtonsStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": [], + "help": "Tooltips for each button.", + "items": { + "type": "string" + }, + "name": "tooltips", + "type": "array" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ToggleButtonsModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "ToggleButtonsView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ToggleButtonsStyleModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/base", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "StyleView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "The width of each button.", + "name": "button_width", + "type": "string" + }, + { + "default": "", + "help": "Width of the description to the side of the control.", + "name": "description_width", + "type": "string" + }, + { + "default": "", + "help": "Text font weight of each button.", + "name": "font_weight", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ToggleButtonsStyleModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/base", + "name": "StyleView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "VBoxModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "VBoxView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "enum": ["success", "info", "warning", "danger", ""], + "help": "Use a predefined styling for the box.", + "name": "box_style", + "type": "string" + }, + { + "default": [], + "help": "List of widget children", + "items": { + "type": "reference", + "widget": "Widget" + }, + "name": "children", + "type": "array" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "VBoxModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "VBoxView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "ValidModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "ValidView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Accept HTML in the description.", + "name": "description_allow_html", + "type": "bool" + }, + { + "default": false, + "help": "Enable or disable user changes.", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "Invalid", + "help": "Message displayed when the value is False", + "name": "readout", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": false, + "help": "Bool value", + "name": "value", + "type": "bool" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "ValidModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "ValidView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "VideoModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "2.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "VideoView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": true, + "help": "When true, the video starts when it's displayed", + "name": "autoplay", + "type": "bool" + }, + { + "default": true, + "help": "Specifies that video controls should be displayed (such as a play/pause button etc)", + "name": "controls", + "type": "bool" + }, + { + "default": "mp4", + "help": "The format of the video.", + "name": "format", + "type": "string" + }, + { + "default": "", + "help": "Height of the video in pixels.", + "name": "height", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": true, + "help": "When true, the video will start from the beginning after finishing", + "name": "loop", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "default": "b''", + "help": "The media data as a memory view of bytes.", + "name": "value", + "type": "bytes" + }, + { + "default": "", + "help": "Width of the video in pixels.", + "name": "width", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "VideoModel", + "version": "2.0.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "VideoView", + "version": "2.0.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { + "type": "string" + }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/output", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "1.0.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "OutputModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/output", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "1.0.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "OutputView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "default": "", + "help": "Parent message id of messages to capture", + "name": "msg_id", + "type": "string" + }, + { + "default": [], + "help": "The output messages synced from the frontend.", + "items": { + "type": "object" + }, + "name": "outputs", + "type": "array" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + } + ], + "model": { + "module": "@jupyter-widgets/output", + "name": "OutputModel", + "version": "1.0.0" + }, + "view": { + "module": "@jupyter-widgets/output", + "name": "OutputView", + "version": "1.0.0" + } + } +] diff --git a/integrations/widgets/widgets-generator/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/AttributeSchema.kt b/integrations/widgets/widgets-generator/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/AttributeSchema.kt new file mode 100644 index 0000000..792ee19 --- /dev/null +++ b/integrations/widgets/widgets-generator/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/AttributeSchema.kt @@ -0,0 +1,76 @@ +package org.jetbrains.kotlinx.jupyter.widget.generator + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.decodeFromJsonElement +import kotlinx.serialization.json.encodeToJsonElement + +/** + * Represents the schema for a single widget attribute in `schema.json`. + */ +@Serializable +internal data class AttributeSchema( + val name: String, + val type: AttributeType, + val default: JsonElement, + @SerialName("allow_none") val allowNone: Boolean = false, + val enum: List = emptyList(), + val help: String = "", + val items: AttributeItems? = null, + val widget: String? = null, + @SerialName("union_attributes") val unionAttributes: List = emptyList(), +) + +@Serializable +internal data class AttributeItems( + val type: AttributeType, + val widget: String? = null, +) + +private object AttributeTypeSerializer { + fun serialize(type: AttributeType): JsonElement = + when (type) { + is AttributeType.Single -> JsonPrimitive(type.name) + is AttributeType.Union -> Json.encodeToJsonElement(type.options.map { serialize(it) }) + } +} + +@Serializable(with = AttributeType.Companion::class) +internal sealed class AttributeType { + data class Single( + val name: String, + ) : AttributeType() + + data class Union( + val options: List, + ) : AttributeType() + + companion object : KSerializer { + private val delegate = JsonElement.serializer() + + override val descriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): AttributeType = + when (val element = delegate.deserialize(decoder)) { + is JsonPrimitive -> Single(element.content) + else -> { + val options = Json.decodeFromJsonElement>(element) + Union(options.map { Single(it.content) }) + } + } + + override fun serialize( + encoder: Encoder, + value: AttributeType, + ) { + encoder.encodeSerializableValue(delegate, AttributeTypeSerializer.serialize(value)) + } + } +} diff --git a/integrations/widgets/widgets-generator/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/PropertyType.kt b/integrations/widgets/widgets-generator/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/PropertyType.kt new file mode 100644 index 0000000..a8c6342 --- /dev/null +++ b/integrations/widgets/widgets-generator/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/PropertyType.kt @@ -0,0 +1,633 @@ +package org.jetbrains.kotlinx.jupyter.widget.generator + +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonNull +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.booleanOrNull +import kotlinx.serialization.json.decodeFromJsonElement +import kotlinx.serialization.json.doubleOrNull +import kotlinx.serialization.json.intOrNull +import kotlin.reflect.KClass + +internal const val WIDGETS_PACKAGE: String = "org.jetbrains.kotlinx.jupyter.widget" +internal const val WIDGET_TYPES_PACKAGE: String = "$WIDGETS_PACKAGE.model.types" +internal const val WIDGET_LIBRARY_PACKAGE: String = "$WIDGETS_PACKAGE.library" + +private val typeArgumentsRegex = Regex("<.*>") + +private val assignedPropertyTypes = + listOf( + AssignedPropertyType("IntRangeSliderWidget", "value", IntRangePropertyType), + AssignedPropertyType("FloatRangeSliderWidget", "value", FloatRangePropertyType), + AssignedPropertyType("SelectionRangeSliderWidget", "index", IntRangePropertyType), + AssignedPropertyType("LinkWidget", "source", PairPropertyType(ReferencePropertyType("Widget"), StringPropertyType, "null to \"\"")), + AssignedPropertyType("LinkWidget", "target", PairPropertyType(ReferencePropertyType("Widget"), StringPropertyType, "null to \"\"")), + AssignedPropertyType( + "DirectionalLinkWidget", + "source", + PairPropertyType(ReferencePropertyType("Widget"), StringPropertyType, "null to \"\""), + ), + AssignedPropertyType( + "DirectionalLinkWidget", + "target", + PairPropertyType(ReferencePropertyType("Widget"), StringPropertyType, "null to \"\""), + ), + ).map { it.copy(widgetName = it.widgetName.toPascalCase()) } + +internal data class EnumInfo( + val className: String, + val values: List, +) + +/** + * Represents a property type in the widget generator. + * Maps Jupyter widget attributes to Kotlin types and property delegates. + */ +internal interface PropertyType { + val kotlinType: String + val typeExpression: String + val isNullable: Boolean + val imports: Set get() = emptySet() + val helperDeclarations: List get() = emptyList() + val isEnum: Boolean get() = false + val enumName: String get() = "" + val enumValues: List get() = emptyList() + val optionName: String + + fun getDefaultValueExpression(defaultValue: JsonElement): String + + val delegateName: String? get() = null + + val checkTypeExpression: String + get() { + val typeWithoutNullability = kotlinType.removeSuffix("?") + return typeWithoutNullability.replace(typeArgumentsRegex, "<*>") + } +} + +private open class BasicPropertyType( + override val kotlinType: String, + override val typeExpression: String, + override val imports: Set, + override val optionName: String = kotlinType, + val nonNullableDelegateName: String? = null, + val nullableDelegateName: String? = null, +) : PropertyType { + override val isNullable: Boolean get() = false + override val delegateName: String? get() = if (isNullable) nullableDelegateName else nonNullableDelegateName + + override fun getDefaultValueExpression(defaultValue: JsonElement): String = renderLiteral(kotlinType, defaultValue) +} + +private open class PrimitiveType( + kotlinType: String, + typeName: String, + nonNullableDelegateName: String? = null, + nullableDelegateName: String? = null, +) : BasicPropertyType( + kotlinType = kotlinType, + typeExpression = typeName, + imports = setOf("$WIDGET_TYPES_PACKAGE.primitive.$typeName"), + nonNullableDelegateName = nonNullableDelegateName, + nullableDelegateName = nullableDelegateName, + ) + +private object StringPropertyType : PrimitiveType( + kotlinType = "String", + typeName = "StringType", + nonNullableDelegateName = "stringProp", + nullableDelegateName = "nullableStringProp", +) + +private object BooleanPropertyType : PrimitiveType( + kotlinType = "Boolean", + typeName = "BooleanType", + nonNullableDelegateName = "boolProp", + nullableDelegateName = "nullableBoolProp", +) + +private object IntPropertyType : PrimitiveType( + kotlinType = "Int", + typeName = "IntType", + nonNullableDelegateName = "intProp", + nullableDelegateName = "nullableIntProp", +) { + override val checkTypeExpression: String get() = "Number" +} + +private object DoublePropertyType : PrimitiveType( + kotlinType = "Double", + typeName = "FloatType", + nonNullableDelegateName = "doubleProp", + nullableDelegateName = "nullableDoubleProp", +) { + override val checkTypeExpression: String get() = "Number" +} + +private object BytesPropertyType : PrimitiveType( + kotlinType = "ByteArray", + typeName = "BytesType", + nonNullableDelegateName = "bytesProp", +) { + override val optionName: String get() = "Bytes" +} + +private object AnyPropertyType : PrimitiveType( + kotlinType = "Any?", + typeName = "AnyType", +) { + override val isNullable: Boolean get() = true +} + +private object IntRangePropertyType : BasicPropertyType( + kotlinType = "IntRange", + typeExpression = "IntRangeType", + imports = setOf("$WIDGET_TYPES_PACKAGE.ranges.IntRangeType"), +) + +private object FloatRangePropertyType : BasicPropertyType( + kotlinType = "ClosedRange", + typeExpression = "FloatRangeType", + imports = setOf("$WIDGET_TYPES_PACKAGE.ranges.FloatRangeType"), +) + +private class PairPropertyType( + val first: PropertyType, + val second: PropertyType, + val defaultValue: String? = null, +) : PropertyType { + override val kotlinType: String get() = "Pair<${first.kotlinType}, ${second.kotlinType}>" + override val typeExpression: String get() = "PairType(${first.typeExpression}, ${second.typeExpression})" + override val isNullable: Boolean get() = false + override val imports: Set get() = first.imports + second.imports + "$WIDGET_TYPES_PACKAGE.compound.PairType" + override val helperDeclarations: List get() = first.helperDeclarations + second.helperDeclarations + override val optionName: String get() = "Pair" + + override fun getDefaultValueExpression(defaultValue: JsonElement): String = + this.defaultValue ?: "Pair(${first.getDefaultValueExpression(defaultValue)}, ${second.getDefaultValueExpression(defaultValue)})" +} + +private open class DatetimeBasePropertyType( + kotlinType: String, + typeName: String, + nonNullableDelegateName: String, + nullableDelegateName: String, + optionName: String, +) : BasicPropertyType( + kotlinType = kotlinType, + typeExpression = typeName, + imports = setOf("$WIDGET_TYPES_PACKAGE.datetime.$typeName"), + optionName = optionName, + nonNullableDelegateName = nonNullableDelegateName, + nullableDelegateName = nullableDelegateName, + ) + +private object DatetimePropertyType : DatetimeBasePropertyType( + kotlinType = "java.time.Instant", + typeName = "DatetimeType", + nonNullableDelegateName = "dateTimeProp", + nullableDelegateName = "nullableDateTimeProp", + optionName = "Datetime", +) + +private object DatePropertyType : DatetimeBasePropertyType( + kotlinType = "java.time.LocalDate", + typeName = "DateType", + nonNullableDelegateName = "dateProp", + nullableDelegateName = "nullableDateProp", + optionName = "Date", +) + +private object TimePropertyType : DatetimeBasePropertyType( + kotlinType = "java.time.LocalTime", + typeName = "TimeType", + nonNullableDelegateName = "timeProp", + nullableDelegateName = "nullableTimeProp", + optionName = "Time", +) + +private object RawObjectPropertyType : BasicPropertyType( + kotlinType = "Map", + typeExpression = "RawObjectType", + imports = setOf("$WIDGET_TYPES_PACKAGE.compound.RawObjectType"), + optionName = "Object", +) + +private class NullablePropertyType( + val inner: PropertyType, +) : PropertyType { + init { + require(!inner.isNullable) + } + + override val kotlinType: String get() = inner.kotlinType + "?" + override val typeExpression: String get() = "NullableType(${inner.typeExpression})" + override val isNullable: Boolean get() = true + override val optionName: String get() = inner.optionName + override val imports: Set get() = inner.imports + "$WIDGET_TYPES_PACKAGE.compound.NullableType" + override val helperDeclarations: List get() = inner.helperDeclarations + override val isEnum: Boolean get() = inner.isEnum + + override fun getDefaultValueExpression(defaultValue: JsonElement): String = inner.getDefaultValueExpression(defaultValue) + + override val delegateName: String? get() = (inner as? BasicPropertyType)?.nullableDelegateName +} + +private class ArrayPropertyType( + attribute: AttributeSchema, + json: Json, + enums: MutableMap, + namePrefix: String, +) : PropertyType { + private val elementType = + run { + val actualItems = attribute.items ?: AttributeItems(type = AttributeType.Single("any")) + val elementSchema = AttributeSchema(name = "item", type = actualItems.type, default = JsonNull, widget = actualItems.widget) + elementSchema.toPropertyType(json, enums, namePrefix) + } + + override val kotlinType: String get() = "List<${elementType.kotlinType}>" + override val typeExpression: String get() = "ArrayType(${elementType.typeExpression})" + override val isNullable: Boolean get() = false + override val optionName: String get() = "List" + override val imports: Set get() = elementType.imports + "$WIDGET_TYPES_PACKAGE.compound.ArrayType" + override val helperDeclarations: List get() = elementType.helperDeclarations + + override fun getDefaultValueExpression(defaultValue: JsonElement): String = defaultArrayValue(elementType.kotlinType, defaultValue) +} + +private class EnumPropertyType( + override val enumName: String, + override val enumValues: List, + defaultValue: JsonElement, +) : PropertyType { + private val defaultEntry = (defaultValue as? JsonPrimitive)?.content?.takeUnless { it == "null" } + + private val defaultExpression = + when { + defaultEntry == null || defaultEntry !in enumValues -> "null" + defaultEntry.isEmpty() -> "$enumName.Default" + else -> "$enumName.${defaultEntry.toPascalCase()}" + } + + private val typeDefaultExpression = + run { + val typeDefaultEntry = defaultEntry?.takeIf { it in enumValues } ?: enumValues.first() + val typeDefaultEntryName = typeDefaultEntry.ifEmpty { "Default" } + "$enumName.${typeDefaultEntryName.toPascalCase()}" + } + + override val kotlinType: String get() = "WidgetEnumEntry<$enumName>" + override val typeExpression: String get() = "WidgetEnumType($enumName, $typeDefaultExpression)" + override val isNullable: Boolean get() = false + override val isEnum: Boolean get() = true + override val optionName: String get() = enumName + override val imports: Set + get() = + setOf( + "$WIDGET_LIBRARY_PACKAGE.enums.$enumName", + "$WIDGET_TYPES_PACKAGE.enums.WidgetEnumEntry", + "$WIDGET_TYPES_PACKAGE.enums.WidgetEnumType", + ) + + override fun getDefaultValueExpression(defaultValue: JsonElement): String = defaultExpression +} + +private class ReferencePropertyType( + widget: String, + private val targetClass: String = + when (widget) { + "Widget" -> "WidgetModel" + "Axis" -> "ControllerAxisWidget" + else -> widget.toWidgetClassName() + }, +) : BasicPropertyType( + kotlinType = "$targetClass?", + typeExpression = "NullableType(WidgetReferenceType<$targetClass>())", + imports = + buildSet { + add("$WIDGET_TYPES_PACKAGE.compound.NullableType") + add("$WIDGET_TYPES_PACKAGE.widget.WidgetReferenceType") + if (targetClass == "WidgetModel") { + add("$WIDGETS_PACKAGE.model.WidgetModel") + } + }, + optionName = targetClass, + nonNullableDelegateName = "widgetProp", + nullableDelegateName = "nullableWidgetProp", + ) { + override val isNullable: Boolean get() = true + + override fun getDefaultValueExpression(defaultValue: JsonElement): String = + if ((defaultValue as? JsonPrimitive)?.content == "reference to new instance") { + "if (fromFrontend) null else widgetManager.${targetClass.toCamelCase().removeSuffix("Widget")}()" + } else { + "null" + } +} + +private fun getEnumObjectName( + enumValue: String, + enumName: String, +): String { + val entryName = if (enumValue.isEmpty()) "Default" else enumValue.toPascalCase() + return "$entryName$enumName" +} + +private class UnionPropertyType( + attribute: AttributeSchema, + json: Json, + enums: MutableMap, + namePrefix: String, +) : PropertyType { + private val name = attribute.name + private val unionName = "${namePrefix}${name.toPascalCase()}" + private val unionTypeName = "${unionName}Type" + private val options: List + private val optionNames: List + private val defaultValueExpression: String + + init { + val optionSchemas = + if (attribute.unionAttributes.isNotEmpty()) { + attribute.unionAttributes.map { json.decodeFromJsonElement(it.addMissingFields(attribute)) } + } else { + when (val t = attribute.type) { + is AttributeType.Single -> listOf(attribute.copy(type = t)) + is AttributeType.Union -> t.options.map { opt -> attribute.copy(type = opt) } + } + } + + options = optionSchemas.map { it.toPropertyType(json, enums, namePrefix, skipEnumRegistration = true) } + + val names = options.map { it.optionName + "Value" } + optionNames = + if (names.distinct().size == names.size) { + names + } else { + options.indices.map { "${names[it]}$it" } + } + + val firstOpt = options.first() + defaultValueExpression = + if (firstOpt is EnumPropertyType) { + val defaultEntry = (attribute.default as? JsonPrimitive)?.content?.takeUnless { it == "null" } + val entryName = + if (defaultEntry == null || defaultEntry !in firstOpt.enumValues) { + if (firstOpt.enumValues.isEmpty()) { + "Default" + } else { + firstOpt.enumValues + .first() + .ifEmpty { "Default" } + .toPascalCase() + } + } else { + defaultEntry.ifEmpty { "Default" }.toPascalCase() + } + "$unionName.$entryName${firstOpt.enumName}" + } else { + val firstOptionDefaultValue = firstOpt.getDefaultValueExpression(attribute.default) + "$unionName.${optionNames.first()}($firstOptionDefaultValue)" + } + } + + override val kotlinType: String get() = unionName + override val typeExpression: String get() = unionTypeName + override val isNullable: Boolean get() = false + override val optionName: String get() = "Union" + override val imports: Set get() = + options.flatMap { if (it is EnumPropertyType) emptySet() else it.imports }.toSet() + + "$WIDGET_TYPES_PACKAGE.compound.UnionType" + + override val helperDeclarations: List + get() { + val helpers = options.flatMap { if (it is EnumPropertyType) emptyList() else it.helperDeclarations }.toMutableList() + + val interfaceDeclaration = + buildString { + appendLine("public sealed interface $unionName {") + options.forEachIndexed { i, opt -> + if (opt is EnumPropertyType) { + opt.enumValues.forEach { enumValue -> + appendLine(" public object ${getEnumObjectName(enumValue, opt.enumName)} : $unionName") + } + } else { + appendLine( + " @JvmInline public value class ${optionNames[i]}(public val value: ${opt.kotlinType}) : $unionName", + ) + } + } + appendLine("}") + } + helpers.add(interfaceDeclaration) + + val typeVarNames = options.indices.map { i -> "${unionTypeName}_Option$i" } + options.forEachIndexed { i, opt -> + if (opt !is EnumPropertyType) { + helpers.add("private val ${typeVarNames[i]} = ${opt.typeExpression}") + } + } + + val serializer = + buildString { + appendLine("{ value, widgetManager ->") + appendLine(" when (value) {") + options.forEachIndexed { i, opt -> + if (opt is EnumPropertyType) { + opt.enumValues.forEach { enumValue -> + appendLine(" is $unionName.${getEnumObjectName(enumValue, opt.enumName)} -> \"$enumValue\"") + } + } else { + appendLine( + " is $unionName.${optionNames[i]} -> ${typeVarNames[i]}.serialize(value.value, widgetManager)", + ) + } + } + appendLine(" }") + append(" }") + } + + val deserializers = + options.indices.joinToString(",\n") { i -> + val opt = options[i] + if (opt is EnumPropertyType) { + val cases = + opt.enumValues.joinToString("\n") { enumValue -> + "\"$enumValue\" -> $unionName.${getEnumObjectName(enumValue, opt.enumName)}" + } + $$""" + | { patch, _ -> + | when (patch) { + | $$cases + | else -> throw Exception("Unknown enum value: $patch") + | } + | } + """.trimMargin() + } else { + " { patch, widgetManager -> $unionName.${optionNames[i]}(${typeVarNames[i]}.deserialize(patch, widgetManager)) }" + } + } + + val unionDeclaration = + """ + |private val $unionTypeName = UnionType<$unionName>( + | name = "$name", + | default = $defaultValueExpression, + | serializer = $serializer, + | deserializers = listOf( + |$deserializers + | ), + |) + """.trimMargin() + helpers.add(unionDeclaration) + return helpers + } + + override fun getDefaultValueExpression(defaultValue: JsonElement): String = defaultValueExpression +} + +/** + * Converts an [AttributeSchema] to a [PropertyType]. + * This involves determining the appropriate Kotlin type, default value, and imports. + * + * @param json The [Json] instance for decoding type attributes. + * @param enums A map to collect enum definitions discovered during conversion. + * @param namePrefix Prefix for generated union class names (usually the widget class name). + * @param skipEnumRegistration If true, discovered enums won't be added to [enums]. + */ +internal fun AttributeSchema.toPropertyType( + json: Json, + enums: MutableMap, + namePrefix: String, + skipEnumRegistration: Boolean = false, +): PropertyType { + val isNullable = allowNone + + assignedPropertyTypes + .find { it.widgetName == namePrefix && it.attributeName == name } + ?.let { return it.propertyType.asNullable() } + + val baseType = + when (type) { + is AttributeType.Single -> { + if (enum.isNotEmpty()) { + val enumName = name.toPascalCase() + if (!skipEnumRegistration) { + enums.getOrPut(enumName) { EnumInfo(enumName, enum) }.also { + if (it.values != enum) error("Enum conflict for $enumName") + } + } + EnumPropertyType(enumName, enum, default) + } else { + when (type.name) { + "string" -> StringPropertyType + "bool" -> BooleanPropertyType + "int" -> IntPropertyType + "float" -> DoublePropertyType + "bytes" -> BytesPropertyType + "any" -> AnyPropertyType + "Datetime" -> DatetimePropertyType + "Date" -> DatePropertyType + "Time" -> TimePropertyType + "reference" -> ReferencePropertyType(widget ?: error("Reference widget is not specified")) + "object" -> RawObjectPropertyType + "array" -> ArrayPropertyType(this, json, enums, namePrefix) + else -> error("Unsupported type ${type.name}") + } + } + } + is AttributeType.Union -> UnionPropertyType(this, json, enums, namePrefix) + } + if (isNullable) { + return baseType.asNullable() + } + return baseType +} + +private fun JsonObject.addMissingFields(base: AttributeSchema): JsonObject { + val newMap = toMutableMap() + if ("name" !in newMap) newMap["name"] = JsonPrimitive(base.name) + if ("default" !in newMap) newMap["default"] = base.default + if ("help" !in newMap) newMap["help"] = JsonPrimitive(base.help) + return JsonObject(newMap) +} + +private fun PropertyType.asNullable(): PropertyType = if (isNullable) this else NullablePropertyType(this) + +private fun renderLiteral( + kotlinType: String, + value: JsonElement, +): String { + val isNullable = kotlinType.endsWith("?") + return when { + value is JsonNull -> "null" + kotlinType == "IntRange" -> { + renderRangeLiteral(value, Int::class) + } + kotlinType == "ClosedRange" -> { + renderRangeLiteral(value, Double::class) + } + kotlinType.startsWith("ByteArray") -> "byteArrayOf()" + kotlinType.startsWith("Map<") -> { + if (isNullable) "null" else "emptyMap()" + } + value is JsonPrimitive -> { + if (value.isString) { + val quoted = + value.content + .replace("\\", "\\\\") + .replace("\"", "\\\"") + "\"$quoted\"" + } else { + val primitiveValue = + value.booleanOrNull + ?: value.intOrNull + ?: value.doubleOrNull + ?: error("Unsupported primitive value for $kotlinType: $value") + val rendered = primitiveValue.toString() + if (kotlinType == "Double" && "." !in rendered) "$rendered.0" else rendered + } + } + else -> error("Unsupported literal for $kotlinType: $value") + } +} + +private fun defaultArrayValue( + elementKotlinType: String, + value: JsonElement, +): String = + if (value is JsonArray && value.isNotEmpty()) { + val renderedItems = value.joinToString(", ") { renderLiteral(elementKotlinType, it) } + "listOf($renderedItems)" + } else { + "emptyList()" + } + +private fun renderRangeLiteral( + jsonValue: JsonElement, + rangeEndType: KClass<*>, +): String { + fun renderElement(element: JsonElement): String = + when (rangeEndType) { + Int::class -> element.toString() + Double::class -> element.toString().let { if ("." !in it) "$it.0" else it } + else -> error("Unsupported range end type: $rangeEndType") + } + + return if (jsonValue is JsonArray && jsonValue.size == 2) { + "${renderElement(jsonValue[0])}..${renderElement(jsonValue[1])}" + } else { + val renderedElement = renderElement(JsonPrimitive(0)) + "$renderedElement..$renderedElement" + } +} + +private data class AssignedPropertyType( + val widgetName: String, + val attributeName: String, + val propertyType: PropertyType, +) diff --git a/integrations/widgets/widgets-generator/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/StringUtil.kt b/integrations/widgets/widgets-generator/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/StringUtil.kt new file mode 100644 index 0000000..b5a9c6e --- /dev/null +++ b/integrations/widgets/widgets-generator/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/StringUtil.kt @@ -0,0 +1,94 @@ +package org.jetbrains.kotlinx.jupyter.widget.generator + +private val commonAbbreviations: Set = + setOf( + "html", + "dom", + ) + +/** + * Ensures that a widget name ends with "Widget" and converts it to PascalCase. + */ +internal fun String.toWidgetClassName(): String = (if (endsWith("Widget")) this else "${this}Widget").toPascalCase() + +/** + * Converts a string to PascalCase, taking into account common abbreviations and delimiters. + */ +internal fun String.toPascalCase(): String { + val parts = splitIntoParts() + if (parts.isEmpty()) return this + + return parts.joinToString("") { part -> + part.toPascalCasePart() + } +} + +/** + * Converts a string to camelCase, taking into account common abbreviations and delimiters. + */ +internal fun String.toCamelCase(): String { + val parts = splitIntoParts() + if (parts.isEmpty()) return this + + return buildString { + append(parts[0].lowercase()) + for (i in 1 until parts.size) { + append(parts[i].toPascalCasePart()) + } + } +} + +/** + * Splits a string into parts based on common delimiters (undescore, hyphen, space) + * or by detecting transitions between lowercase and uppercase letters (PascalCase/camelCase). + * Abbreviations are treated as separate parts. + */ +private fun String.splitIntoParts(): List { + if (isEmpty()) return emptyList() + + val parts = mutableListOf() + val currentPart = StringBuilder() + + var i = 0 + while (i < length) { + val c = this[i] + if (c == '_' || c == '-' || c == ' ') { + if (currentPart.isNotEmpty()) { + parts.add(currentPart.toString()) + currentPart.clear() + } + i++ + continue + } + + // Check for common abbreviations + val abbreviation = commonAbbreviations.find { regionMatches(i, it, 0, it.length, ignoreCase = true) } + if (abbreviation != null) { + if (currentPart.isNotEmpty()) { + parts.add(currentPart.toString()) + currentPart.clear() + } + parts.add(abbreviation) + i += abbreviation.length + continue + } + + // Detect PascalCase/camelCase transitions + if (c.isUpperCase() && currentPart.isNotEmpty()) { + val last = currentPart.last() + if (!last.isUpperCase() || (i + 1 < length && this[i + 1].isLowerCase())) { + parts.add(currentPart.toString()) + currentPart.clear() + } + } + + currentPart.append(c) + i++ + } + if (currentPart.isNotEmpty()) { + parts.add(currentPart.toString()) + } + return parts +} + +private fun String.toPascalCasePart(): String = lowercase().replaceFirstChar { it.uppercase() } diff --git a/integrations/widgets/widgets-generator/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/WidgetGenerator.kt b/integrations/widgets/widgets-generator/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/WidgetGenerator.kt new file mode 100644 index 0000000..e772a73 --- /dev/null +++ b/integrations/widgets/widgets-generator/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/WidgetGenerator.kt @@ -0,0 +1,414 @@ +package org.jetbrains.kotlinx.jupyter.widget.generator + +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import java.nio.file.Files +import java.nio.file.Path +import kotlin.io.path.createDirectories +import kotlin.io.path.div +import kotlin.io.path.exists +import kotlin.io.path.readText +import kotlin.io.path.writeText + +private const val GENERATED_NOTICE = """// Generated by widgets-generator. Do not edit manually.""" + +private val hiddenAttributeNames = + setOf( + "_model_name", + "_model_module", + "_model_module_version", + "_view_name", + "_view_module", + "_view_module_version", + ) + +private data class TraitInfo( + val baseClassName: String, + val traitProperties: Map, + val import: String? = null, +) + +private data class OptionWidgetTraitInfo( + val baseClassName: String, + val indexType: String, +) + +private fun OptionWidgetTraitInfo.toTraitInfo(): TraitInfo = + TraitInfo( + baseClassName = baseClassName, + traitProperties = + mapOf( + "_options_labels" to "List", + "index" to indexType, + ), + import = "$WIDGETS_PACKAGE.library.options.$baseClassName", + ) + +private val traits: List = + listOf( + OptionWidgetTraitInfo( + baseClassName = "SingleNullableSelectionWidgetBase", + indexType = "Int?", + ), + OptionWidgetTraitInfo( + baseClassName = "SingleSelectionWidgetBase", + indexType = "Int", + ), + OptionWidgetTraitInfo( + baseClassName = "MultipleSelectionWidgetBase", + indexType = "List", + ), + OptionWidgetTraitInfo( + baseClassName = "SelectionRangeWidgetBase", + indexType = "IntRange?", + ), + ).map { it.toTraitInfo() } + +private val baseWidgets = setOf("OutputWidget") + +@Serializable +private data class WidgetSchema( + val attributes: List, + val model: WidgetTypeSchema, + val view: WidgetTypeSchema, +) + +@Serializable +private data class WidgetTypeSchema( + val module: String, + val name: String?, + val version: String, +) + +/** + * Main entry point for the widget generator. + */ +public fun main() { + val projectRoot = + Path + .of(".") + .toAbsolutePath() + .normalize() + .parent + ?.parent + ?.parent + ?: error("Unable to resolve project root") + + val generator = WidgetGenerator(projectRoot) + generator.generate() +} + +/** + * Handles the generation of Kotlin widget models from a JSON schema. + * It produces: + * 1. Widget classes with property delegation for state sync. + * 2. Enum objects for widget-specific enums. + * 3. A registry of all default widget factories. + * 4. Global helper functions for widget creation in Jupyter notebooks. + */ +private class WidgetGenerator( + projectRoot: Path, +) { + private val json = Json { ignoreUnknownKeys = true } + + private val schemaPath = projectRoot / "integrations/widgets/widgets-generator/schema.json" + private val apiOutput = projectRoot / "integrations/widgets/widgets-api/src/generated/kotlin" + private val jupyterOutput = projectRoot / "integrations/widgets/widgets-jupyter/src/generated/kotlin" + private val enums = mutableMapOf() + + /** + * Executes the generation process. + */ + fun generate() { + val schemaText = schemaPath.readText() + val widgets = json.decodeFromString>(schemaText) + + recreateDirectory(apiOutput) + recreateDirectory(jupyterOutput) + + val widgetInfos = widgets.map { it.toInfo() } + for (widgetInfo in widgetInfos) { + generateWidgetFile(widgetInfo) + } + generateEnumFiles() + generateFactoryRegistry(widgetInfos) + generateJupyterHelpers(widgetInfos) + } + + private fun WidgetSchema.toInfo(): WidgetInfo { + val baseName = + model.name?.removeSuffix("Model") + ?: view.name?.removeSuffix("View") + ?: error("Either model or view name must be specified") + val classNamePrefix = baseName.toWidgetClassName() + + val isBaseWidget = classNamePrefix in baseWidgets + val className = if (isBaseWidget) "${classNamePrefix}Base" else classNamePrefix + + val functionName = baseName.toCamelCase() + return WidgetInfo(className, functionName, isBaseWidget, this) + } + + /** + * Generates a single Kotlin file for a widget class. + */ + private fun generateWidgetFile(info: WidgetInfo) { + val packageName = "$WIDGETS_PACKAGE.library" + val filePath = apiOutput / packageName.replace('.', '/') / "${info.className}.kt" + filePath.parent.createDirectories() + + val attributeProperties = + info.schema.attributes.associate { + it.name to it.toPropertyType(json, enums, info.className) + } + val trait = + traits.find { trait -> + trait.traitProperties.all { (name, type) -> + val attrType = attributeProperties[name] ?: return@all false + type == null || attrType.kotlinType == type + } + } + + val imports = + sortedSetOf().apply { + for (importName in listOf( + "WidgetManager", + "model.DefaultWidgetFactory", + "model.DefaultWidgetModel", + "model.WidgetSpec", + "model.createAndRegisterWidget", + )) { + add("$WIDGETS_PACKAGE.$importName") + } + } + + val helperDeclarations = mutableListOf() + val properties = + info.schema.attributes.mapNotNull { attribute -> + if (attribute.name in hiddenAttributeNames) return@mapNotNull null + if (trait != null && attribute.name in trait.traitProperties) return@mapNotNull null + val propertyType = attributeProperties[attribute.name]!! + createProperty(attribute, propertyType, helperDeclarations, imports) + } + + val specName = "${info.functionName}Spec" + val specVisibility = if (info.isBaseWidget) "internal" else "private" + val spec = + buildString { + appendLine("$specVisibility val $specName = WidgetSpec(") + + fun addArgument( + name: String, + value: String?, + ) { + appendLine(" $name = ${value?.let { "\"$it\"" } ?: "null"},") + } + + addArgument("modelName", info.schema.model.name) + addArgument("modelModule", info.schema.model.module) + addArgument("modelModuleVersion", info.schema.model.version) + addArgument("viewName", info.schema.view.name) + addArgument("viewModule", info.schema.view.module) + addArgument("viewModuleVersion", info.schema.view.version) + appendLine(")") + appendLine() + + if (!info.isBaseWidget) { + appendLine( + "public fun WidgetManager.${info.functionName}" + + "(setup: ${info.className}.() -> Unit = {}): ${info.className} =\n" + + " createAndRegisterWidget(${info.className}.Factory).apply(setup)\n", + ) + } + } + + val body = + buildString { + val abstractModifier = if (info.isBaseWidget) "abstract " else "" + val superClassName = trait?.baseClassName ?: "DefaultWidgetModel" + if (trait?.import != null) { + imports.add(trait.import) + } + + appendLine("public ${abstractModifier}class ${info.className} internal constructor(") + appendLine(" widgetManager: WidgetManager,") + appendLine(" fromFrontend: Boolean,") + appendLine(") : $superClassName($specName, widgetManager) {") + if (!info.isBaseWidget) { + appendLine(" internal object Factory : DefaultWidgetFactory<${info.className}>($specName, ::${info.className})") + } + + for (property in properties) { + appendLine(property) + } + + appendLine("}") + } + + val header = + buildString { + addHeader(packageName) + if (imports.isNotEmpty()) { + for (import in imports) { + appendLine("import $import") + } + appendLine() + } + + for (declaration in helperDeclarations) { + appendLine(declaration) + appendLine() + } + } + + filePath.writeText(header + spec + body) + } + + /** + * Creates a property declaration string for a widget attribute. + */ + private fun createProperty( + attribute: AttributeSchema, + propertyType: PropertyType, + helperDeclarations: MutableList, + imports: MutableSet, + ): String { + imports.addAll(propertyType.imports) + helperDeclarations.addAll(propertyType.helperDeclarations) + + val propertyName = attribute.name.toCamelCase() + val kotlinType = propertyType.kotlinType + val defaultValueExpression = propertyType.getDefaultValueExpression(attribute.default) + + val delegateName = propertyType.delegateName ?: "prop" + val typeExpressionArgument = if (propertyType.delegateName == null) ", " + propertyType.typeExpression else "" + val delegateCall = "$delegateName(\"${attribute.name}\"$typeExpressionArgument, $defaultValueExpression)" + + return buildString { + val help = attribute.help + if (help.isNotEmpty()) { + appendLine() + appendLine(" /**") + appendLine(" * $help") + appendLine(" */") + } + append(" public var $propertyName: $kotlinType by $delegateCall") + } + } + + private fun generateEnumFiles() { + val packageName = "$WIDGET_LIBRARY_PACKAGE.enums" + val directory = apiOutput / packageName.replace('.', '/') + directory.createDirectories() + + for (enumInfo in enums.values) { + val filePath = directory / "${enumInfo.className}.kt" + val builder = StringBuilder() + builder.addHeader(packageName) + builder.appendLine("import $WIDGET_TYPES_PACKAGE.enums.WidgetEnum") + builder.appendLine("import $WIDGET_TYPES_PACKAGE.enums.WidgetEnumEntry") + builder.appendLine() + + val entries = + enumInfo.values.joinToString("\n") { value -> + val entryName = if (value.isEmpty()) "Default" else value.toPascalCase() + " public val $entryName: WidgetEnumEntry<${enumInfo.className}> by entry(\"$value\")" + } + + builder.appendLine("public object ${enumInfo.className} : WidgetEnum<${enumInfo.className}>() {") + builder.appendLine(entries) + builder.appendLine("}") + + filePath.writeText(builder.toString()) + } + } + + /** + * Generates `DefaultWidgetFactories.kt` with a list of all registered widget factories. + */ + private fun generateFactoryRegistry(widgetInfos: List) { + val packageName = "$WIDGET_LIBRARY_PACKAGE.registry" + val filePath = apiOutput / packageName.replace('.', '/') / "DefaultWidgetFactories.kt" + filePath.parent.createDirectories() + + val registryInfos = widgetInfos.filter { !it.isBaseWidget } + val sortedInfos = registryInfos.sortedInImportsOrder { it.className } + val content = + buildString { + addHeader(packageName) + for (info in sortedInfos) { + appendLine("import $WIDGET_LIBRARY_PACKAGE.${info.className}") + } + appendLine("import $WIDGETS_PACKAGE.model.WidgetFactory") + appendLine() + appendLine("internal val defaultWidgetFactories = listOf>(") + for (info in sortedInfos) { + appendLine(" ${info.className}.Factory,") + } + appendLine(")") + } + + filePath.writeText(content) + } + + private fun generateJupyterHelpers(widgetInfos: List) { + val packageName = "$WIDGETS_PACKAGE.integration" + val filePath = jupyterOutput / packageName.replace('.', '/') / "JupyterWidgetLibrary.kt" + filePath.parent.createDirectories() + + val helperInfos = widgetInfos.filter { !it.isBaseWidget } + val sortedInfos = helperInfos.sortedInImportsOrder { it.functionName } + val content = + buildString { + addHeader(packageName) + for (info in helperInfos.sortedInImportsOrder { it.className }) { + appendLine("import $WIDGET_LIBRARY_PACKAGE.${info.className}") + } + for (info in sortedInfos) { + appendLine("import $WIDGET_LIBRARY_PACKAGE.${info.functionName}") + } + appendLine() + for (info in sortedInfos) { + val functionName = info.functionName.removeSuffix("Widget") + "Widget" + appendLine( + "public fun $functionName(setup: ${info.className}.() -> Unit = {}): ${info.className} = globalWidgetManager.${info.functionName}(setup)", + ) + appendLine() + } + } + + filePath.writeText(content) + } + + private fun StringBuilder.addHeader(packageName: String) { + appendLine(GENERATED_NOTICE) + appendLine("package $packageName") + appendLine() + } + + private fun List.sortedInImportsOrder(representAsString: (T) -> String): List = + sortedWith { a, b -> + when { + representAsString(a).startsWith(representAsString(b)) -> 1 + representAsString(b).startsWith(representAsString(a)) -> -1 + else -> representAsString(a).compareTo(representAsString(b)) + } + } + + private fun recreateDirectory(path: Path) { + if (path.exists()) { + Files + .walk(path) + .sorted(Comparator.reverseOrder()) + .forEach(Files::delete) + } + path.createDirectories() + } +} + +private data class WidgetInfo( + val className: String, + val functionName: String, + val isBaseWidget: Boolean, + val schema: WidgetSchema, +) diff --git a/integrations/widgets/widgets-generator/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/StringUtilTest.kt b/integrations/widgets/widgets-generator/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/StringUtilTest.kt new file mode 100644 index 0000000..6e4d35f --- /dev/null +++ b/integrations/widgets/widgets-generator/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/generator/StringUtilTest.kt @@ -0,0 +1,34 @@ +package org.jetbrains.kotlinx.jupyter.widget.generator + +import io.kotest.matchers.shouldBe +import kotlin.test.Test + +class StringUtilTest { + @Test + fun `toPascalCase should handle various delimiters and abbreviations`() { + "html_style_widget".toPascalCase() shouldBe "HtmlStyleWidget" + "HTMLStyleWidget".toPascalCase() shouldBe "HtmlStyleWidget" + "html-style-widget".toPascalCase() shouldBe "HtmlStyleWidget" + "html style widget".toPascalCase() shouldBe "HtmlStyleWidget" + "html".toPascalCase() shouldBe "Html" + "DOM".toPascalCase() shouldBe "Dom" + "vbox_widget".toPascalCase() shouldBe "VboxWidget" + "hbox_widget".toPascalCase() shouldBe "HboxWidget" + "VBoxModel".toPascalCase() shouldBe "VBoxModel" + } + + @Test + fun `toCamelCase should handle various delimiters and abbreviations`() { + "HTMLStyleWidget".toCamelCase() shouldBe "htmlStyleWidget" + "DOMWidget".toCamelCase() shouldBe "domWidget" + "vbox".toCamelCase() shouldBe "vbox" + "hbox_widget".toCamelCase() shouldBe "hboxWidget" + "VBoxModel".toCamelCase() shouldBe "vBoxModel" + } + + @Test + fun `toCamelCase and toPascalCase should be independent`() { + "html_style_widget".toCamelCase() shouldBe "htmlStyleWidget" + "html-style-widget".toCamelCase() shouldBe "htmlStyleWidget" + } +} diff --git a/integrations/widgets/widgets-jupyter/build.gradle.kts b/integrations/widgets/widgets-jupyter/build.gradle.kts new file mode 100644 index 0000000..371d2e4 --- /dev/null +++ b/integrations/widgets/widgets-jupyter/build.gradle.kts @@ -0,0 +1,35 @@ +plugins { + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.publisher) + alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.kotlin.jupyter.api) +} + +dependencies { + api(projects.integrations.widgets.widgetsApi) +} + +kotlin { + jvmToolchain( + libs.versions.jvm.toolchain + .get() + .toInt(), + ) + explicitApi() +} + +sourceSets { + main { + kotlin.srcDir("src/generated/kotlin") + } +} + +tasks.processJupyterApiResources { + libraryProducers = listOf("org.jetbrains.kotlinx.jupyter.widget.integration.WidgetJupyterIntegration") +} + +kotlinPublications { + publication { + description.set("Kotlin Jupyter kernel integration for IPython Widgets") + } +} diff --git a/integrations/widgets/widgets-jupyter/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/integration/JupyterWidgetLibrary.kt b/integrations/widgets/widgets-jupyter/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/integration/JupyterWidgetLibrary.kt new file mode 100644 index 0000000..2351637 --- /dev/null +++ b/integrations/widgets/widgets-jupyter/src/generated/kotlin/org/jetbrains/kotlinx/jupyter/widget/integration/JupyterWidgetLibrary.kt @@ -0,0 +1,276 @@ +// Generated by widgets-generator. Do not edit manually. +package org.jetbrains.kotlinx.jupyter.widget.integration + +import org.jetbrains.kotlinx.jupyter.widget.library.AccordionWidget +import org.jetbrains.kotlinx.jupyter.widget.library.AudioWidget +import org.jetbrains.kotlinx.jupyter.widget.library.BoundedFloatTextWidget +import org.jetbrains.kotlinx.jupyter.widget.library.BoundedIntTextWidget +import org.jetbrains.kotlinx.jupyter.widget.library.BoxWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ButtonStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ButtonWidget +import org.jetbrains.kotlinx.jupyter.widget.library.CheckboxStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.CheckboxWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ColorPickerWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ColorsInputWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ComboboxWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ControllerAxisWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ControllerButtonWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ControllerWidget +import org.jetbrains.kotlinx.jupyter.widget.library.DatePickerWidget +import org.jetbrains.kotlinx.jupyter.widget.library.DatetimeWidget +import org.jetbrains.kotlinx.jupyter.widget.library.DescriptionStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.DirectionalLinkWidget +import org.jetbrains.kotlinx.jupyter.widget.library.DomWidget +import org.jetbrains.kotlinx.jupyter.widget.library.DropdownWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FileUploadWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FloatLogSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FloatProgressWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FloatRangeSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FloatSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FloatTextWidget +import org.jetbrains.kotlinx.jupyter.widget.library.FloatsInputWidget +import org.jetbrains.kotlinx.jupyter.widget.library.GridBoxWidget +import org.jetbrains.kotlinx.jupyter.widget.library.HBoxWidget +import org.jetbrains.kotlinx.jupyter.widget.library.HtmlMathStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.HtmlMathWidget +import org.jetbrains.kotlinx.jupyter.widget.library.HtmlStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.HtmlWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ImageWidget +import org.jetbrains.kotlinx.jupyter.widget.library.IntProgressWidget +import org.jetbrains.kotlinx.jupyter.widget.library.IntRangeSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.IntSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.IntTextWidget +import org.jetbrains.kotlinx.jupyter.widget.library.IntsInputWidget +import org.jetbrains.kotlinx.jupyter.widget.library.LabelStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.LabelWidget +import org.jetbrains.kotlinx.jupyter.widget.library.LayoutWidget +import org.jetbrains.kotlinx.jupyter.widget.library.LinkWidget +import org.jetbrains.kotlinx.jupyter.widget.library.NaiveDatetimeWidget +import org.jetbrains.kotlinx.jupyter.widget.library.PasswordWidget +import org.jetbrains.kotlinx.jupyter.widget.library.PlayWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ProgressStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.RadioButtonsWidget +import org.jetbrains.kotlinx.jupyter.widget.library.SelectMultipleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.SelectWidget +import org.jetbrains.kotlinx.jupyter.widget.library.SelectionRangeSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.SelectionSliderWidget +import org.jetbrains.kotlinx.jupyter.widget.library.SliderStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.StackWidget +import org.jetbrains.kotlinx.jupyter.widget.library.TabWidget +import org.jetbrains.kotlinx.jupyter.widget.library.TagsInputWidget +import org.jetbrains.kotlinx.jupyter.widget.library.TextStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.TextWidget +import org.jetbrains.kotlinx.jupyter.widget.library.TextareaWidget +import org.jetbrains.kotlinx.jupyter.widget.library.TimeWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ToggleButtonStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ToggleButtonWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ToggleButtonsStyleWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ToggleButtonsWidget +import org.jetbrains.kotlinx.jupyter.widget.library.VBoxWidget +import org.jetbrains.kotlinx.jupyter.widget.library.ValidWidget +import org.jetbrains.kotlinx.jupyter.widget.library.VideoWidget +import org.jetbrains.kotlinx.jupyter.widget.library.accordion +import org.jetbrains.kotlinx.jupyter.widget.library.audio +import org.jetbrains.kotlinx.jupyter.widget.library.boundedFloatText +import org.jetbrains.kotlinx.jupyter.widget.library.boundedIntText +import org.jetbrains.kotlinx.jupyter.widget.library.box +import org.jetbrains.kotlinx.jupyter.widget.library.button +import org.jetbrains.kotlinx.jupyter.widget.library.buttonStyle +import org.jetbrains.kotlinx.jupyter.widget.library.checkbox +import org.jetbrains.kotlinx.jupyter.widget.library.checkboxStyle +import org.jetbrains.kotlinx.jupyter.widget.library.colorPicker +import org.jetbrains.kotlinx.jupyter.widget.library.colorsInput +import org.jetbrains.kotlinx.jupyter.widget.library.combobox +import org.jetbrains.kotlinx.jupyter.widget.library.controller +import org.jetbrains.kotlinx.jupyter.widget.library.controllerAxis +import org.jetbrains.kotlinx.jupyter.widget.library.controllerButton +import org.jetbrains.kotlinx.jupyter.widget.library.datePicker +import org.jetbrains.kotlinx.jupyter.widget.library.datetime +import org.jetbrains.kotlinx.jupyter.widget.library.descriptionStyle +import org.jetbrains.kotlinx.jupyter.widget.library.directionalLink +import org.jetbrains.kotlinx.jupyter.widget.library.domWidget +import org.jetbrains.kotlinx.jupyter.widget.library.dropdown +import org.jetbrains.kotlinx.jupyter.widget.library.fileUpload +import org.jetbrains.kotlinx.jupyter.widget.library.floatLogSlider +import org.jetbrains.kotlinx.jupyter.widget.library.floatProgress +import org.jetbrains.kotlinx.jupyter.widget.library.floatRangeSlider +import org.jetbrains.kotlinx.jupyter.widget.library.floatSlider +import org.jetbrains.kotlinx.jupyter.widget.library.floatText +import org.jetbrains.kotlinx.jupyter.widget.library.floatsInput +import org.jetbrains.kotlinx.jupyter.widget.library.gridBox +import org.jetbrains.kotlinx.jupyter.widget.library.hBox +import org.jetbrains.kotlinx.jupyter.widget.library.html +import org.jetbrains.kotlinx.jupyter.widget.library.htmlMath +import org.jetbrains.kotlinx.jupyter.widget.library.htmlMathStyle +import org.jetbrains.kotlinx.jupyter.widget.library.htmlStyle +import org.jetbrains.kotlinx.jupyter.widget.library.image +import org.jetbrains.kotlinx.jupyter.widget.library.intProgress +import org.jetbrains.kotlinx.jupyter.widget.library.intRangeSlider +import org.jetbrains.kotlinx.jupyter.widget.library.intSlider +import org.jetbrains.kotlinx.jupyter.widget.library.intText +import org.jetbrains.kotlinx.jupyter.widget.library.intsInput +import org.jetbrains.kotlinx.jupyter.widget.library.label +import org.jetbrains.kotlinx.jupyter.widget.library.labelStyle +import org.jetbrains.kotlinx.jupyter.widget.library.layout +import org.jetbrains.kotlinx.jupyter.widget.library.link +import org.jetbrains.kotlinx.jupyter.widget.library.naiveDatetime +import org.jetbrains.kotlinx.jupyter.widget.library.password +import org.jetbrains.kotlinx.jupyter.widget.library.play +import org.jetbrains.kotlinx.jupyter.widget.library.progressStyle +import org.jetbrains.kotlinx.jupyter.widget.library.radioButtons +import org.jetbrains.kotlinx.jupyter.widget.library.select +import org.jetbrains.kotlinx.jupyter.widget.library.selectMultiple +import org.jetbrains.kotlinx.jupyter.widget.library.selectionRangeSlider +import org.jetbrains.kotlinx.jupyter.widget.library.selectionSlider +import org.jetbrains.kotlinx.jupyter.widget.library.sliderStyle +import org.jetbrains.kotlinx.jupyter.widget.library.stack +import org.jetbrains.kotlinx.jupyter.widget.library.tab +import org.jetbrains.kotlinx.jupyter.widget.library.tagsInput +import org.jetbrains.kotlinx.jupyter.widget.library.text +import org.jetbrains.kotlinx.jupyter.widget.library.textStyle +import org.jetbrains.kotlinx.jupyter.widget.library.textarea +import org.jetbrains.kotlinx.jupyter.widget.library.time +import org.jetbrains.kotlinx.jupyter.widget.library.toggleButton +import org.jetbrains.kotlinx.jupyter.widget.library.toggleButtonStyle +import org.jetbrains.kotlinx.jupyter.widget.library.toggleButtons +import org.jetbrains.kotlinx.jupyter.widget.library.toggleButtonsStyle +import org.jetbrains.kotlinx.jupyter.widget.library.vBox +import org.jetbrains.kotlinx.jupyter.widget.library.valid +import org.jetbrains.kotlinx.jupyter.widget.library.video + +public fun accordionWidget(setup: AccordionWidget.() -> Unit = {}): AccordionWidget = globalWidgetManager.accordion(setup) + +public fun audioWidget(setup: AudioWidget.() -> Unit = {}): AudioWidget = globalWidgetManager.audio(setup) + +public fun boundedFloatTextWidget(setup: BoundedFloatTextWidget.() -> Unit = {}): BoundedFloatTextWidget = globalWidgetManager.boundedFloatText(setup) + +public fun boundedIntTextWidget(setup: BoundedIntTextWidget.() -> Unit = {}): BoundedIntTextWidget = globalWidgetManager.boundedIntText(setup) + +public fun boxWidget(setup: BoxWidget.() -> Unit = {}): BoxWidget = globalWidgetManager.box(setup) + +public fun buttonWidget(setup: ButtonWidget.() -> Unit = {}): ButtonWidget = globalWidgetManager.button(setup) + +public fun buttonStyleWidget(setup: ButtonStyleWidget.() -> Unit = {}): ButtonStyleWidget = globalWidgetManager.buttonStyle(setup) + +public fun checkboxWidget(setup: CheckboxWidget.() -> Unit = {}): CheckboxWidget = globalWidgetManager.checkbox(setup) + +public fun checkboxStyleWidget(setup: CheckboxStyleWidget.() -> Unit = {}): CheckboxStyleWidget = globalWidgetManager.checkboxStyle(setup) + +public fun colorPickerWidget(setup: ColorPickerWidget.() -> Unit = {}): ColorPickerWidget = globalWidgetManager.colorPicker(setup) + +public fun colorsInputWidget(setup: ColorsInputWidget.() -> Unit = {}): ColorsInputWidget = globalWidgetManager.colorsInput(setup) + +public fun comboboxWidget(setup: ComboboxWidget.() -> Unit = {}): ComboboxWidget = globalWidgetManager.combobox(setup) + +public fun controllerWidget(setup: ControllerWidget.() -> Unit = {}): ControllerWidget = globalWidgetManager.controller(setup) + +public fun controllerAxisWidget(setup: ControllerAxisWidget.() -> Unit = {}): ControllerAxisWidget = globalWidgetManager.controllerAxis(setup) + +public fun controllerButtonWidget(setup: ControllerButtonWidget.() -> Unit = {}): ControllerButtonWidget = globalWidgetManager.controllerButton(setup) + +public fun datePickerWidget(setup: DatePickerWidget.() -> Unit = {}): DatePickerWidget = globalWidgetManager.datePicker(setup) + +public fun datetimeWidget(setup: DatetimeWidget.() -> Unit = {}): DatetimeWidget = globalWidgetManager.datetime(setup) + +public fun descriptionStyleWidget(setup: DescriptionStyleWidget.() -> Unit = {}): DescriptionStyleWidget = globalWidgetManager.descriptionStyle(setup) + +public fun directionalLinkWidget(setup: DirectionalLinkWidget.() -> Unit = {}): DirectionalLinkWidget = globalWidgetManager.directionalLink(setup) + +public fun domWidget(setup: DomWidget.() -> Unit = {}): DomWidget = globalWidgetManager.domWidget(setup) + +public fun dropdownWidget(setup: DropdownWidget.() -> Unit = {}): DropdownWidget = globalWidgetManager.dropdown(setup) + +public fun fileUploadWidget(setup: FileUploadWidget.() -> Unit = {}): FileUploadWidget = globalWidgetManager.fileUpload(setup) + +public fun floatLogSliderWidget(setup: FloatLogSliderWidget.() -> Unit = {}): FloatLogSliderWidget = globalWidgetManager.floatLogSlider(setup) + +public fun floatProgressWidget(setup: FloatProgressWidget.() -> Unit = {}): FloatProgressWidget = globalWidgetManager.floatProgress(setup) + +public fun floatRangeSliderWidget(setup: FloatRangeSliderWidget.() -> Unit = {}): FloatRangeSliderWidget = globalWidgetManager.floatRangeSlider(setup) + +public fun floatSliderWidget(setup: FloatSliderWidget.() -> Unit = {}): FloatSliderWidget = globalWidgetManager.floatSlider(setup) + +public fun floatTextWidget(setup: FloatTextWidget.() -> Unit = {}): FloatTextWidget = globalWidgetManager.floatText(setup) + +public fun floatsInputWidget(setup: FloatsInputWidget.() -> Unit = {}): FloatsInputWidget = globalWidgetManager.floatsInput(setup) + +public fun gridBoxWidget(setup: GridBoxWidget.() -> Unit = {}): GridBoxWidget = globalWidgetManager.gridBox(setup) + +public fun hBoxWidget(setup: HBoxWidget.() -> Unit = {}): HBoxWidget = globalWidgetManager.hBox(setup) + +public fun htmlWidget(setup: HtmlWidget.() -> Unit = {}): HtmlWidget = globalWidgetManager.html(setup) + +public fun htmlMathWidget(setup: HtmlMathWidget.() -> Unit = {}): HtmlMathWidget = globalWidgetManager.htmlMath(setup) + +public fun htmlMathStyleWidget(setup: HtmlMathStyleWidget.() -> Unit = {}): HtmlMathStyleWidget = globalWidgetManager.htmlMathStyle(setup) + +public fun htmlStyleWidget(setup: HtmlStyleWidget.() -> Unit = {}): HtmlStyleWidget = globalWidgetManager.htmlStyle(setup) + +public fun imageWidget(setup: ImageWidget.() -> Unit = {}): ImageWidget = globalWidgetManager.image(setup) + +public fun intProgressWidget(setup: IntProgressWidget.() -> Unit = {}): IntProgressWidget = globalWidgetManager.intProgress(setup) + +public fun intRangeSliderWidget(setup: IntRangeSliderWidget.() -> Unit = {}): IntRangeSliderWidget = globalWidgetManager.intRangeSlider(setup) + +public fun intSliderWidget(setup: IntSliderWidget.() -> Unit = {}): IntSliderWidget = globalWidgetManager.intSlider(setup) + +public fun intTextWidget(setup: IntTextWidget.() -> Unit = {}): IntTextWidget = globalWidgetManager.intText(setup) + +public fun intsInputWidget(setup: IntsInputWidget.() -> Unit = {}): IntsInputWidget = globalWidgetManager.intsInput(setup) + +public fun labelWidget(setup: LabelWidget.() -> Unit = {}): LabelWidget = globalWidgetManager.label(setup) + +public fun labelStyleWidget(setup: LabelStyleWidget.() -> Unit = {}): LabelStyleWidget = globalWidgetManager.labelStyle(setup) + +public fun layoutWidget(setup: LayoutWidget.() -> Unit = {}): LayoutWidget = globalWidgetManager.layout(setup) + +public fun linkWidget(setup: LinkWidget.() -> Unit = {}): LinkWidget = globalWidgetManager.link(setup) + +public fun naiveDatetimeWidget(setup: NaiveDatetimeWidget.() -> Unit = {}): NaiveDatetimeWidget = globalWidgetManager.naiveDatetime(setup) + +public fun passwordWidget(setup: PasswordWidget.() -> Unit = {}): PasswordWidget = globalWidgetManager.password(setup) + +public fun playWidget(setup: PlayWidget.() -> Unit = {}): PlayWidget = globalWidgetManager.play(setup) + +public fun progressStyleWidget(setup: ProgressStyleWidget.() -> Unit = {}): ProgressStyleWidget = globalWidgetManager.progressStyle(setup) + +public fun radioButtonsWidget(setup: RadioButtonsWidget.() -> Unit = {}): RadioButtonsWidget = globalWidgetManager.radioButtons(setup) + +public fun selectWidget(setup: SelectWidget.() -> Unit = {}): SelectWidget = globalWidgetManager.select(setup) + +public fun selectMultipleWidget(setup: SelectMultipleWidget.() -> Unit = {}): SelectMultipleWidget = globalWidgetManager.selectMultiple(setup) + +public fun selectionRangeSliderWidget(setup: SelectionRangeSliderWidget.() -> Unit = {}): SelectionRangeSliderWidget = globalWidgetManager.selectionRangeSlider(setup) + +public fun selectionSliderWidget(setup: SelectionSliderWidget.() -> Unit = {}): SelectionSliderWidget = globalWidgetManager.selectionSlider(setup) + +public fun sliderStyleWidget(setup: SliderStyleWidget.() -> Unit = {}): SliderStyleWidget = globalWidgetManager.sliderStyle(setup) + +public fun stackWidget(setup: StackWidget.() -> Unit = {}): StackWidget = globalWidgetManager.stack(setup) + +public fun tabWidget(setup: TabWidget.() -> Unit = {}): TabWidget = globalWidgetManager.tab(setup) + +public fun tagsInputWidget(setup: TagsInputWidget.() -> Unit = {}): TagsInputWidget = globalWidgetManager.tagsInput(setup) + +public fun textWidget(setup: TextWidget.() -> Unit = {}): TextWidget = globalWidgetManager.text(setup) + +public fun textStyleWidget(setup: TextStyleWidget.() -> Unit = {}): TextStyleWidget = globalWidgetManager.textStyle(setup) + +public fun textareaWidget(setup: TextareaWidget.() -> Unit = {}): TextareaWidget = globalWidgetManager.textarea(setup) + +public fun timeWidget(setup: TimeWidget.() -> Unit = {}): TimeWidget = globalWidgetManager.time(setup) + +public fun toggleButtonWidget(setup: ToggleButtonWidget.() -> Unit = {}): ToggleButtonWidget = globalWidgetManager.toggleButton(setup) + +public fun toggleButtonStyleWidget(setup: ToggleButtonStyleWidget.() -> Unit = {}): ToggleButtonStyleWidget = globalWidgetManager.toggleButtonStyle(setup) + +public fun toggleButtonsWidget(setup: ToggleButtonsWidget.() -> Unit = {}): ToggleButtonsWidget = globalWidgetManager.toggleButtons(setup) + +public fun toggleButtonsStyleWidget(setup: ToggleButtonsStyleWidget.() -> Unit = {}): ToggleButtonsStyleWidget = globalWidgetManager.toggleButtonsStyle(setup) + +public fun vBoxWidget(setup: VBoxWidget.() -> Unit = {}): VBoxWidget = globalWidgetManager.vBox(setup) + +public fun validWidget(setup: ValidWidget.() -> Unit = {}): ValidWidget = globalWidgetManager.valid(setup) + +public fun videoWidget(setup: VideoWidget.() -> Unit = {}): VideoWidget = globalWidgetManager.video(setup) + diff --git a/integrations/widgets/widgets-jupyter/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/integration/MainJupyterWidgetLibrary.kt b/integrations/widgets/widgets-jupyter/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/integration/MainJupyterWidgetLibrary.kt new file mode 100644 index 0000000..735cf90 --- /dev/null +++ b/integrations/widgets/widgets-jupyter/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/integration/MainJupyterWidgetLibrary.kt @@ -0,0 +1,12 @@ +package org.jetbrains.kotlinx.jupyter.widget.integration + +import org.jetbrains.kotlinx.jupyter.widget.library.OutputWidget +import org.jetbrains.kotlinx.jupyter.widget.library.output + +/** + * Creates an [OutputWidget] and registers it with the global widget manager. + * + * @param setup A lambda to configure the widget after creation. + * @return The created and registered [OutputWidget]. + */ +public fun outputWidget(setup: OutputWidget.() -> Unit = {}): OutputWidget = globalWidgetManager.output(setup) diff --git a/integrations/widgets/widgets-jupyter/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/integration/WidgetJupyterIntegration.kt b/integrations/widgets/widgets-jupyter/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/integration/WidgetJupyterIntegration.kt new file mode 100644 index 0000000..c236811 --- /dev/null +++ b/integrations/widgets/widgets-jupyter/src/main/kotlin/org/jetbrains/kotlinx/jupyter/widget/integration/WidgetJupyterIntegration.kt @@ -0,0 +1,38 @@ +package org.jetbrains.kotlinx.jupyter.widget.integration + +import org.jetbrains.kotlinx.jupyter.api.declare +import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration +import org.jetbrains.kotlinx.jupyter.widget.WidgetManager +import org.jetbrains.kotlinx.jupyter.widget.WidgetManagerImpl +import org.jetbrains.kotlinx.jupyter.widget.library.DatePickerWidget +import org.jetbrains.kotlinx.jupyter.widget.library.enums.BoxStyle +import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel + +private var myWidgetManager: WidgetManager? = null +internal val globalWidgetManager: WidgetManager get() = myWidgetManager!! + +public class WidgetJupyterIntegration : JupyterIntegration() { + override fun Builder.onLoaded() { + importPackage() + importPackage() + importPackage() + + var myLastClassLoader = WidgetJupyterIntegration::class.java.classLoader + val widgetManager = WidgetManagerImpl(notebook.commManager) { myLastClassLoader } + myWidgetManager = widgetManager + + onLoaded { + myLastClassLoader = this.lastClassLoader + + declare("widgetManager" to widgetManager) + } + + afterCellExecution { _, _ -> + myLastClassLoader = this.lastClassLoader + } + + renderWithHost { _, widget -> + widgetManager.renderWidget(widget) + } + } +} diff --git a/integrations/widgets/widgets-tests/build.gradle.kts b/integrations/widgets/widgets-tests/build.gradle.kts new file mode 100644 index 0000000..38d2ba6 --- /dev/null +++ b/integrations/widgets/widgets-tests/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.kotlin.jupyter.api) +} + +dependencies { + testImplementation(projects.integrations.widgets.widgetsJupyter) + testImplementation(libs.kotlin.test) + testImplementation(libs.test.kotlintest.assertions) +} + +tasks.test { + useJUnitPlatform() +} + +kotlin { + jvmToolchain( + libs.versions.jvm.toolchain + .get() + .toInt(), + ) +} diff --git a/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/AbstractWidgetReplTest.kt b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/AbstractWidgetReplTest.kt new file mode 100644 index 0000000..3dd931a --- /dev/null +++ b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/AbstractWidgetReplTest.kt @@ -0,0 +1,162 @@ +package org.jetbrains.kotlinx.jupyter.widget.test + +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.shouldBeInstanceOf +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonObjectBuilder +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.add +import kotlinx.serialization.json.buildJsonArray +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.jsonPrimitive +import kotlinx.serialization.json.put +import org.jetbrains.kotlinx.jupyter.protocol.comms.CommManagerImpl +import org.jetbrains.kotlinx.jupyter.testkit.JupyterReplTestCase +import org.jetbrains.kotlinx.jupyter.widget.test.util.CommEvent +import org.jetbrains.kotlinx.jupyter.widget.test.util.TestServerCommCommunicationFacility +import org.jetbrains.kotlinx.jupyter.widget.test.util.WidgetReplProvider + +abstract class AbstractWidgetReplTest( + protected val facility: TestServerCommCommunicationFacility = TestServerCommCommunicationFacility(), + protected val commManager: CommManagerImpl = CommManagerImpl(facility), + provider: WidgetReplProvider = WidgetReplProvider(commManager), +) : JupyterReplTestCase(provider) { + protected var nextEventIndex: Int = 0 + + protected fun resetEvents() { + facility.sentEvents.clear() + nextEventIndex = 0 + } + + protected fun shouldHaveOpenEvents(vararg expectedModelNames: String): List = + expectedModelNames.map { shouldHaveNextOpenEvent(it) } + + protected fun shouldHaveNextOpenEvent(expectedModelName: String) = shouldHaveOpenEvent(nextEventIndex++, expectedModelName) + + protected fun shouldHaveOpenEvent( + index: Int, + expectedModelName: String, + ): CommEvent.Open { + val openEvent = facility.sentEvents[index].shouldBeInstanceOf() + openEvent.data["state"] + ?.shouldBeInstanceOf() + ?.get("_model_name") + ?.jsonPrimitive + ?.content shouldBe expectedModelName + return openEvent + } + + protected fun shouldHaveNextUpdateEvent(vararg expectedState: Pair) = + shouldHaveMessageEvent(nextEventIndex++, "update", *expectedState) + + protected fun shouldHaveNextEchoUpdateEvent(vararg expectedState: Pair) = + shouldHaveMessageEvent(nextEventIndex++, "echo_update", *expectedState) + + protected fun shouldHaveMessageEvent( + index: Int, + method: String, + vararg expectedState: Pair, + ): CommEvent.Message { + val msgEvent = facility.sentEvents[index].shouldBeInstanceOf() + return msgEvent.shouldHaveMessage(method, *expectedState) + } + + protected fun CommEvent.Message.shouldHaveMessage( + method: String, + vararg expectedState: Pair, + ): CommEvent.Message { + data["method"]?.jsonPrimitive?.content shouldBe method + val state = data["state"].shouldBeInstanceOf() + for ((key, value) in expectedState) { + state[key]?.jsonPrimitive?.content shouldBe value?.toString() + } + return this + } + + protected fun shouldHaveUpdateEvent( + propertyName: String, + vararg expectedState: Pair, + ): CommEvent.Message { + val event = + facility.sentEvents.filterIsInstance().find { + it.data["method"]?.jsonPrimitive?.content == "update" && + it.data["state"]?.shouldBeInstanceOf()?.containsKey(propertyName) == true + } + event.shouldNotBeNull() + return event.shouldHaveMessage("update", *expectedState) + } + + protected fun shouldHaveBufferPath( + msgEvent: CommEvent.Message, + index: Int, + vararg expectedPath: String, + ) { + val paths = msgEvent.data["buffer_paths"]?.shouldBeInstanceOf()!! + val path = paths[index].shouldBeInstanceOf() + path.size shouldBe expectedPath.size + expectedPath.forEachIndexed { i, segment -> + path[i].jsonPrimitive.content shouldBe segment + } + } + + protected fun shouldHaveWidgetDisplayJson( + json: JsonObject?, + expectedModelId: String, + expectedModelName: String, + ) { + json.shouldNotBeNull() + val data = json["data"].shouldBeInstanceOf() + val viewData = data["application/vnd.jupyter.widget-view+json"].shouldBeInstanceOf() + viewData["model_id"]?.jsonPrimitive?.content shouldBe expectedModelId + viewData["version_major"]?.jsonPrimitive?.content shouldBe "2" + viewData["version_minor"]?.jsonPrimitive?.content shouldBe "0" + + val htmlData = data["text/html"].shouldBeInstanceOf().content + htmlData shouldBe "$expectedModelName(id=$expectedModelId)" + } + + protected fun sendUpdate( + commId: String, + vararg state: Pair, + ) = sendUpdate(commId, buildState(*state)) + + protected fun sendUpdate( + commId: String, + state: JsonObject, + buffers: List = emptyList(), + bufferPaths: List> = emptyList(), + ) { + val updateData = + buildJsonObject { + put("method", "update") + put("state", state) + put( + "buffer_paths", + buildJsonArray { + bufferPaths.forEach { path -> + add(buildJsonArray { path.forEach { add(it) } }) + } + }, + ) + } + commManager.processCommMessage(commId, updateData, null, buffers) + } + + protected fun buildState(vararg state: Pair) = buildJsonObject { putState(*state) } + + protected fun JsonObjectBuilder.putState(vararg state: Pair) { + for ((key, value) in state) { + when (value) { + is String -> put(key, value) + is Number -> put(key, value) + is Boolean -> put(key, value) + is JsonElement -> put(key, value) + null -> put(key, null as String?) + else -> throw IllegalArgumentException("Unsupported type: ${value::class}") + } + } + } +} diff --git a/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/CustomMessageTest.kt b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/CustomMessageTest.kt new file mode 100644 index 0000000..e4ba1fc --- /dev/null +++ b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/CustomMessageTest.kt @@ -0,0 +1,153 @@ +package org.jetbrains.kotlinx.jupyter.widget.test + +import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.shouldBeInstanceOf +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put +import org.jetbrains.kotlinx.jupyter.widget.test.util.CommEvent +import org.junit.jupiter.api.Test + +class CustomMessageTest : AbstractWidgetReplTest() { + @Test + fun `send custom message from kernel`() { + execRaw("val s = intSliderWidget()") + // LayoutModel, SliderStyleModel, IntSliderModel + val sliderId = execRaw("widgetManager.getWidgetId(s)") as String + nextEventIndex = 3 + + execRaw("import kotlinx.serialization.json.buildJsonObject") + execRaw("import kotlinx.serialization.json.put") + execRaw("s.sendCustomMessage(buildJsonObject { put(\"foo\", \"bar\") })") + + val msgEvent = facility.sentEvents[nextEventIndex++].shouldBeInstanceOf() + msgEvent.commId shouldBe sliderId + msgEvent.data["method"]?.shouldBeInstanceOf()?.content shouldBe "custom" + val content = msgEvent.data["content"]?.shouldBeInstanceOf()!! + content["foo"]?.shouldBeInstanceOf()?.content shouldBe "bar" + } + + @Test + fun `send custom message with bytes from kernel`() { + execRaw("val s = intSliderWidget()") + execRaw("widgetManager.getWidgetId(s)") as String + nextEventIndex = 3 + + execRaw("import kotlinx.serialization.json.buildJsonObject") + execRaw("import kotlinx.serialization.json.put") + execRaw("s.sendCustomMessage(buildJsonObject { put(\"data\", null as String?) }, buffers = listOf(byteArrayOf(1, 2, 3)))") + } + + @Test + fun `receive custom message from frontend`() { + execRaw("val s = intSliderWidget()") + val sliderId = execRaw("widgetManager.getWidgetId(s)") as String + + execRaw("var receivedContent: kotlinx.serialization.json.JsonObject? = null") + execRaw("s.addCustomMessageListener { content, _, _ -> receivedContent = content }") + + val content = buildJsonObject { put("baz", 42) } + val customData = + buildJsonObject { + put("method", "custom") + put("content", content) + } + commManager.processCommMessage(sliderId, customData, null, emptyList()) + + execRaw("receivedContent?.get(\"baz\")?.toString()") shouldBe "42" + } + + @Test + fun `receive custom message with bytes from frontend`() { + execRaw("val s = intSliderWidget()") + val sliderId = execRaw("widgetManager.getWidgetId(s)") as String + + execRaw("var receivedData: ByteArray? = null") + execRaw("s.addCustomMessageListener { _, _, buffers -> receivedData = buffers.firstOrNull() }") + + val bytes = byteArrayOf(4, 5, 6) + val content = buildJsonObject { put("data", null as String?) } + val customData = + buildJsonObject { + put("method", "custom") + put("content", content) + } + commManager.processCommMessage(sliderId, customData, null, listOf(bytes)) + + execRaw("receivedData") shouldBe bytes + } + + @Test + fun `receive custom message with metadata from frontend`() { + execRaw("val s = intSliderWidget()") + val sliderId = execRaw("widgetManager.getWidgetId(s)") as String + + execRaw("var receivedMetadata: kotlinx.serialization.json.JsonElement? = null") + execRaw("s.addCustomMessageListener { _, metadata, _ -> receivedMetadata = metadata }") + + val content = buildJsonObject { put("foo", "bar") } + val metadata = buildJsonObject { put("meta", "data") } + val customData = + buildJsonObject { + put("method", "custom") + put("content", content) + } + commManager.processCommMessage(sliderId, customData, metadata, emptyList()) + + execRaw("import kotlinx.serialization.json.jsonPrimitive") + execRaw("import kotlinx.serialization.json.jsonObject") + execRaw("(receivedMetadata as kotlinx.serialization.json.JsonObject).get(\"meta\")?.jsonPrimitive?.content") shouldBe "data" + } + + @Test + fun `receive custom message with primitive metadata from frontend`() { + execRaw("val s = intSliderWidget()") + val sliderId = execRaw("widgetManager.getWidgetId(s)") as String + + execRaw("var receivedMetadata: kotlinx.serialization.json.JsonElement? = null") + execRaw("s.addCustomMessageListener { _, metadata, _ -> receivedMetadata = metadata }") + + val content = buildJsonObject { put("foo", "bar") } + val metadata = JsonPrimitive("some string") + val customData = + buildJsonObject { + put("method", "custom") + put("content", content) + } + commManager.processCommMessage(sliderId, customData, metadata, emptyList()) + + execRaw("import kotlinx.serialization.json.jsonPrimitive") + execRaw("receivedMetadata?.jsonPrimitive?.content") shouldBe "some string" + } + + @Test + fun `send custom message with primitive metadata from kernel`() { + execRaw("val s = intSliderWidget()") + val sliderId = execRaw("widgetManager.getWidgetId(s)") as String + nextEventIndex = 3 + + execRaw("import kotlinx.serialization.json.buildJsonObject") + execRaw("import kotlinx.serialization.json.put") + execRaw("import kotlinx.serialization.json.JsonPrimitive") + execRaw("s.sendCustomMessage(buildJsonObject { put(\"foo\", \"bar\") }, metadata = JsonPrimitive(123))") + + val msgEvent = facility.sentEvents[nextEventIndex++].shouldBeInstanceOf() + msgEvent.commId shouldBe sliderId + msgEvent.data["method"]?.shouldBeInstanceOf()?.content shouldBe "custom" + msgEvent.metadata?.shouldBeInstanceOf()?.content shouldBe "123" + } + + @Test + fun `send raw custom message with bytes from kernel`() { + execRaw("val s = intSliderWidget()") + val sliderId = execRaw("widgetManager.getWidgetId(s)") as String + nextEventIndex = 3 + + execRaw("import kotlinx.serialization.json.buildJsonObject") + execRaw("s.sendCustomMessage(buildJsonObject {}, buffers = listOf(byteArrayOf(7, 8, 9)))") + + val msgEvent = facility.sentEvents[nextEventIndex++].shouldBeInstanceOf() + msgEvent.commId shouldBe sliderId + msgEvent.buffers shouldBe listOf(byteArrayOf(7, 8, 9)) + } +} diff --git a/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/LinkWidgetTest.kt b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/LinkWidgetTest.kt new file mode 100644 index 0000000..fc5c6d0 --- /dev/null +++ b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/LinkWidgetTest.kt @@ -0,0 +1,79 @@ +package org.jetbrains.kotlinx.jupyter.widget.test + +import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.shouldBeInstanceOf +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.contentOrNull +import kotlinx.serialization.json.jsonPrimitive +import org.jetbrains.kotlinx.jupyter.widget.library.DirectionalLinkWidget +import org.jetbrains.kotlinx.jupyter.widget.library.LinkWidget +import org.junit.jupiter.api.Test + +class LinkWidgetTest : AbstractWidgetReplTest() { + @Test + fun `linkProperties should create a LinkWidget with correct source and target`() { + execRaw("val play = playWidget()") + execRaw("val slider = intSliderWidget()") + + val playId = execRaw("widgetManager.getWidgetId(play)") as String + val sliderId = execRaw("widgetManager.getWidgetId(slider)") as String + + val link = + execRaw( + """ + widgetManager.linkProperties(play, PlayWidget::value, slider, IntSliderWidget::value) + """.trimIndent(), + ) + link.shouldBeInstanceOf() + + val source = + shouldHaveUpdateEvent("source") + .data["state"]!! + .shouldBeInstanceOf()["source"] + .shouldBeInstanceOf() + source[0].jsonPrimitive.contentOrNull shouldBe "IPY_MODEL_$playId" + source[1].jsonPrimitive.content shouldBe "value" + + val target = + shouldHaveUpdateEvent("target") + .data["state"]!! + .shouldBeInstanceOf()["target"] + .shouldBeInstanceOf() + target[0].jsonPrimitive.contentOrNull shouldBe "IPY_MODEL_$sliderId" + target[1].jsonPrimitive.content shouldBe "value" + } + + @Test + fun `linkPropertiesOneWay should create a DirectionalLinkWidget with correct source and target`() { + execRaw("val play = playWidget()") + execRaw("val slider = intSliderWidget()") + + val playId = execRaw("widgetManager.getWidgetId(play)") as String + val sliderId = execRaw("widgetManager.getWidgetId(slider)") as String + + val link = + execRaw( + """ + widgetManager.linkPropertiesOneWay(play, PlayWidget::value, slider, IntSliderWidget::value) + """.trimIndent(), + ) + link.shouldBeInstanceOf() + + val source = + shouldHaveUpdateEvent("source") + .data["state"]!! + .shouldBeInstanceOf()["source"] + .shouldBeInstanceOf() + source[0].jsonPrimitive.contentOrNull shouldBe "IPY_MODEL_$playId" + source[1].jsonPrimitive.content shouldBe "value" + + val target = + shouldHaveUpdateEvent("target") + .data["state"]!! + .shouldBeInstanceOf()["target"] + .shouldBeInstanceOf() + target[0].jsonPrimitive.contentOrNull shouldBe "IPY_MODEL_$sliderId" + target[1].jsonPrimitive.content shouldBe "value" + } +} diff --git a/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/NotebookTest.kt b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/NotebookTest.kt new file mode 100644 index 0000000..235a6c5 --- /dev/null +++ b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/NotebookTest.kt @@ -0,0 +1,105 @@ +package org.jetbrains.kotlinx.jupyter.widget.test + +import org.jetbrains.jupyter.parser.JupyterParser +import org.jetbrains.jupyter.parser.notebook.Cell +import org.jetbrains.jupyter.parser.notebook.CodeCell +import org.jetbrains.jupyter.parser.notebook.Output +import org.jetbrains.kotlinx.jupyter.repl.result.EvalResultEx +import org.junit.jupiter.api.Test +import java.io.File + +class NotebookTest : AbstractWidgetReplTest() { + @Test + fun `widgets notebook should run successfully`() = + notebookTest( + notebookName = "widgets", + replacer = { + it.replace("WidgetArch.png", "$NOTEBOOK_EXAMPLES_PATH/WidgetArch.png") + }, + ) + + @Test + fun `output notebook should run successfully`() = + notebookTest( + notebookName = "output", + ) + + private fun notebookTest( + notebookName: String, + replacer: CodeReplacer = CodeReplacer.DEFAULT, + cellClause: CellClause = CellClause.DEFAULT, + cleanup: () -> Unit = {}, + ) { + val path = "$NOTEBOOK_EXAMPLES_PATH/$notebookName.ipynb" + doTest(path, replacer, cellClause, cleanup) + } + + private fun doTest( + notebookPath: String, + replacer: CodeReplacer, + cellClause: CellClause, + cleanup: () -> Unit = {}, + ) { + val notebookFile = File(notebookPath) + val notebook = JupyterParser.parse(notebookFile) + val finalClause = cellClause and CellClause.IS_CODE + + val codeCellsData = + notebook.cells + .filter { finalClause.isAccepted(it) } + .map { CodeCellData(it.source, (it as? CodeCell)?.outputs.orEmpty()) } + + try { + for (codeCellData in codeCellsData) { + val code = codeCellData.code + val codeToExecute = replacer.replace(code) + + // println("Executing code:\n$codeToExecute") + val cellResult = execEx(codeToExecute) + if (cellResult is EvalResultEx.AbstractError) { + throw cellResult.error + } + require(cellResult is EvalResultEx.Success) + + // println(cellResult) + } + } finally { + cleanup() + } + } + + companion object { + const val NOTEBOOK_EXAMPLES_PATH = "../notebooks" + } +} + +private fun interface CodeReplacer { + fun replace(code: String): String + + companion object { + val DEFAULT = CodeReplacer { it } + } +} + +private fun interface CellClause { + fun isAccepted(cell: Cell): Boolean + + companion object { + val IS_NOT_SKIPTEST = CellClause { it.metadata.tags?.contains("skiptest") != true } + val IS_CODE = CellClause { it.type == Cell.Type.CODE } + val DEFAULT = IS_CODE and IS_NOT_SKIPTEST + } +} + +private infix fun CellClause.and(other: CellClause): CellClause = + CellClause { cell -> + // Prevent lazy evaluation + val acceptedThis = this.isAccepted(cell) + val acceptedOther = other.isAccepted(cell) + acceptedThis && acceptedOther + } + +private data class CodeCellData( + val code: String, + val outputs: List, +) diff --git a/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/SelectionWidgetBaseTest.kt b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/SelectionWidgetBaseTest.kt new file mode 100644 index 0000000..164f838 --- /dev/null +++ b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/SelectionWidgetBaseTest.kt @@ -0,0 +1,64 @@ +package org.jetbrains.kotlinx.jupyter.widget.test + +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test + +class SelectionWidgetBaseTest : AbstractWidgetReplTest() { + @Test + fun `options as list of pairs`() { + execRaw("val d = dropdownWidget()") + execRaw("""d.options = listOf("One" to 1, "Two" to 2)""") + + execRaw("d.options") shouldBe listOf("One" to 1, "Two" to 2) + execRaw("d.value = 2") + execRaw("d.index") shouldBe 1 + execRaw("d.label") shouldBe "Two" + execRaw("d.value") shouldBe 2 + + execRaw("""d.label = "One"""") + execRaw("d.index") shouldBe 0 + execRaw("d.value") shouldBe 1 + } + + @Test + fun `options change preserves value`() { + execRaw("val d = dropdownWidget()") + execRaw("""d.options = listOf("One" to 1, "Two" to 2)""") + execRaw("d.value = 2") + + execRaw("""d.options = listOf("Two" to 2, "Three" to 3)""") + execRaw("d.value") shouldBe 2 + execRaw("d.index") shouldBe 0 + execRaw("d.label") shouldBe "Two" + } + + @Test + fun `setting value to null`() { + execRaw("val d = dropdownWidget()") + execRaw("""d.options = listOf("a" to "a", "b" to "b")""") + execRaw("""d.value = "a"""") + execRaw("d.value = null") + execRaw("d.index") shouldBe null + } + + @Test + fun `range selection labels as pair`() { + execRaw("val s = selectionRangeSliderWidget()") + execRaw("""s.optionsLabels = listOf("a", "b", "c", "d")""") + execRaw("s.index = 1..2") + execRaw("s.labels") shouldBe ("b" to "c") + execRaw("s.value") shouldBe ("b" to "c") + + execRaw("""s.labels = "a" to "d"""") + execRaw("s.index") shouldBe (0..3) + execRaw("s.value") shouldBe ("a" to "d") + + execRaw("""s.value = "b" to "c"""") + execRaw("s.index") shouldBe (1..2) + execRaw("s.labels") shouldBe ("b" to "c") + + execRaw("s.labels = null") + execRaw("s.index") shouldBe null + execRaw("s.value") shouldBe null + } +} diff --git a/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/WidgetReplTest.kt b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/WidgetReplTest.kt new file mode 100644 index 0000000..c76ebb7 --- /dev/null +++ b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/WidgetReplTest.kt @@ -0,0 +1,228 @@ +package org.jetbrains.kotlinx.jupyter.widget.test + +import io.kotest.matchers.collections.shouldBeEmpty +import io.kotest.matchers.collections.shouldHaveSize +import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.shouldBeInstanceOf +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.buildJsonObject +import org.jetbrains.kotlinx.jupyter.protocol.api.EMPTY +import org.jetbrains.kotlinx.jupyter.widget.library.TimeWidgetStep +import org.junit.jupiter.api.Test + +class WidgetReplTest : AbstractWidgetReplTest() { + @Test + fun `widget initialization sends comm open`() { + execRaw("val s = intSliderWidget()") + + // IntSlider depends on Layout and SliderStyle, so 3 widgets are registered + shouldHaveOpenEvents("LayoutModel", "SliderStyleModel", "IntSliderModel") + facility.sentEvents.shouldHaveSize(3) + } + + @Test + fun `widget property change sends comm message`() { + execRaw("val s = intSliderWidget()") + execRaw("s.value = 42") + + shouldHaveNextOpenEvent("LayoutModel") + shouldHaveNextOpenEvent("SliderStyleModel") + shouldHaveNextOpenEvent("IntSliderModel") + val sliderId = execRaw("widgetManager.getWidgetId(s)") as String + shouldHaveNextUpdateEvent("value" to 42) + facility.sentEvents.shouldHaveSize(4) + + val displayedWidget = execSuccess("s").displayValue + val json = displayedWidget?.toJson(Json.EMPTY, null) + shouldHaveWidgetDisplayJson(json, sliderId, "IntSliderModel") + } + + @Test + fun `nested widget property change sends comm message`() { + execRaw("val s2 = intSliderWidget()") + execRaw("s2.layout?.width = \"100px\"") + + val layoutId = execRaw("widgetManager.getWidgetId(s2.layout!!)") as String + shouldHaveNextOpenEvent("LayoutModel") + shouldHaveNextOpenEvent("SliderStyleModel") + shouldHaveNextOpenEvent("IntSliderModel") + val msgEvent = shouldHaveNextUpdateEvent("width" to "100px") + msgEvent.commId shouldBe layoutId + facility.sentEvents.shouldHaveSize(4) + } + + @Test + fun `image widget with bytes`() { + execRaw("val img = imageWidget()") + execRaw("img.value = byteArrayOf(1, 2, 3)") + + // Image depends on Layout, so 2 widgets registered + shouldHaveNextOpenEvent("LayoutModel") + shouldHaveNextOpenEvent("ImageModel") + val msgEvent = shouldHaveNextUpdateEvent() + msgEvent.buffers.shouldHaveSize(1) + msgEvent.buffers[0] shouldBe byteArrayOf(1, 2, 3) + shouldHaveBufferPath(msgEvent, 0, "value") + facility.sentEvents.shouldHaveSize(3) + } + + @Test + fun `date picker with local date`() { + execRaw("import java.time.LocalDate") + execRaw("val dp = datePickerWidget()") + execRaw("dp.value = LocalDate.of(2023, 1, 1)") + + // DatePicker depends on Layout and DescriptionStyle, so 3 widgets registered + shouldHaveOpenEvents("LayoutModel", "DescriptionStyleModel", "DatePickerModel") + shouldHaveNextUpdateEvent("value" to "2023-01-01") + facility.sentEvents.shouldHaveSize(4) + } + + @Test + fun `time widget with integer step`() { + execRaw("val tw = timeWidget()") + execRaw("tw.step = TimeWidgetStep.DoubleValue(30.0)") + shouldHaveOpenEvents("LayoutModel", "DescriptionStyleModel", "TimeModel") + shouldHaveNextUpdateEvent("step" to 30.0) + } + + @Test + fun `frontend message updates widget property`() { + execRaw("val s = intSliderWidget()") + val sliderId = execRaw("widgetManager.getWidgetId(s)") as String + + sendUpdate(sliderId, "value" to 42) + + execRaw("s.value") shouldBe 42 + } + + @Test + fun `frontend comm open creates widget`() { + val openData = + buildJsonObject { + put( + "state", + buildState( + "_model_name" to "IntSliderModel", + "_model_module" to "@jupyter-widgets/controls", + "_model_module_version" to "2.0.0", + "value" to 55, + ), + ) + put("buffer_paths", JsonArray(emptyList())) + } + + commManager.processCommOpen("new_slider_id", "jupyter.widget", openData, null, emptyList()) + + // Frontend already has all the widgets, so no events should be sent + facility.sentEvents.shouldBeEmpty() + + execRaw("import org.jetbrains.kotlinx.jupyter.widget.library.IntSliderWidget") + execRaw("val createdSlider = widgetManager.getWidget(\"new_slider_id\") as IntSliderWidget") + execRaw("createdSlider.value") shouldBe 55 + } + + @Test + fun `frontend message updates image bytes`() { + execRaw("val img = imageWidget()") + // Image depends on Layout, so 2 widgets registered. Image is the second one. + val imageId = execRaw("widgetManager.getWidgetId(img)") as String + + val bytes = byteArrayOf(10, 20, 30) + sendUpdate( + imageId, + buildState("value" to null), + listOf(bytes), + listOf(listOf("value")), + ) + + execRaw("img.value") shouldBe bytes + } + + @Test + fun `echo_update is disabled by default`() { + execRaw("val s = intSliderWidget()") + val sliderId = execRaw("widgetManager.getWidgetId(s)") as String + resetEvents() + + sendUpdate(sliderId, "value" to 42) + + facility.sentEvents.shouldBeEmpty() + } + + @Test + fun `echo_update can be enabled and filters properties`() { + execRaw("widgetManager.echoUpdateEnabled = true") + execRaw("val s = intSliderWidget()") + val sliderId = execRaw("widgetManager.getWidgetId(s)") as String + resetEvents() + + // 1. Both properties are echoed + sendUpdate(sliderId, "value" to 42) + shouldHaveNextEchoUpdateEvent() + resetEvents() + + // 2. Disable echo for 'value' property + execRaw("import org.jetbrains.kotlinx.jupyter.widget.model.WidgetModel") + execRaw("(s as WidgetModel).getProperty(\"value\")?.echoUpdate = false") + + sendUpdate(sliderId, "value" to 43) + + facility.sentEvents.shouldBeEmpty() + + // 3. Mixed properties: one with echo, one without + // IntSlider has 'step' property too. + sendUpdate(sliderId, "value" to 44, "step" to 2) + + facility.sentEvents.shouldHaveSize(1) + + val echoEvent = shouldHaveNextEchoUpdateEvent() + val echoState = echoEvent.data["state"]?.shouldBeInstanceOf()!! + echoState.containsKey("step") shouldBe true + echoState.containsKey("value") shouldBe false + + // Reset for other tests + execRaw("widgetManager.echoUpdateEnabled = false") + } + + @Test + fun `time widget union type property`() { + execRaw("val t = timeWidget()") + shouldHaveOpenEvents("LayoutModel", "DescriptionStyleModel", "TimeModel") + + execRaw("t.step = TimeWidgetStep.DoubleValue(10.5)") + shouldHaveNextUpdateEvent("step" to 10.5) + + execRaw("t.step = TimeWidgetStep.AnyStep") + shouldHaveNextUpdateEvent("step" to "any") + + facility.sentEvents.shouldHaveSize(5) + } + + @Test + fun `time widget union type property from frontend`() { + execRaw("val t2 = timeWidget()") + shouldHaveOpenEvents("LayoutModel", "DescriptionStyleModel", "TimeModel") + val timeId = execRaw("widgetManager.getWidgetId(t2)") as String + + sendUpdate(timeId, "step" to 42.0) + execRaw("t2.step").shouldBeInstanceOf().value shouldBe 42.0 + + sendUpdate(timeId, "step" to "any") + execRaw("t2.step") shouldBe TimeWidgetStep.AnyStep + } + + @Test + fun `date picker step property`() { + execRaw("val dp = datePickerWidget()") + shouldHaveOpenEvents("LayoutModel", "DescriptionStyleModel", "DatePickerModel") + + execRaw("dp.step = DatePickerWidgetStep.IntValue(5)") + shouldHaveNextUpdateEvent("step" to 5) + + execRaw("dp.step = DatePickerWidgetStep.AnyStep") + shouldHaveNextUpdateEvent("step" to "any") + } +} diff --git a/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/util/CommEvent.kt b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/util/CommEvent.kt new file mode 100644 index 0000000..3eda6c3 --- /dev/null +++ b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/util/CommEvent.kt @@ -0,0 +1,28 @@ +package org.jetbrains.kotlinx.jupyter.widget.test.util + +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject + +sealed interface CommEvent { + data class Open( + val commId: String, + val targetName: String, + val data: JsonObject, + val metadata: JsonElement?, + val buffers: List, + ) : CommEvent + + data class Message( + val commId: String, + val data: JsonObject, + val metadata: JsonElement?, + val buffers: List, + ) : CommEvent + + data class Close( + val commId: String, + val data: JsonObject, + val metadata: JsonElement?, + val buffers: List, + ) : CommEvent +} diff --git a/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/util/TestServerCommCommunicationFacility.kt b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/util/TestServerCommCommunicationFacility.kt new file mode 100644 index 0000000..0ccf97d --- /dev/null +++ b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/util/TestServerCommCommunicationFacility.kt @@ -0,0 +1,46 @@ +package org.jetbrains.kotlinx.jupyter.widget.test.util + +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import org.jetbrains.kotlinx.jupyter.protocol.api.RawMessage +import org.jetbrains.kotlinx.jupyter.protocol.comms.CommCommunicationFacility + +class TestServerCommCommunicationFacility : CommCommunicationFacility { + private val events = mutableListOf() + + val sentEvents: MutableList get() = events + + override val contextMessage: RawMessage? get() = null + + override fun sendCommOpen( + commId: String, + targetName: String, + data: JsonObject, + metadata: JsonElement?, + buffers: List, + ) { + events.add(CommEvent.Open(commId, targetName, data, metadata, buffers)) + } + + override fun sendCommMessage( + commId: String, + data: JsonObject, + metadata: JsonElement?, + buffers: List, + ) { + events.add(CommEvent.Message(commId, data, metadata, buffers)) + } + + override fun sendCommClose( + commId: String, + data: JsonObject, + metadata: JsonElement?, + buffers: List, + ) { + events.add(CommEvent.Close(commId, data, metadata, buffers)) + } + + override fun processCallbacks(action: () -> Unit) { + action() + } +} diff --git a/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/util/WidgetReplProvider.kt b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/util/WidgetReplProvider.kt new file mode 100644 index 0000000..a5df10a --- /dev/null +++ b/integrations/widgets/widgets-tests/src/test/kotlin/org/jetbrains/kotlinx/jupyter/widget/test/util/WidgetReplProvider.kt @@ -0,0 +1,46 @@ +package org.jetbrains.kotlinx.jupyter.widget.test.util + +import org.jetbrains.kotlinx.jupyter.api.EmbeddedKernelRunMode +import org.jetbrains.kotlinx.jupyter.api.libraries.CommManager +import org.jetbrains.kotlinx.jupyter.config.DefaultKernelLoggerFactory +import org.jetbrains.kotlinx.jupyter.config.defaultRepositoriesCoordinates +import org.jetbrains.kotlinx.jupyter.libraries.LibraryResolver +import org.jetbrains.kotlinx.jupyter.libraries.createLibraryHttpUtil +import org.jetbrains.kotlinx.jupyter.repl.ReplForJupyter +import org.jetbrains.kotlinx.jupyter.repl.creating.createRepl +import org.jetbrains.kotlinx.jupyter.repl.embedded.NoOpInMemoryReplResultsHolder +import org.jetbrains.kotlinx.jupyter.testkit.ClasspathLibraryResolver +import org.jetbrains.kotlinx.jupyter.testkit.ReplProvider +import org.jetbrains.kotlinx.jupyter.testkit.ToEmptyLibraryResolver +import java.io.File + +class WidgetReplProvider( + private val commManager: CommManager, +) : ReplProvider { + private val httpUtil = createLibraryHttpUtil(DefaultKernelLoggerFactory) + + override fun invoke(classpath: List): ReplForJupyter { + val resolver = + run { + var res: LibraryResolver = ClasspathLibraryResolver(httpUtil.libraryDescriptorsManager, null) { true } + res = ToEmptyLibraryResolver(res) { it == "widgets" } + res + } + + return createRepl( + httpUtil = httpUtil, + scriptClasspath = classpath, + kernelRunMode = EmbeddedKernelRunMode, + mavenRepositories = defaultRepositoriesCoordinates, + libraryResolver = resolver, + inMemoryReplResultsHolder = NoOpInMemoryReplResultsHolder, + commManager = commManager, + ).apply { + initializeWithCurrentClasspath() + } + } + + private fun ReplForJupyter.initializeWithCurrentClasspath() { + eval { librariesScanner.addLibrariesFromClassLoader(currentClassLoader, this, notebook) } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index c65133b..8024ce7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -20,6 +20,12 @@ projectStructure { project("database-integration-tests") } project("intellij-platform") + folder("widgets") { + project("widgets-api") + project("widgets-jupyter") + project("widgets-generator") + project("widgets-tests") + } } }