Skip to content

Commit

Permalink
Added Rating component and Test page. WIP-Colored icons still to be i…
Browse files Browse the repository at this point in the history
…mplemented in test page.
  • Loading branch information
cfnz committed Jan 27, 2021
1 parent 9858535 commit 8d9e27f
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ interface MIconProps : StyledProps {
var component: String?
}

var MIconProps.color by EnumPropToString(MIconColor.values())
var MIconProps.color by EnumPropToStringNullable(MIconColor.values())
var MIconProps.fontSize by EnumPropToString(MIconFontSize.values())

fun RBuilder.mIcon(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.ccfraser.muirwik.components.lab

import com.ccfraser.muirwik.components.EnumPropToString
import com.ccfraser.muirwik.components.StyledPropsWithCommonAttributes
import com.ccfraser.muirwik.components.createStyled
import com.ccfraser.muirwik.components.setStyledPropsAndRunHandler
import kotlinext.js.Object
import react.*
import styled.StyledHandler

@JsModule("@material-ui/lab/Rating")
private external val module: dynamic

@Suppress("UnsafeCastFromDynamic")
private val component: RComponent<MRatingProps, RState> = module.default

@Suppress("EnumEntryName")
enum class MRatingSize {
large, medium, small
}

interface MRatingProps : StyledPropsWithCommonAttributes {
var defaultValue: Number
var disabled: Boolean
var emptyIcon: ReactElement
var emptyLabelText: String
var getLabelText: (value: Number) -> String
var icon: ReactElement
@JsName("IconContainerComponent")
var iconContainerComponent: FunctionalComponent<MIconContainerProps>
var max: Number
var name: String
var onChange: (event: Object, newValue: Number) -> Unit
var onChangeActive: (event: Object, hoverValue: Number) -> Unit
var precision: Number
var readOnly: Boolean
var value: Number?
}
var MRatingProps.size by EnumPropToString(MRatingSize.values())

interface MIconContainerProps : StyledPropsWithCommonAttributes {
var value: Int
}

fun RBuilder.mRating(
name: String,
value: Number? = null,
max: Number = 5,
precision: Number = 1,
onChange: ((event: Object, newValue: Number) -> Unit)? = null,
defaultValue: Number? = null,
readOnly: Boolean = false,
disabled: Boolean = false,
icon: ReactElement? = null,
emptyIcon: ReactElement? = null,
emptyLabelText: String = "Empty",
size: MRatingSize = MRatingSize.medium,

addAsChild: Boolean = true,
className: String? = null,
handler: StyledHandler<MRatingProps>? = null
) = createStyled(component, addAsChild) {
defaultValue?.let { attrs.defaultValue = it }
attrs.disabled = disabled
emptyIcon?.let { attrs.emptyIcon = it }
attrs.emptyLabelText = emptyLabelText
icon?.let { attrs.icon = icon }
attrs.max = max
attrs.name = name
onChange?.let { attrs.onChange = it }
attrs.precision = precision
attrs.readOnly = readOnly
attrs.size = size
value?.let { attrs.value = it }

setStyledPropsAndRunHandler(className, handler)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ private val component: RComponent<MAlertProps, RState> = module.default

@Suppress("EnumEntryName")
enum class MAlertVariant {
filled, outlined, standard
filled, outlined, standard
}

@Suppress("EnumEntryName")
enum class MAlertSeverity {
error, info, success, warning
error, info, success, warning
}

interface MAlertProps : StyledPropsWithCommonAttributes {
var action: ReactElement
var icon: ReactElement
var onClose: (Event) -> Unit
var closeText: String
var action: ReactElement
var icon: ReactElement
var onClose: (Event) -> Unit
var closeText: String
}

var MAlertProps.variant by EnumPropToStringNullable(MAlertVariant.values())
Expand All @@ -47,13 +47,13 @@ fun RBuilder.mAlert(

className: String? = null,
handler: StyledHandler<MAlertProps>? = null) = createStyled(component, addAsChild) {
message?.let { +message }
attrs.variant = variant
attrs.severity = severity
attrs.closeText = closeText
onClose?.let { attrs.onClose = onClose }
message?.let { +message }
attrs.variant = variant
attrs.severity = severity
attrs.closeText = closeText
onClose?.let { attrs.onClose = onClose }

setStyledPropsAndRunHandler(className, handler)
setStyledPropsAndRunHandler(className, handler)
}

fun RBuilder.mAlert(
Expand All @@ -67,13 +67,13 @@ fun RBuilder.mAlert(

className: String? = null,
handler: StyledHandler<MAlertProps>? = null) = createStyled(component, addAsChild) {
attrs.variant = variant
attrs.severity = severity
attrs.closeText = closeText
onClose?.let { attrs.onClose = onClose }
attrs.variant = variant
attrs.severity = severity
attrs.closeText = closeText
onClose?.let { attrs.onClose = onClose }

+mAlertTitle(title, false)
message?.let { +message }
+mAlertTitle(title, false)
message?.let { +message }

setStyledPropsAndRunHandler(className, handler)
setStyledPropsAndRunHandler(className, handler)
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class MainFrame(props: MainFrameProps) : RComponent<MainFrameProps, MainFrameSta
"Popover" to RBuilder::testPopover,
"Progress" to RBuilder::testProgress,
"Radio Buttons" to RBuilder::testRadioButtons,
"Ratings" to RBuilder::testRatings,
"Selects" to RBuilder::testSelects,
"Sliders" to RBuilder::testSliders,
"Snackbars" to RBuilder::testSnackbar,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package com.ccfraser.muirwik.testapp

import com.ccfraser.muirwik.components.*
import com.ccfraser.muirwik.components.lab.MIconContainerProps
import com.ccfraser.muirwik.components.lab.MRatingSize
import com.ccfraser.muirwik.components.lab.mRating
import com.ccfraser.muirwik.testapp.ComponentStyles.margin
import kotlinx.css.*
import react.*
import styled.StyleSheet
import styled.css
import styled.styledDiv


private object ComponentStyles : StyleSheet("ComponentStyles", isStatic = true) {
val margin by css {
margin(2.spacingUnits)
}
}

private val testRatings = functionalComponent<RProps> { props ->
styledDiv {
var value: Number? by useState(2)
css(margin)
mTypography("Simple Rating", MTypographyVariant.h4)
styledDiv {
css(margin)
mTypography("Controlled", component = "legend")
mRating("simple-controlled", value, onChange = { _, newValue -> value = newValue })
}
styledDiv {
css(margin)
mTypography("Read Only", component = "legend")
mRating("read-only", value, readOnly = true)

}
styledDiv {
css(margin)
mTypography("Disabled", component = "legend")
mRating("disabled", value, disabled = true)
}
styledDiv {
css(margin)
mTypography("Pristine", component = "legend")
mRating("pristine")
}
}
styledDiv {
var value: Number? by useState(2)
css(margin)
mTypography("Customized Rating", MTypographyVariant.h4)
styledDiv {
css(margin)
mTypography("Custom empty icon", component = "legend")
mRating("customized-empty", value, precision = 0.5, onChange = { _, newValue -> value = newValue }) {
attrs.emptyIcon = mIcon("star_border", fontSize = MIconFontSize.inherit, addAsChild = false)
}
}
styledDiv {
css(margin)
// TODO: Not sure how to apply the color styles as in the original demo
mTypography("Custom icon and color (color is still a WIP)", component = "legend")
mRating("customized-empty", value, precision = 0.5, onChange = { _, newValue -> value = newValue },
icon = mIcon("favorite", fontSize = MIconFontSize.inherit, addAsChild = false))
}
styledDiv {
css(margin)
mTypography("Custom icon set", component = "legend")
mRating("customized-icons", value, onChange = { _, newValue -> value = newValue }) {
attrs.iconContainerComponent = iconContainer
}

}
styledDiv {
css(margin)
mTypography("10 Starts", component = "legend")
mRating("customized-10", null, max = 10)
}
}
styledDiv {
var value: Number? by useState(2)
css(margin)
mTypography("Hover Feedback", MTypographyVariant.h4)
styledDiv {
css {
+ComponentStyles.margin
display = Display.flex
alignItems = Align.center
}
var hover: Number by useState(-1)
mRating("hover-feedback", value, precision = 0.5) {
attrs.onChange = { _, newValue -> value = newValue }
attrs.onChangeActive = { _, hoverValue -> hover = hoverValue }
}
styledDiv {
css { marginLeft = 2.spacingUnits }
value?.let { +labelForValue(if (hover != -1) hover else it) }
}
}
}
styledDiv {
css(margin)
mTypography("Sizes", MTypographyVariant.h4)
styledDiv {
css {
+ComponentStyles.margin
display = Display.flex
flexDirection = FlexDirection.column
}
mRating("size-s", null, size = MRatingSize.small)
mRating("size-m", null, size = MRatingSize.medium)
mRating("size-l", null, size = MRatingSize.large)
}
}
}

private fun labelForValue(value: Number) = when(value) {
0.5 -> "Useless"
1 -> "Useless+"
1.5 -> "Poor"
2 -> "Poor+"
2.5 -> "Ok"
3 -> "Ok+"
3.5 -> "Good"
4 -> "Good+"
4.5 -> "Excellent"
5 -> "Excellent+"
else -> "Unknown"
}

private val iconContainer = functionalComponent<MIconContainerProps> { props ->
createElement("span", props, when (props.value) {
1 -> mIcon("sentiment_very_dissatisfied", className = props.className)
2 -> mIcon("sentiment_dissatisfied", className = props.className)
3 -> mIcon("sentiment_satisfied", className = props.className)
4 -> mIcon("sentiment_satisfied_alt", className = props.className)
else -> mIcon("sentiment_very_satisfied", className = props.className)
}
)
}

fun RBuilder.testRatings() = child(testRatings) {
}

0 comments on commit 8d9e27f

Please sign in to comment.