Compare commits

..

69 Commits

Author SHA1 Message Date
2e665a8411 Merge pull request #85 from InsanusMokrassar/0.7.4
0.7.4
2023-11-26 21:17:56 +06:00
96d5936e83 update dependencies 2023-11-26 21:14:31 +06:00
de6253c50e start 0.7.4 2023-11-26 21:14:08 +06:00
1f66ca8346 Merge pull request #84 from InsanusMokrassar/0.7.3
0.7.3
2023-11-02 22:29:42 +06:00
7dc0e08a78 fix in publishing script 2023-11-02 22:29:21 +06:00
0eb80f141a update gradle wrapper 2023-11-02 22:27:15 +06:00
120df9d84e start 0.7.3 and update dependencies 2023-11-02 22:24:34 +06:00
6783bd6666 Merge pull request #83 from InsanusMokrassar/0.7.2
0.7.2
2023-09-07 01:16:01 +06:00
9c4bc444dd update dependencies 2023-09-07 01:12:39 +06:00
0635b4a233 start 0.7.2 2023-09-07 01:09:03 +06:00
29fe133777 Merge pull request #82 from InsanusMokrassar/0.7.1
0.7.1
2023-06-19 16:47:32 +06:00
d2ba2fe96a improvements 2023-06-19 16:42:41 +06:00
c0ce6f5b71 start 0.7.1 2023-06-19 16:38:49 +06:00
665432cdce Merge pull request #81 from InsanusMokrassar/0.7.0
0.7.0
2023-04-13 12:10:00 +06:00
5e379ee3e2 update dependencies 2023-04-13 12:09:01 +06:00
5a86d6705b start 0.7.0 2023-04-13 12:08:43 +06:00
25134879c1 Merge pull request #80 from InsanusMokrassar/0.6.2
0.6.2
2023-03-10 22:31:03 +06:00
30a85795dd start 0.6.2 && update compose 2023-03-10 15:07:19 +06:00
730da9f759 Merge pull request #79 from InsanusMokrassar/0.6.1
0.6.1
2023-03-05 21:36:49 +06:00
8178fa9d39 value in StandardInput is nullable 2023-03-05 18:50:59 +06:00
1eb14becde now StandardInput uses callback with input receiver 2023-03-05 18:15:12 +06:00
6502e0923e DefaultInput -> StandardInput 2023-03-05 14:41:30 +06:00
443043cff5 update dependencies 2023-03-05 14:37:57 +06:00
1765214c97 remove redundant settings fromm gradle.properties 2023-03-05 14:36:16 +06:00
dcc6495030 start 0.6.1 2023-03-05 14:35:56 +06:00
1c16fb4ed7 Merge pull request #78 from InsanusMokrassar/0.6.0
0.6.0
2023-02-28 12:42:40 +06:00
a60fb67ad3 update compose 2023-02-28 12:35:34 +06:00
f8402b24d1 update dependencies 2023-02-28 12:21:43 +06:00
f70f4674ed start 0.6.0 2023-02-28 12:20:49 +06:00
7c81cea8af Merge pull request #77 from InsanusMokrassar/0.5.2
0.5.2
2023-01-26 22:44:37 +06:00
2aca51d742 Update CHANGELOG.md 2023-01-26 22:44:07 +06:00
d8be33d4f6 add inline support 2023-01-24 18:06:16 +06:00
1d6c0db692 add badge support 2023-01-24 13:44:01 +06:00
264bcae65e fixes in dialogs 2023-01-23 12:50:50 +06:00
ce5281c52d start 0.5.2 2023-01-23 12:50:03 +06:00
1349d253d7 Merge pull request #76 from InsanusMokrassar/0.5.1
0.5.1
2023-01-13 13:36:26 +06:00
dbf9efa8f5 fill changelog 2023-01-13 13:25:14 +06:00
c483bb67d8 potential fix of modals composition cancelling 2023-01-13 13:21:45 +06:00
7c5a9ecc3d start 0.5.1 2023-01-13 12:49:25 +06:00
05816f9a57 Merge pull request #75 from InsanusMokrassar/0.5.0
0.5.0
2023-01-12 14:51:06 +06:00
402af2445f temporarily remove UIKitConstants 2023-01-12 14:50:23 +06:00
71ccc74c94 fixes 2023-01-12 14:31:38 +06:00
0b8017a164 small improvement in dialogs 2023-01-11 21:57:43 +06:00
46a897e629 total rework of dialogs 2023-01-11 21:55:47 +06:00
0e1be72219 start 0.5.0 2023-01-11 21:35:30 +06:00
0feafdae4b Merge pull request #74 from InsanusMokrassar/0.4.3
0.4.3
2023-01-04 20:25:13 +06:00
fad48715b4 add gitea to the target repositories 2023-01-03 18:40:53 +06:00
f6bfef4b89 update github workflows 2023-01-03 18:38:33 +06:00
432a5744b3 add opportunity to now show dialog automatically 2023-01-03 18:37:01 +06:00
5dff8d69f2 start 0.4.3 2023-01-03 18:33:50 +06:00
e6ebc70578 Merge pull request #73 from InsanusMokrassar/0.4.2
0.4.2
2022-12-18 10:10:57 +06:00
0eba5d10f7 Update CHANGELOG.md 2022-12-18 10:07:51 +06:00
ffb7f41328 Update libs.versions.toml 2022-12-18 10:07:07 +06:00
77dabb5553 0.4.2 2022-12-18 10:06:45 +06:00
8c086eb3eb Merge pull request #71 from InsanusMokrassar/0.4.1
0.4.1
2022-11-16 00:57:42 +06:00
0d55505e09 fill changelog 2022-11-16 00:57:11 +06:00
eefdb5fda1 list may accept any iterable 2022-11-16 00:45:10 +06:00
0c281aa653 fixes for build 2022-11-16 00:17:03 +06:00
17ae0b119b StandardInput improvements 2022-11-15 21:50:15 +06:00
36214aeba5 start 0.4.1 2022-11-15 21:46:29 +06:00
19f3a59a79 Merge pull request #70 from InsanusMokrassar/0.4.0
0.4.0
2022-11-08 07:56:31 +06:00
5cfee9c4cc Update CHANGELOG.md 2022-11-08 07:54:53 +06:00
c9a17fa92a Update gradle-wrapper.properties 2022-11-08 07:53:42 +06:00
c36e8c58f4 Update libs.versions.toml 2022-11-08 07:52:33 +06:00
67f083610a start 0.4.0 2022-11-08 07:51:48 +06:00
636280a982 Merge pull request #69 from InsanusMokrassar/0.3.0
0.3.0
2022-09-19 20:54:03 +06:00
415549b251 Update libs.versions.toml 2022-09-17 00:55:20 +06:00
0d2672b679 start 0.3.0 2022-09-17 00:53:59 +06:00
a511def014 Merge pull request #68 from InsanusMokrassar/0.2.2
0.2.2
2022-09-14 14:07:24 +06:00
21 changed files with 432 additions and 183 deletions

