-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PD-12487 Make CollapsibleChecklists component
- Loading branch information
1 parent
84228d6
commit 52f57fb
Showing
14 changed files
with
391 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "@paprika/collapsible-list", | ||
"version": "0.1.0", | ||
"description": "CollapsibleList component", | ||
"author": "@paprika", | ||
"license": "MIT", | ||
"main": "lib/index.js", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/acl-services/paprika/tree/master/packages/CollapsibleList" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"dependencies": { | ||
"@babel/runtime-corejs2": "^7.3.1", | ||
"@paprika/collapsible": "^0.1.0", | ||
"@paprika/stylers": "^0.1.1", | ||
"@paprika/tokens": "^0.1.1", | ||
"class-names": "^1.0.0", | ||
"prop-types": "^15.7.2" | ||
}, | ||
"peerDependencies": { | ||
"react": "^16.8.0", | ||
"react-dom": "^16.8.0", | ||
"styled-components": "^4.2.0" | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
packages/CollapsibleChecklists/src/CollapsibleChecklists.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
// import CollapsibleChecklistsStyles from "./CollapsibleChecklists.styles"; | ||
import Heading from "./components/Heading"; | ||
import Group from "./components/Group"; | ||
import Item from "./components/Item"; | ||
|
||
const propTypes = { | ||
children: PropTypes.node, | ||
}; | ||
|
||
const defaultProps = {}; | ||
|
||
const CollapsibleChecklists = props => { | ||
const { children, onChange } = props; | ||
|
||
return children.map((child, index) => { | ||
switch (child.type.displayName) { | ||
case Heading.displayName: | ||
return <Heading key={`heading${index}`} {...child.props} />; // eslint-disable-line react/no-array-index-key | ||
case Group.displayName: | ||
return <Group key={`group${index}`} {...child.props} onChange={onChange} />; // eslint-disable-line react/no-array-index-key | ||
default: | ||
return child; | ||
} | ||
}); | ||
}; | ||
|
||
CollapsibleChecklists.displayName = "CollapsibleChecklists"; | ||
CollapsibleChecklists.propTypes = propTypes; | ||
CollapsibleChecklists.defaultProps = defaultProps; | ||
|
||
CollapsibleChecklists.Heading = Heading; | ||
CollapsibleChecklists.Group = Group; | ||
CollapsibleChecklists.Item = Item; | ||
|
||
export default CollapsibleChecklists; |
109 changes: 109 additions & 0 deletions
109
packages/CollapsibleChecklists/src/components/Group/Group.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
import Collapsible from "@paprika/collapsible"; | ||
import Item from "../Item"; | ||
|
||
const propTypes = { | ||
children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]), // are probably an array of "Items", but could be a Spinner or anything else | ||
isDisabled: PropTypes.bool, | ||
onChange: PropTypes.func, | ||
onExpand: PropTypes.func, | ||
title: PropTypes.node.isRequired, | ||
}; | ||
|
||
const defaultProps = { | ||
children: [], | ||
isDisabled: false, | ||
onChange: () => {}, | ||
onExpand: () => {}, | ||
}; | ||
|
||
function useIsIndeterminate(checkboxRef) { | ||
const [, setIsIndeterminate] = React.useState(null); | ||
React.useEffect(() => { | ||
setIsIndeterminate(checkboxRef.current.indeterminate); | ||
}, [checkboxRef.current.indeterminate]); | ||
} | ||
|
||
function Group(props) { | ||
const { children, isDisabled, onChange, onExpand, title } = props; | ||
const [isCollapsed, setIsCollapsed] = React.useState(true); | ||
const checkboxRef = React.useRef({}); | ||
useIsIndeterminate(checkboxRef); | ||
let allAreChecked = React.Children.count(props.children) > 0; | ||
let noneAreChecked = true; | ||
|
||
React.Children.forEach(children, child => { | ||
if (child.props.isChecked) { | ||
noneAreChecked = false; | ||
} else { | ||
allAreChecked = false; | ||
} | ||
}); | ||
|
||
if (allAreChecked || noneAreChecked) { | ||
checkboxRef.current.indeterminate = false; | ||
} else if (!allAreChecked && !noneAreChecked) { | ||
checkboxRef.current.indeterminate = true; | ||
} | ||
|
||
function handleOnChange() { | ||
const allChildrenAreChecked = | ||
children.filter(child => child.props.isChecked || child.props.isDisabled).length === children.length; | ||
|
||
let childrenToChange = []; | ||
if (allChildrenAreChecked) { | ||
childrenToChange = children.filter(child => !child.props.isDisabled); | ||
} else { | ||
childrenToChange = children.filter(child => !child.props.isChecked && !child.props.isDisabled); | ||
} | ||
|
||
onChange(childrenToChange); | ||
} | ||
|
||
const label = ( | ||
<React.Fragment> | ||
<input | ||
ref={checkboxRef} | ||
checked={allAreChecked} | ||
type="checkbox" | ||
disabled={isDisabled} | ||
onChange={handleOnChange} | ||
/> | ||
{title} | ||
</React.Fragment> | ||
); | ||
|
||
const modifiedChildren = React.Children.map(children, child => { | ||
const newProps = | ||
child.type.displayName === Item.displayName | ||
? { | ||
onChange: () => onChange([child]), | ||
} | ||
: null; | ||
return React.cloneElement(child, newProps); | ||
}); | ||
|
||
return ( | ||
<Collapsible | ||
a11yText="umm..." | ||
hasOnlyIconToggle | ||
isCollapsed={isCollapsed} | ||
isDisabled={isDisabled} | ||
label={label} | ||
onClick={() => { | ||
if (isCollapsed && onExpand) { | ||
onExpand(); | ||
} | ||
setIsCollapsed(!isCollapsed); | ||
}} | ||
> | ||
{modifiedChildren} | ||
</Collapsible> | ||
); | ||
} | ||
|
||
Group.displayName = "Group"; | ||
Group.propTypes = propTypes; | ||
Group.defaultProps = defaultProps; | ||
export default Group; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from "./Group"; |
19 changes: 19 additions & 0 deletions
19
packages/CollapsibleChecklists/src/components/Heading/Heading.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
import headingStyles from "./Heading.styles"; | ||
|
||
const propTypes = { | ||
children: PropTypes.node.isRequired, | ||
}; | ||
|
||
const defaultProps = {}; | ||
|
||
const Heading = ({ children }) => { | ||
return <div css={headingStyles}>{children}</div>; | ||
}; | ||
|
||
Heading.displayName = "Heading"; | ||
Heading.propTypes = propTypes; | ||
Heading.defaultProps = defaultProps; | ||
|
||
export default Heading; |
9 changes: 9 additions & 0 deletions
9
packages/CollapsibleChecklists/src/components/Heading/Heading.styles.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import tokens from "@paprika/tokens"; | ||
// import stylers from "@paprika/stylers"; | ||
|
||
const headingStyles = () => ` | ||
background-color: ${tokens.color.blackLighten70}; | ||
font-weight: bold; | ||
`; | ||
|
||
export default headingStyles; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from "./Heading"; |
31 changes: 31 additions & 0 deletions
31
packages/CollapsibleChecklists/src/components/Item/Item.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
|
||
const propTypes = { | ||
children: PropTypes.node.isRequired, | ||
isChecked: PropTypes.bool, | ||
isDisabled: PropTypes.bool, | ||
onChange: PropTypes.func, | ||
}; | ||
|
||
const defaultProps = { | ||
isChecked: false, | ||
isDisabled: false, | ||
onChange: () => {}, | ||
}; | ||
|
||
function Item(props) { | ||
const { children, isChecked, isDisabled, onChange } = props; | ||
|
||
return ( | ||
<div style={{ marginLeft: "16px" }}> | ||
<input type="checkbox" checked={isChecked} disabled={isDisabled} onChange={onChange} /> {children} | ||
</div> | ||
); | ||
} | ||
|
||
Item.displayName = "Item"; | ||
Item.propTypes = propTypes; | ||
Item.defaultProps = defaultProps; | ||
|
||
export default Item; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from "./Item"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import CollapsibleChecklists from "./CollapsibleChecklists"; | ||
|
||
export { CollapsibleChecklists as default }; |
9 changes: 9 additions & 0 deletions
9
packages/CollapsibleChecklists/stories/CollapsibleChecklists.stories.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import React from "react"; | ||
import { storiesOf } from "@storybook/react"; | ||
import { withKnobs } from "@storybook/addon-knobs"; | ||
|
||
import BasicExample from "./examples/Basic"; | ||
|
||
storiesOf("CollapsibleChecklists", module) | ||
.addDecorator(withKnobs) | ||
.add("Basic", () => <BasicExample />); |
Oops, something went wrong.