mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-05 07:18:29 +08:00
Made widget styles more reusable and customizable.
This commit is contained in:
parent
36a32018ca
commit
737a44303d
@ -53,8 +53,8 @@ class PwResultBuilder<T>(private val logger: KLogger) {
|
|||||||
Severity.Error -> logger.error(cause) { message ?: uiMessage }
|
Severity.Error -> logger.error(cause) { message ?: uiMessage }
|
||||||
}
|
}
|
||||||
|
|
||||||
problems.add(Problem(severity, uiMessage));
|
problems.add(Problem(severity, uiMessage))
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,7 +62,7 @@ class PwResultBuilder<T>(private val logger: KLogger) {
|
|||||||
*/
|
*/
|
||||||
fun addResult(result: PwResult<*>): PwResultBuilder<T> {
|
fun addResult(result: PwResult<*>): PwResultBuilder<T> {
|
||||||
problems.addAll(result.problems)
|
problems.addAll(result.problems)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun success(value: T): Success<T> =
|
fun success(value: T): Success<T> =
|
||||||
|
@ -11,11 +11,11 @@ abstract class DisposableContainer : TrackedDisposable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected fun <T : Disposable> addDisposable(disposable: T): T {
|
protected fun <T : Disposable> addDisposable(disposable: T): T {
|
||||||
return disposer.add(disposable);
|
return disposer.add(disposable)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun addDisposables(vararg disposables: Disposable) {
|
protected fun addDisposables(vararg disposables: Disposable) {
|
||||||
disposer.addAll(*disposables);
|
disposer.addAll(*disposables)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun removeDisposable(disposable: Disposable) =
|
protected fun removeDisposable(disposable: Disposable) =
|
||||||
|
@ -2,7 +2,6 @@ package world.phantasmal.observable.value.list
|
|||||||
|
|
||||||
import world.phantasmal.core.disposable.Disposable
|
import world.phantasmal.core.disposable.Disposable
|
||||||
import world.phantasmal.observable.value.Val
|
import world.phantasmal.observable.value.Val
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
interface ListVal<E> : Val<List<E>>, List<E> {
|
interface ListVal<E> : Val<List<E>>, List<E> {
|
||||||
val sizeVal: Val<Int>
|
val sizeVal: Val<Int>
|
||||||
|
@ -24,7 +24,7 @@ private fun init(): Disposable {
|
|||||||
|
|
||||||
val rootNode = document.body!!
|
val rootNode = document.body!!
|
||||||
|
|
||||||
disposer.add(Application(rootNode, HistoryApplicationUrl()))
|
disposer.add(Application(rootNode, disposer.add(HistoryApplicationUrl())))
|
||||||
|
|
||||||
return disposer
|
return disposer
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package world.phantasmal.web.application.widgets
|
package world.phantasmal.web.application.widgets
|
||||||
|
|
||||||
import org.w3c.dom.Node
|
import org.w3c.dom.Node
|
||||||
import world.phantasmal.webui.dom.div
|
import world.phantasmal.webui.dom.root
|
||||||
import world.phantasmal.webui.widgets.Widget
|
import world.phantasmal.webui.widgets.Widget
|
||||||
|
|
||||||
class ApplicationWidget(
|
class ApplicationWidget(
|
||||||
@ -9,7 +9,7 @@ class ApplicationWidget(
|
|||||||
private val mainContentWidget: MainContentWidget,
|
private val mainContentWidget: MainContentWidget,
|
||||||
) : Widget(::style) {
|
) : Widget(::style) {
|
||||||
override fun Node.createElement() =
|
override fun Node.createElement() =
|
||||||
div(className = "pw-application-application") {
|
root(className = "pw-application-application") {
|
||||||
addChild(navigationWidget)
|
addChild(navigationWidget)
|
||||||
addChild(mainContentWidget)
|
addChild(mainContentWidget)
|
||||||
}
|
}
|
||||||
@ -24,5 +24,10 @@ private fun style() = """
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.pw-application-application .pw-application-main-content {
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
@ -11,7 +11,7 @@ import world.phantasmal.webui.widgets.Widget
|
|||||||
class MainContentWidget(
|
class MainContentWidget(
|
||||||
private val ctrl: MainContentController,
|
private val ctrl: MainContentController,
|
||||||
private val toolViews: Map<PwTool, () -> Widget>,
|
private val toolViews: Map<PwTool, () -> Widget>,
|
||||||
) : Widget() {
|
) : Widget(::style) {
|
||||||
override fun Node.createElement() = div(className = "pw-application-main-content") {
|
override fun Node.createElement() = div(className = "pw-application-main-content") {
|
||||||
ctrl.tools.forEach { (tool, active) ->
|
ctrl.tools.forEach { (tool, active) ->
|
||||||
toolViews[tool]?.let { createWidget ->
|
toolViews[tool]?.let { createWidget ->
|
||||||
@ -20,3 +20,16 @@ class MainContentWidget(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("CssUnusedSymbol")
|
||||||
|
// language=css
|
||||||
|
private fun style() = """
|
||||||
|
.pw-application-main-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pw-application-main-content > * {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
@ -14,7 +14,7 @@ class NavigationWidget(private val ctrl: NavigationController) : Widget(::style)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("CssUnusedSymbol")
|
@Suppress("CssUnusedSymbol", "CssUnresolvedCustomProperty")
|
||||||
// language=css
|
// language=css
|
||||||
private fun style() = """
|
private fun style() = """
|
||||||
.pw-application-navigation {
|
.pw-application-navigation {
|
||||||
@ -23,7 +23,7 @@ private fun style() = """
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
background-color: hsl(0, 0%, 10%);
|
background-color: hsl(0, 0%, 10%);
|
||||||
border-bottom: solid 2px var(--bg-color);
|
border-bottom: solid 2px var(--pw-bg-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pw-application-navigation-spacer {
|
.pw-application-navigation-spacer {
|
||||||
@ -51,10 +51,10 @@ private fun style() = """
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: var(--control-text-color);
|
color: var(--pw-control-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pw-application-navigation-github:hover {
|
.pw-application-navigation-github:hover {
|
||||||
color: var(--control-text-color-hover);
|
color: var(--pw-control-text-color-hover);
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
@ -28,6 +28,7 @@ class PwToolButton(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("CssUnresolvedCustomProperty")
|
||||||
// language=css
|
// language=css
|
||||||
private fun style() = """
|
private fun style() = """
|
||||||
.pw-application-pw-tool-button input {
|
.pw-application-pw-tool-button input {
|
||||||
@ -52,6 +53,6 @@ private fun style() = """
|
|||||||
|
|
||||||
.pw-application-pw-tool-button input:checked + label {
|
.pw-application-pw-tool-button input:checked + label {
|
||||||
color: hsl(0, 0%, 85%);
|
color: hsl(0, 0%, 85%);
|
||||||
background-color: var(--bg-color);
|
background-color: var(--pw-bg-color);
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
@ -2,6 +2,8 @@ package world.phantasmal.web.core.controllers
|
|||||||
|
|
||||||
import world.phantasmal.web.core.stores.PwTool
|
import world.phantasmal.web.core.stores.PwTool
|
||||||
import world.phantasmal.web.core.stores.UiStore
|
import world.phantasmal.web.core.stores.UiStore
|
||||||
|
import world.phantasmal.webui.controllers.Tab
|
||||||
|
import world.phantasmal.webui.controllers.TabController
|
||||||
|
|
||||||
open class PathAwareTab(override val title: String, val path: String) : Tab
|
open class PathAwareTab(override val title: String, val path: String) : Tab
|
||||||
|
|
||||||
|
@ -25,8 +25,14 @@ class HelpWidget : Widget(::style) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("CssUnusedSymbol")
|
||||||
// language=css
|
// language=css
|
||||||
private fun style() = """
|
private fun style() = """
|
||||||
|
.pw-huntoptimizer-help {
|
||||||
|
cursor: initial;
|
||||||
|
user-select: text;
|
||||||
|
}
|
||||||
|
|
||||||
.pw-huntoptimizer-help p {
|
.pw-huntoptimizer-help p {
|
||||||
margin: 1em;
|
margin: 1em;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package world.phantasmal.web.huntoptimizer.widgets
|
package world.phantasmal.web.huntoptimizer.widgets
|
||||||
|
|
||||||
import org.w3c.dom.Node
|
import org.w3c.dom.Node
|
||||||
import world.phantasmal.web.core.widgets.TabContainer
|
import world.phantasmal.webui.widgets.TabContainer
|
||||||
import world.phantasmal.web.huntoptimizer.HuntOptimizerUrls
|
import world.phantasmal.web.huntoptimizer.HuntOptimizerUrls
|
||||||
import world.phantasmal.web.huntoptimizer.controllers.HuntOptimizerController
|
import world.phantasmal.web.huntoptimizer.controllers.HuntOptimizerController
|
||||||
import world.phantasmal.webui.dom.div
|
import world.phantasmal.webui.dom.div
|
||||||
@ -10,7 +10,7 @@ import world.phantasmal.webui.widgets.Widget
|
|||||||
class HuntOptimizerWidget(
|
class HuntOptimizerWidget(
|
||||||
private val ctrl: HuntOptimizerController,
|
private val ctrl: HuntOptimizerController,
|
||||||
private val createMethodsWidget: () -> MethodsWidget,
|
private val createMethodsWidget: () -> MethodsWidget,
|
||||||
) : Widget() {
|
) : Widget(::style) {
|
||||||
override fun Node.createElement() = div(className = "pw-huntoptimizer-hunt-optimizer") {
|
override fun Node.createElement() = div(className = "pw-huntoptimizer-hunt-optimizer") {
|
||||||
addChild(TabContainer(
|
addChild(TabContainer(
|
||||||
ctrl = ctrl,
|
ctrl = ctrl,
|
||||||
@ -29,3 +29,16 @@ class HuntOptimizerWidget(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("CssUnusedSymbol")
|
||||||
|
// language=css
|
||||||
|
private fun style() = """
|
||||||
|
.pw-huntoptimizer-hunt-optimizer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pw-huntoptimizer-hunt-optimizer > * {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package world.phantasmal.web.huntoptimizer.widgets
|
package world.phantasmal.web.huntoptimizer.widgets
|
||||||
|
|
||||||
import org.w3c.dom.Node
|
import org.w3c.dom.Node
|
||||||
import world.phantasmal.web.core.widgets.TabContainer
|
import world.phantasmal.webui.widgets.TabContainer
|
||||||
import world.phantasmal.web.huntoptimizer.controllers.MethodsController
|
import world.phantasmal.web.huntoptimizer.controllers.MethodsController
|
||||||
import world.phantasmal.webui.dom.div
|
import world.phantasmal.webui.dom.div
|
||||||
import world.phantasmal.webui.widgets.Widget
|
import world.phantasmal.webui.widgets.Widget
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
/* Defaults */
|
|
||||||
|
|
||||||
:root {
|
|
||||||
/* Basic Widget variables */
|
|
||||||
|
|
||||||
--bg-color: hsl(0, 0%, 15%);
|
|
||||||
--text-color: hsl(0, 0%, 80%);
|
|
||||||
--text-color-disabled: hsl(0, 0%, 55%);
|
|
||||||
--font-family: Verdana, Geneva, sans-serif;
|
|
||||||
--border-color: hsl(0, 0%, 25%);
|
|
||||||
--border-color-focus: hsl(0, 0%, 35%);
|
|
||||||
--border: solid 1px var(--border-color);
|
|
||||||
--border-focus: solid 1px var(--border-color-focus);
|
|
||||||
|
|
||||||
/* Scrollbars */
|
|
||||||
|
|
||||||
--scrollbar-color: hsl(0, 0%, 13%);
|
|
||||||
--scrollbar-thumb-color: hsl(0, 0%, 17%);
|
|
||||||
|
|
||||||
/* Controls */
|
|
||||||
|
|
||||||
--control-bg-color: hsl(0, 0%, 20%);
|
|
||||||
--control-bg-color-hover: hsl(0, 0%, 25%);
|
|
||||||
--control-text-color: hsl(0, 0%, 80%);
|
|
||||||
--control-text-color-hover: hsl(0, 0%, 90%);
|
|
||||||
--control-border: solid 1px hsl(0, 0%, 10%);
|
|
||||||
|
|
||||||
--control-inner-border: solid 1px hsl(0, 0%, 35%);
|
|
||||||
--control-inner-border-focus: solid 1px hsl(0, 0%, 50%);
|
|
||||||
|
|
||||||
/* Inputs */
|
|
||||||
|
|
||||||
--input-bg-color: hsl(0, 0%, 12%);
|
|
||||||
--input-bg-color-disabled: hsl(0, 0%, 15%);
|
|
||||||
--input-text-color: hsl(0, 0%, 75%);
|
|
||||||
--input-text-color-disabled: var(--text-color-disabled);
|
|
||||||
--input-border: solid 1px hsl(0, 0%, 25%);
|
|
||||||
--input-border-hover: solid 1px hsl(0, 0%, 30%);
|
|
||||||
--input-border-focus: solid 1px hsl(0, 0%, 40%);
|
|
||||||
--input-border-disabled: solid 1px hsl(0, 0%, 20%);
|
|
||||||
|
|
||||||
--input-inner-border: solid 1px hsl(0, 0%, 5%);
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
background-color: var(--scrollbar-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
|
||||||
background-color: var(--scrollbar-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
background-color: var(--scrollbar-thumb-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-corner {
|
|
||||||
background-color: var(--scrollbar-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
cursor: default;
|
|
||||||
user-select: none;
|
|
||||||
overflow: hidden;
|
|
||||||
margin: 0;
|
|
||||||
font-size: 13px;
|
|
||||||
background-color: var(--bg-color);
|
|
||||||
color: var(--text-color);
|
|
||||||
font-family: var(--font-family);
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 1.1em;
|
|
||||||
margin: 0.5em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#root *[hidden] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
@ -5,9 +5,13 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Phantasmal World</title>
|
<title>Phantasmal World</title>
|
||||||
<script src="web.js" async></script>
|
<script src="web.js" async></script>
|
||||||
<link rel="stylesheet" href="index.css">
|
<style>
|
||||||
|
body {
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package world.phantasmal.web.core.controllers
|
package world.phantasmal.webui.controllers
|
||||||
|
|
||||||
import world.phantasmal.observable.value.MutableVal
|
import world.phantasmal.observable.value.MutableVal
|
||||||
import world.phantasmal.observable.value.Val
|
import world.phantasmal.observable.value.Val
|
||||||
import world.phantasmal.observable.value.mutableVal
|
import world.phantasmal.observable.value.mutableVal
|
||||||
import world.phantasmal.webui.controllers.Controller
|
|
||||||
|
|
||||||
interface Tab {
|
interface Tab {
|
||||||
val title: String
|
val title: String
|
@ -0,0 +1,95 @@
|
|||||||
|
package world.phantasmal.webui.dom
|
||||||
|
|
||||||
|
@Suppress("CssUnusedSymbol", "CssUnresolvedCustomProperty")
|
||||||
|
// language=css
|
||||||
|
internal const val DEFAULT_STYLE = """
|
||||||
|
#pw-root {
|
||||||
|
/* Basic Widget variables */
|
||||||
|
|
||||||
|
--pw-bg-color: hsl(0, 0%, 15%);
|
||||||
|
--pw-text-color: hsl(0, 0%, 80%);
|
||||||
|
--pw-text-color-disabled: hsl(0, 0%, 55%);
|
||||||
|
--pw-font-family: Verdana, Geneva, sans-serif;
|
||||||
|
--pw-border-color: hsl(0, 0%, 25%);
|
||||||
|
--pw-border-color-focus: hsl(0, 0%, 35%);
|
||||||
|
--pw-border: solid 1px var(--pw-border-color);
|
||||||
|
--pw-border-focus: solid 1px var(--pw-border-color-focus);
|
||||||
|
|
||||||
|
/* Scrollbars */
|
||||||
|
|
||||||
|
--pw-scrollbar-color: hsl(0, 0%, 13%);
|
||||||
|
--pw-scrollbar-thumb-color: hsl(0, 0%, 17%);
|
||||||
|
|
||||||
|
/* Controls */
|
||||||
|
|
||||||
|
--pw-control-bg-color: hsl(0, 0%, 20%);
|
||||||
|
--pw-control-bg-color-hover: hsl(0, 0%, 25%);
|
||||||
|
--pw-control-text-color: hsl(0, 0%, 80%);
|
||||||
|
--pw-control-text-color-hover: hsl(0, 0%, 90%);
|
||||||
|
--pw-control-border: solid 1px hsl(0, 0%, 10%);
|
||||||
|
|
||||||
|
--pw-control-inner-border: solid 1px hsl(0, 0%, 35%);
|
||||||
|
--pw-control-inner-border-focus: solid 1px hsl(0, 0%, 50%);
|
||||||
|
|
||||||
|
/* Inputs */
|
||||||
|
|
||||||
|
--pw-input-bg-color: hsl(0, 0%, 12%);
|
||||||
|
--pw-input-bg-color-disabled: hsl(0, 0%, 15%);
|
||||||
|
--pw-input-text-color: hsl(0, 0%, 75%);
|
||||||
|
--pw-input-text-color-disabled: var(--pw-text-color-disabled);
|
||||||
|
--pw-input-border: solid 1px hsl(0, 0%, 25%);
|
||||||
|
--pw-input-border-hover: solid 1px hsl(0, 0%, 30%);
|
||||||
|
--pw-input-border-focus: solid 1px hsl(0, 0%, 40%);
|
||||||
|
--pw-input-border-disabled: solid 1px hsl(0, 0%, 20%);
|
||||||
|
|
||||||
|
--pw-input-inner-border: solid 1px hsl(0, 0%, 5%);
|
||||||
|
|
||||||
|
/* TabContainer */
|
||||||
|
|
||||||
|
--pw-tab-bg-color: hsl(0, 0%, 12%);
|
||||||
|
--pw-tab-bg-color-hover: hsl(0, 0%, 18%);
|
||||||
|
--pw-tab-bg-color-active: var(--pw-bg-color);
|
||||||
|
--pw-tab-text-color: hsl(0, 0%, 75%);
|
||||||
|
--pw-tab-text-color-hover: hsl(0, 0%, 85%);
|
||||||
|
--pw-tab-text-color-active: hsl(0, 0%, 90%);
|
||||||
|
|
||||||
|
/* Root element styling */
|
||||||
|
|
||||||
|
cursor: default;
|
||||||
|
user-select: none;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 13px;
|
||||||
|
background-color: var(--pw-bg-color);
|
||||||
|
color: var(--pw-text-color);
|
||||||
|
font-family: var(--pw-font-family), sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pw-root * {
|
||||||
|
scrollbar-color: var(--pw-scrollbar-thumb-color) var(--pw-scrollbar-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pw-root ::-webkit-scrollbar {
|
||||||
|
background-color: var(--pw-scrollbar-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pw-root ::-webkit-scrollbar-track {
|
||||||
|
background-color: var(--pw-scrollbar-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pw-root ::-webkit-scrollbar-thumb {
|
||||||
|
background-color: var(--pw-scrollbar-thumb-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pw-root ::-webkit-scrollbar-corner {
|
||||||
|
background-color: var(--pw-scrollbar-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pw-root h2 {
|
||||||
|
font-size: 1.1em;
|
||||||
|
margin: 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pw-root *[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
"""
|
@ -1,6 +1,11 @@
|
|||||||
package world.phantasmal.webui.dom
|
package world.phantasmal.webui.dom
|
||||||
|
|
||||||
|
import kotlinx.browser.document
|
||||||
|
import kotlinx.dom.appendText
|
||||||
import org.w3c.dom.AddEventListenerOptions
|
import org.w3c.dom.AddEventListenerOptions
|
||||||
|
import org.w3c.dom.HTMLElement
|
||||||
|
import org.w3c.dom.HTMLStyleElement
|
||||||
|
import org.w3c.dom.Node
|
||||||
import org.w3c.dom.events.Event
|
import org.w3c.dom.events.Event
|
||||||
import org.w3c.dom.events.EventTarget
|
import org.w3c.dom.events.EventTarget
|
||||||
import world.phantasmal.core.disposable.Disposable
|
import world.phantasmal.core.disposable.Disposable
|
||||||
@ -19,3 +24,12 @@ fun <E : Event> disposableListener(
|
|||||||
target.removeEventListener(type, listener)
|
target.removeEventListener(type, listener)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Node.root(className: String? = null, block: HTMLElement.() -> Unit): HTMLElement {
|
||||||
|
val styleEl = document.createElement("style") as HTMLStyleElement
|
||||||
|
styleEl.id = "pw-root-styles"
|
||||||
|
styleEl.appendText(DEFAULT_STYLE)
|
||||||
|
document.head!!.append(styleEl)
|
||||||
|
|
||||||
|
return div(id = "pw-root", className, block = block)
|
||||||
|
}
|
||||||
|
@ -8,7 +8,7 @@ import world.phantasmal.webui.dom.div
|
|||||||
class LazyLoader(
|
class LazyLoader(
|
||||||
hidden: Val<Boolean> = falseVal(),
|
hidden: Val<Boolean> = falseVal(),
|
||||||
private val createWidget: () -> Widget,
|
private val createWidget: () -> Widget,
|
||||||
) : Widget(NO_STYLE, hidden) {
|
) : Widget(::style, hidden) {
|
||||||
private var initialized = false
|
private var initialized = false
|
||||||
|
|
||||||
override fun Node.createElement() = div(className = "pw-lazy-loader") {
|
override fun Node.createElement() = div(className = "pw-lazy-loader") {
|
||||||
@ -20,3 +20,16 @@ class LazyLoader(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("CssUnusedSymbol")
|
||||||
|
// language=css
|
||||||
|
private fun style() = """
|
||||||
|
.pw-lazy-loader {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pw-lazy-loader > * {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
package world.phantasmal.web.core.widgets
|
package world.phantasmal.webui.widgets
|
||||||
|
|
||||||
import org.w3c.dom.Node
|
import org.w3c.dom.Node
|
||||||
import world.phantasmal.observable.value.Val
|
import world.phantasmal.observable.value.Val
|
||||||
import world.phantasmal.observable.value.falseVal
|
import world.phantasmal.observable.value.falseVal
|
||||||
import world.phantasmal.web.core.controllers.Tab
|
import world.phantasmal.webui.controllers.Tab
|
||||||
import world.phantasmal.web.core.controllers.TabController
|
import world.phantasmal.webui.controllers.TabController
|
||||||
import world.phantasmal.webui.dom.div
|
import world.phantasmal.webui.dom.div
|
||||||
import world.phantasmal.webui.dom.span
|
import world.phantasmal.webui.dom.span
|
||||||
import world.phantasmal.webui.widgets.LazyLoader
|
|
||||||
import world.phantasmal.webui.widgets.Widget
|
|
||||||
|
|
||||||
class TabContainer<T : Tab>(
|
class TabContainer<T : Tab>(
|
||||||
hidden: Val<Boolean> = falseVal(),
|
hidden: Val<Boolean> = falseVal(),
|
||||||
@ -56,11 +54,16 @@ class TabContainer<T : Tab>(
|
|||||||
@Suppress("CssUnresolvedCustomProperty", "CssUnusedSymbol")
|
@Suppress("CssUnresolvedCustomProperty", "CssUnusedSymbol")
|
||||||
// language=css
|
// language=css
|
||||||
private fun style() = """
|
private fun style() = """
|
||||||
|
.pw-tab-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.pw-tab-container-bar {
|
.pw-tab-container-bar {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
padding: 3px 3px 0 3px;
|
padding: 3px 3px 0 3px;
|
||||||
border-bottom: var(--border);
|
border-bottom: var(--pw-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pw-tab-container-tab {
|
.pw-tab-container-tab {
|
||||||
@ -69,21 +72,31 @@ private fun style() = """
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
height: calc(100% + 1px);
|
height: calc(100% + 1px);
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
border: var(--border);
|
border: var(--pw-border);
|
||||||
margin: 0 1px -1px 1px;
|
margin: 0 1px -1px 1px;
|
||||||
background-color: hsl(0, 0%, 12%);
|
background-color: var(--pw-tab-bg-color);
|
||||||
color: hsl(0, 0%, 75%);
|
color: var(--pw-tab-text-color);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pw-tab-container-tab:hover {
|
.pw-tab-container-tab:hover {
|
||||||
background-color: hsl(0, 0%, 18%);
|
background-color: var(--pw-tab-bg-color-hover);
|
||||||
color: hsl(0, 0%, 85%);
|
color: var(--pw-tab-text-color-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pw-tab-container-tab.active {
|
.pw-tab-container-tab.active {
|
||||||
background-color: var(--bg-color);
|
background-color: var(--pw-tab-bg-color-active);
|
||||||
color: hsl(0, 0%, 90%);
|
color: var(--pw-tab-text-color-active);
|
||||||
border-bottom-color: var(--bg-color);
|
border-bottom-color: var(--pw-tab-bg-color-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pw-tab-container-panes {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pw-tab-container-panes > * {
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
"""
|
"""
|
@ -22,6 +22,8 @@ abstract class Widget(
|
|||||||
private val _children = mutableListOf<Widget>()
|
private val _children = mutableListOf<Widget>()
|
||||||
|
|
||||||
private val elementDelegate = lazy {
|
private val elementDelegate = lazy {
|
||||||
|
// Add CSS declarations to stylesheet if this is the first time we're instantiating this
|
||||||
|
// widget.
|
||||||
if (style !== NO_STYLE && STYLES_ADDED.add(this::class)) {
|
if (style !== NO_STYLE && STYLES_ADDED.add(this::class)) {
|
||||||
STYLE_EL.appendText(style())
|
STYLE_EL.appendText(style())
|
||||||
}
|
}
|
||||||
@ -157,6 +159,7 @@ abstract class Widget(
|
|||||||
companion object {
|
companion object {
|
||||||
private val STYLE_EL by lazy {
|
private val STYLE_EL by lazy {
|
||||||
val el = document.createElement("style") as HTMLStyleElement
|
val el = document.createElement("style") as HTMLStyleElement
|
||||||
|
el.id = "pw-widget-styles"
|
||||||
document.head!!.append(el)
|
document.head!!.append(el)
|
||||||
el
|
el
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user