Improvements in Dropdowns and new attribute in NavItemElement

This commit is contained in:
InsanusMokrassar 2022-04-15 13:06:14 +06:00
parent 8c2ce7b75d
commit ebb350c688
9 changed files with 190 additions and 37 deletions

View File

@ -2,6 +2,9 @@
## 0.0.51 ## 0.0.51
* New interface `Dropdown` which will be used to create (or retrieve) dropdown for an element
* New attribute in `NavItemElement` for configuration of `A` element
## 0.0.50 ## 0.0.50
* Add opportunity to customize content in title of `Nav` after text * Add opportunity to customize content in title of `Nav` after text

View File

@ -1,8 +1,7 @@
package dev.inmo.jsuikit package dev.inmo.jsuikit
import dev.inmo.jsuikit.modifiers.AttributeValue import dev.inmo.jsuikit.modifiers.AttributeValue
import dev.inmo.jsuikit.utils.AttributeBuilder import dev.inmo.jsuikit.utils.*
import dev.inmo.jsuikit.utils.buildAttribute
import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.attributes.AttrsScope
@Deprecated("Will be removed soon") @Deprecated("Will be removed soon")
@ -25,7 +24,7 @@ class UIKitAttributeValueBuilder {
fun AttrsScope<*>.buildAndAddAttribute( fun AttrsScope<*>.buildAndAddAttribute(
attributeName: String, attributeName: String,
skipNullValues: Boolean = true, skipNullValues: Boolean = true,
block: AttributeBuilder.() -> Unit block: ParametersBuilder.() -> Unit
) { ) {
buildAttribute(attributeName, skipNullValues, block).let { buildAttribute(attributeName, skipNullValues, block).let {
attr(it.first, it.second) attr(it.first, it.second)

View File

@ -3,10 +3,26 @@ package dev.inmo.jsuikit.elements
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.buildAndAddAttribute import dev.inmo.jsuikit.buildAndAddAttribute
import dev.inmo.jsuikit.modifiers.* import dev.inmo.jsuikit.modifiers.*
import dev.inmo.jsuikit.types.DropdownOptions
import dev.inmo.jsuikit.utils.Milliseconds import dev.inmo.jsuikit.utils.Milliseconds
import org.jetbrains.compose.web.dom.* import org.jetbrains.compose.web.dom.*
import org.w3c.dom.HTMLDivElement import org.w3c.dom.HTMLDivElement
@Composable
fun Dropdown(
vararg modifiers: UIKitModifier,
dropdownOptions: DropdownOptions,
attributesCustomizer: AttrBuilderContext<HTMLDivElement> = {},
contentBuilder: ContentBuilder<HTMLDivElement>
) {
Div(
{
include(UIKitDropdown(dropdownOptions), *modifiers)
attributesCustomizer()
},
contentBuilder
)
}
@Composable @Composable
fun Dropdown( fun Dropdown(
vararg modifiers: UIKitModifier, vararg modifiers: UIKitModifier,
@ -26,21 +42,24 @@ fun Dropdown(
) { ) {
Div( Div(
{ {
buildAndAddAttribute("uk-dropdown") { include(
"toggle" to toggle UIKitDropdown(
"pos" to pos DropdownOptions(
"mode" to mode toggle = toggle,
"delayShow" to delayShow pos = pos,
"delayHide" to delayHide mode = mode,
"boundary" to boundary delayShow = delayShow,
"boundaryAlign" to boundaryAlign delayHide = delayHide,
"flip" to flip boundary = boundary,
"offset" to offset boundaryAlign = boundaryAlign,
"animation" to animation flip = flip,
"duration" to duration offset = offset,
} animation = animation,
classes("uk-dropdown") duration = duration
include(*modifiers) )
),
*modifiers
)
attributesCustomizer() attributesCustomizer()
}, },
contentBuilder contentBuilder

View File

@ -249,6 +249,7 @@ fun NavHeader(
fun NavItemElement( fun NavItemElement(
vararg modifiers: UIKitModifier, vararg modifiers: UIKitModifier,
attributesCustomizer: AttrBuilderContext<HTMLLIElement> = {}, attributesCustomizer: AttrBuilderContext<HTMLLIElement> = {},
anchorAttributesCustomizer: AttrBuilderContext<HTMLAnchorElement> = {},
contentAllocator: ContentBuilder<HTMLAnchorElement> contentAllocator: ContentBuilder<HTMLAnchorElement>
) { ) {
Li( Li(
@ -257,7 +258,7 @@ fun NavItemElement(
attributesCustomizer() attributesCustomizer()
} }
) { ) {
A("#") { A("#", attrs = anchorAttributesCustomizer) {
contentAllocator() contentAllocator()
} }
} }

View File

@ -1,5 +1,9 @@
package dev.inmo.jsuikit.modifiers package dev.inmo.jsuikit.modifiers
import dev.inmo.jsuikit.types.DropdownOptions
import dev.inmo.jsuikit.utils.Milliseconds
import dev.inmo.jsuikit.utils.buildAttribute
sealed class UIKitDropdown(classname: String) : UIKitModifier { sealed class UIKitDropdown(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname) override val classes: Array<String> = arrayOf(classname)
@ -64,4 +68,48 @@ sealed class UIKitDropdown(classname: String) : UIKitModifier {
} }
class Custom(
dropdownOptions: DropdownOptions
) : UIKitDropdown("uk-dropdown") {
override val otherAttrs: Map<String, String> = mapOf(
buildAttribute(
"uk-dropdown"
) {
dropdownOptions.includeParameters(this)
}
)
}
companion object {
operator fun invoke(
dropdownOptions: DropdownOptions
) = Custom(dropdownOptions)
operator fun invoke(
toggle: String? = null,
pos: Position? = null,
mode: Mode? = null,
delayShow: Milliseconds? = null,
delayHide: Milliseconds? = null,
boundary: String? = null,
boundaryAlign: Boolean? = null,
flip: Flip? = null,
offset: Int? = null,
animation: UIKitAnimation? = null,
duration: Milliseconds? = null,
) = Custom(
DropdownOptions(
toggle = toggle,
pos = pos,
mode = mode,
delayShow = delayShow,
delayHide = delayHide,
boundary = boundary,
boundaryAlign = boundaryAlign,
flip = flip,
offset = offset,
animation = animation,
duration = duration
)
)
}
} }

View File

@ -0,0 +1,44 @@
package dev.inmo.jsuikit.types
import dev.inmo.jsuikit.modifiers.UIKitAnimation
import dev.inmo.jsuikit.modifiers.UIKitDropdown
import dev.inmo.jsuikit.utils.*
external interface Dropdown {
fun show()
fun hide(delay: Boolean)
fun hide(delay: Milliseconds)
}
data class DropdownOptions(
private val toggle: String? = null,
private val pos: UIKitDropdown.Position? = null,
private val mode: UIKitDropdown.Mode? = null,
private val delayShow: Milliseconds? = null,
private val delayHide: Milliseconds? = null,
private val boundary: String? = null,
private val boundaryAlign: Boolean? = null,
private val flip: UIKitDropdown.Flip? = null,
private val offset: Int? = null,
private val animation: UIKitAnimation? = null,
private val duration: Milliseconds? = null,
) {
fun includeParameters(parametersBuilder: ParametersBuilder) {
with(parametersBuilder) {
"toggle" to toggle
"pos" to pos
"mode" to mode
"delayShow" to delayShow
"delayHide" to delayHide
"boundary" to boundary
"boundaryAlign" to boundaryAlign
"flip" to flip
"offset" to offset
"animation" to animation
"duration" to duration
}
}
fun parameters() = buildParametersWithoutNulls {
includeParameters(this)
}
}

View File

@ -13,4 +13,7 @@ external interface UIKit {
fun modal(element: Element): UIKitDialog fun modal(element: Element): UIKitDialog
fun modal(selector: String): UIKitDialog? fun modal(selector: String): UIKitDialog?
fun dropdown(element: Element, options: DropdownOptions = definedExternally): Dropdown
fun dropdown(selector: String, options: DropdownOptions = definedExternally): Dropdown?
} }

View File

@ -2,26 +2,24 @@ package dev.inmo.jsuikit.utils
class AttributeBuilder ( class AttributeBuilder (
val attributeName: String, val attributeName: String,
val skipNullValues: Boolean = true, val parametersBuilder: ParametersBuilder
private val parametersPreset: MutableMap<String, String?> = mutableMapOf()
) { ) {
fun build(): Pair<String, String> = parametersBuilder.build().run {
fun add(k: String, v: Any? = null) { Pair(
if (v != null || !skipNullValues) { attributeName, toList().joinToString(";") {
parametersPreset[k] = v ?.toString()
}
}
infix fun String.to(value: Any?) = add(this, value)
operator fun String.unaryPlus() = add(this, null)
fun build(): Pair<String, String> = Pair(
attributeName, parametersPreset.toList().joinToString(";") {
"${it.first}${it.second ?.let { ": $it" } ?: ""}" "${it.first}${it.second ?.let { ": $it" } ?: ""}"
} }
) )
} }
}
inline fun buildAttribute(attributeName: String, skipNullValues: Boolean = true, block: AttributeBuilder.() -> Unit) = AttributeBuilder( inline fun buildAttribute(
attributeName: String,
skipNullValues: Boolean = true,
block: ParametersBuilder.() -> Unit
) = AttributeBuilder(
attributeName, attributeName,
skipNullValues ParametersBuilder(skipNullValues)
).apply(block).build() ).apply {
parametersBuilder.block()
}.build()

View File

@ -0,0 +1,38 @@
package dev.inmo.jsuikit.utils
class ParametersBuilder(
val skipNullValues: Boolean = true,
private val parameters: MutableMap<String, String?> = mutableMapOf()
) {
fun add(k: String, v: Any? = null) {
if (v != null || !skipNullValues) {
parameters[k] = v ?.toString()
}
}
infix fun String.to(value: Any?) = add(this, value)
operator fun String.unaryPlus() = add(this, null)
operator fun Map<String, String?>.unaryPlus() = forEach {
}
fun build() = parameters.toMap()
fun buildNotNullable() = parameters.mapNotNull { (k, v) ->
if (v != null) {
Pair(k, v)
} else {
null
}
}.toMap()
}
fun buildParameters(
skipNullValues: Boolean = true,
block: ParametersBuilder.() -> Unit
) = ParametersBuilder(skipNullValues).apply(block).build()
fun buildParametersWithoutNulls(
skipNullValues: Boolean = true,
block: ParametersBuilder.() -> Unit
) = ParametersBuilder(skipNullValues).apply(block).buildNotNullable()