Compare commits

..

65 Commits

Author SHA1 Message Date
2a3f14593b use iterables for data in default tables 2022-03-01 13:26:04 +06:00
bfd6790014 start 0.0.40 2022-03-01 13:25:37 +06:00
27ad91be74 Merge pull request #40 from InsanusMokrassar/0.0.39
0.0.39
2022-03-01 01:21:19 +06:00
3c7f17523b refactor invoke functions 2022-03-01 00:49:19 +06:00
c81c1125a0 add UIKitDialog 2022-03-01 00:14:17 +06:00
2e28334b41 add support of notifications 2022-02-28 23:55:09 +06:00
7c33efa121 start 0.0.39 2022-02-28 23:54:59 +06:00
7b6a8c81b4 Merge pull request #39 from InsanusMokrassar/0.0.38
0.0.38
2022-02-25 00:36:19 +06:00
031d07d97a AttributesCollection#plus 2022-02-25 00:22:17 +06:00
a2eda2726b add UIKitToggle 2022-02-25 00:12:20 +06:00
eb15ce9281 start 0.0.38 2022-02-25 00:12:02 +06:00
3b3319c8aa Merge pull request #38 from InsanusMokrassar/0.0.37
0.0.37
2022-02-24 14:44:23 +06:00
0b40c3acf0 remove auto margin from dialog 2022-02-24 14:42:45 +06:00
ebbfac6763 fix in Accordion and UIKitAccordion.Companion 2022-02-23 23:10:19 +06:00
6f913c0a83 Accordion 2022-02-23 20:25:27 +06:00
528f6652e0 start 0.0.37 2022-02-23 20:25:13 +06:00
e3ba921018 Merge pull request #37 from InsanusMokrassar/0.0.36
0.0.36
2022-02-18 15:18:00 +06:00
44c35c6778 support of UIKitForm 2022-02-17 19:31:31 +06:00
7b06e0ecb1 add UIKitCustom 2022-02-17 17:46:15 +06:00
366971bcf5 add afterHeaderBuilder and beforeFooterBuilder in Dialog 2022-02-17 17:28:42 +06:00
d4d0adf020 vertical and horizontal in margins 2022-02-17 15:16:30 +06:00
fc2fb24fce reorder comment arguments 2022-02-17 14:57:09 +06:00
687c3ab065 start 0.0.36 2022-02-17 14:56:47 +06:00
70f1abd527 Merge pull request #36 from InsanusMokrassar/0.0.35
0.0.35
2022-02-17 14:09:11 +06:00
1785e2158e improve work with modal dialogs 2022-02-16 19:54:07 +06:00
23ec737a05 start 0.0.35 2022-02-16 19:53:28 +06:00
f7eecc01e3 Merge pull request #35 from InsanusMokrassar/0.0.34
0.0.34
2022-02-09 16:10:11 +06:00
e4c2622115 fix of class in Alert 2022-02-09 15:47:02 +06:00
1a655810bd fixes in AlertCloseButton 2022-02-09 15:28:47 +06:00
dcc8646f18 add AlertCloseButton 2022-02-09 13:53:56 +06:00
53c728d7bc make Alert#attrs to be optional 2022-02-09 13:48:06 +06:00
01349d2fac add Alert and several things in animation 2022-02-09 13:43:56 +06:00
5ac4242b68 start 0.0.34 2022-02-09 13:43:11 +06:00
c1c1f847a9 Merge pull request #34 from InsanusMokrassar/0.0.33
attribute builder now may skip nullable values
2022-02-09 01:27:47 +06:00
1f8298f626 attribute builder now may skip nullable values 2022-02-09 01:26:33 +06:00
94698a0468 Merge pull request #33 from InsanusMokrassar/0.0.33
0.0.33
2022-02-09 01:19:14 +06:00
ca8f927304 updates and attributes buildings and fixes 2022-02-09 01:18:51 +06:00
a856545471 start 0.0.33 2022-02-09 01:18:34 +06:00
41b8063c72 Merge pull request #32 from InsanusMokrassar/0.0.32
0.0.32
2022-02-08 22:09:00 +06:00
6f4f1776c4 fix in UIKitWidth#Fixed 2022-02-08 19:12:24 +06:00
e10bbdeaa0 support of UIKitHeight, AttributesBuilder and Percents/Pixels abstractions 2022-02-08 18:48:49 +06:00
9dd486090a start 0.0.32 2022-02-08 18:48:20 +06:00
4479d9b0f9 Merge pull request #31 from InsanusMokrassar/0.0.31
0.0.31
2022-01-28 14:14:42 +06:00
cef131b1d0 UIKitVisibility 2022-01-28 14:14:27 +06:00
15340eadb1 start 0.0.31 2022-01-28 14:14:14 +06:00
36ab3fe52e Merge pull request #30 from InsanusMokrassar/0.0.30
0.0.30
2022-01-28 14:01:31 +06:00
029a7804ad add UIKitComment, Comment element, upfill UIKitSubNav 2022-01-28 14:01:06 +06:00
7edea7bf74 start 0.0.30 2022-01-28 14:00:34 +06:00
b1ea6d3a61 Merge pull request #29 from InsanusMokrassar/0.0.29
0.0.29
2022-01-26 13:38:46 +06:00
a304dcf5df fixes for build 2022-01-26 13:37:59 +06:00
a88562d3c4 upfill UIKitText 2022-01-26 13:37:03 +06:00
d9a01a8ab8 start 0.0.29 2022-01-26 13:36:49 +06:00
56b1268172 Merge pull request #28 from InsanusMokrassar/0.0.28
0.0.28
2022-01-26 13:20:44 +06:00
a3c8cdcc96 Fixes in UIKitWidth 2022-01-26 13:20:14 +06:00
68d1ba6a37 start 0.0.28 2022-01-26 13:19:51 +06:00
1cf9655575 Merge pull request #27 from InsanusMokrassar/0.0.27
0.0.27
2022-01-26 00:51:54 +06:00
4a7101697a TextField -> StandardInput + fixes in it 2022-01-26 00:51:26 +06:00
17badd4724 start 0.0.27 2022-01-26 00:50:55 +06:00
39e54e8ca3 Merge pull request #26 from InsanusMokrassar/0.0.26
0.0.26
2022-01-25 23:44:43 +06:00
ed31eb01e5 add UIKitColumn 2022-01-25 23:44:22 +06:00
9d06725221 start 0.0.26 2022-01-25 23:44:15 +06:00
d8d4a7fcf1 Merge pull request #25 from InsanusMokrassar/0.0.25
0.0.25
2022-01-25 20:29:04 +06:00
252fe4a295 extend divider 2022-01-25 20:28:50 +06:00
6dbff07692 start 0.0.25 2022-01-25 20:28:34 +06:00
e94585fc7e Merge pull request #24 from InsanusMokrassar/0.0.24
0.0.24
2022-01-25 20:22:41 +06:00
46 changed files with 1254 additions and 86 deletions

View File