View File

@@ -1,15 +0,0 @@
name: Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Build with Gradle
run: ./gradlew build

26
.github/workflows/build_and_publish.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Rewrite version
run: |
branch="`echo "${{ github.ref }}" | grep -o "[^/]*$"`"
cat gradle.properties | sed -e "s/^version=\([0-9\.]*\)/version=\1-branch_$branch-build${{ github.run_number }}/" > gradle.properties.tmp
rm gradle.properties
mv gradle.properties.tmp gradle.properties
- name: Build with Gradle
run: ./gradlew build
- name: Publish
continue-on-error: true
run: ./gradlew publishAllPublicationsToGiteaRepository
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}

View File

@@ -1,5 +1,76 @@
# Changelog # Changelog
## 0.7.4
* `Kotlin`: `1.9.21`
* `Compose`: `1.5.11`
## 0.7.3
* `Kotlin`: `1.9.20`
* `Compose`: `1.5.10`
## 0.7.2
* `Kotlin`: `1.9.10`
* `Compose`: `1.5.1`
## 0.7.1
* Type of `animation` parameter in `Alert` has been changed according to docs: now it is `Boolean`
* Add tooltip `JS` part support
## 0.7.0
* `Kotlin`: `1.8.20`
* `Compose`: `1.4.0`
## 0.6.2
* `Compose`: `1.3.1`
## 0.6.1
* `DefaultInput` has been renamed to `StandardInput`
* `Compose`: `1.3.1-rc02`
## 0.6.0
* `Kotlin`: `1.8.10`
* `Compose`: `1.3.1-rc01`
## 0.5.2
* More fixes in Dialogs
* Badge supported
* Inline creation support
## 0.5.1
* Fixes in new `Dialog`s
## 0.5.0
* Fully rework `Dialog` elements
## 0.4.3
* Add opportunity to now show dialog automatically
## 0.4.2
* `Compose`: `1.2.2`
## 0.4.1
* Now it is possible to use `StandardInput` with simple `T` types instead of states
* `List` may accept any `Iterable`
## 0.4.0
* `Kotlin`: `1.7.20`
* `Compose`: `1.2.1`
## 0.2.2 ## 0.2.2
* Add support of `Drop` component * Add support of `Drop` component

