Comparing version 0.18.0 to 0.19.0-beta1
{ | ||
"name": "gestalt", | ||
"version": "0.18.0", | ||
"version": "0.19.0-beta1", | ||
"license": "SEE LICENSE IN LICENSE", | ||
@@ -103,5 +103,3 @@ "homepage": "https://pinterest.github.io/gestalt", | ||
"jest": { | ||
"modulePathIgnorePatterns": [ | ||
"\\.ghost\\.js$" | ||
], | ||
"testRegex": "jest\\.js$", | ||
"moduleNameMapper": { | ||
@@ -108,0 +106,0 @@ "\\.(svg)$": "<rootDir>/src/__mocks__/fileMock.js", |
@@ -57,7 +57,7 @@ // @flow | ||
props: { | ||
props: {| | ||
name: string, | ||
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl', | ||
src?: string, | ||
}; | ||
|}; | ||
@@ -64,0 +64,0 @@ render() { |
@@ -180,2 +180,3 @@ // @flow | ||
\`\`\`jsx | ||
<Box color="red" /> | ||
<Box color="white" /> | ||
@@ -185,6 +186,12 @@ <Box color="lightGray" /> | ||
<Box color="darkGray" /> | ||
<Box color="red" /> | ||
<Box color="green" /> | ||
<Box color="pine" /> | ||
<Box color="olive" /> | ||
<Box color="blue" /> | ||
<Box color="slate" /> | ||
<Box color="pine" /> | ||
<Box color="navy" /> | ||
<Box color="midnight" /> | ||
<Box color="purple" /> | ||
<Box color="eggplant" /> | ||
<Box color="maroon" /> | ||
<Box color="watermelon" /> | ||
<Box color="orange" /> | ||
@@ -195,2 +202,3 @@ <Box color="transparent" /> | ||
<Box xs={{ display: 'flex' }} wrap> | ||
<ColorSwatch color="red" /> | ||
<ColorSwatch color="white" /> | ||
@@ -200,6 +208,12 @@ <ColorSwatch color="lightGray" /> | ||
<ColorSwatch color="darkGray" /> | ||
<ColorSwatch color="red" /> | ||
<ColorSwatch color="green" /> | ||
<ColorSwatch color="pine" /> | ||
<ColorSwatch color="olive" /> | ||
<ColorSwatch color="blue" /> | ||
<ColorSwatch color="slate" /> | ||
<ColorSwatch color="pine" /> | ||
<ColorSwatch color="navy" /> | ||
<ColorSwatch color="midnight" /> | ||
<ColorSwatch color="purple" /> | ||
<ColorSwatch color="eggplant" /> | ||
<ColorSwatch color="maroon" /> | ||
<ColorSwatch color="watermelon" /> | ||
<ColorSwatch color="orange" /> | ||
@@ -206,0 +220,0 @@ <ColorSwatch color="transparent" /> |
@@ -6,4 +6,4 @@ // @flow | ||
import styles from './Box.css'; | ||
import colors from '../Colors.css'; | ||
// -- | ||
@@ -305,3 +305,4 @@ | ||
type Color = 'blue' | 'darkGray' | 'pine' | 'gray' | 'red' | 'slate' | 'lightGray' | 'white' | 'orange' | 'transparent'; | ||
type Color = 'blue' | 'darkGray' | 'pine' | 'gray' | 'red' | 'olive' | 'lightGray' | 'white' |'orange' | | ||
'green' | 'navy' | 'midnight' | 'purple' | 'orchid' | 'eggplant' | 'maroon' | 'watermelon' | 'transparent'; | ||
@@ -311,19 +312,35 @@ const color = (value: Color): Style => { | ||
case 'blue': | ||
return fromClassName('bg-blue'); | ||
return fromClassName(colors['bg-blue']); | ||
case 'darkGray': | ||
return fromClassName('bg-dark-gray'); | ||
return fromClassName(colors['bg-darkGray']); | ||
case 'pine': | ||
return fromClassName('bg-pine'); | ||
return fromClassName(colors['bg-pine']); | ||
case 'gray': | ||
return fromClassName('bg-gray'); | ||
return fromClassName(colors['bg-gray']); | ||
case 'red': | ||
return fromClassName('bg-red'); | ||
case 'slate': | ||
return fromClassName('bg-slate'); | ||
return fromClassName(colors['bg-red']); | ||
case 'olive': | ||
return fromClassName(colors['bg-olive']); | ||
case 'lightGray': | ||
return fromClassName('bg-light-gray'); | ||
return fromClassName(colors['bg-lightGray']); | ||
case 'white': | ||
return fromClassName('bg-white'); | ||
return fromClassName(colors['bg-white']); | ||
case 'orange': | ||
return fromClassName('bg-orange'); | ||
return fromClassName(colors['bg-orange']); | ||
case 'green': | ||
return fromClassName(colors['bg-green']); | ||
case 'navy': | ||
return fromClassName(colors['bg-navy']); | ||
case 'midnight': | ||
return fromClassName(colors['bg-midnight']); | ||
case 'purple': | ||
return fromClassName(colors['bg-purple']); | ||
case 'orchid': | ||
return fromClassName(colors['bg-orchid']); | ||
case 'eggplant': | ||
return fromClassName(colors['bg-eggplant']); | ||
case 'maroon': | ||
return fromClassName(colors['bg-maroon']); | ||
case 'watermelon': | ||
return fromClassName(colors['bg-watermelon']); | ||
default /* transparent */: | ||
@@ -554,6 +571,14 @@ return identity(); | ||
'red', | ||
'slate', | ||
'olive', | ||
'lightGray', | ||
'white', | ||
'orange', | ||
'green', | ||
'navy', | ||
'midnight', | ||
'purple', | ||
'orchid', | ||
'eggplant', | ||
'maroon', | ||
'watermelon', | ||
'transparent', | ||
@@ -560,0 +585,0 @@ ]), |
@@ -10,3 +10,3 @@ // @flow | ||
type Props<T> = { | ||
type Props<T> = {| | ||
comp: () => void, | ||
@@ -18,3 +18,3 @@ items: T[], | ||
scrollContainer: HTMLElement, | ||
}; | ||
|}; | ||
@@ -21,0 +21,0 @@ export default class BoxGrid extends Component { |
@@ -17,4 +17,4 @@ // @flow | ||
type Props = { | ||
ariaExpanded?: boolean, /* accessibility */ | ||
ariaHaspopup?: boolean, /* accessibility */ | ||
accessibilityExpanded?: boolean, | ||
accessibilityHaspopup?: boolean, | ||
color?: 'gray' | 'red' | 'blue', /* default: gray */ | ||
@@ -21,0 +21,0 @@ disabled?: boolean, /* default: false */ |
@@ -7,5 +7,5 @@ // @flow | ||
type Props = { | ||
ariaExpanded?: boolean, | ||
ariaHaspopup?: boolean, | ||
type Props = {| | ||
accessibilityExpanded?: boolean, | ||
accessibilityHaspopup?: boolean, | ||
color?: 'gray' | 'red' | 'blue', | ||
@@ -17,3 +17,3 @@ disabled?: boolean, | ||
type?: 'submit' | 'button', | ||
} | ||
|} | ||
@@ -26,4 +26,4 @@ type GestaltContext = { | ||
const { | ||
ariaExpanded, | ||
ariaHaspopup, | ||
accessibilityExpanded, | ||
accessibilityHaspopup, | ||
color = 'gray', | ||
@@ -50,4 +50,4 @@ disabled = false, | ||
<button | ||
aria-expanded={ariaExpanded} | ||
aria-haspopup={ariaHaspopup} | ||
aria-expanded={accessibilityExpanded} | ||
aria-haspopup={accessibilityHaspopup} | ||
className={classes} | ||
@@ -68,4 +68,4 @@ disabled={disabled} | ||
Button.propTypes = { | ||
ariaExpanded: PropTypes.bool, | ||
ariaHaspopup: PropTypes.bool, | ||
accessibilityExpanded: PropTypes.bool, | ||
accessibilityHaspopup: PropTypes.bool, | ||
color: PropTypes.oneOf(['blue', 'gray', 'red']), | ||
@@ -72,0 +72,0 @@ disabled: PropTypes.bool, |
@@ -23,3 +23,3 @@ // @flow | ||
type Props = { | ||
ariaLabel: String, | ||
accessibilityLabel: String, | ||
children?: any | ||
@@ -34,3 +34,3 @@ } | ||
\`\`\`html | ||
<Card ariaLabel="Ben Silbermann - Pinterest CEO"> | ||
<Card accessibilityLabel="Ben Silbermann - Pinterest CEO"> | ||
<Box> | ||
@@ -59,3 +59,3 @@ <Link color="darkGray" href="https://pinterest.com"> | ||
> | ||
<Card ariaLabel="Ben Silbermann - Pinterest CEO"> | ||
<Card accessibilityLabel="Ben Silbermann - Pinterest CEO"> | ||
<Link color="darkGray" href="https://pinterest.com"> | ||
@@ -71,3 +71,3 @@ <Avatar | ||
</Link> | ||
<Button color="red" fullWidth text="Follow" /> | ||
<Button color="red" text="Follow" /> | ||
</Card> | ||
@@ -80,3 +80,3 @@ </Box> | ||
> | ||
<Card ariaLabel="Evan Sharp - Pinterest Co-Founder"> | ||
<Card accessibilityLabel="Evan Sharp - Pinterest Co-Founder"> | ||
<Link color="darkGray" href="https://pinterest.com"> | ||
@@ -92,3 +92,3 @@ <Avatar | ||
</Link> | ||
<Button color="red" fullWidth text="Follow" /> | ||
<Button color="red" text="Follow" /> | ||
</Card> | ||
@@ -95,0 +95,0 @@ </Box> |
@@ -13,5 +13,5 @@ /* eslint-env jest */ | ||
it('renders an empty Card', () => snapshot(<Card ariaLabel="Empty card" />)); | ||
it('renders an empty Card', () => snapshot(<Card accessibilityLabel="Empty card" />)); | ||
it('renders a Card with text', () => | ||
snapshot(<Card ariaLabel="Chris Lloyd - founder of Box">Chris Lloyd</Card>) | ||
snapshot(<Card accessibilityLabel="Chris Lloyd - founder of Box">Chris Lloyd</Card>) | ||
); |
@@ -11,3 +11,3 @@ // @flow | ||
static PropTypes = { | ||
ariaLabel: PropTypes.string.isRequired, | ||
accessibilityLabel: PropTypes.string.isRequired, | ||
children: PropTypes.node | ||
@@ -24,6 +24,6 @@ } | ||
static props: { | ||
ariaLabel: String, | ||
static props: {| | ||
accessibilityLabel: String, | ||
children?: any | ||
} | ||
|} | ||
@@ -54,3 +54,3 @@ state = { | ||
const { | ||
ariaLabel, | ||
accessibilityLabel, | ||
children | ||
@@ -73,3 +73,3 @@ } = this.props; | ||
<Box | ||
aria-label={ariaLabel} | ||
aria-label={accessibilityLabel} | ||
disableFocusStyles={inputDevice !== 'key'} | ||
@@ -76,0 +76,0 @@ onBlur={this.handleBlur} |
@@ -9,3 +9,3 @@ // @flow | ||
type Props<T> = { | ||
type Props<T> = {| | ||
columnWidth: number, | ||
@@ -18,3 +18,3 @@ comp: () => void, | ||
scrollContainer: HTMLElement, | ||
}; | ||
|}; | ||
@@ -21,0 +21,0 @@ export default class ClassicGrid extends Component { |
@@ -7,3 +7,3 @@ /* @flow */ | ||
type Props = { | ||
type Props = {| | ||
children?: any, | ||
@@ -14,3 +14,3 @@ xs: Columns, | ||
lg?: Columns, | ||
}; | ||
|}; | ||
@@ -17,0 +17,0 @@ export default function Column(props: Props) { |
@@ -5,5 +5,5 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
children?: any, | ||
} | ||
|} | ||
@@ -10,0 +10,0 @@ export default function Container(props: Props) { |
@@ -8,3 +8,3 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
id?: string, | ||
@@ -17,3 +17,3 @@ idealDirection?: 'up' | 'right' | 'down' | 'left', | ||
trigger: React$Element<any>, | ||
}; | ||
|}; | ||
@@ -20,0 +20,0 @@ export default function ErrorFlyout(props: Props) { |
@@ -18,4 +18,4 @@ // @flow | ||
type Props = { | ||
accessibilityCloseLabel: string, // needed for accessibility and internationalization | ||
children?: any, | ||
closeLabel: string, // needed for accessibility and internationalization | ||
idealDirection?: 'up' | 'right' | 'down' | 'left', | ||
@@ -158,3 +158,3 @@ isOpen?: boolean, | ||
<Flyout | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
idealDirection="down" | ||
@@ -165,5 +165,5 @@ isOpen={this.state.isOpen} | ||
<IconButton | ||
aria-expanded={this.state.isOpen} | ||
aria-haspopup | ||
label="More options" | ||
accessibilityExpanded={this.state.isOpen} | ||
accessibilityHaspopup | ||
accessibilityLabel="More options" | ||
icon="ellipsis" | ||
@@ -181,3 +181,3 @@ onClick={() => this.setState({ isOpen: !this.state.isOpen })} | ||
<Flyout | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
idealDirection="right" | ||
@@ -188,5 +188,5 @@ isOpen={this.state.isOpen} | ||
<IconButton | ||
aria-expanded={this.state.isOpen} | ||
aria-haspopup | ||
label="Profile options" | ||
accessibilityExpanded={this.state.isOpen} | ||
accessibilityHaspopup | ||
accessibilityLabel="Profile options" | ||
icon="person" | ||
@@ -203,3 +203,3 @@ onClick={() => this.setState({ isOpen: !this.state.isOpen })} | ||
<Flyout | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
isOpen={this.state.isOpen} | ||
@@ -209,5 +209,5 @@ onDismiss={() => this.setState({ isOpen: false })} | ||
<IconButton | ||
aria-expanded={this.state.isOpen} | ||
aria-haspopup | ||
label="Add pin" | ||
accessibilityExpanded={this.state.isOpen} | ||
accessibilityHaspopup | ||
accessibilityLabel="Add pin" | ||
icon="plus" | ||
@@ -224,3 +224,3 @@ onClick={() => this.setState({ isOpen: !this.state.isOpen })} | ||
<Flyout | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
idealDirection="up" | ||
@@ -231,4 +231,4 @@ isOpen={this.state.isOpen} | ||
<Button | ||
aria-expanded={this.state.isOpen} | ||
aria-haspopup | ||
accessibilityExpanded={this.state.isOpen} | ||
accessibilityHaspopup | ||
text="Help" | ||
@@ -248,3 +248,3 @@ onClick={() => this.setState({ isOpen: !this.state.isOpen })} | ||
<Flyout | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
idealDirection="right" | ||
@@ -255,6 +255,6 @@ isOpen={!!atom.deref().more} | ||
<IconButton | ||
aria-expanded={!!atom.deref().more} | ||
aria-haspopup | ||
accessibilityLabel="More options" | ||
accessibilityExpanded={!!atom.deref().more} | ||
accessibilityHaspopup | ||
icon="ellipsis" | ||
label="More options" | ||
onClick={() => atom.reset({ more: !atom.deref().more })} | ||
@@ -271,3 +271,3 @@ /> | ||
<Flyout | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
idealDirection="right" | ||
@@ -278,6 +278,6 @@ isOpen={!!atom.deref().profile} | ||
<IconButton | ||
aria-expanded={!!atom.deref().profile} | ||
aria-haspopup | ||
accessibilityLabel="Profile options" | ||
accessibilityExpanded={!!atom.deref().profile} | ||
accessibilityHaspopup | ||
icon="person" | ||
label="Profile options" | ||
onClick={() => atom.reset({ profile: !atom.deref().profile })} | ||
@@ -293,3 +293,3 @@ /> | ||
<Flyout | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
isOpen={!!atom.deref().add} | ||
@@ -299,6 +299,6 @@ onDismiss={() => atom.reset({ add: false })} | ||
<IconButton | ||
aria-expanded={!!atom.deref().add} | ||
aria-haspopup | ||
accessibilityLabel="Add pin" | ||
accessibilityExpanded={!!atom.deref().add} | ||
accessibilityHaspopup | ||
icon="add" | ||
label="Add pin" | ||
onClick={() => atom.reset({ add: !atom.deref().add })} | ||
@@ -314,3 +314,3 @@ /> | ||
<Flyout | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
idealDirection="up" | ||
@@ -321,4 +321,4 @@ isOpen={!!atom.deref().help} | ||
<Button | ||
aria-expanded={!!atom.deref().help} | ||
aria-haspopup | ||
accessibilityExpanded={!!atom.deref().help} | ||
accessibilityHaspopup | ||
onClick={() => atom.reset({ help: !atom.deref().help })} | ||
@@ -325,0 +325,0 @@ text="Help" |
@@ -10,3 +10,3 @@ /* eslint-env jest */ | ||
<Flyout | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
idealDirection="down" | ||
@@ -33,3 +33,3 @@ isOpen={false} | ||
<Flyout | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
idealDirection="down" | ||
@@ -36,0 +36,0 @@ isOpen={false} |
@@ -11,3 +11,3 @@ /* eslint-env jest */ | ||
<MobileFlyout | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
isOpen={false} | ||
@@ -25,3 +25,3 @@ onDismiss={() => null} | ||
<MobileFlyout | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
isOpen | ||
@@ -28,0 +28,0 @@ onDismiss={() => null} |
@@ -9,5 +9,5 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
accessibilityCloseLabel: string, | ||
children?: any, | ||
closeLabel: string, | ||
idealDirection?: 'up' | 'right' | 'down' | 'left', | ||
@@ -18,3 +18,3 @@ isOpen: boolean, | ||
trigger: React$Element<any>, | ||
}; | ||
|}; | ||
@@ -62,7 +62,15 @@ type State = { | ||
render() { | ||
const { children, closeLabel, idealDirection, isOpen, onDismiss, size, trigger } = this.props; | ||
const { | ||
accessibilityCloseLabel, | ||
children, | ||
idealDirection, | ||
isOpen, | ||
onDismiss, | ||
size, | ||
trigger | ||
} = this.props; | ||
return this.state.breakpoint === 'xs' ? ( | ||
<MobileFlyout | ||
closeLabel={closeLabel} | ||
accessibilityCloseLabel={accessibilityCloseLabel} | ||
isOpen={isOpen} | ||
@@ -78,3 +86,2 @@ onDismiss={onDismiss} | ||
bgColor="white" | ||
closeLabel={closeLabel} | ||
idealDirection={idealDirection} | ||
@@ -97,3 +104,3 @@ isOpen={isOpen} | ||
children: PropTypes.node, | ||
closeLabel: PropTypes.string.isRequired, | ||
accessibilityCloseLabel: PropTypes.string.isRequired, | ||
idealDirection: PropTypes.oneOf(['up', 'right', 'down', 'left']), | ||
@@ -100,0 +107,0 @@ isOpen: PropTypes.bool.isRequired, |
@@ -12,3 +12,3 @@ // @flow | ||
children?: any, | ||
closeLabel: string, | ||
accessibilityCloseLabel: string, | ||
isOpen: boolean, | ||
@@ -50,3 +50,3 @@ onDismiss: () => void, | ||
render() { | ||
const { children, closeLabel, isOpen, onDismiss, trigger } = this.props; | ||
const { children, accessibilityCloseLabel, isOpen, onDismiss, trigger } = this.props; | ||
return ( | ||
@@ -66,3 +66,3 @@ <div className="inline-block"> | ||
<div className={cx('pull-right')}> | ||
<IconButton icon="cancel" label={closeLabel} onClick={onDismiss} /> | ||
<IconButton accessibilityLabel={accessibilityCloseLabel} icon="cancel" onClick={onDismiss} /> | ||
</div> | ||
@@ -81,3 +81,3 @@ {children} | ||
children: PropTypes.node, | ||
closeLabel: PropTypes.string.isRequired, | ||
accessibilityCloseLabel: PropTypes.string.isRequired, | ||
isOpen: PropTypes.bool.isRequired, | ||
@@ -84,0 +84,0 @@ onDismiss: PropTypes.func.isRequired, |
@@ -150,3 +150,3 @@ /* eslint-env jest */ | ||
<Contents | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
onClick={jest.fn()} | ||
@@ -153,0 +153,0 @@ onDismiss={jest.fn()} |
@@ -15,3 +15,3 @@ /* eslint-env jest */ | ||
<Controller | ||
closeLabel="close" | ||
accessibilityCloseLabel="close" | ||
isOpen={false} | ||
@@ -18,0 +18,0 @@ onDismiss={() => null} |
@@ -45,3 +45,3 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
bgColor: 'dark-gray' | 'white' | 'orange', | ||
@@ -56,3 +56,3 @@ children?: any, | ||
width: number, | ||
}; | ||
|}; | ||
@@ -59,0 +59,0 @@ type State = { |
@@ -6,3 +6,3 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
bgColor: 'dark-gray' | 'white' | 'orange', | ||
@@ -16,3 +16,3 @@ children?: any, | ||
trigger: React$Element<any>, | ||
}; | ||
|}; | ||
@@ -19,0 +19,0 @@ const SIZE_WIDTH_MAP = { |
@@ -5,4 +5,8 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
children?: any, | ||
|}; | ||
type State = { | ||
inputDevice: string, | ||
}; | ||
@@ -16,3 +20,3 @@ | ||
static childContextTypes = { | ||
inputDevice: React.PropTypes.string | ||
inputDevice: React.PropTypes.string, | ||
}; | ||
@@ -24,31 +28,21 @@ | ||
this.state = { | ||
inputDevice: 'key' | ||
inputDevice: 'key', | ||
}; | ||
} | ||
state: { | ||
inputDevice: string, | ||
} | ||
state: State; | ||
getChildContext() { | ||
return { | ||
inputDevice: this.state.inputDevice | ||
inputDevice: this.state.inputDevice, | ||
}; | ||
} | ||
componentDidMount() { | ||
document.addEventListener('keydown', this.onKeyDown); | ||
document.addEventListener('mousedown', this.onMouseDown); | ||
document.addEventListener('touchstart', this.onTouchStart); | ||
shouldComponentUpdate(nextProps: Props, nextState: State) { | ||
return this.state.inputDevice !== nextState.inputDevice; | ||
} | ||
componentWillUnmount() { | ||
document.removeEventListener('keydown', this.onKeyDown); | ||
document.removeEventListener('mousedown', this.onMouseDown); | ||
document.removeEventListener('touchstart', this.onTouchStart); | ||
} | ||
onKeyDown = () => { | ||
this.setState({ | ||
inputDevice: 'key' | ||
inputDevice: 'key', | ||
}); | ||
@@ -59,3 +53,3 @@ } | ||
this.setState({ | ||
inputDevice: 'mouse' | ||
inputDevice: 'mouse', | ||
}); | ||
@@ -66,3 +60,3 @@ } | ||
this.setState({ | ||
inputDevice: 'touch' | ||
inputDevice: 'touch', | ||
}); | ||
@@ -73,3 +67,7 @@ } | ||
return ( | ||
<Box> | ||
<Box | ||
onKeyDown={this.onKeyDown} | ||
onMouseDown={this.onMouseDown} | ||
onTouchStart={this.onTouchStart} | ||
> | ||
{this.props.children} | ||
@@ -76,0 +74,0 @@ </Box> |
@@ -43,6 +43,6 @@ // @flow | ||
type GroupAvatarProps = { | ||
type GroupAvatarProps = {| | ||
collaborators: Array<CollabProps>, | ||
size: 'xs' | 'sm' | 'md' | 'lg' | 'xl', | ||
}; | ||
|}; | ||
@@ -49,0 +49,0 @@ type GridItemPropsType = { |
@@ -23,3 +23,3 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
accessibilityLevel?: 1 | 2 | 3 | 4 | 5 | 6, | ||
@@ -30,3 +30,3 @@ children?: any, | ||
truncate?: bool, | ||
}; | ||
|}; | ||
@@ -33,0 +33,0 @@ export default function Heading(props: Props) { |
@@ -16,3 +16,3 @@ // @flow | ||
type IconProps = { | ||
ariaLabel: string, | ||
accessibilityLabel: string, | ||
color?: 'white' | 'gray' | 'darkGray' | 'blue' | 'red', /* default: gray */ | ||
@@ -41,7 +41,7 @@ /* $Keys is an undocumented feature of Flow that helps with creating enums dynamically. | ||
if (color !== 'white') { | ||
return <Icon icon="pin" ariaLabel="Pin" color={color} />; | ||
return <Icon icon="pin" accessibilityLabel="Pin" color={color} />; | ||
} | ||
return ( | ||
<Box xs={{ display: 'flexColumn' }} alignItems="center" color="darkGray" shape="circle" justifyContent="center" dangerouslySetInlineStyle={{ __style: { minWidth: 26, minHeight: 26 } }}> | ||
<Icon icon="pin" ariaLabel="Pin" color="white" /> | ||
<Icon icon="pin" accessibilityLabel="Pin" color="white" /> | ||
</Box> | ||
@@ -54,4 +54,4 @@ ); | ||
\`\`\`html | ||
<Icon icon="pin" ariaLabel="Pin" /> | ||
<Icon icon="pin" ariaLabel="Pin" color="darkGray" /> | ||
<Icon icon="pin" accessibilityLabel="Pin" /> | ||
<Icon icon="pin" accessibilityLabel="Pin" color="darkGray" /> | ||
\`\`\` | ||
@@ -76,7 +76,7 @@ `, | ||
\`\`\`html | ||
<Icon icon="pin" ariaLabel="Pin" size={16} /> | ||
<Icon icon="pin" ariaLabel="Pin" size={20} /> | ||
<Icon icon="pin" ariaLabel="Pin" size={24} /> | ||
<Icon icon="pin" ariaLabel="Pin" size={28} /> | ||
<Icon icon="pin" ariaLabel="Pin" size={32} /> | ||
<Icon icon="pin" accessibilityLabel="Pin" size={16} /> | ||
<Icon icon="pin" accessibilityLabel="Pin" size={20} /> | ||
<Icon icon="pin" accessibilityLabel="Pin" size={24} /> | ||
<Icon icon="pin" accessibilityLabel="Pin" size={28} /> | ||
<Icon icon="pin" accessibilityLabel="Pin" size={32} /> | ||
\`\`\` | ||
@@ -90,3 +90,3 @@ `, | ||
</Box> | ||
<Icon icon="pin" ariaLabel="Pin" size={size} /> | ||
<Icon icon="pin" accessibilityLabel="Pin" size={size} /> | ||
</Box> | ||
@@ -103,3 +103,3 @@ )} | ||
</Box> | ||
<Icon icon={iconName} ariaLabel={iconName.replace(/-/g, ' ')} color="gray" /> | ||
<Icon icon={iconName} accessibilityLabel={iconName.replace(/-/g, ' ')} color="gray" /> | ||
</Box> | ||
@@ -116,7 +116,7 @@ ); | ||
\`\`\`html | ||
<Icon icon="pin" ariaLabel="Pin" /> | ||
<Icon icon="add-circle" ariaLabel="Add" /> | ||
<Icon icon="add-pin" ariaLabel="Add a Pin" /> | ||
<Icon icon="arrow-back" ariaLabel="Back" /> | ||
<Icon icon="arrow-circle-forward" ariaLabel="Forward" /> | ||
<Icon icon="pin" accessibilityLabel="Pin" /> | ||
<Icon icon="add-circle" accessibilityLabel="Add" /> | ||
<Icon icon="add-pin" accessibilityLabel="Add a Pin" /> | ||
<Icon icon="arrow-back" accessibilityLabel="Back" /> | ||
<Icon icon="arrow-circle-forward" accessibilityLabel="Forward" /> | ||
\`\`\` | ||
@@ -123,0 +123,0 @@ `, |
@@ -19,2 +19,3 @@ // @flow | ||
type IconProps = { | ||
accessibilityLabel: string, | ||
color?: Color, | ||
@@ -25,3 +26,2 @@ /* $Keys is an undocumented feature of Flow that helps with creating enums dynamically. | ||
*/ | ||
ariaLabel: string, | ||
icon: $Keys<typeof icons>, | ||
@@ -34,3 +34,3 @@ inline?: boolean, | ||
const { | ||
ariaLabel, | ||
accessibilityLabel, | ||
color = 'gray', | ||
@@ -51,4 +51,4 @@ icon, | ||
return ( | ||
<svg className={cs} height={size} width={size} viewBox="0 0 16 16" aria-label={ariaLabel} role="img"> | ||
<title>{ariaLabel}</title> | ||
<svg className={cs} height={size} width={size} viewBox="0 0 16 16" aria-label={accessibilityLabel} role="img"> | ||
<title>{accessibilityLabel}</title> | ||
<path d={path} /> | ||
@@ -60,3 +60,3 @@ </svg> | ||
Icon.propTypes = { | ||
ariaLabel: PropTypes.string.isRequired, | ||
accessibilityLabel: PropTypes.string.isRequired, | ||
color: PropTypes.oneOf(['white', 'gray', 'darkGray', 'blue', 'red']), | ||
@@ -63,0 +63,0 @@ icon: PropTypes.oneOf(Object.keys(icons)).isRequired, |
// @flow | ||
import React from 'react'; | ||
import { card, md } from 'corkboard'; | ||
import { ns } from '../../../.corkboard/cards'; | ||
import Box from '../../Box/Box'; | ||
import GestaltProvider from '../../GestaltProvider/GestaltProvider'; | ||
import IconButton from '../IconButton'; | ||
import { ns } from '../../../.corkboard/cards'; | ||
@@ -15,4 +17,5 @@ ns('IconButton', | ||
type Props = { | ||
ariaExpanded?: boolean, /* accessibility */ | ||
ariaHaspopup?: boolean, /* accessibility */ | ||
accessibilityExpanded?: boolean, | ||
accessibilityHaspopup?: boolean, | ||
accessibilityLabel: string, | ||
bgColor?: 'transparent' | 'lightGray', /* default: transparent */ | ||
@@ -25,3 +28,2 @@ iconColor?: 'gray' | 'darkGray' | 'red' | 'blue', /* default: gray */ | ||
icon: $Keys<typeof icons>, | ||
label: string, | ||
onClick?: () => void, | ||
@@ -49,5 +51,5 @@ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl', /* default: md */ | ||
<IconButton | ||
accessibilityLabel={icon.replace(/-/g, ' ')} | ||
bgColor={bgColor} | ||
icon={icon} | ||
label={icon.replace(/-/g, ' ')} | ||
size={size} | ||
@@ -67,5 +69,5 @@ /> | ||
<IconButton | ||
accessibilityLabel="cancel" | ||
bgColor="lightGray" | ||
icon="cancel" | ||
label="cancel" | ||
size="sm" | ||
@@ -75,10 +77,14 @@ /> | ||
`, | ||
<div className="flex mxn2 flex-wrap"> | ||
{sizes.map((size, key) => | ||
<div className="col-2 text-center border-box" key={key}> | ||
<h5>{size}</h5> | ||
<IconButtonEx icon="heart" size={size} /> | ||
</div> | ||
)} | ||
</div> | ||
<GestaltProvider> | ||
<Box xs={{ display: 'flex' }} margin={{ left: -2, right: -2 }} wrap> | ||
{sizes.map((size, key) => | ||
<Box xs={{ display: 'flexColumn' }} alignItems="center" padding={{ x: 3 }} key={key}> | ||
<h5>{size}</h5> | ||
<Box xs={{ display: 'flex' }} justifyContent="center"> | ||
<IconButtonEx icon="heart" size={size} /> | ||
</Box> | ||
</Box> | ||
)} | ||
</Box> | ||
</GestaltProvider> | ||
); | ||
@@ -99,4 +105,4 @@ | ||
<IconButton | ||
accessibilityLabel="add" | ||
icon="add" | ||
label="add" | ||
/> | ||
@@ -106,5 +112,5 @@ \`\`\` | ||
<IconButton | ||
accessibilityLabel="cancel" | ||
bgColor="lightGray" | ||
icon="cancel" | ||
label="cancel" | ||
/> | ||
@@ -114,15 +120,15 @@ \`\`\` | ||
`, | ||
<div> | ||
<div className="flex mxn2 flex-wrap"> | ||
<GestaltProvider> | ||
<Box margin={{ left: -2, right: -2 }} wrap xs={{ display: 'flex' }}> | ||
{icons.map((icon, i) => | ||
<div className="col-12 px2 mb1 border-box flex" key={i}> | ||
<Box key={i} margin={{ bottom: 1 }} padding={{ x: 2 }} xs={{ display: 'flex', column: 12 }}> | ||
{colors.map((color, idx) => | ||
<div className="px1" key={idx}> | ||
<Box padding={{ x: 1 }} key={idx}> | ||
<IconButtonEx bgColor={color} icon={icon} size="md" /> | ||
</div> | ||
</Box> | ||
)} | ||
</div> | ||
</Box> | ||
)} | ||
</div> | ||
</div> | ||
</Box> | ||
</GestaltProvider> | ||
); | ||
@@ -138,5 +144,5 @@ | ||
<IconButton | ||
accessibilityLabel="heart" | ||
iconColor="red" | ||
icon="heart" | ||
label="heart" | ||
/> | ||
@@ -146,6 +152,6 @@ \`\`\` | ||
<IconButton | ||
accessibilityLabel="pinterest" | ||
bgColor="lightGray" | ||
iconColor="red" | ||
icon="pinterest" | ||
label="pinterest" | ||
/> | ||
@@ -155,32 +161,34 @@ \`\`\` | ||
<IconButton | ||
accessibilityLabel="globe" | ||
iconColor="blue" | ||
icon="globe" | ||
label="globe" | ||
/> | ||
\`\`\` | ||
`, | ||
<div className="flex mxn2 flex-wrap"> | ||
<div className="px1"> | ||
<IconButton | ||
iconColor="red" | ||
icon="heart" | ||
label="heart" | ||
/> | ||
</div> | ||
<div className="px1"> | ||
<IconButton | ||
bgColor="lightGray" | ||
iconColor="red" | ||
icon="pinterest" | ||
label="pinterest" | ||
/> | ||
</div> | ||
<div className="px1"> | ||
<IconButton | ||
iconColor="blue" | ||
icon="globe" | ||
label="globe" | ||
/> | ||
</div> | ||
</div> | ||
<GestaltProvider> | ||
<Box margin={{ left: -2, right: -2 }} wrap xs={{ display: 'flex' }}> | ||
<Box padding={{ x: 1 }}> | ||
<IconButton | ||
accessibilityLabel="heart" | ||
iconColor="red" | ||
icon="heart" | ||
/> | ||
</Box> | ||
<Box padding={{ x: 1 }}> | ||
<IconButton | ||
accessibilityLabel="pinterest" | ||
bgColor="lightGray" | ||
iconColor="red" | ||
icon="pinterest" | ||
/> | ||
</Box> | ||
<Box padding={{ x: 1 }}> | ||
<IconButton | ||
accessibilityLabel="globe" | ||
iconColor="blue" | ||
icon="globe" | ||
/> | ||
</Box> | ||
</Box> | ||
</GestaltProvider> | ||
); |
@@ -5,3 +5,3 @@ // @flow | ||
import React, { PropTypes } from 'react'; | ||
import cx from 'classnames'; | ||
import classnames from 'classnames'; | ||
import Box from '../Box/Box'; | ||
@@ -12,5 +12,6 @@ import Icon from '../Icon/Icon'; | ||
type Props = { | ||
ariaExpanded?: boolean, | ||
ariaHaspopup?: boolean, | ||
type Props = {| | ||
accessibilityExpanded?: boolean, | ||
accessibilityHaspopup?: boolean, | ||
accessibilityLabel: string, | ||
bgColor?: 'transparent' | 'lightGray', | ||
@@ -23,7 +24,6 @@ iconColor?: 'gray' | 'darkGray' | 'red' | 'blue', | ||
icon: $Keys<typeof icons>, | ||
label: string, | ||
onClick?: () => void, | ||
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl', | ||
tabIndex?: -1 | 0, | ||
} | ||
|} | ||
@@ -43,10 +43,14 @@ const defaultIconButtonIconColors = { | ||
export default function IconButton(props: Props) { | ||
type GestaltContext = { | ||
inputDevice: '' | 'key' | 'mouse' | 'touch' | ||
} | ||
export default function IconButton(props: Props, context: GestaltContext) { | ||
const { | ||
ariaExpanded, | ||
ariaHaspopup, | ||
accessibilityExpanded, | ||
accessibilityHaspopup, | ||
accessibilityLabel, | ||
bgColor = 'transparent', | ||
iconColor = defaultIconButtonIconColors[bgColor], | ||
icon, | ||
label, | ||
onClick, | ||
@@ -57,2 +61,4 @@ size = 'md', | ||
const { inputDevice = 'key' } = context; | ||
const inlineStyle = { | ||
@@ -67,6 +73,11 @@ height: buttonSize[size], | ||
<button | ||
aria-expanded={ariaExpanded} | ||
aria-haspopup={ariaHaspopup} | ||
aria-label={label} | ||
className={cx(styles.button, styles[bgColor])} | ||
aria-expanded={accessibilityExpanded} | ||
aria-haspopup={accessibilityHaspopup} | ||
aria-label={accessibilityLabel} | ||
className={classnames( | ||
styles.button, | ||
styles[bgColor], { | ||
[styles.disableFocusOutline]: inputDevice !== 'key' | ||
} | ||
)} | ||
onClick={onClick} | ||
@@ -83,3 +94,3 @@ style={inlineStyle} | ||
*/} | ||
<Icon color={iconColor} icon={icon} size={iconSize} ariaLabel="" /> | ||
<Icon color={iconColor} icon={icon} size={iconSize} accessibilityLabel="" /> | ||
</Box> | ||
@@ -90,5 +101,10 @@ </button> | ||
IconButton.contextTypes = { | ||
inputDevice: React.PropTypes.string | ||
}; | ||
IconButton.propTypes = { | ||
ariaExpanded: PropTypes.bool, | ||
ariaHaspopup: PropTypes.bool, | ||
accessibilityExpanded: PropTypes.bool, | ||
accessibilityHaspopup: PropTypes.bool, | ||
accessibilityLabel: PropTypes.string.isRequired, | ||
bgColor: PropTypes.oneOf( | ||
@@ -101,3 +117,2 @@ ['transparent', 'lightGray'] | ||
), | ||
label: PropTypes.string.isRequired, | ||
onClick: PropTypes.func, | ||
@@ -104,0 +119,0 @@ size: PropTypes.oneOf( |
@@ -26,3 +26,3 @@ // @flow | ||
props: { | ||
props: {| | ||
alt: string, | ||
@@ -38,3 +38,3 @@ children?: any, | ||
srcSet?: {[key: string]: string}, | ||
}; | ||
|}; | ||
@@ -41,0 +41,0 @@ handleLoad = () => { |
// @flow | ||
import './Borders.css'; | ||
import './Colors.css'; | ||
import './LegacyColors.css'; | ||
import './Column.css'; | ||
@@ -5,0 +5,0 @@ import './Cursor.css'; |
@@ -5,6 +5,6 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
children?: any, | ||
htmlFor: string, | ||
}; | ||
|}; | ||
@@ -11,0 +11,0 @@ export default function Label(props: Props) { |
@@ -5,3 +5,3 @@ // @flow | ||
type PropType = { | ||
type PropType = {| | ||
children?: any, | ||
@@ -11,3 +11,3 @@ contentAspectRatio: number, | ||
width: number, | ||
}; | ||
|}; | ||
@@ -14,0 +14,0 @@ export default function Letterbox( |
@@ -77,3 +77,3 @@ // @flow | ||
<Link color="blue" href="https://pinterest.com"> | ||
<Icon icon="pin" color="blue" inline ariaLabel="pin" /> | ||
<Icon icon="pin" color="blue" inline accessibilityLabel="pin" /> | ||
Pinterest.com | ||
@@ -80,0 +80,0 @@ </Link> |
@@ -25,3 +25,3 @@ // @flow | ||
type LinkProps = { | ||
type LinkProps = {| | ||
// eslint-disable-next-line react/no-unused-prop-types | ||
@@ -33,3 +33,3 @@ children?: any, | ||
inline?: boolean, | ||
}; | ||
|}; | ||
@@ -36,0 +36,0 @@ type GestaltContext = { |
@@ -6,3 +6,3 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
children?: any, | ||
@@ -13,3 +13,3 @@ height?: number, | ||
wash?: bool, | ||
}; | ||
|}; | ||
@@ -16,0 +16,0 @@ export default function Mask(props: Props) { |
@@ -109,3 +109,3 @@ // @flow | ||
minCols={1} | ||
ref={(ref) => { this.grid = (ref ? ref.gridRef : ref); }} | ||
ref={(ref) => { this.grid = ref; }} | ||
scrollContainer={this.scrollContainer} | ||
@@ -112,0 +112,0 @@ /> |
@@ -5,8 +5,4 @@ /* global describe */ | ||
import ghost from 'ghostjs'; | ||
import selectors from './lib/selectors'; | ||
const selectors = { | ||
gridItem: '[class*="Masonry__Masonry__Item"]', | ||
afterGrid: '.afterGrid', | ||
}; | ||
describe.skip('Masonry > Cache invalidation', () => { | ||
@@ -13,0 +9,0 @@ it('Able to invalidate cache', async () => { |
@@ -5,9 +5,4 @@ /* global describe */ | ||
import ghost from 'ghostjs'; | ||
import selectors from './lib/selectors'; | ||
const selectors = { | ||
gridItem: '[data-grid-item]', | ||
afterGrid: '.afterGrid', | ||
insertItem: '#insert-item', | ||
}; | ||
const getAnimationCount = async () => await ghost.script(() => window.TEST_ANIMATION_COUNT); | ||
@@ -14,0 +9,0 @@ |
@@ -5,9 +5,4 @@ /* global describe */ | ||
import ghost from 'ghostjs'; | ||
import selectors from './lib/selectors'; | ||
const selectors = { | ||
gridItem: '[data-grid-item]', | ||
afterGrid: '.afterGrid', | ||
insertItem: '#insert-item', | ||
}; | ||
const getItemColumnMap = async () => { | ||
@@ -14,0 +9,0 @@ const gridItems = await ghost.findElements(selectors.gridItem); |
@@ -5,8 +5,4 @@ /* global describe */ | ||
import ghost from 'ghostjs'; | ||
import selectors from './lib/selectors'; | ||
const selectors = { | ||
gridItem: '[class*="Masonry__Masonry__Item"]', | ||
staticItem: '.static', | ||
}; | ||
const PIN_INSERTION_TIME = 500; | ||
@@ -13,0 +9,0 @@ |
@@ -5,7 +5,4 @@ /* global describe */ | ||
import ghost from 'ghostjs'; | ||
import selectors from './lib/selectors'; | ||
const selectors = { | ||
gridItem: '[class*="Masonry__Masonry__Item"]', | ||
}; | ||
describe('Masonry > Parent Sizing', () => { | ||
@@ -12,0 +9,0 @@ it('The grid starts from the left bounding box of the parent', async () => { |
@@ -5,8 +5,4 @@ /* global describe */ | ||
import ghost from 'ghostjs'; | ||
import selectors from './lib/selectors'; | ||
const selectors = { | ||
gridItem: '[class*="Masonry__Masonry__Item"]', | ||
afterGrid: '.afterGrid', | ||
}; | ||
describe('Masonry > Render Height', () => { | ||
@@ -13,0 +9,0 @@ it('Items can be positioned under the grid', async () => { |
@@ -5,32 +5,8 @@ /* global describe */ | ||
import ghost from 'ghostjs'; | ||
import countColumns from './lib/countColumns'; | ||
import triggerResize from './lib/triggerResize'; | ||
const PIN_SIZE = 235; | ||
const RESIZE_DEBOUNCE = 100; | ||
const RESIZE_DEBOUNCE = 300; | ||
const selectors = { | ||
gridItem: '[class*="Masonry__Masonry__Item"]', | ||
staticItem: '.static', | ||
}; | ||
const countColumns = async () => { | ||
const itemLeftMap = {}; | ||
const gridItems = await ghost.findElements(selectors.gridItem); | ||
for (let i = 0; i < gridItems.length; i += 1) { | ||
const itemRect = await gridItems[i].rect(); | ||
itemLeftMap[itemRect.left] = itemLeftMap[itemRect.left] || []; | ||
itemLeftMap[itemRect.left].push(itemRect); | ||
} | ||
return Object.keys(itemLeftMap).length; | ||
}; | ||
const triggerReisze = async (resizeWidthTo) => { | ||
await ghost.script((newWidth) => { | ||
// Mock out the window width for the next resize calculation. | ||
const gridWrapper = document.getElementById('gridWrapper'); | ||
gridWrapper.style.width = `${newWidth}px`; | ||
window.dispatchEvent(new Event('resize')); | ||
}, [resizeWidthTo]); | ||
}; | ||
describe('Masonry > Resize', () => { | ||
@@ -43,4 +19,2 @@ it('Reflows the grid after a resize', async () => { | ||
ghost.close(); | ||
// First load the page with javascript disabled to get the item position | ||
await ghost.open('http://localhost:3000/Masonry', { | ||
@@ -53,2 +27,4 @@ viewportSize: { | ||
// Wait for the grid to be hydrated. | ||
// TODO: Break this out into a utility /w wait() instead. | ||
await ghost.wait(1000); | ||
@@ -59,3 +35,3 @@ | ||
await triggerReisze(GRID_WIDTH - PIN_SIZE); | ||
await triggerResize(GRID_WIDTH - PIN_SIZE); | ||
@@ -62,0 +38,0 @@ // Wait for the resize debounce to complete. |
@@ -28,5 +28,7 @@ /* global describe */ | ||
await ghost.script(() => window.NEXT_FETCH()); | ||
const largerFetchCount = await ghost.script(() => window.TEST_FETCH_COUNTS); | ||
assert.ok(largerFetchCount >= 1); | ||
await ghost.wait(async () => { | ||
const largerFetchCount = await ghost.script(() => window.TEST_FETCH_COUNTS); | ||
return largerFetchCount >= 1; | ||
}); | ||
}); | ||
}); |
@@ -5,8 +5,4 @@ /* global describe */ | ||
import ghost from 'ghostjs'; | ||
import selectors from './lib/selectors'; | ||
const selectors = { | ||
gridItem: '[class*="Masonry__Masonry__Item"]', | ||
staticItem: '.static', | ||
}; | ||
describe('Masonry > Server Render Layout', () => { | ||
@@ -13,0 +9,0 @@ it('items rendered on the server maintain position after mounting', async () => { |
/* global describe */ | ||
/* global it */ | ||
import ghost from 'ghostjs'; | ||
import selectors from './lib/selectors'; | ||
const selectors = { | ||
gridItem: '[class*="Masonry__Masonry__Item"]', | ||
staticItem: '.static', | ||
}; | ||
const getFirstItemDisplay = async () => { | ||
@@ -11,0 +7,0 @@ const gridItems = await ghost.findElements(selectors.gridItem); |
/* global describe */ | ||
/* global it */ | ||
import ghost from 'ghostjs'; | ||
import selectors from './lib/selectors'; | ||
const selectors = { | ||
gridItem: '[class*="Masonry__Masonry__Item"]', | ||
scrollContainer: '[data-scroll-container]', | ||
staticItem: '.static', | ||
}; | ||
const getFirstItemDisplay = async () => { | ||
@@ -12,0 +7,0 @@ const gridItems = await ghost.findElements(selectors.gridItem); |
@@ -9,5 +9,6 @@ // @flow | ||
import throttle from '../throttle'; | ||
import ThrottleInsertion from './ThrottleInsertion'; | ||
type Props<T> = { | ||
const MAX_ITEMS_PER_INSERTION = 1; | ||
type Props<T> = {| | ||
columnWidth: number, | ||
@@ -21,3 +22,3 @@ comp: () => void, | ||
scrollContainer: HTMLElement, | ||
}; | ||
|}; | ||
@@ -92,3 +93,3 @@ type GridItemType<T> = { | ||
this.props.scrollContainer.addEventListener('scroll', this.updateVirtualBounds); | ||
this.props.scrollContainer.addEventListener('resize', this.handleResize); | ||
window.addEventListener('resize', this.handleResize); | ||
@@ -127,4 +128,4 @@ // Determine #columns and itemWidth | ||
if (items[i] !== this.props.items[i]) { | ||
this.insertedItemsCount = 0; | ||
this.setGridItems(items); | ||
break; | ||
} | ||
@@ -152,3 +153,3 @@ } | ||
this.props.scrollContainer.removeEventListener('scroll', this.updateVirtualBounds); | ||
this.props.scrollContainer.removeEventListener('resize', this.handleResize); | ||
window.removeEventListener('resize', this.handleResize); | ||
this.gridWrapper.removeEventListener('animationend', this.handleAnimationEnd); | ||
@@ -227,3 +228,5 @@ } | ||
}, () => { | ||
this.insertItems(items); | ||
this.insertedItemsCount = 0; | ||
this.serverRefSizes = []; | ||
this.insertItems(items, null, null, true); | ||
}); | ||
@@ -283,4 +286,4 @@ } | ||
resizeTimeout: ?number; | ||
scrollBuffer: number; | ||
serverRefs: Array<HTMLElement>; | ||
serverRefSizes: Array<*>; | ||
@@ -293,3 +296,2 @@ updateItems(items: Array<*>) { | ||
this.insertItems(items.slice(this.insertedItemsCount)); | ||
this.insertedItemsCount = items.length; | ||
} | ||
@@ -330,13 +332,8 @@ } | ||
insertItems(items: Array<*>, colIdx?: (number | null) = null, itemIdx?: (number | null) = null) { | ||
// Append a temporary node to the dom to measure it. | ||
const measuringNode = document.createElement('div'); | ||
// Force width for flexible layouts | ||
measuringNode.style.width = `${this.itemWidth}px`; | ||
if (document.body) { | ||
document.body.appendChild(measuringNode); | ||
} | ||
insertItems(newItems: Array<*>, colIdx?: (number | null) = null, | ||
itemIdx?: (number | null) = null, forceUpdate?: (boolean | null) = null) { | ||
const gridItems = this.state.gridItems; | ||
const previousItemInColumn = colIdx !== null && itemIdx !== null && | ||
gridItems[colIdx] && gridItems[colIdx][itemIdx - 1] ? | ||
gridItems[colIdx][itemIdx - 1] : null; | ||
@@ -349,10 +346,42 @@ if (!gridItems.length) { | ||
this.itemKeyCounter = this.itemKeyCounter || 0; | ||
let items; | ||
if (forceUpdate) { | ||
items = newItems; | ||
} else if (this.insertedItemsCount === 0 && this.serverRefs.length) { | ||
items = newItems.slice(0, this.columnCount); | ||
} else if (this.serverRefs.length && this.insertedItemsCount < this.serverRefs.length) { | ||
items = newItems.slice(0, this.serverRefs.length - this.insertedItemsCount); | ||
} else if (newItems.length > MAX_ITEMS_PER_INSERTION) { | ||
items = newItems.slice(0, MAX_ITEMS_PER_INSERTION); | ||
} else { | ||
items = newItems; | ||
} | ||
items.forEach((itemData, insertedItemIdx) => { | ||
this.itemKeyCounter = this.itemKeyCounter || 1; | ||
if (!this.serverRefSizes && this.serverRefs.length > 0) { | ||
this.serverRefSizes = this.serverRefs.map((ref) => { | ||
const serverRendered = ref; | ||
serverRendered.style.width = `${this.itemWidth}px`; | ||
return [serverRendered.clientWidth, serverRendered.clientHeight]; | ||
}); | ||
} | ||
// build out initial item info blobs for each component | ||
const pendingDomMeasurements = []; | ||
const itemInfos = items.map((itemData, insertedItemIdx) => { | ||
const actualIdx = insertedItemIdx + this.insertedItemsCount; | ||
const itemInfo = {}; | ||
const key = colIdx != null && itemIdx != null ? | ||
parseFloat(`${insertedItemIdx.toString()}.${this.itemKeyCounter}1`) : | ||
this.itemKeyCounter; | ||
let key; | ||
if (colIdx != null && itemIdx != null) { | ||
const counterAsDecimal = (this.itemKeyCounter % 10000) / 1000; | ||
if (previousItemInColumn) { | ||
key = parseFloat(`${parseInt(previousItemInColumn.key, 10) + counterAsDecimal}`); | ||
} else { | ||
key = parseFloat(`${counterAsDecimal}`); | ||
} | ||
} else { | ||
key = this.itemKeyCounter; | ||
} | ||
this.itemKeyCounter += 1; | ||
@@ -367,21 +396,52 @@ const component = ( | ||
let clientHeight; | ||
let clientWidth; | ||
if (this.serverRefs && this.serverRefs[insertedItemIdx]) { | ||
const serverRendered = this.serverRefs[insertedItemIdx]; | ||
serverRendered.style.width = `${this.itemWidth}px`; | ||
clientHeight = serverRendered.clientHeight; | ||
clientWidth = serverRendered.clientWidth; | ||
if (this.serverRefSizes && actualIdx < this.serverRefSizes.length) { | ||
const sizeInfo = this.serverRefSizes[actualIdx]; | ||
itemInfo.width = sizeInfo[0]; | ||
itemInfo.height = sizeInfo[1]; | ||
} else { | ||
ReactDOM.unstable_renderSubtreeIntoContainer( | ||
this, component, measuringNode); | ||
clientHeight = measuringNode.clientHeight; | ||
clientWidth = measuringNode.clientWidth; | ||
pendingDomMeasurements.push({ | ||
component, | ||
itemInfo | ||
}); | ||
} | ||
itemInfo.component = component; | ||
itemInfo.width = clientWidth; | ||
itemInfo.height = clientHeight; | ||
itemInfo.itemData = itemData; | ||
itemInfo.key = key; | ||
return itemInfo; | ||
}); | ||
if (pendingDomMeasurements.length > 0) { | ||
// Append a temporary node to the dom to measure it. | ||
const measuringNode = document.createElement('div'); | ||
if (document.body) { | ||
document.body.appendChild(measuringNode); | ||
} | ||
ReactDOM.unstable_renderSubtreeIntoContainer( | ||
this, <div> { pendingDomMeasurements.map(({ component }, idx) => | ||
<div key={`el-${idx}`} style={{ width: `${this.itemWidth}px` }}>{ component }</div> | ||
)} </div>, measuringNode); | ||
const wrapperNodes = measuringNode.children[0].children; | ||
for (let i = 0; i < wrapperNodes.length; i += 1) { | ||
const { itemInfo } = pendingDomMeasurements[i]; | ||
const el = wrapperNodes[i]; | ||
itemInfo.width = el.clientWidth; | ||
itemInfo.height = el.clientHeight; | ||
} | ||
ReactDOM.unmountComponentAtNode(measuringNode); | ||
if (document.body) { | ||
document.body.removeChild(measuringNode); | ||
} | ||
} | ||
// insert the actual items into the grid | ||
items.forEach((itemData, insertedItemIdx) => { | ||
const itemInfo = itemInfos[insertedItemIdx]; | ||
if (colIdx != null && itemIdx != null) { | ||
@@ -392,5 +452,3 @@ if (!gridItems[colIdx]) { | ||
const left = colIdx * this.itemWidth; | ||
const previousItemInColumn = gridItems[colIdx] && gridItems[colIdx][itemIdx - 1] ? | ||
gridItems[colIdx][itemIdx - 1].bottom : 0; | ||
const top = previousItemInColumn || 0; | ||
const top = previousItemInColumn ? previousItemInColumn.bottom : 0; | ||
@@ -403,4 +461,3 @@ // Construct a more specific render key for inserted items. | ||
itemInfo.top = top; | ||
itemInfo.bottom = top + clientHeight + this.gutterWidth; | ||
itemInfo.key = key; | ||
itemInfo.bottom = top + itemInfo.height + this.gutterWidth; | ||
@@ -429,15 +486,12 @@ gridItems[colIdx].splice(itemIdx, 0, itemInfo); | ||
itemInfo.top = top; | ||
itemInfo.bottom = top + clientHeight + this.gutterWidth; | ||
itemInfo.key = key; | ||
itemInfo.bottom = top + itemInfo.height + this.gutterWidth; | ||
itemInfo.key = itemInfo.key; | ||
gridItems[column].push(itemInfo); | ||
} | ||
this.itemKeyCounter += 1; | ||
ReactDOM.unmountComponentAtNode(measuringNode); | ||
}); | ||
if (document.body) { | ||
document.body.removeChild(measuringNode); | ||
if (colIdx === null && itemIdx === null) { | ||
// update the number of items retrieved from the main feed | ||
this.insertedItemsCount += items.length; | ||
} | ||
@@ -459,3 +513,2 @@ | ||
this.serverRefs = []; | ||
this.setState({ | ||
@@ -465,3 +518,7 @@ gridItems, | ||
minHeight: minHeight || this.state.minHeight, | ||
serverItems: null, | ||
serverItems: null | ||
}, () => { | ||
if (this.insertedItemsCount < this.props.items.length) { | ||
setTimeout(() => this.insertItems(this.props.items.slice(this.insertedItemsCount)), 25); | ||
} | ||
}); | ||
@@ -542,3 +599,2 @@ } | ||
} | ||
this.scrollBuffer = this.containerHeight * 2; | ||
} | ||
@@ -622,2 +678,3 @@ | ||
render() { | ||
const allItems = this.state.serverItems || this.allItems(); | ||
const itemClassName = [ | ||
@@ -636,6 +693,7 @@ this.state.serverItems ? 'static' : styles.Masonry__Item, | ||
fetchMore={this.fetchMore} | ||
isFetching={this.state.fetchingFrom !== false || this.props.insertionsQueued} | ||
isFetching={this.state.fetchingFrom !== false | ||
|| this.insertedItemsCount < this.props.items.length} | ||
renderHeight={this.renderHeight} | ||
/> | ||
{(this.state.serverItems || this.allItems()).map(item => | ||
{allItems.map((item, idx) => | ||
<MasonryComponentWrapper | ||
@@ -655,3 +713,7 @@ key={`wrapper-${item.key}`} | ||
}} | ||
{...this.state.serverItems ? { ref: (ref) => { this.serverRefs.push(ref); } } : {}} | ||
{...this.state.serverItems ? { ref: (ref) => { | ||
if (this.serverRefs.length < idx) { | ||
this.serverRefs.push(ref); | ||
} | ||
} } : {}} | ||
> | ||
@@ -698,7 +760,2 @@ <div | ||
/** | ||
* Whether or not insertions are queued from <ThrottleInsertion> | ||
*/ | ||
insertionsQueued: React.PropTypes.bool, | ||
/** | ||
* An array of all objects to display in the grid. | ||
@@ -739,4 +796,2 @@ */ | ||
export { Masonry as DefaultGrid }; | ||
export default ThrottleInsertion(Masonry); | ||
export default Masonry; |
@@ -24,7 +24,7 @@ // @flow | ||
type Props = { | ||
accessibilityCloseLabel: string, | ||
accessibilityModalLabel: string, | ||
children?: any, | ||
closeLabel: string, | ||
footer?: any, | ||
header: any, | ||
modalLabel: string, | ||
heading: string, | ||
role?: 'alertdialog' | 'dialog', /* default: dialog */ | ||
@@ -38,3 +38,3 @@ onDismiss: () => void, | ||
<div className="py2"> | ||
<Text bold size="md">Header & Footer</Text> | ||
<Text bold size="md">Heading & Footer</Text> | ||
<Divider /> | ||
@@ -62,25 +62,23 @@ <Text> | ||
Some of the padding required to style your modal has already been provided for ease of use. The modal shown | ||
by clicking on the "View padding" button highlights what the default behavior is. It was created using the | ||
\`props\` below. The two divider's between the \`header\`, \`children\`, and \`footer\` are included as well. | ||
by clicking on the "View padding" button highlights what the default behavior is. The two divider's between | ||
the \`heading\`, \`children\`, and \`footer\` are included as well. | ||
<b>\`header\`</b> | ||
\`\`\`jsx | ||
<div className="bg-gray"> | ||
<Heading size="sm">Heading</Heading> | ||
</div> | ||
} | ||
<Modal | ||
accessibilityCloseLabel="close" | ||
accessibilityModalLabel="View default padding and styling" | ||
heading="Heading" | ||
onDismiss={() => this.setState({ isOpen: false })} | ||
footer={ | ||
<div className="bg-gray"> | ||
<Heading size="sm">Footer</Heading> | ||
</div> | ||
} | ||
size="md" | ||
> | ||
<div className="bg-gray" style={{ height: 400 }}> | ||
<Heading size="sm">Children</Heading> | ||
</div> | ||
</Modal> | ||
\`\`\` | ||
<b>\`footer\`</b> | ||
\`\`\`jsx | ||
<div className="bg-gray"> | ||
<Heading size="sm">Footer</Heading> | ||
</div> | ||
\`\`\` | ||
<b>\`children\`</b> | ||
\`\`\`jsx | ||
<div className="bg-gray" style={{ height: 400 }}> | ||
<Heading size="sm">Children</Heading> | ||
</div> | ||
\`\`\` | ||
`, | ||
@@ -92,9 +90,5 @@ atom => ( | ||
<Modal | ||
closeLabel="close" | ||
header={ | ||
<div className="bg-gray"> | ||
<Heading size="sm">Heading</Heading> | ||
</div> | ||
} | ||
modalLabel="View default padding and styling" | ||
accessibilityCloseLabel="close" | ||
accessibilityModalLabel="View default padding and styling" | ||
heading="Heading" | ||
onDismiss={() => atom.reset({ isOpen: false })} | ||
@@ -145,3 +139,3 @@ footer={ | ||
<Column xs={8}> | ||
<SelectList id="category" onChange={() => undefined} options={[{ key: 'food', value: 'Food' }]} selectedKey="food" /> | ||
<SelectList id="category" onChange={() => undefined} options={[{ key: 'food', value: 'Food' }]} value="food" /> | ||
</Column> | ||
@@ -157,3 +151,3 @@ </div> | ||
<Column xs={8}> | ||
<Button id="cover" label="Cover Photo" text="Cover" /> | ||
<Button text="Cover" /> | ||
</Column> | ||
@@ -213,8 +207,8 @@ </div> | ||
<Column xs={6}> | ||
<Button label="delete" text="Delete Board" /> | ||
<Button text="Delete Board" /> | ||
</Column> | ||
<Column xs={6}> | ||
<div className="flex justify-end"> | ||
<Button label="cancel" text="Cancel" onClick={onClose} /> | ||
<Button color="red" label="save" text="Save" /> | ||
<Button text="Cancel" onClick={onClose} /> | ||
<Button color="red" text="Save" /> | ||
</div> | ||
@@ -229,15 +223,12 @@ </Column> | ||
\`\`\`jsx | ||
<Button text="Edit board" onClick={() => this.setState({ isOpen: !this.state.isOpen })} /> | ||
{this.state.isOpen ? ( | ||
<Modal | ||
closeLabel="close" | ||
header={<Heading size="xs">Edit your board</Heading>} | ||
modalLabel="Edit Julia's board" | ||
onDismiss={() => this.setState({ isOpen: false })} | ||
footer={footerButtons} | ||
size="md" | ||
> | ||
{children} | ||
</Modal> | ||
) : null} | ||
<Modal | ||
accessibilityCloseLabel="close" | ||
accessibilityModalLabel="Edit Julia's board" | ||
heading="Edit your board" | ||
onDismiss={() => this.setState({ isOpen: false })} | ||
footer={footerButtons} | ||
size="md" | ||
> | ||
{children} | ||
</Modal> | ||
\`\`\` | ||
@@ -250,5 +241,5 @@ `, | ||
<Modal | ||
closeLabel="close" | ||
header={<Heading size="xs">Edit your board</Heading>} | ||
modalLabel="Edit Julia's board" | ||
accessibilityCloseLabel="close" | ||
accessibilityModalLabel="Edit Julia's board" | ||
heading="Edit your board" | ||
onDismiss={() => atom.reset({ isOpen: false })} | ||
@@ -279,3 +270,3 @@ footer={editBoardFooter(() => atom.reset({ isOpen: false }))} | ||
<div className="flex"> | ||
<Spinner label="random image" show={!this.state.hasLoaded} /> | ||
<Spinner accessibilityLabel="random image" show={!this.state.hasLoaded} /> | ||
<div ref={(c) => { this.image = c; }}> | ||
@@ -295,3 +286,3 @@ <img alt="" onLoad={this.handleLoad} src="http://placebear.com/400/400" /> | ||
<div className="flex justify-end"> | ||
<Button label="cancel" text="Cancel" onClick={onClose} /> | ||
<Button text="Cancel" onClick={onClose} /> | ||
</div> | ||
@@ -306,18 +297,15 @@ ); | ||
component first renders a \`Spinner\` and then switches to the actual images once loaded. This results in | ||
the \`header\` and \`footer\` being rendered prior to the content. You could also choose to display the | ||
the \`heading\` and \`footer\` being rendered prior to the content. You could also choose to display the | ||
\`Spinner\` while waiting for the contents to load and then only display the \`Modal\` once fully loaded. | ||
\`\`\`jsx | ||
<Button text="View images" onClick={() => this.setState({ isOpen: !this.state.isOpen })} /> | ||
{this.state.isOpen ? ( | ||
<Modal | ||
closeLabel="close" | ||
header={<Heading size="xs">Images</Heading>} | ||
modalLabel="View random images" | ||
onDismiss={() => this.setState({ isOpen: false })} | ||
footer={footerButtons} | ||
size="lg" | ||
> | ||
<ImageModalContents /> | ||
</Modal> | ||
) : null} | ||
<Modal | ||
accessibilityCloseLabel="close" | ||
accessibilityModalLabel="View random images" | ||
heading="Images" | ||
onDismiss={() => this.setState({ isOpen: false })} | ||
footer={footerButtons} | ||
size="lg" | ||
> | ||
<ImageModalContents /> | ||
</Modal> | ||
\`\`\` | ||
@@ -330,5 +318,5 @@ `, | ||
<Modal | ||
closeLabel="close" | ||
header={<Heading size="xs">Images</Heading>} | ||
modalLabel="View random images" | ||
accessibilityCloseLabel="close" | ||
accessibilityModalLabel="View random images" | ||
heading="Images" | ||
onDismiss={() => atom.reset({ isOpen: false })} | ||
@@ -356,6 +344,6 @@ footer={viewImagesFooter(() => atom.reset({ isOpen: false }))} | ||
<div className="py1"> | ||
<Button fullWidth text="Cancel" onClick={onClose} /> | ||
<Button text="Cancel" onClick={onClose} /> | ||
</div> | ||
<div className="py1"> | ||
<Button color="red" fullWidth text="Block" onClick={onClose} /> | ||
<Button color="red" text="Block" onClick={onClose} /> | ||
</div> | ||
@@ -371,5 +359,5 @@ </div> | ||
*Note: There are 2 small visual differences from the other Modal's we've seen so far. First, there is no cancel button in the top | ||
*Note: There are 3 small visual differences from the other Modal's we've seen so far. First, there is no cancel button in the top | ||
right, forcing the user to take an explicit action. Second, there is no divider between the heading, children, | ||
and footer.* | ||
and footer. Finally, the heading's are larger and are left-aligned rather than centered.* | ||
@@ -383,5 +371,5 @@ | ||
<Modal | ||
closeLabel="close" | ||
header={<Heading size="md">Block Chris?</Heading>} | ||
modalLabel="Would you like to block Chris?" | ||
accessibilityCloseLabel="close" | ||
accessibilityModalLabel="Would you like to block Chris?" | ||
heading="Block Chris?" | ||
onDismiss={() => atom.reset({ isOpen: false })} | ||
@@ -388,0 +376,0 @@ footer={alertFooter(() => atom.reset({ isOpen: false }))} |
@@ -5,2 +5,3 @@ // @flow | ||
import Divider from '../Divider/Divider'; | ||
import Heading from '../Heading/Heading'; | ||
import IconButton from '../IconButton/IconButton'; | ||
@@ -18,12 +19,12 @@ import styles from './Modal.css'; | ||
type Props = { | ||
type Props = {| | ||
accessibilityCloseLabel: string, | ||
accessibilityModalLabel: string, | ||
children?: any, | ||
closeLabel: string, | ||
footer?: any, | ||
header: any, | ||
modalLabel: string, | ||
heading: string, | ||
onDismiss: () => void, | ||
role?: 'alertdialog' | 'dialog', | ||
size?: 'sm' | 'md' | 'lg', | ||
}; | ||
|}; | ||
@@ -117,3 +118,11 @@ type State = { | ||
render() { | ||
const { children, closeLabel, footer, header, modalLabel, role = 'dialog', size = 'sm' } = this.props; | ||
const { | ||
accessibilityCloseLabel, | ||
accessibilityModalLabel, | ||
children, | ||
footer, | ||
heading, | ||
role = 'dialog', | ||
size = 'sm' | ||
} = this.props; | ||
const width = SIZE_WIDTH_MAP[size]; | ||
@@ -134,3 +143,3 @@ | ||
<div | ||
aria-label={modalLabel} | ||
aria-label={accessibilityModalLabel} | ||
className={containerClasses} | ||
@@ -149,6 +158,18 @@ ref={(c) => { this.container = c; }} | ||
<div className="border-box fit"> | ||
<div className="flex py3 px2 justify-between"> | ||
{header} | ||
{role === 'dialog' ? <IconButton label={closeLabel} icon="cancel" onClick={this.handleClose} /> : null } | ||
</div> | ||
{role === 'dialog' ? | ||
<div className="flex py3 justify-center text-center" style={{ paddingLeft: 50, paddingRight: 50 }}> | ||
<Heading size="xs" accessibilityLevel={1}> | ||
{heading} | ||
</Heading> | ||
</div> | ||
: <div className="flex py3 px2"> | ||
<Heading size="lg" accessibilityLevel={1}> | ||
{heading} | ||
</Heading> | ||
</div> } | ||
{role === 'dialog' ? | ||
<div className="absolute top-0 right-0 p1"> | ||
<IconButton accessibilityLabel={accessibilityCloseLabel} icon="cancel" onClick={this.handleClose} /> | ||
</div> | ||
: null } | ||
{role === 'dialog' ? <Divider /> : null} | ||
@@ -178,6 +199,6 @@ </div> | ||
children: PropTypes.node, | ||
closeLabel: PropTypes.string.isRequired, | ||
accessibilityCloseLabel: PropTypes.string.isRequired, | ||
footer: PropTypes.node, | ||
header: PropTypes.node.isRequired, | ||
modalLabel: PropTypes.string.isRequired, | ||
heading: PropTypes.string.isRequired, | ||
accessibilityModalLabel: PropTypes.string.isRequired, | ||
onDismiss: PropTypes.func, | ||
@@ -184,0 +205,0 @@ role: PropTypes.oneOf(['alertdialog', 'dialog']), |
@@ -16,3 +16,3 @@ // @flow | ||
props: { | ||
props: {| | ||
checked?: boolean, | ||
@@ -23,3 +23,3 @@ id: string, | ||
value: string, | ||
}; | ||
|}; | ||
@@ -26,0 +26,0 @@ handleChange = (e: { nativeEvent: { target: { checked: boolean}}}) => { |
@@ -17,3 +17,3 @@ // @flow | ||
type Props = { | ||
aria: { label: string }, | ||
accessibilityLabel: string, | ||
id: string, | ||
@@ -33,7 +33,7 @@ onChange: ({ value: string }) => void, | ||
<Box padding={2}> | ||
<Icon icon="pinterest" color="red" size={20} ariaLabel="Pinterest" /> | ||
<Icon icon="pinterest" color="red" size={20} accessibilityLabel="Pinterest" /> | ||
</Box> | ||
<Box grow padding={{ x: 1 }}> | ||
<SearchField | ||
aria={{ label: 'Demo Search Field' }} | ||
accessibilityLabel="Demo Search Field" | ||
id="searchField" | ||
@@ -47,6 +47,6 @@ onChange={({ value }) => atom.reset({ value })} | ||
<Box padding={{ x: 1 }}> | ||
<IconButton icon="speech-ellipsis" size="md" label="Notifications" /> | ||
<IconButton accessibilityLabel="Notifications" icon="speech-ellipsis" size="md" /> | ||
</Box> | ||
<Box padding={{ x: 1 }}> | ||
<IconButton icon="person" size="md" label="Profile" /> | ||
<IconButton accessibilityLabel="Profile" icon="person" size="md" /> | ||
</Box> | ||
@@ -53,0 +53,0 @@ </Box> |
@@ -11,5 +11,3 @@ // @flow | ||
static propTypes = { | ||
aria: PropTypes.shape({ | ||
label: PropTypes.string.isRequired, | ||
}).isRequired, | ||
accessibilityLabel: PropTypes.string.isRequired, | ||
id: PropTypes.string.isRequired, | ||
@@ -26,5 +24,5 @@ onChange: PropTypes.func.isRequired, | ||
props: { | ||
props: {| | ||
// eslint-disable-next-line react/no-unused-prop-types | ||
aria: { label: string }, | ||
accessibilityLabel: string, | ||
id: string, | ||
@@ -35,3 +33,3 @@ onChange: ({ value: string }) => void, | ||
value?: string, | ||
}; | ||
|}; | ||
@@ -51,3 +49,3 @@ handleChange = (e: Event) => { | ||
const { | ||
aria: { label }, | ||
accessibilityLabel, | ||
id, | ||
@@ -81,6 +79,6 @@ placeholder, | ||
> | ||
<Icon icon="search" ariaLabel="" /> | ||
<Icon icon="search" accessibilityLabel="" /> | ||
</Box> | ||
<input | ||
aria-label={label} | ||
aria-label={accessibilityLabel} | ||
className={styles.input} | ||
@@ -97,4 +95,4 @@ id={id} | ||
<IconButton | ||
accessibilityLabel="" | ||
icon="clear" | ||
label="" | ||
size="sm" | ||
@@ -101,0 +99,0 @@ onClick={onClear} |
@@ -7,7 +7,7 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
items: Array<any>, | ||
onChange: (i: number, e: Event) => void, | ||
selectedItemIndex: number | ||
}; | ||
|}; | ||
@@ -14,0 +14,0 @@ export default function SegmentedControl(props: Props) { |
@@ -23,3 +23,3 @@ // @flow | ||
props: { | ||
props: {| | ||
id: string, | ||
@@ -33,3 +33,3 @@ name?: string, | ||
value?: ?string, | ||
}; | ||
|}; | ||
@@ -70,3 +70,3 @@ handleOnChange = (e: Event) => { | ||
> | ||
<Icon icon="arrow-down" size={14} color="darkGray" ariaLabel="" /> | ||
<Icon icon="arrow-down" size={14} color="darkGray" accessibilityLabel="" /> | ||
</Box> | ||
@@ -73,0 +73,0 @@ <select |
@@ -13,3 +13,3 @@ // @flow | ||
type Props = { | ||
label: string, | ||
accessibilityLabel: string, | ||
show: bool, | ||
@@ -33,5 +33,5 @@ }; | ||
</button> | ||
<Spinner show={atom.deref().show} label="Example spinner" /> | ||
<Spinner show={atom.deref().show} accessibilityLabel="Example spinner" /> | ||
<p>Data</p> | ||
</div> | ||
), { heading: false, initialState: { show: true } }); |
// @flow | ||
/* global $Exact */ | ||
/* global $Shape */ | ||
import React, { PropTypes, Component } from 'react'; | ||
@@ -10,6 +12,6 @@ import Box from '../Box/Box'; | ||
type Props = { | ||
label: string, | ||
type Props = {| | ||
accessibilityLabel: string, | ||
show: bool, | ||
}; | ||
|}; | ||
@@ -20,3 +22,3 @@ export default class Spinner extends Component { | ||
show: PropTypes.bool.isRequired, | ||
label: PropTypes.string.isRequired, | ||
accessibilityLabel: PropTypes.string.isRequired, | ||
} | ||
@@ -64,3 +66,3 @@ | ||
render() { | ||
const { label } = this.props; | ||
const { accessibilityLabel } = this.props; | ||
const { visible } = this.state; | ||
@@ -74,3 +76,3 @@ if (!visible) { | ||
<div className={styles.icon}> | ||
<Icon icon="knoop" ariaLabel={label} size={SIZE} /> | ||
<Icon icon="knoop" accessibilityLabel={accessibilityLabel} size={SIZE} /> | ||
</div> | ||
@@ -77,0 +79,0 @@ </Box> |
@@ -8,3 +8,3 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
id: string, | ||
@@ -14,3 +14,3 @@ name?: string, | ||
switched?: boolean, | ||
} | ||
|} | ||
@@ -17,0 +17,0 @@ export default function Switch(props: Props) { |
@@ -234,5 +234,2 @@ // @flow | ||
</div> | ||
<div className="mb2"> | ||
<Text underline>Underline</Text> | ||
</div> | ||
</div>); |
@@ -16,3 +16,3 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
align?: 'left' | 'right' | 'center' | 'justify', | ||
@@ -27,3 +27,3 @@ bold?: bool, | ||
truncate?: bool, | ||
}; | ||
|}; | ||
@@ -30,0 +30,0 @@ export default function Text(props: Props) { |
@@ -29,3 +29,3 @@ // @flow | ||
props: { | ||
props: {| | ||
errorMessage?: string, | ||
@@ -39,3 +39,3 @@ id: string, | ||
value?: string, | ||
}; | ||
|}; | ||
@@ -42,0 +42,0 @@ handleChange = (e: Event) => { |
@@ -36,3 +36,3 @@ // @flow | ||
props: { | ||
props: {| | ||
errorMessage?: string, | ||
@@ -47,3 +47,3 @@ hasError?: bool, | ||
value?: string, | ||
}; | ||
|}; | ||
@@ -50,0 +50,0 @@ handleChange = (e: Event) => { |
@@ -50,2 +50,3 @@ // @flow | ||
}} | ||
padding={{ x: 1 }} | ||
position="fixed" | ||
@@ -93,2 +94,3 @@ > | ||
}} | ||
padding={{ x: 1 }} | ||
position="fixed" | ||
@@ -95,0 +97,0 @@ > |
@@ -9,6 +9,6 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
text: string | Array<string>, | ||
thumbnail?: React$Element<any>, | ||
}; | ||
|}; | ||
@@ -47,3 +47,3 @@ export default function Toast(props: Props) { | ||
<Box dangerouslySetInlineStyle={{ __style: { paddingLeft: 24 } }}> | ||
<Icon ariaLabel="" color="white" icon="arrow-circle-forward" size={36} /> | ||
<Icon accessibilityLabel="" color="white" icon="arrow-circle-forward" size={36} /> | ||
</Box> | ||
@@ -59,3 +59,2 @@ </Box> | ||
shape="pill" | ||
margin={{ left: 1, right: 1 }} | ||
dangerouslySetInlineStyle={{ | ||
@@ -62,0 +61,0 @@ __style: { |
@@ -69,3 +69,3 @@ // @flow | ||
<IconButton | ||
label="Create a new board" | ||
accessibilityLabel="Create a new board" | ||
icon="add" | ||
@@ -90,3 +90,3 @@ onClick={() => this.setState({ isOpen: !this.state.isOpen })} | ||
<IconButton | ||
label="Create a new board" | ||
accessibilityLabel="Create a new board" | ||
icon="add" | ||
@@ -93,0 +93,0 @@ onClick={() => atom.reset({ value: !atom.deref().value })} |
@@ -7,3 +7,3 @@ // @flow | ||
type Props = { | ||
type Props = {| | ||
children?: any, | ||
@@ -15,3 +15,3 @@ idealDirection?: 'up' | 'right' | 'down' | 'left', | ||
trigger: React$Element<any>, | ||
}; | ||
|}; | ||
@@ -18,0 +18,0 @@ export default function Tooltip(props: Props) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
0
0
1
0
1565613
234
26114
30