diff --git a/src/addons/Confirm/Confirm.js b/src/addons/Confirm/Confirm.js
index 99d285f27e..0f51287af6 100644
--- a/src/addons/Confirm/Confirm.js
+++ b/src/addons/Confirm/Confirm.js
@@ -1,6 +1,6 @@
import _ from 'lodash'
import PropTypes from 'prop-types'
-import React, { Component } from 'react'
+import React from 'react'
import { customPropTypes, getUnhandledProps } from '../../lib'
import Button from '../../elements/Button'
@@ -10,55 +10,56 @@ import Modal from '../../modules/Modal'
* A Confirm modal gives the user a choice to confirm or cancel an action/
* @see Modal
*/
-class Confirm extends Component {
- handleCancel = (e) => {
- _.invoke(this.props, 'onCancel', e, this.props)
+const Confirm = React.forwardRef(function (props, ref) {
+ const { cancelButton, confirmButton, content, header, open, size } = props
+ const rest = getUnhandledProps(Confirm, props)
+
+ const handleCancel = (e) => {
+ _.invoke(props, 'onCancel', e, props)
}
- handleCancelOverrides = (predefinedProps) => ({
+ const handleCancelOverrides = (predefinedProps) => ({
onClick: (e, buttonProps) => {
_.invoke(predefinedProps, 'onClick', e, buttonProps)
- this.handleCancel(e)
+ handleCancel(e)
},
})
- handleConfirmOverrides = (predefinedProps) => ({
+ const handleConfirmOverrides = (predefinedProps) => ({
onClick: (e, buttonProps) => {
_.invoke(predefinedProps, 'onClick', e, buttonProps)
- _.invoke(this.props, 'onConfirm', e, this.props)
+ _.invoke(props, 'onConfirm', e, props)
},
})
- render() {
- const { cancelButton, confirmButton, content, header, open, size } = this.props
- const rest = getUnhandledProps(Confirm, this.props)
-
- // `open` is auto controlled by the Modal
- // It cannot be present (even undefined) with `defaultOpen`
- // only apply it if the user provided an open prop
- const openProp = {}
- if (_.has(this.props, 'open')) openProp.open = open
-
- return (
-
- {Modal.Header.create(header, { autoGenerateKey: false })}
- {Modal.Content.create(content, { autoGenerateKey: false })}
-
- {Button.create(cancelButton, {
- autoGenerateKey: false,
- overrideProps: this.handleCancelOverrides,
- })}
- {Button.create(confirmButton, {
- autoGenerateKey: false,
- defaultProps: { primary: true },
- overrideProps: this.handleConfirmOverrides,
- })}
-
-
- )
+ // `open` is auto controlled by the Modal
+ // It cannot be present (even undefined) with `defaultOpen`
+ // only apply it if the user provided an open prop
+ const openProp = {}
+ if (_.has(props, 'open')) {
+ openProp.open = open
}
-}
+ return (
+
+ {Modal.Header.create(header, { autoGenerateKey: false })}
+ {Modal.Content.create(content, { autoGenerateKey: false })}
+
+ {Button.create(cancelButton, {
+ autoGenerateKey: false,
+ overrideProps: handleCancelOverrides,
+ })}
+ {Button.create(confirmButton, {
+ autoGenerateKey: false,
+ defaultProps: { primary: true },
+ overrideProps: handleConfirmOverrides,
+ })}
+
+
+ )
+})
+
+Confirm.displayName = 'Confirm'
Confirm.propTypes = {
/** The cancel button text. */
cancelButton: customPropTypes.itemShorthand,
diff --git a/src/addons/Radio/Radio.js b/src/addons/Radio/Radio.js
index 4edc9add52..0159880db2 100644
--- a/src/addons/Radio/Radio.js
+++ b/src/addons/Radio/Radio.js
@@ -9,17 +9,19 @@ import Checkbox from '../../modules/Checkbox'
* @see Checkbox
* @see Form
*/
-function Radio(props) {
+const Radio = React.forwardRef(function (props, ref) {
const { slider, toggle, type } = props
+
const rest = getUnhandledProps(Radio, props)
// const ElementType = getElementType(Radio, props)
// radio, slider, toggle are exclusive
// use an undefined radio if slider or toggle are present
const radio = !(slider || toggle) || undefined
- return
-}
+ return
+})
+Radio.displayName = 'Radio'
Radio.propTypes = {
/** Format to emphasize the current selection state. */
slider: Checkbox.propTypes.slider,
diff --git a/src/addons/TextArea/TextArea.js b/src/addons/TextArea/TextArea.js
index 91e4bdbb88..d6b0537f02 100644
--- a/src/addons/TextArea/TextArea.js
+++ b/src/addons/TextArea/TextArea.js
@@ -1,50 +1,45 @@
-import { Ref } from '@fluentui/react-component-ref'
import _ from 'lodash'
import PropTypes from 'prop-types'
-import React, { Component, createRef } from 'react'
+import React from 'react'
-import { getElementType, getUnhandledProps } from '../../lib'
+import { getElementType, getUnhandledProps, useMergedRefs } from '../../lib'
/**
* A TextArea can be used to allow for extended user input.
* @see Form
*/
-class TextArea extends Component {
- ref = createRef()
+const TextArea = React.forwardRef(function (props, ref) {
+ const { rows, value } = props
+ const elementRef = useMergedRefs(ref, React.useRef())
- focus = () => this.ref.current.focus()
+ const handleChange = (e) => {
+ const newValue = _.get(e, 'target.value')
- handleChange = (e) => {
- const value = _.get(e, 'target.value')
-
- _.invoke(this.props, 'onChange', e, { ...this.props, value })
+ _.invoke(props, 'onChange', e, { ...props, value: newValue })
}
- handleInput = (e) => {
- const value = _.get(e, 'target.value')
+ const handleInput = (e) => {
+ const newValue = _.get(e, 'target.value')
- _.invoke(this.props, 'onInput', e, { ...this.props, value })
+ _.invoke(props, 'onInput', e, { ...props, value: newValue })
}
- render() {
- const { rows, value } = this.props
- const rest = getUnhandledProps(TextArea, this.props)
- const ElementType = getElementType(TextArea, this.props)
-
- return (
- [
-
- ]
- )
- }
-}
-
+ const rest = getUnhandledProps(TextArea, props)
+ const ElementType = getElementType(TextArea, props)
+
+ return (
+
+ )
+})
+
+TextArea.displayName = 'TextArea'
TextArea.propTypes = {
/** An element type to render as (string or function). */
as: PropTypes.elementType,
diff --git a/src/modules/Checkbox/Checkbox.js b/src/modules/Checkbox/Checkbox.js
index bd4e02f10f..00eeeb80a6 100644
--- a/src/modules/Checkbox/Checkbox.js
+++ b/src/modules/Checkbox/Checkbox.js
@@ -1,11 +1,9 @@
-import { Ref } from '@fluentui/react-component-ref'
import cx from 'clsx'
import _ from 'lodash'
import PropTypes from 'prop-types'
-import React, { createRef } from 'react'
+import React from 'react'
import {
- ModernAutoControlledComponent as Component,
createHTMLLabel,
customPropTypes,
getElementType,
@@ -14,6 +12,9 @@ import {
makeDebugger,
partitionHTMLProps,
useKeyOnly,
+ useAutoControlledValue,
+ useMergedRefs,
+ useIsomorphicLayoutEffect,
} from '../../lib'
const debug = makeDebugger('checkbox')
@@ -23,39 +24,92 @@ const debug = makeDebugger('checkbox')
* @see Form
* @see Radio
*/
-export default class Checkbox extends Component {
- inputRef = createRef()
- labelRef = createRef()
+const Checkbox = React.forwardRef(function (props, ref) {
+ const {
+ className,
+ disabled,
+ label,
+ id,
+ name,
+ radio,
+ readOnly,
+ slider,
+ tabIndex,
+ toggle,
+ type,
+ value,
+ } = props
+
+ const [checked, setChecked] = useAutoControlledValue({
+ state: props.checked,
+ defaultState: props.defaultChecked,
+ initialState: false,
+ })
+ const [indeterminate, setIndeterminate] = useAutoControlledValue({
+ state: props.indeterminate,
+ defaultState: props.defaultIndeterminate,
+ initialState: false,
+ })
+
+ const inputRef = useMergedRefs(React.useRef(), ref)
+ const labelRef = React.useRef()
+
+ const isClickFromMouse = React.useRef()
+
+ // ----------------------------------------
+ // Effects
+ // ----------------------------------------
+
+ useIsomorphicLayoutEffect(() => {
+ // Note: You can't directly set the indeterminate prop on the input, so we
+ // need to maintain a ref to the input and set it manually whenever the
+ // component updates.
+ if (inputRef.current) {
+ inputRef.current.indeterminate = !!indeterminate
+ }
+ })
- componentDidMount() {
- this.setIndeterminate()
- }
+ // ----------------------------------------
+ // Helpers
+ // ----------------------------------------
- componentDidUpdate() {
- this.setIndeterminate()
+ const canToggle = () => {
+ return !disabled && !readOnly && !(radio && checked)
}
- canToggle = () => {
- const { disabled, radio, readOnly } = this.props
- const { checked } = this.state
+ const computeTabIndex = () => {
+ if (!_.isNil(tabIndex)) {
+ return tabIndex
+ }
- return !disabled && !readOnly && !(radio && checked)
+ return disabled ? -1 : 0
}
- computeTabIndex = () => {
- const { disabled, tabIndex } = this.props
+ // ----------------------------------------
+ // Handlers
+ // ----------------------------------------
- if (!_.isNil(tabIndex)) return tabIndex
- return disabled ? -1 : 0
+ const handleChange = (e) => {
+ if (!canToggle()) {
+ return
+ }
+
+ debug('handleChange()', _.get(e, 'target.tagName'))
+
+ _.invoke(props, 'onChange', e, {
+ ...props,
+ checked: !checked,
+ indeterminate: false,
+ })
+ setChecked(!checked)
+ setIndeterminate(false)
}
- handleClick = (e) => {
+ const handleClick = (e) => {
debug('handleClick()', _.get(e, 'target.tagName'))
- const { id } = this.props
- const { checked, indeterminate } = this.state
- const isInputClick = _.invoke(this.inputRef.current, 'contains', e.target)
- const isLabelClick = _.invoke(this.labelRef.current, 'contains', e.target)
+ const isInputClick = _.invoke(inputRef.current, 'contains', e.target)
+ const isLabelClick = _.invoke(labelRef.current, 'contains', e.target)
const isRootClick = !isLabelClick && !isInputClick
const hasId = !_.isNil(id)
@@ -63,23 +117,23 @@ export default class Checkbox extends Component {
// /~https://github.com/Semantic-Org/Semantic-UI-React/pull/3351
if (!isLabelClickAndForwardedToInput) {
- _.invoke(this.props, 'onClick', e, {
- ...this.props,
+ _.invoke(props, 'onClick', e, {
+ ...props,
checked: !checked,
indeterminate: !!indeterminate,
})
}
- if (this.isClickFromMouse) {
- this.isClickFromMouse = false
+ if (isClickFromMouse.current) {
+ isClickFromMouse.current = false
if (isLabelClick && !hasId) {
- this.handleChange(e)
+ handleChange(e)
}
// Changes should be triggered for the slider variation
if (isRootClick) {
- this.handleChange(e)
+ handleChange(e)
}
if (isLabelClick && hasId) {
@@ -90,32 +144,17 @@ export default class Checkbox extends Component {
}
}
- handleChange = (e) => {
- const { checked } = this.state
-
- if (!this.canToggle()) return
- debug('handleChange()', _.get(e, 'target.tagName'))
-
- _.invoke(this.props, 'onChange', e, {
- ...this.props,
- checked: !checked,
- indeterminate: false,
- })
- this.setState({ checked: !checked, indeterminate: false })
- }
-
- handleMouseDown = (e) => {
+ const handleMouseDown = (e) => {
debug('handleMouseDown()')
- const { checked, indeterminate } = this.state
- _.invoke(this.props, 'onMouseDown', e, {
- ...this.props,
+ _.invoke(props, 'onMouseDown', e, {
+ ...props,
checked: !!checked,
indeterminate: !!indeterminate,
})
if (!e.defaultPrevented) {
- _.invoke(this.inputRef.current, 'focus')
+ _.invoke(inputRef.current, 'focus')
}
// Heads up!
@@ -123,98 +162,75 @@ export default class Checkbox extends Component {
e.preventDefault()
}
- handleMouseUp = (e) => {
+ const handleMouseUp = (e) => {
debug('handleMouseUp()')
- const { checked, indeterminate } = this.state
- this.isClickFromMouse = true
- _.invoke(this.props, 'onMouseUp', e, {
- ...this.props,
+ isClickFromMouse.current = true
+ _.invoke(props, 'onMouseUp', e, {
+ ...props,
checked: !!checked,
indeterminate: !!indeterminate,
})
}
- // Note: You can't directly set the indeterminate prop on the input, so we
- // need to maintain a ref to the input and set it manually whenever the
- // component updates.
- setIndeterminate = () => {
- const { indeterminate } = this.state
-
- _.set(this.inputRef, 'current.indeterminate', !!indeterminate)
- }
-
- render() {
- const {
- className,
- disabled,
- label,
- id,
- name,
- radio,
- readOnly,
- slider,
- toggle,
- type,
- value,
- } = this.props
- const { checked, indeterminate } = this.state
-
- const classes = cx(
- 'ui',
- useKeyOnly(checked, 'checked'),
- useKeyOnly(disabled, 'disabled'),
- useKeyOnly(indeterminate, 'indeterminate'),
- // auto apply fitted class to compact white space when there is no label
- // https://semantic-ui.com/modules/checkbox.html#fitted
- useKeyOnly(_.isNil(label), 'fitted'),
- useKeyOnly(radio, 'radio'),
- useKeyOnly(readOnly, 'read-only'),
- useKeyOnly(slider, 'slider'),
- useKeyOnly(toggle, 'toggle'),
- 'checkbox',
- className,
- )
- const unhandled = getUnhandledProps(Checkbox, this.props)
- const ElementType = getElementType(Checkbox, this.props)
- const [htmlInputProps, rest] = partitionHTMLProps(unhandled, { htmlProps: htmlInputAttrs })
-
- // Heads Up!
- // Do not remove empty labels, they are required by SUI CSS
- const labelElement = createHTMLLabel(label, {
- defaultProps: { htmlFor: id },
- autoGenerateKey: false,
- }) ||
-
- return (
-
- [
-
- ]
- [{labelElement}]
-
- )
- }
-}
-
+ // ----------------------------------------
+ // Render
+ // ----------------------------------------
+
+ const classes = cx(
+ 'ui',
+ useKeyOnly(checked, 'checked'),
+ useKeyOnly(disabled, 'disabled'),
+ useKeyOnly(indeterminate, 'indeterminate'),
+ // auto apply fitted class to compact white space when there is no label
+ // https://semantic-ui.com/modules/checkbox.html#fitted
+ useKeyOnly(_.isNil(label), 'fitted'),
+ useKeyOnly(radio, 'radio'),
+ useKeyOnly(readOnly, 'read-only'),
+ useKeyOnly(slider, 'slider'),
+ useKeyOnly(toggle, 'toggle'),
+ 'checkbox',
+ className,
+ )
+ const unhandled = getUnhandledProps(Checkbox, props)
+ const ElementType = getElementType(Checkbox, props)
+ const [htmlInputProps, rest] = partitionHTMLProps(unhandled, { htmlProps: htmlInputAttrs })
+
+ // Heads Up!
+ // Do not remove empty labels, they are required by SUI CSS
+ const labelElement = createHTMLLabel(label, {
+ defaultProps: { htmlFor: id },
+ autoGenerateKey: false,
+ }) ||
+
+ return (
+
+
+ {React.cloneElement(labelElement, { ref: labelRef })}
+
+ )
+})
+
+Checkbox.displayName = 'Checkbox'
Checkbox.propTypes = {
/** An element type to render as (string or function). */
as: PropTypes.elementType,
@@ -307,4 +323,4 @@ Checkbox.defaultProps = {
type: 'checkbox',
}
-Checkbox.autoControlledProps = ['checked', 'indeterminate']
+export default Checkbox
diff --git a/src/modules/Embed/Embed.js b/src/modules/Embed/Embed.js
index bc13b44071..e691507927 100644
--- a/src/modules/Embed/Embed.js
+++ b/src/modules/Embed/Embed.js
@@ -4,31 +4,43 @@ import PropTypes from 'prop-types'
import React from 'react'
import {
- ModernAutoControlledComponent as Component,
childrenUtils,
createHTMLIframe,
customPropTypes,
getElementType,
getUnhandledProps,
useKeyOnly,
+ useAutoControlledValue,
} from '../../lib'
import Icon from '../../elements/Icon'
/**
* An embed displays content from other websites like YouTube videos or Google Maps.
*/
-export default class Embed extends Component {
- getSrc() {
- const {
- autoplay = true,
- brandedUI = false,
- color = '#444444',
- hd = true,
- id,
- source,
- url,
- } = this.props
-
+const Embed = React.forwardRef(function (props, ref) {
+ const {
+ aspectRatio,
+ autoplay = true,
+ brandedUI = false,
+ children,
+ className,
+ color = '#444444',
+ content,
+ hd = true,
+ icon,
+ id,
+ iframe,
+ placeholder,
+ source,
+ url,
+ } = props
+ const [active, setActive] = useAutoControlledValue({
+ state: props.active,
+ defaultState: props.defaultActive,
+ initialState: false,
+ })
+
+ const getSrc = () => {
if (source === 'youtube') {
return [
`//www.youtube.com/embed/${id}`,
@@ -57,49 +69,35 @@ export default class Embed extends Component {
return url
}
- handleClick = (e) => {
- const { active } = this.state
-
- _.invoke(this.props, 'onClick', e, { ...this.props, active: true })
- if (!active) this.setState({ active: true })
+ const handleClick = (e) => {
+ _.invoke(props, 'onClick', e, { ...props, active: true })
+ if (!active) {
+ setActive(true)
+ }
}
- render() {
- const { aspectRatio, className, icon, placeholder } = this.props
- const { active } = this.state
-
- const classes = cx('ui', aspectRatio, useKeyOnly(active, 'active'), 'embed', className)
- const rest = getUnhandledProps(Embed, this.props)
- const ElementType = getElementType(Embed, this.props)
-
- const iconShorthand = icon !== undefined ? icon : 'video play'
-
- return (
-
- {Icon.create(iconShorthand, { autoGenerateKey: false })}
- {placeholder && }
- {this.renderEmbed()}
-
- )
- }
+ const renderEmbed = () => {
+ if (!active) {
+ return null
+ }
- renderEmbed() {
- const { children, content, iframe, source } = this.props
- const { active } = this.state
+ if (!childrenUtils.isNil(children)) {
+ return
{children}
+ }
- if (!active) return null
- if (!childrenUtils.isNil(children)) return {children}
- if (!childrenUtils.isNil(content)) return {content}
+ if (!childrenUtils.isNil(content)) {
+ return {content}
+ }
return (
- {createHTMLIframe(childrenUtils.isNil(iframe) ? this.getSrc() : iframe, {
+ {createHTMLIframe(childrenUtils.isNil(iframe) ? getSrc() : iframe, {
defaultProps: {
allowFullScreen: false,
frameBorder: 0,
height: '100%',
scrolling: 'no',
- src: this.getSrc(),
+ src: getSrc(),
title: `Embedded content from ${source}.`,
width: '100%',
},
@@ -108,8 +106,23 @@ export default class Embed extends Component {
)
}
-}
+ const classes = cx('ui', aspectRatio, useKeyOnly(active, 'active'), 'embed', className)
+ const rest = getUnhandledProps(Embed, props)
+ const ElementType = getElementType(Embed, props)
+
+ const iconShorthand = icon !== undefined ? icon : 'video play'
+
+ return (
+
+ {Icon.create(iconShorthand, { autoGenerateKey: false })}
+ {placeholder && }
+ {renderEmbed()}
+
+ )
+})
+
+Embed.displayName = 'Embed'
Embed.propTypes = {
/** An element type to render as (string or function). */
as: PropTypes.elementType,
@@ -177,4 +190,4 @@ Embed.propTypes = {
url: customPropTypes.every([customPropTypes.disallow(['source']), PropTypes.string]),
}
-Embed.autoControlledProps = ['active']
+export default Embed
diff --git a/src/modules/Progress/Progress.js b/src/modules/Progress/Progress.js
index d9c08dc8e2..6e26f4afd1 100644
--- a/src/modules/Progress/Progress.js
+++ b/src/modules/Progress/Progress.js
@@ -1,7 +1,7 @@
import cx from 'clsx'
import _ from 'lodash'
import PropTypes from 'prop-types'
-import React, { Component } from 'react'
+import React from 'react'
import {
childrenUtils,
@@ -15,105 +15,150 @@ import {
} from '../../lib'
/**
- * A progress bar shows the progression of a task.
+ * @param {Number|String} percent
+ * @param {Number|String} total
+ * @param {Number|String} value
+ *
+ * @return {Number|String}
*/
-class Progress extends Component {
- calculatePercent = () => {
- const { percent, total, value } = this.props
+function calculatePercent(percent, total, value) {
+ if (!_.isUndefined(percent)) {
+ return percent
+ }
- if (!_.isUndefined(percent)) return percent
- if (!_.isUndefined(total) && !_.isUndefined(value)) return (value / total) * 100
+ if (!_.isUndefined(total) && !_.isUndefined(value)) {
+ return (value / total) * 100
}
- computeValueText = (percent) => {
- const { progress, total, value } = this.props
+ return 0
+}
+
+/**
+ * @param {Number|String} percent
+ * @param {Number|String} total
+ * @param {Number|String} value
+ * @param {Boolean|'percent'|'ratio'|'value'} progress
+ * @param {Number} precision
+ *
+ * @return {Number}
+ */
+function getPercent(percent, total, value, progress, precision) {
+ const clampedPercent = _.clamp(calculatePercent(percent, total, value), 0, 100)
- if (progress === 'value') return value
- if (progress === 'ratio') return `${value}/${total}`
- return `${percent}%`
+ if (!_.isUndefined(total) && !_.isUndefined(value) && progress === 'value') {
+ return (value / total) * 100
}
- getPercent = () => {
- const { precision, progress, total, value } = this.props
- const percent = _.clamp(this.calculatePercent(), 0, 100)
+ if (progress === 'value') {
+ return value
+ }
- if (!_.isUndefined(total) && !_.isUndefined(value) && progress === 'value') {
- return (value / total) * 100
- }
- if (progress === 'value') return value
- if (_.isUndefined(precision)) return percent
- return _.round(percent, precision)
+ if (_.isUndefined(precision)) {
+ return clampedPercent
}
- isAutoSuccess = () => {
- const { autoSuccess, percent, total, value } = this.props
+ return _.round(clampedPercent, precision)
+}
- return autoSuccess && (percent >= 100 || value >= total)
+/**
+ * A progress bar shows the progression of a task.
+ */
+const Progress = React.forwardRef(function (props, ref) {
+ const {
+ active,
+ autoSuccess,
+ attached,
+ children,
+ className,
+ color,
+ content,
+ disabled,
+ error,
+ indicating,
+ inverted,
+ label,
+ percent,
+ precision,
+ progress,
+ total,
+ size,
+ success,
+ value,
+ warning,
+ } = props
+
+ const calculatedPercent = getPercent(percent, total, value, progress, precision) || 0
+ const isAutoSuccess = autoSuccess && (percent >= 100 || value >= total)
+
+ const computeValueText = () => {
+ if (progress === 'value') {
+ return value
+ }
+
+ if (progress === 'ratio') {
+ return `${value}/${total}`
+ }
+
+ return `${calculatedPercent}%`
}
- renderLabel = () => {
- const { children, content, label } = this.props
+ const renderLabel = () => {
+ if (!childrenUtils.isNil(children)) {
+ return {children}
+ }
+
+ if (!childrenUtils.isNil(content)) {
+ return {content}
+ }
- if (!childrenUtils.isNil(children)) return {children}
- if (!childrenUtils.isNil(content)) return {content}
return createHTMLDivision(label, {
autoGenerateKey: false,
defaultProps: { className: 'label' },
})
}
- renderProgress = (percent) => {
- const { precision, progress } = this.props
-
- if (!progress && _.isUndefined(precision)) return
- return {this.computeValueText(percent)}
- }
+ const renderProgress = () => {
+ if (!progress && _.isUndefined(precision)) {
+ return
+ }
- render() {
- const {
- active,
- attached,
- className,
- color,
- disabled,
- error,
- indicating,
- inverted,
- size,
- success,
- warning,
- } = this.props
-
- const classes = cx(
- 'ui',
- color,
- size,
- useKeyOnly(active || indicating, 'active'),
- useKeyOnly(disabled, 'disabled'),
- useKeyOnly(error, 'error'),
- useKeyOnly(indicating, 'indicating'),
- useKeyOnly(inverted, 'inverted'),
- useKeyOnly(success || this.isAutoSuccess(), 'success'),
- useKeyOnly(warning, 'warning'),
- useValueAndKey(attached, 'attached'),
- 'progress',
- className,
- )
- const rest = getUnhandledProps(Progress, this.props)
- const ElementType = getElementType(Progress, this.props)
- const percent = this.getPercent() || 0
-
- return (
-
-
- {this.renderProgress(percent)}
-
- {this.renderLabel()}
-
- )
+ return {computeValueText()}
}
-}
+ const classes = cx(
+ 'ui',
+ color,
+ size,
+ useKeyOnly(active || indicating, 'active'),
+ useKeyOnly(disabled, 'disabled'),
+ useKeyOnly(error, 'error'),
+ useKeyOnly(indicating, 'indicating'),
+ useKeyOnly(inverted, 'inverted'),
+ useKeyOnly(success || isAutoSuccess, 'success'),
+ useKeyOnly(warning, 'warning'),
+ useValueAndKey(attached, 'attached'),
+ 'progress',
+ className,
+ )
+ const rest = getUnhandledProps(Progress, props)
+ const ElementType = getElementType(Progress, props)
+
+ return (
+
+
+ {renderProgress()}
+
+ {renderLabel()}
+
+ )
+})
+
+Progress.displayName = 'Progress'
Progress.propTypes = {
/** An element type to render as (string or function). */
as: PropTypes.elementType,
diff --git a/test/specs/addons/Radio/Radio-test.js b/test/specs/addons/Radio/Radio-test.js
index aaf4ad215a..96826928df 100644
--- a/test/specs/addons/Radio/Radio-test.js
+++ b/test/specs/addons/Radio/Radio-test.js
@@ -6,6 +6,7 @@ import * as common from 'test/specs/commonTests'
describe('Radio', () => {
common.isConformant(Radio)
+ common.forwardsRef(Radio, { tagName: 'input' })
it('renders a radio Checkbox', () => {
const wrapper = shallow()
diff --git a/test/specs/addons/TextArea/TextArea-test.js b/test/specs/addons/TextArea/TextArea-test.js
index 295bf0cbcb..0ba2816f11 100644
--- a/test/specs/addons/TextArea/TextArea-test.js
+++ b/test/specs/addons/TextArea/TextArea-test.js
@@ -34,18 +34,17 @@ describe('TextArea', () => {
if (attachTo) document.body.removeChild(attachTo)
})
- common.isConformant(TextArea, {
- eventTargets: {
- onChange: 'textarea',
- },
- })
+ common.isConformant(TextArea)
+ common.forwardsRef(TextArea, { tagName: 'textarea' })
describe('focus', () => {
it('can be set via a ref', () => {
- wrapperMount()
+ const ref = React.createRef()
+
+ wrapperMount()
const element = document.querySelector('textarea')
- wrapper.instance().focus()
+ ref.current.focus()
document.activeElement.should.equal(element)
})
})
diff --git a/test/specs/modules/Checkbox/Checkbox-test.js b/test/specs/modules/Checkbox/Checkbox-test.js
index 3123b4c6e5..6103acd18f 100644
--- a/test/specs/modules/Checkbox/Checkbox-test.js
+++ b/test/specs/modules/Checkbox/Checkbox-test.js
@@ -24,6 +24,7 @@ const wrapperShallow = (...args) => (wrapper = shallow(...args))
describe('Checkbox', () => {
common.isConformant(Checkbox)
+ common.forwardsRef(Checkbox, { tagName: 'input' })
common.hasUIClassName(Checkbox)
common.propKeyOnlyToClassName(Checkbox, 'checked')
@@ -110,6 +111,7 @@ describe('Checkbox', () => {
domEvent.click(input)
input.indeterminate.should.be.true()
})
+
it('can not be indeterminate', () => {
wrapperMount()
const input = document.querySelector('.ui.checkbox input')
diff --git a/test/specs/modules/Embed/Embed-test.js b/test/specs/modules/Embed/Embed-test.js
index edab24d3ca..0401ee3c66 100644
--- a/test/specs/modules/Embed/Embed-test.js
+++ b/test/specs/modules/Embed/Embed-test.js
@@ -14,10 +14,9 @@ const assertIframeSrc = (props, srcPart) => {
describe('Embed', () => {
common.isConformant(Embed)
+ common.forwardsRef(Embed)
common.hasUIClassName(Embed)
- common.rendersChildren(Embed, {
- requiredProps: { active: true },
- })
+ common.rendersChildren(Embed, { requiredProps: { active: true } })
common.implementsHTMLIFrameProp(Embed, {
alwaysPresent: true,
diff --git a/test/specs/modules/Progress/Progress-test.js b/test/specs/modules/Progress/Progress-test.js
index 75d7a3f043..5c71fa6a01 100644
--- a/test/specs/modules/Progress/Progress-test.js
+++ b/test/specs/modules/Progress/Progress-test.js
@@ -7,6 +7,7 @@ import * as common from 'test/specs/commonTests'
describe('Progress', () => {
common.isConformant(Progress)
+ common.forwardsRef(Progress)
common.hasUIClassName(Progress)
common.rendersChildren(Progress)
@@ -41,26 +42,26 @@ describe('Progress', () => {
it('applies the success class when percent >= 100%', () => {
const wrapper = shallow()
- wrapper.setProps({ percent: 100, autoSuccess: true }).should.have.have.className('success')
+ wrapper.setProps({ percent: 100, autoSuccess: true })
+ wrapper.should.have.have.className('success')
- wrapper.setProps({ percent: 99, autoSuccess: true }).should.not.have.have.className('success')
+ wrapper.setProps({ percent: 99, autoSuccess: true })
+ wrapper.should.not.have.have.className('success')
- wrapper.setProps({ percent: 101, autoSuccess: true }).should.have.have.className('success')
+ wrapper.setProps({ percent: 101, autoSuccess: true })
+ wrapper.should.have.have.className('success')
})
it('applies the success class when value >= total', () => {
const wrapper = shallow()
- wrapper
- .setProps({ total: 1, value: 1, autoSuccess: true })
- .should.have.have.className('success')
+ wrapper.setProps({ total: 1, value: 1, autoSuccess: true })
+ wrapper.should.have.have.className('success')
- wrapper
- .setProps({ total: 1, value: 0, autoSuccess: true })
- .should.not.have.have.className('success')
+ wrapper.setProps({ total: 1, value: 0, autoSuccess: true })
+ wrapper.should.not.have.have.className('success')
- wrapper
- .setProps({ total: 1, value: 2, autoSuccess: true })
- .should.have.have.className('success')
+ wrapper.setProps({ total: 1, value: 2, autoSuccess: true })
+ wrapper.should.have.have.className('success')
})
})