View File

@@ -3,10 +3,8 @@ org.gradle.parallel=true
kotlin.js.generate.externals=true kotlin.js.generate.externals=true
kotlin.incremental=true kotlin.incremental=true
kotlin.incremental.js=true kotlin.incremental.js=true
android.useAndroidX=true
android.enableJetifier=true
# Project data # Project data
group=dev.inmo group=dev.inmo
version=0.2.2 version=0.7.4

View File

@@ -1,8 +1,8 @@
[versions] [versions]
kt = "1.7.0" kt = "1.9.21"
jb-compose = "1.2.0-alpha01-dev753" jb-compose = "1.5.11"
jb-dokka = "1.7.0" jb-dokka = "1.9.10"
gh-release = "2.4.1" gh-release = "2.4.1"
[libraries] [libraries]

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@@ -1,7 +1,7 @@
apply plugin: 'maven-publish' apply plugin: 'maven-publish'
task javadocsJar(type: Jar) { task javadocsJar(type: Jar) {
classifier = 'javadoc' archiveClassifier = 'javadoc'
} }
publishing { publishing {
@@ -38,14 +38,32 @@ publishing {
} }
} }
repositories { repositories {
if (project.hasProperty('GITEA_TOKEN') || System.getenv('GITEA_TOKEN') != null) {
maven {
name = "GITEA"
url = uri("https://git.inmo.dev/api/packages/InsanusMokrassar/maven")
credentials(HttpHeaderCredentials) {
name = "Authorization"
value = project.hasProperty('GITEA_TOKEN') ? project.property('GITEA_TOKEN') : System.getenv('GITEA_TOKEN')
}
authentication {
header(HttpHeaderAuthentication)
}
}
}
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) { if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
maven { maven {
name = "sonatype" name = "sonatype"
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/") url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials { credentials {
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER') username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD') password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
} }
} }
} }
} }
@@ -66,4 +84,10 @@ if (project.hasProperty("signing.gnupg.keyName")) {
dependsOn(it) dependsOn(it)
} }
} }
// Workaround to make android sign operations depend on signing tasks
project.getTasks().withType(AbstractPublishToMaven.class).configureEach {
def signingTasks = project.getTasks().withType(Sign.class)
mustRunAfter(signingTasks)
}
} }

View File

@@ -1 +1 @@
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://opensource.org/licenses/Apache-2.0"}],"mavenConfig":{"name":"${project.name}","description":"${project.name}","url":"https://github.com/InsanusMokrassar/JSUIKitKBindings","vcsUrl":"https://github.com/InsanusMokrassar/JSUIKitKBindings.git","developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}}} {"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://opensource.org/licenses/Apache-2.0"}],"mavenConfig":{"name":"${project.name}","description":"${project.name}","url":"https://github.com/InsanusMokrassar/JSUIKitKBindings","vcsUrl":"https://github.com/InsanusMokrassar/JSUIKitKBindings.git","developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"GITEA","url":"https://git.inmo.dev/api/packages/InsanusMokrassar/maven","credsType":{"type":"dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository.CredentialsType.HttpHeaderCredentials","headerName":"Authorization","headerValueProperty":"GITEA_TOKEN"}},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}}}

View File

@@ -1,3 +1 @@
rootProject.name = 'kjsuikit' rootProject.name = 'kjsuikit'
enableFeaturePreview("VERSION_CATALOGS")

View File

@@ -12,7 +12,7 @@ import org.w3c.dom.HTMLDivElement
@Composable @Composable
fun Alert( fun Alert(
attrs: Attrs<HTMLDivElement> = Attrs.empty(), attrs: Attrs<HTMLDivElement> = Attrs.empty(),
animation: UIKitAnimation? = UIKitAnimation.Fade, animation: Boolean = true,
duration: Milliseconds? = null, duration: Milliseconds? = null,
selClose: String? = null, selClose: String? = null,
content: ContentBuilder<HTMLDivElement> content: ContentBuilder<HTMLDivElement>
@@ -22,7 +22,7 @@ fun Alert(
include(UIKitAlert) include(UIKitAlert)
buildAndAddAttribute("uk-alert") { buildAndAddAttribute("uk-alert") {
"animation" to animation ?.classes ?.firstOrNull() "animation" to animation
"duration" to duration "duration" to duration
"sel-close" to selClose "sel-close" to selClose
} }

View File

@@ -0,0 +1,25 @@
package dev.inmo.jsuikit.elements
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.modifiers.UIKitBadge
import dev.inmo.jsuikit.modifiers.include
import org.jetbrains.compose.web.dom.AttrBuilderContext
import org.jetbrains.compose.web.dom.ContentBuilder
import org.jetbrains.compose.web.dom.Span
import org.jetbrains.compose.web.dom.Text
import org.w3c.dom.HTMLSpanElement
@Composable
fun Badge(
text: String,
onAfterText: ContentBuilder<HTMLSpanElement>? = null,
onBeforeText: ContentBuilder<HTMLSpanElement>? = null,
attrs: AttrBuilderContext<HTMLSpanElement>? = null
) = Span({
include(UIKitBadge)
attrs ?.invoke(this)
}) {
onAfterText ?.invoke(this)
Text(text)
onBeforeText ?.invoke(this)
}

View File

@@ -1,33 +1,22 @@
package dev.inmo.jsuikit.elements package dev.inmo.jsuikit.elements
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffectResult import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import dev.inmo.jsuikit.modifiers.* import dev.inmo.jsuikit.modifiers.*
import org.jetbrains.compose.web.dom.* import org.jetbrains.compose.web.dom.*
import org.jetbrains.compose.web.renderComposableInBody
import org.w3c.dom.HTMLDivElement import org.w3c.dom.HTMLDivElement
import org.w3c.dom.HTMLElement
import org.w3c.dom.events.Event
import kotlin.random.Random import kotlin.random.Random
import kotlin.random.nextUInt import kotlin.random.nextUInt
private class DialogDisposableEffectResult(
private val element: HTMLElement,
private val onDispose: (() -> Unit)?,
private val onDisposed: (() -> Unit)?
) : DisposableEffectResult {
override fun dispose() {
onDispose?.invoke()
UIKit.modal("#${element.id}") ?.hide()
onDisposed?.invoke()
}
}
@Composable @Composable
fun Dialog( fun Dialog(
vararg modifiers: UIKitModifier, vararg modifiers: UIKitModifier,
attributesCustomizer: AttrBuilderContext<HTMLDivElement> = {}, attributesCustomizer: AttrBuilderContext<HTMLDivElement> = {},
onHide: (() -> Unit)? = null, onHidden: ((HTMLDivElement) -> Unit)? = null,
onHidden: (() -> Unit)? = null, onShown: ((HTMLDivElement) -> Unit)? = null,
dialogAttrsBuilder: AttrBuilderContext<HTMLDivElement>? = null, dialogAttrsBuilder: AttrBuilderContext<HTMLDivElement>? = null,
headerAttrsBuilder: AttrBuilderContext<HTMLDivElement>? = null, headerAttrsBuilder: AttrBuilderContext<HTMLDivElement>? = null,
headerBuilder: ContentBuilder<HTMLDivElement>? = null, headerBuilder: ContentBuilder<HTMLDivElement>? = null,
@@ -36,101 +25,148 @@ fun Dialog(
footerAttrsBuilder: AttrBuilderContext<HTMLDivElement>? = null, footerAttrsBuilder: AttrBuilderContext<HTMLDivElement>? = null,
footerBuilder: ContentBuilder<HTMLDivElement>? = null, footerBuilder: ContentBuilder<HTMLDivElement>? = null,
bodyAttrsBuilder: AttrBuilderContext<HTMLDivElement>? = null, bodyAttrsBuilder: AttrBuilderContext<HTMLDivElement>? = null,
bodyBuilder: ContentBuilder<HTMLDivElement> autoShow: Boolean = true,
removeOnHide: Boolean = true,
bodyBuilder: ContentBuilder<HTMLDivElement> = {}
) { ) {
Div( val draw = remember { mutableStateOf(true) }
{
if (modifiers.none { it is UIKitModal.WithCustomAttributes }) { remember {
include(UIKitModal) renderComposableInBody {
} if (draw.value) {
id("dialog${Random.nextUInt()}")
include(*modifiers)
attributesCustomizer()
}
) {
Div(
{
include(UIKitModal.Dialog)
dialogAttrsBuilder ?.let { it() } ?: include(UIKitMargin.Auto.Vertical)
}
) {
headerBuilder ?.let {
Div( Div(
{ {
include(UIKitModal.Header) if (modifiers.none { it is UIKitModal.WithCustomAttributes }) {
headerAttrsBuilder ?.let { it() } include(UIKitModal)
}
id("dialog${Random.nextUInt()}")
include(*modifiers)
attributesCustomizer()
} }
) { ) {
it() DisposableEffect(true) {
} val htmlElement = scopeElement
}
afterHeaderBuilder ?.let { it() } if (autoShow) {
Div( UIKit.modal(htmlElement).show()
{ }
include(UIKitModal.Body)
bodyAttrsBuilder ?.let { it() } if (onHidden != null || removeOnHide) {
} htmlElement.addEventListener("hidden", {
) { if (it.target != htmlElement) return@addEventListener
bodyBuilder()
} onHidden ?.invoke(htmlElement)
beforeFooterBuilder ?.let { it() }
footerBuilder ?.let { if (removeOnHide) {
Div( htmlElement.remove()
{ }
include(UIKitModal.Footer) })
footerAttrsBuilder ?.let { it() } ?: include(UIKitText.Alignment.Horizontal.Right) }
onShown ?.let {
htmlElement.addEventListener("shown", {
if (it.target != htmlElement) return@addEventListener
onShown(htmlElement)
})
}
onDispose {
draw.value = false
}
}
Div(
{
include(UIKitModal.Dialog)
dialogAttrsBuilder ?.let { it() } ?: include(UIKitMargin.Auto.Vertical)
}
) {
headerBuilder ?.let {
Div(
{
include(UIKitModal.Header)
headerAttrsBuilder ?.let { it() }
}
) {
it()
}
}
afterHeaderBuilder ?.let { it() }
Div(
{
include(UIKitModal.Body)
bodyAttrsBuilder ?.let { it() }
}
) {
bodyBuilder()
}
beforeFooterBuilder ?.let { it() }
footerBuilder ?.let {
Div(
{
include(UIKitModal.Footer)
footerAttrsBuilder ?.let { it() } ?: include(UIKitText.Alignment.Horizontal.Right)
}
) {
it()
}
}
} }
) {
it()
} }
} }
} }
DisposableRefEffect {
DialogDisposableEffectResult(it, onHide, onHidden)
}
DomSideEffect { htmlElement ->
var wrapper: (Event) -> Unit = {}
wrapper = { it: Event ->
htmlElement.removeEventListener("hidden", wrapper)
htmlElement.remove()
onHidden ?.invoke()
}
htmlElement.addEventListener("hidden", wrapper)
UIKit.modal("#${htmlElement.id}") ?.show()
}
} }
Div({
hidden()
ref {
onDispose {
draw.value = false
}
}
})
} }
@Composable @Composable
fun Dialog( fun Dialog(
title: String, title: String,
vararg modifiers: UIKitModifier, vararg modifiers: UIKitModifier,
hide: (() -> Unit)? = null,
hidden: (() -> Unit)? = null,
footerBuilder: (@Composable () -> Unit)? = null,
attributesCustomizer: AttrBuilderContext<HTMLDivElement> = {}, attributesCustomizer: AttrBuilderContext<HTMLDivElement> = {},
bodyBuilder: @Composable () -> Unit onHidden: ((HTMLDivElement) -> Unit)? = null,
onShown: ((HTMLDivElement) -> 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,
autoShow: Boolean = true,
removeOnHide: Boolean = true,
bodyBuilder: ContentBuilder<HTMLDivElement> = {}
) = Dialog( ) = Dialog(
modifiers = modifiers, modifiers = modifiers,
attributesCustomizer = attributesCustomizer,
onHidden = onHidden,
onShown = onShown,
dialogAttrsBuilder = dialogAttrsBuilder,
headerAttrsBuilder = headerAttrsBuilder,
headerBuilder = { headerBuilder = {
H2({ include(UIKitModal.Title) }) { H2({ include(UIKitModal.Title) }) {
Text(title) Text(title)
} }
headerBuilder ?.invoke(this)
}, },
onHide = hide, afterHeaderBuilder = afterHeaderBuilder,
onHidden = hidden, beforeFooterBuilder = beforeFooterBuilder,
footerBuilder = footerBuilder ?.let { _ -> footerAttrsBuilder = footerAttrsBuilder,
{ footerBuilder = footerBuilder,
footerBuilder() bodyAttrsBuilder = bodyAttrsBuilder,
} autoShow = autoShow,
}, removeOnHide = removeOnHide,
attributesCustomizer = { bodyBuilder = bodyBuilder
attributesCustomizer()
},
bodyBuilder = {
bodyBuilder()
}
) )

View File

@@ -202,60 +202,62 @@ sealed class Icon(val name: String) {
object Youtube : Brands("youtube") object Youtube : Brands("youtube")
} }
@Composable
operator fun invoke(
vararg modifiers: UIKitModifier,
type: UIKitIconType = UIKitIconType.Default,
ratio: Float? = null,
attributesCustomizer: AttrBuilderContext<out HTMLElement> = {},
onClick: ((Event) -> Unit)? = null
) {
val configurer: AttrBuilderContext<out HTMLElement> = {
include(*modifiers, type, UIKitIcon)
attr("uk-icon", "icon: $name${if (ratio != null) { "; ratio: $ratio" } else ""}")
onClick ?.let { _ ->
onClick { onClick(it.nativeEvent) }
}
attributesCustomizer()
}
when (type) {
UIKitIconType.Default -> Span(configurer)
UIKitIconType.Link -> A(href = "#", configurer)
UIKitIconType.Button -> Button(configurer)
}
}
class Custom(name: String) : Icon(name) class Custom(name: String) : Icon(name)
@Composable companion object {
fun drawAsButton( }
vararg modifiers: UIKitModifier,
ratio: Float? = null,
attributesCustomizer: AttrBuilderContext<out HTMLElement> = {},
onClick: ((Event) -> Unit)? = null
) = invoke(*modifiers, type = UIKitIconType.Button, ratio = ratio, onClick = onClick, attributesCustomizer = attributesCustomizer)
@Composable
fun drawAsIcon(
vararg modifiers: UIKitModifier,
ratio: Float? = null,
attributesCustomizer: AttrBuilderContext<out HTMLElement> = {},
onClick: ((Event) -> Unit)? = null
) = invoke(*modifiers, type = UIKitIconType.Default, ratio = ratio, onClick = onClick, attributesCustomizer = attributesCustomizer)
@Composable
fun drawAsLink(
vararg modifiers: UIKitModifier,
ratio: Float? = null,
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)
} }
@Composable
operator fun Icon.invoke(
vararg modifiers: UIKitModifier,
type: UIKitIconType = UIKitIconType.Default,
ratio: Float? = null,
attributesCustomizer: AttrBuilderContext<out HTMLElement> = {},
onClick: ((Event) -> Unit)? = null
) {
val configurer: AttrBuilderContext<out HTMLElement> = {
include(*modifiers, type, UIKitIcon)
attr("uk-icon", "icon: $name${if (ratio != null) { "; ratio: $ratio" } else ""}")
onClick ?.let { _ ->
onClick { onClick(it.nativeEvent) }
}
attributesCustomizer()
}
when (type) {
UIKitIconType.Default -> Span(configurer)
UIKitIconType.Link -> A(href = "#", configurer)
UIKitIconType.Button -> Button(configurer)
}
}
@Composable
fun Icon.drawAsButton(
vararg modifiers: UIKitModifier,
ratio: Float? = null,
attributesCustomizer: AttrBuilderContext<out HTMLElement> = {},
onClick: ((Event) -> Unit)? = null
) = invoke(*modifiers, type = UIKitIconType.Button, ratio = ratio, onClick = onClick, attributesCustomizer = attributesCustomizer)
@Composable
fun Icon.drawAsIcon(
vararg modifiers: UIKitModifier,
ratio: Float? = null,
attributesCustomizer: AttrBuilderContext<out HTMLElement> = {},
onClick: ((Event) -> Unit)? = null
) = invoke(*modifiers, type = UIKitIconType.Default, ratio = ratio, onClick = onClick, attributesCustomizer = attributesCustomizer)
@Composable
fun Icon.drawAsLink(
vararg modifiers: UIKitModifier,
ratio: Float? = null,
attributesCustomizer: AttrBuilderContext<out HTMLElement> = {},
onClick: ((Event) -> Unit)? = null
) = invoke(*modifiers, type = UIKitIconType.Link, ratio = ratio, onClick = onClick, attributesCustomizer = attributesCustomizer)
@Composable
fun Icon.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,18 @@
package dev.inmo.jsuikit.elements
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.modifiers.UIKitUtility
import dev.inmo.jsuikit.modifiers.include
import org.jetbrains.compose.web.dom.AttrBuilderContext
import org.jetbrains.compose.web.dom.ContentBuilder
import org.jetbrains.compose.web.dom.Div
import org.w3c.dom.HTMLDivElement
@Composable
fun Inline(
attrBuilderContext: AttrBuilderContext<HTMLDivElement>? = null,
contentBuilder: ContentBuilder<HTMLDivElement>
) = Div({
include(UIKitUtility.Inline)
attrBuilderContext ?.invoke(this)
}, contentBuilder)

View File

@@ -10,7 +10,7 @@ import org.w3c.dom.HTMLUListElement
@Composable @Composable
fun <T> List( fun <T> List(
data: SnapshotStateList<T>, data: Iterable<T>,
ukAttrs: Attrs<HTMLUListElement> = Attrs.empty(), ukAttrs: Attrs<HTMLUListElement> = Attrs.empty(),
elementAllocator: @Composable ElementScope<HTMLUListElement>.(T) -> Unit elementAllocator: @Composable ElementScope<HTMLUListElement>.(T) -> Unit
) { ) {
@@ -29,7 +29,7 @@ fun <T> List(
@Composable @Composable
fun <T> ListWithTitle( fun <T> ListWithTitle(
title: String, title: String,
data: SnapshotStateList<T>, data: Iterable<T>,
vararg titleModifiers: UIKitModifier, vararg titleModifiers: UIKitModifier,
ulModifiers: Array<UIKitModifier> = emptyArray(), ulModifiers: Array<UIKitModifier> = emptyArray(),
besidesTitleAndList: (@Composable () -> Unit)? = null, besidesTitleAndList: (@Composable () -> Unit)? = null,

View File

@@ -11,11 +11,12 @@ import org.w3c.dom.HTMLInputElement
@Composable @Composable
fun <T> StandardInput( fun <T> StandardInput(
type: InputType<T>, type: InputType<T>,
state: MutableState<T>, value: T? = null,
disabledState: State<Boolean>? = null,
placeholder: String? = null,
vararg modifiers: UIKitModifier, vararg modifiers: UIKitModifier,
disabled: Boolean = false,
placeholder: String? = null,
attributesCustomizer: AttrBuilderContext<HTMLInputElement> = {}, attributesCustomizer: AttrBuilderContext<HTMLInputElement> = {},
onChange: HTMLInputElement.(T) -> Unit
) { ) {
Input(type) { Input(type) {
classes("uk-input") classes("uk-input")
@@ -23,7 +24,7 @@ fun <T> StandardInput(
placeholder ?.let(::placeholder) placeholder ?.let(::placeholder)
state.value.let { value ?.let {
when (it) { when (it) {
is String -> value(it) is String -> value(it)
is Number -> value(it) is Number -> value(it)
@@ -31,13 +32,44 @@ fun <T> StandardInput(
} }
} }
onInput { state.value = it.value } onInput { event -> event.target.onChange(event.value) }
disabledState ?.let { if (disabled) {
if (it.value) { disabled()
disabled()
}
} }
attributesCustomizer() attributesCustomizer()
} }
} }
@Deprecated("Renamed", ReplaceWith("StandardInput(type, value, *modifiers, disabled, placeholder, attributesCustomizer, onChange)"))
@Composable
fun <T> DefaultInput(
type: InputType<T>,
value: T,
disabled: Boolean = false,
placeholder: String? = null,
vararg modifiers: UIKitModifier,
attributesCustomizer: AttrBuilderContext<HTMLInputElement> = {},
onChange: (T) -> Unit
) = StandardInput(type, value, modifiers = modifiers, disabled, placeholder, attributesCustomizer) {
onChange(it)
}
@Composable
fun <T> StandardInput(
type: InputType<T>,
state: MutableState<T>,
disabledState: State<Boolean>? = null,
placeholder: String? = null,
vararg modifiers: UIKitModifier,
attributesCustomizer: AttrBuilderContext<HTMLInputElement> = {},
) = StandardInput(
type,
state.value,
modifiers = modifiers,
disabledState ?.value == true,
placeholder,
attributesCustomizer = attributesCustomizer
) {
state.value = it
}

View File

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

View File

@@ -6,6 +6,7 @@ import kotlin.js.Json
external interface UIKit { external interface UIKit {
val notification: UIKitNotifications val notification: UIKitNotifications
val modal: UIKitDialogs val modal: UIKitDialogs
val util: UIKitUtil
fun notification(message: String, parameters: Json) fun notification(message: String, parameters: Json)
@@ -16,4 +17,7 @@ external interface UIKit {
fun dropdown(element: Element, options: DropdownOptions = definedExternally): Dropdown fun dropdown(element: Element, options: DropdownOptions = definedExternally): Dropdown
fun dropdown(selector: String, options: DropdownOptions = definedExternally): Dropdown? fun dropdown(selector: String, options: DropdownOptions = definedExternally): Dropdown?
fun tooltip(element: Element): UIKitTooltip
fun tooltip(selector: String): UIKitTooltip?
} }

View File

@@ -0,0 +1,6 @@
package dev.inmo.jsuikit.types
external interface UIKitTooltip {
fun show()
fun hide()
}

View File

@@ -0,0 +1,8 @@
package dev.inmo.jsuikit.types
import org.w3c.dom.HTMLElement
external interface UIKitUtil {
fun on(selector: String, event: String, callback: () -> Unit)
fun on(element: HTMLElement, event: String, callback: () -> Unit)
}

View File

@@ -0,0 +1,9 @@
package dev.inmo.jsuikit.utils
import org.jetbrains.compose.web.dom.AttrBuilderContext
import org.w3c.dom.Element
operator fun <T : Element> AttrBuilderContext<T>.plus(other: AttrBuilderContext<T>): AttrBuilderContext<T> = {
this@plus()
other()
}