Custom checkbox
This commit is contained in:
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user