Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRAFT: remove bootstrap from Form component #3327

Draft
wants to merge 1 commit into
base: alpha
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions src/Form/BSFeedback.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import classNames from 'classnames';
import React from 'react';
import PropTypes from 'prop-types';
// import { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers';

const propTypes = {
/**
* Specify whether the feedback is for valid or invalid fields
*
* @type {('valid'|'invalid')}
*/
type: PropTypes.string,

Check failure on line 12 in src/Form/BSFeedback.jsx

View workflow job for this annotation

GitHub Actions / tests

propType "type" is not required, but has no corresponding defaultProps declaration

/** Display feedback as a tooltip. */
tooltip: PropTypes.bool,

Check failure on line 15 in src/Form/BSFeedback.jsx

View workflow job for this annotation

GitHub Actions / tests

propType "tooltip" is not required, but has no corresponding defaultProps declaration

as: PropTypes.elementType,

Check failure on line 17 in src/Form/BSFeedback.jsx

View workflow job for this annotation

GitHub Actions / tests

propType "as" is not required, but has no corresponding defaultProps declaration
};

const Feedback = React.forwardRef(
(
{
as: Component = 'div',
className,

Check failure on line 24 in src/Form/BSFeedback.jsx

View workflow job for this annotation

GitHub Actions / tests

'className' is missing in props validation
type = 'valid',
tooltip = false,
...props
},
ref,
) => (
<Component
{...props}
ref={ref}
className={classNames(
className,
`${type}-${tooltip ? 'tooltip' : 'feedback'}`,
)}
/>
),
);

Feedback.displayName = 'Feedback';
Feedback.propTypes = propTypes;

export default Feedback;
92 changes: 92 additions & 0 deletions src/Form/BSForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import FormCheck from './FormCheck';

Check failure on line 4 in src/Form/BSForm.jsx

View workflow job for this annotation

GitHub Actions / tests

Missing file extension for "./FormCheck"

Check failure on line 4 in src/Form/BSForm.jsx

View workflow job for this annotation

GitHub Actions / tests

Unable to resolve path to module './FormCheck'
import FormFile from './FormFile';

Check failure on line 5 in src/Form/BSForm.jsx

View workflow job for this annotation

GitHub Actions / tests

Missing file extension for "./FormFile"

Check failure on line 5 in src/Form/BSForm.jsx

View workflow job for this annotation

GitHub Actions / tests

Unable to resolve path to module './FormFile'
import FormControl from './FormControl';
import FormGroup from './FormGroup';
import FormLabel from './FormLabel';
import FormText from './FormText';
import Switch from './Switch';

Check failure on line 10 in src/Form/BSForm.jsx

View workflow job for this annotation

GitHub Actions / tests

Missing file extension for "./Switch"

Check failure on line 10 in src/Form/BSForm.jsx

View workflow job for this annotation

GitHub Actions / tests

Unable to resolve path to module './Switch'
// import { useBootstrapPrefix } from './ThemeProvider';
import createWithBsPrefix from './createWithBsPrefix';
// import { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers';

const FormRow = createWithBsPrefix('form-row');

const propTypes = {
/**
* @default {'form'}
*/
bsPrefix: PropTypes.string,

/**
* The Form `ref` will be forwarded to the underlying element,
* which means, unless it's rendered `as` a composite component,
* it will be a DOM node, when resolved.
*
* @type {ReactRef}
* @alias ref
*/
_ref: PropTypes.any,

/**
* Display the series of labels, form controls,
* and buttons on a single horizontal row
*/
inline: PropTypes.bool,

/**
* Mark a form as having been validated. Setting it to `true` will
* toggle any validation styles on the forms elements.
*/
validated: PropTypes.bool,
as: PropTypes.elementType,
};

const defaultProps = {
inline: false,
};

const FormImpl = (React.forwardRef(
(
{
bsPrefix,
inline,
className,
validated,
as: Component = 'form',
...props
},
ref,
) => {
// bsPrefix = useBootstrapPrefix(bsPrefix, 'form');
bsPrefix = 'form';
return (
<Component
{...props}
ref={ref}
className={classNames(
className,
validated && 'was-validated',
inline && `${bsPrefix}-inline`,
)}
/>
);
},
));

FormImpl.displayName = 'Form';
FormImpl.propTypes = propTypes;
FormImpl.defaultProps = defaultProps;

FormImpl.Row = FormRow;
FormImpl.Group = FormGroup;
FormImpl.Control = FormControl;
FormImpl.Check = FormCheck;
FormImpl.File = FormFile;
FormImpl.Switch = Switch;
FormImpl.Label = FormLabel;
FormImpl.Text = FormText;

export default FormImpl;
207 changes: 207 additions & 0 deletions src/Form/BSFormCheck.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import classNames from 'classnames';
import PropTypes from 'prop-types';
// import all from 'prop-types-extra/lib/all';
import React, { useContext, useMemo } from 'react';
import Feedback from './BSFeedback';
import FormCheckInput from './FormCheckInput';
import FormCheckLabel from './FormCheckLabel';
import FormContext from './BSFormContext';
// import { useBootstrapPrefix } from './ThemeProvider';

