start 0.0.1 and actualize

This commit is contained in:
2021-12-22 14:38:12 +06:00
parent 7ee648aa18
commit f1abef9fcd
63 changed files with 2022 additions and 511 deletions

View File

@@ -0,0 +1,78 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import androidx.compose.web.events.SyntheticMouseEvent
import dev.inmo.jsuikit.defaults.modifers.*
import org.jetbrains.compose.web.attributes.InputType
import org.jetbrains.compose.web.attributes.disabled
import org.jetbrains.compose.web.dom.*
import org.w3c.dom.HTMLButtonElement
import org.w3c.dom.events.Event
@Composable
fun DefaultButton(
vararg modifiers: UIKitModifier,
disabled: Boolean = false,
buttonType: UIKitButton.Type = UIKitButton.Type.Default,
onClick: ((SyntheticMouseEvent) -> Unit)? = null,
contentAllocator: ContentBuilder<HTMLButtonElement>
) {
Button(
{
onClick ?.let { onClick(it) }
classes("uk-button")
include(*modifiers, buttonType)
if (disabled) {
disabled()
}
}
) {
contentAllocator()
}
}
@Composable
fun DefaultButton(
text: String,
vararg modifiers: UIKitModifier,
disabled: Boolean = false,
buttonType: UIKitButton.Type = UIKitButton.Type.Default,
preTextContentAllocator: ContentBuilder<HTMLButtonElement>? = null,
afterTextContentAllocator: ContentBuilder<HTMLButtonElement>? = null,
onClick: ((SyntheticMouseEvent) -> Unit)? = null
) = DefaultButton(*modifiers, disabled = disabled, buttonType = buttonType, onClick = onClick) {
preTextContentAllocator ?.apply { preTextContentAllocator() }
Text(text)
afterTextContentAllocator ?.apply { afterTextContentAllocator() }
}
@Composable
fun UploadButton(
text: String,
vararg buttonModifiers: UIKitModifier,
containerModifiers: Array<UIKitModifier> = emptyArray(),
disabled: Boolean = false,
buttonType: UIKitButton.Type = UIKitButton.Type.Default,
onChange: (Event) -> Unit
) {
Div(
{
classes("js-upload", "uk-form-custom")
attr("uk-form-custom", "")
include(*containerModifiers)
}
) {
Input(InputType.File) { onChange { onChange(it.nativeEvent) } }
Button(
{
classes("uk-button")
include(*buttonModifiers, buttonType)
if (disabled) {
disabled()
}
}
) {
Text(text)
}
}
}

View File

@@ -0,0 +1,94 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffectResult
import dev.inmo.jsuikit.defaults.modifers.UIKitModifier
import dev.inmo.jsuikit.defaults.modifers.include
import org.jetbrains.compose.web.dom.*
import org.w3c.dom.HTMLElement
import org.w3c.dom.events.Event
import kotlin.random.Random
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()
js("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,
bodyBuilder: @Composable () -> Unit
) {
Div(
{
attr("uk-modal", "")
classes("uk-flex-top", "uk-modal")
id("dialog${Random.nextUInt()}")
include(*modifiers)
}
) {
Div(
{
classes("uk-modal-dialog", "uk-margin-auto-vertical")
}
) {
title ?.let {
Div(
{
classes("uk-modal-header")
}
) {
H2({ classes("uk-modal-title") }) {
Text(title)
}
}
}
Div(
{
classes("uk-modal-body")
}
) {
bodyBuilder()
}
footerBuilder ?.let {
Div(
{
classes("uk-modal-footer", "uk-text-right")
}
) {
footerBuilder()
}
}
}
DisposableRefEffect {
DialogDisposableEffectResult(it, hide, hidden)
}
DomSideEffect { htmlElement ->
var wrapper: (Event) -> Unit = {}
wrapper = { it: Event ->
htmlElement.removeEventListener("hidden", wrapper)
htmlElement.remove()
hidden ?.invoke()
}
htmlElement.addEventListener("hidden", wrapper)
val dialog = js("UIkit").modal("#${htmlElement.id}")
dialog.show()
Unit
}
}
}

View File

@@ -0,0 +1,7 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import org.jetbrains.compose.web.dom.Hr
@Composable
fun Divider() = Hr({ classes("uk-divider-icon") })

View File

@@ -0,0 +1,46 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.defaults.modifers.*
import dev.inmo.jsuikit.defaults.utils.Milliseconds
import org.jetbrains.compose.web.dom.ContentBuilder
import org.jetbrains.compose.web.dom.Div
import org.w3c.dom.HTMLDivElement
@Composable
fun Dropdown(
vararg modifiers: UIKitModifier,
toggle: String? = null,
pos: UIKitDropdown.Position? = null,
mode: UIKitDropdown.Mode? = null,
delayShow: Milliseconds? = null,
delayHide: Milliseconds? = null,
boundary: String? = null,
boundaryAlign: Boolean? = null,
flip: UIKitDropdown.Flip? = null,
offset: Int? = null,
animation: UIKitAnimation? = null,
duration: Milliseconds? = null,
contentBuilder: ContentBuilder<HTMLDivElement>
) {
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)
},
contentBuilder
)
}

View File

@@ -0,0 +1,23 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.defaults.modifers.UIKitModifier
import dev.inmo.jsuikit.defaults.modifers.include
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.dom.ElementScope
import org.w3c.dom.HTMLDivElement
@Composable
fun Flex(
vararg modifiers: UIKitModifier,
filler: @Composable ElementScope<HTMLDivElement>.() -> Unit
) {
Div(
{
classes("uk-flex")
include(*modifiers)
}
) {
filler()
}
}

