Upgrade Kotlin to 2.3.0, refine MainView, and update dependencies

Updated Kotlin Multiplatform to 2.3.0 for enhanced compatibility and improvements. Streamlined `MainView` with cleaner structure, added responsive scaling, and introduced a `HiddenCss` class. Upgraded various dependencies, including `vst-ui-base` to 2.2.3 and `midi-arrays` to 0.3.6, ensuring better functionality and consistency. Added changes to build task configurations for improved build pipelines.
This commit is contained in:
2026-01-21 17:09:11 +01:00
parent 7110188d33
commit a4eb5b62ef
8 changed files with 370 additions and 334 deletions

9
.run/JS.run.xml Normal file
View File

@@ -0,0 +1,9 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="JS" type="JavascriptDebugType" engineId="98ca6316-2f89-46d9-a9e5-fa9e2b0625b3"
uri="http://localhost:9005">
<method v="2">
<option name="Gradle.BeforeRunTask" enabled="false" tasks="buildJS" externalProjectPath="$PROJECT_DIR$" vmOptions=""
scriptParameters=""/>
</method>
</configuration>
</component>

View File

@@ -17,11 +17,11 @@
</ExternalSystemSettings> </ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess> <ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess> <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
<DebugAllEnabled>false</DebugAllEnabled> <DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest> <RunAsTest>false</RunAsTest>
<method v="2"> <GradleProfilingDisabled>false</GradleProfilingDisabled>
<option name="Gradle.BeforeRunTask" enabled="true" tasks="clean build" externalProjectPath="$PROJECT_DIR$" <GradleCoverageDisabled>false</GradleCoverageDisabled>
vmOptions="" scriptParameters=""/> <method v="2"/>
</method>
</configuration> </configuration>
</component> </component>

View File

