Skip to content

Commit

Permalink
Just check immediate children for FormCheckLabel
Browse files Browse the repository at this point in the history
  • Loading branch information
TyMick committed Nov 6, 2021
1 parent 5343b0a commit 0754b49
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 55 deletions.
Empty file modified .husky/pre-commit
100644 → 100755
Empty file.
36 changes: 8 additions & 28 deletions src/ElementChildren.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,36 +36,16 @@ function forEach<P = any>(
}

/**
* Finds a child component by type (either a string for an HTML element or a
* component for a React element) and separates it from the parent component's
* other children.
* Finds whether a component's `children` prop includes a React element of the
* specified type.
*/
function getChildOfType<P = any>(
children: React.ReactNode | React.ReactNode[],
function hasChildOfType<P = any>(
children: React.ReactNode,
type: string | React.JSXElementConstructor<P>,
): {
matchingChild: React.ReactElement<
P,
string | React.JSXElementConstructor<P>
> | null;
otherChildren: React.ReactNode[];
} {
const childrenList = Array.isArray(children)
? children
: React.Children.toArray(children);
const childIndex = childrenList.findIndex(
(child) => React.isValidElement<P>(child) && child.type === type,
): boolean {
return React.Children.toArray(children).some(
(child) => React.isValidElement(child) && child.type === type,
);

return childIndex === -1
? { matchingChild: null, otherChildren: childrenList }
: {
matchingChild: childrenList[childIndex] as React.ReactElement<P>,
otherChildren: [
...childrenList.slice(0, childIndex),
...childrenList.slice(childIndex + 1),
],
};
}

export { map, forEach, getChildOfType };
export { map, forEach, hasChildOfType };
46 changes: 19 additions & 27 deletions src/FormCheck.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import FormCheckLabel from './FormCheckLabel';
import FormContext from './FormContext';
import { useBootstrapPrefix } from './ThemeProvider';
import { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers';
import { getChildOfType } from './ElementChildren';
import { hasChildOfType } from './ElementChildren';

export type FormCheckType = 'checkbox' | 'radio' | 'switch';

Expand Down Expand Up @@ -153,9 +153,11 @@ const FormCheck: BsPrefixRefForwardingComponent<'input', FormCheckProps> =
[controlId, id],
);

const { matchingChild: inputChild, otherChildren: childrenAfterInput } =
getChildOfType(children, FormCheckInput);
const inputElement = inputChild ?? (
const hasLabel =
(!children && label != null && label !== false) ||
hasChildOfType(children, FormCheckInput);

const input = (
<FormCheckInput
{...props}
type={type === 'switch' ? 'checkbox' : type}
Expand All @@ -167,25 +169,6 @@ const FormCheck: BsPrefixRefForwardingComponent<'input', FormCheckProps> =
/>
);

const { matchingChild: labelChild, otherChildren: childrenAfterLabel } =
getChildOfType(childrenAfterInput, FormCheckLabel);
const labelElement = labelChild ?? (
<FormCheckLabel title={title}>{label}</FormCheckLabel>
);
const hasLabel = (label != null && label !== false) || labelChild != null;

const { matchingChild: feedbackChild, otherChildren } = getChildOfType(
childrenAfterLabel,
Feedback,
);
const feedbackElement =
feedbackChild ??
(feedback && (
<Feedback type={feedbackType} tooltip={feedbackTooltip}>
{feedback}
</Feedback>
));

return (
<FormContext.Provider value={innerFormContext}>
<div
Expand All @@ -197,10 +180,19 @@ const FormCheck: BsPrefixRefForwardingComponent<'input', FormCheckProps> =
type === 'switch' && bsSwitchPrefix,
)}
>
{inputElement}
{labelElement}
{feedbackElement}
{otherChildren}
{children || (
<>
{input}
{hasLabel && (
<FormCheckLabel title={title}>{label}</FormCheckLabel>
)}
{feedback && (
<Feedback type={feedbackType} tooltip={feedbackTooltip}>
{feedback}
</Feedback>
)}
</>
)}
</div>
</FormContext.Provider>
);
Expand Down

0 comments on commit 0754b49

Please sign in to comment.