View File

@@ -0,0 +1,48 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.defaults.modifers.UIKitModifier
import dev.inmo.jsuikit.defaults.modifers.include
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.dom.ElementScope
import org.w3c.dom.HTMLDivElement
@Composable
fun GridColumn(
vararg modifiers: UIKitModifier,
builder: @Composable ElementScope<HTMLDivElement>.() -> Unit
) {
Div(
{
include(*modifiers)
}
) {
builder()
}
}
@Composable
fun Grid(
vararg modifiers: UIKitModifier,
masonry: Boolean = false,
parallax: Int? = null,
marginClass: String? = null,
firstColumnClass: String? = null,
builder: @Composable ElementScope<HTMLDivElement>.() -> Unit
) {
val attrs = listOfNotNull(
if (masonry) "masonry" to "true" else null,
parallax ?.let { "parallax" to it.toString() },
marginClass ?.let { "margin" to it },
firstColumnClass ?.let { "first-column" to it },
)
Div(
{
attr("uk-grid", attrs.joinToString(";") { (k, v) -> "$k: $v" })
classes("uk-grid")
include(*modifiers)
}
) {
builder()
}
}

View File

@@ -0,0 +1,250 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.defaults.modifers.*
import org.jetbrains.compose.web.dom.Button
import org.jetbrains.compose.web.dom.Span
import org.w3c.dom.events.Event
sealed class Icon(val name: String) {
sealed class App(iconName: String) : Icon(iconName) {
object Home : App("home")
sealed class Sign(iconName: String) : App("sign-$iconName") {
object In : Sign("in")
object Out : Sign("out")
}
object User : App("user")
object Users : App("users")
object Lock : App("lock")
object Unlock : App("unlock")
object Settings : App("settings")
object Cog : App("cog")
object Nut : App("nut")
object Comment : App("comment")
object Commenting : App("commenting")
object Comments : App("comments")
object Hashtag : App("hashtag")
object Tag : App("tag")
object Cart : App("cart")
object Bag : App("bag")
sealed class Credit(iconName: String) : App("credit-$iconName") {
object Card : Credit("card")
}
object Mail : App("mail")
object Receiver : App("receiver")
object Print : App("print")
object Search : App("search")
object Location : App("location")
object Bookmark : App("bookmark")
object Code : App("code")
sealed class Paint(iconName: String) : App("paint-$iconName") {
object Bucket : Paint("bucket")
}
object Camera : App("camera")
sealed class Video(iconName: String) : App("video-$iconName") {
object Camera : Video("camera")
}
object Bell : App("bell")
object Microphone : App("microphone")
object Bolt : App("bolt")
object Star : App("star")
object Heart : App("heart")
object Happy : App("happy")
object Lifesaver : App("lifesaver")
object Rss : App("rss")
object Social : App("social")
sealed class Git(iconName: String) : App("git-$iconName") {
object Branch : Git("branch")
object Fork : Git("fork")
}
object World : App("world")
object Calendar : App("calendar")
object Clock : App("clock")
object History : App("history")
object Future : App("future")
object Pencil : App("pencil")
object Trash : App("trash")
object Move : App("move")
object Link : App("link")
object Question : App("question")
object Info : App("info")
object Warning : App("warning")
object Image : App("image")
object Thumbnails : App("thumbnails")
object Table : App("table")
object List : App("list")
object Menu : App("menu")
object Grid : App("grid")
sealed class More(iconName: String) : App("more${iconName.takeIf { it.isNotEmpty() } ?.let { "-$it" } ?: "" }") {
object Vertical : More("vertical")
companion object : More("more")
}
sealed class Plus(iconName: String) : App("plus${iconName.takeIf { it.isNotEmpty() } ?.let { "-$it" } ?: "" }") {
object Circle : Plus("circle")
companion object : Plus("plus")
}
sealed class Minus(iconName: String) : App("minus${iconName.takeIf { it.isNotEmpty() } ?.let { "-$it" } ?: "" }") {
object Circle : Minus("circle")
companion object : Minus("minus")
}
object Close : App("close")
object Check : App("check")
object Ban : App("ban")
object Refresh : App("refresh")
sealed class Play(iconName: String) : App("play${iconName.takeIf { it.isNotEmpty() } ?.let { "-$it" } ?: "" }") {
object Circle : Play("circle")
companion object : Play("play")
}
}
sealed class Devices(iconName: String) : Icon(iconName) {
object Tv : Devices("tv")
object Desktop : Devices("desktop")
object Laptop : Devices("laptop")
sealed class Tablet(iconName: String) : Devices("tablet${iconName.takeIf { it.isNotEmpty() } ?.let { "-$it" } ?: "" }") {
object Landscape : Tablet("landscape")
companion object : Tablet("tablet")
}
sealed class Phone(iconName: String) : Devices("phone${iconName.takeIf { it.isNotEmpty() } ?.let { "-$it" } ?: "" }") {
object Landscape : Phone("landscape")
companion object : Phone("phone")
}
}
sealed class Storage(iconName: String) : Icon(iconName) {
sealed class File(iconName: String) : Storage("file${iconName.takeIf { it.isNotEmpty() } ?.let { "-$it" } ?: "" }") {
object Text : File("text")
object Pdf : File("pdf")
object Edit : File("edit")
companion object : File("file")
}
object Copy : Storage("copy")
object Folder : Storage("folder")
object Album : Storage("album")
object Push : Storage("push")
object Pull : Storage("pull")
object Server : Storage("server")
object Database : Storage("database")
sealed class Cloud(iconName: String) : Storage("cloud-$iconName") {
object Upload : Cloud("upload")
object Download : Cloud("download")
}
object Download : Storage("download")
object Upload : Storage("upload")
}
sealed class Direction(iconName: String) : Icon(iconName) {
object Reply : Direction("reply")
object Forward : Direction("forward")
object Expand : Direction("expand")
object Shrink : Direction("shrink")
sealed class Arrow(iconName: String) : Direction("arrow-$iconName") {
object Up : Arrow("up")
object Down : Arrow("down")
object Left : Arrow("left")
object Right : Arrow("right")
}
sealed class Chevron(iconName: String) : Direction("chevron-$iconName") {
object Up : Chevron("up")
object Down : Chevron("down")
object Left : Chevron("left")
object Right : Chevron("right")
sealed class Double(iconName: String) : Chevron("double-$iconName") {
object Left : Double("left")
object Right : Double("right")
}
}
sealed class Triangle(iconName: String) : Direction("triangle-$iconName") {
object Up : Triangle("up")
object Down : Triangle("down")
object Left : Triangle("left")
object Right : Triangle("right")
}
}
sealed class Editor(iconName: String) : Icon(iconName) {
object Bold : Editor("bold")
object Italic : Editor("italic")
object Strikethrough : Editor("strikethrough")
sealed class Quote(iconName: String) : Editor("quote-$iconName") {
object Right : Quote("right")
}
}
sealed class Brands(iconName: String) : Icon(iconName) {
object _500px : Brands("500px")
object Behance : Brands("behance")
object Discord : Brands("discord")
object Dribbble : Brands("dribbble")
object Etsy : Brands("etsy")
object Facebook : Brands("facebook")
object Flickr : Brands("flickr")
object Foursquare : Brands("foursquare")
sealed class Github(iconName: String) : Brands("github${iconName.takeIf { it.isNotEmpty() } ?.let { "-$it" } ?: "" }") {
object Alt : Github("alt")
companion object : Github("github")
}
object Gitter : Brands("gitter")
object Google : Brands("google")
object Instagram : Brands("instagram")
object Joomla : Brands("joomla")
object Linkedin : Brands("linkedin")
object Pagekit : Brands("pagekit")
object Pinterest : Brands("pinterest")
object Reddit : Brands("reddit")
object Soundcloud : Brands("soundcloud")
object Tiktok : Brands("tiktok")
object Tripadvisor : Brands("tripadvisor")
object Tumblr : Brands("tumblr")
object Twitch : Brands("twitch")
object Twitter : Brands("twitter")
object Uikit : Brands("uikit")
object Vimeo : Brands("vimeo")
object Whatsapp : Brands("whatsapp")
object Wordpress : Brands("wordpress")
object Xing : Brands("xing")
object Yelp : Brands("yelp")
object Youtube : Brands("youtube")
}
@Composable
operator fun invoke(
vararg modifier: UIKitModifier,
type: UIKitIconType = UIKitIconType.Default,
ratio: Float? = null,
onClick: ((Event) -> Unit)? = null
) {
if (type == UIKitIconType.Button) {
Button(
{
classes("uk-icon")
include(*modifier, type)
attr("uk-icon", "icon: $name${if (ratio != null) { "; ratio: $ratio" } else ""}")
onClick ?.let { _ ->
onClick { onClick(it.nativeEvent) }
}
}
)
} else {
Span(
{
classes("uk-icon")
include(*modifier, type)
attr("uk-icon", "icon: $name${if (ratio != null) { "; ratio: $ratio" } else ""}")
onClick ?.let { _ ->
onClick { onClick(it.nativeEvent) }
}
}
)
}
}
@Composable
fun drawAsButton(
vararg modifier: UIKitModifier,
ratio: Float? = null,
onClick: ((Event) -> Unit)? = null
) = invoke(*modifier, type = UIKitIconType.Button, ratio = ratio, onClick = onClick)
@Composable
fun drawAsIcon(
vararg modifier: UIKitModifier,
ratio: Float? = null,
onClick: ((Event) -> Unit)? = null
) = invoke(*modifier, type = UIKitIconType.Default, ratio = ratio, onClick = onClick)
}