const propTypes = {
/**
* @default 'form-check'
*/
bsPrefix: PropTypes.string,

/**
* A seperate bsPrefix used for custom controls
*
* @default 'custom-control'
*/
bsCustomPrefix: PropTypes.string,

/**
* The FormCheck `ref` will be forwarded to the underlying input element,
* which means it will be a DOM node, when resolved.
*
* @type {ReactRef}
* @alias ref
*/
_ref: PropTypes.any,

/**
* The underlying HTML element to use when rendering the FormCheck.
*
* @type {('input'|elementType)}
*/
as: PropTypes.elementType,

/**
* A HTML id attribute, necessary for proper form accessibility.
* An id is recommended for allowing label clicks to toggle the check control.
*
* This is **required** for custom check controls or when `type="switch"` due to
* how they are rendered.
*/
id: PropTypes.string,

/**
* Provide a function child to manually handle the layout of the FormCheck's inner components.
*
* ```jsx
* <FormCheck>
* <FormCheck.Input isInvalid type={radio} />
* <FormCheck.Label>Allow us to contact you?</FormCheck.Label>
* <Feedback type="invalid">Yo this is required</Feedback>
* </FormCheck>
* ```
*/
children: PropTypes.node,

/**
* Groups controls horizontally with other `FormCheck`s.
*/
inline: PropTypes.bool,

/**
* Disables the control.
*/
disabled: PropTypes.bool,

/**
* `title` attribute for the underlying `FormCheckLabel`.
*/
title: PropTypes.string,

/**
* Label for the control.
*/
label: PropTypes.node,

/** Use Bootstrap's custom form elements to replace the browser defaults */
// custom: all(PropTypes.bool, ({ custom, id }) => (custom && !id ? Error('Custom check controls require an id to work') : null)),

/**
* The type of checkable.
* @type {('radio' | 'checkbox' | 'switch')}
*/
type: all(
PropTypes.oneOf(['radio', 'checkbox', 'switch']).isRequired,
({ type, custom }) => (type === 'switch' && custom === false
? Error('`custom` cannot be set to `false` when the type is `switch`')
: null),
({ type, id }) => (type === 'switch' && !id
? Error('`id` must be defined when the type is `switch`')
: null),
),

/** Manually style the input as valid */
isValid: PropTypes.bool,

/** Manually style the input as invalid */
isInvalid: PropTypes.bool,

/** Display feedback as a tooltip. */
feedbackTooltip: PropTypes.bool,

/** A message to display when the input is in a validation state */
feedback: PropTypes.node,
};

const FormCheck = (React.forwardRef(
(
{
id,
bsPrefix,
bsCustomPrefix,
inline = false,
disabled = false,
isValid = false,
isInvalid = false,
feedbackTooltip = false,
feedback,
className,
style,
title = '',
type = 'checkbox',
label,
children,
custom: propCustom,
as = 'input',
...props
},
ref,
) => {
const custom = type === 'switch' ? true : propCustom;
const [prefix, defaultPrefix] = custom
? [bsCustomPrefix, 'custom-control']
: [bsPrefix, 'form-check'];

// bsPrefix = useBootstrapPrefix(prefix, defaultPrefix);
bsPrefix = 'form-check';

const { controlId } = useContext(FormContext);
const innerFormContext = useMemo(
() => ({
controlId: id || controlId,
custom,
}),
[controlId, custom, id],
);

const hasLabel = custom || (label != null && label !== false && !children);

const input = (
<FormCheckInput
{...props}
type={type === 'switch' ? 'checkbox' : type}
ref={ref}
isValid={isValid}
isInvalid={isInvalid}
isStatic={!hasLabel}
disabled={disabled}
as={as}
/>
);

return (
<FormContext.Provider value={innerFormContext}>
<div
style={style}
className={classNames(
className,
bsPrefix,
custom && `custom-${type}`,
inline && `${bsPrefix}-inline`,
)}
>
{children || (
<>
{input}
{hasLabel && (
<FormCheckLabel title={title}>{label}</FormCheckLabel>
)}
{(isValid || isInvalid) && (
<Feedback
type={isValid ? 'valid' : 'invalid'}
tooltip={feedbackTooltip}
>
{feedback}
</Feedback>
)}
</>
)}
</div>
</FormContext.Provider>
);
},
));

FormCheck.displayName = 'FormCheck';
FormCheck.propTypes = propTypes;

FormCheck.Input = FormCheckInput;
FormCheck.Label = FormCheckLabel;

export default FormCheck;
7 changes: 7 additions & 0 deletions src/Form/BSFormContext.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

const FormContext = React.createContext({
controlId: undefined,
});

export default FormContext;
Loading
Loading