You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.9 KiB
122 lines
3.9 KiB
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.InputAttrsScope |
|
import org.jetbrains.compose.web.attributes.name |
|
|
|
typealias RadioInputAttrsBuilder = (InputAttrsScope<Boolean>.() -> Unit) |
|
|
|
/** |
|
* @param value - sets `value` attribute |
|
* @param id - sets `id` attribute |
|
* @param attrs - builder to set any eligible attribute |
|
*/ |
|
@Composable |
|
@NonRestartableComposable |
|
@ExperimentalComposeWebApi |
|
fun <T> RadioGroupScope<T>.RadioInput( |
|
value: T, |
|
id: String? = null, |
|
attrs: RadioInputAttrsBuilder? = null |
|
) { |
|
val checkedValue = getCompositionLocalRadioGroupCheckedValue() |
|
val radioGroupName = getCompositionLocalRadioGroupName() |
|
|
|
Input( |
|
type = InputType.Radio, |
|
attrs = { |
|
attrs?.invoke(this) |
|
if (id != null) id(id) |
|
name(radioGroupName) |
|
|
|
val valueString = value.toString() |
|
checked(checkedValue == valueString) |
|
value(valueString) |
|
} |
|
) |
|
} |
|
|
|
/** |
|
* @param checkedValue - value of a radio input that has to be checked |
|
* @param name - radio group name. It has to be unique among all radio groups. |
|
* If it's null during first composition, radio group will use a generated name. |
|
* @param content - is a composable lambda that contains any number of [RadioInput] |
|
*/ |
|
@Composable |
|
@NonRestartableComposable |
|
@ExperimentalComposeWebApi |
|
fun <E, T : Enum<E>?> RadioGroup( |
|
checkedValue: T, |
|
name: String? = null, |
|
content: @Composable RadioGroupScope<T>.() -> Unit |
|
) { |
|
val radioGroupName = remember { name ?: generateNextRadioGroupName() } |
|
|
|
CompositionLocalProvider( |
|
radioGroupCompositionLocalValue provides checkedValue.toString(), |
|
radioGroupCompositionLocalName provides radioGroupName, |
|
content = { |
|
// normal cast would fail here! |
|
// this is to specify the type of the values for radio inputs |
|
content(radioGroupScopeImpl.unsafeCast<RadioGroupScope<T>>()) |
|
} |
|
) |
|
} |
|
|
|
/** |
|
* @param checkedValue - value of a radio input that has to be checked |
|
* @param name - radio group name. It has to be unique among all radio groups. |
|
* If it's null during first composition, radio group will use a generated name. |
|
* @param content - is a composable lambda that contains any number of [RadioInput] |
|
*/ |
|
@Composable |
|
@NonRestartableComposable |
|
@ExperimentalComposeWebApi |
|
fun RadioGroup( |
|
checkedValue: String?, |
|
name: String? = null, |
|
content: @Composable RadioGroupScope<String>.() -> Unit |
|
) { |
|
val radioGroupName = remember { name ?: generateNextRadioGroupName() } |
|
|
|
CompositionLocalProvider( |
|
radioGroupCompositionLocalValue provides checkedValue, |
|
radioGroupCompositionLocalName provides radioGroupName, |
|
content = { |
|
// normal cast would fail here! |
|
// this is to specify the type of the values for radio inputs |
|
content(radioGroupScopeImpl.unsafeCast<RadioGroupScope<String>>()) |
|
} |
|
) |
|
} |
|
|
|
@ExperimentalComposeWebApi |
|
class RadioGroupScope<T> internal constructor() |
|
|
|
@OptIn(ExperimentalComposeWebApi::class) |
|
private val radioGroupScopeImpl = RadioGroupScope<Any>() |
|
|
|
private var generatedRadioGroupNamesCounter = 0 |
|
|
|
private fun generateNextRadioGroupName(): String { |
|
return "\$compose\$generated\$radio\$group-${generatedRadioGroupNamesCounter++}" |
|
} |
|
|
|
internal val radioGroupCompositionLocalValue = compositionLocalOf<String?> { |
|
error("No radio group checked value provided") |
|
} |
|
internal val radioGroupCompositionLocalName = compositionLocalOf<String> { |
|
error("No radio group name provided") |
|
} |
|
|
|
@Composable |
|
internal fun getCompositionLocalRadioGroupCheckedValue(): String? { |
|
return radioGroupCompositionLocalValue.current |
|
} |
|
|
|
@Composable |
|
internal fun getCompositionLocalRadioGroupName(): String { |
|
return radioGroupCompositionLocalName.current |
|
}
|
|
|