commit
d67e489ccb
4 changed files with 301 additions and 2 deletions
24
javascripts/src/components/common/Spinner.spec.tsx
Normal file
24
javascripts/src/components/common/Spinner.spec.tsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
// License: LGPL-3.0-or-later
|
||||
import * as React from 'react';
|
||||
import 'jest';
|
||||
import Spinner from './Spinner'
|
||||
import { mount } from 'enzyme';
|
||||
import toJson from 'enzyme-to-json';
|
||||
|
||||
describe('Spinner', () => {
|
||||
test('is small', () => {
|
||||
expect(toJson(mount(<Spinner size="small"/>))).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('is normal', () => {
|
||||
expect(toJson(mount(<Spinner size="normal"/>))).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('is large', () => {
|
||||
expect(toJson(mount(<Spinner size="large"/>))).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('has custom color ', () => {
|
||||
expect(toJson(mount(<Spinner size="small" color={"#ffffff"}/>))).toMatchSnapshot()
|
||||
})
|
||||
})
|
55
javascripts/src/components/common/Spinner.tsx
Normal file
55
javascripts/src/components/common/Spinner.tsx
Normal file
|
@ -0,0 +1,55 @@
|
|||
// License: LGPL-3.0-or-later
|
||||
import { Color } from 'csstype';
|
||||
import * as React from 'react';
|
||||
import { VelocityComponent } from 'velocity-react';
|
||||
import ScreenReaderOnlyText from './ScreenReaderOnlyText';
|
||||
|
||||
export interface SpinnerProps {
|
||||
size: 'small' | 'normal' | 'large'
|
||||
color?: Color
|
||||
}
|
||||
|
||||
class Spinner extends React.Component<SpinnerProps, {}> {
|
||||
static defaultProps = {
|
||||
color: 'currentcolor'
|
||||
}
|
||||
|
||||
generateStyle(): React.CSSProperties {
|
||||
let spinnerDimension: number
|
||||
let spinnerBorderWidth: number = 3
|
||||
switch (this.props.size) {
|
||||
case 'small':
|
||||
spinnerDimension = 25
|
||||
break;
|
||||
case 'normal':
|
||||
spinnerDimension = 50
|
||||
break;
|
||||
case 'large':
|
||||
spinnerDimension = 100
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
display: 'inline-block',
|
||||
width: `${spinnerDimension}px`,
|
||||
height: `${spinnerDimension}px`,
|
||||
verticalAlign: 'text-bottom',
|
||||
border: `${spinnerBorderWidth}px solid ${this.props.color}`,
|
||||
borderRightColor: 'transparent',
|
||||
borderRadius: '50%',
|
||||
}
|
||||
|
||||
}
|
||||
render() {
|
||||
return <VelocityComponent animation={{ rotateZ: 360 }} duration={750} loop={true} easing={'linear'} runOnMount={true}>
|
||||
<div style={this.generateStyle()} role="status">
|
||||
<ScreenReaderOnlyText>Loading...</ScreenReaderOnlyText>
|
||||
</div>
|
||||
</VelocityComponent>;
|
||||
}
|
||||
}
|
||||
|
||||
export default Spinner;
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Spinner has custom color 1`] = `
|
||||
<Spinner
|
||||
color="#ffffff"
|
||||
size="small"
|
||||
>
|
||||
<VelocityComponent
|
||||
animation={
|
||||
Object {
|
||||
"rotateZ": 360,
|
||||
}
|
||||
}
|
||||
duration={750}
|
||||
easing="linear"
|
||||
interruptBehavior="stop"
|
||||
loop={true}
|
||||
runOnMount={true}
|
||||
targetQuerySelector={null}
|
||||
>
|
||||
<div
|
||||
role="status"
|
||||
style={
|
||||
Object {
|
||||
"border": "3px solid #ffffff",
|
||||
"borderRadius": "50%",
|
||||
"borderRightColor": "transparent",
|
||||
"display": "inline-block",
|
||||
"height": "25px",
|
||||
"verticalAlign": "text-bottom",
|
||||
"width": "25px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<ScreenReaderOnlyText>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"border": 0,
|
||||
"clip": "rect(0,0,0,0)",
|
||||
"height": "1px",
|
||||
"margin": "-1px",
|
||||
"overflow": "hidden",
|
||||
"padding": 0,
|
||||
"position": "absolute",
|
||||
"width": "1px",
|
||||
}
|
||||
}
|
||||
>
|
||||
Loading...
|
||||
</span>
|
||||
</ScreenReaderOnlyText>
|
||||
</div>
|
||||
</VelocityComponent>
|
||||
</Spinner>
|
||||
`;
|
||||
|
||||
exports[`Spinner is large 1`] = `
|
||||
<Spinner
|
||||
color="currentcolor"
|
||||
size="large"
|
||||
>
|
||||
<VelocityComponent
|
||||
animation={
|
||||
Object {
|
||||
"rotateZ": 360,
|
||||
}
|
||||
}
|
||||
duration={750}
|
||||
easing="linear"
|
||||
interruptBehavior="stop"
|
||||
loop={true}
|
||||
runOnMount={true}
|
||||
targetQuerySelector={null}
|
||||
>
|
||||
<div
|
||||
role="status"
|
||||
style={
|
||||
Object {
|
||||
"border": "3px solid currentcolor",
|
||||
"borderRadius": "50%",
|
||||
"borderRightColor": "transparent",
|
||||
"display": "inline-block",
|
||||
"height": "100px",
|
||||
"verticalAlign": "text-bottom",
|
||||
"width": "100px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<ScreenReaderOnlyText>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"border": 0,
|
||||
"clip": "rect(0,0,0,0)",
|
||||
"height": "1px",
|
||||
"margin": "-1px",
|
||||
"overflow": "hidden",
|
||||
"padding": 0,
|
||||
"position": "absolute",
|
||||
"width": "1px",
|
||||
}
|
||||
}
|
||||
>
|
||||
Loading...
|
||||
</span>
|
||||
</ScreenReaderOnlyText>
|
||||
</div>
|
||||
</VelocityComponent>
|
||||
</Spinner>
|
||||
`;
|
||||
|
||||
exports[`Spinner is normal 1`] = `
|
||||
<Spinner
|
||||
color="currentcolor"
|
||||
size="normal"
|
||||
>
|
||||
<VelocityComponent
|
||||
animation={
|
||||
Object {
|
||||
"rotateZ": 360,
|
||||
}
|
||||
}
|
||||
duration={750}
|
||||
easing="linear"
|
||||
interruptBehavior="stop"
|
||||
loop={true}
|
||||
runOnMount={true}
|
||||
targetQuerySelector={null}
|
||||
>
|
||||
<div
|
||||
role="status"
|
||||
style={
|
||||
Object {
|
||||
"border": "3px solid currentcolor",
|
||||
"borderRadius": "50%",
|
||||
"borderRightColor": "transparent",
|
||||
"display": "inline-block",
|
||||
"height": "50px",
|
||||
"verticalAlign": "text-bottom",
|
||||
"width": "50px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<ScreenReaderOnlyText>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"border": 0,
|
||||
"clip": "rect(0,0,0,0)",
|
||||
"height": "1px",
|
||||
"margin": "-1px",
|
||||
"overflow": "hidden",
|
||||
"padding": 0,
|
||||
"position": "absolute",
|
||||
"width": "1px",
|
||||
}
|
||||
}
|
||||
>
|
||||
Loading...
|
||||
</span>
|
||||
</ScreenReaderOnlyText>
|
||||
</div>
|
||||
</VelocityComponent>
|
||||
</Spinner>
|
||||
`;
|
||||
|
||||
exports[`Spinner is small 1`] = `
|
||||
<Spinner
|
||||
color="currentcolor"
|
||||
size="small"
|
||||
>
|
||||
<VelocityComponent
|
||||
animation={
|
||||
Object {
|
||||
"rotateZ": 360,
|
||||
}
|
||||
}
|
||||
duration={750}
|
||||
easing="linear"
|
||||
interruptBehavior="stop"
|
||||
loop={true}
|
||||
runOnMount={true}
|
||||
targetQuerySelector={null}
|
||||
>
|
||||
<div
|
||||
role="status"
|
||||
style={
|
||||
Object {
|
||||
"border": "3px solid currentcolor",
|
||||
"borderRadius": "50%",
|
||||
"borderRightColor": "transparent",
|
||||
"display": "inline-block",
|
||||
"height": "25px",
|
||||
"verticalAlign": "text-bottom",
|
||||
"width": "25px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<ScreenReaderOnlyText>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"border": 0,
|
||||
"clip": "rect(0,0,0,0)",
|
||||
"height": "1px",
|
||||
"margin": "-1px",
|
||||
"overflow": "hidden",
|
||||
"padding": 0,
|
||||
"position": "absolute",
|
||||
"width": "1px",
|
||||
}
|
||||
}
|
||||
>
|
||||
Loading...
|
||||
</span>
|
||||
</ScreenReaderOnlyText>
|
||||
</div>
|
||||
</VelocityComponent>
|
||||
</Spinner>
|
||||
`;
|
3
types/velocity-react/index.d.ts
vendored
3
types/velocity-react/index.d.ts
vendored
|
@ -11,11 +11,10 @@ interface VelocityComponentProps
|
|||
animation: Animation
|
||||
runOnMount?: boolean
|
||||
targetQuerySelector?: TargetQuerySelector
|
||||
|
||||
}
|
||||
|
||||
|
||||
export declare class VelocityComponent extends React.Component<VelocityComponentProps, {}>
|
||||
export declare class VelocityComponent extends React.Component<VelocityComponentProps & jquery.velocity.Options, {}>
|
||||
{
|
||||
runAnimation():void
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue