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.
package io.udash.bootstrap
package button
import com.avsystem.commons._
import io.udash._
import io.udash.bindings.modifiers.Binding
import io.udash.bootstrap.utils.{BootstrapStyles, UdashBootstrapComponent}
import io.udash.properties.seq
import org.scalajs.dom.Element
import scalatags.JsDom.all._
final class UdashButtonGroup[ItemType, ElemType <: ReadableProperty[ItemType]] private(
items: seq.ReadableSeqProperty[ItemType, ElemType],
size: ReadableProperty[Option[BootstrapStyles.Size]],
vertical: ReadableProperty[Boolean],
justified: ReadableProperty[Boolean],
override val componentId: ComponentId
)(itemFactory: (ElemType, Binding.NestedInterceptor) => Seq[Element]) extends UdashBootstrapComponent {
import io.udash.css.CssView._
private def buttonFullWidth: Binding =
BootstrapStyles.Sizing.width100.styleIf(justified)
private val classes: List[Modifier] = {
(BootstrapStyles.Button.group: Modifier) ::
nestedInterceptor(BootstrapStyles.Button.groupVertical.styleIf(vertical)) ::
nestedInterceptor(BootstrapStyles.Display.flex().styleIf(justified)) ::
nestedInterceptor((BootstrapStyles.Button.groupSize _).reactiveOptionApply(size)) :: Nil
}
override val render: Element =
div(componentId, role := "group", classes)(
nestedInterceptor(
repeatWithNested(items) { case (item, nested) =>
val elements = itemFactory(item, nested)
elements.foreach(el => nested(buttonFullWidth).applyTo(el))
elements
}
)
).render
}
object UdashButtonGroup {
/**
* Creates a static buttons group.
* More: Bootstrap Docs.
*
* @param size A buttons group size. It shadows the size of each button.
* @param vertical If true, the buttons will be rendered vertically.
* @param justified If true, the buttons will be justified.
* @param componentId An id of the root DOM node.
* @param buttons Rendered buttons belonging to this group.
* @return A `UdashButtonGroup` component, call `render` to create a DOM element representing this group.
*/
def apply(
size: ReadableProperty[Option[BootstrapStyles.Size]] = UdashBootstrap.None,
vertical: ReadableProperty[Boolean] = UdashBootstrap.False,
justified: ReadableProperty[Boolean] = UdashBootstrap.False,
componentId: ComponentId = ComponentId.generate()
)(buttons: Element*): UdashButtonGroup[Element, Property[Element]] = {
reactive[Element, Property[Element]](
SeqProperty[Element](buttons),
size, vertical, justified, componentId
)((p, _) => p.get)
}
/**
* Creates a dynamic button group. `items` sequence changes will be synchronized with the rendered button group.
* More: Bootstrap Docs.
*
* @param items Data items which will be represented as the buttons in this group.
* @param size A buttons group size. It shadows the size of each button.
* @param vertical If true, the buttons will be rendered vertically.
* @param justified If true, the buttons will be justified.
* @param componentId An id of the root DOM node.
* @param itemFactory Creates a button based on an item from the `items` sequence.
* Use the provided interceptor to properly clean up bindings inside the content.
* @tparam ItemType A single element's type in the `items` sequence.
* @tparam ElemType A type of a property containing an element in the `items` sequence.
* @return A `UdashButtonGroup` component, call `render` to create a DOM element representing this group.
*/
def reactive[ItemType, ElemType <: ReadableProperty[ItemType]](
items: seq.ReadableSeqProperty[ItemType, ElemType],
size: ReadableProperty[Option[BootstrapStyles.Size]] = UdashBootstrap.None,
vertical: ReadableProperty[Boolean] = UdashBootstrap.False,
justified: ReadableProperty[Boolean] = UdashBootstrap.False,
componentId: ComponentId = ComponentId.generate()
)(itemFactory: (ElemType, Binding.NestedInterceptor) => Seq[Element]): UdashButtonGroup[ItemType, ElemType] = {
new UdashButtonGroup[ItemType, ElemType](
items, size, vertical, justified, componentId
)(itemFactory)
}
/**
* Creates a dynamic toggle buttons group. `items` sequence changes will be synchronized with the rendered button group.
* More: Bootstrap Docs.
*
* @param selectedItems Elements represented by the active buttons.
* @param options Data items which will be represented as buttons in this group.
* @param size A buttons group size. It shadows the size of each button.
* @param vertical If true, the buttons will be rendered vertically.
* @param justified If true, the buttons will be justified.
* @param componentId An id of the root DOM node.
* @param btnFactory It should create UdashButton instance based on provided item and active property.
* Don't forget to pass the second argument to created button as `active` arguemnt.
* The default implementation uses `toString` in order to create a button's content.
* @return A `UdashButtonGroup` component, call `render` to create a DOM element representing this group.
*/
def checkboxes[ItemType, ElemType <: ReadableProperty[ItemType]](
selectedItems: SeqProperty[ItemType],
options: seq.ReadableSeqProperty[ItemType, ElemType],
size: ReadableProperty[Option[BootstrapStyles.Size]] = UdashBootstrap.None,
vertical: ReadableProperty[Boolean] = UdashBootstrap.False,
justified: ReadableProperty[Boolean] = UdashBootstrap.False,
componentId: ComponentId = ComponentId.generate()
)(
btnFactory: (ElemType, ReadableProperty[Boolean], Binding.NestedInterceptor) => UdashButton =
(item: ElemType, active: ReadableProperty[Boolean], nested: Binding.NestedInterceptor) =>
nested(UdashButton(active = active)(nested => Seq(nested(bind(item)))))
): UdashButtonGroup[ItemType, ElemType] = {
new UdashButtonGroup[ItemType, ElemType](
options, size, vertical, justified, componentId
)((item, nested) => {
val active: ReadableProperty[Boolean] = selectedItems.transform(_.contains(item.get))
val btn: UdashButton = btnFactory(item, active, nested)
btn.listen {
case UdashButton.ButtonClickEvent(_, _) =>
if (active.get) selectedItems.remove(item.get)
else selectedItems.append(item.get)
}
nested(btn)
btn.render
})
}
/**
* Creates a dynamic radio buttons group. `items` sequence changes will be synchronized with the rendered button group.
* More: Bootstrap Docs.
*
* @param selectedItem An element represented by the active buttons.
* @param options Data items which will be represented as buttons in this group.
* @param size A buttons group size. It shadows the size of each button.
* @param vertical If true, the buttons will be rendered vertically.
* @param justified If true, the buttons will be justified.
* @param componentId An id of the root DOM node.
* @param btnFactory It should create UdashButton instance based on provided item and active property.
* Don't forget to pass the second argument to created button as `active` arguemnt.
* The default implementation uses `toString` in order to create a button's content.
* @return A `UdashButtonGroup` component, call `render` to create a DOM element representing this group.
*/
def radio[ItemType, ElemType <: ReadableProperty[ItemType]](
selectedItem: Property[ItemType],
options: seq.ReadableSeqProperty[ItemType, ElemType],
size: ReadableProperty[Option[BootstrapStyles.Size]] = UdashBootstrap.None,
vertical: ReadableProperty[Boolean] = UdashBootstrap.False,
justified: ReadableProperty[Boolean] = UdashBootstrap.False,
componentId: ComponentId = ComponentId.generate()
)(
btnFactory: (ElemType, ReadableProperty[Boolean], Binding.NestedInterceptor) => UdashButton =
(item: ElemType, active: ReadableProperty[Boolean], nested: Binding.NestedInterceptor) =>
nested(UdashButton(active = active)(nested => Seq(nested(bind(item)))))
): UdashButtonGroup[ItemType, ElemType] = {
new UdashButtonGroup[ItemType, ElemType](
options, size, vertical, justified, componentId
)((item, nested) => {
val active: ReadableProperty[Boolean] = selectedItem.transform(_ == item.get)
val btn: UdashButton = btnFactory(item, active, nested)
btn.listen {
case UdashButton.ButtonClickEvent(_, _) =>
selectedItem.set(item.get)
}
nested(btn)
btn.render
})
}
}