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
|
animation: Animation
|
||||||
runOnMount?: boolean
|
runOnMount?: boolean
|
||||||
targetQuerySelector?: TargetQuerySelector
|
targetQuerySelector?: TargetQuerySelector
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export declare class VelocityComponent extends React.Component<VelocityComponentProps, {}>
|
export declare class VelocityComponent extends React.Component<VelocityComponentProps & jquery.velocity.Options, {}>
|
||||||
{
|
{
|
||||||
runAnimation():void
|
runAnimation():void
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue