Browse Source

Simplify elements internal api by removing Tag interface completely and rely on existing HTMLElement hierarchy (#779)

* Relax upperbound for ElementBuilder to Element

It's still a lie since there's a HTMLElement cast later on but it will
make possible further improvements

* Don't use Tags anywhere in code

* Remove Tags completely
MERGE_HTML_BUILDER
Shagen Ogandzhanian 4 years ago committed by GitHub
parent
commit
60944c87c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 246
      web/core/src/jsMain/kotlin/androidx/compose/web/attributes/Attrs.kt
  2. 4
      web/core/src/jsMain/kotlin/androidx/compose/web/attributes/AttrsBuilder.kt
  3. 12
      web/core/src/jsMain/kotlin/androidx/compose/web/elements/Base.kt
  4. 117
      web/core/src/jsMain/kotlin/androidx/compose/web/elements/Elements.kt
  5. 7
      web/core/src/jsMain/kotlin/androidx/compose/web/elements/Style.kt
  6. 3
      web/core/src/jsTest/kotlin/elements/ElementsTests.kt

246
web/core/src/jsMain/kotlin/androidx/compose/web/attributes/Attrs.kt

@ -1,327 +1,300 @@
package org.jetbrains.compose.web.attributes
import org.w3c.dom.HTMLAnchorElement
import org.w3c.dom.HTMLButtonElement
import org.w3c.dom.HTMLFormElement
import org.w3c.dom.HTMLImageElement
import org.w3c.dom.HTMLInputElement
interface Tag {
object Div : Tag
object A : Tag
object Button : Tag
object Form : Tag
object Input : Tag
object Select : Tag
object Option : Tag
object OptGroup : Tag
object H : Tag
object Hr : Tag
object Ul : Tag
object Ol : Tag
object Li : Tag
object Img : Tag
object TextArea : Tag
object Nav : Tag
object Span : Tag
object P : Tag
object Br : Tag
object Style : Tag
object Pre : Tag
object Code : Tag
object Label : Tag
object Table : Tag
object Caption : Tag
object Col : Tag
object Colgroup : Tag
object Tr : Tag
object Thead : Tag
object Th : Tag
object Td : Tag
object Tbody : Tag
object Tfoot : Tag
}
/* Anchor <a> attributes */
fun AttrsBuilder<Tag.A>.href(value: String?) =
import org.w3c.dom.HTMLLabelElement
import org.w3c.dom.HTMLOptGroupElement
import org.w3c.dom.HTMLOptionElement
import org.w3c.dom.HTMLSelectElement
import org.w3c.dom.HTMLTableCellElement
import org.w3c.dom.HTMLTableColElement
import org.w3c.dom.HTMLTextAreaElement
fun AttrsBuilder<HTMLAnchorElement>.href(value: String?) =
attr("href", value)
fun AttrsBuilder<Tag.A>.target(value: ATarget = ATarget.Self) =
fun AttrsBuilder<HTMLAnchorElement>.target(value: ATarget = ATarget.Self) =
attr("target", value.targetStr)
fun AttrsBuilder<Tag.A>.ref(value: ARel) =
fun AttrsBuilder<HTMLAnchorElement>.ref(value: ARel) =
attr("rel", value.relStr)
fun AttrsBuilder<Tag.A>.ping(value: String) =
fun AttrsBuilder<HTMLAnchorElement>.ping(value: String) =
attr("ping", value)
fun AttrsBuilder<Tag.A>.ping(vararg urls: String) =
fun AttrsBuilder<HTMLAnchorElement>.ping(vararg urls: String) =
attr("ping", urls.joinToString(" "))
fun AttrsBuilder<Tag.A>.hreflang(value: String) =
fun AttrsBuilder<HTMLAnchorElement>.hreflang(value: String) =
attr("hreflang", value)
fun AttrsBuilder<Tag.A>.download(value: String = "") =
fun AttrsBuilder<HTMLAnchorElement>.download(value: String = "") =
attr("download", value)
/* Button attributes */
fun AttrsBuilder<Tag.Button>.autoFocus(value: Boolean = true) =
fun AttrsBuilder<HTMLButtonElement>.autoFocus(value: Boolean = true) =
attr("autofocus", if (value) "" else null)
fun AttrsBuilder<Tag.Button>.disabled(value: Boolean = true) =
fun AttrsBuilder<HTMLButtonElement>.disabled(value: Boolean = true) =
attr("disabled", if (value) "" else null)
fun AttrsBuilder<Tag.Button>.form(formId: String) =
fun AttrsBuilder<HTMLButtonElement>.form(formId: String) =
attr("form", formId)
fun AttrsBuilder<Tag.Button>.formAction(url: String) =
fun AttrsBuilder<HTMLButtonElement>.formAction(url: String) =
attr("formaction", url)
fun AttrsBuilder<Tag.Button>.formEncType(value: ButtonFormEncType) =
fun AttrsBuilder<HTMLButtonElement>.formEncType(value: ButtonFormEncType) =
attr("formenctype", value.typeStr)
fun AttrsBuilder<Tag.Button>.formMethod(value: ButtonFormMethod) =
fun AttrsBuilder<HTMLButtonElement>.formMethod(value: ButtonFormMethod) =
attr("formmethod", value.methodStr)
fun AttrsBuilder<Tag.Button>.formNoValidate(value: Boolean = true) =
fun AttrsBuilder<HTMLButtonElement>.formNoValidate(value: Boolean = true) =
attr("formnovalidate", if (value) "" else null)
fun AttrsBuilder<Tag.Button>.formTarget(value: ButtonFormTarget) =
fun AttrsBuilder<HTMLButtonElement>.formTarget(value: ButtonFormTarget) =
attr("formtarget", value.targetStr)
fun AttrsBuilder<Tag.Button>.name(value: String) =
fun AttrsBuilder<HTMLButtonElement>.name(value: String) =
attr("name", value)
fun AttrsBuilder<Tag.Button>.type(value: ButtonType) =
fun AttrsBuilder<HTMLButtonElement>.type(value: ButtonType) =
attr("type", value.str)
fun AttrsBuilder<Tag.Button>.value(value: String) =
fun AttrsBuilder<HTMLButtonElement>.value(value: String) =
attr("value", value)
/* Form attributes */
fun AttrsBuilder<Tag.Form>.action(value: String) =
fun AttrsBuilder<HTMLFormElement>.action(value: String) =
attr("action", value)
fun AttrsBuilder<Tag.Form>.acceptCharset(value: String) =
fun AttrsBuilder<HTMLFormElement>.acceptCharset(value: String) =
attr("accept-charset", value)
fun AttrsBuilder<Tag.Form>.autoComplete(value: Boolean) =
fun AttrsBuilder<HTMLFormElement>.autoComplete(value: Boolean) =
attr("autocomplete", if (value) "" else null)
fun AttrsBuilder<Tag.Form>.encType(value: FormEncType) =
fun AttrsBuilder<HTMLFormElement>.encType(value: FormEncType) =
attr("enctype", value.typeStr)
fun AttrsBuilder<Tag.Form>.method(value: FormMethod) =
fun AttrsBuilder<HTMLFormElement>.method(value: FormMethod) =
attr("method", value.methodStr)
fun AttrsBuilder<Tag.Form>.noValidate(value: Boolean = true) =
fun AttrsBuilder<HTMLFormElement>.noValidate(value: Boolean = true) =
attr("novalidate", if (value) "" else null)
fun AttrsBuilder<Tag.Form>.target(value: FormTarget) =
fun AttrsBuilder<HTMLFormElement>.target(value: FormTarget) =
attr("target", value.targetStr)
/* Input attributes */
fun AttrsBuilder<Tag.Input>.type(value: InputType) =
fun AttrsBuilder<HTMLInputElement>.type(value: InputType) =
attr("type", value.typeStr)
fun AttrsBuilder<Tag.Input>.accept(value: String) =
fun AttrsBuilder<HTMLInputElement>.accept(value: String) =
attr("accept", value) // type: file only
fun AttrsBuilder<Tag.Input>.alt(value: String) =
fun AttrsBuilder<HTMLInputElement>.alt(value: String) =
attr("alt", value) // type: image only
fun AttrsBuilder<Tag.Input>.autoComplete(value: Boolean = true) =
fun AttrsBuilder<HTMLInputElement>.autoComplete(value: Boolean = true) =
attr("autocomplete", if (value) "" else null)
fun AttrsBuilder<Tag.Input>.autoFocus(value: Boolean = true) =
fun AttrsBuilder<HTMLInputElement>.autoFocus(value: Boolean = true) =
attr("autofocus", if (value) "" else null)
fun AttrsBuilder<Tag.Input>.capture(value: String) =
fun AttrsBuilder<HTMLInputElement>.capture(value: String) =
attr("capture", value) // type: file only
fun AttrsBuilder<Tag.Input>.checked(value: Boolean = true) =
fun AttrsBuilder<HTMLInputElement>.checked(value: Boolean = true) =
attr("checked", if (value) "" else null) // radio, checkbox
fun AttrsBuilder<Tag.Input>.dirName(value: String) =
fun AttrsBuilder<HTMLInputElement>.dirName(value: String) =
attr("dirname", value) // text, search
fun AttrsBuilder<Tag.Input>.disabled(value: Boolean = true) =
fun AttrsBuilder<HTMLInputElement>.disabled(value: Boolean = true) =
attr("disabled", if (value) "" else null)
fun AttrsBuilder<Tag.Input>.form(id: String) =
fun AttrsBuilder<HTMLInputElement>.form(id: String) =
attr("form", id)
fun AttrsBuilder<Tag.Input>.formAction(url: String) =
fun AttrsBuilder<HTMLInputElement>.formAction(url: String) =
attr("formaction", url)
fun AttrsBuilder<Tag.Input>.formEncType(value: InputFormEncType) =
fun AttrsBuilder<HTMLInputElement>.formEncType(value: InputFormEncType) =
attr("formenctype", value.typeStr)
fun AttrsBuilder<Tag.Input>.formMethod(value: InputFormMethod) =
fun AttrsBuilder<HTMLInputElement>.formMethod(value: InputFormMethod) =
attr("formmethod", value.methodStr)
fun AttrsBuilder<Tag.Input>.formNoValidate(value: Boolean = true) =
fun AttrsBuilder<HTMLInputElement>.formNoValidate(value: Boolean = true) =
attr("formnovalidate", if (value) "" else null)
fun AttrsBuilder<Tag.Input>.formTarget(value: InputFormTarget) =
fun AttrsBuilder<HTMLInputElement>.formTarget(value: InputFormTarget) =
attr("formtarget", value.targetStr)
fun AttrsBuilder<Tag.Input>.height(value: Int) =
fun AttrsBuilder<HTMLInputElement>.height(value: Int) =
attr("height", value.toString()) // image only
fun AttrsBuilder<Tag.Input>.width(value: Int) =
fun AttrsBuilder<HTMLInputElement>.width(value: Int) =
attr("width", value.toString()) // image only
fun AttrsBuilder<Tag.Input>.list(dataListId: String) =
fun AttrsBuilder<HTMLInputElement>.list(dataListId: String) =
attr("list", dataListId)
fun AttrsBuilder<Tag.Input>.max(value: String) =
fun AttrsBuilder<HTMLInputElement>.max(value: String) =
attr("max", value)
fun AttrsBuilder<Tag.Input>.maxLength(value: Int) =
fun AttrsBuilder<HTMLInputElement>.maxLength(value: Int) =
attr("maxlength", value.toString())
fun AttrsBuilder<Tag.Input>.min(value: String) =
fun AttrsBuilder<HTMLInputElement>.min(value: String) =
attr("min", value)
fun AttrsBuilder<Tag.Input>.minLength(value: Int) =
fun AttrsBuilder<HTMLInputElement>.minLength(value: Int) =
attr("minlength", value.toString())
fun AttrsBuilder<Tag.Input>.multiple(value: Boolean = true) =
fun AttrsBuilder<HTMLInputElement>.multiple(value: Boolean = true) =
attr("multiple", if (value) "" else null)
fun AttrsBuilder<Tag.Input>.name(value: String) =
fun AttrsBuilder<HTMLInputElement>.name(value: String) =
attr("name", value)
fun AttrsBuilder<Tag.Input>.pattern(value: String) =
fun AttrsBuilder<HTMLInputElement>.pattern(value: String) =
attr("pattern", value)
fun AttrsBuilder<Tag.Input>.placeholder(value: String) =
fun AttrsBuilder<HTMLInputElement>.placeholder(value: String) =
attr("placeholder", value)
fun AttrsBuilder<Tag.Input>.readOnly(value: Boolean = true) =
fun AttrsBuilder<HTMLInputElement>.readOnly(value: Boolean = true) =
attr("readonly", if (value) "" else null)
fun AttrsBuilder<Tag.Input>.required(value: Boolean = true) =
fun AttrsBuilder<HTMLInputElement>.required(value: Boolean = true) =
attr("required", value.toString())
fun AttrsBuilder<Tag.Input>.size(value: Int) =
fun AttrsBuilder<HTMLInputElement>.size(value: Int) =
attr("size", value.toString())
fun AttrsBuilder<Tag.Input>.src(value: String) =
fun AttrsBuilder<HTMLInputElement>.src(value: String) =
attr("src", value.toString()) // image only
fun AttrsBuilder<Tag.Input>.step(value: Int) =
fun AttrsBuilder<HTMLInputElement>.step(value: Int) =
attr("step", value.toString()) // numeric types only
fun AttrsBuilder<Tag.Input>.valueAttr(value: String) =
fun AttrsBuilder<HTMLInputElement>.valueAttr(value: String) =
attr("value", value)
fun AttrsBuilder<Tag.Input>.value(value: String): AttrsBuilder<Tag.Input> {
fun AttrsBuilder<HTMLInputElement>.value(value: String): AttrsBuilder<HTMLInputElement> {
prop(setInputValue, value)
return this
}
/* Option attributes */
fun AttrsBuilder<Tag.Option>.value(value: String) =
fun AttrsBuilder<HTMLOptionElement>.value(value: String) =
attr("value", value)
fun AttrsBuilder<Tag.Option>.disabled(value: Boolean = true) =
fun AttrsBuilder<HTMLOptionElement>.disabled(value: Boolean = true) =
attr("disabled", if (value) "" else null)
fun AttrsBuilder<Tag.Option>.selected(value: Boolean = true) =
fun AttrsBuilder<HTMLOptionElement>.selected(value: Boolean = true) =
attr("selected", if (value) "" else null)
fun AttrsBuilder<Tag.Option>.label(value: String) =
fun AttrsBuilder<HTMLOptionElement>.label(value: String) =
attr("label", value)
/* Select attributes */
fun AttrsBuilder<Tag.Select>.autocomplete(value: String) =
fun AttrsBuilder<HTMLSelectElement>.autocomplete(value: String) =
attr("autocomplete", value)
fun AttrsBuilder<Tag.Select>.autofocus(value: Boolean = true) =
fun AttrsBuilder<HTMLSelectElement>.autofocus(value: Boolean = true) =
attr("autofocus", if (value) "" else null)
fun AttrsBuilder<Tag.Select>.disabled(value: Boolean = true) =
fun AttrsBuilder<HTMLSelectElement>.disabled(value: Boolean = true) =
attr("disabled", if (value) "" else null)
fun AttrsBuilder<Tag.Select>.form(formId: String) =
fun AttrsBuilder<HTMLSelectElement>.form(formId: String) =
attr("form", formId)
fun AttrsBuilder<Tag.Select>.multiple(value: Boolean = true) =
fun AttrsBuilder<HTMLSelectElement>.multiple(value: Boolean = true) =
attr("multiple", if (value) "" else null)
fun AttrsBuilder<Tag.Select>.name(value: String) =
fun AttrsBuilder<HTMLSelectElement>.name(value: String) =
attr("name", value)
fun AttrsBuilder<Tag.Select>.required(value: Boolean = true) =
fun AttrsBuilder<HTMLSelectElement>.required(value: Boolean = true) =
attr("required", if (value) "" else null)
fun AttrsBuilder<Tag.Select>.size(numberOfRows: Int) =
fun AttrsBuilder<HTMLSelectElement>.size(numberOfRows: Int) =
attr("size", numberOfRows.toString())
/* OptGroup attributes */
fun AttrsBuilder<Tag.OptGroup>.label(value: String) =
fun AttrsBuilder<HTMLOptGroupElement>.label(value: String) =
attr("label", value)
fun AttrsBuilder<Tag.OptGroup>.disabled(value: Boolean = true) =
fun AttrsBuilder<HTMLOptGroupElement>.disabled(value: Boolean = true) =
attr("disabled", if (value) "" else null)
/* TextArea attributes */
fun AttrsBuilder<Tag.TextArea>.autoComplete(value: Boolean = true) =
fun AttrsBuilder<HTMLTextAreaElement>.autoComplete(value: Boolean = true) =
attr("autocomplete", if (value) "on" else "off")
fun AttrsBuilder<Tag.TextArea>.autoFocus(value: Boolean = true) =
fun AttrsBuilder<HTMLTextAreaElement>.autoFocus(value: Boolean = true) =
attr("autofocus", if (value) "" else null)
fun AttrsBuilder<Tag.TextArea>.cols(value: Int) =
fun AttrsBuilder<HTMLTextAreaElement>.cols(value: Int) =
attr("cols", value.toString())
fun AttrsBuilder<Tag.TextArea>.disabled(value: Boolean = true) =
fun AttrsBuilder<HTMLTextAreaElement>.disabled(value: Boolean = true) =
attr("disabled", if (value) "" else null)
fun AttrsBuilder<Tag.TextArea>.form(formId: String) =
fun AttrsBuilder<HTMLTextAreaElement>.form(formId: String) =
attr("form", formId)
fun AttrsBuilder<Tag.TextArea>.maxLength(value: Int) =
fun AttrsBuilder<HTMLTextAreaElement>.maxLength(value: Int) =
attr("maxlength", value.toString())
fun AttrsBuilder<Tag.TextArea>.minLength(value: Int) =
fun AttrsBuilder<HTMLTextAreaElement>.minLength(value: Int) =
attr("minlength", value.toString())
fun AttrsBuilder<Tag.TextArea>.name(value: String) =
fun AttrsBuilder<HTMLTextAreaElement>.name(value: String) =
attr("name", value)
fun AttrsBuilder<Tag.TextArea>.placeholder(value: String) =
fun AttrsBuilder<HTMLTextAreaElement>.placeholder(value: String) =
attr("placeholder", value)
fun AttrsBuilder<Tag.TextArea>.readOnly(value: Boolean = true) =
fun AttrsBuilder<HTMLTextAreaElement>.readOnly(value: Boolean = true) =
attr("readonly", if (value) "" else null)
fun AttrsBuilder<Tag.TextArea>.required(value: Boolean = true) =
fun AttrsBuilder<HTMLTextAreaElement>.required(value: Boolean = true) =
attr("required", if (value) "" else null)
fun AttrsBuilder<Tag.TextArea>.rows(value: Int) =
fun AttrsBuilder<HTMLTextAreaElement>.rows(value: Int) =
attr("rows", value.toString())
fun AttrsBuilder<Tag.TextArea>.wrap(value: TextAreaWrap) =
fun AttrsBuilder<HTMLTextAreaElement>.wrap(value: TextAreaWrap) =
attr("wrap", value.str)
fun AttrsBuilder<Tag.TextArea>.value(value: String): AttrsBuilder<Tag.TextArea> {
fun AttrsBuilder<HTMLTextAreaElement>.value(value: String): AttrsBuilder<HTMLTextAreaElement> {
prop(setInputValue, value)
return this
}
/* Img attributes */
fun AttrsBuilder<Tag.Img>.src(value: String?): AttrsBuilder<Tag.Img> =
fun AttrsBuilder<HTMLImageElement>.src(value: String?): AttrsBuilder<HTMLImageElement> =
attr("src", value)
fun AttrsBuilder<Tag.Img>.alt(value: String?): AttrsBuilder<Tag.Img> =
fun AttrsBuilder<HTMLImageElement>.alt(value: String?): AttrsBuilder<HTMLImageElement> =
attr("alt", value)
private val setInputValue: (HTMLInputElement, String) -> Unit = { e, v ->
@ -329,24 +302,19 @@ private val setInputValue: (HTMLInputElement, String) -> Unit = { e, v ->
}
/* Img attributes */
fun AttrsBuilder<Tag.Label>.forId(value: String?): AttrsBuilder<Tag.Label> =
fun AttrsBuilder<HTMLLabelElement>.forId(value: String?): AttrsBuilder<HTMLLabelElement> =
attr("for", value)
/* Table attributes */
fun AttrsBuilder<Tag.Th>.scope(value: Scope?): AttrsBuilder<Tag.Th> =
attr("scope", value?.str)
fun AttrsBuilder<Tag.Col>.span(value: Int): AttrsBuilder<Tag.Col> =
fun AttrsBuilder<HTMLTableColElement>.span(value: Int): AttrsBuilder<HTMLTableColElement> =
attr("span", value.toString())
fun AttrsBuilder<Tag.Th>.colspan(value: Int): AttrsBuilder<Tag.Th> =
attr("colspan", value.toString())
fun AttrsBuilder<Tag.Th>.rowspan(value: Int): AttrsBuilder<Tag.Th> =
attr("rowspan", value.toString())
fun AttrsBuilder<HTMLTableCellElement>.scope(value: Scope?): AttrsBuilder<HTMLTableCellElement> =
attr("scope", value?.str)
fun AttrsBuilder<Tag.Td>.colspan(value: Int): AttrsBuilder<Tag.Td> =
fun AttrsBuilder<HTMLTableCellElement>.colspan(value: Int): AttrsBuilder<HTMLTableCellElement> =
attr("colspan", value.toString())
fun AttrsBuilder<Tag.Td>.rowspan(value: Int): AttrsBuilder<Tag.Td> =
fun AttrsBuilder<HTMLTableCellElement>.rowspan(value: Int): AttrsBuilder<HTMLTableCellElement> =
attr("rowspan", value.toString())

4
web/core/src/jsMain/kotlin/androidx/compose/web/attributes/AttrsBuilder.kt

@ -7,7 +7,7 @@ import org.jetbrains.compose.web.css.StyleBuilderImpl
import org.w3c.dom.Element
import org.w3c.dom.HTMLElement
class AttrsBuilder<TTag : Tag> : EventsListenerBuilder() {
class AttrsBuilder<TElement : Element> : EventsListenerBuilder() {
private val attributesMap = mutableMapOf<String, String>()
val styleBuilder = StyleBuilderImpl()
@ -34,7 +34,7 @@ class AttrsBuilder<TTag : Tag> : EventsListenerBuilder() {
this.refEffect = effect
}
fun attr(attr: String, value: String?): AttrsBuilder<TTag> {
fun attr(attr: String, value: String?): AttrsBuilder<TElement> {
if (value == null) {
attributesMap.remove(attr)
} else {

12
web/core/src/jsMain/kotlin/androidx/compose/web/elements/Base.kt

@ -13,7 +13,6 @@ import androidx.compose.runtime.remember
import org.jetbrains.compose.web.DomApplier
import org.jetbrains.compose.web.DomElementWrapper
import org.jetbrains.compose.web.attributes.AttrsBuilder
import org.jetbrains.compose.web.attributes.Tag
import kotlinx.browser.document
import org.w3c.dom.Element
import org.w3c.dom.HTMLAnchorElement
@ -23,7 +22,6 @@ import org.w3c.dom.HTMLDivElement
import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLFormElement
import org.w3c.dom.HTMLHRElement
import org.w3c.dom.HTMLHeadElement
import org.w3c.dom.HTMLHeadingElement
import org.w3c.dom.HTMLImageElement
import org.w3c.dom.HTMLInputElement
@ -151,9 +149,9 @@ interface ElementBuilder<TElement : Element> {
}
@Composable
fun <TTag : Tag, TElement : Element> TagElement(
fun <TElement : Element> TagElement(
elementBuilder: ElementBuilder<TElement>,
applyAttrs: AttrsBuilder<TTag>.() -> Unit,
applyAttrs: AttrsBuilder<TElement>.() -> Unit,
content: (@Composable ElementScope<TElement>.() -> Unit)?
) {
val scope = remember { ElementScopeImpl<TElement>() }
@ -166,7 +164,7 @@ fun <TTag : Tag, TElement : Element> TagElement(
}
},
attrsSkippableUpdate = {
val attrsApplied = AttrsBuilder<TTag>().also { it.applyAttrs() }
val attrsApplied = AttrsBuilder<TElement>().also { it.applyAttrs() }
refEffect.effect = attrsApplied.refEffect
val attrsCollected = attrsApplied.collect()
val events = attrsApplied.collectListeners()
@ -188,9 +186,9 @@ fun <TTag : Tag, TElement : Element> TagElement(
}
@Composable
fun <TTag : Tag, TElement : Element> TagElement(
fun <TElement : Element> TagElement(
tagName: String,
applyAttrs: AttrsBuilder<TTag>.() -> Unit,
applyAttrs: AttrsBuilder<TElement>.() -> Unit,
content: (@Composable ElementScope<TElement>.() -> Unit)?
) = TagElement(
elementBuilder = ElementBuilder.createBuilder(tagName),

117
web/core/src/jsMain/kotlin/androidx/compose/web/elements/Elements.kt

@ -6,7 +6,6 @@ import org.jetbrains.compose.web.DomApplier
import org.jetbrains.compose.web.DomNodeWrapper
import org.jetbrains.compose.web.attributes.AttrsBuilder
import org.jetbrains.compose.web.attributes.InputType
import org.jetbrains.compose.web.attributes.Tag
import org.jetbrains.compose.web.attributes.action
import org.jetbrains.compose.web.attributes.alt
import org.jetbrains.compose.web.attributes.forId
@ -60,7 +59,7 @@ fun Text(value: String) {
@Composable
fun Div(
attrs: AttrBuilderContext<Tag.Div> = {},
attrs: AttrBuilderContext<HTMLDivElement> = {},
content: ContentBuilder<HTMLDivElement>? = null
) {
TagElement(
@ -73,10 +72,10 @@ fun Div(
@Composable
fun A(
href: String? = null,
attrs: AttrBuilderContext<Tag.A> = {},
attrs: AttrBuilderContext<HTMLAnchorElement> = {},
content: ContentBuilder<HTMLAnchorElement>? = null
) {
TagElement<Tag.A, HTMLAnchorElement>(
TagElement(
elementBuilder = ElementBuilder.A,
applyAttrs = {
href(href)
@ -90,9 +89,9 @@ fun A(
fun Input(
type: InputType = InputType.Text,
value: String = "",
attrs: AttrBuilderContext<Tag.Input> = {}
attrs: AttrBuilderContext<HTMLInputElement> = {}
) {
TagElement<Tag.Input, HTMLInputElement>(
TagElement(
elementBuilder = ElementBuilder.Input,
applyAttrs = {
type(type)
@ -105,107 +104,107 @@ fun Input(
@Composable
fun Button(
attrs: AttrBuilderContext<Tag.Button> = {},
attrs: AttrBuilderContext<HTMLButtonElement> = {},
content: ContentBuilder<HTMLButtonElement>? = null
) = TagElement(elementBuilder = ElementBuilder.Button, applyAttrs = attrs, content = content)
@Composable
fun H1(
attrs: AttrBuilderContext<Tag.H> = {},
attrs: AttrBuilderContext<HTMLHeadingElement> = {},
content: ContentBuilder<HTMLHeadingElement>? = null
) = TagElement(elementBuilder = ElementBuilder.H1, applyAttrs = attrs, content = content)
@Composable
fun H2(
attrs: AttrBuilderContext<Tag.H> = {},
attrs: AttrBuilderContext<HTMLHeadingElement> = {},
content: ContentBuilder<HTMLHeadingElement>? = null
) = TagElement(elementBuilder = ElementBuilder.H2, applyAttrs = attrs, content = content)
@Composable
fun H3(
attrs: AttrBuilderContext<Tag.H> = {},
attrs: AttrBuilderContext<HTMLHeadingElement> = {},
content: ContentBuilder<HTMLHeadingElement>? = null
) = TagElement(elementBuilder = ElementBuilder.H3, applyAttrs = attrs, content = content)
@Composable
fun H4(
attrs: AttrBuilderContext<Tag.H> = {},
attrs: AttrBuilderContext<HTMLHeadingElement> = {},
content: ContentBuilder<HTMLHeadingElement>? = null
) = TagElement(elementBuilder = ElementBuilder.H4, applyAttrs = attrs, content = content)
@Composable
fun H5(
attrs: AttrBuilderContext<Tag.H> = {},
attrs: AttrBuilderContext<HTMLHeadingElement> = {},
content: ContentBuilder<HTMLHeadingElement>? = null
) = TagElement(elementBuilder = ElementBuilder.H5, applyAttrs = attrs, content = content)
@Composable
fun H6(
attrs: AttrBuilderContext<Tag.H> = {},
attrs: AttrBuilderContext<HTMLHeadingElement> = {},
content: ContentBuilder<HTMLHeadingElement>? = null
) = TagElement(elementBuilder = ElementBuilder.H6, applyAttrs = attrs, content = content)
@Composable
fun P(
attrs: AttrBuilderContext<Tag.P> = {},
attrs: AttrBuilderContext<HTMLParagraphElement> = {},
content: ContentBuilder<HTMLParagraphElement>? = null
) = TagElement(elementBuilder = ElementBuilder.P, applyAttrs = attrs, content = content)
@Composable
fun Em(
attrs: AttrBuilderContext<Tag> = {},
attrs: AttrBuilderContext<HTMLElement> = {},
content: ContentBuilder<HTMLElement>? = null
) = TagElement(elementBuilder = ElementBuilder.Em, applyAttrs = attrs, content = content)
@Composable
fun I(
attrs: AttrBuilderContext<Tag> = {},
attrs: AttrBuilderContext<HTMLElement> = {},
content: ContentBuilder<HTMLElement>? = null
) = TagElement(elementBuilder = ElementBuilder.I, applyAttrs = attrs, content = content)
@Composable
fun B(
attrs: AttrBuilderContext<Tag> = {},
attrs: AttrBuilderContext<HTMLElement> = {},
content: ContentBuilder<HTMLElement>? = null
) = TagElement(elementBuilder = ElementBuilder.B, applyAttrs = attrs, content = content)
@Composable
fun Small(
attrs: AttrBuilderContext<Tag> = {},
attrs: AttrBuilderContext<HTMLElement> = {},
content: ContentBuilder<HTMLElement>? = null
) = TagElement(elementBuilder = ElementBuilder.Small, applyAttrs = attrs, content = content)
@Composable
fun Span(
attrs: AttrBuilderContext<Tag.Span> = {},
attrs: AttrBuilderContext<HTMLSpanElement> = {},
content: ContentBuilder<HTMLSpanElement>? = null
) = TagElement(elementBuilder = ElementBuilder.Span, applyAttrs = attrs, content = content)
@Composable
fun Br(attrs: AttrBuilderContext<Tag.Br> = {}) =
TagElement<Tag.Br, HTMLBRElement>(elementBuilder = ElementBuilder.Br, applyAttrs = attrs, content = null)
fun Br(attrs: AttrBuilderContext<HTMLBRElement> = {}) =
TagElement(elementBuilder = ElementBuilder.Br, applyAttrs = attrs, content = null)
@Composable
fun Ul(
attrs: AttrBuilderContext<Tag.Ul> = {},
attrs: AttrBuilderContext<HTMLUListElement> = {},
content: ContentBuilder<HTMLUListElement>? = null
) = TagElement(elementBuilder = ElementBuilder.Ul, applyAttrs = attrs, content = content)
@Composable
fun Ol(
attrs: AttrBuilderContext<Tag.Ol> = {},
attrs: AttrBuilderContext<HTMLOListElement> = {},
content: ContentBuilder<HTMLOListElement>? = null
) = TagElement(elementBuilder = ElementBuilder.Ol, applyAttrs = attrs, content = content)
@Composable
fun DOMScope<HTMLOListElement>.Li(
attrs: AttrBuilderContext<Tag.Li> = {},
attrs: AttrBuilderContext<HTMLLIElement> = {},
content: ContentBuilder<HTMLLIElement>? = null
) = TagElement(elementBuilder = ElementBuilder.Li, applyAttrs = attrs, content = content)
@Composable
fun DOMScope<HTMLUListElement>.Li(
attrs: AttrBuilderContext<Tag.Li> = {},
attrs: AttrBuilderContext<HTMLLIElement> = {},
content: ContentBuilder<HTMLLIElement>? = null
) = TagElement(elementBuilder = ElementBuilder.Li, applyAttrs = attrs, content = content)
@ -213,8 +212,8 @@ fun DOMScope<HTMLUListElement>.Li(
fun Img(
src: String,
alt: String = "",
attrs: AttrBuilderContext<Tag.Img> = {}
) = TagElement<Tag.Img, HTMLImageElement>(
attrs: AttrBuilderContext<HTMLImageElement> = {}
) = TagElement(
elementBuilder = ElementBuilder.Img,
applyAttrs = {
src(src).alt(alt)
@ -226,9 +225,9 @@ fun Img(
@Composable
fun Form(
action: String? = null,
attrs: AttrBuilderContext<Tag.Form> = {},
attrs: AttrBuilderContext<HTMLFormElement> = {},
content: ContentBuilder<HTMLFormElement>? = null
) = TagElement<Tag.Form, HTMLFormElement>(
) = TagElement(
elementBuilder = ElementBuilder.Form,
applyAttrs = {
if (!action.isNullOrEmpty()) action(action)
@ -239,7 +238,7 @@ fun Form(
@Composable
fun Select(
attrs: AttrBuilderContext<Tag.Select> = {},
attrs: AttrBuilderContext<HTMLSelectElement> = {},
content: ContentBuilder<HTMLSelectElement>? = null
) = TagElement(
elementBuilder = ElementBuilder.Select,
@ -250,9 +249,9 @@ fun Select(
@Composable
fun Option(
value: String,
attrs: AttrBuilderContext<Tag.Option> = {},
attrs: AttrBuilderContext<HTMLOptionElement> = {},
content: ContentBuilder<HTMLOptionElement>? = null
) = TagElement<Tag.Option, HTMLOptionElement>(
) = TagElement(
elementBuilder = ElementBuilder.Option,
applyAttrs = {
value(value)
@ -264,9 +263,9 @@ fun Option(
@Composable
fun OptGroup(
label: String,
attrs: AttrBuilderContext<Tag.OptGroup> = {},
attrs: AttrBuilderContext<HTMLOptGroupElement> = {},
content: ContentBuilder<HTMLOptGroupElement>? = null
) = TagElement<Tag.OptGroup, HTMLOptGroupElement>(
) = TagElement(
elementBuilder = ElementBuilder.OptGroup,
applyAttrs = {
label(label)
@ -277,7 +276,7 @@ fun OptGroup(
@Composable
fun Section(
attrs: AttrBuilderContext<Tag> = {},
attrs: AttrBuilderContext<HTMLElement> = {},
content: ContentBuilder<HTMLElement>? = null
) = TagElement(
elementBuilder = ElementBuilder.Section,
@ -287,9 +286,9 @@ fun Section(
@Composable
fun TextArea(
attrs: AttrBuilderContext<Tag.TextArea> = {},
attrs: AttrBuilderContext<HTMLTextAreaElement> = {},
value: String
) = TagElement<Tag.TextArea, HTMLTextAreaElement>(
) = TagElement(
elementBuilder = ElementBuilder.TextArea,
applyAttrs = {
value(value)
@ -301,7 +300,7 @@ fun TextArea(
@Composable
fun Nav(
attrs: AttrBuilderContext<Tag.Nav> = {},
attrs: AttrBuilderContext<HTMLElement> = {},
content: ContentBuilder<HTMLElement>? = null
) = TagElement(
elementBuilder = ElementBuilder.Nav,
@ -311,7 +310,7 @@ fun Nav(
@Composable
fun Pre(
attrs: AttrBuilderContext<Tag.Pre> = {},
attrs: AttrBuilderContext<HTMLPreElement> = {},
content: ContentBuilder<HTMLPreElement>? = null
) {
TagElement(
@ -323,7 +322,7 @@ fun Pre(
@Composable
fun Code(
attrs: AttrBuilderContext<Tag.Code> = {},
attrs: AttrBuilderContext<HTMLElement> = {},
content: ContentBuilder<HTMLElement>? = null
) {
TagElement(
@ -335,10 +334,10 @@ fun Code(
@Composable
fun Main(
attrs: AttrBuilderContext<Tag.Div> = {},
attrs: AttrBuilderContext<HTMLElement> = {},
content: ContentBuilder<HTMLElement>? = null
) {
TagElement<Tag.Div, HTMLElement>(
TagElement(
elementBuilder = ElementBuilder.Main,
applyAttrs = attrs,
content = content
@ -347,10 +346,10 @@ fun Main(
@Composable
fun Footer(
attrs: AttrBuilderContext<Tag.Div> = {},
attrs: AttrBuilderContext<HTMLElement> = {},
content: ContentBuilder<HTMLElement>? = null
) {
TagElement<Tag.Div, HTMLElement>(
TagElement(
elementBuilder = ElementBuilder.Footer,
applyAttrs = attrs,
content = content
@ -359,9 +358,9 @@ fun Footer(
@Composable
fun Hr(
attrs: AttrBuilderContext<Tag.Hr> = {}
attrs: AttrBuilderContext<HTMLHRElement> = {}
) {
TagElement<Tag.Hr, HTMLHRElement>(
TagElement(
elementBuilder = ElementBuilder.Hr,
applyAttrs = attrs,
content = null
@ -371,10 +370,10 @@ fun Hr(
@Composable
fun Label(
forId: String? = null,
attrs: AttrBuilderContext<Tag.Label> = {},
attrs: AttrBuilderContext<HTMLLabelElement> = {},
content: ContentBuilder<HTMLLabelElement>? = null
) {
TagElement<Tag.Label, HTMLLabelElement>(
TagElement(
elementBuilder = ElementBuilder.Label,
applyAttrs = {
forId(forId)
@ -386,7 +385,7 @@ fun Label(
@Composable
fun Table(
attrs: AttrBuilderContext<Tag.Table> = {},
attrs: AttrBuilderContext<HTMLTableElement> = {},
content: ContentBuilder<HTMLTableElement>? = null
) {
TagElement(
@ -398,7 +397,7 @@ fun Table(
@Composable
fun Caption(
attrs: AttrBuilderContext<Tag.Caption> = {},
attrs: AttrBuilderContext<HTMLTableCaptionElement> = {},
content: ContentBuilder<HTMLTableCaptionElement>? = null
) {
TagElement(
@ -410,9 +409,9 @@ fun Caption(
@Composable
fun Col(
attrs: AttrBuilderContext<Tag.Col> = {}
attrs: AttrBuilderContext<HTMLTableColElement> = {}
) {
TagElement<Tag.Col, HTMLTableColElement>(
TagElement(
elementBuilder = ElementBuilder.Col,
applyAttrs = attrs,
content = null
@ -421,7 +420,7 @@ fun Col(
@Composable
fun Colgroup(
attrs: AttrBuilderContext<Tag.Colgroup> = {},
attrs: AttrBuilderContext<HTMLTableColElement> = {},
content: ContentBuilder<HTMLTableColElement>? = null
) {
TagElement(
@ -433,7 +432,7 @@ fun Colgroup(
@Composable
fun Tr(
attrs: AttrBuilderContext<Tag.Tr> = {},
attrs: AttrBuilderContext<HTMLTableRowElement> = {},
content: ContentBuilder<HTMLTableRowElement>? = null
) {
TagElement(
@ -445,7 +444,7 @@ fun Tr(
@Composable
fun Thead(
attrs: AttrBuilderContext<Tag.Thead> = {},
attrs: AttrBuilderContext<HTMLTableSectionElement> = {},
content: ContentBuilder<HTMLTableSectionElement>? = null
) {
TagElement(
@ -457,7 +456,7 @@ fun Thead(
@Composable
fun Th(
attrs: AttrBuilderContext<Tag.Th> = {},
attrs: AttrBuilderContext<HTMLTableCellElement> = {},
content: ContentBuilder<HTMLTableCellElement>? = null
) {
TagElement(
@ -469,7 +468,7 @@ fun Th(
@Composable
fun Td(
attrs: AttrBuilderContext<Tag.Td> = {},
attrs: AttrBuilderContext<HTMLTableCellElement> = {},
content: ContentBuilder<HTMLTableCellElement>? = null
) {
TagElement(
@ -481,7 +480,7 @@ fun Td(
@Composable
fun Tbody(
attrs: AttrBuilderContext<Tag.Tbody> = {},
attrs: AttrBuilderContext<HTMLTableSectionElement> = {},
content: ContentBuilder<HTMLTableSectionElement>? = null
) {
TagElement(
@ -493,7 +492,7 @@ fun Tbody(
@Composable
fun Tfoot(
attrs: AttrBuilderContext<Tag.Tfoot> = {},
attrs: AttrBuilderContext<HTMLTableSectionElement> = {},
content: ContentBuilder<HTMLTableSectionElement>? = null
) {
TagElement(

7
web/core/src/jsMain/kotlin/androidx/compose/web/elements/Style.kt

@ -2,7 +2,6 @@ package org.jetbrains.compose.web.dom
import androidx.compose.runtime.Composable
import org.jetbrains.compose.web.attributes.AttrsBuilder
import org.jetbrains.compose.web.attributes.Tag
import org.w3c.dom.HTMLStyleElement
import org.w3c.dom.css.CSSGroupingRule
import org.w3c.dom.css.CSSRule
@ -18,7 +17,7 @@ import org.jetbrains.compose.web.css.*
*/
@Composable
inline fun Style(
crossinline applyAttrs: AttrsBuilder<Tag.Style>.() -> Unit = {},
crossinline applyAttrs: AttrsBuilder<HTMLStyleElement>.() -> Unit = {},
rulesBuild: StyleSheetBuilder.() -> Unit
) {
val builder = StyleSheetBuilderImpl()
@ -34,10 +33,10 @@ inline fun Style(
*/
@Composable
inline fun Style(
crossinline applyAttrs: AttrsBuilder<Tag.Style>.() -> Unit = {},
crossinline applyAttrs: AttrsBuilder<HTMLStyleElement>.() -> Unit = {},
cssRules: CSSRuleDeclarationList
) {
TagElement<Tag.Style, HTMLStyleElement>(
TagElement(
elementBuilder = ElementBuilder.Style,
applyAttrs = {
applyAttrs()

3
web/core/src/jsTest/kotlin/elements/ElementsTests.kt

@ -7,7 +7,6 @@ package org.jetbrains.compose.web.core.tests.elements
import androidx.compose.runtime.Composable
import org.jetbrains.compose.web.attributes.AttrsBuilder
import org.jetbrains.compose.web.attributes.Tag
import org.jetbrains.compose.web.core.tests.runTest
import org.jetbrains.compose.web.dom.A
import org.jetbrains.compose.web.dom.B
@ -130,7 +129,7 @@ class ElementsTests {
fun rawCreation() = runTest {
@Composable
fun CustomElement(
attrs: AttrsBuilder<Tag.Div>.() -> Unit,
attrs: AttrsBuilder<HTMLElement>.() -> Unit,
content: ContentBuilder<HTMLElement>? = null
) {
TagElement(

Loading…
Cancel
Save