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
* 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
* Add opportunity to customize content in title of `Nav` after text

View File

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

View File

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

View File

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

View File

@ -1,5 +1,9 @@
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 {
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(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 (
val attributeName: String,
val skipNullValues: Boolean = true,
private val parametersPreset: MutableMap<String, String?> = mutableMapOf()
val parametersBuilder: ParametersBuilder
) {
fun add(k: String, v: Any? = null) {
if (v != null || !skipNullValues) {
parametersPreset[k] = v ?.toString()
}
fun build(): Pair<String, String> = parametersBuilder.build().run {
Pair(
attributeName, toList().joinToString(";") {
"${it.first}${it.second ?.let { ": $it" } ?: ""}"
}
)
}
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" } ?: ""}"
}
)
}
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,
skipNullValues
).apply(block).build()
ParametersBuilder(skipNullValues)
).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()