@@ -40,7 +40,7 @@ kotlin {
val commonMain by getting { val commonMain by getting {
dependencies { dependencies {
implementation("nl.astraeus:vst-worklet-base:1.0.1") implementation("nl.astraeus:vst-worklet-base:1.0.1")
implementation("nl.astraeus:midi-arrays:0.3.4") implementation("nl.astraeus:midi-arrays:0.3.6")
} }
} }
val jsMain by getting val jsMain by getting

View File

@@ -5,12 +5,8 @@ package nl.astraeus.vst.chip
import nl.astraeus.midi.message.SortedTimedMidiMessageList import nl.astraeus.midi.message.SortedTimedMidiMessageList
import nl.astraeus.midi.message.TimedMidiMessage import nl.astraeus.midi.message.TimedMidiMessage
import nl.astraeus.tba.SlicedByteArray import nl.astraeus.tba.SlicedByteArray
import nl.astraeus.vst.ADSR import nl.astraeus.vst.*
import nl.astraeus.vst.AudioWorkletProcessor
import nl.astraeus.vst.currentTime
import nl.astraeus.vst.midi.MidiMessageHandler import nl.astraeus.vst.midi.MidiMessageHandler
import nl.astraeus.vst.registerProcessor
import nl.astraeus.vst.sampleRate
import org.khronos.webgl.Float32Array import org.khronos.webgl.Float32Array
import org.khronos.webgl.get import org.khronos.webgl.get
import org.khronos.webgl.set import org.khronos.webgl.set
@@ -392,8 +388,8 @@ class VstChipProcessor : AudioWorkletProcessor() {
val delaySampleIndex = val delaySampleIndex =
(note.sample + note.combDelayBuffer.length) % note.combDelayBuffer.length (note.sample + note.combDelayBuffer.length) % note.combDelayBuffer.length
left[i] = left[i] + (note.combDelayBuffer[delaySampleIndex] * feedback.toFloat()) //left[i] = left[i] + (note.combDelayBuffer[delaySampleIndex] * feedback.toFloat())
right[i] = right[i] + (note.combDelayBuffer[delaySampleIndex] * feedback.toFloat()) //right[i] = right[i] + (note.combDelayBuffer[delaySampleIndex] * feedback.toFloat())
note.combDelayBuffer[delaySampleIndex] = (left[i] + right[i]) / 2f note.combDelayBuffer[delaySampleIndex] = (left[i] + right[i]) / 2f
// end - comb filter delay // end - comb filter delay

View File

@@ -56,8 +56,8 @@ kotlin {
sourceSets { sourceSets {
val commonMain by getting { val commonMain by getting {
dependencies { dependencies {
api("nl.astraeus:vst-ui-base:2.0.0") api("nl.astraeus:vst-ui-base:2.2.3")
implementation("nl.astraeus:midi-arrays:0.3.4") implementation("nl.astraeus:midi-arrays:0.3.6")
} }
} }
val jsMain by getting val jsMain by getting
@@ -85,6 +85,17 @@ tasks.register<Copy>("buildJS") {
from(layout.projectDirectory.dir("web2")) from(layout.projectDirectory.dir("web2"))
into(layout.projectDirectory.dir("web")) into(layout.projectDirectory.dir("web"))
} }
tasks.register<Copy>("buildJSProd") {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
dependsOn("audio-worklet:jsBrowserDistribution")
dependsOn("jsBrowserDistribution")
from(layout.projectDirectory.dir("web1"))
into(layout.projectDirectory.dir("web"))
from(layout.projectDirectory.dir("web2"))
into(layout.projectDirectory.dir("web"))
}
/* Hardcoded deploy configuration */ /* Hardcoded deploy configuration */

View File

@@ -1,5 +1,5 @@
group = "nl.astraeus" group = "nl.astraeus"
version = "0.1.0" version = "0.2.0"
allprojects { allprojects {
repositories { repositories {

View File

@@ -1,6 +1,6 @@
pluginManagement { pluginManagement {
plugins { plugins {
kotlin("multiplatform") version "2.1.20" kotlin("multiplatform") version "2.3.0"
} }
repositories { repositories {
gradlePluginPortal() gradlePluginPortal()

View File

@@ -2,34 +2,13 @@
package nl.astraeus.vst.chip.view package nl.astraeus.vst.chip.view
import kotlinx.browser.document
import kotlinx.browser.window import kotlinx.browser.window
import kotlinx.html.InputType import kotlinx.html.*
import kotlinx.html.canvas
import kotlinx.html.classes
import kotlinx.html.div
import kotlinx.html.h1
import kotlinx.html.input
import kotlinx.html.js.onChangeFunction import kotlinx.html.js.onChangeFunction
import kotlinx.html.js.onClickFunction import kotlinx.html.js.onClickFunction
import kotlinx.html.js.onInputFunction import kotlinx.html.js.onInputFunction
import kotlinx.html.option import nl.astraeus.css.properties.*
import kotlinx.html.select
import kotlinx.html.span
import nl.astraeus.css.properties.AlignItems
import nl.astraeus.css.properties.BoxSizing
import nl.astraeus.css.properties.Display
import nl.astraeus.css.properties.FlexDirection
import nl.astraeus.css.properties.FontWeight
import nl.astraeus.css.properties.JustifyContent
import nl.astraeus.css.properties.Position
import nl.astraeus.css.properties.Transform
import nl.astraeus.css.properties.em
import nl.astraeus.css.properties.hsla
import nl.astraeus.css.properties.prc
import nl.astraeus.css.properties.px
import nl.astraeus.css.properties.rem
import nl.astraeus.css.properties.vh
import nl.astraeus.css.properties.vw
import nl.astraeus.css.style.Style import nl.astraeus.css.style.Style
import nl.astraeus.css.style.cls import nl.astraeus.css.style.cls
import nl.astraeus.komp.HtmlBuilder import nl.astraeus.komp.HtmlBuilder
@@ -50,12 +29,9 @@ import nl.astraeus.vst.ui.css.Css.noTextSelect
import nl.astraeus.vst.ui.css.CssName import nl.astraeus.vst.ui.css.CssName
import nl.astraeus.vst.ui.css.hover import nl.astraeus.vst.ui.css.hover
import org.khronos.webgl.get import org.khronos.webgl.get
import org.w3c.dom.CanvasRenderingContext2D import org.w3c.dom.*
import org.w3c.dom.HTMLCanvasElement
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.HTMLSelectElement
object WaveformView: Komponent() { object WaveformView : Komponent() {
init { init {
window.requestAnimationFrame(::onAnimationFrame) window.requestAnimationFrame(::onAnimationFrame)
@@ -102,9 +78,11 @@ object WaveformView: Komponent() {
class MainView : Komponent() { class MainView : Komponent() {
private var messages: MutableList<String> = ArrayList() private var messages: MutableList<String> = ArrayList()
var started = false var started = false
var firstRender = true
init { init {
css() css()
window.addEventListener("resize", { requestUpdate() }, Any())
} }
fun addMessage(message: String) { fun addMessage(message: String) {
@@ -122,307 +100,333 @@ class MainView : Komponent() {
override fun HtmlBuilder.render() { override fun HtmlBuilder.render() {
div(MainDivCss.name) { div(MainDivCss.name) {
if (!started) { id = "fixed-container"
div(StartSplashCss.name) { style = scaleContainer(currentElement(), 1920, 1080)
div(StartBoxCss.name) {
div(StartButtonCss.name) { div(InnerDivCss.name) {
+"START" if (!started) {
div(StartSplashCss.name) {
div(StartBoxCss.name) {
div(StartButtonCss.name) {
id = "start-button"
+"START"
}
} }
} onClickFunction = {
onClickFunction = { document.getElementById("start-button")?.classList?.add(HiddenCss.name)
VstChipWorklet.create { VstChipWorklet.create {
started = true started = true
requestUpdate() requestUpdate()
WebsocketClient.send("LOAD\n") WebsocketClient.send("LOAD\n")
}
} }
} }
} }
} h1 {
h1 { +"VST Chip"
+"VST Chip" }
} div {
div { span {
span { +"Midi input: "
+"Midi input: " select {
select {
option {
+"None"
value = "none"
}
for (mi in Midi.inputs) {
option { option {
+mi.name +"None"
value = mi.id value = "none"
selected = mi.id == Midi.currentInput?.id }
for (mi in Midi.inputs) {
option {
+mi.name
value = mi.id
selected = mi.id == Midi.currentInput?.id
}
}
onChangeFunction = { event ->
val target = event.target as HTMLSelectElement
if (target.value == "none") {
Midi.setInput(null)
} else {
Midi.setInput(target.value)
}
} }
} }
}
onChangeFunction = { event -> span {
val target = event.target as HTMLSelectElement +"channel:"
if (target.value == "none") { input {
Midi.setInput(null) type = InputType.number
} else { value = VstChipWorklet.midiChannel.toString()
Midi.setInput(target.value) onInputFunction = { event ->
val target = event.target as HTMLInputElement
println("onInput channel: $target")
VstChipWorklet.midiChannel = target.value.toInt()
} }
} }
} }
} }
span { div {
+"channel:" span(ButtonBarCss.name) {
input { +"SAVE"
type = InputType.number onClickFunction = {
value = VstChipWorklet.midiChannel.toString() val patch = VstChipWorklet.save().copy(
onInputFunction = { event -> midiId = Midi.currentInput?.id ?: "",
val target = event.target as HTMLInputElement midiName = Midi.currentInput?.name ?: ""
println("onInput channel: $target") )
VstChipWorklet.midiChannel = target.value.toInt()
WebsocketClient.send("SAVE\n${JSON.stringify(patch)}")
}
}
span(ButtonBarCss.name) {
+"STOP"
onClickFunction = {
VstChipWorklet.postDirectlyToWorklet(
TimedMidiMessage(getCurrentTime(), (0xb0 + midiChannel).toByte(), 123, 0)
.data.buffer.data
)
} }
} }
} }
div {
span(ButtonBarCss.name) {
+"Sine"
if (VstChipWorklet.waveform == 0) {
classes += SelectedCss.name
}
onClickFunction = {
VstChipWorklet.waveform = 0
requestUpdate()
}
}
span(ButtonBarCss.name) {
+"Square"
if (VstChipWorklet.waveform == 1) {
classes += SelectedCss.name
}
onClickFunction = {
VstChipWorklet.waveform = 1
requestUpdate()
}
}
span(ButtonBarCss.name) {
+"Triangle"
if (VstChipWorklet.waveform == 2) {
classes += SelectedCss.name
}
onClickFunction = {
VstChipWorklet.waveform = 2
requestUpdate()
}
}
span(ButtonBarCss.name) {
+"Sawtooth"
if (VstChipWorklet.waveform == 3) {
classes += SelectedCss.name
}
onClickFunction = {
VstChipWorklet.waveform = 3
requestUpdate()
}
}
}
div(ControlsCss.name) {
include(
ExpKnobComponent(
value = VstChipWorklet.volume,
label = "Volume",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.volume = value
}
)
include(
KnobComponent(
value = VstChipWorklet.dutyCycle,
label = "Duty cycle",
minValue = 0.0,
maxValue = 1.0,
step = 2.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.dutyCycle = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.fmModFreq,
label = "FM Freq",
minValue = 0.0,
maxValue = 2.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.fmModFreq = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.fmModAmp,
label = "FM Ampl",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.fmModAmp = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.amModFreq,
label = "AM Freq",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.amModFreq = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.amModAmp,
label = "AM Ampl",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.amModAmp = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.feedback,
label = "Feedback",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.feedback = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.delay,
label = "Delay",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.delay = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.delayDepth,
label = "Delay depth",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.delayDepth = value
}
)
}
div(ControlsCss.name) {
include(
ExpKnobComponent(
value = VstChipWorklet.attack,
label = "Attack",
minValue = 0.0,
maxValue = 5.0,
step = 25.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.attack = value / 5.0
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.decay,
label = "Decay",
minValue = 0.0,
maxValue = 5.0,
step = 25.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.decay = value / 5.0
}
)
include(
KnobComponent(
value = VstChipWorklet.sustain,
label = "Sustain",
minValue = 0.0,
maxValue = 1.0,
step = 2.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.sustain = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.release,
label = "Release",
minValue = 0.0,
maxValue = 5.0,
step = 25.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.release = value / 5.0
}
)
}
include(WaveformView)
} }
div {
span(ButtonBarCss.name) {
+"SAVE"
onClickFunction = {
val patch = VstChipWorklet.save().copy(
midiId = Midi.currentInput?.id ?: "",
midiName = Midi.currentInput?.name ?: ""
)
WebsocketClient.send("SAVE\n${JSON.stringify(patch)}")
}
}
span(ButtonBarCss.name) {
+"STOP"
onClickFunction = {
VstChipWorklet.postDirectlyToWorklet(
TimedMidiMessage(getCurrentTime(), (0xb0 + midiChannel).toByte(), 123, 0)
.data.buffer.data
)
}
}
}
div {
span(ButtonBarCss.name) {
+"Sine"
if (VstChipWorklet.waveform == 0) {
classes += SelectedCss.name
}
onClickFunction = {
VstChipWorklet.waveform = 0
requestUpdate()
}
}
span(ButtonBarCss.name) {
+"Square"
if (VstChipWorklet.waveform == 1) {
classes += SelectedCss.name
}
onClickFunction = {
VstChipWorklet.waveform = 1
requestUpdate()
}
}
span(ButtonBarCss.name) {
+"Triangle"
if (VstChipWorklet.waveform == 2) {
classes += SelectedCss.name
}
onClickFunction = {
VstChipWorklet.waveform = 2
requestUpdate()
}
}
span(ButtonBarCss.name) {
+"Sawtooth"
if (VstChipWorklet.waveform == 3) {
classes += SelectedCss.name
}
onClickFunction = {
VstChipWorklet.waveform = 3
requestUpdate()
}
}
}
div(ControlsCss.name) {
include(
ExpKnobComponent(
value = VstChipWorklet.volume,
label = "Volume",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.volume = value
}
)
include(
KnobComponent(
value = VstChipWorklet.dutyCycle,
label = "Duty cycle",
minValue = 0.0,
maxValue = 1.0,
step = 2.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.dutyCycle = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.fmModFreq,
label = "FM Freq",
minValue = 0.0,
maxValue = 2.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.fmModFreq = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.fmModAmp,
label = "FM Ampl",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.fmModAmp = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.amModFreq,
label = "AM Freq",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.amModFreq = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.amModAmp,
label = "AM Ampl",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.amModAmp = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.feedback,
label = "Feedback",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.feedback = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.delay,
label = "Delay",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.delay = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.delayDepth,
label = "Delay depth",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.delayDepth = value
}
)
}
div(ControlsCss.name) {
include(
ExpKnobComponent(
value = VstChipWorklet.attack,
label = "Attack",
minValue = 0.0,
maxValue = 5.0,
step = 25.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.attack = value / 5.0
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.decay,
label = "Decay",
minValue = 0.0,
maxValue = 5.0,
step = 25.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.decay = value / 5.0
}
)
include(
KnobComponent(
value = VstChipWorklet.sustain,
label = "Sustain",
minValue = 0.0,
maxValue = 1.0,
step = 2.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.sustain = value
}
)
include(
ExpKnobComponent(
value = VstChipWorklet.release,
label = "Release",
minValue = 0.0,
maxValue = 5.0,
step = 25.0 / 127.0,
width = 100,
height = 120,
) { value ->
VstChipWorklet.release = value / 5.0
}
)
}
include(WaveformView)
} }
} }
private fun scaleContainer(
container: Element,
containerWidth: Int,
containerHeight: Int,
): String {
val vpWidth = window.innerWidth
val vpHeight = window.innerHeight
val scaleX: Double = vpWidth / containerWidth.toDouble()
val scaleY: Double = vpHeight / containerHeight.toDouble()
val scale = if (scaleX < scaleY) scaleX else scaleY
val left = (vpWidth - containerWidth * scale) / 2
val top = (vpHeight - containerHeight * scale) / 2
return "transform: translate(${left}px, ${top}px) scale($scale);"
}
companion object MainViewCss : CssName() { companion object MainViewCss : CssName() {
object MainDivCss : CssName() object MainDivCss : CssName()
object InnerDivCss : CssName()
object ActiveCss : CssName() object ActiveCss : CssName()
object ButtonCss : CssName() object ButtonCss : CssName()
object ButtonBarCss : CssName() object ButtonBarCss : CssName()
@@ -431,6 +435,7 @@ class MainView : Komponent() {
object StartSplashCss : CssName() object StartSplashCss : CssName()
object StartBoxCss : CssName() object StartBoxCss : CssName()
object StartButtonCss : CssName() object StartButtonCss : CssName()
object HiddenCss : CssName()
object ControlsCss : CssName() object ControlsCss : CssName()
private fun css() { private fun css() {
@@ -445,10 +450,12 @@ class MainView : Komponent() {
select("html", "body") { select("html", "body") {
margin(0.px) margin(0.px)
padding(0.px) padding(0.px)
width(100.prc)
height(100.prc) height(100.prc)
overflow(Overflow.hidden)
} }
select("html", "body") { select("html", "body") {
backgroundColor(Css.currentStyle.mainBackgroundColor) backgroundColor(Css.currentStyle.mainBackgroundColor.darken(10))
color(Css.currentStyle.mainFontColor) color(Css.currentStyle.mainFontColor)
fontFamily("JetbrainsMono, monospace") fontFamily("JetbrainsMono, monospace")
@@ -478,7 +485,17 @@ class MainView : Komponent() {
minHeight(4.rem) minHeight(4.rem)
} }
select(cls(MainDivCss)) { select(cls(MainDivCss)) {
margin(1.rem) backgroundColor(Css.currentStyle.mainBackgroundColor)
width(1920.px)
height(1080.px)
position(Position.absolute)
top(0.px)
left(0.px)
transformOrigin("0 0")
select(cls(InnerDivCss)) {
padding(1.rem)
}
} }
select("select") { select("select") {
plain("appearance", "none") plain("appearance", "none")
@@ -496,17 +513,17 @@ class MainView : Komponent() {
position(Position.fixed) position(Position.fixed)
left(0.px) left(0.px)
top(0.px) top(0.px)
width(100.vw) width(1920.px)
height(100.vh) height(1080.px)
zIndex(100) zIndex(100)
backgroundColor(hsla(32, 0, 5, 0.65)) backgroundColor(hsla(32, 0, 5, 0.65))
select(cls(StartBoxCss)) { select(cls(StartBoxCss)) {
position(Position.relative) position(Position.relative)
left(25.vw) left(100.px)
top(25.vh) top(100.px)
width(50.vw) width(1720.px)
height(50.vh) height(880.px)
backgroundColor(hsla(239, 50, 10, 1.0)) backgroundColor(hsla(239, 50, 10, 1.0))
borderColor(Css.currentStyle.mainFontColor) borderColor(Css.currentStyle.mainFontColor)
borderWidth(2.px) borderWidth(2.px)
@@ -531,6 +548,9 @@ class MainView : Komponent() {
padding(1.rem) padding(1.rem)
backgroundColor(Css.currentStyle.mainBackgroundColor) backgroundColor(Css.currentStyle.mainBackgroundColor)
} }
select(HiddenCss.cls()) {
display(Display.none)
}
} }
} }