All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
commonMain.io.github.lyxnx.compose.pine.Checkbox.kt Maven / Gradle / Ivy
package io.github.lyxnx.compose.pine
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.snap
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.selection.triStateToggleable
import androidx.compose.material3.Icon
import androidx.compose.material3.minimumInteractiveComponentSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.state.ToggleableState
import androidx.compose.ui.unit.dp
import compose.icons.TablerIcons
import compose.icons.tablericons.Outline
import compose.icons.tablericons.outline.Check
import compose.icons.tablericons.outline.Minus
import io.github.lyxnx.compose.ui.dropShadow
import io.github.lyxnx.compose.ui.ifTrue
/**
* A Pine Theme dual state checkbox (on/off)
*
* @param checked whether this checkbox is checked
* @param onCheckChanged action to perform when clicking - this is passed the inverse of the [checked] parameter
* @param modifier the modifier to be applied to the checkbox
* @param enabled whether the checkbox is enabled
* @param colors any custom colors to be used for the checkbox
* @param interactionSource interaction source used to dispatch interaction events to
*/
@Composable
public fun Checkbox(
checked: Boolean,
onCheckChanged: ((Boolean) -> Unit)?,
modifier: Modifier = Modifier,
enabled: Boolean = true,
colors: CheckboxColors = CheckboxDefaults.checkboxColors(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
) {
val state = remember(checked) {
if (checked) ToggleableState.On else ToggleableState.Off
}
TriStateCheckbox(
state = state,
onClick = if (onCheckChanged != null) {
{
onCheckChanged(!checked)
}
} else null,
modifier = modifier,
enabled = enabled,
colors = colors,
interactionSource = interactionSource
)
}
/**
* A Pine Theme tri state checkbox
*
* @param state the checkbox state
* @param onClick action to perform when clicking
* @param modifier the modifier to be applied to the checkbox
* @param enabled whether the checkbox is enabled
* @param colors any custom colors to be used for the checkbox
* @param interactionSource interaction source used to dispatch interaction events to
*/
@Composable
public fun TriStateCheckbox(
state: ToggleableState,
onClick: (() -> Unit)?,
modifier: Modifier = Modifier,
enabled: Boolean = true,
colors: CheckboxColors = CheckboxDefaults.triStateCheckboxColors(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
) {
val isFocused by interactionSource.collectIsFocusedAsState()
val backgroundColor by colors.backgroundColor(interactionSource, enabled, state)
val borderColor by colors.borderColor(interactionSource, enabled, state)
val indicatorColor by colors.indicatorColor(interactionSource, enabled, state)
val focusShadowColor by colors.shadowColor(state)
val transition = updateTransition(state)
val checkDrawFraction = transition.animateFloat(
transitionSpec = {
when {
initialState == ToggleableState.Off -> tween(100)
targetState == ToggleableState.Off -> snap(100)
else -> spring()
}
}
) {
when (it) {
ToggleableState.On -> 0.75f
ToggleableState.Off -> 0f
ToggleableState.Indeterminate -> 0.75f
}
}
Box(
modifier
.ifTrue(onClick != null) {
Modifier.minimumInteractiveComponentSize()
}
.ifTrue(isFocused) {
dropShadow(
color = focusShadowColor,
shape = PineTheme.shapes.small,
spread = 2.dp
)
}
.clip(PineTheme.shapes.small)
.ifTrue(onClick != null) {
triStateToggleable(
state = state,
onClick = onClick!!,
enabled = enabled,
role = Role.Checkbox,
interactionSource = interactionSource,
indication = LocalIndication.current
)
}
.border(1.dp, borderColor, PineTheme.shapes.small)
.background(backgroundColor)
.requiredSize(24.dp),
contentAlignment = Alignment.Center
) {
if (state == ToggleableState.On || state == ToggleableState.Indeterminate) {
Icon(
painter = rememberVectorPainter(if (state == ToggleableState.On) TablerIcons.Outline.Check else TablerIcons.Outline.Minus),
contentDescription = null,
tint = indicatorColor,
modifier = Modifier.fillMaxSize(checkDrawFraction.value)
)
}
}
}