@@ -1,5 +1,83 @@
# Changelog
## 0.0.40
* All `DefaultTable` functions now use `Iterable` as data type
## 0.0.39
* Add support of `Notifications`
## 0.0.38
* Add support of `Toggle`
* Attributes collection now can be concatenated
## 0.0.37
* `Dialog` now do not add auto margin by default
* Support of `Accordion` element
## 0.0.36
* Reorder arguments in `DefaultComment` fun
* Add `Vertical` and `Horizontal` members in margins
* Add `afterHeaderBuilder` and `beforeFooterBuilder` properties in `Dialog` fun
* Add `UIKitCustom` to be able for simple creating of custom modifiers
* Add support of `UIKitForm`
## 0.0.35
* Add `UIKitModal`
* Improve work with dialogs
## 0.0.34
* Add `Alert`
* Add `Animation#KenBurns`
## 0.0.33
* Fixes in attributes building and related things
## 0.0.32
* Support of `UIKitHeight`
* New builder `AttributesBuilder`
* New `Percents`/`Pixels` abstractions
* Fixes in `UIKitWidth#Fixed` classnames
## 0.0.31
* Support of `UIKitVisibility`
## 0.0.30
* Add `UIKitComment`
* Including of `Comment` element
* Upfill `UIKitSubNav`
## 0.0.29
* Unfilling of `UIKitText`
## 0.0.28
* Fixes in `UIKitWidth`
## 0.0.27
* `TextField` has been renamed to `StandardInput`
* `StandardInput` now will look for changes in state
## 0.0.26
* Add UIKitColumn
## 0.0.25
* Full including of divider
## 0.0.24
* Add opportunity to fill space between header and body of table

View File

@@ -9,4 +9,4 @@ android.enableJetifier=true
# Project data
group=dev.inmo
version=0.0.24
version=0.0.40

View File

