-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Expand file tree
/
Copy pathspinner.tsx
More file actions
135 lines (118 loc) · 4.18 KB
/
spinner.tsx
File metadata and controls
135 lines (118 loc) · 4.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import type { ComponentInterface } from '@stencil/core';
import { Component, Host, Prop, h } from '@stencil/core';
import { createColorClasses } from '@utils/theme';
import { config } from '../../global/config';
import { getIonMode } from '../../global/ionic-global';
import type { Color } from '../../interface';
import type { SpinnerTypes } from './spinner-configs';
import { SPINNERS } from './spinner-configs';
import type { SpinnerConfig } from './spinner-interface';
/**
* @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component.
*/
@Component({
tag: 'ion-spinner',
styleUrl: 'spinner.scss',
shadow: true,
})
export class Spinner implements ComponentInterface {
/**
* The color to use from your application's color palette.
* Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
* For more information on colors, see [theming](/docs/theming/basics).
*/
@Prop({ reflect: true }) color?: Color;
/**
* Duration of the spinner animation in milliseconds. The default varies based on the spinner.
*/
@Prop() duration?: number;
/**
* The name of the SVG spinner to use. If a name is not provided, the platform's default
* spinner will be used.
*/
@Prop() name?: SpinnerTypes;
/**
* If `true`, the spinner's animation will be paused.
*/
@Prop() paused = false;
/**
* Set to `"xsmall"` for the smallest size.
* Set to `"small"` for a smaller size.
* Set to `"medium"` for a medium size.
* Set to `"large"` for a large size.
* Set to `"xlarge"` for the largest size.
*
* Defaults to `"medium"`.
*/
@Prop() size?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
private getName(): SpinnerTypes {
const spinnerName = this.name || config.get('spinner');
const mode = getIonMode(this);
if (spinnerName) {
return spinnerName;
}
return mode === 'ios' ? 'lines' : 'circular';
}
/**
* Set the size based on the custom theme config
*/
get sizeValue(): string {
const sizeConfig = config.getObjectValue('IonSpinner.size', 'medium') as string;
console.log('sizeConfig', sizeConfig);
const size = this.size || sizeConfig;
return size;
}
render() {
const { duration: animatedDuration, color, paused, sizeValue } = this;
const spinnerName = this.getName();
const spinner = SPINNERS[spinnerName] ?? SPINNERS['lines'];
const duration = typeof animatedDuration === 'number' && animatedDuration > 10 ? animatedDuration : spinner.dur;
const svgs: SVGElement[] = [];
if (spinner.circles !== undefined) {
for (let i = 0; i < spinner.circles; i++) {
svgs.push(buildCircle(spinner, duration, i, spinner.circles));
}
} else if (spinner.lines !== undefined) {
for (let i = 0; i < spinner.lines; i++) {
svgs.push(buildLine(spinner, duration, i, spinner.lines));
}
}
return (
<Host
class={createColorClasses(color, {
[`spinner-${spinnerName}`]: true,
'spinner-paused': paused || config.getBoolean('_testing'),
[`spinner-${sizeValue}`]: true,
})}
role="progressbar"
style={spinner.elmDuration ? { animationDuration: duration + 'ms' } : {}}
>
{svgs}
</Host>
);
}
}
const buildCircle = (spinner: SpinnerConfig, duration: number, index: number, total: number) => {
const data = spinner.fn(duration, index, total);
data.style['animation-duration'] = duration + 'ms';
return (
<svg viewBox={data.viewBox || '0 0 64 64'} style={data.style}>
<circle
transform={data.transform || 'translate(32,32)'}
cx={data.cx}
cy={data.cy}
r={data.r}
style={spinner.elmDuration ? { animationDuration: duration + 'ms' } : {}}
/>
</svg>
);
};
const buildLine = (spinner: SpinnerConfig, duration: number, index: number, total: number) => {
const data = spinner.fn(duration, index, total);
data.style['animation-duration'] = duration + 'ms';
return (
<svg viewBox={data.viewBox || '0 0 64 64'} style={data.style}>
<line transform="translate(32,32)" y1={data.y1} y2={data.y2} />
</svg>
);
};