From ea5f0abbf6460a3d4f4c0a75ff5fa49057835aca Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 14 Jun 2021 16:42:02 +0300 Subject: [PATCH] Css revamp --- .../visionforge/gdml/demo/GDMLAppComponent.kt | 39 ++-- .../visionforge/gdml/demo/GdmlJsDemoApp.kt | 29 ++- demo/gdml/src/jsMain/resources/index.html | 2 +- .../visionforge/react/ThreeCanvasComponent.kt | 8 +- ui/ring/src/main/kotlin/ringui/Alert.kt | 9 +- ui/ring/src/main/kotlin/ringui/Button.kt | 10 +- ui/ring/src/main/kotlin/ringui/Dialog.kt | 9 +- ui/ring/src/main/kotlin/ringui/Dropdown.kt | 46 ++++ ui/ring/src/main/kotlin/ringui/Icon.kt | 9 +- ui/ring/src/main/kotlin/ringui/Link.kt | 9 +- ui/ring/src/main/kotlin/ringui/RingUI.kt | 14 -- .../src/main/kotlin/ringui/header/Header.kt | 6 +- .../ThreeViewWithControls.kt | 204 ++++++++++++------ .../ringPropertyEditor.kt | 15 +- .../ringThreeControls.kt | 53 ++--- 15 files changed, 307 insertions(+), 155 deletions(-) create mode 100644 ui/ring/src/main/kotlin/ringui/Dropdown.kt delete mode 100644 ui/ring/src/main/kotlin/ringui/RingUI.kt 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 d26a5ad8..1d619dfb 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 @@ -4,6 +4,7 @@ import kotlinx.browser.window import org.w3c.files.FileReader import org.w3c.files.get import react.* +import react.dom.h2 import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.fetch import space.kscience.dataforge.names.Name @@ -12,9 +13,9 @@ import space.kscience.gdml.decodeFromString import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.ring.ThreeCanvasWithControls import space.kscience.visionforge.ring.tab +import space.kscience.visionforge.root import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.Solids -import styled.styledDiv external interface GDMLAppProps : RProps { var context: Context @@ -24,8 +25,8 @@ external interface GDMLAppProps : RProps { @JsExport val GDMLApp = functionalComponent("GDMLApp") { props -> - var vision: Solid? by useState { props.vision } val visionManager = useMemo(props.context) { props.context.fetch(Solids).visionManager } + var vision: Solid? by useState { props.vision?.apply { root(visionManager) } } fun loadData(name: String, data: String) { val parsedVision = when { @@ -43,28 +44,30 @@ val GDMLApp = functionalComponent("GDMLApp") { props -> vision = parsedVision as? Solid ?: error("Parsed vision is not a solid") } - styledDiv { - child(ThreeCanvasWithControls) { - attrs { - this.context = props.context - this.solid = vision - this.selected = props.selected - tab("Load") { - fileDrop("(drag file here)") { files -> - val file = files?.get(0) - if (file != null) { - FileReader().apply { - onload = { - val string = result as String - loadData(file.name, string) - } - readAsText(file) + child(ThreeCanvasWithControls) { + attrs { + this.context = props.context + this.solid = vision + this.selected = props.selected + tab("Load") { + h2 { + +"Drag and drop .gdml or .json VisionForge files here" + } + fileDrop("(drag file here)") { files -> + val file = files?.get(0) + if (file != null) { + FileReader().apply { + onload = { + val string = result as String + loadData(file.name, string) } + readAsText(file) } } } } } + } } diff --git a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlJsDemoApp.kt b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlJsDemoApp.kt index aefb24be..dc659c7c 100644 --- a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlJsDemoApp.kt +++ b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlJsDemoApp.kt @@ -1,28 +1,45 @@ package space.kscience.visionforge.gdml.demo import kotlinx.browser.document +import kotlinx.css.* import react.child import react.dom.render import space.kscience.dataforge.context.Global import space.kscience.gdml.GdmlShowCase import space.kscience.visionforge.Application -import space.kscience.visionforge.bootstrap.useBootstrap import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.startApplication +import styled.injectGlobal private class GDMLDemoApp : Application { override fun start(state: Map) { - useBootstrap() - - val element = document.getElementById("app") ?: error("Element with id 'app' not found on page") - - val context = Global.buildContext("demo"){ + val context = Global.buildContext("gdml-demo"){ plugin(ThreePlugin) } + injectGlobal { + html{ + height = 100.pct + } + + body{ + height = 100.pct + display = Display.flex + alignItems = Align.stretch + } + + "#application"{ + width = 100.pct + display = Display.flex + alignItems = Align.stretch + } + } + + val element = document.getElementById("application") ?: error("Element with id 'application' not found on page") + render(element) { child(GDMLApp) { val vision = GdmlShowCase.cubes().toVision() diff --git a/demo/gdml/src/jsMain/resources/index.html b/demo/gdml/src/jsMain/resources/index.html index 8f5ca1ef..c468cbd5 100644 --- a/demo/gdml/src/jsMain/resources/index.html +++ b/demo/gdml/src/jsMain/resources/index.html @@ -8,6 +8,6 @@ -
+
\ No newline at end of file diff --git a/ui/react/src/main/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt b/ui/react/src/main/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt index 33b5754f..2534e746 100644 --- a/ui/react/src/main/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt +++ b/ui/react/src/main/kotlin/space/kscience/visionforge/react/ThreeCanvasComponent.kt @@ -21,11 +21,6 @@ public external interface ThreeCanvasProps : RProps { public var selected: Name? } -public external interface ThreeCanvasState : RState { - public var element: Element? -// var canvas: ThreeCanvas? -} - public val ThreeCanvasComponent: FunctionalComponent = functionalComponent( "ThreeCanvasComponent" ) { props -> @@ -55,8 +50,7 @@ public val ThreeCanvasComponent: FunctionalComponent = functio css { maxWidth = 100.vw maxHeight = 100.vh - display = Display.block - bottom = 0.px + flex(1.0, 1.0, FlexBasis.auto) } ref = elementRef } diff --git a/ui/ring/src/main/kotlin/ringui/Alert.kt b/ui/ring/src/main/kotlin/ringui/Alert.kt index 05cebfe0..db2647cb 100644 --- a/ui/ring/src/main/kotlin/ringui/Alert.kt +++ b/ui/ring/src/main/kotlin/ringui/Alert.kt @@ -1,6 +1,7 @@ package ringui import react.RBuilder +import react.RClass import react.RHandler import react.dom.WithClassName @@ -27,8 +28,14 @@ public object AlertTypes { public var LOADING: String = "loading" } +@JsModule("@jetbrains/ring-ui/components/alert/alert") +internal external object AlertModule { + @JsName("default") + val Alert: RClass +} + public fun RBuilder.ringAlert(handler: RHandler) { - RingUI.Alert { + AlertModule.Alert { handler() } } \ No newline at end of file diff --git a/ui/ring/src/main/kotlin/ringui/Button.kt b/ui/ring/src/main/kotlin/ringui/Button.kt index 040bb5da..421de6ce 100644 --- a/ui/ring/src/main/kotlin/ringui/Button.kt +++ b/ui/ring/src/main/kotlin/ringui/Button.kt @@ -2,6 +2,7 @@ package ringui import org.w3c.dom.events.MouseEvent import react.RBuilder +import react.RClass import react.RHandler import react.dom.WithClassName @@ -28,8 +29,15 @@ public external interface ButtonProps : WithClassName { public var onMouseDown: (MouseEvent) -> Unit } +@JsModule("@jetbrains/ring-ui/components/button/button") +internal external object ButtonModule { + @JsName("default") + val Button: RClass +} + + public fun RBuilder.ringButton(handler: RHandler) { - RingUI.Button { + ButtonModule.Button { handler() } } \ No newline at end of file diff --git a/ui/ring/src/main/kotlin/ringui/Dialog.kt b/ui/ring/src/main/kotlin/ringui/Dialog.kt index 90ac16b9..7df7df1a 100644 --- a/ui/ring/src/main/kotlin/ringui/Dialog.kt +++ b/ui/ring/src/main/kotlin/ringui/Dialog.kt @@ -1,6 +1,7 @@ package ringui import react.RBuilder +import react.RClass import react.RHandler import react.dom.WithClassName @@ -20,8 +21,14 @@ public external interface DialogProps : WithClassName { public var autoFocusFirst: Boolean } +@JsModule("@jetbrains/ring-ui/components/dialog/dialog") +internal external object DialogModule { + @JsName("default") + val Dialog: RClass +} + public fun RBuilder.ringDialog(show: Boolean, handler: RHandler) { - RingUI.Dialog { + DialogModule.Dialog { attrs.show = show handler() } diff --git a/ui/ring/src/main/kotlin/ringui/Dropdown.kt b/ui/ring/src/main/kotlin/ringui/Dropdown.kt new file mode 100644 index 00000000..4fde43c6 --- /dev/null +++ b/ui/ring/src/main/kotlin/ringui/Dropdown.kt @@ -0,0 +1,46 @@ +package ringui + +import org.w3c.dom.events.Event +import react.RBuilder +import react.RClass +import react.RHandler +import react.ReactElement +import react.dom.WithClassName + +public external interface AnchorProps : WithClassName + +public external interface DropdownProps : WithClassName { + /** + * Can be string, React element, or a function accepting an object with {active, pinned} properties and returning a React element + * React element should render some interactive HTML element like `button` or `a` + */ + public var anchor: dynamic //: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired, + public var initShown: Boolean + public var activeClassName: String + public var clickMode: Boolean + public var hoverMode: Boolean + public var hoverShowTimeOut: Number + public var hoverHideTimeOut: Number + public var onShow: () -> Unit + public var onHide: () -> Unit + public var onMouseEnter: (Event) -> Unit + public var onMouseLeave: (Event) -> Unit + //'data-test': PropTypes.string +} + +@JsModule("@jetbrains/ring-ui/components/dropdown/dropdown") +public external object DropdownModule { + public val Anchor: RClass + + @JsName("default") + public val Dropdown: RClass +} + + +public fun RBuilder.ringDropdown(anchor: dynamic, handler: RHandler): ReactElement = + DropdownModule.Dropdown { + attrs { + this.anchor = anchor + } + handler() + } \ No newline at end of file diff --git a/ui/ring/src/main/kotlin/ringui/Icon.kt b/ui/ring/src/main/kotlin/ringui/Icon.kt index a8ea7d66..ad41b18a 100644 --- a/ui/ring/src/main/kotlin/ringui/Icon.kt +++ b/ui/ring/src/main/kotlin/ringui/Icon.kt @@ -1,6 +1,7 @@ package ringui import react.RBuilder +import react.RClass import react.RHandler import react.dom.WithClassName @@ -14,8 +15,14 @@ public external interface IconProps : WithClassName { public var loading: Boolean } +@JsModule("@jetbrains/ring-ui/components/icon/icon") +internal external object IconModule { + @JsName("default") + val Icon: RClass +} + public fun RBuilder.ringIcon(handler: RHandler) { - RingUI.Icon { + IconModule.Icon { handler() } } \ No newline at end of file diff --git a/ui/ring/src/main/kotlin/ringui/Link.kt b/ui/ring/src/main/kotlin/ringui/Link.kt index 7688c5ce..712a30ca 100644 --- a/ui/ring/src/main/kotlin/ringui/Link.kt +++ b/ui/ring/src/main/kotlin/ringui/Link.kt @@ -2,6 +2,7 @@ package ringui import org.w3c.dom.events.MouseEvent import react.RBuilder +import react.RClass import react.RHandler import react.dom.WithClassName @@ -17,8 +18,14 @@ public external interface LinkProps : WithClassName { public var onClick: (MouseEvent) -> Unit } +@JsModule("@jetbrains/ring-ui/components/link/link") +internal external object LinkModule { + @JsName("default") + val Link: RClass +} + public fun RBuilder.ringLink(handler: RHandler) { - RingUI.Link { + LinkModule.Link { handler() } } \ No newline at end of file diff --git a/ui/ring/src/main/kotlin/ringui/RingUI.kt b/ui/ring/src/main/kotlin/ringui/RingUI.kt deleted file mode 100644 index 816627de..00000000 --- a/ui/ring/src/main/kotlin/ringui/RingUI.kt +++ /dev/null @@ -1,14 +0,0 @@ -package ringui - -import react.RClass -import ringui.header.HeaderProps - -@JsModule("@jetbrains/ring-ui") -public external object RingUI { - public val Alert: RClass - public val Button: RClass - public val Dialog: RClass - public val Header: RClass - public val Link: RClass - public val Icon: RClass -} diff --git a/ui/ring/src/main/kotlin/ringui/header/Header.kt b/ui/ring/src/main/kotlin/ringui/header/Header.kt index 379e2539..182fe6de 100644 --- a/ui/ring/src/main/kotlin/ringui/header/Header.kt +++ b/ui/ring/src/main/kotlin/ringui/header/Header.kt @@ -4,10 +4,11 @@ import react.RBuilder import react.RClass import react.RHandler import react.dom.WithClassName -import ringui.RingUI @JsModule("@jetbrains/ring-ui/components/header/header") internal external object HeaderModule { + @JsName("default") + val Header: RClass val RerenderableHeader: RClass val Logo: RClass val Tray: RClass @@ -24,8 +25,9 @@ public external interface HeaderProps : WithClassName { public var theme: String } + public fun RBuilder.ringHeader(handler: RHandler) { - RingUI.Header { + HeaderModule.Header { handler() } } diff --git a/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ThreeViewWithControls.kt b/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ThreeViewWithControls.kt index 60734c63..6fb32a4e 100644 --- a/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ThreeViewWithControls.kt +++ b/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ThreeViewWithControls.kt @@ -2,14 +2,21 @@ package space.kscience.visionforge.ring import kotlinx.css.* import react.* -import ringui.grid.RowPosition -import ringui.grid.ringCol -import ringui.grid.ringGrid -import ringui.grid.ringRow -import ringui.tabs.ringTab +import react.dom.div +import react.dom.span +import ringui.ringLink import space.kscience.dataforge.context.Context import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.NameToken +import space.kscience.dataforge.names.isEmpty +import space.kscience.dataforge.names.length +import space.kscience.visionforge.VisionGroup +import space.kscience.visionforge.allProperties +import space.kscience.visionforge.ownProperties import space.kscience.visionforge.react.ThreeCanvasComponent +import space.kscience.visionforge.react.flexColumn +import space.kscience.visionforge.react.flexRow +import space.kscience.visionforge.react.propertyEditor import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.specifications.Canvas3DOptions import styled.css @@ -22,72 +29,143 @@ public external interface ThreeCanvasWithControlsProps : RProps { public var additionalTabs: Map Unit>? } -public fun ThreeCanvasWithControlsProps.tab(title: String, block: RBuilder.()->Unit){ - additionalTabs = (additionalTabs?: emptyMap()) + (title to block) +public fun ThreeCanvasWithControlsProps.tab(title: String, block: RBuilder.() -> Unit) { + additionalTabs = (additionalTabs ?: emptyMap()) + (title to block) } -@JsExport -public val ThreeCanvasWithControls: (props: ThreeCanvasWithControlsProps) -> dynamic = - functionalComponent("ThreeViewWithControls") { props -> - var selected by useState { props.selected } - val onSelect: (Name?) -> Unit = { - selected = it - } - val options = useMemo { - Canvas3DOptions.invoke { - this.onSelect = onSelect + +public fun RBuilder.nameCrumbs(name: Name?, link: (Name) -> Unit): ReactElement = styledDiv { + div { + ringLink { + attrs { + onClick = { + link(Name.EMPTY) + } } + +"\u2302" } - styledDiv { - css { - height = 100.pct - width = 100.pct - maxHeight = 100.vh - maxWidth = 100.vw - } - ringGrid { - ringRow { + if (name != null) { + val tokens = ArrayList(name.length) + name.tokens.forEach { token -> + tokens.add(token) + val fullName = Name(tokens.toList()) + span { +"/" } + ringLink { + +token.toString() attrs { - start = RowPosition.sm - } - ringCol { - attrs { - xs = 12 - sm = 12 - md = 8 - lg = 9 - } - child(ThreeCanvasComponent) { - attrs { - this.context = props.context - this.solid = props.solid - this.selected = selected - this.options = options - } - } - } - ringCol { - attrs { - xs = 12 - sm = 12 - md = 4 - lg = 3 - } - styledDiv { - css { - padding(top = 4.px) - width = 100.pct - //border(1.px, BorderStyle.solid, Color.lightGray) - } - ringThreeControls(options, props.solid, selected, onSelect) { - props.additionalTabs?.forEach { (title, builder) -> - ringTab(title, title, builder) - } - } + onClick = { + console.log("Selected = $fullName") + link(fullName) } } } } } - } \ No newline at end of file + } + +} + +@JsExport +public val ThreeCanvasWithControls: FunctionalComponent = + functionalComponent("ThreeViewWithControls") { props -> + var selected by useState { props.selected } + + val onSelect: (Name?) -> Unit = { + selected = it + } + + val options = useMemo(props.context) { + Canvas3DOptions.invoke { + this.onSelect = onSelect + } + } + + val selectedVision = useMemo(selected) { + selected?.let { + when { + it.isEmpty() -> props.solid + else -> (props.solid as? VisionGroup)?.get(it) + } + } + } + + flexRow { + css { + flex(1.0, 1.0, FlexBasis.auto) + flexWrap = FlexWrap.wrap + alignItems = Align.stretch + alignContent = Align.stretch + } + + flexColumn { + css { + minWidth = 600.px + flex(10.0, 1.0, FlexBasis("600px")) + position = Position.relative + } + + child(ThreeCanvasComponent) { + attrs { + this.context = props.context + this.solid = props.solid + this.selected = selected + this.options = options + } + } + + selectedVision?.let { vision -> + styledDiv { + css { + position = Position.absolute + top = 10.px + right = 10.px + } + styledDiv { + css { + minWidth = 450.px + backgroundColor = Color.white + borderRadius = 3.px + borderColor = Color.blue + borderWidth = 1.px + borderStyle = BorderStyle.solid + padding(3.px) + } + propertyEditor( + ownProperties = vision.ownProperties, + allProperties = vision.allProperties(), + updateFlow = vision.propertyChanges, + descriptor = vision.descriptor, + key = selected + ) + } + } + styledDiv { + css { + position = Position.absolute + bottom = 10.px + left = 10.px + backgroundColor = Color.white + borderRadius = 3.px + borderColor = Color.blue + borderWidth = 1.px + borderStyle = BorderStyle.solid + padding(3.px) + } + nameCrumbs(selected) { selected = it } + } + } + } + flexColumn { + css { + padding(4.px) + minWidth = 400.px + flex(1.0, 10.0, FlexBasis("300px")) + alignItems = Align.stretch + alignContent = Align.stretch + //border(1.px, BorderStyle.solid, Color.lightGray) + } + ringThreeControls(options, props.solid, selected, onSelect, additionalTabs = props.additionalTabs) + } + } + } diff --git a/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ringPropertyEditor.kt b/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ringPropertyEditor.kt index ed082f03..5ef7da96 100644 --- a/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ringPropertyEditor.kt +++ b/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ringPropertyEditor.kt @@ -4,7 +4,6 @@ import org.w3c.dom.Element import react.RBuilder import react.dom.p import react.dom.render -import react.useMemo import ringui.island.ringIsland import ringui.island.ringIslandContent import ringui.island.ringIslandHeader @@ -22,14 +21,12 @@ public fun RBuilder.ringPropertyEditor( descriptor: NodeDescriptor? = vision.descriptor, key: Any? = null, ) { - - val styles = useMemo(vision, key) { - if (vision is SolidReference) { - (vision.styles + vision.prototype.styles).distinct() - } else { - vision.styles - } + val styles = if (vision is SolidReference) { + (vision.styles + vision.prototype.styles).distinct() + } else { + vision.styles } + flexColumn { ringIsland("Properties") { propertyEditor( @@ -52,7 +49,7 @@ public fun RBuilder.ringPropertyEditor( ringIslandContent { if (styles.size == 1) { val styleName = styles.first() - p{ + p { +styleName } val style = vision.getStyle(styleName) diff --git a/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ringThreeControls.kt b/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ringThreeControls.kt index 6d93088b..58b7839f 100644 --- a/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ringThreeControls.kt +++ b/ui/ring/src/main/kotlin/space.kscience.visionforge.ring/ringThreeControls.kt @@ -1,10 +1,7 @@ package space.kscience.visionforge.ring -import kotlinx.css.BorderStyle -import kotlinx.css.Color -import kotlinx.css.padding +import kotlinx.css.* import kotlinx.css.properties.border -import kotlinx.css.px import kotlinx.html.js.onClickFunction import org.w3c.dom.events.Event import org.w3c.files.Blob @@ -17,9 +14,7 @@ import ringui.tabs.ringSmartTabs import ringui.tabs.ringTab import space.kscience.dataforge.meta.withDefault import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.isEmpty import space.kscience.visionforge.Vision -import space.kscience.visionforge.VisionGroup import space.kscience.visionforge.encodeToString import space.kscience.visionforge.react.flexColumn import space.kscience.visionforge.react.flexRow @@ -27,6 +22,7 @@ import space.kscience.visionforge.react.propertyEditor import space.kscience.visionforge.react.visionTree import space.kscience.visionforge.solid.specifications.Canvas3DOptions import styled.css +import styled.styledDiv internal fun saveData(event: Event, fileName: String, mimeType: String = "text/plain", dataBuilder: () -> String) { event.stopPropagation(); @@ -89,38 +85,35 @@ public external interface ThreeControlsProps : RProps { public var vision: Vision? public var selected: Name? public var onSelect: (Name?) -> Unit + public var additionalTabs: Map Unit> } @JsExport public val ThreeControls: FunctionalComponent = functionalComponent { props -> - ringSmartTabs(if (props.selected != null) "Properties" else "Tree") { - ringTab("Canvas") { + ringSmartTabs("Tree") { + props.vision?.let { + ringTab("Tree") { + styledDiv { + css { + height = 100.pct + overflowY = Overflow.auto + } + ringIsland("Vision tree") { + visionTree(it, props.selected, props.onSelect) + } + } + } + } + ringTab("Settings") { ringIsland("Canvas configuration") { canvasControls(props.canvasOptions, props.vision) } } - props.vision?.let { - ringTab("Tree") { - ringIsland("Vision tree") { - visionTree(it, props.selected, props.onSelect) - } + props.additionalTabs.forEach { (name, handler) -> + ringTab(name){ + handler() } } - if (props.selected != null) { - ringTab("Properties") { - props.selected.let { selected -> - val selectedObject: Vision? = when { - selected == null -> null - selected.isEmpty() -> props.vision - else -> (props.vision as? VisionGroup)?.get(selected) - } - if (selectedObject != null) { - ringPropertyEditor(selectedObject, key = selected) - } - } - } - } - props.children() } } @@ -129,13 +122,13 @@ public fun RBuilder.ringThreeControls( vision: Vision?, selected: Name?, onSelect: (Name?) -> Unit = {}, - builder: RBuilder.() -> Unit = {}, + additionalTabs: Map Unit>? = null ): ReactElement = child(ThreeControls) { attrs { this.canvasOptions = canvasOptions this.vision = vision this.selected = selected this.onSelect = onSelect + this.additionalTabs = additionalTabs?: emptyMap() } - builder() } \ No newline at end of file