diff --git a/package-lock.json b/package-lock.json
index 95a7e0f41..fa514c9f7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,7 +15,7 @@
"@edx/frontend-component-footer": "^13.0.2",
"@edx/frontend-component-header": "^5.0.2",
"@edx/frontend-enterprise-hotjar": "^2.0.0",
- "@edx/frontend-lib-content-components": "^2.1.1",
+ "@edx/frontend-lib-content-components": "^2.1.3",
"@edx/frontend-platform": "7.0.1",
"@edx/openedx-atlas": "^0.6.0",
"@fortawesome/fontawesome-svg-core": "1.2.36",
@@ -2632,9 +2632,9 @@
}
},
"node_modules/@edx/frontend-lib-content-components": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@edx/frontend-lib-content-components/-/frontend-lib-content-components-2.1.1.tgz",
- "integrity": "sha512-VCEhFfLkK+o08g7Ts9YgYNb8GHd6d9Mw8lTT1L2OIMsDC2ncFHBUGOfzmoRt+M3cJMb2nAL7Yh4wvNxhgRhhuA==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@edx/frontend-lib-content-components/-/frontend-lib-content-components-2.1.3.tgz",
+ "integrity": "sha512-RDlWyZ57Ecbz1qOZv2aHMSsWbwo2IoK06PHEXsEgZv0f1lmp25BqlDNhhipczcdg0te5K8gVR4qATZ4+EnhKWQ==",
"dependencies": {
"@codemirror/lang-html": "^6.0.0",
"@codemirror/lang-xml": "^6.0.0",
diff --git a/package.json b/package.json
index aa1dfc997..2c91d5ae8 100644
--- a/package.json
+++ b/package.json
@@ -42,7 +42,7 @@
"@edx/frontend-component-footer": "^13.0.2",
"@edx/frontend-component-header": "^5.0.2",
"@edx/frontend-enterprise-hotjar": "^2.0.0",
- "@edx/frontend-lib-content-components": "^2.1.1",
+ "@edx/frontend-lib-content-components": "^2.1.3",
"@edx/frontend-platform": "7.0.1",
"@edx/openedx-atlas": "^0.6.0",
"@fortawesome/fontawesome-svg-core": "1.2.36",
diff --git a/src/files-and-videos/generic/table-components/sort-and-filter-modal/SortAndFilterModal.jsx b/src/files-and-videos/generic/table-components/sort-and-filter-modal/SortAndFilterModal.jsx
index 14ce54f81..fef4b8c01 100644
--- a/src/files-and-videos/generic/table-components/sort-and-filter-modal/SortAndFilterModal.jsx
+++ b/src/files-and-videos/generic/table-components/sort-and-filter-modal/SortAndFilterModal.jsx
@@ -1,6 +1,8 @@
import React, { useContext, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n';
+// SelectableBox in paragon has a bug only visible on stage where you can't change selection. So we override it
+import { SelectableBox } from '@edx/frontend-lib-content-components';
import {
ActionRow,
Button,
@@ -9,7 +11,6 @@ import {
ModalDialog,
useCheckboxSetValues,
} from '@openedx/paragon';
-import SelectableBox from '../../../../generic/SelectableBox';
import messages from './messages';
import { getCheckedFilters, getFilterOptions, processFilters } from './utils';
diff --git a/src/generic/SelectableBox/FormCheckbox.jsx b/src/generic/SelectableBox/FormCheckbox.jsx
deleted file mode 100644
index d2e1951ba..000000000
--- a/src/generic/SelectableBox/FormCheckbox.jsx
+++ /dev/null
@@ -1,145 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import { useCheckboxSetContext } from './FormCheckboxSetContext';
-import { FormGroupContextProvider, useFormGroupContext } from './FormGroupContext';
-import FormLabel from './FormLabel';
-import FormControlFeedback from './FormControlFeedback';
-
-const CheckboxControl = React.forwardRef(
- ({ isIndeterminate, ...props }, ref) => {
- const { getCheckboxControlProps, hasCheckboxSetProvider } = useCheckboxSetContext();
- const defaultRef = React.useRef();
- const resolvedRef = ref || defaultRef;
- const { getControlProps } = useFormGroupContext();
- let checkboxProps = getControlProps({
- ...props,
- className: classNames('pgn__form-checkbox-input', props.className),
- });
-
- if (hasCheckboxSetProvider) {
- checkboxProps = getCheckboxControlProps(checkboxProps);
- }
-
- React.useEffect(() => {
- // this if(resolvedRef.current) prevents console errors in testing
- if (resolvedRef.current) {
- resolvedRef.current.indeterminate = isIndeterminate;
- }
- }, [resolvedRef, isIndeterminate]);
-
- return (
-
- );
- },
-);
-
-CheckboxControl.propTypes = {
- /** Specifies whether the checkbox should be rendered in indeterminate state. */
- isIndeterminate: PropTypes.bool,
- /** Specifies class name to append to the base element. */
- className: PropTypes.string,
-};
-
-CheckboxControl.defaultProps = {
- isIndeterminate: false,
- className: undefined,
-};
-
-const FormCheckbox = React.forwardRef(({
- children,
- className,
- controlClassName,
- labelClassName,
- description,
- isInvalid,
- isValid,
- controlAs,
- floatLabelLeft,
- ...props
-}, ref) => {
- const { hasCheckboxSetProvider } = useCheckboxSetContext();
- const { hasFormGroupProvider, useSetIsControlGroupEffect, getControlProps } = useFormGroupContext();
- useSetIsControlGroupEffect(true);
- const shouldActAsGroup = hasFormGroupProvider && !hasCheckboxSetProvider;
- const groupProps = shouldActAsGroup ? {
- ...getControlProps({}),
- role: 'group',
- } : {};
-
- const control = React.createElement(controlAs, { ...props, className: controlClassName, ref });
- return (
-
-
- {control}
-
-
- {children}
-
- {description && (
-
- {description}
-
- )}
-
-
-
- );
-});
-
-FormCheckbox.propTypes = {
- /** Specifies id of the FormCheckbox component. */
- id: PropTypes.string,
- /** Specifies contents of the component. */
- children: PropTypes.node.isRequired,
- /** Specifies class name to append to the base element. */
- className: PropTypes.string,
- /** Specifies class name for control component. */
- controlClassName: PropTypes.string,
- /** Specifies class name for label component. */
- labelClassName: PropTypes.string,
- /** Specifies description to show under the checkbox. */
- description: PropTypes.node,
- /** Specifies whether to display checkbox in invalid state, this affects styling. */
- isInvalid: PropTypes.bool,
- /** Specifies whether to display checkbox in valid state, this affects styling. */
- isValid: PropTypes.bool,
- /** Specifies control element. */
- controlAs: PropTypes.elementType,
- /** Specifies whether the floating label should be aligned to the left. */
- floatLabelLeft: PropTypes.bool,
- /** Specifies whether the `FormCheckbox` is disabled. */
- disabled: PropTypes.bool,
-};
-
-FormCheckbox.defaultProps = {
- id: undefined,
- className: undefined,
- controlClassName: undefined,
- labelClassName: undefined,
- description: undefined,
- isInvalid: false,
- isValid: false,
- controlAs: CheckboxControl,
- floatLabelLeft: false,
- disabled: false,
-};
-
-export { CheckboxControl };
-export default FormCheckbox;
diff --git a/src/generic/SelectableBox/FormCheckboxSet.jsx b/src/generic/SelectableBox/FormCheckboxSet.jsx
deleted file mode 100644
index 2d90cada0..000000000
--- a/src/generic/SelectableBox/FormCheckboxSet.jsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { useFormGroupContext } from './FormGroupContext';
-import { FormCheckboxSetContextProvider } from './FormCheckboxSetContext';
-import FormControlSet from './FormControlSet';
-
-const FormCheckboxSet = ({
- children,
- name,
- value,
- defaultValue,
- isInline,
- onChange,
- onFocus,
- onBlur,
- ...props
-}) => {
- const { getControlProps, useSetIsControlGroupEffect } = useFormGroupContext();
- useSetIsControlGroupEffect(true);
- const controlProps = getControlProps(props);
- return (
-
-
- {children}
-
-
- );
-};
-
-FormCheckboxSet.propTypes = {
- /** Specifies contents of the component. */
- children: PropTypes.node.isRequired,
- /** Specifies class name to append to the base element. */
- className: PropTypes.string,
- /** Specifies name for the component. */
- name: PropTypes.string.isRequired,
- /** Specifies values for the checkboxes. */
- value: PropTypes.arrayOf(PropTypes.string),
- /** Specifies default values for the checkboxes. */
- defaultValue: PropTypes.arrayOf(PropTypes.string),
- /** Specifies whether to display components with inline styling. */
- isInline: PropTypes.bool,
- /** Specifies onChange event handler. */
- onChange: PropTypes.func,
- /** Specifies onFocus event handler. */
- onFocus: PropTypes.func,
- /** Specifies onBlur event handler. */
- onBlur: PropTypes.func,
-};
-
-FormCheckboxSet.defaultProps = {
- className: undefined,
- value: undefined,
- defaultValue: undefined,
- isInline: false,
- onChange: undefined,
- onFocus: undefined,
- onBlur: undefined,
-};
-
-export default FormCheckboxSet;
diff --git a/src/generic/SelectableBox/FormCheckboxSetContext.jsx b/src/generic/SelectableBox/FormCheckboxSetContext.jsx
deleted file mode 100644
index 1dd45b524..000000000
--- a/src/generic/SelectableBox/FormCheckboxSetContext.jsx
+++ /dev/null
@@ -1,77 +0,0 @@
-import React, { useContext } from 'react';
-import PropTypes from 'prop-types';
-import { callAllHandlers } from './fieldUtils';
-
-const identityFn = props => props;
-
-const FormCheckboxSetContext = React.createContext({
- getCheckboxControlProps: identityFn,
- hasCheckboxSetProvider: false,
-});
-
-const useCheckboxSetContext = () => useContext(FormCheckboxSetContext);
-
-const FormCheckboxSetContextProvider = ({
- children,
- name,
- onBlur,
- onFocus,
- onChange,
- value,
- defaultValue,
-}) => {
- const isControlled = !defaultValue && Array.isArray(value);
- const getCheckboxControlProps = (checkboxProps) => ({
- ...checkboxProps,
- name,
- /* istanbul ignore next */
- onBlur: checkboxProps.onBlur ? callAllHandlers(onBlur, checkboxProps.onBlur) : onBlur,
- /* istanbul ignore next */
- onFocus: checkboxProps.onFocus ? callAllHandlers(onFocus, checkboxProps.onFocus) : onFocus,
- /* istanbul ignore next */
- onChange: checkboxProps.onChange ? callAllHandlers(onChange, checkboxProps.onChange) : onChange,
- checked: isControlled ? value.includes(checkboxProps.value) : undefined,
- defaultChecked: isControlled ? undefined : (defaultValue && defaultValue.includes(checkboxProps.value)),
- });
- // eslint-disable-next-line react/jsx-no-constructed-context-values
- const contextValue = {
- name,
- value,
- defaultValue,
- getCheckboxControlProps,
- onBlur,
- onFocus,
- onChange,
- hasCheckboxSetProvider: true,
- };
- return (
-
- {children}
-
- );
-};
-
-FormCheckboxSetContextProvider.propTypes = {
- children: PropTypes.node.isRequired,
- name: PropTypes.string,
- onBlur: PropTypes.func,
- onFocus: PropTypes.func,
- onChange: PropTypes.func,
- value: PropTypes.arrayOf(PropTypes.string),
- defaultValue: PropTypes.arrayOf(PropTypes.string),
-};
-
-FormCheckboxSetContextProvider.defaultProps = {
- onBlur: undefined,
- name: undefined,
- onFocus: undefined,
- onChange: undefined,
- value: undefined,
- defaultValue: undefined,
-};
-
-export default FormCheckboxSetContext;
-export {
- useCheckboxSetContext,
- FormCheckboxSetContextProvider,
-};
diff --git a/src/generic/SelectableBox/FormControlFeedback.jsx b/src/generic/SelectableBox/FormControlFeedback.jsx
deleted file mode 100644
index b4e211218..000000000
--- a/src/generic/SelectableBox/FormControlFeedback.jsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import { useFormGroupContext } from './FormGroupContext';
-import FormText, { resolveTextType } from './FormText';
-
-const FormControlFeedback = ({ children, ...props }) => {
- const { getDescriptorProps, isInvalid, isValid } = useFormGroupContext();
- const descriptorProps = getDescriptorProps(props);
- const className = classNames('pgn__form-control-description', props.className);
- const textType = props.type || resolveTextType({ isInvalid, isValid });
- return (
-
- {children}
-
- );
-};
-
-const FEEDBACK_TYPES = [
- 'default',
- 'valid',
- 'invalid',
- 'warning',
- 'criteria-empty',
- 'criteria-valid',
- 'criteria-invalid',
-];
-
-FormControlFeedback.propTypes = {
- /** Specifies contents of the component. */
- children: PropTypes.node.isRequired,
- /** Specifies class name to append to the base element. */
- className: PropTypes.string,
- /** Specifies whether to show an icon next to the text. */
- hasIcon: PropTypes.bool,
- /** Specifies feedback type, this affects styling. */
- type: PropTypes.oneOf(FEEDBACK_TYPES),
- /** Specifies icon to show, will only be shown if `hasIcon` prop is set to `true`. */
- icon: PropTypes.node,
- /** Specifies whether to show feedback with muted styling. */
- muted: PropTypes.bool,
-};
-
-FormControlFeedback.defaultProps = {
- hasIcon: true,
- type: undefined,
- icon: undefined,
- className: undefined,
- muted: false,
-};
-
-export default FormControlFeedback;
diff --git a/src/generic/SelectableBox/FormControlSet.jsx b/src/generic/SelectableBox/FormControlSet.jsx
deleted file mode 100644
index 69052e767..000000000
--- a/src/generic/SelectableBox/FormControlSet.jsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-
-const FormControlSet = ({
- as,
- className,
- isInline,
- children,
- ...props
-}) => React.createElement(as, {
- className: classNames(
- className,
- {
- 'pgn__form-control-set': !isInline,
- 'pgn__form-control-set-inline': isInline,
- },
- ),
- ...props,
-}, children);
-
-FormControlSet.propTypes = {
- /** Specifies the base element */
- as: PropTypes.elementType,
- /** A class name to append to the base element. */
- className: PropTypes.string,
- /** Specifies whether the component should be displayed with inline styling. */
- isInline: PropTypes.bool,
- /** Specifies contents of the component. */
- children: PropTypes.node,
-};
-
-FormControlSet.defaultProps = {
- as: 'div',
- className: undefined,
- isInline: false,
- children: null,
-};
-
-export default FormControlSet;
diff --git a/src/generic/SelectableBox/FormGroupContext.jsx b/src/generic/SelectableBox/FormGroupContext.jsx
deleted file mode 100644
index af38a4f8a..000000000
--- a/src/generic/SelectableBox/FormGroupContext.jsx
+++ /dev/null
@@ -1,121 +0,0 @@
-import React, {
- useState, useEffect, useMemo, useCallback,
-} from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import newId from './newId';
-import { useIdList, omitUndefinedProperties } from './fieldUtils';
-import { FORM_CONTROL_SIZES } from './constants';
-
-const identityFn = props => props;
-const noop = () => {};
-
-const FormGroupContext = React.createContext({
- getControlProps: identityFn,
- useSetIsControlGroupEffect: noop,
- getLabelProps: identityFn,
- getDescriptorProps: identityFn,
- hasFormGroupProvider: false,
-});
-
-const useFormGroupContext = () => React.useContext(FormGroupContext);
-
-const useStateEffect = (initialState) => {
- const [state, setState] = useState(initialState);
- const useSetStateEffect = (newState) => {
- useEffect(() => setState(newState), [newState]);
- };
- return [state, useSetStateEffect];
-};
-
-const FormGroupContextProvider = ({
- children,
- controlId: explicitControlId,
- isInvalid,
- isValid,
- size,
-}) => {
- const controlId = useMemo(() => explicitControlId || newId('form-field'), [explicitControlId]);
- const [describedByIds, registerDescriptorId] = useIdList(controlId);
- const [labelledByIds, registerLabelerId] = useIdList(controlId);
- const [isControlGroup, useSetIsControlGroupEffect] = useStateEffect(false);
-
- const getControlProps = useCallback((controlProps) => {
- // labelledByIds from the list above should only be added to a control
- // if it the control is a group. We prefer adding a condition here because:
- // - Hooks cannot be called inside conditionals
- // - The getLabelProps function below is forced to generate an id
- // whether it is needed or not.
- // - This is what allows consumers of Paragon to use
- // interchangeably between ControlGroup type controls and regular Controls
- const labelledByIdsForControl = isControlGroup ? labelledByIds : undefined;
- return omitUndefinedProperties({
- ...controlProps,
- 'aria-describedby': classNames(controlProps['aria-describedby'], describedByIds) || undefined,
- 'aria-labelledby': classNames(controlProps['aria-labelledby'], labelledByIdsForControl) || undefined,
- id: controlId,
- });
- }, [
- isControlGroup,
- describedByIds,
- labelledByIds,
- controlId,
- ]);
-
- const getLabelProps = (labelProps) => {
- const id = registerLabelerId(labelProps?.id);
- if (isControlGroup) {
- return { ...labelProps, id };
- }
- return { ...labelProps, htmlFor: controlId };
- };
-
- const getDescriptorProps = (descriptorProps) => {
- const id = registerDescriptorId(descriptorProps?.id);
- return { ...descriptorProps, id };
- };
-
- // eslint-disable-next-line react/jsx-no-constructed-context-values
- const contextValue = {
- getControlProps,
- getLabelProps,
- getDescriptorProps,
- useSetIsControlGroupEffect,
- isControlGroup,
- controlId,
- isInvalid,
- isValid,
- size,
- hasFormGroupProvider: true,
- };
-
- return (
-
- {children}
-
- );
-};
-
-FormGroupContextProvider.propTypes = {
- children: PropTypes.node.isRequired,
- controlId: PropTypes.string,
- isInvalid: PropTypes.bool,
- isValid: PropTypes.bool,
- size: PropTypes.oneOf([
- FORM_CONTROL_SIZES.SMALL,
- FORM_CONTROL_SIZES.LARGE,
- ]),
-};
-
-FormGroupContextProvider.defaultProps = {
- controlId: undefined,
- isInvalid: undefined,
- isValid: undefined,
- size: undefined,
-};
-
-export {
- FormGroupContext,
- FormGroupContextProvider,
- useFormGroupContext,
-};
diff --git a/src/generic/SelectableBox/FormLabel.jsx b/src/generic/SelectableBox/FormLabel.jsx
deleted file mode 100644
index 7f45bb9bc..000000000
--- a/src/generic/SelectableBox/FormLabel.jsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import { useFormGroupContext } from './FormGroupContext';
-import { FORM_CONTROL_SIZES } from './constants';
-
-const FormLabel = ({ children, isInline, ...props }) => {
- const { size, isControlGroup, getLabelProps } = useFormGroupContext();
- const className = classNames(
- 'pgn__form-label',
- {
- 'pgn__form-label-inline': isInline,
- 'pgn__form-label-lg': size === FORM_CONTROL_SIZES.LARGE,
- 'pgn__form-label-sm': size === FORM_CONTROL_SIZES.SMALL,
- },
- props.className,
- );
- const labelProps = getLabelProps({ ...props, className });
- const componentType = isControlGroup ? 'p' : 'label';
- return React.createElement(componentType, labelProps, children);
-};
-
-const SIZE_CHOICES = ['sm', 'lg'];
-
-FormLabel.propTypes = {
- /** Specifies class name to append to the base element. */
- className: PropTypes.string,
- /** Specifies contents of the component. */
- children: PropTypes.node.isRequired,
- /** Specifies whether the component should be displayed with inline styling. */
- isInline: PropTypes.bool,
- /** Specifies size of the component. */
- size: PropTypes.oneOf(SIZE_CHOICES),
-};
-
-FormLabel.defaultProps = {
- isInline: false,
- size: undefined,
- className: undefined,
-};
-
-export default FormLabel;
diff --git a/src/generic/SelectableBox/FormRadio.jsx b/src/generic/SelectableBox/FormRadio.jsx
deleted file mode 100644
index 1609f8266..000000000
--- a/src/generic/SelectableBox/FormRadio.jsx
+++ /dev/null
@@ -1,112 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import { useRadioSetContext } from './FormRadioSetContext';
-import { FormGroupContextProvider, useFormGroupContext } from './FormGroupContext';
-import FormLabel from './FormLabel';
-import FormControlFeedback from './FormControlFeedback';
-
-const RadioControl = React.forwardRef((props, ref) => {
- const { getControlProps } = useFormGroupContext();
- const { getRadioControlProps, hasRadioSetProvider } = useRadioSetContext();
- let radioProps = getControlProps({
- ...props,
- className: classNames('pgn__form-radio-input', props.className),
- });
-
- if (hasRadioSetProvider) {
- radioProps = getRadioControlProps(radioProps);
- }
-
- const onChange = (...args) => {
- // eslint-disable-next-line no-console
- console.log('RadioControl.onChange called with args: ', args);
- if (radioProps.onChange) {
- radioProps.onChange(...args);
- }
- };
-
- return (
-
- );
-});
-
-RadioControl.propTypes = {
- className: PropTypes.string,
-};
-
-RadioControl.defaultProps = {
- className: undefined,
-};
-
-const FormRadio = React.forwardRef(({
- children,
- className,
- controlClassName,
- labelClassName,
- description,
- isInvalid,
- isValid,
- ...props
-}, ref) => (
-
-
-
-
-
- {children}
-
- {description && (
-
- {description}
-
- )}
-
-
-
-));
-
-FormRadio.propTypes = {
- /** Specifies id of the FormRadio component. */
- id: PropTypes.string,
- /** Specifies contents of the component. */
- children: PropTypes.node.isRequired,
- /** Specifies class name to append to the base element. */
- className: PropTypes.string,
- /** Specifies class name for control component. */
- controlClassName: PropTypes.string,
- /** Specifies class name for label component. */
- labelClassName: PropTypes.string,
- /** Specifies description to show under the radio's value. */
- description: PropTypes.node,
- /** Specifies whether to display component in invalid state, this affects styling. */
- isInvalid: PropTypes.bool,
- /** Specifies whether to display component in valid state, this affects styling. */
- isValid: PropTypes.bool,
- /** Specifies whether the `FormRadio` is disabled. */
- disabled: PropTypes.bool,
-};
-
-FormRadio.defaultProps = {
- id: undefined,
- className: undefined,
- controlClassName: undefined,
- labelClassName: undefined,
- description: undefined,
- isInvalid: false,
- isValid: false,
- disabled: false,
-};
-
-export { RadioControl };
-export default FormRadio;
diff --git a/src/generic/SelectableBox/FormRadioSet.jsx b/src/generic/SelectableBox/FormRadioSet.jsx
deleted file mode 100644
index 05524ba20..000000000
--- a/src/generic/SelectableBox/FormRadioSet.jsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { useFormGroupContext } from './FormGroupContext';
-import { FormRadioSetContextProvider } from './FormRadioSetContext';
-import FormControlSet from './FormControlSet';
-
-const FormRadioSet = ({
- children,
- name,
- value,
- defaultValue,
- isInline,
- onChange,
- onFocus,
- onBlur,
- ...props
-}) => {
- const { getControlProps, useSetIsControlGroupEffect } = useFormGroupContext();
- useSetIsControlGroupEffect(true);
- const controlProps = getControlProps(props);
- return (
-
-
- {children}
-
-
- );
-};
-
-FormRadioSet.propTypes = {
- /** Specifies contents of the component. */
- children: PropTypes.node.isRequired,
- /** A class name to append to the base element. */
- className: PropTypes.string,
- /** Specifies name for the component. */
- name: PropTypes.string.isRequired,
- /** Specifies values for the FormRadioSet. */
- value: PropTypes.string,
- /** Specifies default values. */
- defaultValue: PropTypes.string,
- /** Specifies whether the component should be displayed with inline styling. */
- isInline: PropTypes.bool,
- /** Specifies onChange event handler. */
- onChange: PropTypes.func,
- /** Specifies onFocus event handler. */
- onFocus: PropTypes.func,
- /** Specifies onBlur event handler. */
- onBlur: PropTypes.func,
-};
-
-FormRadioSet.defaultProps = {
- className: undefined,
- value: undefined,
- defaultValue: undefined,
- isInline: false,
- onChange: undefined,
- onFocus: undefined,
- onBlur: undefined,
-};
-
-export default FormRadioSet;
diff --git a/src/generic/SelectableBox/FormRadioSetContext.jsx b/src/generic/SelectableBox/FormRadioSetContext.jsx
deleted file mode 100644
index 38bbc3292..000000000
--- a/src/generic/SelectableBox/FormRadioSetContext.jsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import React, { useContext } from 'react';
-import PropTypes from 'prop-types';
-import { callAllHandlers } from './fieldUtils';
-
-const identityFn = props => props;
-
-const FormRadioSetContext = React.createContext({
- getRadioControlProps: identityFn,
- hasRadioSetProvider: false,
-});
-
-const useRadioSetContext = () => useContext(FormRadioSetContext);
-
-const FormRadioSetContextProvider = ({
- children,
- name,
- onBlur,
- onFocus,
- onChange,
- value,
- defaultValue,
-}) => {
- const handleChange = (...args) => {
- // eslint-disable-next-line no-console
- console.log('FormRadioSetContextProvider.handleChange called with args: ', args);
- onChange(...args);
- };
- const isControlled = !defaultValue && value !== undefined;
- // eslint-disable-next-line no-console
- console.log('FormRadioSetContextProvider | isControlled: ', isControlled);
- const getRadioControlProps = (radioProps) => ({
- ...radioProps,
- name,
- /* istanbul ignore next */
- onBlur: radioProps.onBlur ? callAllHandlers(onBlur, radioProps.onBlur) : onBlur,
- /* istanbul ignore next */
- onFocus: radioProps.onFocus ? callAllHandlers(onFocus, radioProps.onFocus) : onFocus,
- /* istanbul ignore next */
- onChange: radioProps.onChange ? callAllHandlers(handleChange, radioProps.onChange) : onChange,
- checked: isControlled ? value === radioProps.value : undefined,
- defaultChecked: isControlled ? undefined : defaultValue === radioProps.value,
- });
- // eslint-disable-next-line react/jsx-no-constructed-context-values
- const contextValue = {
- name,
- value,
- defaultValue,
- getRadioControlProps,
- onBlur,
- onFocus,
- onChange,
- hasRadioSetProvider: true,
- };
- return (
-
- {children}
-
- );
-};
-
-FormRadioSetContextProvider.propTypes = {
- children: PropTypes.node.isRequired,
- name: PropTypes.string.isRequired,
- onBlur: PropTypes.func,
- onFocus: PropTypes.func,
- onChange: PropTypes.func,
- value: PropTypes.string,
- defaultValue: PropTypes.string,
-};
-
-FormRadioSetContextProvider.defaultProps = {
- onBlur: undefined,
- onFocus: undefined,
- onChange: undefined,
- value: undefined,
- defaultValue: undefined,
-};
-
-export default FormRadioSetContext;
-export {
- useRadioSetContext,
- FormRadioSetContextProvider,
-};
diff --git a/src/generic/SelectableBox/FormText.jsx b/src/generic/SelectableBox/FormText.jsx
deleted file mode 100644
index f6469a151..000000000
--- a/src/generic/SelectableBox/FormText.jsx
+++ /dev/null
@@ -1,115 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-// import Icon from '../Icon';
-// import {
-// Check, Close, Cancel, CheckCircle, RadioButtonUnchecked, WarningFilled,
-// } from '../../icons';
-
-import { FORM_TEXT_TYPES } from './constants';
-
-// const FORM_TEXT_ICONS = {
-// [FORM_TEXT_TYPES.DEFAULT]: null,
-// [FORM_TEXT_TYPES.VALID]: Check,
-// [FORM_TEXT_TYPES.INVALID]: Close,
-// [FORM_TEXT_TYPES.WARNING]: WarningFilled,
-// [FORM_TEXT_TYPES.CRITERIA_EMPTY]: RadioButtonUnchecked,
-// [FORM_TEXT_TYPES.CRITERIA_VALID]: CheckCircle,
-// [FORM_TEXT_TYPES.CRITERIA_INVALID]: Cancel,
-// };
-
-const resolveTextType = ({ isInvalid, isValid }) => {
- if (isValid) {
- return FORM_TEXT_TYPES.VALID;
- }
- if (isInvalid) {
- return FORM_TEXT_TYPES.INVALID;
- }
- return FORM_TEXT_TYPES.DEFAULT;
-};
-
-// const FormTextIcon = ({ type, customIcon }) => {
-// if (customIcon) {
-// return customIcon;
-// }
-
-// const typeIcon = FORM_TEXT_ICONS[type];
-// if (typeIcon) {
-// return ;
-// }
-
-// return null;
-// };
-
-// FormTextIcon.propTypes = {
-// type: PropTypes.oneOf(Object.values(FORM_TEXT_TYPES)),
-// customIcon: PropTypes.node,
-// };
-
-// FormTextIcon.defaultProps = {
-// type: undefined,
-// customIcon: undefined,
-// };
-
-const FormText = ({
- children, type, icon, muted, hasIcon, ...props
-}) => {
- const className = classNames(
- props.className,
- 'pgn__form-text',
- `pgn__form-text-${type}`,
- {
- 'text-muted': muted,
- },
- );
-
- return (
-
- {/* {hasIcon &&
} */}
-
- {children}
-
-
- );
-};
-
-const FORM_TEXT_TYPE_CHOICES = [
- 'default',
- 'valid',
- 'invalid',
- 'warning',
- 'criteria-empty',
- 'criteria-valid',
- 'criteria-invalid',
-];
-
-FormText.propTypes = {
- /** Specifies contents of the component. */
- children: PropTypes.node.isRequired,
- /** Specifies class name to append to the base element. */
- className: PropTypes.string,
- /** Specifies whether to show an icon next to the text. */
- hasIcon: PropTypes.bool,
- /** Specifies text type, this affects styling. */
- type: PropTypes.oneOf(FORM_TEXT_TYPE_CHOICES),
- /** Specifies icon to show, will only be shown if `hasIcon` prop is set to `true`. */
- icon: PropTypes.node,
- /** Specifies whether to show text with muted styling. */
- muted: PropTypes.bool,
-};
-
-FormText.defaultProps = {
- hasIcon: true,
- type: 'default',
- icon: undefined,
- className: undefined,
- muted: false,
-};
-
-export default FormText;
-export {
- FORM_TEXT_TYPES,
- // FORM_TEXT_ICONS,
- // FormTextIcon,
- resolveTextType,
-};
diff --git a/src/generic/SelectableBox/README.md b/src/generic/SelectableBox/README.md
deleted file mode 100644
index 4ab1f417d..000000000
--- a/src/generic/SelectableBox/README.md
+++ /dev/null
@@ -1,215 +0,0 @@
----
-title: 'SelectableBox'
-type: 'component'
-components:
-- SelectableBox
-- SelectableBoxSet
-categories:
-- Forms
-- Content
-status: 'New'
-designStatus: 'Done'
-devStatus: 'In progress'
-notes: |
----
-
-A box that has selection states. It can be used as an alternative to a radio button or checkbox set.
-
-The ``SelectableBox`` can contain any kind of content as long as it is not clickable. In other words, there should be no clickable targets distinct from selection.
-
-## Basic Usage
-
-As ``Checkbox``
-
-```jsx live
-() => {
- const type = 'checkbox';
- const allCheeseOptions = ['swiss', 'cheddar', 'pepperjack'];
- const [checkedCheeses, { add, remove, set, clear }] = useCheckboxSetValues(['swiss']);
-
- const handleChange = e => {
- e.target.checked ? add(e.target.value) : remove(e.target.value);
- };
-
- const isInvalid = () => checkedCheeses.includes('swiss');
- const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
-
- return (
-
-
-
-
-
It is my first SelectableBox
-
Swiss
-
-
-
- Cheddar
-
-
- Pepperjack
-
-
-
- );
-}
-```
-
-## As Radio
-
-```jsx live
-() => {
- const type = 'radio';
- const [value, setValue] = useState('green');
- const handleChange = e => setValue(e.target.value);
- const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
-
- return (
-
-
-
-
It is Red color
-
Select me
-
-
-
- Green
- Leaves and grass
-
-
- Blue
- The sky
-
-
- );
-}
-```
-## As Checkbox
-As ``Checkbox`` with ``isIndeterminate``
-
-```jsx live
-() => {
- const type = 'checkbox';
- const allCheeseOptions = ['swiss', 'cheddar', 'pepperjack'];
- const [checkedCheeses, { add, remove, set, clear }] = useCheckboxSetValues(['swiss']);
-
- const allChecked = allCheeseOptions.every(value => checkedCheeses.includes(value));
- const someChecked = allCheeseOptions.some(value => checkedCheeses.includes(value));
- const isIndeterminate = someChecked && !allChecked;
- const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.small.maxWidth });
-
- const handleChange = e => {
- e.target.checked ? add(e.target.value) : remove(e.target.value);
- };
-
- const handleCheckAllChange = ({ checked }) => {
- checked ? set(allCheeseOptions) : clear();
- };
-
- return (
- <>
-
-
- All the cheese
-
-
-
-
-
-
It is my first SelectableBox
-
Swiss
-
-
-
- Cheddar
-
-
- Pepperjack
-
-
- >
- );
-}
-```
-
-As ``Checkbox`` with ``ariaLabelledby``
-
-```jsx live
-() => {
- const type = 'checkbox';
- const allCheeseOptions = ['swiss', 'cheddar', 'pepperjack'];
- const [checkedCheeses, { add, remove, set, clear }] = useCheckboxSetValues(['swiss']);
-
- const handleChange = e => {
- e.target.checked ? add(e.target.value) : remove(e.target.value);
- };
-
- const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
-
- return (
-
-
- Select your favorite cheese
-
-
-
-
- Swiss
-
-
-
-
- Cheddar
-
-
-
-
- Pepperjack
-
-
-
-
- );
-}
-```
diff --git a/src/generic/SelectableBox/SelectableBoxSet.jsx b/src/generic/SelectableBox/SelectableBoxSet.jsx
deleted file mode 100644
index a96cccab5..000000000
--- a/src/generic/SelectableBox/SelectableBoxSet.jsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import { getInputType } from './utils';
-// import { requiredWhenNot } from '../utils/propTypes';
-
-const INPUT_TYPES = [
- 'radio',
- 'checkbox',
-];
-
-const DEFAULT_COLUMNS_NUMBER = 2;
-
-const SelectableBoxSet = React.forwardRef(({
- children,
- name,
- value,
- defaultValue,
- onChange,
- type,
- columns,
- className,
- ariaLabel,
- ariaLabelledby,
- ...props
-}, ref) => {
- const inputType = getInputType('SelectableBoxSet', type);
-
- return React.createElement(
- inputType,
- {
- name,
- value,
- defaultValue,
- onChange,
- ref,
- className: classNames(
- 'pgn__selectable_box-set',
- `pgn__selectable_box-set--${columns || DEFAULT_COLUMNS_NUMBER}`,
- className,
- ),
- 'aria-label': ariaLabel,
- 'aria-labelledby': ariaLabelledby,
- ...props,
- },
- children,
- );
-});
-
-SelectableBoxSet.propTypes = {
- /** Specifies a name for the group of `SelectableBox`'es. */
- name: PropTypes.string.isRequired,
- /** Content of the `SelectableBoxSet`. */
- children: PropTypes.node,
- /** A function that receives event of the clicked `SelectableBox` and can be used to handle the value change. */
- onChange: PropTypes.func,
- /** Indicates selected `SelectableBox`'es. */
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.array]),
- /** Specifies default values for the `SelectableBox`'es. */
- defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
- /** Indicates the input type: checkbox or radio. */
- type: PropTypes.oneOf(INPUT_TYPES),
- /**
- * Specifies number of `SelectableBox`'es in a row.
- *
- * Class that is responsible for the columns number: `pgn__selectable_box-set--{columns}`.
- * Max number of columns: `12`.
- */
- columns: PropTypes.number,
- /** A class that is be appended to the base element. */
- className: PropTypes.string,
- /**
- * The ID of the label for the `SelectableBoxSet`.
- *
- * An accessible label must be provided to the `SelectableBoxSet`.
- */
- ariaLabelledby: PropTypes.string,
- /**
- * A label for the `SelectableBoxSet`.
- *
- * If not using `ariaLabelledby`, then `ariaLabel` must be provided */
- // eslint-disable-next-line react/forbid-prop-types
- ariaLabel: PropTypes.any, // requiredWhenNot(PropTypes.string, 'ariaLabelledby'),
-};
-
-SelectableBoxSet.defaultProps = {
- children: undefined,
- onChange: () => {},
- value: undefined,
- defaultValue: undefined,
- type: 'radio',
- columns: DEFAULT_COLUMNS_NUMBER,
- className: undefined,
- ariaLabelledby: undefined,
- ariaLabel: undefined,
-};
-
-export default SelectableBoxSet;
diff --git a/src/generic/SelectableBox/_variables.scss b/src/generic/SelectableBox/_variables.scss
deleted file mode 100644
index b7d4e114d..000000000
--- a/src/generic/SelectableBox/_variables.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-$selectable-box-padding: 1rem !default;
-$selectable-box-border-radius: .25rem !default;
-$selectable-box-space: .75rem !default;
-$min-cols-number: 1 !default;
-$max-cols-number: 12 !default;
diff --git a/src/generic/SelectableBox/constants.js b/src/generic/SelectableBox/constants.js
deleted file mode 100644
index 68abdda93..000000000
--- a/src/generic/SelectableBox/constants.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/* eslint-disable import/prefer-default-export */
-const FORM_CONTROL_SIZES = {
- SMALL: 'sm',
- LARGE: 'lg',
-};
-
-const FORM_TEXT_TYPES = {
- DEFAULT: 'default',
- VALID: 'valid',
- INVALID: 'invalid',
- WARNING: 'warning',
- CRITERIA_EMPTY: 'criteria-empty',
- CRITERIA_VALID: 'criteria-valid',
- CRITERIA_INVALID: 'criteria-invalid',
-};
-
-export { FORM_CONTROL_SIZES, FORM_TEXT_TYPES };
diff --git a/src/generic/SelectableBox/fieldUtils.js b/src/generic/SelectableBox/fieldUtils.js
deleted file mode 100644
index 5c0d980a1..000000000
--- a/src/generic/SelectableBox/fieldUtils.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import classNames from 'classnames';
-import { useState, useEffect } from 'react';
-import newId from './newId';
-
-const omitUndefinedProperties = (obj = {}) => Object.entries(obj)
- .reduce((acc, [key, value]) => {
- if (value !== undefined) {
- acc[key] = value;
- }
- return acc;
- }, {});
-
-const callAllHandlers = (...handlers) => {
- const unifiedEventHandler = (event) => {
- handlers
- .filter(handler => typeof handler === 'function')
- .forEach(handler => handler(event));
- };
- return unifiedEventHandler;
-};
-
-const useHasValue = ({ defaultValue, value }) => {
- const [hasUncontrolledValue, setHasUncontrolledValue] = useState(!!defaultValue || defaultValue === 0);
- const hasValue = !!value || value === 0 || hasUncontrolledValue;
- const handleInputEvent = (e) => setHasUncontrolledValue(e.target.value);
- return [hasValue, handleInputEvent];
-};
-
-const useIdList = (uniqueIdPrefix, initialList) => {
- const [idList, setIdList] = useState(initialList || []);
- const addId = (idToAdd) => {
- setIdList(oldIdList => [...oldIdList, idToAdd]);
- return idToAdd;
- };
- const getNewId = () => {
- const idToAdd = newId(`${uniqueIdPrefix}-`);
- return addId(idToAdd);
- };
- const removeId = (idToRemove) => {
- setIdList(oldIdList => oldIdList.filter(id => id !== idToRemove));
- };
-
- const useRegisteredId = (explicitlyRegisteredId) => {
- const [registeredId, setRegisteredId] = useState(explicitlyRegisteredId);
- useEffect(() => {
- if (explicitlyRegisteredId) {
- addId(explicitlyRegisteredId);
- } else if (!registeredId) {
- setRegisteredId(getNewId(uniqueIdPrefix));
- }
- return () => removeId(registeredId);
- }, [registeredId, explicitlyRegisteredId]);
- return registeredId;
- };
-
- return [idList, useRegisteredId];
-};
-
-const mergeAttributeValues = (...values) => {
- const mergedValues = classNames(values);
- return mergedValues || undefined;
-};
-
-export {
- callAllHandlers,
- useHasValue,
- mergeAttributeValues,
- useIdList,
- omitUndefinedProperties,
-};
diff --git a/src/generic/SelectableBox/index.jsx b/src/generic/SelectableBox/index.jsx
deleted file mode 100644
index d5e1978ff..000000000
--- a/src/generic/SelectableBox/index.jsx
+++ /dev/null
@@ -1,115 +0,0 @@
-import React, { useRef, useEffect } from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import SelectableBoxSet from './SelectableBoxSet';
-import { useCheckboxSetContext } from './FormCheckboxSetContext';
-import { useRadioSetContext } from './FormRadioSetContext';
-import { getInputType } from './utils';
-
-const INPUT_TYPES = [
- 'radio',
- 'checkbox',
-];
-
-const SelectableBox = React.forwardRef(({
- type,
- value,
- checked,
- children,
- isIndeterminate,
- isInvalid,
- onClick,
- onFocus,
- inputHidden,
- className,
- ...props
-}, ref) => {
- const inputType = getInputType('SelectableBox', type);
- const { value: radioValue } = useRadioSetContext();
- const { value: checkboxValues = [] } = useCheckboxSetContext();
-
- const isChecked = () => {
- switch (type) {
- case 'radio':
- return radioValue === value;
- case 'checkbox':
- return checkboxValues.includes(value);
- default:
- return radioValue === value;
- }
- };
-
- const inputRef = useRef(null);
- const input = React.createElement(inputType, {
- value,
- checked,
- hidden: inputHidden,
- ref: inputRef,
- tabIndex: -1,
- onChange: () => {},
- ...(type === 'checkbox' ? { ...props, isIndeterminate } : { ...props }),
- }, null);
-
- useEffect(() => {
- if (onClick && inputRef.current) {
- inputRef.current.onclick = () => onClick(inputRef.current);
- }
- }, [onClick]);
-
- return (
- inputRef.current.click()}
- onClick={() => inputRef.current.click()}
- onFocus={onFocus}
- className={classNames('pgn__selectable_box', className, {
- 'pgn__selectable_box-active': isChecked() || checked,
- 'pgn__selectable_box-invalid': isInvalid,
- })}
- tabIndex={0}
- ref={ref}
- {...props}
- >
- {input}
- {children}
-
- );
-});
-
-SelectableBox.propTypes = {
- /** Content of the `SelectableBox`. */
- children: PropTypes.node.isRequired,
- /** A value that is passed to the input tag. */
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
- /** Controls whether `SelectableBox` is checked. */
- checked: PropTypes.bool,
- /** Indicates the input type: checkbox or radio. */
- type: PropTypes.oneOf(INPUT_TYPES),
- /** Function that is called when the `SelectableBox` is clicked. */
- onClick: PropTypes.func,
- /** Function that is called when the `SelectableBox` is focused. */
- onFocus: PropTypes.func,
- /** Controls display of the input (checkbox or radio button) on the `SelectableBox`. */
- inputHidden: PropTypes.bool,
- /** Indicates a state for the 'checkbox' `type` when `SelectableBox` is neither checked nor unchecked. */
- isIndeterminate: PropTypes.bool,
- /** Adds errors styles to the `SelectableBox`. */
- isInvalid: PropTypes.bool,
- /** A class that is appended to the base element. */
- className: PropTypes.string,
-};
-
-SelectableBox.defaultProps = {
- value: undefined,
- checked: false,
- type: 'radio',
- onClick: () => {},
- onFocus: () => {},
- inputHidden: true,
- isIndeterminate: false,
- isInvalid: false,
- className: undefined,
-};
-
-SelectableBox.Set = SelectableBoxSet;
-export default SelectableBox;
diff --git a/src/generic/SelectableBox/index.scss b/src/generic/SelectableBox/index.scss
deleted file mode 100644
index 1038286af..000000000
--- a/src/generic/SelectableBox/index.scss
+++ /dev/null
@@ -1,54 +0,0 @@
-@import "variables";
-
-.pgn__selectable_box-set {
- display: grid;
- grid-auto-rows: 1fr;
- grid-gap: $selectable-box-space;
-
- @for $i from $min-cols-number through $max-cols-number {
- &.pgn__selectable_box-set--#{$i} {
- grid-template-columns: repeat(#{$i}, 1fr);
- }
- }
-
- & > * + * {
- margin: 0;
- }
-}
-
-.pgn__selectable_box {
- position: relative;
- height: 100%;
- padding: $selectable-box-padding;
- box-shadow: $level-1-box-shadow;
- border-radius: $selectable-box-border-radius;
- text-align: start;
- background: $white;
-
- &:focus-visible {
- outline: 1px solid $primary-700;
- }
-
- .pgn__form-radio,
- .pgn__form-checkbox {
- position: absolute;
- top: $selectable-box-padding;
- inset-inline-end: $selectable-box-padding;
-
- input {
- margin-inline-end: 0;
- }
- }
-
- * {
- pointer-events: none;
- }
-}
-
-.pgn__selectable_box-active {
- outline: 2px solid $primary-500;
-}
-
-.pgn__selectable_box-invalid {
- outline: 2px solid $danger-300;
-}
diff --git a/src/generic/SelectableBox/newId.js b/src/generic/SelectableBox/newId.js
deleted file mode 100644
index 9055c9e31..000000000
--- a/src/generic/SelectableBox/newId.js
+++ /dev/null
@@ -1,8 +0,0 @@
-let lastId = 0;
-
-const newId = (prefix = 'id') => {
- lastId += 1;
- return `${prefix}${lastId}`;
-};
-
-export default newId;
diff --git a/src/generic/SelectableBox/tests/SelectableBox.test.jsx b/src/generic/SelectableBox/tests/SelectableBox.test.jsx
deleted file mode 100644
index 226c5a9f8..000000000
--- a/src/generic/SelectableBox/tests/SelectableBox.test.jsx
+++ /dev/null
@@ -1,124 +0,0 @@
-import React from 'react';
-import { render, screen } from '@testing-library/react';
-import userEvent from '@testing-library/user-event';
-import renderer from 'react-test-renderer';
-
-import SelectableBox from '..';
-
-const checkboxType = 'checkbox';
-const checkboxText = 'SelectableCheckbox';
-
-const radioType = 'radio';
-const radioText = 'SelectableRadio';
-
-const SelectableCheckbox = (props) => {checkboxText} ;
-
-const SelectableRadio = (props) => {radioText} ;
-
-describe(' ', () => {
- describe('correct rendering', () => {
- it('renders without props', () => {
- const tree = renderer.create((
- SelectableBox
- )).toJSON();
- expect(tree).toMatchSnapshot();
- });
- it('correct render when type prop is changed', () => {
- const { rerender } = render( );
- const checkboxControl = screen.getByText(radioText);
- expect(checkboxControl).toBeTruthy();
- rerender( );
- const radioControl = screen.getByText(radioText);
- expect(radioControl).toBeTruthy();
- });
- it('renders with radio input type if neither checkbox nor radio is passed', () => {
- // Mock the `console.error` is intentional because an invalid `type` prop
- // with `wrongType` specified for `ForwardRef` expects one of the ['radio','flag'] parameters.
- // eslint-disable-next-line no-console
- const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
- render( );
- const selectableBox = screen.getByRole('button');
- expect(selectableBox).toBeTruthy();
- consoleErrorSpy.mockRestore();
- });
- it('renders with checkbox input type', () => {
- render( );
- const selectableBox = screen.getByRole('button');
- expect(selectableBox).toBeTruthy();
- });
- it('renders with radio input type', () => {
- render( );
- const selectableBox = screen.getByRole('button');
- expect(selectableBox).toBeTruthy();
- });
- it('renders with correct children', () => {
- render( );
- const selectableBox = screen.getByText(radioText);
- expect(selectableBox).toBeTruthy();
- });
- it('renders with correct class', () => {
- const className = 'myClass';
- render( );
- const selectableBox = screen.getByRole('button');
- expect(selectableBox.classList.contains(className)).toEqual(true);
- });
- it('renders as active when checked is passed', () => {
- render( );
- const selectableBox = screen.getByRole('button');
- const inputElement = screen.getByRole('radio', { hidden: true });
- expect(selectableBox.classList.contains('pgn__selectable_box-active')).toEqual(true);
- expect(inputElement.checked).toEqual(true);
- });
- it('renders as invalid when isInvalid is passed', () => {
- render( );
- const selectableBox = screen.getByRole('button');
- expect(selectableBox.classList.contains('pgn__selectable_box-invalid')).toEqual(true);
- });
- it('renders with on click event when onClick is passed', async () => {
- const onClickSpy = jest.fn();
- render( );
- const selectableBox = screen.getByRole('button');
- await userEvent.click(selectableBox);
- expect(onClickSpy).toHaveBeenCalledTimes(1);
- });
- it('renders with on key press event when onClick is passed', async () => {
- const onClickSpy = jest.fn();
- render( );
- const selectableBox = screen.getByRole('button');
- selectableBox.focus();
- await userEvent.keyboard('{enter}');
- expect(onClickSpy).toHaveBeenCalledTimes(1);
- });
- it('renders with hidden input when inputHidden is passed', () => {
- const { rerender } = render( );
- const inputElement = screen.getByRole('checkbox', { hidden: true });
- expect(inputElement.getAttribute('hidden')).toEqual('');
- rerender( );
- expect(inputElement.getAttribute('hidden')).toBeNull();
- });
- });
- describe('correct interactions', () => {
- it('correct checkbox state change when checked is changed', () => {
- const { rerender } = render( );
- const checkbox = screen.getByRole('button');
- expect(checkbox.className).not.toContain('pgn__selectable_box-active');
- rerender( );
- expect(checkbox.className).toContain('pgn__selectable_box-active');
- });
- it('correct radio state change when checked is changed', () => {
- const { rerender } = render( );
- const radio = screen.getByRole('button');
- expect(radio.className).toContain('pgn__selectable_box-active');
- rerender( );
- expect(radio.className).toContain('pgn__selectable_box-active');
- });
- it('ref is passed to onClick function', () => {
- let inputRef;
- const onClick = (ref) => { inputRef = ref; };
- render( );
- const radio = screen.getByRole('button');
- userEvent.click(radio);
- expect(inputRef).not.toBeFalsy();
- });
- });
-});
diff --git a/src/generic/SelectableBox/tests/SelectableBoxSet.test.jsx b/src/generic/SelectableBox/tests/SelectableBoxSet.test.jsx
deleted file mode 100644
index cf3db6f3c..000000000
--- a/src/generic/SelectableBox/tests/SelectableBoxSet.test.jsx
+++ /dev/null
@@ -1,107 +0,0 @@
-import React from 'react';
-import { render, screen } from '@testing-library/react';
-import '@testing-library/jest-dom/extend-expect';
-import userEvent from '@testing-library/user-event';
-import SelectableBox from '..';
-
-const boxText = (text) => `SelectableBox${text}`;
-
-const checkboxType = 'checkbox';
-const checkboxText = (text) => `SelectableCheckbox${text}`;
-
-const radioType = 'radio';
-const radioText = (text) => `SelectableRadio${text}`;
-
-const ariaLabel = 'test-default-label';
-
-const SelectableBoxSet = (props) => (
-
- {boxText(1)}
- {boxText(2)}
- {boxText(3)}
-
-);
-
-const SelectableCheckboxSet = (props) => (
-
- {checkboxText(1)}
- {checkboxText(2)}
- {checkboxText(3)}
-
-);
-
-const SelectableRadioSet = (props) => (
-
- {radioText(1)}
- {radioText(2)}
- {radioText(3)}
-
-);
-
-describe(' ', () => {
- describe('correct rendering', () => {
- it('renders without props', () => {
- const { container } = render( );
- expect(container).toMatchSnapshot();
- });
- it('forwards props', () => {
- render(( ));
- expect(screen.getByTestId('test-radio-set-name')).toBeInTheDocument();
- });
- it('correct render when type prop is changed', () => {
- const { rerender } = render( );
- expect(screen.getByTestId('radio-set')).toBeInTheDocument();
- rerender( );
- expect(screen.getByTestId('radio-set')).toBeInTheDocument();
- rerender( );
- expect(screen.getByTestId('checkbox-set')).toBeInTheDocument();
- });
- it('renders with children', () => {
- render(
- {checkboxText(1)} ,
- );
- expect(screen.getByText(checkboxText(1))).toBeInTheDocument();
- });
- it('renders with on change event', async () => {
- const onChangeSpy = jest.fn();
- render( );
- const checkbox = screen.getByRole('button', { name: checkboxText(1) });
- await userEvent.click(checkbox);
- expect(onChangeSpy).toHaveBeenCalledTimes(1);
- });
- it('renders with checkbox type', () => {
- render( );
- expect(screen.getByTestId('checkbox-set')).toBeInTheDocument();
- });
- it('renders with radio type if neither checkbox nor radio is passed', () => {
- render( );
- expect(screen.getByTestId('radio-set')).toBeInTheDocument();
- });
- it('renders with radio type', () => {
- render( );
- expect(screen.getByTestId('radio-set')).toBeInTheDocument();
- });
- it('renders with correct number of columns', () => {
- const columns = 10;
- render( );
- const selectableBoxSet = screen.getByTestId('selectable-box-set');
- expect(selectableBoxSet).toHaveClass(`pgn__selectable_box-set--${columns}`);
- });
- it('renders with an aria-label attribute', () => {
- render(( ));
- expect(screen.getByLabelText('test-radio-set-label')).toBeInTheDocument();
- });
- it('renders with an aria-labelledby attribute', () => {
- render((
- <>
- Radio Set Label text
-
- >
- ));
- expect(screen.getByLabelText('Radio Set Label text')).toBeInTheDocument();
- });
- });
-});
diff --git a/src/generic/SelectableBox/tests/__snapshots__/SelectableBox.test.jsx.snap b/src/generic/SelectableBox/tests/__snapshots__/SelectableBox.test.jsx.snap
deleted file mode 100644
index 96676cabf..000000000
--- a/src/generic/SelectableBox/tests/__snapshots__/SelectableBox.test.jsx.snap
+++ /dev/null
@@ -1,22 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[` correct rendering renders without props 1`] = `
-
-
- SelectableBox
-
-`;
diff --git a/src/generic/SelectableBox/tests/__snapshots__/SelectableBoxSet.test.jsx.snap b/src/generic/SelectableBox/tests/__snapshots__/SelectableBoxSet.test.jsx.snap
deleted file mode 100644
index 4c9a0ab8f..000000000
--- a/src/generic/SelectableBox/tests/__snapshots__/SelectableBoxSet.test.jsx.snap
+++ /dev/null
@@ -1,57 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[` correct rendering renders without props 1`] = `
-
-`;
diff --git a/src/generic/SelectableBox/utils.js b/src/generic/SelectableBox/utils.js
deleted file mode 100644
index 16883a772..000000000
--- a/src/generic/SelectableBox/utils.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import { CheckboxControl } from './FormCheckbox';
-import { RadioControl } from './FormRadio';
-import FormRadioSet from './FormRadioSet';
-import FormCheckboxSet from './FormCheckboxSet';
-
-// eslint-disable-next-line import/prefer-default-export,consistent-return
-export const getInputType = (component, type) => {
- if (component === 'SelectableBox') {
- switch (type) {
- case 'radio':
- return RadioControl;
- case 'checkbox':
- return CheckboxControl;
- default:
- return RadioControl;
- }
- } else if (component === 'SelectableBoxSet') {
- switch (type) {
- case 'radio':
- return FormRadioSet;
- case 'checkbox':
- return FormCheckboxSet;
- default:
- return FormRadioSet;
- }
- }
-};