All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jsMain.styled.CssAccess.kt Maven / Gradle / Ivy

package styled

import js.core.asList
import js.core.jso
import web.buffer.Blob
import web.buffer.BlobPart
import web.cssom.CSSStyleSheet
import web.dom.Element
import web.dom.document
import web.html.HTMLAnchorElement
import web.location.location
import web.storage.localStorage
import web.uievents.CLICK
import web.uievents.MouseEvent
import web.url.URL
import web.window.window

external interface StyledNext {
    fun useDevSheet(isDev: Boolean)

    fun getStylesheets(): Array

    /**
     * @param [block] is executed on every CSS text rule in DOM
     * @return resulting array of [block] returned values if they are not null
     */
    fun  mapNotNullRules(block: (String) -> T?): Array

    /** @return array of all CSS rules that contain partialCss */
    fun getCss(partialCss: String?): Array

    /** download a file with CSS rules that contain partialCss */
    fun downloadCss(partialCss: String?, filename: String?)
}

internal object GlobalCssAccess {
    private enum class SheetType {
        Dev,
        CSSOM
    }

    private const val sheetTypeKey: String = "sheetType"

    private fun downloadFile(blob: BlobPart, name: String) {
        val binaryData = arrayOf(blob)
        val blobUrl = URL.createObjectURL(Blob(binaryData, jso { type = "application/text" }))
        val link = document.createElement("a") as HTMLAnchorElement
        link.href = blobUrl
        link.download = name
        document.body.appendChild(link)
        link.dispatchEvent(MouseEvent(MouseEvent.CLICK, jso { bubbles = true; cancelable = true; view = window }))
        document.body.removeChild(link)
    }

    fun useDevSheet(isDev: Boolean = true) {
        localStorage.setItem(sheetTypeKey, if (isDev) SheetType.Dev.name else SheetType.CSSOM.name)
        location.reload()
    }

    fun isDevSheet(): Boolean {
        return localStorage.getItem(sheetTypeKey) == SheetType.Dev.name
    }

    internal fun setupCssHelperFunctions() {
        window.asDynamic().StyledNext = object : StyledNext {
            override fun useDevSheet(isDev: Boolean) {
                [email protected](isDev)
            }

            override fun getStylesheets(): Array {
                return buildList {
                    for (i in 0 until document.styleSheets.length) {
                        val node = document.styleSheets.item(i) ?: continue
                        if ((node.ownerNode as Element).id.startsWith("ksc-global-style")) add(node)
                    }
                }.toTypedArray()
            }

            override fun  mapNotNullRules(block: (String) -> T?): Array {
                return getStylesheets().flatMap { sheet ->
                    sheet.cssRules.asList().mapNotNull { rule ->
                        block(rule.cssText)
                    }
                }.toTypedArray()
            }

            override fun getCss(partialCss: String?) = mapNotNullRules { if (it.contains(partialCss ?: "")) it else null }
            override fun downloadCss(partialCss: String?, filename: String?) {
                downloadFile(getCss(partialCss).joinToString("\n"), filename ?: "index.css")
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy