From 659b9c3525f933cc369cfa1d6e0f2bc5b1abd150 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 27 Dec 2023 12:01:55 +0300 Subject: [PATCH] More or less working muon monitor --- demo/gdml/src/jsMain/kotlin/drop/FileDrop.kt | 50 ------ .../visionforge/gdml/demo/FileDrop.kt | 87 +++++++++++ .../visionforge/gdml/demo/GDMLAppComponent.kt | 4 +- .../visionforge/gdml/demo/fileDrop.kt | 30 ---- demo/gdml/webpack.config.d/01.ring.js | 3 - .../js-playground/webpack.config.d/01.ring.js | 3 - demo/muon-monitor/build.gradle.kts | 14 +- .../mipt/npm/muon/monitor/MMAppComponent.kt | 55 ++++--- .../ru/mipt/npm/muon/monitor/MMDemoApp.kt | 6 +- demo/muon-monitor/webpack.config.d/01.ring.js | 3 - demo/playground/build.gradle.kts | 6 + demo/playground/webpack.config.d/01.ring.js | 23 --- settings.gradle.kts | 8 +- .../build.gradle.kts | 11 +- .../visionforge/compose/MetaViewer.kt | 0 .../visionforge/compose/NameCrumbs.kt | 0 .../visionforge/compose/PropertyEditor.kt | 0 .../kscience/visionforge/compose/Tabs.kt | 88 +++++++++++ .../visionforge/compose/TreeStyles.kt | 18 +-- .../visionforge/compose/VisionForgeStyles.kt | 7 + .../visionforge/compose/VisionTree.kt | 0 .../kscience/visionforge/compose/bootstrap.kt | 0 .../visionforge/compose/composeVision.kt | 0 .../space/kscience/visionforge/compose/css.kt | 0 .../kscience/visionforge/compose/layouts.kt | 0 .../visionforge/compose/valueChooser.kt | 0 .../kscience/visionforge/compose/Tabs.kt | 102 ------------ .../build.gradle.kts | 10 ++ .../webpack.config.d/01.ring.js | 24 --- .../solid/specifications/Canvas3DUIScheme.kt | 2 +- visionforge-tables/build.gradle.kts | 12 +- .../src/jsMain/kotlin/tabulator/Tabulator.kt | 1 + visionforge-threejs/build.gradle.kts | 2 +- .../visionforge/solid/three/ThreePlugin.kt | 1 + .../solid/three/compose/ThreeControls.kt | 14 +- .../solid/three/compose/ThreeView.kt | 146 ++++++++++-------- .../build.gradle.kts | 4 +- 37 files changed, 370 insertions(+), 364 deletions(-) delete mode 100644 demo/gdml/src/jsMain/kotlin/drop/FileDrop.kt create mode 100644 demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/FileDrop.kt delete mode 100644 demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/fileDrop.kt delete mode 100644 demo/gdml/webpack.config.d/01.ring.js delete mode 100644 demo/js-playground/webpack.config.d/01.ring.js delete mode 100644 demo/muon-monitor/webpack.config.d/01.ring.js delete mode 100644 demo/playground/webpack.config.d/01.ring.js rename {visionforge-compose => visionforge-compose-html}/build.gradle.kts (88%) rename {visionforge-compose => visionforge-compose-html}/src/jsMain/kotlin/space/kscience/visionforge/compose/MetaViewer.kt (100%) rename {visionforge-compose => visionforge-compose-html}/src/jsMain/kotlin/space/kscience/visionforge/compose/NameCrumbs.kt (100%) rename {visionforge-compose => visionforge-compose-html}/src/jsMain/kotlin/space/kscience/visionforge/compose/PropertyEditor.kt (100%) create mode 100644 visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/Tabs.kt rename {visionforge-compose => visionforge-compose-html}/src/jsMain/kotlin/space/kscience/visionforge/compose/TreeStyles.kt (89%) create mode 100644 visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/VisionForgeStyles.kt rename {visionforge-compose => visionforge-compose-html}/src/jsMain/kotlin/space/kscience/visionforge/compose/VisionTree.kt (100%) rename {visionforge-compose => visionforge-compose-html}/src/jsMain/kotlin/space/kscience/visionforge/compose/bootstrap.kt (100%) rename {visionforge-compose => visionforge-compose-html}/src/jsMain/kotlin/space/kscience/visionforge/compose/composeVision.kt (100%) rename {visionforge-compose => visionforge-compose-html}/src/jsMain/kotlin/space/kscience/visionforge/compose/css.kt (100%) rename {visionforge-compose => visionforge-compose-html}/src/jsMain/kotlin/space/kscience/visionforge/compose/layouts.kt (100%) rename {visionforge-compose => visionforge-compose-html}/src/jsMain/kotlin/space/kscience/visionforge/compose/valueChooser.kt (100%) delete mode 100644 visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/Tabs.kt delete mode 100644 visionforge-jupyter/visionforge-jupyter-common/webpack.config.d/01.ring.js diff --git a/demo/gdml/src/jsMain/kotlin/drop/FileDrop.kt b/demo/gdml/src/jsMain/kotlin/drop/FileDrop.kt deleted file mode 100644 index 5116155b..00000000 --- a/demo/gdml/src/jsMain/kotlin/drop/FileDrop.kt +++ /dev/null @@ -1,50 +0,0 @@ -@file:JsModule("react-file-drop") -@file:JsNonModule - -package drop - -import org.w3c.dom.DragEvent -import org.w3c.files.FileList -import react.Component -import react.Props -import react.State - -sealed external class DropEffects { - @JsName("copy") - object Copy : DropEffects - - @JsName("move") - object Move : DropEffects - - @JsName("link") - object Link : DropEffects - - @JsName("none") - object None : DropEffects -} - -external interface FileDropProps : Props { - var className: String? - var targetClassName: String? - var draggingOverFrameClassName: String? - var draggingOverTargetClassName: String? - - // var frame?: Exclude | HTMLDocument; - var onFrameDragEnter: ((event: DragEvent) -> Unit)? - var onFrameDragLeave: ((event: DragEvent) -> Unit)? - var onFrameDrop: ((event: DragEvent) -> Unit)? - - // var onDragOver: ReactDragEventHandler? -// var onDragLeave: ReactDragEventHandler? - var onDrop: ((files: FileList?, event: dynamic) -> Unit)?//event:DragEvent) - var dropEffect: DropEffects? -} - -external interface FileDropState : State { - var draggingOverFrame: Boolean - var draggingOverTarget: Boolean -} - -external class FileDrop : Component { - override fun render(): dynamic -} \ No newline at end of file diff --git a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/FileDrop.kt b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/FileDrop.kt new file mode 100644 index 00000000..010f782b --- /dev/null +++ b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/FileDrop.kt @@ -0,0 +1,87 @@ +@file:OptIn(ExperimentalComposeWebApi::class) + +package space.kscience.visionforge.gdml.demo + +import androidx.compose.runtime.* +import org.jetbrains.compose.web.ExperimentalComposeWebApi +import org.jetbrains.compose.web.attributes.InputType +import org.jetbrains.compose.web.attributes.name +import org.jetbrains.compose.web.css.* +import org.jetbrains.compose.web.dom.Div +import org.jetbrains.compose.web.dom.I +import org.jetbrains.compose.web.dom.Input +import org.jetbrains.compose.web.dom.Text +import org.w3c.files.FileList + + +//https://codepen.io/zahedkamal87/pen/PobNNwE +@Composable +fun FileDrop( + title: String = "Drop files or Click here to select files to upload.", + onFileDrop: (FileList) -> Unit, +) { + var dragOver by remember { mutableStateOf(false) } + + Div({ + id("dropzone") + style { + border( + width = 0.2.cssRem, + style = LineStyle.Dashed, + color = Color("#6583fe") + ) + padding(2.cssRem) + borderRadius(0.25.cssRem) + backgroundColor(Color("#fff")) + textAlign("center") + fontSize(1.5.cssRem) + transitions { + all { + delay(0.25.s) + timingFunction(AnimationTimingFunction.EaseInOut) + properties("background-color") + } + } + cursor("pointer") + } + listOf("drag", "dragstart", "dragend", "dragenter").forEach { + addEventListener(it) { event -> + event.preventDefault() + event.stopPropagation() + } + } + onDragOver { event -> + event.preventDefault() + event.stopPropagation() + dragOver = true + } + onDragLeave { event -> + event.preventDefault() + event.stopPropagation() + dragOver = false + } + onDrop { event -> + event.preventDefault() + event.stopPropagation() + dragOver = false + event.dataTransfer?.files?.let { + onFileDrop(it) + } + } + }) { + + I({ classes("bi", "bi-cloud-upload", "dropzone-icon") }) + Text(title) + Input(type = InputType.File, attrs = { + style { + display(DisplayStyle.None) + } + classes("dropzone-input") + name("files") + }) + } +} +// +//dropzone.addEventListener("click", function(e) { +// dropzone_input.click(); +//}); \ No newline at end of file diff --git a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GDMLAppComponent.kt b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GDMLAppComponent.kt index 7a7aa3cc..65a702e4 100644 --- a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GDMLAppComponent.kt +++ b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GDMLAppComponent.kt @@ -69,8 +69,8 @@ fun GDMLApp(solids: Solids, initialVision: Solid?, selected: Name? = null) { H2 { Text("Drag and drop .gdml or .json VisionForge files here") } - fileDrop("(drag file here)") { files -> - val file = files?.get(0) + FileDrop("(drag file here)") { files -> + val file = files[0] if (file != null) { readFileAsync(file) } diff --git a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/fileDrop.kt b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/fileDrop.kt deleted file mode 100644 index 2478c3af..00000000 --- a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/fileDrop.kt +++ /dev/null @@ -1,30 +0,0 @@ -package space.kscience.visionforge.gdml.demo - -import drop.FileDrop -import kotlinx.css.* -import org.w3c.files.FileList -import react.RBuilder -import styled.css -import styled.styledDiv - -//TODO move styles to inline - -fun RBuilder.fileDrop(title: String, action: (files: FileList?) -> Unit) { - styledDiv { - css { - border = Border(style = BorderStyle.dashed, width = 1.px, color = Color.orange) - flexGrow = 0.0 - alignContent = Align.center - } - - child(FileDrop::class) { - attrs { - onDrop = { files, _ -> - console.info("loaded $files") - action(files) - } - } - +title - } - } -} \ No newline at end of file diff --git a/demo/gdml/webpack.config.d/01.ring.js b/demo/gdml/webpack.config.d/01.ring.js deleted file mode 100644 index 41da041c..00000000 --- a/demo/gdml/webpack.config.d/01.ring.js +++ /dev/null @@ -1,3 +0,0 @@ -const ringConfig = require('@jetbrains/ring-ui/webpack.config').config; - -config.module.rules.push(...ringConfig.module.rules) \ No newline at end of file diff --git a/demo/js-playground/webpack.config.d/01.ring.js b/demo/js-playground/webpack.config.d/01.ring.js deleted file mode 100644 index 41da041c..00000000 --- a/demo/js-playground/webpack.config.d/01.ring.js +++ /dev/null @@ -1,3 +0,0 @@ -const ringConfig = require('@jetbrains/ring-ui/webpack.config').config; - -config.module.rules.push(...ringConfig.module.rules) \ No newline at end of file diff --git a/demo/muon-monitor/build.gradle.kts b/demo/muon-monitor/build.gradle.kts index f2b0e4dd..a3bc26e8 100644 --- a/demo/muon-monitor/build.gradle.kts +++ b/demo/muon-monitor/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id("space.kscience.gradle.mpp") + alias(spclibs.plugins.compose) application } @@ -14,11 +15,22 @@ kscience { fullStack( "muon-monitor.js", jvmConfig = { withJava() }, - jsConfig = { useCommonJs() } +// jsConfig = { useCommonJs() }, + browserConfig = { + webpackTask{ + cssSupport{ + enabled = true + } + scssSupport{ + enabled = true + } + } + } ) commonMain { implementation(projects.visionforgeSolid) + implementation(projects.visionforgeComposeHtml) } jvmMain { implementation("org.apache.commons:commons-math3:3.6.1") diff --git a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt index 2ecf9472..13d92075 100644 --- a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt +++ b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt @@ -4,12 +4,13 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.remember import app.softwork.bootstrapcompose.Button +import app.softwork.bootstrapcompose.ButtonGroup +import app.softwork.bootstrapcompose.Container import kotlinx.browser.window import kotlinx.coroutines.await import kotlinx.coroutines.launch import kotlinx.serialization.json.Json import org.jetbrains.compose.web.css.* -import org.jetbrains.compose.web.dom.Div import org.jetbrains.compose.web.dom.P import org.jetbrains.compose.web.dom.Span import org.jetbrains.compose.web.dom.Text @@ -17,8 +18,6 @@ import org.w3c.fetch.RequestInit import space.kscience.dataforge.meta.invoke import space.kscience.dataforge.names.Name import space.kscience.visionforge.Colors -import space.kscience.visionforge.compose.FlexColumn -import space.kscience.visionforge.compose.FlexRow import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.ambientLight import space.kscience.visionforge.solid.edges @@ -51,16 +50,21 @@ fun MMApp(solids: Solids, model: Model, selected: Name? = null) { val events = remember { mutableStateListOf() } - Div({ - style { - height(100.vh - 12.pt) + Container(fluid = true, + attrs = { + style { + height(100.vh - 12.pt) + } } - }) { - ThreeView(solids, root, selected, mmOptions) { - Tab("Events") { - - FlexColumn { - FlexRow { + ) { + ThreeView( + solids = solids, + solid = root, + initialSelected = selected, + options = mmOptions, + sidebarTabs = { + Tab("Events") { + ButtonGroup { Button("Next") { solids.context.launch { val event = window.fetch( @@ -84,23 +88,24 @@ fun MMApp(solids: Solids, model: Model, selected: Name? = null) { model.reset() } } - } - events.forEach { event -> - P { - Span { - Text(event.id.toString()) - } - Text(" : ") - Span({ - style { - color(Color.blue) + + events.forEach { event -> + P { + Span { + Text(event.id.toString()) + } + Text(" : ") + Span({ + style { + color(Color.blue) + } + }) { + Text(event.hits.toString()) } - }) { - Text(event.hits.toString()) } } } } - } + ) } } \ No newline at end of file diff --git a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt index 0fc98ac5..fa08b0ff 100644 --- a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt +++ b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt @@ -1,11 +1,13 @@ package ru.mipt.npm.muon.monitor +import org.jetbrains.compose.web.css.Style import org.jetbrains.compose.web.renderComposable import org.w3c.dom.Document import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.request import space.kscience.visionforge.Application import space.kscience.visionforge.VisionManager +import space.kscience.visionforge.compose.VisionForgeStyles import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.startApplication @@ -22,8 +24,8 @@ private class MMDemoApp : Application { val model = Model(visionManager) - val element = document.getElementById("app") ?: error("Element with id 'app' not found on page") - renderComposable(element) { + renderComposable("app") { + Style(VisionForgeStyles) MMApp(context.request(Solids), model) } } diff --git a/demo/muon-monitor/webpack.config.d/01.ring.js b/demo/muon-monitor/webpack.config.d/01.ring.js deleted file mode 100644 index 41da041c..00000000 --- a/demo/muon-monitor/webpack.config.d/01.ring.js +++ /dev/null @@ -1,3 +0,0 @@ -const ringConfig = require('@jetbrains/ring-ui/webpack.config').config; - -config.module.rules.push(...ringConfig.module.rules) \ No newline at end of file diff --git a/demo/playground/build.gradle.kts b/demo/playground/build.gradle.kts index 22b109ac..71004852 100644 --- a/demo/playground/build.gradle.kts +++ b/demo/playground/build.gradle.kts @@ -16,6 +16,12 @@ kotlin { js(IR) { browser { webpackTask { + cssSupport{ + enabled = true + } + scssSupport{ + enabled = true + } mainOutputFileName.set("js/visionforge-playground.js") } } diff --git a/demo/playground/webpack.config.d/01.ring.js b/demo/playground/webpack.config.d/01.ring.js deleted file mode 100644 index b3cc4770..00000000 --- a/demo/playground/webpack.config.d/01.ring.js +++ /dev/null @@ -1,23 +0,0 @@ -const ringConfig = require('@jetbrains/ring-ui/webpack.config').config; -const path = require('path'); - -config.module.rules.push(...ringConfig.module.rules) - -config.module.rules.push( - { - test: /\.css$/, - exclude: [ - path.resolve(__dirname, "../../node_modules/@jetbrains/ring-ui") - ], - use: [ - { - loader: 'style-loader', - options: {} - }, - { - loader: 'css-loader', - options: {} - } - ] - } -) \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index b2a1b7aa..6ccab6fa 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -41,11 +41,11 @@ dependencyResolutionManagement { include( // ":ui", - ":ui:react", - ":ui:ring", +// ":ui:react", +// ":ui:ring", // ":ui:material", - ":ui:bootstrap", - ":visionforge-compose", +// ":ui:bootstrap", + ":visionforge-compose-html", ":visionforge-core", ":visionforge-solid", // ":visionforge-fx", diff --git a/visionforge-compose/build.gradle.kts b/visionforge-compose-html/build.gradle.kts similarity index 88% rename from visionforge-compose/build.gradle.kts rename to visionforge-compose-html/build.gradle.kts index f8388b5c..1885365f 100644 --- a/visionforge-compose/build.gradle.kts +++ b/visionforge-compose-html/build.gradle.kts @@ -1,10 +1,9 @@ - plugins { id("space.kscience.gradle.mpp") alias(spclibs.plugins.compose) } -kscience{ +kscience { jvm() js() // wasm() @@ -13,22 +12,22 @@ kscience{ kotlin { // android() sourceSets { - commonMain{ - dependencies{ + commonMain { + dependencies { api(projects.visionforgeCore) + api(compose.runtime) } } val jvmMain by getting { dependencies { - api(compose.runtime) api(compose.foundation) api(compose.material) api(compose.preview) } } - val jsMain by getting{ + val jsMain by getting { dependencies { api(compose.html.core) api("app.softwork:bootstrap-compose:0.1.15") diff --git a/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/MetaViewer.kt b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/MetaViewer.kt similarity index 100% rename from visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/MetaViewer.kt rename to visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/MetaViewer.kt diff --git a/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/NameCrumbs.kt b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/NameCrumbs.kt similarity index 100% rename from visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/NameCrumbs.kt rename to visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/NameCrumbs.kt diff --git a/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/PropertyEditor.kt b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/PropertyEditor.kt similarity index 100% rename from visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/PropertyEditor.kt rename to visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/PropertyEditor.kt diff --git a/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/Tabs.kt b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/Tabs.kt new file mode 100644 index 00000000..ce953304 --- /dev/null +++ b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/Tabs.kt @@ -0,0 +1,88 @@ +package space.kscience.visionforge.compose + +import androidx.compose.runtime.* +import app.softwork.bootstrapcompose.Card +import app.softwork.bootstrapcompose.NavbarLink +import app.softwork.bootstrapcompose.Styling +import org.jetbrains.compose.web.dom.* +import org.w3c.dom.HTMLAnchorElement +import org.w3c.dom.HTMLDivElement + + +public class ComposeTab( + public val key: String, + public val title: ContentBuilder, + public val disabled: Boolean, + public val content: ContentBuilder, +) + +@Composable +public fun Tabs( + tabs: List, + activeKey: String, + styling: (Styling.() -> Unit)? = null, + attrs: AttrBuilderContext? = null, +) { + var active by remember(activeKey) { mutableStateOf(activeKey) } + + val activeTab by derivedStateOf { tabs.find { it.key == active } } + + Card( + styling, + attrs, + header = { + Ul({ classes("nav", "nav-tabs", "card-header-tabs") }) { + tabs.forEach { tab -> + Li({ + classes("nav-item") + }) { + NavbarLink( + active = active == tab.key, + disabled = tab.disabled, + attrs = { + onClick { event -> + event.preventDefault() + active = tab.key + } + } + ) { + tab.title.invoke(this) + } + } + } + } + } + ) { + activeTab?.content?.invoke(this) + } +} + +public class TabsBuilder { + internal val tabs: MutableList = mutableListOf() + + @Composable + public fun Tab( + key: String, + label: ContentBuilder = { Text(key) }, + disabled: Boolean = false, + content: ContentBuilder, + ) { + tabs.add(ComposeTab(key, label, disabled, content)) + } + + public fun addTab(tab: ComposeTab) { + tabs.add(tab) + } +} + +@Composable +public fun Tabs( + activeKey: String? = null, + styling: (Styling.() -> Unit)? = null, + attrs: AttrBuilderContext? = null, + builder: @Composable TabsBuilder.() -> Unit, +) { + val result = TabsBuilder().apply { builder() } + + Tabs(result.tabs, activeKey ?: result.tabs.firstOrNull()?.key ?: "", styling, attrs) +} \ No newline at end of file diff --git a/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/TreeStyles.kt b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/TreeStyles.kt similarity index 89% rename from visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/TreeStyles.kt rename to visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/TreeStyles.kt index de9001ba..ab6b843a 100644 --- a/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/TreeStyles.kt +++ b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/TreeStyles.kt @@ -5,7 +5,7 @@ import org.jetbrains.compose.web.css.* @OptIn(ExperimentalComposeWebApi::class) -public object TreeStyles : StyleSheet() { +public object TreeStyles : StyleSheet(VisionForgeStyles) { /** * Remove default bullets */ @@ -46,13 +46,11 @@ public object TreeStyles : StyleSheet() { public val treeItem: String by style { alignItems(AlignItems.Center) paddingLeft(10.px) - border { - left { - width(1.px) - color(Color.lightgray) - style = LineStyle.Dashed - } - } + property("border-left", CSSBorder().apply{ + width(1.px) + color(Color.lightgray) + style = LineStyle.Dashed + }) } public val treeLabel: String by style { @@ -75,7 +73,7 @@ public object TreeStyles : StyleSheet() { alignSelf(AlignSelf.Stretch) marginAll(1.px, 5.px) backgroundColor(Color.white) - border{ + border { style(LineStyle.Solid) } borderRadius(2.px) @@ -84,7 +82,7 @@ public object TreeStyles : StyleSheet() { cursor("pointer") disabled { cursor("auto") - border{ + border { style(LineStyle.Dashed) } color(Color.lightgray) diff --git a/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/VisionForgeStyles.kt b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/VisionForgeStyles.kt new file mode 100644 index 00000000..06d1187c --- /dev/null +++ b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/VisionForgeStyles.kt @@ -0,0 +1,7 @@ +package space.kscience.visionforge.compose + +import org.jetbrains.compose.web.css.StyleSheet + +public object VisionForgeStyles: StyleSheet() { + +} \ No newline at end of file diff --git a/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/VisionTree.kt b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/VisionTree.kt similarity index 100% rename from visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/VisionTree.kt rename to visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/VisionTree.kt diff --git a/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/bootstrap.kt b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/bootstrap.kt similarity index 100% rename from visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/bootstrap.kt rename to visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/bootstrap.kt diff --git a/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/composeVision.kt b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/composeVision.kt similarity index 100% rename from visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/composeVision.kt rename to visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/composeVision.kt diff --git a/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/css.kt b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/css.kt similarity index 100% rename from visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/css.kt rename to visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/css.kt diff --git a/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/layouts.kt b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/layouts.kt similarity index 100% rename from visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/layouts.kt rename to visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/layouts.kt diff --git a/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/valueChooser.kt b/visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/valueChooser.kt similarity index 100% rename from visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/valueChooser.kt rename to visionforge-compose-html/src/jsMain/kotlin/space/kscience/visionforge/compose/valueChooser.kt diff --git a/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/Tabs.kt b/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/Tabs.kt deleted file mode 100644 index cae4e797..00000000 --- a/visionforge-compose/src/jsMain/kotlin/space/kscience/visionforge/compose/Tabs.kt +++ /dev/null @@ -1,102 +0,0 @@ -package space.kscience.visionforge.compose - -import androidx.compose.runtime.* -import org.jetbrains.compose.web.dom.* -import org.w3c.dom.HTMLDivElement -import org.w3c.dom.HTMLLIElement - - -public class ComposeTab( - public val key: String, - public val title: String, - public val content: ContentBuilder, - public val disabled: Boolean, - public val titleExt: ContentBuilder, -) - -@Composable -public fun Tabs(tabs: List, activeKey: String) { - var active by remember(activeKey) { mutableStateOf(activeKey) } - - Div({ classes("card", "text-center") }) { - Div({ classes("card-header") }) { - - Ul({ classes("nav", "nav-tabs", "card-header-tabs") }) { - tabs.forEach { tab -> - Li({ - classes("nav-item") - }) { - A(attrs = { - classes("nav-link") - if (active == tab.key) { - classes("active") - } - if (tab.disabled) { - classes("disabled") - } - onClick { - active = tab.key - } - }) { - Text(tab.title) - } - tab.titleExt.invoke(this) - } - } - } - } - tabs.find { it.key == active }?.let { tab -> - Div({ classes("card-body") }) { - tab.content.invoke(this) - } - } - } - - -} - -public class TabBuilder internal constructor(public val key: String) { - private var title: String = key - public var disabled: Boolean = false - private var content: ContentBuilder = {} - private var titleExt: ContentBuilder = {} - - @Composable - public fun Content(content: ContentBuilder) { - this.content = content - } - - @Composable - public fun Title(title: String, titleExt: ContentBuilder = {}) { - this.title = title - this.titleExt = titleExt - } - - internal fun build(): ComposeTab = ComposeTab( - key, - title, - content, - disabled, - titleExt - ) -} - -public class TabsBuilder { - public var active: String = "" - internal val tabs: MutableList = mutableListOf() - - @Composable - public fun Tab(key: String, builder: @Composable TabBuilder.() -> Unit) { - tabs.add(TabBuilder(key).apply { builder() }.build()) - } - - public fun addTab(tab: ComposeTab) { - tabs.add(tab) - } -} - -@Composable -public fun Tabs(builder: @Composable TabsBuilder.() -> Unit) { - val result = TabsBuilder().apply { builder() } - Tabs(result.tabs, result.active) -} \ No newline at end of file diff --git a/visionforge-jupyter/visionforge-jupyter-common/build.gradle.kts b/visionforge-jupyter/visionforge-jupyter-common/build.gradle.kts index b9883d9b..14984d77 100644 --- a/visionforge-jupyter/visionforge-jupyter-common/build.gradle.kts +++ b/visionforge-jupyter/visionforge-jupyter-common/build.gradle.kts @@ -7,6 +7,16 @@ description = "Jupyter api artifact including all common modules" kscience { fullStack( "js/visionforge-jupyter-common.js", + browserConfig = { + webpackTask { + cssSupport{ + enabled = true + } + scssSupport { + enabled = true + } + } + } ) dependencies { api(projects.visionforgeSolid) diff --git a/visionforge-jupyter/visionforge-jupyter-common/webpack.config.d/01.ring.js b/visionforge-jupyter/visionforge-jupyter-common/webpack.config.d/01.ring.js deleted file mode 100644 index cfb15cb8..00000000 --- a/visionforge-jupyter/visionforge-jupyter-common/webpack.config.d/01.ring.js +++ /dev/null @@ -1,24 +0,0 @@ -const ringConfig = require('@jetbrains/ring-ui/webpack.config').config; - -const path = require('path'); - -config.module.rules.push(...ringConfig.module.rules) - -config.module.rules.push( - { - test: /\.css$/, - exclude: [ - path.resolve(__dirname, "../../node_modules/@jetbrains/ring-ui") - ], - use: [ - { - loader: 'style-loader', - options: {} - }, - { - loader: 'css-loader', - options: {} - } - ] - } -) \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DUIScheme.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DUIScheme.kt index 4424e2fc..5f85cc44 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DUIScheme.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DUIScheme.kt @@ -7,7 +7,7 @@ import space.kscience.dataforge.meta.boolean public class Canvas3DUIScheme : Scheme() { - public var enabled: Boolean by boolean{true} + public var enabled: Boolean by boolean { true } public companion object : SchemeSpec(::Canvas3DUIScheme) } \ No newline at end of file diff --git a/visionforge-tables/build.gradle.kts b/visionforge-tables/build.gradle.kts index 9eb9f2cf..23912afe 100644 --- a/visionforge-tables/build.gradle.kts +++ b/visionforge-tables/build.gradle.kts @@ -7,8 +7,14 @@ val tablesVersion = "0.3.0" kscience { jvm() js { - useCommonJs() binaries.library() + browser { + webpackTask{ + scssSupport { + enabled = true + } + } + } } useSerialization() @@ -17,8 +23,8 @@ kscience { api("space.kscience:tables-kt:${tablesVersion}") } jsMain { - implementation(npm("tabulator-tables", "5.5.2")) - implementation(npm("@types/tabulator-tables", "5.5.3")) + api(npm("tabulator-tables", "5.5.2")) + api(npm("@types/tabulator-tables", "5.5.3")) } } diff --git a/visionforge-tables/src/jsMain/kotlin/tabulator/Tabulator.kt b/visionforge-tables/src/jsMain/kotlin/tabulator/Tabulator.kt index f6efd32a..8908ee89 100644 --- a/visionforge-tables/src/jsMain/kotlin/tabulator/Tabulator.kt +++ b/visionforge-tables/src/jsMain/kotlin/tabulator/Tabulator.kt @@ -5,6 +5,7 @@ "NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING") @file:JsModule("tabulator-tables") +@file:JsNonModule package tabulator diff --git a/visionforge-threejs/build.gradle.kts b/visionforge-threejs/build.gradle.kts index 6e522585..f385061c 100644 --- a/visionforge-threejs/build.gradle.kts +++ b/visionforge-threejs/build.gradle.kts @@ -14,7 +14,7 @@ kscience { commonMain { api(projects.visionforgeSolid) - api(projects.visionforgeCompose) + api(projects.visionforgeComposeHtml) } jsMain { diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt index ac757183..e3a0f20b 100644 --- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt +++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt @@ -4,6 +4,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.jetbrains.compose.web.renderComposable import org.w3c.dom.Element +import org.w3c.dom.HTMLElement import space.kscience.dataforge.context.* import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.names.* diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/compose/ThreeControls.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/compose/ThreeControls.kt index 238aea55..e37cfd6b 100644 --- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/compose/ThreeControls.kt +++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/compose/ThreeControls.kt @@ -1,6 +1,9 @@ package space.kscience.visionforge.solid.three.compose import androidx.compose.runtime.Composable +import app.softwork.bootstrapcompose.Column +import app.softwork.bootstrapcompose.Layout.Height +import app.softwork.bootstrapcompose.Row import org.jetbrains.compose.web.css.* import org.jetbrains.compose.web.dom.Button import org.jetbrains.compose.web.dom.Text @@ -18,8 +21,8 @@ internal fun CanvasControls( vision: Vision?, options: Canvas3DOptions, ) { - FlexColumn { - FlexRow({ + Column { + Row(attrs = { style { border { width(1.px) @@ -64,8 +67,11 @@ public fun ThreeControls( onSelect: (Name?) -> Unit, tabBuilder: @Composable TabsBuilder.() -> Unit = {}, ) { - Tabs { - active = "Tree" + Tabs( + styling = { + Layout.height = Height.Full + } + ) { vision?.let { vision -> Tab("Tree") { CardTitle("Vision tree") diff --git a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/compose/ThreeView.kt b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/compose/ThreeView.kt index 4b680b80..acd4882d 100644 --- a/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/compose/ThreeView.kt +++ b/visionforge-threejs/src/jsMain/kotlin/space/kscience/visionforge/solid/three/compose/ThreeView.kt @@ -2,6 +2,10 @@ package space.kscience.visionforge.solid.three.compose import androidx.compose.runtime.* import app.softwork.bootstrapcompose.Card +import app.softwork.bootstrapcompose.Column +import app.softwork.bootstrapcompose.Layout.Height +import app.softwork.bootstrapcompose.Layout.Width +import app.softwork.bootstrapcompose.Row import kotlinx.dom.clear import org.jetbrains.compose.web.ExperimentalComposeWebApi import org.jetbrains.compose.web.css.* @@ -90,24 +94,27 @@ public fun ThreeView( if (optionsSnapshot.controls.enabled) { - - FlexRow({ - style { - height(100.percent) - width(100.percent) - flexWrap(FlexWrap.Wrap) - alignItems(AlignItems.Stretch) - alignContent(AlignContent.Stretch) - } - }) { - FlexColumn({ - style { - height(100.percent) - minWidth(600.px) - flex(10, 1, 600.px) - position(Position.Relative) + Row( + styling = { + Layout { + width = Width.Full + height = Height.Full } - }) { + } + ) { + Column( + styling = { + Layout { + height = Height.Full + } + }, + attrs = { + style { + position(Position.Relative) + minWidth(600.px) + } + } + ) { if (solid == null) { Div({ style { @@ -143,61 +150,68 @@ public fun ThreeView( } selectedVision?.let { vision -> - Div({ - style { - position(Position.Absolute) - top(5.px) - right(5.px) - width(450.px) + Card( + attrs = { + style { + position(Position.Absolute) + top(5.px) + right(5.px) + width(450.px) + } + }, + headerAttrs = { + // border = true + }, + header = { + NameCrumbs(selected) { selected = it } + }, + footer = { + vision.styles.takeIf { it.isNotEmpty() }?.let { styles -> + P { + B { Text("Styles: ") } + Text(styles.joinToString(separator = ", ")) + } + } } - }) { - Card( - headerAttrs = { - // border = true + ) { + PropertyEditor( + scope = solids.context, + meta = vision.properties.root(), + getPropertyState = { name -> + if (vision.properties.own?.get(name) != null) { + EditorPropertyState.Defined + } else if (vision.properties.root()[name] != null) { + // TODO differentiate + EditorPropertyState.Default() + } else { + EditorPropertyState.Undefined + } }, - header = { - NameCrumbs(selected) { selected = it } - } - ) { - PropertyEditor( - scope = solids.context, - meta = vision.properties.root(), - getPropertyState = { name -> - if (vision.properties.own?.get(name) != null) { - EditorPropertyState.Defined - } else if (vision.properties.root()[name] != null) { - // TODO differentiate - EditorPropertyState.Default() - } else { - EditorPropertyState.Undefined - } - }, - updates = vision.properties.changes, - rootDescriptor = vision.descriptor - ) - - } - - vision.styles.takeIf { it.isNotEmpty() }?.let { styles -> - P { - B { Text("Styles: ") } - Text(styles.joinToString(separator = ", ")) - } - } + updates = vision.properties.changes, + rootDescriptor = vision.descriptor + ) } } } - } - FlexColumn({ - style { - paddingAll(4.px) - minWidth(400.px) - height(100.percent) - overflowY("auto") - flex(1, 10, 300.px) + + Column( + auto = true, + styling = { + Layout { + height = Height.Full + } + }, + attrs = { + style { + paddingAll(4.px) + minWidth(400.px) + height(100.percent) + overflowY("auto") + } + } + ) { + ThreeControls(solid, optionsSnapshot, selected, onSelect = { selected = it }, tabBuilder = sidebarTabs) } - }) { - ThreeControls(solid, optionsSnapshot, selected, onSelect = { selected = it }, tabBuilder = sidebarTabs) } } else { SimpleThreeView(solids.context, optionsSnapshot, solid, selected) diff --git a/visionforge-threejs/visionforge-threejs-server/build.gradle.kts b/visionforge-threejs/visionforge-threejs-server/build.gradle.kts index 395fea38..f6c30385 100644 --- a/visionforge-threejs/visionforge-threejs-server/build.gradle.kts +++ b/visionforge-threejs/visionforge-threejs-server/build.gradle.kts @@ -10,7 +10,7 @@ kscience { commonMain { api(projects.visionforgeSolid) - api(projects.visionforgeCompose) + api(projects.visionforgeComposeHtml) } jvmMain{ @@ -19,6 +19,8 @@ kscience { jsMain{ api(projects.visionforgeThreejs) + implementation(npm("file-saver","2.0.5")) + implementation(npm("@types/file-saver", "2.0.7")) compileOnly(npm("webpack-bundle-analyzer","4.5.0")) } } \ No newline at end of file