Custom checkbox

This commit is contained in:
Aarni Halinen
2020-07-22 22:40:23 +03:00
parent 0bd28ee687
commit 103c48c790
3 changed files with 168 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
import React from "react";
import styled from "styled-components";
const Container = styled.label`
display: block;
position: relative;
padding-left: 35px;
margin-bottom: 12px;
cursor: pointer;
font-size: 22px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
/* On mouse-over, add a grey background color */
&:hover input ~ .checkbox {
background-color: #ccc;
}
/* When the checkbox is checked, add a blue background */
& input:checked ~ .checkbox {
background-color: #2196F3;
}
/* Style the checkmark/indicator */
& .checkbox:after {
left: 9px;
top: 5px;
width: 5px;
height: 10px;
border: solid white;
border-width: 0 3px 3px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
/* Show the checkmark when checked */
& input:checked ~ .checkbox:after {
display: block;
}
`;
/* Hide the browser's default checkbox */
const DefaultBox = styled.input`
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
`;
/* Create a custom checkbox */
const CustomBox = styled.span`
position: absolute;
top: 0;
left: 0;
height: 25px;
width: 25px;
background-color: #eee;
/* Create the checkmark/indicator (hidden when not checked) */
&:after {
content: "";
position: absolute;
display: none;
}
`;
type CheckboxProps = Omit<
React.InputHTMLAttributes<HTMLInputElement>,
"type"
>;
const Checkbox: React.FC<CheckboxProps> = ({children, ...props}) => (
<Container>
{children}
<DefaultBox
type="checkbox"
{...props}
/>
<CustomBox className="checkbox" />
</Container>
)
export default Checkbox;
+73
View File
@@ -0,0 +1,73 @@
import React from "react";
import { WidgetProps } from "react-jsonschema-form";
import Checkbox from "./Checkbox";
// See https://github.com/rjsf-team/react-jsonschema-form/blob/master/packages/core/src/components/widgets/CheckboxesWidget.js
function selectValue(value, selected, all) {
const at = all.indexOf(value);
const updated = selected.slice(0, at).concat(value, selected.slice(at));
// As inserting values at predefined index positions doesn't work with empty
// arrays, we need to reorder the updated selection to match the initial order
return updated.sort((a, b) => all.indexOf(a) > all.indexOf(b));
}
function deselectValue(value, selected) {
return selected.filter(v => v !== value);
}
type CheckboxesProps = Omit<WidgetProps, "options"> & {
options: any;
};
const Checkboxes: React.FC<CheckboxesProps> = ({id, disabled, options, value, autofocus, readonly, onChange}) => {
const { enumOptions, enumDisabled, inline } = options;
return (
<div className="checkboxes" id={id}>
{enumOptions.map((option, index) => {
const checked = value.indexOf(option.value) !== -1;
const itemDisabled =
enumDisabled && enumDisabled.indexOf(option.value) != -1;
const disabledCls =
disabled || itemDisabled || readonly ? "disabled" : "";
const checkbox = (
<Checkbox
id={`${id}_${index}`}
checked={checked}
disabled={disabled || itemDisabled || readonly}
autoFocus={autofocus && index === 0}
onChange={event => {
const all = enumOptions.map(({ value }) => value);
if (event.target.checked) {
onChange(selectValue(option.value, value, all));
} else {
onChange(deselectValue(option.value, value));
}
}}
>
{option.label}
</Checkbox>
);
return inline ? (
<label key={index} className={`checkbox-inline ${disabledCls}`}>
{checkbox}
</label>
) : (
<div key={index} className={`checkbox ${disabledCls}`}>
<label>{checkbox}</label>
</div>
);
})}
</div>
)
}
Checkboxes.defaultProps = {
autofocus: false,
options: {
inline: false,
}
}
export default Checkboxes;
+8
View File
@@ -6,6 +6,13 @@ import { SignupForm } from "@models/SignupForm";
import { buildSchema, buildUISchema } from "./FormUtils";
import AsideSection from "@components/AsideSection";
import MainSection from "@components/MainSection";
import Checkbox from "@components/Checkbox/Checkbox";
import Checkboxes from "@components/Checkbox/Checkboxes";
const customWidgets = {
// "radio": Checkbox,
"checkboxes": Checkboxes
};
interface SignUpPageViewProps {
signUpForm: SignupForm;
@@ -51,6 +58,7 @@ const SignUpPageView: React.FC<SignUpPageViewProps> = ({
schema={schema as any}
uiSchema={uiSchema}
formData={formData}
widgets={customWidgets}
idPrefix="rjsf"
onChange={onChange}
onSubmit={onSubmit}