From 49c0ec79e5c65620ec167fdd2fba590607516daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Petu=C5=A1ka?= Date: Tue, 1 Feb 2022 13:06:34 +0000 Subject: [PATCH] web: AttrsScope interface extraction (#1694) * AttrsScope interface extraction * PR amendments * resolve conflicts * remove yarn lockfile * move submodule back (cherry picked from commit f98dfbc7617aee72abee3109199ff4aeedeaa5a4) --- .gitignore | 5 +- web/benchmark-core/build.gradle.kts | 4 +- web/build.gradle.kts | 20 +- .../jetbrains/compose/web/attributes/Attrs.kt | 186 ++++++------- .../{AttrsBuilder.kt => AttrsScope.kt} | 148 ++++++---- ...tenerBuilder.kt => EventsListenerScope.kt} | 232 +++++++++------- .../web/attributes/SyntheticEventListener.kt | 6 +- ...nputAttrsBuilder.kt => InputAttrsScope.kt} | 37 ++- ...ectAttrsBuilder.kt => SelectAttrsScope.kt} | 18 +- .../builders/TextAreaAttrsBuilder.kt | 49 ---- .../attributes/builders/TextAreaAttrsScope.kt | 64 +++++ .../org/jetbrains/compose/web/css/CSSRules.kt | 2 +- .../css/{StyleBuilder.kt => StyleScope.kt} | 23 +- .../jetbrains/compose/web/elements/Base.kt | 21 +- .../compose/web/elements/Elements.kt | 153 ++++++----- .../compose/web/elements/InputElements.kt | 42 +-- .../compose/web/elements/RadioGroup.kt | 4 +- .../jsTest/kotlin/elements/AttributesTests.kt | 42 +-- .../jsTest/kotlin/elements/ElementsTests.kt | 7 +- .../compose/web/sample/tests/InputsTests.kt | 2 +- .../org/jetbrains/compose/web/svg/svg.kt | 258 +++++++++--------- web/widgets/src/jsMain/kotlin/Modifier.kt | 8 +- .../jsMain/kotlin/internal/ActualModifier.kt | 6 +- 23 files changed, 732 insertions(+), 605 deletions(-) rename web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/{AttrsBuilder.kt => AttrsScope.kt} (55%) rename web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/{EventsListenerBuilder.kt => EventsListenerScope.kt} (59%) rename web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/{InputAttrsBuilder.kt => InputAttrsScope.kt} (66%) rename web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/{SelectAttrsBuilder.kt => SelectAttrsScope.kt} (69%) delete mode 100644 web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/TextAreaAttrsBuilder.kt create mode 100644 web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/TextAreaAttrsScope.kt rename web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/{StyleBuilder.kt => StyleScope.kt} (90%) diff --git a/.gitignore b/.gitignore index 1292cbd859..e752e3601e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,7 @@ out build/ /captures .externalNativeBuild -.cxx \ No newline at end of file +.cxx + +# Ignoring the persistant lockfile until kotlin.js vulnerabilities are fixed +yarn.lock diff --git a/web/benchmark-core/build.gradle.kts b/web/benchmark-core/build.gradle.kts index 956ae3d8f5..60d5e761cb 100644 --- a/web/benchmark-core/build.gradle.kts +++ b/web/benchmark-core/build.gradle.kts @@ -6,11 +6,11 @@ plugins { kotlin { js(IR) { - browser() { + browser { testTask { useKarma { useChromeHeadless() - //useFirefox() + // useFirefox() } } } diff --git a/web/build.gradle.kts b/web/build.gradle.kts index 5ce9c8ddd7..63407d478c 100644 --- a/web/build.gradle.kts +++ b/web/build.gradle.kts @@ -1,4 +1,3 @@ -import org.gradle.api.tasks.testing.AbstractTestTask import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.jetbrains.compose.gradle.kotlinKarmaConfig @@ -19,7 +18,7 @@ fun Project.isSampleProject() = projectDir.parentFile.name == "examples" tasks.register("printBundleSize") { dependsOn( - subprojects.filter { it.isSampleProject() }.map { ":examples:${it.name}:printBundleSize" } + subprojects.filter { it.isSampleProject() }.map { ":examples:${it.name}:printBundleSize" } ) } @@ -34,7 +33,7 @@ subprojects { group = "org.jetbrains.compose.web" version = COMPOSE_WEB_VERSION - tasks.withType() { + tasks.withType { kotlinOptions.jvmTarget = "11" } @@ -54,6 +53,16 @@ subprojects { } pluginManager.withPlugin("kotlin-multiplatform") { + configure { + sourceSets { + all { + languageSettings { + optIn("org.jetbrains.compose.web.internal.runtime.ComposeWebInternalApi") + optIn("kotlin.RequiresOptIn") + } + } + } + } val printTestBundleSize by tasks.registering { dependsOn(tasks.named("jsTest")) doLast { @@ -72,7 +81,6 @@ subprojects { } } - if (isSampleProject()) { val printBundleSize by tasks.registering { dependsOn(tasks.named("jsBrowserDistribution")) @@ -93,10 +101,10 @@ subprojects { configurations.all { resolutionStrategy.dependencySubstitution { substitute(module("org.jetbrains.compose.web:web-widgets")).apply { - with(project(":web-widgets")) + with(project(":web-widgets")) } substitute(module("org.jetbrains.compose.web:web-core")).apply { - with(project(":web-core")) + with(project(":web-core")) } } } diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/Attrs.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/Attrs.kt index ddc851ec6a..5e2137d6dd 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/Attrs.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/Attrs.kt @@ -15,284 +15,284 @@ import org.w3c.dom.HTMLTableCellElement import org.w3c.dom.HTMLTableColElement import org.w3c.dom.HTMLTextAreaElement -fun AttrsBuilder.href(value: String) = +fun AttrsScope.href(value: String) = attr("href", value) -fun AttrsBuilder.target(value: ATarget = ATarget.Self) = +fun AttrsScope.target(value: ATarget = ATarget.Self) = attr("target", value.targetStr) -fun AttrsBuilder.ref(value: ARel) = +fun AttrsScope.ref(value: ARel) = attr("rel", value.relStr) -fun AttrsBuilder.ping(value: String) = +fun AttrsScope.ping(value: String) = attr("ping", value) -fun AttrsBuilder.ping(vararg urls: String) = +fun AttrsScope.ping(vararg urls: String) = attr("ping", urls.joinToString(" ")) -fun AttrsBuilder.hreflang(value: String) = +fun AttrsScope.hreflang(value: String) = attr("hreflang", value) -fun AttrsBuilder.download(value: String = "") = +fun AttrsScope.download(value: String = "") = attr("download", value) /* Button attributes */ -fun AttrsBuilder.autoFocus() = +fun AttrsScope.autoFocus() = attr("autofocus", "") -fun AttrsBuilder.disabled() = +fun AttrsScope.disabled() = attr("disabled", "") -fun AttrsBuilder.form(formId: String) = +fun AttrsScope.form(formId: String) = attr("form", formId) -fun AttrsBuilder.formAction(url: String) = +fun AttrsScope.formAction(url: String) = attr("formaction", url) -fun AttrsBuilder.formEncType(value: ButtonFormEncType) = +fun AttrsScope.formEncType(value: ButtonFormEncType) = attr("formenctype", value.typeStr) -fun AttrsBuilder.formMethod(value: ButtonFormMethod) = +fun AttrsScope.formMethod(value: ButtonFormMethod) = attr("formmethod", value.methodStr) -fun AttrsBuilder.formNoValidate() = +fun AttrsScope.formNoValidate() = attr("formnovalidate", "") -fun AttrsBuilder.formTarget(value: ButtonFormTarget) = +fun AttrsScope.formTarget(value: ButtonFormTarget) = attr("formtarget", value.targetStr) -fun AttrsBuilder.name(value: String) = +fun AttrsScope.name(value: String) = attr("name", value) -fun AttrsBuilder.type(value: ButtonType) = +fun AttrsScope.type(value: ButtonType) = attr("type", value.str) -fun AttrsBuilder.value(value: String) = +fun AttrsScope.value(value: String) = attr("value", value) /* Form attributes */ -fun AttrsBuilder.action(value: String) = +fun AttrsScope.action(value: String) = attr("action", value) -fun AttrsBuilder.acceptCharset(value: String) = +fun AttrsScope.acceptCharset(value: String) = attr("accept-charset", value) -fun AttrsBuilder.autoComplete(value: Boolean = true) = +fun AttrsScope.autoComplete(value: Boolean = true) = attr("autocomplete", if(value) "on" else "off") -fun AttrsBuilder.encType(value: FormEncType) = +fun AttrsScope.encType(value: FormEncType) = attr("enctype", value.typeStr) -fun AttrsBuilder.method(value: FormMethod) = +fun AttrsScope.method(value: FormMethod) = attr("method", value.methodStr) -fun AttrsBuilder.noValidate() = +fun AttrsScope.noValidate() = attr("novalidate", "") -fun AttrsBuilder.target(value: FormTarget) = +fun AttrsScope.target(value: FormTarget) = attr("target", value.targetStr) -fun AttrsBuilder.onSubmit( +fun AttrsScope.onSubmit( listener: (SyntheticSubmitEvent) -> Unit ) { - addEventListener(eventName = EventsListenerBuilder.SUBMIT, listener = listener) + addEventListener(eventName = EventsListenerScope.SUBMIT, listener = listener) } -fun AttrsBuilder.onReset( +fun AttrsScope.onReset( listener: (SyntheticSubmitEvent) -> Unit ) { - addEventListener(eventName = EventsListenerBuilder.RESET, listener = listener) + addEventListener(eventName = EventsListenerScope.RESET, listener = listener) } /* Input attributes */ -fun AttrsBuilder.type(value: InputType<*>) = +fun AttrsScope.type(value: InputType<*>) = attr("type", value.typeStr) -fun AttrsBuilder.accept(value: String) = +fun AttrsScope.accept(value: String) = attr("accept", value) // type: file only -fun AttrsBuilder.alt(value: String) = +fun AttrsScope.alt(value: String) = attr("alt", value) // type: image only -fun AttrsBuilder.autoComplete(value: AutoComplete) = +fun AttrsScope.autoComplete(value: AutoComplete) = attr("autocomplete", value.unsafeCast()) -fun AttrsBuilder.autoFocus() = +fun AttrsScope.autoFocus() = attr("autofocus", "") -fun AttrsBuilder.capture(value: String) = +fun AttrsScope.capture(value: String) = attr("capture", value) // type: file only -fun AttrsBuilder.dirName(value: String) = +fun AttrsScope.dirName(value: String) = attr("dirname", value) // text, search -fun AttrsBuilder.disabled() = +fun AttrsScope.disabled() = attr("disabled", "") -fun AttrsBuilder.form(id: String) = +fun AttrsScope.form(id: String) = attr("form", id) -fun AttrsBuilder.formAction(url: String) = +fun AttrsScope.formAction(url: String) = attr("formaction", url) -fun AttrsBuilder.formEncType(value: InputFormEncType) = +fun AttrsScope.formEncType(value: InputFormEncType) = attr("formenctype", value.typeStr) -fun AttrsBuilder.formMethod(value: InputFormMethod) = +fun AttrsScope.formMethod(value: InputFormMethod) = attr("formmethod", value.methodStr) -fun AttrsBuilder.formNoValidate() = +fun AttrsScope.formNoValidate() = attr("formnovalidate", "") -fun AttrsBuilder.formTarget(value: InputFormTarget) = +fun AttrsScope.formTarget(value: InputFormTarget) = attr("formtarget", value.targetStr) -fun AttrsBuilder.height(value: Int) = +fun AttrsScope.height(value: Int) = attr("height", value.toString()) // image only -fun AttrsBuilder.width(value: Int) = +fun AttrsScope.width(value: Int) = attr("width", value.toString()) // image only -fun AttrsBuilder.list(dataListId: String) = +fun AttrsScope.list(dataListId: String) = attr("list", dataListId) -fun AttrsBuilder.max(value: String) = +fun AttrsScope.max(value: String) = attr("max", value) -fun AttrsBuilder.maxLength(value: Int) = +fun AttrsScope.maxLength(value: Int) = attr("maxlength", value.toString()) -fun AttrsBuilder.min(value: String) = +fun AttrsScope.min(value: String) = attr("min", value) -fun AttrsBuilder.minLength(value: Int) = +fun AttrsScope.minLength(value: Int) = attr("minlength", value.toString()) -fun AttrsBuilder.multiple() = +fun AttrsScope.multiple() = attr("multiple", "") -fun AttrsBuilder.name(value: String) = +fun AttrsScope.name(value: String) = attr("name", value) -fun AttrsBuilder.pattern(value: String) = +fun AttrsScope.pattern(value: String) = attr("pattern", value) -fun AttrsBuilder.placeholder(value: String) = +fun AttrsScope.placeholder(value: String) = attr("placeholder", value) -fun AttrsBuilder.readOnly() = +fun AttrsScope.readOnly() = attr("readonly", "") -fun AttrsBuilder.required(value: Boolean = true) = +fun AttrsScope.required(value: Boolean = true) = attr("required", value.toString()) -fun AttrsBuilder.size(value: Int) = +fun AttrsScope.size(value: Int) = attr("size", value.toString()) -fun AttrsBuilder.src(value: String) = +fun AttrsScope.src(value: String) = attr("src", value) // image only -fun AttrsBuilder.step(value: Number) = +fun AttrsScope.step(value: Number) = attr("step", value.toString()) // numeric types only /* Option attributes */ -fun AttrsBuilder.value(value: String) = +fun AttrsScope.value(value: String) = attr("value", value) -fun AttrsBuilder.disabled() = +fun AttrsScope.disabled() = attr("disabled", "") -fun AttrsBuilder.selected() = +fun AttrsScope.selected() = attr("selected", "") -fun AttrsBuilder.label(value: String) = +fun AttrsScope.label(value: String) = attr("label", value) /* Select attributes */ -fun AttrsBuilder.autoComplete(value: AutoComplete) = +fun AttrsScope.autoComplete(value: AutoComplete) = attr("autocomplete", value.unsafeCast()) -fun AttrsBuilder.autofocus() = +fun AttrsScope.autofocus() = attr("autofocus", "") -fun AttrsBuilder.disabled() = +fun AttrsScope.disabled() = attr("disabled", "") -fun AttrsBuilder.form(formId: String) = +fun AttrsScope.form(formId: String) = attr("form", formId) -fun AttrsBuilder.multiple() = +fun AttrsScope.multiple() = attr("multiple", "") -fun AttrsBuilder.name(value: String) = +fun AttrsScope.name(value: String) = attr("name", value) -fun AttrsBuilder.required() = +fun AttrsScope.required() = attr("required", "") -fun AttrsBuilder.size(numberOfRows: Int) = +fun AttrsScope.size(numberOfRows: Int) = attr("size", numberOfRows.toString()) /* OptGroup attributes */ -fun AttrsBuilder.label(value: String) = +fun AttrsScope.label(value: String) = attr("label", value) -fun AttrsBuilder.disabled() = +fun AttrsScope.disabled() = attr("disabled", "") /* TextArea attributes */ -fun AttrsBuilder.autoComplete(value: AutoComplete) = +fun AttrsScope.autoComplete(value: AutoComplete) = attr("autocomplete", value.unsafeCast()) -fun AttrsBuilder.autoFocus() = +fun AttrsScope.autoFocus() = attr("autofocus", "") -fun AttrsBuilder.cols(value: Int) = +fun AttrsScope.cols(value: Int) = attr("cols", value.toString()) -fun AttrsBuilder.disabled() = +fun AttrsScope.disabled() = attr("disabled", "") -fun AttrsBuilder.form(formId: String) = +fun AttrsScope.form(formId: String) = attr("form", formId) -fun AttrsBuilder.maxLength(value: Int) = +fun AttrsScope.maxLength(value: Int) = attr("maxlength", value.toString()) -fun AttrsBuilder.minLength(value: Int) = +fun AttrsScope.minLength(value: Int) = attr("minlength", value.toString()) -fun AttrsBuilder.name(value: String) = +fun AttrsScope.name(value: String) = attr("name", value) -fun AttrsBuilder.placeholder(value: String) = +fun AttrsScope.placeholder(value: String) = attr("placeholder", value) -fun AttrsBuilder.readOnly() = +fun AttrsScope.readOnly() = attr("readonly", "") -fun AttrsBuilder.required() = +fun AttrsScope.required() = attr("required", "") -fun AttrsBuilder.rows(value: Int) = +fun AttrsScope.rows(value: Int) = attr("rows", value.toString()) -fun AttrsBuilder.wrap(value: TextAreaWrap) = +fun AttrsScope.wrap(value: TextAreaWrap) = attr("wrap", value.str) /* Img attributes */ -fun AttrsBuilder.src(value: String): AttrsBuilder = +fun AttrsScope.src(value: String): AttrsScope = attr("src", value) -fun AttrsBuilder.alt(value: String): AttrsBuilder = +fun AttrsScope.alt(value: String): AttrsScope = attr("alt", value) @@ -313,19 +313,19 @@ internal val setCheckedValue: (HTMLInputElement, Boolean) -> Unit = { e, v -> } /* Img attributes */ -fun AttrsBuilder.forId(value: String): AttrsBuilder = +fun AttrsScope.forId(value: String): AttrsScope = attr("for", value) /* Table attributes */ -fun AttrsBuilder.span(value: Int): AttrsBuilder = +fun AttrsScope.span(value: Int): AttrsScope = attr("span", value.toString()) -fun AttrsBuilder.scope(value: Scope): AttrsBuilder = +fun AttrsScope.scope(value: Scope): AttrsScope = attr("scope", value.str) -fun AttrsBuilder.colspan(value: Int): AttrsBuilder = +fun AttrsScope.colspan(value: Int): AttrsScope = attr("colspan", value.toString()) -fun AttrsBuilder.rowspan(value: Int): AttrsBuilder = +fun AttrsScope.rowspan(value: Int): AttrsScope = attr("rowspan", value.toString()) diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/AttrsBuilder.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/AttrsScope.kt similarity index 55% rename from web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/AttrsBuilder.kt rename to web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/AttrsScope.kt index c4c0d1c157..b6205c8fbc 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/AttrsBuilder.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/AttrsScope.kt @@ -2,35 +2,35 @@ package org.jetbrains.compose.web.attributes import androidx.compose.runtime.DisposableEffectResult import androidx.compose.runtime.DisposableEffectScope -import org.jetbrains.compose.web.css.StyleBuilder -import org.jetbrains.compose.web.css.StyleBuilderImpl +import org.jetbrains.compose.web.css.StyleScope +import org.jetbrains.compose.web.css.StyleScopeBuilder +import org.jetbrains.compose.web.internal.runtime.ComposeWebInternalApi import org.w3c.dom.Element import org.w3c.dom.HTMLElement /** - * [AttrsBuilder] is a class that is used (as a builder context, that is as AttrsBuilder.() -> Unit) + * [AttrsScope] is a class that is used (as a builder context, that is as AttrsBuilder.() -> Unit) * in all DOM-element creating API calls. It's used for adding attributes to the element created, * adding inline style values (via [style]) and attaching events to the element (since AttrsBuilder - * is an [EventsListenerBuilder]) + * is an [EventsListenerScope]) * * In that aspect the most important method is [attr]. Setting the most frequently attributes, like [id], [tabIndex] * are extracted to a separate methods. * */ -open class AttrsBuilder : EventsListenerBuilder() { - internal val attributesMap = mutableMapOf() - internal val styleBuilder = StyleBuilderImpl() - - internal val propertyUpdates = mutableListOf Unit, Any>>() - internal var refEffect: (DisposableEffectScope.(TElement) -> DisposableEffectResult)? = null - - internal var inputControlledValueSet = false - internal var inputDefaultValueSet = false - internal var inputControlledCheckedSet = false - internal var inputDefaultCheckedSet = false - +interface AttrsScope: EventsListenerScope { + @ComposeWebInternalApi + val attributesMap: Map + @ComposeWebInternalApi + val styleScope: StyleScope + + @ComposeWebInternalApi + val propertyUpdates: List Unit, Any>> + @ComposeWebInternalApi + var refEffect: (DisposableEffectScope.(TElement) -> DisposableEffectResult)? + /** - * [style] add inline CSS-style properties to the element via [StyleBuilder] context + * [style] add inline CSS-style properties to the element via [StyleScope] context * * Example: * ``` @@ -39,18 +39,18 @@ open class AttrsBuilder : EventsListenerBuilder() { * }) * ``` */ - fun style(builder: StyleBuilder.() -> Unit) { - styleBuilder.apply(builder) + fun style(builder: StyleScope.() -> Unit) { + styleScope.apply(builder) } - + /** * [classes] adds all values passed as params to the element's classList. * This method acts cumulatively, that is, each call adds values to the classList. * In the ideology of Composable functions and their recomposition one just don't need to remove classes, * since if your classList is, for instance, condition-dependent, you can always just call this method conditionally. */ - fun classes(vararg classes: String) = prop(setClassList, classes) - + fun classes(vararg classes: String)= prop(setClassList, classes) + fun id(value: String) = attr(ID, value) fun hidden() = attr(HIDDEN, true.toString()) fun title(value: String) = attr(TITLE, value) @@ -60,17 +60,80 @@ open class AttrsBuilder : EventsListenerBuilder() { fun lang(value: String) = attr(LANG, value) fun tabIndex(value: Int) = attr(TAB_INDEX, value.toString()) fun spellCheck(value: Boolean) = attr(SPELLCHECK, value.toString()) - + /** * see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode */ fun inputMode(value: String) = attr("inputmode", value) - + /** * see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode */ fun inputMode(value: InputMode) = attr("inputmode", value.str) + + /** + * [ref] can be used to retrieve a reference to a html element. + * The lambda that `ref` takes in is not Composable. It will be called only once when an element added into a composition. + * Likewise, the lambda passed in `onDispose` will be called only once when an element leaves the composition. + * + * Under the hood, `ref` uses [DisposableEffect](https://developer.android.com/jetpack/compose/side-effects#disposableeffect) + */ + fun ref(effect: DisposableEffectScope.(TElement) -> DisposableEffectResult) + + /** + * [attr] adds arbitrary attribute to the Element. + * If it called twice for the same attribute name, attribute value will be resolved to the last call. + * + * @param attr - the name of the attribute + * @param value - the value of the attribute + * + * For boolean attributes cast boolean value to String and pass it as value. + */ + fun attr(attr: String, value: String): AttrsScope + + /** + * [prop] allows setting values of element's properties which can't be set by ussing [attr]. + * [update] is a lambda with two parameters: `element` and `value`. `element` is a reference to a native element. + * Some examples of properties that can set using [prop]: `value`, `checked`, `innerText`. + * + * Unlike [ref], lambda passed to [prop] will be invoked every time when AttrsBuilder being called during recomposition. + * [prop] is not supposed to be used for adding listeners, subscriptions, etc. + * Also see [ref]. + * + * Code Example: + * ``` + * Input(type = InputType.Text, attrs = { + * // This is only an example. One doesn't need to set `value` like this, since [Input] has `value(v: String)` + * prop({ element: HTMLInputElement, value: String -> element.value = value }, "someTextInputValue") + * }) + * ``` + */ + @Suppress("UNCHECKED_CAST") + fun prop(update: (E, V) -> Unit, value: V) + + fun copyFrom(attrsScope: AttrsScope) + + companion object { + const val CLASS = "class" + const val ID = "id" + const val HIDDEN = "hidden" + const val TITLE = "title" + const val DIR = "dir" + const val DRAGGABLE = "draggable" + const val CONTENT_EDITABLE = "contenteditable" + const val LANG = "lang" + const val TAB_INDEX = "tabindex" + const val SPELLCHECK = "spellcheck" + } +} +open class AttrsScopeBuilder : AttrsScope, EventsListenerScope by EventsListenerScopeBuilder() { + override val attributesMap = mutableMapOf() + override val styleScope: StyleScope = StyleScopeBuilder() + + override val propertyUpdates = mutableListOf Unit, Any>>() + override var refEffect: (DisposableEffectScope.(TElement) -> DisposableEffectResult)? = null + /** * [ref] can be used to retrieve a reference to a html element. * The lambda that `ref` takes in is not Composable. It will be called only once when an element added into a composition. @@ -78,7 +141,7 @@ open class AttrsBuilder : EventsListenerBuilder() { * * Under the hood, `ref` uses [DisposableEffect](https://developer.android.com/jetpack/compose/side-effects#disposableeffect) */ - fun ref(effect: DisposableEffectScope.(TElement) -> DisposableEffectResult) { + override fun ref(effect: DisposableEffectScope.(TElement) -> DisposableEffectResult) { this.refEffect = effect } @@ -91,7 +154,7 @@ open class AttrsBuilder : EventsListenerBuilder() { * * For boolean attributes cast boolean value to String and pass it as value. */ - fun attr(attr: String, value: String): AttrsBuilder { + override fun attr(attr: String, value: String): AttrsScope { attributesMap[attr] = value return this } @@ -114,35 +177,22 @@ open class AttrsBuilder : EventsListenerBuilder() { * ``` */ @Suppress("UNCHECKED_CAST") - fun prop(update: (E, V) -> Unit, value: V) { + override fun prop(update: (E, V) -> Unit, value: V) { propertyUpdates.add((update to value) as Pair<(Element, Any) -> Unit, Any>) } internal fun collect(): Map { return attributesMap } - - internal fun copyFrom(attrsBuilder: AttrsBuilder) { - refEffect = attrsBuilder.refEffect - styleBuilder.copyFrom(attrsBuilder.styleBuilder) - - attributesMap.putAll(attrsBuilder.attributesMap) - propertyUpdates.addAll(attrsBuilder.propertyUpdates) - - copyListenersFrom(attrsBuilder) - } - - companion object { - const val CLASS = "class" - const val ID = "id" - const val HIDDEN = "hidden" - const val TITLE = "title" - const val DIR = "dir" - const val DRAGGABLE = "draggable" - const val CONTENT_EDITABLE = "contenteditable" - const val LANG = "lang" - const val TAB_INDEX = "tabindex" - const val SPELLCHECK = "spellcheck" + + override fun copyFrom(attrsScope: AttrsScope) { + refEffect = attrsScope.refEffect + styleScope.copyFrom(attrsScope.styleScope) + + attributesMap.putAll(attrsScope.attributesMap) + propertyUpdates.addAll(attrsScope.propertyUpdates) + + copyListenersFrom(attrsScope) } } diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/EventsListenerBuilder.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/EventsListenerScope.kt similarity index 59% rename from web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/EventsListenerBuilder.kt rename to web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/EventsListenerScope.kt index 5912331b90..65aa23d2b8 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/EventsListenerBuilder.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/EventsListenerScope.kt @@ -5,191 +5,200 @@ import androidx.compose.web.events.SyntheticEvent import androidx.compose.web.events.SyntheticMouseEvent import androidx.compose.web.events.SyntheticWheelEvent import org.jetbrains.compose.web.events.* -import org.w3c.dom.HTMLFormElement +import org.jetbrains.compose.web.internal.runtime.ComposeWebInternalApi import org.w3c.dom.events.EventTarget private typealias SyntheticMouseEventListener = (SyntheticMouseEvent) -> Unit private typealias SyntheticWheelEventListener = (SyntheticWheelEvent) -> Unit private typealias SyntheticDragEventListener = (SyntheticDragEvent) -> Unit +@Deprecated( + message = "Renamed to EventsListenerScopeBuilder", + replaceWith = ReplaceWith("EventsListenerScopeBuilder", "org.jetbrains.compose.web.attributes.EventsListenerScopeBuilder") +) +typealias EventsListenerBuilder = EventsListenerScopeBuilder + /** - * [EventsListenerBuilder] is used most often not directly but via [AttrsBuilder]. + * [EventsListenerScope] is used most often not directly but via [AttrsScope]. * Its purpose is to add events to the element. For all most frequently used events there * exist dedicated method. In case you need to support event that doesn't have such method, * use [addEventListener] */ -open class EventsListenerBuilder { - - protected val listeners = mutableListOf>() - +interface EventsListenerScope { + @ComposeWebInternalApi + val listeners: List> + + @ComposeWebInternalApi + fun registerEventListener(listener: SyntheticEventListener<*>) + /* Mouse Events */ - + fun onContextMenu(listener: SyntheticMouseEventListener) { - listeners.add(MouseEventListener(CONTEXTMENU, listener)) + registerEventListener(MouseEventListener(CONTEXTMENU, listener)) } - + fun onClick(listener: SyntheticMouseEventListener) { - listeners.add(MouseEventListener(CLICK, listener)) + registerEventListener(MouseEventListener(CLICK, listener)) } - + fun onDoubleClick(listener: SyntheticMouseEventListener) { - listeners.add(MouseEventListener(DBLCLICK, listener)) + registerEventListener(MouseEventListener(DBLCLICK, listener)) } - + fun onMouseDown(listener: SyntheticMouseEventListener) { - listeners.add(MouseEventListener(MOUSEDOWN, listener)) + registerEventListener(MouseEventListener(MOUSEDOWN, listener)) } - + fun onMouseUp(listener: SyntheticMouseEventListener) { - listeners.add(MouseEventListener(MOUSEUP, listener)) + registerEventListener(MouseEventListener(MOUSEUP, listener)) } - + fun onMouseEnter(listener: SyntheticMouseEventListener) { - listeners.add(MouseEventListener(MOUSEENTER, listener)) + registerEventListener(MouseEventListener(MOUSEENTER, listener)) } - + fun onMouseLeave(listener: SyntheticMouseEventListener) { - listeners.add(MouseEventListener(MOUSELEAVE, listener)) + registerEventListener(MouseEventListener(MOUSELEAVE, listener)) } - + fun onMouseMove(listener: SyntheticMouseEventListener) { - listeners.add(MouseEventListener(MOUSEMOVE, listener)) + registerEventListener(MouseEventListener(MOUSEMOVE, listener)) } - + fun onMouseOut(listener: SyntheticMouseEventListener) { - listeners.add(MouseEventListener(MOUSEOUT, listener)) + registerEventListener(MouseEventListener(MOUSEOUT, listener)) } - + fun onMouseOver(listener: SyntheticMouseEventListener) { - listeners.add(MouseEventListener(MOUSEOVER, listener)) + registerEventListener(MouseEventListener(MOUSEOVER, listener)) } - + fun onWheel(listener: SyntheticWheelEventListener) { - listeners.add(MouseWheelEventListener(WHEEL, listener)) + registerEventListener(MouseWheelEventListener(WHEEL, listener)) } - + /* Drag Events */ - + fun onDrag(listener: SyntheticDragEventListener) { - listeners.add(DragEventListener(DRAG, listener)) + registerEventListener(DragEventListener(DRAG, listener)) } - + fun onDrop(listener: SyntheticDragEventListener) { - listeners.add(DragEventListener(DROP, listener)) + registerEventListener(DragEventListener(DROP, listener)) } - + fun onDragStart(listener: SyntheticDragEventListener) { - listeners.add(DragEventListener(DRAGSTART, listener)) + registerEventListener(DragEventListener(DRAGSTART, listener)) } - + fun onDragEnd(listener: SyntheticDragEventListener) { - listeners.add(DragEventListener(DRAGEND, listener)) + registerEventListener(DragEventListener(DRAGEND, listener)) } - + fun onDragOver(listener: SyntheticDragEventListener) { - listeners.add(DragEventListener(DRAGOVER, listener)) + registerEventListener(DragEventListener(DRAGOVER, listener)) } - + fun onDragEnter(listener: SyntheticDragEventListener) { - listeners.add(DragEventListener(DRAGENTER, listener)) + registerEventListener(DragEventListener(DRAGENTER, listener)) } - + fun onDragLeave(listener: SyntheticDragEventListener) { - listeners.add(DragEventListener(DRAGLEAVE, listener)) + registerEventListener(DragEventListener(DRAGLEAVE, listener)) } - + /* End of Drag Events */ - + /* Clipboard Events */ - + fun onCopy(listener: (SyntheticClipboardEvent) -> Unit) { - listeners.add(ClipboardEventListener(COPY, listener)) + registerEventListener(ClipboardEventListener(COPY, listener)) } - + fun onCut(listener: (SyntheticClipboardEvent) -> Unit) { - listeners.add(ClipboardEventListener(CUT, listener)) + registerEventListener(ClipboardEventListener(CUT, listener)) } - + fun onPaste(listener: (SyntheticClipboardEvent) -> Unit) { - listeners.add(ClipboardEventListener(PASTE, listener)) + registerEventListener(ClipboardEventListener(PASTE, listener)) } - + /* End of Clipboard Events */ - + /* Keyboard Events */ - + fun onKeyDown(listener: (SyntheticKeyboardEvent) -> Unit) { - listeners.add(KeyboardEventListener(KEYDOWN, listener)) + registerEventListener(KeyboardEventListener(KEYDOWN, listener)) } - + fun onKeyUp(listener: (SyntheticKeyboardEvent) -> Unit) { - listeners.add(KeyboardEventListener(KEYUP, listener)) + registerEventListener(KeyboardEventListener(KEYUP, listener)) } - + /* End of Keyboard Events */ - + /* Focus Events */ - + fun onFocus(listener: (SyntheticFocusEvent) -> Unit) { - listeners.add(FocusEventListener(FOCUS, listener)) + registerEventListener(FocusEventListener(FOCUS, listener)) } - + fun onBlur(listener: (SyntheticFocusEvent) -> Unit) { - listeners.add(FocusEventListener(BLUR, listener)) + registerEventListener(FocusEventListener(BLUR, listener)) } - + fun onFocusIn(listener: (SyntheticFocusEvent) -> Unit) { - listeners.add(FocusEventListener(FOCUSIN, listener)) + registerEventListener(FocusEventListener(FOCUSIN, listener)) } - + fun onFocusOut(listener: (SyntheticFocusEvent) -> Unit) { - listeners.add(FocusEventListener(FOCUSOUT, listener)) + registerEventListener(FocusEventListener(FOCUSOUT, listener)) } - + /* End of Focus Events */ - + /* Touch Events */ - + fun onTouchCancel(listener: (SyntheticTouchEvent) -> Unit) { - listeners.add(TouchEventListener(TOUCHCANCEL, listener)) + registerEventListener(TouchEventListener(TOUCHCANCEL, listener)) } - + fun onTouchMove(listener: (SyntheticTouchEvent) -> Unit) { - listeners.add(TouchEventListener(TOUCHMOVE, listener)) + registerEventListener(TouchEventListener(TOUCHMOVE, listener)) } - + fun onTouchEnd(listener: (SyntheticTouchEvent) -> Unit) { - listeners.add(TouchEventListener(TOUCHEND, listener)) + registerEventListener(TouchEventListener(TOUCHEND, listener)) } - + fun onTouchStart(listener: (SyntheticTouchEvent) -> Unit) { - listeners.add(TouchEventListener(TOUCHSTART, listener)) + registerEventListener(TouchEventListener(TOUCHSTART, listener)) } - + /* End of Touch Events */ - + /* Animation Events */ - + fun onAnimationEnd(listener: (SyntheticAnimationEvent) -> Unit) { - listeners.add(AnimationEventListener(ANIMATIONEND, listener)) + registerEventListener(AnimationEventListener(ANIMATIONEND, listener)) } - + fun onAnimationIteration(listener: (SyntheticAnimationEvent) -> Unit) { - listeners.add(AnimationEventListener(ANIMATIONITERATION, listener)) + registerEventListener(AnimationEventListener(ANIMATIONITERATION, listener)) } - + fun onAnimationStart(listener: (SyntheticAnimationEvent) -> Unit) { - listeners.add(AnimationEventListener(ANIMATIONSTART, listener)) + registerEventListener(AnimationEventListener(ANIMATIONSTART, listener)) } - + /* End of Animation Events */ - + fun onScroll(listener: (SyntheticEvent) -> Unit) { - listeners.add(SyntheticEventListener(SCROLL, listener)) + registerEventListener(SyntheticEventListener(SCROLL, listener)) } - - internal fun collectListeners(): List> = listeners - + + fun collectListeners(): List> = listeners + /** * [addEventListener] used for adding arbitrary events to the element. It resembles the standard DOM addEventListener method * @param eventName - the name of the event @@ -200,33 +209,32 @@ open class EventsListenerBuilder { eventName: String, listener: (T) -> Unit ) { - listeners.add(SyntheticEventListener(eventName, listener)) + registerEventListener(SyntheticEventListener(eventName, listener)) } - + fun addEventListener( eventName: String, listener: (SyntheticEvent) -> Unit ) { - listeners.add(SyntheticEventListener(eventName, listener)) + registerEventListener(SyntheticEventListener(eventName, listener)) } - - internal fun copyListenersFrom(from: EventsListenerBuilder) { - listeners.addAll(from.listeners) - } - + + @ComposeWebInternalApi + fun copyListenersFrom(from: EventsListenerScope) + companion object { const val COPY = "copy" const val CUT = "cut" const val PASTE = "paste" const val CONTEXTMENU = "contextmenu" - + const val CLICK = "click" const val DBLCLICK = "dblclick" const val FOCUS = "focus" const val BLUR = "blur" const val FOCUSIN = "focusin" const val FOCUSOUT = "focusout" - + const val KEYDOWN = "keydown" const val KEYUP = "keyup" const val MOUSEDOWN = "mousedown" @@ -239,22 +247,22 @@ open class EventsListenerBuilder { const val WHEEL = "wheel" const val SCROLL = "scroll" const val SELECT = "select" - + const val TOUCHCANCEL = "touchcancel" const val TOUCHEND = "touchend" const val TOUCHMOVE = "touchmove" const val TOUCHSTART = "touchstart" - + const val ANIMATIONCANCEL = "animationcancel" // firefox and safari only const val ANIMATIONEND = "animationend" const val ANIMATIONITERATION = "animationiteration" const val ANIMATIONSTART = "animationstart" - + const val BEFOREINPUT = "beforeinput" const val INPUT = "input" const val CHANGE = "change" const val INVALID = "invalid" - + const val DRAG = "drag" const val DROP = "drop" const val DRAGSTART = "dragstart" @@ -262,8 +270,20 @@ open class EventsListenerBuilder { const val DRAGOVER = "dragover" const val DRAGENTER = "dragenter" const val DRAGLEAVE = "dragleave" - + const val SUBMIT = "submit" const val RESET = "reset" } } + +open class EventsListenerScopeBuilder: EventsListenerScope { + override val listeners: MutableList> = mutableListOf() + + override fun registerEventListener(listener: SyntheticEventListener<*>) { + listeners.add(listener) + } + + override fun copyListenersFrom(from: EventsListenerScope) { + listeners.addAll(from.listeners) + } +} diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/SyntheticEventListener.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/SyntheticEventListener.kt index 1e40f8f974..bb7d38e6a0 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/SyntheticEventListener.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/SyntheticEventListener.kt @@ -5,9 +5,9 @@ import androidx.compose.web.events.SyntheticDragEvent import androidx.compose.web.events.SyntheticEvent import androidx.compose.web.events.SyntheticMouseEvent import androidx.compose.web.events.SyntheticWheelEvent -import org.jetbrains.compose.web.attributes.EventsListenerBuilder.Companion.CHANGE -import org.jetbrains.compose.web.attributes.EventsListenerBuilder.Companion.INPUT -import org.jetbrains.compose.web.attributes.EventsListenerBuilder.Companion.SELECT +import org.jetbrains.compose.web.attributes.EventsListenerScope.Companion.CHANGE +import org.jetbrains.compose.web.attributes.EventsListenerScope.Companion.INPUT +import org.jetbrains.compose.web.attributes.EventsListenerScope.Companion.SELECT import org.jetbrains.compose.web.events.* import org.jetbrains.compose.web.internal.runtime.ComposeWebInternalApi import org.jetbrains.compose.web.internal.runtime.NamedEventListener diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/InputAttrsBuilder.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/InputAttrsScope.kt similarity index 66% rename from web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/InputAttrsBuilder.kt rename to web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/InputAttrsScope.kt index bd43fe268f..5fc18e8a70 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/InputAttrsBuilder.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/InputAttrsScope.kt @@ -7,13 +7,22 @@ package org.jetbrains.compose.web.attributes.builders import androidx.compose.web.events.SyntheticEvent import org.jetbrains.compose.web.attributes.* +import org.jetbrains.compose.web.attributes.EventsListenerScope.Companion.BEFOREINPUT +import org.jetbrains.compose.web.attributes.EventsListenerScope.Companion.INPUT +import org.jetbrains.compose.web.attributes.EventsListenerScope.Companion.INVALID import org.jetbrains.compose.web.events.SyntheticChangeEvent import org.jetbrains.compose.web.events.SyntheticInputEvent import org.jetbrains.compose.web.events.SyntheticSelectEvent import org.w3c.dom.HTMLInputElement +@Deprecated( + message = "Renamed to InputAttrsScope", + replaceWith = ReplaceWith("InputAttrsScope", "org.jetbrains.compose.web.attributes.builders.InputAttrsScope") +) +typealias InputAttrsBuilder = InputAttrsScope + /** - * An extension of [AttrsBuilder]. + * An extension of [AttrsScope]. * This class provides a set of methods specific for [Input] element: * * [value] - sets the current input's value. @@ -28,11 +37,11 @@ import org.w3c.dom.HTMLInputElement * [onBeforeInput] - add `beforeinput` event listener * [onSelect] - add `select` event listener */ -class InputAttrsBuilder( +class InputAttrsScope( val inputType: InputType -) : AttrsBuilder() { +) : AttrsScopeBuilder() { - fun value(value: String): InputAttrsBuilder { + fun value(value: String): InputAttrsScope { when (inputType) { InputType.Checkbox, InputType.Radio, @@ -43,27 +52,27 @@ class InputAttrsBuilder( return this } - fun value(value: Number): InputAttrsBuilder { + fun value(value: Number): InputAttrsScope { value(value.toString()) return this } - fun checked(checked: Boolean): InputAttrsBuilder { + fun checked(checked: Boolean): InputAttrsScope { prop(setCheckedValue, checked) return this } - fun defaultChecked(): InputAttrsBuilder { + fun defaultChecked(): InputAttrsScope { attr("checked", "") return this } - fun defaultValue(value: String): InputAttrsBuilder { + fun defaultValue(value: String): InputAttrsScope { attr("value", value) return this } - fun defaultValue(value: Number): InputAttrsBuilder { + fun defaultValue(value: Number): InputAttrsScope { attr("value", value.toString()) return this } @@ -77,25 +86,25 @@ class InputAttrsBuilder( fun onInput( listener: (SyntheticInputEvent) -> Unit ) { - listeners.add(InputEventListener(eventName = INPUT, inputType, listener)) + registerEventListener(InputEventListener(eventName = INPUT, inputType, listener)) } fun onChange( listener: (SyntheticChangeEvent) -> Unit ) { - listeners.add(ChangeEventListener(inputType, listener)) + registerEventListener(ChangeEventListener(inputType, listener)) } fun onBeforeInput( listener: (SyntheticInputEvent) -> Unit ) { - listeners.add(InputEventListener(eventName = BEFOREINPUT, inputType, listener)) + registerEventListener(InputEventListener(eventName = BEFOREINPUT, inputType, listener)) } fun onSelect( listener: (SyntheticSelectEvent) -> Unit ) { - listeners.add(SelectEventListener(listener)) + registerEventListener(SelectEventListener(listener)) } } @@ -105,5 +114,3 @@ internal external interface JsWeakMap { fun has(key: Any): Boolean fun set(key: Any, value: Any): JsWeakMap } - - diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/SelectAttrsBuilder.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/SelectAttrsScope.kt similarity index 69% rename from web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/SelectAttrsBuilder.kt rename to web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/SelectAttrsScope.kt index 3a9e39bad0..edce1c5b60 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/SelectAttrsBuilder.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/SelectAttrsScope.kt @@ -5,27 +5,33 @@ package androidx.compose.web.attributes -import org.jetbrains.compose.web.attributes.AttrsBuilder -import org.jetbrains.compose.web.attributes.EventsListenerBuilder.Companion.CHANGE -import org.jetbrains.compose.web.attributes.EventsListenerBuilder.Companion.INPUT +import org.jetbrains.compose.web.attributes.AttrsScopeBuilder +import org.jetbrains.compose.web.attributes.EventsListenerScope.Companion.CHANGE +import org.jetbrains.compose.web.attributes.EventsListenerScope.Companion.INPUT import org.jetbrains.compose.web.attributes.SyntheticEventListener import org.jetbrains.compose.web.events.SyntheticChangeEvent import org.jetbrains.compose.web.events.SyntheticInputEvent import org.w3c.dom.HTMLSelectElement import org.w3c.dom.events.Event -class SelectAttrsBuilder : AttrsBuilder() { +@Deprecated( + message = "Renamed to SelectAttrsScope", + replaceWith = ReplaceWith("SelectAttrsScope", "org.jetbrains.compose.web.attributes.builders.SelectAttrsScope") +) +typealias SelectAttrsBuilder = SelectAttrsScope + +class SelectAttrsScope : AttrsScopeBuilder() { fun onInput( listener: (SyntheticInputEvent) -> Unit ) { - listeners.add(SelectInputEventListener(INPUT, listener)) + registerEventListener(SelectInputEventListener(INPUT, listener)) } fun onChange( listener: (SyntheticChangeEvent) -> Unit ) { - listeners.add(SelectChangeEventListener(listener)) + registerEventListener(SelectChangeEventListener(listener)) } } diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/TextAreaAttrsBuilder.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/TextAreaAttrsBuilder.kt deleted file mode 100644 index 7ab34636ab..0000000000 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/TextAreaAttrsBuilder.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2020-2021 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -package org.jetbrains.compose.web.attributes.builders - -import org.jetbrains.compose.web.attributes.* -import org.jetbrains.compose.web.events.SyntheticChangeEvent -import org.jetbrains.compose.web.events.SyntheticSelectEvent -import org.jetbrains.compose.web.events.SyntheticInputEvent -import org.w3c.dom.HTMLTextAreaElement - -class TextAreaAttrsBuilder : AttrsBuilder() { - - fun value(value: String): AttrsBuilder { - prop(setInputValue, value) - return this - } - - fun defaultValue(value: String): AttrsBuilder { - prop(setTextAreaDefaultValue, value) - return this - } - - fun onInput( - listener: (SyntheticInputEvent) -> Unit - ) { - listeners.add(InputEventListener(INPUT, InputType.Text, listener)) - } - - fun onChange( - listener: (SyntheticChangeEvent) -> Unit - ) { - listeners.add(ChangeEventListener(InputType.Text, listener)) - } - - fun onBeforeInput( - listener: (SyntheticInputEvent) -> Unit - ) { - listeners.add(InputEventListener(BEFOREINPUT, InputType.Text, listener)) - } - - fun onSelect( - listener: (SyntheticSelectEvent) -> Unit - ) { - listeners.add(SelectEventListener(listener)) - } -} diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/TextAreaAttrsScope.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/TextAreaAttrsScope.kt new file mode 100644 index 0000000000..b6bbad3bb4 --- /dev/null +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/attributes/builders/TextAreaAttrsScope.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2020-2021 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. + */ + +package org.jetbrains.compose.web.attributes.builders + +import org.jetbrains.compose.web.attributes.AttrsScope +import org.jetbrains.compose.web.attributes.AttrsScopeBuilder +import org.jetbrains.compose.web.attributes.ChangeEventListener +import org.jetbrains.compose.web.attributes.EventsListenerScope.Companion.BEFOREINPUT +import org.jetbrains.compose.web.attributes.EventsListenerScope.Companion.INPUT +import org.jetbrains.compose.web.attributes.InputEventListener +import org.jetbrains.compose.web.attributes.InputType +import org.jetbrains.compose.web.attributes.SelectEventListener +import org.jetbrains.compose.web.attributes.setInputValue +import org.jetbrains.compose.web.attributes.setTextAreaDefaultValue +import org.jetbrains.compose.web.events.SyntheticChangeEvent +import org.jetbrains.compose.web.events.SyntheticInputEvent +import org.jetbrains.compose.web.events.SyntheticSelectEvent +import org.w3c.dom.HTMLTextAreaElement + +@Deprecated( + message = "Renamed to TextAreaAttrsScope", + replaceWith = ReplaceWith("TextAreaAttrsScope", "org.jetbrains.compose.web.attributes.builders.TextAreaAttrsScope") +) +typealias TextAreaAttrsBuilder = TextAreaAttrsScope + +class TextAreaAttrsScope : AttrsScopeBuilder() { + + fun value(value: String): AttrsScope { + prop(setInputValue, value) + return this + } + + fun defaultValue(value: String): AttrsScope { + prop(setTextAreaDefaultValue, value) + return this + } + + fun onInput( + listener: (SyntheticInputEvent) -> Unit + ) { + registerEventListener(InputEventListener(INPUT, InputType.Text, listener)) + } + + fun onChange( + listener: (SyntheticChangeEvent) -> Unit + ) { + registerEventListener(ChangeEventListener(InputType.Text, listener)) + } + + fun onBeforeInput( + listener: (SyntheticInputEvent) -> Unit + ) { + registerEventListener(InputEventListener(BEFOREINPUT, InputType.Text, listener)) + } + + fun onSelect( + listener: (SyntheticSelectEvent) -> Unit + ) { + registerEventListener(SelectEventListener(listener)) + } +} diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/CSSRules.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/CSSRules.kt index 0e3d2717a1..9de2332de3 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/CSSRules.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/CSSRules.kt @@ -4,7 +4,7 @@ import org.jetbrains.compose.web.css.selectors.CSSSelector interface CSSStyleRuleBuilder : StyleBuilder -open class CSSRuleBuilderImpl : CSSStyleRuleBuilder, StyleBuilderImpl() +open class CSSRuleBuilderImpl : CSSStyleRuleBuilder, StyleScopeBuilder() @Suppress("EqualsOrHashCode") interface CSSRuleDeclaration { diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/StyleBuilder.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/StyleScope.kt similarity index 90% rename from web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/StyleBuilder.kt rename to web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/StyleScope.kt index f8b9ebaae0..8d6a4d1edc 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/StyleBuilder.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/StyleScope.kt @@ -11,7 +11,7 @@ import org.jetbrains.compose.web.internal.runtime.ComposeWebInternalApi import kotlin.properties.ReadOnlyProperty /** - * StyleBuilder serves for two main purposes. Passed as a builder context (in [AttrsBuilder]), it + * StyleBuilder serves for two main purposes. Passed as a builder context (in [AttrsScope]), it * makes it possible to: * 1. Add inlined css properties to the element (@see [property]) * 2. Set values to CSS variables (@see [variable]) @@ -125,13 +125,26 @@ fun variable() = } interface StyleHolder { + @ComposeWebInternalApi val properties: StylePropertyList + @ComposeWebInternalApi val variables: StylePropertyList } +interface StyleScope : StyleBuilder, StyleHolder { + @ComposeWebInternalApi + fun copyFrom(sb: StyleScope) +} + +@Deprecated( + message = "Renamed to StyleScopeBuilder", + replaceWith = ReplaceWith("StyleScopeBuilder", "org.jetbrains.compose.web.css.StyleScopeBuilder") +) +typealias StyleBuilderImpl = StyleScopeBuilder + @OptIn(ComposeWebInternalApi::class) @Suppress("EqualsOrHashCode") -open class StyleBuilderImpl : StyleBuilder, StyleHolder { +open class StyleScopeBuilder : StyleScope { override val properties: MutableStylePropertyList = mutableListOf() override val variables: MutableStylePropertyList = mutableListOf() @@ -147,11 +160,11 @@ open class StyleBuilderImpl : StyleBuilder, StyleHolder { override fun equals(other: Any?): Boolean { return if (other is StyleHolder) { properties.nativeEquals(other.properties) && - variables.nativeEquals(other.variables) + variables.nativeEquals(other.variables) } else false } - internal fun copyFrom(sb: StyleBuilderImpl) { + override fun copyFrom(sb: StyleScope) { properties.addAll(sb.properties) variables.addAll(sb.variables) } @@ -174,6 +187,6 @@ internal fun StylePropertyList.nativeEquals(properties: StylePropertyList): Bool return all { prop -> val otherProp = properties[index++] prop.name == otherProp.name && - prop.value.toString() == otherProp.value.toString() + prop.value.toString() == otherProp.value.toString() } } diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/Base.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/Base.kt index 200613ce68..5b708c32cb 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/Base.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/Base.kt @@ -1,8 +1,9 @@ package org.jetbrains.compose.web.dom import androidx.compose.runtime.* -import org.jetbrains.compose.web.attributes.AttrsBuilder +import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.ExperimentalComposeWebApi +import org.jetbrains.compose.web.attributes.AttrsScopeBuilder import org.jetbrains.compose.web.css.StyleHolder import org.jetbrains.compose.web.internal.runtime.ComposeWebInternalApi import org.jetbrains.compose.web.internal.runtime.DomNodeWrapper @@ -95,7 +96,7 @@ private class DomElementWrapper(override val node: Element): DomNodeWrapper(node @Composable fun TagElement( elementBuilder: ElementBuilder, - applyAttrs: (AttrsBuilder.() -> Unit)?, + applyAttrs: (AttrsScope.() -> Unit)?, content: (@Composable ElementScope.() -> Unit)? ) { val scope = remember { ElementScopeImpl() } @@ -108,16 +109,16 @@ fun TagElement( DomElementWrapper(node) }, attrsSkippableUpdate = { - val attrsBuilder = AttrsBuilder() - applyAttrs?.invoke(attrsBuilder) + val attrsScope = AttrsScopeBuilder() + applyAttrs?.invoke(attrsScope) - refEffect = attrsBuilder.refEffect + refEffect = attrsScope.refEffect update { - set(attrsBuilder.collect(), DomElementWrapper::updateAttrs) - set(attrsBuilder.collectListeners(), DomElementWrapper::updateEventListeners) - set(attrsBuilder.propertyUpdates, DomElementWrapper::updateProperties) - set(attrsBuilder.styleBuilder, DomElementWrapper::updateStyleDeclarations) + set(attrsScope.collect(), DomElementWrapper::updateAttrs) + set(attrsScope.collectListeners(), DomElementWrapper::updateEventListeners) + set(attrsScope.propertyUpdates, DomElementWrapper::updateProperties) + set(attrsScope.styleScope, DomElementWrapper::updateStyleDeclarations) } }, elementScope = scope, @@ -135,7 +136,7 @@ fun TagElement( @ExperimentalComposeWebApi fun TagElement( tagName: String, - applyAttrs: AttrsBuilder.() -> Unit, + applyAttrs: AttrsScope.() -> Unit, content: (@Composable ElementScope.() -> Unit)? ) = TagElement( elementBuilder = ElementBuilder.createBuilder(tagName), diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/Elements.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/Elements.kt index 6ebec334b4..a48b9712c4 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/Elements.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/Elements.kt @@ -1,16 +1,16 @@ package org.jetbrains.compose.web.dom import androidx.compose.runtime.* -import androidx.compose.web.attributes.SelectAttrsBuilder +import androidx.compose.web.attributes.SelectAttrsScope import kotlinx.browser.document import org.jetbrains.compose.web.attributes.* import org.jetbrains.compose.web.attributes.builders.* import org.jetbrains.compose.web.css.CSSRuleDeclarationList import org.jetbrains.compose.web.css.StyleSheetBuilder import org.jetbrains.compose.web.css.StyleSheetBuilderImpl +import org.jetbrains.compose.web.internal.runtime.ComposeWebInternalApi import org.jetbrains.compose.web.internal.runtime.DomApplier import org.jetbrains.compose.web.internal.runtime.DomNodeWrapper -import org.jetbrains.compose.web.internal.runtime.ComposeWebInternalApi import org.w3c.dom.Element import org.w3c.dom.HTMLAnchorElement import org.w3c.dom.HTMLAreaElement @@ -23,8 +23,8 @@ import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLEmbedElement import org.w3c.dom.HTMLFieldSetElement import org.w3c.dom.HTMLFormElement -import org.w3c.dom.HTMLHeadingElement import org.w3c.dom.HTMLHRElement +import org.w3c.dom.HTMLHeadingElement import org.w3c.dom.HTMLIFrameElement import org.w3c.dom.HTMLImageElement import org.w3c.dom.HTMLInputElement @@ -60,7 +60,12 @@ import org.w3c.dom.HTMLVideoElement import org.w3c.dom.Text import org.w3c.dom.css.CSSStyleSheet -typealias AttrBuilderContext = AttrsBuilder.() -> Unit +@Deprecated( + message = "Renamed to AttrsBuilder", + replaceWith = ReplaceWith("AttrsBuilder", "org.jetbrains.compose.web.dom.AttrsBuilder") +) +typealias AttrBuilderContext = AttrsBuilder +typealias AttrsBuilder = AttrsScope.() -> Unit typealias ContentBuilder = @Composable ElementScope.() -> Unit private open class ElementBuilderImplementation(private val tagName: String) : ElementBuilder { @@ -163,7 +168,7 @@ fun interface ElementBuilder { @Composable fun Address( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -175,7 +180,7 @@ fun Address( @Composable fun Article( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -187,7 +192,7 @@ fun Article( @Composable fun Aside( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -199,7 +204,7 @@ fun Aside( @Composable fun Header( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -211,7 +216,7 @@ fun Header( @Composable fun Area( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -223,7 +228,7 @@ fun Area( @Composable fun Audio( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -235,7 +240,7 @@ fun Audio( @Composable fun HTMLMap( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -247,7 +252,7 @@ fun HTMLMap( @Composable fun Track( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -259,7 +264,7 @@ fun Track( @Composable fun Video( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -271,7 +276,7 @@ fun Video( @Composable fun Datalist( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -283,7 +288,7 @@ fun Datalist( @Composable fun Fieldset( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -295,7 +300,7 @@ fun Fieldset( @Composable fun Legend( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -307,7 +312,7 @@ fun Legend( @Composable fun Meter( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -319,7 +324,7 @@ fun Meter( @Composable fun Output( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -331,7 +336,7 @@ fun Output( @Composable fun Progress( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -343,7 +348,7 @@ fun Progress( @Composable fun Embed( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -355,7 +360,7 @@ fun Embed( @Composable fun Iframe( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -367,7 +372,7 @@ fun Iframe( @Composable fun Object( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -379,7 +384,7 @@ fun Object( @Composable fun Param( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -391,7 +396,7 @@ fun Param( @Composable fun Picture( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -403,7 +408,7 @@ fun Picture( @Composable fun Source( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -426,7 +431,7 @@ fun Text(value: String) { @Composable fun Div( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -439,7 +444,7 @@ fun Div( @Composable fun A( href: String? = null, - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -458,101 +463,101 @@ fun A( @Composable fun Button( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = Button, applyAttrs = attrs, content = content) @Composable fun H1( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = H1, applyAttrs = attrs, content = content) @Composable fun H2( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = H2, applyAttrs = attrs, content = content) @Composable fun H3( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = H3, applyAttrs = attrs, content = content) @Composable fun H4( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = H4, applyAttrs = attrs, content = content) @Composable fun H5( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = H5, applyAttrs = attrs, content = content) @Composable fun H6( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = H6, applyAttrs = attrs, content = content) @Composable fun P( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = P, applyAttrs = attrs, content = content) @Composable fun Em( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = Em, applyAttrs = attrs, content = content) @Composable fun I( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = I, applyAttrs = attrs, content = content) @Composable fun B( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = B, applyAttrs = attrs, content = content) @Composable fun Small( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = Small, applyAttrs = attrs, content = content) @Composable fun Span( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = Span, applyAttrs = attrs, content = content) @Composable -fun Br(attrs: AttrBuilderContext? = null) = +fun Br(attrs: AttrsBuilder? = null) = TagElement(elementBuilder = Br, applyAttrs = attrs, content = null) @Composable fun Ul( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = Ul, applyAttrs = attrs, content = content) @Composable fun Ol( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = Ol, applyAttrs = attrs, content = content) @Composable fun Li( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement(elementBuilder = Li, applyAttrs = attrs, content = content) @@ -560,7 +565,7 @@ fun Li( fun Img( src: String, alt: String = "", - attrs: AttrBuilderContext? = null + attrs: AttrsBuilder? = null ) = TagElement( elementBuilder = Img, applyAttrs = { @@ -575,7 +580,7 @@ fun Img( @Composable fun Form( action: String? = null, - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement( elementBuilder = Form, @@ -590,7 +595,7 @@ fun Form( @Composable fun Select( - attrs: (SelectAttrsBuilder.() -> Unit)? = null, + attrs: (SelectAttrsScope.() -> Unit)? = null, multiple: Boolean = false, content: ContentBuilder? = null ) = TagElement( @@ -598,7 +603,7 @@ fun Select( applyAttrs = { if (multiple) multiple() if (attrs != null) { - val selectAttrsBuilder = with(SelectAttrsBuilder()) { + val selectAttrsBuilder = with(SelectAttrsScope()) { attrs() this } @@ -611,7 +616,7 @@ fun Select( @Composable fun Option( value: String, - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement( elementBuilder = Option, @@ -627,7 +632,7 @@ fun Option( @Composable fun OptGroup( label: String, - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement( elementBuilder = OptGroup, @@ -642,7 +647,7 @@ fun OptGroup( @Composable fun Section( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement( elementBuilder = Section, @@ -671,7 +676,7 @@ fun Section( @Composable fun TextArea( value: String? = null, - attrs: (TextAreaAttrsBuilder.() -> Unit)? = null + attrs: (TextAreaAttrsScope.() -> Unit)? = null ) { // if firstProvidedValueWasNotNull then TextArea behaves as controlled input val firstProvidedValueWasNotNull = remember { value != null } @@ -682,7 +687,7 @@ fun TextArea( TagElement( elementBuilder = TextArea, applyAttrs = { - val textAreaAttrsBuilder = TextAreaAttrsBuilder() + val textAreaAttrsBuilder = TextAreaAttrsScope() textAreaAttrsBuilder.onInput { // controlled state needs to be restored after every input keyForRestoringControlledState.value = keyForRestoringControlledState.value + 1 @@ -708,7 +713,7 @@ private val textAreaRestoreControlledStateEffect: DomEffectScope.(HTMLTextAreaEl @Composable fun Nav( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) = TagElement( elementBuilder = Nav, @@ -718,7 +723,7 @@ fun Nav( @Composable fun Pre( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -730,7 +735,7 @@ fun Pre( @Composable fun Code( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -742,7 +747,7 @@ fun Code( @Composable fun Main( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -754,7 +759,7 @@ fun Main( @Composable fun Footer( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -766,7 +771,7 @@ fun Footer( @Composable fun Hr( - attrs: AttrBuilderContext? = null + attrs: AttrsBuilder? = null ) { TagElement( elementBuilder = Hr, @@ -778,7 +783,7 @@ fun Hr( @Composable fun Label( forId: String? = null, - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -797,7 +802,7 @@ fun Label( @Composable fun Table( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -809,7 +814,7 @@ fun Table( @Composable fun Caption( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -821,7 +826,7 @@ fun Caption( @Composable fun Col( - attrs: AttrBuilderContext? = null + attrs: AttrsBuilder? = null ) { TagElement( elementBuilder = Col, @@ -832,7 +837,7 @@ fun Col( @Composable fun Colgroup( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -844,7 +849,7 @@ fun Colgroup( @Composable fun Tr( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -856,7 +861,7 @@ fun Tr( @Composable fun Thead( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -868,7 +873,7 @@ fun Thead( @Composable fun Th( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -880,7 +885,7 @@ fun Th( @Composable fun Td( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -892,7 +897,7 @@ fun Td( @Composable fun Tbody( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -904,7 +909,7 @@ fun Tbody( @Composable fun Tfoot( - attrs: AttrBuilderContext? = null, + attrs: AttrsBuilder? = null, content: ContentBuilder? = null ) { TagElement( @@ -922,7 +927,7 @@ fun Tfoot( */ @Composable fun Style( - applyAttrs: (AttrsBuilder.() -> Unit)? = null, + applyAttrs: (AttrsScope.() -> Unit)? = null, cssRules: CSSRuleDeclarationList ) { TagElement( @@ -951,7 +956,7 @@ fun Style( */ @Composable inline fun Style( - noinline applyAttrs: (AttrsBuilder.() -> Unit)? = null, + noinline applyAttrs: (AttrsScope.() -> Unit)? = null, rulesBuild: StyleSheetBuilder.() -> Unit ) { val builder = StyleSheetBuilderImpl() @@ -994,7 +999,7 @@ inline fun Style( @Composable fun Input( type: InputType, - attrs: InputAttrsBuilder.() -> Unit + attrs: InputAttrsScope.() -> Unit ) { // changes to this key trigger [inputRestoreControlledStateEffect] val keyForRestoringControlledState: MutableState = remember { mutableStateOf(0) } @@ -1002,7 +1007,7 @@ fun Input( TagElement( elementBuilder = Input, applyAttrs = { - val inputAttrsBuilder = InputAttrsBuilder(type) + val inputAttrsBuilder = InputAttrsScope(type) inputAttrsBuilder.type(type) inputAttrsBuilder.onInput { // controlled state needs to be restored after every input diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/InputElements.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/InputElements.kt index 5e9a451602..26152fa6e2 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/InputElements.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/InputElements.kt @@ -2,12 +2,12 @@ package org.jetbrains.compose.web.dom import androidx.compose.runtime.Composable import androidx.compose.runtime.NonRestartableComposable -import org.jetbrains.compose.web.attributes.builders.InputAttrsBuilder +import org.jetbrains.compose.web.attributes.builders.InputAttrsScope import org.jetbrains.compose.web.attributes.* -private fun InputAttrsBuilder.applyAttrsWithStringValue( +private fun InputAttrsScope.applyAttrsWithStringValue( value: String, - attrs: InputAttrsBuilder.() -> Unit + attrs: InputAttrsScope.() -> Unit ) { value(value) attrs() @@ -22,7 +22,7 @@ private fun InputAttrsBuilder.applyAttrsWithStringValue( */ @Composable @NonRestartableComposable -fun CheckboxInput(checked: Boolean = false, attrs: InputAttrsBuilder.() -> Unit = {}) { +fun CheckboxInput(checked: Boolean = false, attrs: InputAttrsScope.() -> Unit = {}) { Input( type = InputType.Checkbox, attrs = { @@ -41,7 +41,7 @@ fun CheckboxInput(checked: Boolean = false, attrs: InputAttrsBuilder.() */ @Composable @NonRestartableComposable -fun DateInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = {}) { +fun DateInput(value: String = "", attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.Date, attrs = { applyAttrsWithStringValue(value, attrs) }) } @@ -54,7 +54,7 @@ fun DateInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = */ @Composable @NonRestartableComposable -fun DateTimeLocalInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = {}) { +fun DateTimeLocalInput(value: String = "", attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.DateTimeLocal, attrs = { applyAttrsWithStringValue(value, attrs) }) } @@ -67,7 +67,7 @@ fun DateTimeLocalInput(value: String = "", attrs: InputAttrsBuilder.() - */ @Composable @NonRestartableComposable -fun EmailInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = {}) { +fun EmailInput(value: String = "", attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.Email, attrs = { applyAttrsWithStringValue(value, attrs) }) } @@ -80,7 +80,7 @@ fun EmailInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = */ @Composable @NonRestartableComposable -fun FileInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = {}) { +fun FileInput(value: String = "", attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.File, attrs = { applyAttrsWithStringValue(value, attrs) }) } @@ -93,7 +93,7 @@ fun FileInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = */ @Composable @NonRestartableComposable -fun HiddenInput(attrs: InputAttrsBuilder.() -> Unit = {}) { +fun HiddenInput(attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.Hidden, attrs = attrs) } @@ -106,7 +106,7 @@ fun HiddenInput(attrs: InputAttrsBuilder.() -> Unit = {}) { */ @Composable @NonRestartableComposable -fun MonthInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = {}) { +fun MonthInput(value: String = "", attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.Month, attrs = { applyAttrsWithStringValue(value, attrs) }) } @@ -123,7 +123,7 @@ fun NumberInput( value: Number? = null, min: Number? = null, max: Number? = null, - attrs: InputAttrsBuilder.() -> Unit = {} + attrs: InputAttrsScope.() -> Unit = {} ) { Input( type = InputType.Number, @@ -145,7 +145,7 @@ fun NumberInput( */ @Composable @NonRestartableComposable -fun PasswordInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = {}) { +fun PasswordInput(value: String = "", attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.Password, attrs = { applyAttrsWithStringValue(value, attrs) }) } @@ -158,7 +158,7 @@ fun PasswordInput(value: String = "", attrs: InputAttrsBuilder.() -> Uni */ @Composable @NonRestartableComposable -fun RadioInput(checked: Boolean = false, attrs: InputAttrsBuilder.() -> Unit = {}) { +fun RadioInput(checked: Boolean = false, attrs: InputAttrsScope.() -> Unit = {}) { Input( type = InputType.Radio, attrs = { @@ -182,7 +182,7 @@ fun RangeInput( min: Number? = null, max: Number? = null, step: Number = 1, - attrs: InputAttrsBuilder.() -> Unit = {} + attrs: InputAttrsScope.() -> Unit = {} ) { Input( type = InputType.Range, @@ -205,7 +205,7 @@ fun RangeInput( */ @Composable @NonRestartableComposable -fun SearchInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = {}) { +fun SearchInput(value: String = "", attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.Search, attrs = { applyAttrsWithStringValue(value, attrs) }) } @@ -215,7 +215,7 @@ fun SearchInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit */ @Composable @NonRestartableComposable -fun SubmitInput(attrs: InputAttrsBuilder.() -> Unit = {}) { +fun SubmitInput(attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.Submit, attrs = attrs) } @@ -228,7 +228,7 @@ fun SubmitInput(attrs: InputAttrsBuilder.() -> Unit = {}) { */ @Composable @NonRestartableComposable -fun TelInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = {}) { +fun TelInput(value: String = "", attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.Tel, attrs = { applyAttrsWithStringValue(value, attrs) }) } @@ -241,7 +241,7 @@ fun TelInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = { */ @Composable @NonRestartableComposable -fun TextInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = {}) { +fun TextInput(value: String = "", attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.Text, attrs = { applyAttrsWithStringValue(value, attrs) }) } @@ -254,7 +254,7 @@ fun TextInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = */ @Composable @NonRestartableComposable -fun TimeInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = {}) { +fun TimeInput(value: String = "", attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.Time, attrs = { applyAttrsWithStringValue(value, attrs) }) } @@ -267,7 +267,7 @@ fun TimeInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = */ @Composable @NonRestartableComposable -fun UrlInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = {}) { +fun UrlInput(value: String = "", attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.Url, attrs = { applyAttrsWithStringValue(value, attrs) }) } @@ -280,6 +280,6 @@ fun UrlInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = { */ @Composable @NonRestartableComposable -fun WeekInput(value: String = "", attrs: InputAttrsBuilder.() -> Unit = {}) { +fun WeekInput(value: String = "", attrs: InputAttrsScope.() -> Unit = {}) { Input(type = InputType.Week, attrs = { applyAttrsWithStringValue(value, attrs) }) } diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/RadioGroup.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/RadioGroup.kt index 35408514ef..c7c8cd4541 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/RadioGroup.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/RadioGroup.kt @@ -3,10 +3,10 @@ package org.jetbrains.compose.web.dom import androidx.compose.runtime.* import org.jetbrains.compose.web.ExperimentalComposeWebApi import org.jetbrains.compose.web.attributes.InputType -import org.jetbrains.compose.web.attributes.builders.InputAttrsBuilder +import org.jetbrains.compose.web.attributes.builders.InputAttrsScope import org.jetbrains.compose.web.attributes.name -typealias RadioInputAttrsBuilder = (InputAttrsBuilder.() -> Unit) +typealias RadioInputAttrsBuilder = (InputAttrsScope.() -> Unit) /** * @param value - sets `value` attribute diff --git a/web/core/src/jsTest/kotlin/elements/AttributesTests.kt b/web/core/src/jsTest/kotlin/elements/AttributesTests.kt index 0062ee2190..cf2f32e7be 100644 --- a/web/core/src/jsTest/kotlin/elements/AttributesTests.kt +++ b/web/core/src/jsTest/kotlin/elements/AttributesTests.kt @@ -21,7 +21,7 @@ class AttributesTests { @Test fun copyFromStyleBuilderCopiesCorrectly() { - val copyFromStyleBuilder = StyleBuilderImpl().apply { + val copyFromStyleBuilder = StyleScopeBuilder().apply { property("color", "red") property("height", 100.px) @@ -29,7 +29,7 @@ class AttributesTests { variable("var2", 100.px) } - val copyToStyleBuilder = StyleBuilderImpl().apply { + val copyToStyleBuilder = StyleScopeBuilder().apply { copyFrom(copyFromStyleBuilder) } @@ -38,7 +38,7 @@ class AttributesTests { @Test fun copyFromAttrsBuilderCopiesCorrectly() { - val attrsBuilderCopyFrom = AttrsBuilder().apply { + val attrsScopeCopyFrom = AttrsScopeBuilder().apply { id("id1") classes("a b c") attr("title", "customTitle") @@ -56,54 +56,54 @@ class AttributesTests { onMouseEnter { } } - val copyToAttrsBuilder = AttrsBuilder().apply { - copyFrom(attrsBuilderCopyFrom) + val copyToAttrsScope = AttrsScopeBuilder().apply { + copyFrom(attrsScopeCopyFrom) } - assertEquals(attrsBuilderCopyFrom.attributesMap, copyToAttrsBuilder.attributesMap) - assertEquals(attrsBuilderCopyFrom.styleBuilder, copyToAttrsBuilder.styleBuilder) - assertEquals(attrsBuilderCopyFrom.refEffect, copyToAttrsBuilder.refEffect) - assertEquals(attrsBuilderCopyFrom.propertyUpdates, copyToAttrsBuilder.propertyUpdates) - assertEquals(attrsBuilderCopyFrom.collectListeners(), copyToAttrsBuilder.collectListeners()) + assertEquals(attrsScopeCopyFrom.attributesMap, copyToAttrsScope.attributesMap) + assertEquals(attrsScopeCopyFrom.styleScope, copyToAttrsScope.styleScope) + assertEquals(attrsScopeCopyFrom.refEffect, copyToAttrsScope.refEffect) + assertEquals(attrsScopeCopyFrom.propertyUpdates, copyToAttrsScope.propertyUpdates) + assertEquals(attrsScopeCopyFrom.collectListeners(), copyToAttrsScope.collectListeners()) } @Test fun attrsBuilderCopyFromPreservesExistingAttrs() { - val attrsBuilderCopyFrom = AttrsBuilder().apply { + val attrsScopeCopyFrom = AttrsScopeBuilder().apply { attr("title", "customTitle") } - val copyToAttrsBuilder = AttrsBuilder().apply { + val copyToAttrsScope = AttrsScopeBuilder().apply { id("id1") onClick { } style { width(100.px) } - copyFrom(attrsBuilderCopyFrom) + copyFrom(attrsScopeCopyFrom) } - assertEquals("id1", copyToAttrsBuilder.attributesMap["id"]) - assertEquals(StyleBuilderImpl().apply { width(100.px) }, copyToAttrsBuilder.styleBuilder) + assertEquals("id1", copyToAttrsScope.attributesMap["id"]) + assertEquals(StyleScopeBuilder().apply { width(100.px) }, copyToAttrsScope.styleScope) - val listeners = copyToAttrsBuilder.collectListeners() + val listeners = copyToAttrsScope.collectListeners() assertEquals(1, listeners.size) assertEquals("click", listeners[0].event) } @Test fun attrsBuilderCopyFromOverridesSameAttrs() { - val attrsBuilderCopyFrom = AttrsBuilder().apply { + val attrsScopeCopyFrom = AttrsScopeBuilder().apply { attr("title", "customTitleNew") } - val copyToAttrsBuilder = AttrsBuilder().apply { + val copyToAttrsScope = AttrsScopeBuilder().apply { attr("title", "customTitleOld") } - assertEquals("customTitleOld", copyToAttrsBuilder.attributesMap["title"]) + assertEquals("customTitleOld", copyToAttrsScope.attributesMap["title"]) - copyToAttrsBuilder.copyFrom(attrsBuilderCopyFrom) - assertEquals("customTitleNew", copyToAttrsBuilder.attributesMap["title"]) + copyToAttrsScope.copyFrom(attrsScopeCopyFrom) + assertEquals("customTitleNew", copyToAttrsScope.attributesMap["title"]) } @Test diff --git a/web/core/src/jsTest/kotlin/elements/ElementsTests.kt b/web/core/src/jsTest/kotlin/elements/ElementsTests.kt index 19d8b3f6a1..540bab2d1a 100644 --- a/web/core/src/jsTest/kotlin/elements/ElementsTests.kt +++ b/web/core/src/jsTest/kotlin/elements/ElementsTests.kt @@ -6,10 +6,9 @@ package org.jetbrains.compose.web.core.tests.elements import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import kotlinx.browser.document import org.jetbrains.compose.web.ExperimentalComposeWebApi -import org.jetbrains.compose.web.attributes.AttrsBuilder +import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.testutils.* import org.jetbrains.compose.web.dom.* import org.w3c.dom.HTMLElement @@ -113,8 +112,8 @@ class ElementsTests { fun rawCreation() = runTest { @Composable fun CustomElement( - attrs: AttrsBuilder.() -> Unit, - content: ContentBuilder? = null + attrs: AttrsScope.() -> Unit, + content: ContentBuilder? = null ) { TagElement( tagName = "custom", diff --git a/web/integration-core/src/jsMain/kotlin/androidx/compose/web/sample/tests/InputsTests.kt b/web/integration-core/src/jsMain/kotlin/androidx/compose/web/sample/tests/InputsTests.kt index fa50ed8584..b0633bae25 100644 --- a/web/integration-core/src/jsMain/kotlin/androidx/compose/web/sample/tests/InputsTests.kt +++ b/web/integration-core/src/jsMain/kotlin/androidx/compose/web/sample/tests/InputsTests.kt @@ -343,7 +343,7 @@ class InputsTests { }) Div(attrs = { - addEventListener(EventsListenerBuilder.INPUT) { + addEventListener(EventsListenerScope.INPUT) { state2 = "div caught an input" } }) { diff --git a/web/svg/src/jsMain/kotlin/org/jetbrains/compose/web/svg/svg.kt b/web/svg/src/jsMain/kotlin/org/jetbrains/compose/web/svg/svg.kt index b4ebaf7c41..dee2de80df 100644 --- a/web/svg/src/jsMain/kotlin/org/jetbrains/compose/web/svg/svg.kt +++ b/web/svg/src/jsMain/kotlin/org/jetbrains/compose/web/svg/svg.kt @@ -61,9 +61,9 @@ private val View = ElementBuilderNS("view", SVG_NS) @Composable @ExperimentalComposeWebSvgApi fun Svg( - viewBox: String? = null, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + viewBox: String? = null, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Svg, @@ -78,9 +78,9 @@ fun Svg( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.SvgA( - href: String, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + href: String, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = A, @@ -95,11 +95,11 @@ fun ElementScope.SvgA( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Circle( - cx: CSSLengthOrPercentageValue, - cy: CSSLengthOrPercentageValue, - r: CSSLengthOrPercentageValue, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + cx: CSSLengthOrPercentageValue, + cy: CSSLengthOrPercentageValue, + r: CSSLengthOrPercentageValue, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Circle, @@ -117,11 +117,11 @@ fun ElementScope.Circle( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Circle( - cx: Number, - cy: Number, - r: Number, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + cx: Number, + cy: Number, + r: Number, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Circle, @@ -139,10 +139,10 @@ fun ElementScope.Circle( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.SvgText( - text: String, - x: Number = 0, - y: Number = 0, - attrs: AttrBuilderContext? = null, + text: String, + x: Number = 0, + y: Number = 0, + attrs: AttrsBuilder? = null, ) { TagElement( elementBuilder = Text, @@ -160,9 +160,9 @@ fun ElementScope.SvgText( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.View( - id: String, - viewBox: String, - attrs: AttrBuilderContext? = null, + id: String, + viewBox: String, + attrs: AttrsBuilder? = null, ) { TagElement( elementBuilder = View, @@ -178,12 +178,12 @@ fun ElementScope.View( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Rect( - x: Number, - y: Number, - width: Number, - height: Number, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + x: Number, + y: Number, + width: Number, + height: Number, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Rect, @@ -201,12 +201,12 @@ fun ElementScope.Rect( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Rect( - x: CSSLengthOrPercentageValue, - y: CSSLengthOrPercentageValue, - width: CSSLengthOrPercentageValue, - height: CSSLengthOrPercentageValue, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + x: CSSLengthOrPercentageValue, + y: CSSLengthOrPercentageValue, + width: CSSLengthOrPercentageValue, + height: CSSLengthOrPercentageValue, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Rect, @@ -224,12 +224,12 @@ fun ElementScope.Rect( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Ellipse( - cx: CSSLengthOrPercentageValue, - cy: CSSLengthOrPercentageValue, - rx: CSSLengthOrPercentageValue, - ry: CSSLengthOrPercentageValue, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + cx: CSSLengthOrPercentageValue, + cy: CSSLengthOrPercentageValue, + rx: CSSLengthOrPercentageValue, + ry: CSSLengthOrPercentageValue, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Ellipse, @@ -247,12 +247,12 @@ fun ElementScope.Ellipse( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Ellipse( - cx: Number, - cy: Number, - rx: Number, - ry: Number, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + cx: Number, + cy: Number, + rx: Number, + ry: Number, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Ellipse, @@ -271,9 +271,9 @@ fun ElementScope.Ellipse( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Symbol( - id: String? = null, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + id: String? = null, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Symbol, @@ -288,9 +288,9 @@ fun ElementScope.Symbol( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Use( - href: String, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + href: String, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Use, @@ -305,12 +305,12 @@ fun ElementScope.Use( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Line( - x1: CSSLengthOrPercentageValue, - y1: CSSLengthOrPercentageValue, - x2: CSSLengthOrPercentageValue, - y2: CSSLengthOrPercentageValue, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + x1: CSSLengthOrPercentageValue, + y1: CSSLengthOrPercentageValue, + x2: CSSLengthOrPercentageValue, + y2: CSSLengthOrPercentageValue, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Line, @@ -328,12 +328,12 @@ fun ElementScope.Line( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Line( - x1: Number, - y1: Number, - x2: Number, - y2: Number, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + x1: Number, + y1: Number, + x2: Number, + y2: Number, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Line, @@ -352,9 +352,9 @@ fun ElementScope.Line( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.ClipPath( - id: String, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + id: String, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = ClipPath, @@ -369,9 +369,9 @@ fun ElementScope.ClipPath( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Path( - d: String, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + d: String, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Path, @@ -386,8 +386,8 @@ fun ElementScope.Path( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.G( - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = G, @@ -399,9 +399,9 @@ fun ElementScope.G( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Image( - href: String, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + href: String, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Image, @@ -416,9 +416,9 @@ fun ElementScope.Image( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Mask( - id: String? = null, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + id: String? = null, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Mask, @@ -433,8 +433,8 @@ fun ElementScope.Mask( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Defs( - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Defs, @@ -446,9 +446,9 @@ fun ElementScope.Defs( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Pattern( - id: String, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + id: String, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Pattern, @@ -463,9 +463,9 @@ fun ElementScope.Pattern( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Polygon( - vararg points: Number, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + vararg points: Number, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Polygon, @@ -480,9 +480,9 @@ fun ElementScope.Polygon( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Polyline( - vararg points: Number, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + vararg points: Number, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Polyline, @@ -497,9 +497,9 @@ fun ElementScope.Polyline( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.TextPath( - href: String, - text: String, - attrs: AttrBuilderContext? = null, + href: String, + text: String, + attrs: AttrsBuilder? = null, ) { TagElement( elementBuilder = TextPath, @@ -516,8 +516,8 @@ fun ElementScope.TextPath( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Animate( - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Animate, @@ -529,8 +529,8 @@ fun ElementScope.Animate( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.AnimateMotion( - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = AnimateMotion, @@ -542,8 +542,8 @@ fun ElementScope.AnimateMotion( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.AnimateTransform( - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = AnimateTransform, @@ -555,9 +555,9 @@ fun ElementScope.AnimateTransform( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.LinearGradient( - id: String? = null, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + id: String? = null, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = LinearGradient, @@ -573,9 +573,9 @@ fun ElementScope.LinearGradient( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.RadialGradient( - id: String? = null, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + id: String? = null, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = RadialGradient, @@ -590,8 +590,8 @@ fun ElementScope.RadialGradient( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Stop( - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Stop, @@ -603,8 +603,8 @@ fun ElementScope.Stop( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Switch( - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Switch, @@ -616,8 +616,8 @@ fun ElementScope.Switch( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Title( - text: String, - attrs: AttrBuilderContext? = null, + text: String, + attrs: AttrsBuilder? = null, ) { TagElement( elementBuilder = Title, @@ -631,8 +631,8 @@ fun ElementScope.Title( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Tspan( - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Tspan, @@ -644,8 +644,8 @@ fun ElementScope.Tspan( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Desc( - content: String, - attrs: AttrBuilderContext? = null, + content: String, + attrs: AttrsBuilder? = null, ) { TagElement( elementBuilder = Desc, @@ -659,8 +659,8 @@ fun ElementScope.Desc( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Marker( - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Marker, @@ -672,8 +672,8 @@ fun ElementScope.Marker( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Mpath( - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Mpath, @@ -685,8 +685,8 @@ fun ElementScope.Mpath( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Filter( - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Filter, @@ -698,10 +698,10 @@ fun ElementScope.Filter( @Composable @ExperimentalComposeWebSvgApi fun ElementScope.Set( - attributeName: String, - to: String, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + attributeName: String, + to: String, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = Set, @@ -717,13 +717,13 @@ fun ElementScope.Set( @Composable @ExperimentalComposeWebSvgApi fun SvgElement( - name: String, - attrs: AttrBuilderContext? = null, - content: ContentBuilder? = null + name: String, + attrs: AttrsBuilder? = null, + content: ContentBuilder? = null ) { TagElement( elementBuilder = ElementBuilderNS(name, SVG_NS), applyAttrs = attrs, content = content ) -} \ No newline at end of file +} diff --git a/web/widgets/src/jsMain/kotlin/Modifier.kt b/web/widgets/src/jsMain/kotlin/Modifier.kt index 2f6d4bc02d..10f8b1a4e3 100644 --- a/web/widgets/src/jsMain/kotlin/Modifier.kt +++ b/web/widgets/src/jsMain/kotlin/Modifier.kt @@ -8,7 +8,7 @@ import org.jetbrains.compose.web.css.margin import org.jetbrains.compose.web.css.px import org.jetbrains.compose.web.css.Color.RGB import org.jetbrains.compose.common.internal.castOrCreate -import org.jetbrains.compose.web.attributes.AttrsBuilder +import org.jetbrains.compose.web.attributes.AttrsScope @ExperimentalComposeWebWidgetsApi @Deprecated(message = webWidgetsDeprecationMessage) @@ -21,10 +21,10 @@ actual fun Modifier.background(color: Color): Modifier = castOrCreate().apply { @ExperimentalComposeWebWidgetsApi @Deprecated(message = webWidgetsDeprecationMessage) fun Modifier.asAttributeBuilderApplier( - passThroughHandler: (AttrsBuilder<*>.() -> Unit)? = null -): AttrsBuilder<*>.() -> Unit = + passThroughHandler: (AttrsScope<*>.() -> Unit)? = null +): AttrsScope<*>.() -> Unit = castOrCreate().let { modifier -> - val st: AttrsBuilder<*>.() -> Unit = { + val st: AttrsScope<*>.() -> Unit = { modifier.attrHandlers.forEach { it.invoke(this) } style { diff --git a/web/widgets/src/jsMain/kotlin/internal/ActualModifier.kt b/web/widgets/src/jsMain/kotlin/internal/ActualModifier.kt index 59a9c30bbe..eaaa35e283 100644 --- a/web/widgets/src/jsMain/kotlin/internal/ActualModifier.kt +++ b/web/widgets/src/jsMain/kotlin/internal/ActualModifier.kt @@ -4,19 +4,19 @@ import org.jetbrains.compose.annotations.webWidgetsDeprecationMessage import org.jetbrains.compose.common.ui.ExperimentalComposeWebWidgetsApi import org.jetbrains.compose.common.ui.Modifier import org.jetbrains.compose.web.css.StyleBuilder -import org.jetbrains.compose.web.attributes.AttrsBuilder +import org.jetbrains.compose.web.attributes.AttrsScope @ExperimentalComposeWebWidgetsApi @Deprecated(message = webWidgetsDeprecationMessage) class ActualModifier : Modifier { val styleHandlers = mutableListOf Unit>() - val attrHandlers = mutableListOf.() -> Unit>() + val attrHandlers = mutableListOf.() -> Unit>() fun add(builder: StyleBuilder.() -> Unit) { styleHandlers.add(builder) } - fun addAttributeBuilder(builder: AttrsBuilder<*>.() -> Unit) { + fun addAttributeBuilder(builder: AttrsScope<*>.() -> Unit) { attrHandlers.add(builder) } }