View File

@@ -0,0 +1,39 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.defaults.modifers.UIKitModifier
import dev.inmo.jsuikit.defaults.modifers.include
import org.jetbrains.compose.web.dom.Span
import org.jetbrains.compose.web.dom.Text
sealed interface Label {
val suffix: String
@Composable
operator fun invoke(
text: String,
vararg modifiers: UIKitModifier
) = Span(
{
classes("uk-label", "uk-label-$suffix")
include(*modifiers)
}
) {
Text(text)
}
object Success : Label {
override val suffix: String
get() = "success"
}
object Warning : Label {
override val suffix: String
get() = "warning"
}
object Error : Label {
override val suffix: String
get() = "danger"
}
}

View File

@@ -0,0 +1,33 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.snapshots.SnapshotStateList
import dev.inmo.jsuikit.defaults.modifers.UIKitModifier
import dev.inmo.jsuikit.defaults.modifers.include
import org.jetbrains.compose.web.dom.*
import org.w3c.dom.HTMLUListElement
@Composable
fun <T> List(
title: String,
data: SnapshotStateList<T>,
titleModifiers: Array<UIKitModifier> = emptyArray(),
ulModifiers: Array<UIKitModifier> = emptyArray(),
besidesTitleAndList: (@Composable () -> Unit)? = null,
elementAllocator: @Composable ElementScope<HTMLUListElement>.(T) -> Unit
) {
H4({ include(*titleModifiers) }) {
Text(title)
}
besidesTitleAndList ?.invoke()
Ul(
{
classes("uk-list")
include(*ulModifiers)
}
) {
data.forEach {
elementAllocator(it)
}
}
}

View File

@@ -0,0 +1,49 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.defaults.modifers.*
import dev.inmo.jsuikit.defaults.utils.Milliseconds
import org.jetbrains.compose.web.dom.*
import org.w3c.dom.HTMLLIElement
import org.w3c.dom.HTMLUListElement
@Composable
fun Nav(
vararg modifiers: UIKitModifier,
multiple: Boolean? = null,
collapsible: Boolean? = null,
animation: UIKitAnimation? = null,
duration: Milliseconds? = null,
dataAllocator: ContentBuilder<HTMLUListElement>
) {
Ul(
{
buildAndAddAttribute("uk-nav") {
"multiple" to multiple ?.toString()
"collapsible" to collapsible ?.toString()
"animation" to animation
"duration" to duration ?.toString()
}
classes("uk-nav")
include(*modifiers)
}
) {
dataAllocator()
}
}
@Composable
fun NavElement(
vararg modifiers: UIKitModifier,
attributesAllocator: (AttrBuilderContext<HTMLLIElement>)? = null,
contentAllocator: ContentBuilder<HTMLLIElement>
) {
Li(
{
attributesAllocator ?.apply { attributesAllocator() }
include(*modifiers)
}
) {
contentAllocator()
}
}

View File

@@ -0,0 +1,33 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.defaults.modifers.UIKitModifier
import dev.inmo.jsuikit.defaults.modifers.include
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.dom.Nav
@Composable
fun Navbar(
vararg navModifiers: UIKitModifier,
leftBuilder: NavbarNavBuilder? = null,
centerBuilder: NavbarNavBuilder? = null,
rightBuilder: NavbarNavBuilder? = null,
) {
Nav(
{
attr("uk-navbar", "")
classes("uk-navbar-container", "uk-navbar")
include(*navModifiers)
}
) {
leftBuilder ?.let {
Div({ classes("uk-navbar-left") }) { it.draw() }
}
centerBuilder ?.let {
Div({ classes("uk-navbar-center") }) { it.draw() }
}
rightBuilder ?.let {
Div({ classes("uk-navbar-right") }) { it.draw() }
}
}
}

View File

@@ -0,0 +1,58 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.defaults.modifers.UIKitModifier
import dev.inmo.jsuikit.defaults.modifers.include
import org.jetbrains.compose.web.attributes.AttrsBuilder
import org.jetbrains.compose.web.dom.*
import org.w3c.dom.HTMLLIElement
interface NavbarNavElement {
fun AttrsBuilder<HTMLLIElement>.setup() {}
@Composable
fun ElementScope<HTMLLIElement>.fill()
class Default(
private val setupCallback: AttrsBuilder<HTMLLIElement>.() -> Unit,
private val fillCallback: @Composable ElementScope<HTMLLIElement>.() -> Unit
) : NavbarNavElement {
override fun AttrsBuilder<HTMLLIElement>.setup() {
setupCallback()
}
@Composable
override fun ElementScope<HTMLLIElement>.fill() {
fillCallback()
}
}
}
class NavbarNavBuilder(
private val modifiers: Array<UIKitModifier>,
private val elements: List<NavbarNavElement>
) {
constructor(
modifiers: Array<UIKitModifier>,
vararg elements: NavbarNavElement
) : this(modifiers, elements.toList())
constructor(
vararg elements: NavbarNavElement
) : this(emptyArray(), elements.toList())
@Composable
fun draw() {
Ul(
{
classes("uk-navbar-nav")
include(*modifiers)
}
) {
elements.forEach { element ->
Li(
{ element.apply { setup() } }
) {
element.apply { fill() }
}
}
}
}
}

View File

@@ -0,0 +1,22 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.defaults.modifers.UIKitModifier
import dev.inmo.jsuikit.defaults.modifers.include
import org.jetbrains.compose.web.dom.Progress
@Composable
fun Progress(
value: Int,
vararg modifiers: UIKitModifier,
max: Int = 100
) {
Progress(
{
classes("uk-progress")
include(*modifiers)
attr("max", max.toString())
attr("value", value.toString())
}
)
}

View File

@@ -0,0 +1,22 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import dev.inmo.jsuikit.defaults.modifers.*
import org.jetbrains.compose.web.dom.Div
@Composable
fun Spinner(
vararg modifier: UIKitModifier,
ratio: Float? = null
) {
Div(
{
attr("uk-spinner", ratio ?.let { "ratio: $it" } ?: "")
classes("uk-icon", "uk-spinner")
include(*modifier)
}
)
}
@Composable
fun DefaultSpinner() = Spinner(UIKitAlign.Center, UIKitMargin.Small, UIKitText.Alignment.Center)

View File

@@ -0,0 +1,47 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.snapshots.SnapshotStateList
import dev.inmo.jsuikit.defaults.modifers.*
import org.jetbrains.compose.web.dom.*
@Composable
fun <T> DefaultTable(
heading: List<String>,
dataList: SnapshotStateList<T>,
vararg tableModifiers: UIKitModifier,
cellFiller: @Composable (i: Int, t: T) -> Unit
) {
val headingIndexes = heading.indices
Table(
{
classes("uk-table")
include(*tableModifiers)
}
) {
Thead {
Tr {
heading.forEach {
Th(
{
include(UIKitExtension.TextTransformUnset)
}
) {
Text(it)
}
}
}
}
Tbody {
dataList.forEach {
Tr {
headingIndexes.forEach { i ->
Td {
cellFiller(i, it)
}
}
}
}
}
}
}

View File

@@ -0,0 +1,30 @@
package dev.inmo.jsuikit.defaults
import androidx.compose.runtime.*
import dev.inmo.jsuikit.defaults.modifers.UIKitModifier
import dev.inmo.jsuikit.defaults.modifers.include
import org.jetbrains.compose.web.attributes.*
import org.jetbrains.compose.web.dom.Input
@Composable
fun <T> TextField(
type: InputType<T>,
state: MutableState<T>,
disabledState: State<Boolean>? = null,
placeholder: String? = null,
vararg modifiers: UIKitModifier
) {
Input(type) {
classes("uk-input")
include(*modifiers)
placeholder ?.let(::placeholder)
onChange { state.value = it.value }
disabledState ?.let {
if (it.value) {
disabled()
}
}
}
}

View File

@@ -0,0 +1,27 @@
package dev.inmo.jsuikit.defaults
import dev.inmo.jsuikit.defaults.modifers.AttributeValue
import org.jetbrains.compose.web.attributes.AttrsBuilder
class UIKitAttributeValueBuilder {
private val attrs = mutableListOf<Pair<String, String>>()
infix fun String.to(other: String?) {
other ?.let {
attrs.add(Pair(this, other))
}
}
infix fun String.to(other: AttributeValue?) {
this to other ?.name
}
fun build(): String = attrs.joinToString(";") { (k, v) -> "$k: $v" }
}
fun AttrsBuilder<*>.buildAndAddAttribute(
attributeName: String,
block: UIKitAttributeValueBuilder.() -> Unit
) {
attr(attributeName, UIKitAttributeValueBuilder().apply(block).build())
}

View File

@@ -0,0 +1,3 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class AttributeValue(val name: String)

View File

@@ -0,0 +1,4 @@
package dev.inmo.jsuikit.defaults.modifers
inline val UIKit
get() = js("UIkit")

View File

@@ -0,0 +1,8 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitAlign(classnameSuffix: String) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-align-$classnameSuffix")
object Left : UIKitAlign("left")
object Center : UIKitAlign("center")
object Right : UIKitAlign("right")
}

View File

@@ -0,0 +1,63 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitAnimation (name: String) : UIKitModifier, AttributeValue(name) {
override val classes: Array<String> = arrayOf("uk-animation-$name")
object Fade : UIKitAnimation("fade")
sealed class Scale(suffix: String) : UIKitAnimation("scale-$suffix") {
object Up : Scale("up")
object Down : Scale("down")
}
sealed class Slide(suffix: String) : UIKitAnimation("slide-$suffix") {
sealed class Top(suffixWithStroke: String) : Slide("top$suffixWithStroke") {
object Small : Top("-small")
object Medium : Top("-medium")
companion object : Top("")
}
sealed class Bottom(suffixWithStroke: String) : Slide("bottom$suffixWithStroke") {
object Small : Bottom("-small")
object Medium : Bottom("-medium")
companion object : Bottom("")
}
sealed class Left(suffixWithStroke: String) : Slide("left$suffixWithStroke") {
object Small : Left("-small")
object Medium : Left("-medium")
companion object : Left("")
}
sealed class Right(suffixWithStroke: String) : Slide("right$suffixWithStroke") {
object Small : Right("-small")
object Medium : Right("-medium")
companion object : Right("")
}
}
object Shake : UIKitAnimation("shake")
object Stroke : UIKitAnimation("stroke")
object Reverse : UIKitAnimation("reverse")
object Fast : UIKitAnimation("fast")
}

View File

@@ -0,0 +1,46 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitBackground(suffix: String) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-background-$suffix")
sealed class Color(suffix: String) : UIKitBackground(suffix) {
object Default : Color("default")
object Muted : Color("muted")
object Primary : Color("primary")
object Secondary : Color("secondary")
}
sealed class Size(suffix: String) : UIKitBackground(suffix) {
object Cover : Size("cover")
object Contain : Size("contain")
object FullWidth : Size("width-1-1")
object FullHeight : Size("height-1-1")
}
sealed class Position(suffix: String) : UIKitBackground(suffix) {
sealed class Top(suffix: String) : Position("top-$suffix") {
object Left : Top("left")
object Center : Top("center")
object Right : Top("right")
}
sealed class Center(suffix: String) : Position("center-$suffix") {
object Left : Position.Center("left")
object Center : Position.Center("center")
object Right : Position.Center("right")
}
sealed class Bottom(suffix: String) : Position("bottom-$suffix") {
object Left : Bottom("left")
object Center : Bottom("center")
object Right : Bottom("right")
}
}
object NoRepeat : Size("norepeat")
object Fixed : Size("fixed")
}

View File

@@ -0,0 +1,14 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitButton(suffix: String) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-button-$suffix")
sealed class Type(suffix: String) : UIKitButton(suffix) {
object Default : Type("default")
object Primary : Type("primary")
object Secondary : Type("secondary")
object Danger : Type("danger")
object Text : Type("text")
object Link : Type("link")
}
}

View File

@@ -0,0 +1,64 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitDropdown(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
object Nav : UIKitDropdown("uk-dropdown-nav")
object Grid : UIKitDropdown("uk-dropdown-grid")
sealed class Position(name: String) : AttributeValue(name) {
sealed class Bottom(name: String) : Position("bottom-$name") {
object Left : Bottom("left")
object Center : Bottom("center")
object Right : Bottom("right")
object Justify : Bottom("justify")
}
sealed class Top(name: String) : Position("top-$name") {
object Left : Top("left")
object Center : Top("center")
object Right : Top("right")
object Justify : Top("justify")
}
sealed class Left(name: String) : Position("left-$name") {
object Top : Left("top")
object Center : Left("center")
object Bottom : Left("bottom")
}
sealed class Right(name: String) : Position("right-$name") {
object Top : Right("top")
object Center : Right("center")
object Bottom : Right("bottom")
}
}
sealed class Mode(name: String) : AttributeValue(name) {
object Click : Mode("click")
object Hover : Mode("hover")
}
sealed class Flip(name: String) : AttributeValue(name) {
object True : Flip("true")
object False : Flip("false")
object X : Flip("x")
object Y : Flip("y")
}
}

View File

@@ -0,0 +1,7 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitExtension(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
object TextTransformUnset : UIKitExtension("text_transform_unset")
object CursorPointer : UIKitExtension("cursor_pointer")
}

View File

@@ -0,0 +1,79 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitFlex(suffix: String) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-flex-$suffix")
object Inline : UIKitFlex("inline")
sealed class Alignment(suffix: String) : UIKitFlex(suffix) {
sealed class Horizontal(suffix: String) : Alignment(suffix) {
object Left : Horizontal("left")
object Center : Horizontal("center")
object Right : Horizontal("right")
object Between : Horizontal("between")
object Around : Horizontal("around")
}
sealed class Vertical(suffix: String) : Alignment(suffix) {
object Stretch : Vertical("stretch")
object Top : Vertical("top")
object Middle : Vertical("middle")
object Bottom : Vertical("bottom")
}
}
sealed class Direction(suffix: String) : UIKitFlex(suffix) {
sealed class Row(suffix: String) : Direction(suffix) {
object Reverse : Row("row-reverse")
companion object : Row("row")
}
sealed class Column(suffix: String) : Direction(suffix) {
object Reverse : Column("column-reverse")
companion object : Column("column")
}
}
sealed class Wrap(suffix: String) : UIKitFlex(suffix) {
object Reverse : Wrap("wrap-reverse")
object Stretch : Wrap("wrap-stretch")
object Between : Wrap("wrap-between")
object Around : Wrap("wrap-around")
object Top : Wrap("wrap-top")
object Middle : Wrap("wrap-middle")
object Bottom : Wrap("wrap-bottom")
companion object : Wrap("wrap")
}
sealed class Order(suffix: String) : UIKitFlex(suffix) {
object First : Order("first")
object Last : Order("last")
}
sealed class Dimensions(suffix: String) : UIKitFlex(suffix) {
object None : Dimensions("none")
object Auto : Dimensions("auto")
object BasedOnFlex : Dimensions("1")
}
object NoWrap : UIKitFlex("nowrap")
}

View File

@@ -0,0 +1,20 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitGrid(suffix: String) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-grid-$suffix")
sealed class Gap(suffix: String) : UIKitGrid(suffix) {
object Small : Gap("small")
object Medium : Gap("medium")
object Large : Gap("large")
object Collapse : Gap("collapse")
}
object Divider : UIKitGrid("divider")
object MatchHeight : UIKitGrid("match")
object ItemMatchHeight : UIKitGrid("item-match")
}

View File

@@ -0,0 +1,11 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitIconType(suffix: String?) : UIKitModifier {
override val classes: Array<String> = suffix ?.let {
arrayOf("uk-icon-$suffix")
} ?: emptyArray()
object Default : UIKitIconType(null)
object Link : UIKitIconType("link")
object Button : UIKitIconType("button")
}

View File

@@ -0,0 +1,72 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitMargin(val classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
object Top : Small("uk-margin-top")
object Bottom : Small("uk-margin-bottom")
object Left : Small("uk-margin-left")
object Right : Small("uk-margin-right")
companion object : Small("uk-margin")
sealed class Small(classname: String) : UIKitMargin(classname) {
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")
companion object : Small("uk-margin-small")
}
sealed class Medium(classname: String) : UIKitMargin(classname) {
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")
companion object : Medium("uk-margin-medium")
}
sealed class Large(classname: String) : UIKitMargin(classname) {
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")
companion object : Large("uk-margin-large")
}
sealed class XLarge(classname: String) : UIKitMargin(classname) {
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")
companion object : XLarge("uk-margin-xlarge")
}
sealed class Auto(classname: String) : UIKitMargin(classname) {
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")
companion object : Auto("uk-margin-auto")
}
sealed class Remove(classname: String) : UIKitMargin(classname) {
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 Adjacent : Remove("uk-margin-remove-adjacent")
object FirstChild : Remove("uk-margin-remove-first-child")
object LastChild : Remove("uk-margin-remove-last-child")
companion object : Remove("uk-margin-remove")
}
}

View File

@@ -0,0 +1,17 @@
package dev.inmo.jsuikit.defaults.modifers
import org.jetbrains.compose.web.attributes.AttrsBuilder
interface UIKitModifier {
val classes: Array<String>
get() = emptyArray()
val otherAttrs: Map<String, String>
get() = emptyMap()
}
fun AttrsBuilder<*>.include(vararg container: UIKitModifier?) {
container.forEach {
it ?.classes ?.let { newClasses -> classes(*newClasses) }
it ?.otherAttrs ?.let { attrs -> attrs.forEach { (k, v) -> attr(k, v) } }
}
}

View File

@@ -0,0 +1,17 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitNav(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
object Accordion : UIKitNav("uk-nav-parent-icon")
object Subnav : UIKitNav("uk-nav-sub")
object Header : UIKitNav("uk-nav-header")
object Divider : UIKitNav("uk-nav-divider")
object Default : UIKitNav("uk-nav-default")
object Primary : UIKitNav("uk-nav-primary")
object Center : UIKitNav("uk-nav-center")
}

View File

@@ -0,0 +1,17 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitNavbar(suffix: String) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-navbar-$suffix")
object Transparent : UIKitNavbar("transparent")
sealed class Dropdown(suffix: String?) : UIKitNavbar("dropdown${suffix ?.let { "-$it" } ?: ""}") {
object Nav : Dropdown("nav")
companion object : Dropdown(null)
}
object Item : UIKitNavbar("item")
companion object {
val Logo = UIKitUtility.Logo
}
}

View File

@@ -0,0 +1,29 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitPadding(suffix: String?) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-padding${suffix ?.let { "-$it" } ?: ""}")
sealed class Size(suffix: String?) : UIKitPadding(suffix) {
object Small : Size("small")
object Large : Size("large")
companion object : Size(null)
}
sealed class Remove(suffix: String?) : UIKitPadding("remove${suffix ?.let { "-$it" } ?: ""}") {
object Top : Remove("top")
object Bottom : Remove("bottom")
object Left : Remove("left")
object Right : Remove("right")
object Vertical : Remove("vertical")
object Horizontal : Remove("horizontal")
companion object : Remove(null)
}
}

View File

@@ -0,0 +1,53 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitPosition(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
sealed class Top(classname: String) : UIKitPosition(classname) {
companion object : Top("uk-position-top")
object Left : Top("uk-position-top-left")
object Center : Top("uk-position-top-center")
object Right : Top("uk-position-top-right")
}
sealed class Left(classname: String) : UIKitPosition(classname) {
companion object : Left("uk-position-left")
}
sealed class Right(classname: String) : UIKitPosition(classname) {
companion object : Right("uk-position-right")
}
sealed class Center(classname: String) : UIKitPosition(classname) {
companion object : Center("uk-position-center")
sealed class Left(classname: String) : Center(classname) {
object Out : Left("uk-position-center-left-out")
companion object : Left("uk-position-center-left")
}
sealed class Right(classname: String) : Center(classname) {
object Out : Right("uk-position-center-right-out")
companion object : Right("uk-position-center-right")
}
}
sealed class Bottom(classname: String) : UIKitPosition(classname) {
companion object : Bottom("uk-position-bottom")
object Left : Bottom("uk-position-bottom-left")
object Center : Bottom("uk-position-bottom-center")
object Right : Bottom("uk-position-bottom-right")
}
sealed class Size(classname: String) : UIKitPosition(classname) {
object Small : Size("uk-position-small")
object Medium : Size("uk-position-medium")
object Large : Size("uk-position-large")
}
object Relative : UIKitPosition("uk-position-relative")
object Absolute : UIKitPosition("uk-position-absolute")
object Fixed : UIKitPosition("uk-position-fixed")
object ZIndex : UIKitPosition("uk-position-z-index")
object Cover : UIKitPosition("uk-position-cover")
}

View File

@@ -0,0 +1,20 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitScreenSizeModifier(val name: String) {
class UIKitScreenSizeModifierModified (
val modifier: UIKitScreenSizeModifier,
val base: UIKitModifier
) : UIKitModifier {
override val classes: Array<String> = base.classes.map { "$it@${modifier.name}" }.toTypedArray()
}
object Small : UIKitScreenSizeModifier("s")
object Medium : UIKitScreenSizeModifier("m")
object Large : UIKitScreenSizeModifier("l")
object XLarge : UIKitScreenSizeModifier("xl")
fun modify(modifier: UIKitModifier): UIKitModifier = UIKitScreenSizeModifierModified(
this,
modifier
)
}

View File

@@ -0,0 +1,13 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitTable(suffix: String) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-table-$suffix")
object Divider : UIKitTable("divider")
object Size {
object Small : UIKitTable("small")
object Large : UIKitTable("large")
}
object Hover : UIKitTable("hover")
object Justify : UIKitTable("justify")
}

View File

@@ -0,0 +1,25 @@
package dev.inmo.jsuikit.defaults.modifers
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 Color(suffix: String) : UIKitText(suffix) {
object Muted : Color("muted")
object Emphasis : Color("emphasis")
object Primary : Color("primary")
object Secondary : Color("secondary")
object Success : Color("success")
object Warning : Color("warning")
object Danger : Color("danger")
}
}

View File

@@ -0,0 +1,46 @@
package dev.inmo.jsuikit.defaults.modifers
class UIKitTooltipModifier(
text: String,
align: Align? = null,
delay: Int? = null,
offset: Int? = null,
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" }
)
sealed class Align(name: String) {
val k = "pos"
val v = name
sealed class Top(suffix: String) : Align("top$suffix") {
object Center : Top("")
object Left : Top("-left")
object Right : Top("-right")
}
sealed class Bottom(suffix: String) : Align("bottom$suffix") {
object Center : Bottom("")
object Left : Bottom("-left")
object Right : Bottom("-right")
}
object Left : Align("left")
object Right : Align("right")
}
}

View File

@@ -0,0 +1,12 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitUtility(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf(classname)
sealed class Overflow(suffix: String) : UIKitUtility("uk-overflow-$suffix") {
object Hidden : Overflow("hidden")
object Auto : Overflow("auto")
}
object Logo : UIKitUtility("uk-logo")
}

View File

@@ -0,0 +1,33 @@
package dev.inmo.jsuikit.defaults.modifers
sealed class UIKitWidth(classname: String) : UIKitModifier {
override val classes: Array<String> = arrayOf("uk-width-$classname")
object Full : UIKitWidth("1-1")
object Expand : UIKitWidth("expand")
object Half : UIKitWidth("1-2")
object OneThird : UIKitWidth("1-3")
object TwoThird : UIKitWidth("2-3")
object OneFourth : UIKitWidth("1-4")
val TwoFourth get() = Half
object ThreeFourth : UIKitWidth("3-4")
val FourFourth get() = Full
object OneFifth : UIKitWidth("1-5")
object TwoFifth : UIKitWidth("2-5")
object ThreeFifth : UIKitWidth("3-5")
object FourFifth : UIKitWidth("4-5")
val FiveFifth get() = Full
object OneSixth : UIKitWidth("1-6")
val TwoSixth get() = OneThird
val ThreeSixth get() = Half
val FourSixth get() = TwoThird
object FiveSixth : UIKitWidth("5-6")
val SixSixth get() = Full
override fun toString() = classes.first()
}

View File

@@ -0,0 +1,3 @@
package dev.inmo.jsuikit.defaults.utils
typealias Milliseconds = Long

View File

@@ -0,0 +1,244 @@
val src = """App
home
sign-in
sign-out
user
users
lock
unlock
settings
cog
nut
comment
commenting
comments
hashtag
tag
cart
bag
credit-card
mail
receiver
print
search
location
bookmark
code
paint-bucket
camera
video-camera
bell
microphone
bolt
star
heart
happy
lifesaver
rss
social
git-branch
git-fork
world
calendar
clock
history
future
pencil
trash
move
link
question
info
warning
image
thumbnails
table
list
menu
grid
more
more-vertical
plus
plus-circle
minus
minus-circle
close
check
ban
refresh
play
play-circle
Devices
tv
desktop
laptop
tablet
phone
tablet-landscape
phone-landscape
Storage
file
file-text
file-pdf
copy
file-edit
folder
album
push
pull
server
database
cloud-upload
cloud-download
download
upload
Direction
reply
forward
expand
shrink
arrow-up
arrow-down
arrow-left
arrow-right
chevron-up
chevron-down
chevron-left
chevron-right
chevron-double-left
chevron-double-right
triangle-up
triangle-down
triangle-left
triangle-right
Editor
bold
italic
strikethrough
quote-right
Brands
500px
behance
discord
dribbble
etsy
facebook
flickr
foursquare
github
github-alt
gitter
google
instagram
joomla
linkedin
pagekit
pinterest
reddit
soundcloud
tiktok
tripadvisor
tumblr
twitch
twitter
uikit
vimeo
whatsapp
wordpress
xing
yelp
youtube"""
data class IconsPart(
val src: String,
val subelements: List<IconsPart>,
val classname: String = src.split("-").joinToString("") { it.replaceFirstChar { it.uppercase() } },
val isSelfIcon: Boolean = true
) {
private val prefix = if (subelements.isEmpty()) "object" else "sealed class"
private val classnameArgs = if (subelements.isEmpty()) "" else "(iconName: String)"
private val parentClassnameArgs = if (subelements.isEmpty())
"(\"$src\")" else if (src.first().isLowerCase()) "(\"$src${if (isSelfIcon) "\${iconName.takeIf { it.isNotEmpty() } ?.let { \"-\$it\" } ?: \"\" }" else "-\$iconName" }\")"
else
"(iconName)"
private fun body(linePrefix: String = ""): String {
val newLinePrefix = "$linePrefix "
val postfix = if (isSelfIcon) {
"${newLinePrefix}companion object : $classname(\"$src\")\n"
} else {
""
}
return subelements.takeIf {
it.isNotEmpty()
} ?.joinToString("\n", " {\n", "\n$postfix$linePrefix}") {
it.generateString(this, newLinePrefix)
} ?: ""
}
fun generateString(parent: IconsPart?, linePrefix: String = ""): String {
return "$linePrefix$prefix $classname$classnameArgs ${parent ?.let { ": ${it.classname}$parentClassnameArgs" } ?: ""}${body(linePrefix)}"
}
}
class SimpleElement(
val src: String,
private val subelements: List<SimpleElement>,
private val isElement: Boolean
) {
val allSubelements: List<String> = listOf(src) + subelements.flatMap {
it.allSubelements.map {
if (src.first().isLowerCase()) {
"$src-$it"
} else {
it
}
}
}
fun toIconElement(): IconsPart = IconsPart(
src,
subelements.map { it.toIconElement() },
isSelfIcon = isElement
)
}
fun split(list: List<String>): SimpleElement {
val currentSrc = list.first().takeWhile { it != '-' }
val withoutFirst = list.drop(1)
val resultSubelements = mutableListOf<SimpleElement>()
val withoutPrefix = when {
currentSrc.first().isUpperCase() -> withoutFirst.takeWhile { !it.first().isUpperCase() }
else -> list.filter { it.startsWith("$currentSrc-") }.map { it.removePrefix("$currentSrc-") }
}
var left: List<String> = withoutPrefix
while (left.isNotEmpty()) {
val newElement = split(left)
resultSubelements.add(newElement)
left = left - (newElement.allSubelements.toSet() + newElement.src)
}
return SimpleElement(currentSrc, resultSubelements, currentSrc.first().isLowerCase() && list.any { it.endsWith(currentSrc) })
}
fun main() {
val splitted = src.split("\n")
var leftList = splitted
val resultSubelements = mutableListOf<SimpleElement>()
while (leftList.isNotEmpty()) {
val subelement = split(leftList)
leftList = leftList - (subelement.allSubelements.toSet() + subelement.src)
resultSubelements.add(subelement)
}
val rootElement = SimpleElement("Icon", resultSubelements, false).toIconElement()
println(rootElement.generateString(null))
}