@@ -1,8 +1,11 @@
package dev.inmo.jsuikit
import dev.inmo.jsuikit.modifiers.AttributeValue
import dev.inmo.jsuikit.utils.AttributeBuilder
import dev.inmo.jsuikit.utils.buildAttribute
import org.jetbrains.compose.web.attributes.AttrsBuilder
@Deprecated("Will be removed soon")
class UIKitAttributeValueBuilder {
private val attrs = mutableListOf<Pair<String, String>>()
@@ -21,7 +24,10 @@ class UIKitAttributeValueBuilder {
fun AttrsBuilder<*>.buildAndAddAttribute(
attributeName: String,
block: UIKitAttributeValueBuilder.() -> Unit
skipNullValues: Boolean = true,
block: AttributeBuilder.() -> Unit
) {
attr(attributeName, UIKitAttributeValueBuilder().apply(block).build())
buildAttribute(attributeName, skipNullValues, block).let {
attr(it.first, it.second)
}
}

View File

@@ -0,0 +1,89 @@
package dev.inmo.jsuikit.elements
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.modifiers.UIKitAccordion
import dev.inmo.jsuikit.modifiers.include
import dev.inmo.jsuikit.utils.Attrs
import org.jetbrains.compose.web.attributes.AttrsBuilder
import org.jetbrains.compose.web.dom.*
import org.w3c.dom.*
@Composable
fun <T> Accordion(
data: Iterable<T>,
attrs: Attrs<HTMLUListElement> = Attrs.empty(),
itemAttrsBuilder: AttrsBuilder<HTMLLIElement>.(Int, T) -> Unit = { _, _ -> },
itemContentBuilder: @Composable ElementScope<HTMLLIElement>.(Int, T) -> Unit
) {
Ul(
{
include(UIKitAccordion)
attrs.builder(this)
}
) {
data.forEachIndexed { i, t ->
Li({ itemAttrsBuilder(i, t) }) {
itemContentBuilder(i, t)
}
}
}
}
@Composable
fun <T> DefaultAccordion(
data: Iterable<T>,
attrs: Attrs<HTMLUListElement> = Attrs.empty(),
itemAttrsBuilder: AttrsBuilder<HTMLLIElement>.(Int, T) -> Unit = { _, _ -> },
titleAttrsBuilder: AttrsBuilder<HTMLAnchorElement>.(Int, T) -> Unit = { _, _ -> },
titleContentBuilder: @Composable ElementScope<HTMLAnchorElement>.(Int, T) -> Unit = { _, _ -> },
beforeTitleContentBuilder: @Composable ElementScope<HTMLLIElement>.(Int, T) -> Unit = { _, _ -> },
afterTitleContentBuilder: @Composable ElementScope<HTMLLIElement>.(Int, T) -> Unit = { _, _ -> },
afterContentContentBuilder: @Composable ElementScope<HTMLLIElement>.(Int, T) -> Unit = { _, _ -> },
contentAttrsBuilder: AttrsBuilder<HTMLDivElement>.(Int, T) -> Unit = { _, _ -> },
contentContentBuilder: @Composable ElementScope<HTMLDivElement>.(Int, T) -> Unit
) = Accordion(
data,
attrs,
itemAttrsBuilder
) { i, t ->
beforeTitleContentBuilder(i, t)
A(
attrs = {
include(UIKitAccordion.Title)
titleAttrsBuilder(i, t)
}
) {
titleContentBuilder(i, t)
}
afterTitleContentBuilder(i, t)
Div(
{
include(UIKitAccordion.Content)
contentAttrsBuilder(i, t)
}
) {
contentContentBuilder(i, t)
}
afterContentContentBuilder(i, t)
}
@Composable
fun <T> DefaultAccordion(
data: Iterable<T>,
titleResolver: (Int, T) -> String,
attrs: Attrs<HTMLUListElement> = Attrs.empty(),
itemAttrsBuilder: AttrsBuilder<HTMLLIElement>.(Int, T) -> Unit = { _, _ -> },
titleAttrsBuilder: AttrsBuilder<HTMLAnchorElement>.(Int, T) -> Unit = { _, _ -> },
contentAttrsBuilder: AttrsBuilder<HTMLDivElement>.(Int, T) -> Unit = { _, _ -> },
contentContentBuilder: @Composable ElementScope<HTMLDivElement>.(Int, T) -> Unit
) = DefaultAccordion(
data,
attrs,
itemAttrsBuilder,
titleAttrsBuilder,
{ i, t ->
org.jetbrains.compose.web.dom.Text(titleResolver(i, t))
},
contentAttrsBuilder = contentAttrsBuilder,
contentContentBuilder = contentContentBuilder
)

View File

@@ -0,0 +1,49 @@
package dev.inmo.jsuikit.elements
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.buildAndAddAttribute
import dev.inmo.jsuikit.modifiers.*
import dev.inmo.jsuikit.utils.Attrs
import dev.inmo.jsuikit.utils.Milliseconds
import org.jetbrains.compose.web.dom.*
import org.w3c.dom.HTMLAnchorElement
import org.w3c.dom.HTMLDivElement
@Composable
fun Alert(
attrs: Attrs<HTMLDivElement> = Attrs.empty(),
animation: UIKitAnimation? = UIKitAnimation.Fade,
duration: Milliseconds? = null,
selClose: String? = null,
content: ContentBuilder<HTMLDivElement>
) = Div(
{
attrs.builder(this)
include(UIKitAlert)
buildAndAddAttribute("uk-alert") {
"animation" to animation ?.classes ?.firstOrNull()
"duration" to duration
"sel-close" to selClose
}
},
content
)
@Composable
fun AlertCloseButton(
attrs: Attrs<HTMLAnchorElement> = Attrs.empty(),
content: ContentBuilder<HTMLAnchorElement> = @Composable {}
) {
A(
null,
{
include(UIKitAlert.Close, UIKitIcon)
attr("uk-close", "")
classes("uk-close")
attrs.builder(this)
},
content
)
}

View File

@@ -0,0 +1,106 @@
package dev.inmo.jsuikit.elements
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.modifiers.*
import dev.inmo.jsuikit.utils.*
import org.jetbrains.compose.web.dom.*
import org.w3c.dom.*
@Composable
fun Comment(
rootAttrs: Attrs<HTMLElement> = Attrs.empty(),
headerAttrs: Attrs<HTMLElement>? = null,
headerContent: ContentBuilder<HTMLElement>? = null,
bodyAttrs: Attrs<HTMLDivElement>? = null,
bodyContent: ContentBuilder<HTMLDivElement>? = null,
) {
Article(
{
include(UIKitComment)
rootAttrs.builder(this)
}
) {
if (headerAttrs != null || headerContent != null) {
Header (
{
include(UIKitComment.Header)
headerAttrs ?.builder ?.invoke(this)
}
) {
headerContent ?.let { it(this) }
}
}
if (bodyAttrs != null || bodyContent != null) {
Div(
{
include(UIKitComment.Body)
bodyAttrs ?.builder ?.invoke(this)
}
) {
bodyContent ?.let { it(this) }
}
}
}
}
@Composable
fun DefaultComment(
rootAttrs: Attrs<HTMLElement> = Attrs.empty(),
headerGridAttrs: Attrs<HTMLDivElement>? = null,
headerAttrs: Attrs<HTMLElement>? = null,
additionalHeaderContent: ContentBuilder<HTMLElement>? = null,
avatarUrl: String? = null,
avatarAttrs: Attrs<HTMLImageElement>? = null,
titleAttrs: Attrs<HTMLHeadingElement>? = null,
titleContent: ContentBuilder<HTMLHeadingElement>? = null,
metaAttrs: Attrs<HTMLUListElement>? = null,
metaContent: ContentBuilder<HTMLUListElement>? = null,
bodyAttrs: Attrs<HTMLDivElement>? = null,
bodyContent: ContentBuilder<HTMLDivElement>? = null,
) {
Comment(
rootAttrs = rootAttrs,
headerAttrs = headerAttrs,
headerContent = {
if (arrayOf(headerGridAttrs, avatarUrl, avatarAttrs, titleAttrs, titleContent, metaAttrs, metaContent).anyNotNull()) {
Grid(
UIKitGrid.Gap.Medium, UIKitFlex.Alignment.Vertical.Middle,
attributesCustomizer = headerGridAttrs ?.builder ?: {}
) {
if (avatarUrl != null) {
Div({ include(UIKitWidth.Auto) }) {
Img(avatarUrl, attrs = avatarAttrs ?.builder)
}
}
if (arrayOf(titleAttrs, titleContent, metaAttrs, metaContent).anyNotNull()) {
Div({ include(UIKitWidth.Expand) }) {
optionallyDraw(titleAttrs, titleContent) {
H4(
{
include(UIKitComment.Title, UIKitMargin.Remove)
titleAttrs ?.builder ?.invoke(this)
}
) {
titleContent ?.invoke(this)
}
}
optionallyDraw(metaAttrs, metaContent) {
Ul (
{
include(UIKitComment.Meta, UIKitSubNav, UIKitSubNav.Divider, UIKitMargin.Remove.Top)
metaAttrs ?.builder ?.invoke(this)
}
) {
metaContent ?.invoke(this)
}
}
}
}
}
}
additionalHeaderContent ?.let { it(this) }
},
bodyAttrs = bodyAttrs,
bodyContent = bodyContent
)
}

View File

@@ -2,8 +2,7 @@ package dev.inmo.jsuikit.elements
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffectResult
import dev.inmo.jsuikit.modifiers.UIKitModifier
import dev.inmo.jsuikit.modifiers.include
import dev.inmo.jsuikit.modifiers.*
import org.jetbrains.compose.web.dom.*
import org.jetbrains.compose.web.dom.Text
import org.w3c.dom.*
@@ -18,25 +17,32 @@ private class DialogDisposableEffectResult(
) : DisposableEffectResult {
override fun dispose() {
onDispose?.invoke()
js("UIkit").modal("#${element.id}") ?.hide()
UIKit.modal("#${element.id}") ?.hide()
onDisposed?.invoke()
}
}
@Composable
fun Dialog(
title: String? = null,
vararg modifiers: UIKitModifier,
hide: (() -> Unit)? = null,
hidden: (() -> Unit)? = null,
footerBuilder: (@Composable () -> Unit)? = null,
attributesCustomizer: AttrBuilderContext<HTMLDivElement> = {},
bodyBuilder: @Composable () -> Unit
onHide: (() -> Unit)? = null,
onHidden: (() -> Unit)? = null,
dialogAttrsBuilder: AttrBuilderContext<HTMLDivElement>? = null,
headerAttrsBuilder: AttrBuilderContext<HTMLDivElement>? = null,
headerBuilder: ContentBuilder<HTMLDivElement>? = null,
afterHeaderBuilder: ContentBuilder<HTMLDivElement>? = null,
beforeFooterBuilder: ContentBuilder<HTMLDivElement>? = null,
footerAttrsBuilder: AttrBuilderContext<HTMLDivElement>? = null,
footerBuilder: ContentBuilder<HTMLDivElement>? = null,
bodyAttrsBuilder: AttrBuilderContext<HTMLDivElement>? = null,
bodyBuilder: ContentBuilder<HTMLDivElement>
) {
Div(
{
attr("uk-modal", "")
classes("uk-flex-top", "uk-modal")
if (modifiers.none { it is UIKitModal.WithCustomAttributes }) {
include(UIKitModal)
}
id("dialog${Random.nextUInt()}")
include(*modifiers)
attributesCustomizer()
@@ -44,40 +50,44 @@ fun Dialog(
) {
Div(
{
classes("uk-modal-dialog", "uk-margin-auto-vertical")
include(UIKitModal.Dialog)
dialogAttrsBuilder ?.let { it() } ?: include(UIKitMargin.Auto.Vertical)
}
) {
title ?.let {
headerBuilder ?.let {
Div(
{
classes("uk-modal-header")
include(UIKitModal.Header)
headerAttrsBuilder ?.let { it() }
}
) {
H2({ classes("uk-modal-title") }) {
Text(title)
}
it()
}
}
afterHeaderBuilder ?.let { it() }
Div(
{
classes("uk-modal-body")
include(UIKitModal.Body)
bodyAttrsBuilder ?.let { it() }
}
) {
bodyBuilder()
}
beforeFooterBuilder ?.let { it() }
footerBuilder ?.let {
Div(
{
classes("uk-modal-footer", "uk-text-right")
include(UIKitModal.Footer)
footerAttrsBuilder ?.let { it() } ?: include(UIKitText.Alignment.Horizontal.Right)
}
) {
footerBuilder()
it()
}
}
}
DisposableRefEffect {
DialogDisposableEffectResult(it, hide, hidden)
DialogDisposableEffectResult(it, onHide, onHidden)
}
DomSideEffect { htmlElement ->
@@ -85,13 +95,42 @@ fun Dialog(
wrapper = { it: Event ->
htmlElement.removeEventListener("hidden", wrapper)
htmlElement.remove()
hidden ?.invoke()
onHidden ?.invoke()
}
htmlElement.addEventListener("hidden", wrapper)
val dialog = js("UIkit").modal("#${htmlElement.id}")
dialog.show()
Unit
UIKit.modal("#${htmlElement.id}") ?.show()
}
}
}
@Composable
fun Dialog(
title: String,
vararg modifiers: UIKitModifier,
hide: (() -> Unit)? = null,
hidden: (() -> Unit)? = null,
footerBuilder: (@Composable () -> Unit)? = null,
attributesCustomizer: AttrBuilderContext<HTMLDivElement> = {},
bodyBuilder: @Composable () -> Unit
) = Dialog(
modifiers = modifiers,
headerBuilder = {
H2({ include(UIKitModal.Title) }) {
Text(title)
}
},
onHide = hide,
onHidden = hidden,
footerBuilder = footerBuilder ?.let { _ ->
{
footerBuilder()
}
},
attributesCustomizer = {
attributesCustomizer()
},
bodyBuilder = {
bodyBuilder()
}
)

View File

@@ -1,7 +1,40 @@
package dev.inmo.jsuikit.elements
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.modifiers.*
import org.jetbrains.compose.web.dom.AttrBuilderContext
import org.jetbrains.compose.web.dom.Hr
import org.w3c.dom.HTMLHRElement
object Divider {
@Composable
fun Common(
vararg modifiers: UIKitModifier,
attributesCustomizer: AttrBuilderContext<HTMLHRElement> = {}
) = Hr {
include(*modifiers)
attributesCustomizer()
}
@Composable
fun Icon(
vararg modifiers: UIKitModifier,
attributesCustomizer: AttrBuilderContext<HTMLHRElement> = {}
) = Common(
*(modifiers + UIKitDivider.Icon), attributesCustomizer = attributesCustomizer
)
@Composable
fun Small(
vararg modifiers: UIKitModifier,
attributesCustomizer: AttrBuilderContext<HTMLHRElement> = {}
) = Common(
*(modifiers + UIKitDivider.Small), attributesCustomizer = attributesCustomizer
)
@Composable
fun Vertical(
vararg modifiers: UIKitModifier,
attributesCustomizer: AttrBuilderContext<HTMLHRElement> = {}
) = Common(
*(modifiers + UIKitDivider.Vertical), attributesCustomizer = attributesCustomizer
)
}
@Composable
fun Divider() = Hr({ classes("uk-divider-icon") })

View File

@@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.buildAndAddAttribute
import dev.inmo.jsuikit.modifiers.*
import dev.inmo.jsuikit.utils.Milliseconds
import dev.inmo.jsuikit.utils.buildAttribute
import org.jetbrains.compose.web.dom.*
import org.w3c.dom.HTMLDivElement

View File

@@ -211,8 +211,7 @@ sealed class Icon(val name: String) {
onClick: ((Event) -> Unit)? = null
) {
val configurer: AttrBuilderContext<out HTMLElement> = {
classes("uk-icon")
include(*modifiers, type)
include(*modifiers, type, UIKitIcon)
attr("uk-icon", "icon: $name${if (ratio != null) { "; ratio: $ratio" } else ""}")
onClick ?.let { _ ->
onClick { onClick(it.nativeEvent) }
@@ -251,4 +250,12 @@ sealed class Icon(val name: String) {
attributesCustomizer: AttrBuilderContext<out HTMLElement> = {},
onClick: ((Event) -> Unit)? = null
) = invoke(*modifiers, type = UIKitIconType.Link, ratio = ratio, onClick = onClick, attributesCustomizer = attributesCustomizer)
@Composable
fun drawAsFormInputPart(
vararg modifiers: UIKitModifier,
ratio: Float? = null,
attributesCustomizer: AttrBuilderContext<out HTMLElement> = {},
onClick: ((Event) -> Unit)? = null
) = invoke(*modifiers, UIKitForm.Icon, ratio = ratio, onClick = onClick, attributesCustomizer = attributesCustomizer)
}

View File

@@ -0,0 +1,15 @@
package dev.inmo.jsuikit.elements
import dev.inmo.jsuikit.modifiers.UIKit
import dev.inmo.jsuikit.types.UIKitNotificationParameter
import dev.inmo.jsuikit.types.NotificationsGroup
import dev.inmo.jsuikit.types.invoke
import dev.inmo.jsuikit.utils.Milliseconds
fun Notification(
message: String,
status: UIKitNotificationParameter.Style? = null,
timeout: Milliseconds? = null,
group: NotificationsGroup? = null,
position: UIKitNotificationParameter.Position? = null
) = UIKit.notification.invoke(message, status, timeout, group, position)

View File

@@ -23,4 +23,4 @@ fun Spinner(
}
@Composable
fun DefaultSpinner() = Spinner(UIKitAlign.Center, UIKitMargin.Small, UIKitText.Alignment.Center)
fun DefaultSpinner() = Spinner(UIKitAlign.Center, UIKitMargin.Small, UIKitText.Alignment.Horizontal.Center, UIKitText.Alignment.Vertical.Middle)

View File

@@ -9,7 +9,7 @@ import org.jetbrains.compose.web.dom.Input
import org.w3c.dom.HTMLInputElement
@Composable
fun <T> TextField(
fun <T> StandardInput(
type: InputType<T>,
state: MutableState<T>,
disabledState: State<Boolean>? = null,
@@ -23,7 +23,16 @@ fun <T> TextField(
placeholder ?.let(::placeholder)
onChange { state.value = it.value }
state.value.let {
when (it) {
is String -> value(it)
is Number -> value(it)
else -> {}
}
}
onInput { state.value = it.value }
disabledState ?.let {
if (it.value) {
disabled()
@@ -32,3 +41,14 @@ fun <T> TextField(
attributesCustomizer()
}
}
@Composable
@Deprecated("Renamed", ReplaceWith("StandardInput", "dev.inmo.jsuikit.elements.StandardInput"))
fun <T> TextField(
type: InputType<T>,
state: MutableState<T>,
disabledState: State<Boolean>? = null,
placeholder: String? = null,
vararg modifiers: UIKitModifier,
attributesCustomizer: AttrBuilderContext<HTMLInputElement> = {},
) = StandardInput(type, state, disabledState, placeholder, modifiers = modifiers, attributesCustomizer)

View File

@@ -11,7 +11,7 @@ import org.w3c.dom.*
@Composable
fun <T> DefaultTable(
headerBuilders: List<ContentBuilder<HTMLTableCellElement>>,
dataList: SnapshotStateList<T>,
dataList: Iterable<T>,
vararg tableModifiers: UIKitModifier,
attributesCustomizer: AttrBuilderContext<HTMLTableElement> = {},
headerCustomizer: AttrBuilderContext<HTMLTableSectionElement> = {},
@@ -68,7 +68,7 @@ fun <T> DefaultTable(
@Composable
fun <T> DefaultTable(
heading: List<String>,
dataList: SnapshotStateList<T>,
dataList: Iterable<T>,
vararg tableModifiers: UIKitModifier,
attributesCustomizer: AttrBuilderContext<HTMLTableElement> = {},
headerCustomizer: AttrBuilderContext<HTMLTableSectionElement> = {},

View File

@@ -1,4 +1,6 @@
package dev.inmo.jsuikit.modifiers
inline val UIKit
get() = js("UIkit")
import dev.inmo.jsuikit.types.UIKit
inline val UIKit: UIKit
get() = js("UIkit").unsafeCast<UIKit>()

View File

@@ -0,0 +1,51 @@
package dev.inmo.jsuikit.modifiers
import dev.inmo.jsuikit.utils.*
import org.w3c.dom.PageTransitionEvent
sealed class UIKitAccordion(
vararg classnames: String,
override val otherAttrs: Map<String, String> = emptyMap()
) : UIKitModifier {
@Suppress("UNCHECKED_CAST")
override val classes: Array<String> = classnames as Array<String>
object Title : UIKitAccordion("uk-accordion-title")
object Content : UIKitAccordion("uk-accordion-content")
class Custom internal constructor(
otherAttrs: Map<String, String> = emptyMap()
) : UIKitAccordion (otherAttrs = otherAttrs)
companion object : UIKitAccordion("uk-accordion", otherAttrs = mapOf("uk-accordion" to "")) {
val Open = UIKitUtility.Open
operator fun invoke(
activeItemIndex: Int? = null,
animation: Boolean? = null,
collapsible: Boolean? = null,
contentSelector: String? = null,
animationDuration: Milliseconds? = null,
multiple: Boolean? = null,
targetsSelector: String? = null,
toggleSelector: String? = null,
transition: PageTransitionEvent? = null,
offsetTopPixels: Int? = null,
) = Custom(
mapOf(
buildAttribute("uk-accordion") {
"active" to activeItemIndex
"animation" to animation
"collapsible" to collapsible
"content" to contentSelector
"duration" to animationDuration
"multiple" to multiple
"targets" to targetsSelector
"toggle" to toggleSelector
"transition" to transition
"offset" to offsetTopPixels
}
)
)
}
}

View File

@@ -0,0 +1,18 @@
package dev.inmo.jsuikit.modifiers
sealed class UIKitAlert(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
sealed class Style(classname: String) : UIKitAlert(classname) {
object Primary : Style("uk-alert-primary")
object Success : Style("uk-alert-success")
object Warning : Style("uk-alert-warning")
object Danger : Style("uk-alert-danger")
}
object Close : UIKitAlert("uk-alert-close")
companion object : UIKitAlert("uk-alert")
}

View File

@@ -60,4 +60,9 @@ sealed class UIKitAnimation (name: String) : UIKitModifier, AttributeValue(name)
object Fast : UIKitAnimation("fast")
object KenBurns : UIKitAnimation("kenburns")
override fun toString(): String {
return classes.joinToString(" ")
}
}

View File

@@ -0,0 +1,14 @@
package dev.inmo.jsuikit.modifiers
sealed class UIKitBase(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
sealed class Heading(suffix: String) : UIKitBase("uk-h$suffix") {
object H1 : Heading("1")
object H2 : Heading("2")
object H3 : Heading("3")
object H4 : Heading("4")
object H5 : Heading("5")
object H6 : Heading("6")
}
}

View File

@@ -0,0 +1,15 @@
package dev.inmo.jsuikit.modifiers
sealed class UIKitColumn(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
object Two : UIKitColumn("uk-column-1-2")
object Three : UIKitColumn("uk-column-1-3")
object Four : UIKitColumn("uk-column-1-4")
object Five : UIKitColumn("uk-column-1-5")
object Six : UIKitColumn("uk-column-1-6")
object Divider : UIKitColumn("uk-column-divider")
object Span : UIKitColumn("uk-column-span")
}

View File

@@ -0,0 +1,17 @@
package dev.inmo.jsuikit.modifiers
sealed class UIKitComment(suffix: String?) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-comment${suffix ?.let { "-$it" } ?: ""}")
object Body : UIKitComment("body")
object Header : UIKitComment("header")
object Title : UIKitComment("title")
object Meta : UIKitComment("meta")
object Avatar : UIKitComment("avatar")
object Primary : UIKitComment("primary")
object List : UIKitComment("list")
companion object : UIKitComment(null)
}

View File

@@ -0,0 +1,6 @@
package dev.inmo.jsuikit.modifiers
class UIKitCustom(
override val classes: Array<String> = emptyArray(),
override val otherAttrs: Map<String, String> = emptyMap()
) : UIKitModifier

View File

@@ -0,0 +1,10 @@
package dev.inmo.jsuikit.modifiers
sealed class UIKitDivider(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
object Icon : UIKitDivider("uk-divider-icon")
object Small : UIKitDivider("uk-divider-small")
object Vertical : UIKitDivider("uk-divider-vertical")
}

View File

@@ -0,0 +1,58 @@
package dev.inmo.jsuikit.modifiers
import dev.inmo.jsuikit.utils.buildAttribute
sealed class UIKitForm(
vararg classnames: String,
override val otherAttrs: Map<String, String> = emptyMap()
) : UIKitModifier {
@Suppress("UNCHECKED_CAST")
override val classes: Array<String> = classnames as Array<String>
object Fieldset : UIKitForm("uk-fieldset")
object Legend : UIKitForm("uk-legend")
object Input : UIKitForm("uk-input")
object Select : UIKitForm("uk-select")
object TextArea : UIKitForm("uk-textarea")
object Radio : UIKitForm("uk-radio", otherAttrs = mapOf("type" to "radio"))
object Checkbox : UIKitForm("uk-checkbox", otherAttrs = mapOf("type" to "checkbox"))
object Range : UIKitForm("uk-range", otherAttrs = mapOf("type" to "range"))
sealed class State(vararg classnames: String) : UIKitForm(*classnames) {
object Danger : State("uk-form-danger")
object Success : State("uk-form-success")
}
sealed class Size(vararg classnames: String) : UIKitForm(*classnames) {
object Large : Size("uk-form-large")
object Default : Size() // :)
object Small : Size("uk-form-small")
}
sealed class Width(vararg classnames: String) : UIKitForm(*classnames) {
object Large : Width("uk-form-width-large")
object Medium : Width("uk-form-width-medium")
object Small : Width("uk-form-width-small")
object XSmall : Width("uk-form-width-xsmall")
}
object Blank : UIKitForm("uk-form-blank")
sealed class Layout(vararg classnames: String) : UIKitForm(*classnames) {
object Stacked : Layout("uk-form-stacked")
object Horizontal : Layout("uk-form-horizontal")
object Label : Layout("uk-form-label")
object Controls : Layout("uk-form-controls")
}
object Icon : UIKitForm("uk-form-icon")
class Custom(
target: String = "true"
) : UIKitForm(
otherAttrs = mapOf(
buildAttribute("uk-form-custom") {
"target" to target
}
)
)
}

View File

@@ -0,0 +1,80 @@
package dev.inmo.jsuikit.modifiers
import dev.inmo.jsuikit.utils.*
import org.jetbrains.compose.web.css.CSSKeyframe
sealed class UIKitHeight(
classname: String?,
override val otherAttrs: Map<String, String> = emptyMap()
) : UIKitModifier {
override val classes: Array<String> = classname ?.let { arrayOf(it) } ?: emptyArray()
object Full : UIKitHeight("uk-height-1-1")
sealed class Size(classname: String) : UIKitHeight(classname) {
sealed class Small(classname: String = "uk-height-small") : Size(classname) {
object Max : Small("uk-height-max-small")
companion object : Small()
}
sealed class Medium(classname: String = "uk-height-medium") : Size(classname) {
object Max : Medium("uk-height-max-medium")
companion object : Medium()
}
sealed class Large(classname: String = "uk-height-large") : Size(classname) {
object Max : Large("uk-height-max-large")
companion object : Large()
}
}
class Viewport(offsetTop: Boolean? = null, offsetBottom: String? = null, expand: Boolean? = null, minHeight: Int? = null) : UIKitHeight(
null,
mapOf(
buildAttribute("uk-height-viewport") {
offsetTop ?.let { "offset-top" to it.toString() }
offsetBottom ?.let { "offset-bottom" to it }
expand ?.let { "expand" to it.toString() }
minHeight ?.let { "min-height" to it.toString() }
}
)
)
fun Viewport(
offsetTop: Boolean? = null,
offsetBottom: Boolean,
expand: Boolean? = null,
minHeight: Int? = null
) = Viewport(offsetTop, offsetBottom.toString(), expand, minHeight)
fun Viewport(
offsetTop: Boolean? = null,
offsetBottom: Pixels,
expand: Boolean? = null,
minHeight: Int? = null
) = Viewport(offsetTop, offsetBottom.toString(), expand, minHeight)
fun Viewport(
offsetTop: Boolean? = null,
offsetBottom: Percents,
expand: Boolean? = null,
minHeight: Int? = null
) = Viewport(offsetTop, offsetBottom.toString(), expand, minHeight)
class Match(target: String? = null, row: Boolean? = null) : UIKitHeight(
null,
mapOf(
buildAttribute("uk-height-match") {
target ?.let { "target" to it }
row ?.let { "row" to it.toString() }
}
)
)
}

View File

@@ -0,0 +1,7 @@
package dev.inmo.jsuikit.modifiers
sealed class UIKitIcon(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
companion object : UIKitIcon("uk-icon")
}

View File

@@ -1,68 +1,87 @@
package dev.inmo.jsuikit.modifiers
sealed class UIKitMargin(val classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
sealed class UIKitMargin(vararg classnames: String) : UIKitModifier {
@Suppress("UNCHECKED_CAST")
override val classes: Array<String> = classnames as Array<String>
object Top : Small("uk-margin-top")
object Bottom : Small("uk-margin-bottom")
object Left : Small("uk-margin-left")
object Right : Small("uk-margin-right")
object Top : UIKitMargin("uk-margin-top")
object Bottom : UIKitMargin("uk-margin-bottom")
object Left : UIKitMargin("uk-margin-left")
object Right : UIKitMargin("uk-margin-right")
object Vertical : UIKitMargin() { override val classes: Array<String> = Top.classes + Bottom.classes }
object Horizontal : UIKitMargin() { override val classes: Array<String> = Left.classes + Right.classes }
companion object : Small("uk-margin")
sealed class Small(classname: String) : UIKitMargin(classname) {
sealed class Small(vararg classnames: String) : UIKitMargin(*classnames) {
object Top : Small("uk-margin-small-top")
object Bottom : Small("uk-margin-small-bottom")
object Left : Small("uk-margin-small-left")
object Right : Small("uk-margin-small-right")
object Vertical : Small() {
override val classes: Array<String> = Top.classes + Bottom.classes
}
object Horizontal : Small() {
override val classes: Array<String> = Left.classes + Right.classes
}
companion object : Small("uk-margin-small")
}
sealed class Medium(classname: String) : UIKitMargin(classname) {
sealed class Medium(vararg classnames: String) : UIKitMargin(*classnames) {
object Top : Medium("uk-margin-medium-top")
object Bottom : Medium("uk-margin-medium-bottom")
object Left : Medium("uk-margin-medium-left")
object Right : Medium("uk-margin-medium-right")
object Vertical : Medium() { override val classes: Array<String> = Top.classes + Bottom.classes }
object Horizontal : Medium() { override val classes: Array<String> = Left.classes + Right.classes }
companion object : Medium("uk-margin-medium")
}
sealed class Large(classname: String) : UIKitMargin(classname) {
sealed class Large(vararg classnames: String) : UIKitMargin(*classnames) {
object Top : Large("uk-margin-large-top")
object Bottom : Large("uk-margin-large-bottom")
object Left : Large("uk-margin-large-left")
object Right : Large("uk-margin-large-right")
object Vertical : Large() { override val classes: Array<String> = Top.classes + Bottom.classes }
object Horizontal : Large() { override val classes: Array<String> = Left.classes + Right.classes }
companion object : Large("uk-margin-large")
}
sealed class XLarge(classname: String) : UIKitMargin(classname) {
sealed class XLarge(vararg classnames: String) : UIKitMargin(*classnames) {
object Top : XLarge("uk-margin-xlarge-top")
object Bottom : XLarge("uk-margin-xlarge-bottom")
object Left : XLarge("uk-margin-xlarge-left")
object Right : XLarge("uk-margin-xlarge-right")
object Vertical : XLarge() { override val classes: Array<String> = Top.classes + Bottom.classes }
object Horizontal : XLarge() { override val classes: Array<String> = Left.classes + Right.classes }
companion object : XLarge("uk-margin-xlarge")
}
sealed class Auto(classname: String) : UIKitMargin(classname) {
sealed class Auto(vararg classnames: String) : UIKitMargin(*classnames) {
object Top : Auto("uk-margin-auto-top")
object Bottom : Auto("uk-margin-auto-bottom")
object Left : Auto("uk-margin-auto-left")
object Right : Auto("uk-margin-auto-right")
object Vertical : Auto("uk-margin-auto-vertical")
object Horizontal : Auto() { override val classes: Array<String> = Left.classes + Right.classes }
companion object : Auto("uk-margin-auto")
}
sealed class Remove(classname: String) : UIKitMargin(classname) {
sealed class Remove(vararg classnames: String) : UIKitMargin(*classnames) {
object Top : Remove("uk-margin-remove-top")
object Bottom : Remove("uk-margin-remove-bottom")
object Left : Remove("uk-margin-remove-left")
object Right : Remove("uk-margin-remove-right")
object Vertical : Remove("uk-margin-remove-vertical")
object Horizontal : Remove() { override val classes: Array<String> = Left.classes + Right.classes }
object Adjacent : Remove("uk-margin-remove-adjacent")
object FirstChild : Remove("uk-margin-remove-first-child")
object LastChild : Remove("uk-margin-remove-last-child")

View File

@@ -0,0 +1,58 @@
package dev.inmo.jsuikit.modifiers
import dev.inmo.jsuikit.utils.buildAttribute
sealed class UIKitModal(
classname: String,
override val otherAttrs: Map<String, String> = emptyMap()
) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
object Dialog : UIKitModal("uk-modal-dialog")
object Title : UIKitModal("uk-modal-title")
object Header : UIKitModal("uk-modal-header")
object Body : UIKitModal("uk-modal-body")
object Footer : UIKitModal("uk-modal-footer")
object Container : UIKitModal("uk-modal-container")
object Full : UIKitModal("uk-modal-full")
object Page : UIKitModal("uk-modal-page")
sealed class Close(classname: String) : UIKitModal(classname) {
object Default : Close("uk-modal-close-default")
object Outside : Close("uk-modal-close-outside")
object Full : Close("uk-modal-close-full")
companion object : Close("uk-modal-close")
}
internal class WithCustomAttributes(
otherAttrs: Map<String, String> = emptyMap()
) : UIKitModal("uk-modal", otherAttrs)
companion object : UIKitModal("uk-modal", mapOf("uk-modal" to "")) {
operator fun invoke(
escClose: Boolean? = null,
backgroundClose: Boolean? = null,
stack: Boolean? = null,
container: Boolean? = null,
classPage: String? = null,
classPanel: String? = null,
closingSelection: String? = null,
): UIKitModal = WithCustomAttributes(
mapOf(
buildAttribute("uk-modal") {
"esc-close" to escClose
"bg-close" to backgroundClose
"stack" to stack
"container" to container
"cls-page" to classPage
"cls-panel" to classPanel
"sel-close" to closingSelection
}
)
)
}
}

View File

@@ -4,7 +4,6 @@ sealed class UIKitNav(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
object ParentIcon : UIKitNav("uk-nav-parent-icon")
object SubNav : UIKitNav("uk-nav-sub")
object Header : UIKitNav("uk-nav-header")
object Divider : UIKitNav("uk-nav-divider")
@@ -15,5 +14,7 @@ sealed class UIKitNav(classname: String) : UIKitModifier {
object Center : UIKitNav("uk-nav-center")
companion object : UIKitNav("uk-nav")
companion object : UIKitNav("uk-nav") {
val SubNav = UIKitSubNav
}
}

View File

@@ -0,0 +1,10 @@
package dev.inmo.jsuikit.modifiers
sealed class UIKitSubNav(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
object Divider : UIKitSubNav("uk-subnav-divider")
object Pill : UIKitSubNav("uk-subnav-pill")
companion object : UIKitSubNav("uk-subnav")
}

View File

@@ -3,16 +3,34 @@ package dev.inmo.jsuikit.modifiers
sealed class UIKitText(suffix: String) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-text-$suffix")
object Lead : UIKitText("lead")
object Meta : UIKitText("meta")
sealed class Alignment(suffix: String) : UIKitText(suffix) {
object Left : Alignment("left")
object Right : Alignment("right")
object Center : Alignment("center")
object Justify : Alignment("justify")
sealed class Style(suffix: String) : UIKitText(suffix) {
object Lead : Style("lead")
object Meta : Style("meta")
object Italic : Style("italic")
}
sealed class Size(suffix: String) : UIKitText(suffix) {
object Small : Size("small")
object Default : Size("default")
object Large : Size("large")
}
sealed class Weight(suffix: String) : UIKitText(suffix) {
object Light : Weight("light")
object Normal : Weight("normal")
object Bold : Weight("bold")
object Lighter : Weight("lighter")
object Bolder : Weight("bolder")
}
sealed class Transform(suffix: String) : UIKitText(suffix) {
object Capitalize : Transform("capitalize")
object Uppercase : Transform("uppercase")
object Lowercase : Transform("lowercase")
}
object DecorationNone : UIKitText("decoration-none")
sealed class Color(suffix: String) : UIKitText(suffix) {
object Muted : Color("muted")
object Emphasis : Color("emphasis")
@@ -22,4 +40,32 @@ sealed class UIKitText(suffix: String) : UIKitModifier {
object Warning : Color("warning")
object Danger : Color("danger")
}
object Background : UIKitText("background")
sealed class Alignment(suffix: String) : UIKitText(suffix) {
sealed class Horizontal(suffix: String) : Alignment(suffix) {
object Left : Horizontal("left")
object Right : Horizontal("right")
object Center : Horizontal("center")
object Justify : Horizontal("justify")
}
sealed class Vertical(suffix: String) : Alignment(suffix) {
object Top : Vertical("top")
object Middle : Vertical("middle")
object Bottom : Vertical("bottom")
object Baseline : Vertical("baseline")
}
}
sealed class Wrapping(suffix: String) : UIKitText(suffix) {
object Truncate : Wrapping("truncate")
object Break : Wrapping("break")
object NoWrap : Wrapping("nowrap")
}
}

View File

@@ -0,0 +1,64 @@
package dev.inmo.jsuikit.modifiers
import dev.inmo.jsuikit.utils.Milliseconds
import dev.inmo.jsuikit.utils.buildAttribute
sealed class UIKitToggle(
vararg classnames: String,
override val otherAttrs: Map<String, String>
) : UIKitModifier {
@Suppress("UNCHECKED_CAST")
override val classes: Array<String> = classnames as Array<String>
sealed class Mode {
abstract val mode: String
object Click : Mode() {
override val mode: String
get() = "click"
}
object Hover : Mode() {
override val mode: String
get() = "hover"
}
object ClickAndHover : Mode() {
override val mode: String
get() = "${Click.mode}, ${Hover.mode}"
}
object Media : Mode() {
override val mode: String
get() = "media"
}
override fun toString(): String = mode
}
class Custom internal constructor(otherAttrs: Map<String, String>) : UIKitToggle(otherAttrs = otherAttrs)
companion object {
operator fun invoke(
target: String? = null,
mode: Mode? = null,
classesToApplyOnToggle: String? = null,
media: String? = null,
animation: UIKitAnimation? = null,
duration: Milliseconds? = null,
queued: Boolean? = null
) = Custom(
mapOf(
buildAttribute("uk-toggle") {
"target" to target
"mode" to mode
"cls" to classesToApplyOnToggle
"media" to media
"animation" to animation
"duration" to duration
"queued" to queued
}
)
)
}
}

View File

@@ -1,5 +1,7 @@
package dev.inmo.jsuikit.modifiers
import dev.inmo.jsuikit.utils.buildAttribute
class UIKitTooltipModifier(
text: String,
align: Align? = null,
@@ -8,16 +10,15 @@ class UIKitTooltipModifier(
duration: Int? = null,
animation: UIKitAnimation? = null
) : UIKitModifier {
private val parametersMap = listOfNotNull(
"title" to text,
align ?.let { it.k to it.v },
delay ?.let { "delay" to it.toString() },
offset ?.let { "offset" to it.toString() },
duration ?.let { "duration" to it.toString() },
animation ?.let { "animation" to it.name },
)
override val otherAttrs: Map<String, String> = mapOf(
"uk-tooltip" to parametersMap.joinToString(";") { (k, v) -> "$k: $v" }
buildAttribute("uk-tooltip") {
"title" to text
align ?.let { it.k to it.v }
delay ?.let { "delay" to it.toString() }
offset ?.let { "offset" to it.toString() }
duration ?.let { "duration" to it.toString() }
animation ?.let { "animation" to it.name }
}
)
sealed class Align(name: String) {

View File

@@ -109,4 +109,6 @@ sealed class UIKitUtility(classname: String) : UIKitModifier {
object Disabled : UIKitUtility("uk-disabled")
object Drag : UIKitUtility("uk-drag")
object Active : UIKitUtility("uk-active")
object Open : UIKitUtility("uk-open")
}

View File

@@ -0,0 +1,30 @@
package dev.inmo.jsuikit.modifiers
sealed class UIKitVisibility(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
sealed class Hidden(suffix: String?) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-hidden${suffix ?.let { "-$it" } ?: ""}")
object Hover : Hidden("hover")
sealed class Touch(suffix: String?) : Hidden(suffix) {
override val classes: Array<String> = arrayOf("${suffix ?: ""}touch")
object No : Touch("no")
companion object : Touch(null)
}
companion object : Hidden(null) {
val NoTouch = Touch.No
}
}
sealed class Invisible(suffix: String?) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-invisible${suffix ?.let { "-$it" } ?: ""}")
object Hover : Invisible("hover")
companion object : Invisible(null)
}
}

View File

@@ -1,29 +1,29 @@
package dev.inmo.jsuikit.modifiers
sealed class UIKitWidth(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-width-$classname")
override val classes: Array<String> = arrayOf(classname)
object Auto : UIKitWidth("auto")
object Expand : UIKitWidth("expand")
object Full : UIKitWidth("1-1")
object Auto : UIKitWidth("uk-width-auto")
object Expand : UIKitWidth("uk-width-expand")
object Full : UIKitWidth("uk-width-1-1")
object Half : UIKitWidth("1-2")
object Half : UIKitWidth("uk-width-1-2")
object OneThird : UIKitWidth("1-3")
object TwoThird : UIKitWidth("2-3")
object OneThird : UIKitWidth("uk-width-1-3")
object TwoThird : UIKitWidth("uk-width-2-3")
object OneFourth : UIKitWidth("1-4")
object ThreeFourth : UIKitWidth("3-4")
object OneFourth : UIKitWidth("uk-width-1-4")
object ThreeFourth : UIKitWidth("uk-width-3-4")
object OneFifth : UIKitWidth("1-5")
object TwoFifth : UIKitWidth("2-5")
object ThreeFifth : UIKitWidth("3-5")
object FourFifth : UIKitWidth("4-5")
object OneFifth : UIKitWidth("uk-width-1-5")
object TwoFifth : UIKitWidth("uk-width-2-5")
object ThreeFifth : UIKitWidth("uk-width-3-5")
object FourFifth : UIKitWidth("uk-width-4-5")
object OneSixth : UIKitWidth("1-6")
object FiveSixth : UIKitWidth("5-6")
object OneSixth : UIKitWidth("uk-width-1-6")
object FiveSixth : UIKitWidth("uk-width-5-6")
sealed class Child(suffix: String) : UIKitWidth("child-$suffix") {
sealed class Child(suffix: String) : UIKitWidth("uk-child-width-$suffix") {
object Full : Child("1-1")
object Half : Child("1-2")
@@ -57,7 +57,7 @@ sealed class UIKitWidth(classname: String) : UIKitModifier {
}
}
sealed class Fixed(suffix: String) : UIKitWidth("fixed-$suffix") {
sealed class Fixed(suffix: String) : UIKitWidth("uk-width-$suffix") {
object Small : Fixed("small")
object Medium : Fixed("medium")

View File

@@ -0,0 +1,16 @@
package dev.inmo.jsuikit.types
import org.w3c.dom.Element
import kotlin.js.Json
external interface UIKit {
val notification: UIKitNotifications
val modal: UIKitDialogs
fun notification(message: String, parameters: Json)
fun notification(element: Element): UIKitNotification?
fun modal(element: Element): UIKitDialog
fun modal(selector: String): UIKitDialog?
}

View File

@@ -0,0 +1,38 @@
package dev.inmo.jsuikit.types
import org.w3c.dom.Element
import kotlin.js.Promise
external interface UIKitDialogs {
fun alert(text: String): UIKitDialogPromiseAlert
fun confirm(text: String): UIKitDialogPromiseConfirm
fun prompt(title: String): UIKitDialogPromisePrompt
fun prompt(title: String, preset: String): UIKitDialogPromisePrompt
fun dialog(element: Element): UIKitDialog
}
external class UIKitDialogPromiseConfirm : Promise<Unit> {
val dialog: UIKitDialog
fun then(
onConfirm: () -> Unit = definedExternally,
onRejected: () -> Unit = definedExternally,
)
}
external class UIKitDialogPromisePrompt : Promise<Unit> {
val dialog: UIKitDialog
fun then(onResult: (data: String?) -> Unit)
}
external class UIKitDialogPromiseAlert : Promise<Unit> {
val dialog: UIKitDialog
fun then(onClose: () -> Unit)
}
external interface UIKitDialog {
fun show()
fun hide()
}

View File

@@ -0,0 +1,39 @@
package dev.inmo.jsuikit.types
sealed class UIKitNotificationParameter {
abstract val parameterName: String
abstract val parameterValue: String
sealed class Style(override val parameterValue: String) : UIKitNotificationParameter() {
override val parameterName: String
get() = "status"
object Primary : Style("primary")
object Success : Style("success")
object Warning : Style("warning")
object Danger : Style("danger")
}
sealed class Position(override val parameterValue: String) : UIKitNotificationParameter() {
override val parameterName: String
get() = "pos"
sealed class Top(parameterValue: String) : Position("top-$parameterValue") {
object Left : Top("left")
object Center : Top("center")
object Right : Top("right")
}
sealed class Bottom(parameterValue: String) : Position("bottom-$parameterValue") {
object Left : Bottom("left")
object Center : Bottom("center")
object Right : Bottom("right")
}
}
}

View File

@@ -0,0 +1,47 @@
package dev.inmo.jsuikit.types
import dev.inmo.jsuikit.modifiers.UIKit
import dev.inmo.jsuikit.utils.Milliseconds
import org.w3c.dom.Element
import kotlin.js.Json
import kotlin.js.json
typealias NotificationsGroup = String
external interface UIKitNotifications {
fun closeAll(group: NotificationsGroup)
}
external interface UIKitNotification {
fun close(immediate: Boolean)
}
data class UIKitNotificationsParameters(
val status: UIKitNotificationParameter.Style? = null,
val timeout: Milliseconds? = null,
val group: NotificationsGroup? = null,
val position: UIKitNotificationParameter.Position? = null
) {
fun parametersJson() = json(
*listOfNotNull(
status ?.let { it.parameterName to it.parameterValue },
timeout ?.let { "timeout" to timeout.toString() },
group ?.let { "group" to it },
position ?.let { it.parameterName to it.parameterValue },
).toTypedArray()
)
}
operator fun UIKitNotifications.invoke(
message: String,
parameters: UIKitNotificationsParameters
) = UIKit.notification(message, parameters.parametersJson())
operator fun UIKitNotifications.invoke(
message: String,
status: UIKitNotificationParameter.Style? = null,
timeout: Milliseconds? = null,
group: NotificationsGroup? = null,
position: UIKitNotificationParameter.Position? = null
) = invoke(message, UIKitNotificationsParameters(status, timeout, group, position))

View File

@@ -0,0 +1,11 @@
package dev.inmo.jsuikit.utils
fun <T> Array<T>.anyNotNull(): Boolean {
for (item in this) {
if (item != null) {
return true
}
}
return false
}

View File

@@ -0,0 +1,27 @@
package dev.inmo.jsuikit.utils
class AttributeBuilder (
val attributeName: String,
val skipNullValues: Boolean = true,
private val parametersPreset: MutableMap<String, String?> = mutableMapOf()
) {
fun add(k: String, v: Any? = null) {
if (v != null || !skipNullValues) {
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" } ?: ""}"
}
)
}
inline fun buildAttribute(attributeName: String, skipNullValues: Boolean = true, block: AttributeBuilder.() -> Unit) = AttributeBuilder(
attributeName,
skipNullValues
).apply(block).build()

View File

@@ -15,6 +15,13 @@ class AttributesCollection<T : Element> (
attrs()
}
operator fun plus(other: AttributesCollection<T>) = AttributesCollection<T>(
*(modifiers + other.modifiers).distinct().toTypedArray()
) {
this@AttributesCollection.attrs.invoke(this)
other.attrs.invoke(this)
}
companion object {
val Empty = Attrs<Element>()

View File

@@ -0,0 +1,16 @@
package dev.inmo.jsuikit.utils
import androidx.compose.runtime.Composable
import org.jetbrains.compose.web.dom.ContentBuilder
import org.w3c.dom.Element
@Composable
inline fun <T : Element> optionallyDraw (
attrs: Attrs<T>? = null,
noinline contentBuilder: ContentBuilder<T>? = null,
whatToDraw: @Composable () -> Unit
) {
if (attrs != null || contentBuilder != null) {
whatToDraw()
}
}

View File

@@ -0,0 +1,5 @@
package dev.inmo.jsuikit.utils
value class Percents(val int: Int) {
override fun toString(): String = "${int}%"
}

View File

@@ -0,0 +1,5 @@
package dev.inmo.jsuikit.utils
value class Pixels(val int: Int) {
override fun toString(): String = "${int}px"
}