@cloud-ru/ds-loader 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE +201 -0
  3. package/README.md +88 -0
  4. package/dist/cjs/components/Spinner/Spinner.d.ts +10 -0
  5. package/dist/cjs/components/Spinner/Spinner.js +20 -0
  6. package/dist/cjs/components/Spinner/constants.d.ts +17 -0
  7. package/dist/cjs/components/Spinner/constants.js +17 -0
  8. package/dist/cjs/components/Spinner/index.d.ts +1 -0
  9. package/dist/cjs/components/Spinner/index.js +17 -0
  10. package/dist/cjs/components/Spinner/styles.module.css +36 -0
  11. package/dist/cjs/components/Spinner/utils.d.ts +5 -0
  12. package/dist/cjs/components/Spinner/utils.js +20 -0
  13. package/dist/cjs/components/Sun/Sun.d.ts +10 -0
  14. package/dist/cjs/components/Sun/Sun.js +17 -0
  15. package/dist/cjs/components/Sun/constants.d.ts +18 -0
  16. package/dist/cjs/components/Sun/constants.js +26 -0
  17. package/dist/cjs/components/Sun/index.d.ts +1 -0
  18. package/dist/cjs/components/Sun/index.js +17 -0
  19. package/dist/cjs/components/Sun/styles.module.css +88 -0
  20. package/dist/cjs/components/constants.d.ts +13 -0
  21. package/dist/cjs/components/constants.js +16 -0
  22. package/dist/cjs/components/index.d.ts +4 -0
  23. package/dist/cjs/components/index.js +20 -0
  24. package/dist/cjs/components/types.d.ts +4 -0
  25. package/dist/cjs/components/types.js +2 -0
  26. package/dist/cjs/index.d.ts +1 -0
  27. package/dist/cjs/index.js +17 -0
  28. package/dist/cjs/package.json +3 -0
  29. package/dist/cjs/style.css +124 -0
  30. package/dist/esm/components/Spinner/Spinner.d.ts +10 -0
  31. package/dist/esm/components/Spinner/Spinner.js +14 -0
  32. package/dist/esm/components/Spinner/constants.d.ts +17 -0
  33. package/dist/esm/components/Spinner/constants.js +14 -0
  34. package/dist/esm/components/Spinner/index.d.ts +1 -0
  35. package/dist/esm/components/Spinner/index.js +1 -0
  36. package/dist/esm/components/Spinner/styles.module.css +36 -0
  37. package/dist/esm/components/Spinner/utils.d.ts +5 -0
  38. package/dist/esm/components/Spinner/utils.js +17 -0
  39. package/dist/esm/components/Sun/Sun.d.ts +10 -0
  40. package/dist/esm/components/Sun/Sun.js +11 -0
  41. package/dist/esm/components/Sun/constants.d.ts +18 -0
  42. package/dist/esm/components/Sun/constants.js +23 -0
  43. package/dist/esm/components/Sun/index.d.ts +1 -0
  44. package/dist/esm/components/Sun/index.js +1 -0
  45. package/dist/esm/components/Sun/styles.module.css +88 -0
  46. package/dist/esm/components/constants.d.ts +13 -0
  47. package/dist/esm/components/constants.js +13 -0
  48. package/dist/esm/components/index.d.ts +4 -0
  49. package/dist/esm/components/index.js +4 -0
  50. package/dist/esm/components/types.d.ts +4 -0
  51. package/dist/esm/components/types.js +1 -0
  52. package/dist/esm/index.d.ts +1 -0
  53. package/dist/esm/index.js +1 -0
  54. package/dist/esm/style.css +124 -0
  55. package/dist/tsconfig.cjs.tsbuildinfo +1 -0
  56. package/dist/tsconfig.esm.tsbuildinfo +1 -0
  57. package/package.json +42 -0
  58. package/src/components/Spinner/Spinner.tsx +41 -0
  59. package/src/components/Spinner/constants.ts +26 -0
  60. package/src/components/Spinner/index.ts +1 -0
  61. package/src/components/Spinner/styles.module.scss +30 -0
  62. package/src/components/Spinner/utils.ts +21 -0
  63. package/src/components/Sun/Sun.tsx +60 -0
  64. package/src/components/Sun/constants.ts +25 -0
  65. package/src/components/Sun/index.ts +1 -0
  66. package/src/components/Sun/styles.module.scss +72 -0
  67. package/src/components/constants.ts +14 -0
  68. package/src/components/index.ts +4 -0
  69. package/src/components/types.ts +6 -0
  70. package/src/index.ts +1 -0
@@ -0,0 +1,41 @@
1
+ import { extractSupportProps, WithSupportProps } from '@cloud-ru/ds-utils';
2
+ import cn from 'classnames';
3
+
4
+ import { LOADER_SIZE } from '../constants';
5
+ import { LoaderSize } from '../types';
6
+ import { SPINNER_GEOMETRY, SPINNER_TRACK_OPACITY } from './constants';
7
+ import styles from './styles.module.scss';
8
+ import { buildQuarterArcPath } from './utils';
9
+
10
+ export type SpinnerProps = WithSupportProps<{
11
+ /** Размер */
12
+ size?: LoaderSize;
13
+ /** CSS-класс */
14
+ className?: string;
15
+ }>;
16
+
17
+ /** Компонент спиннер */
18
+ export function Spinner({ size = LOADER_SIZE.S, className, ...rest }: SpinnerProps) {
19
+ const { frame, ring, strokeWidth } = SPINNER_GEOMETRY[size];
20
+ const center = frame / 2;
21
+ const radius = ring / 2;
22
+
23
+ return (
24
+ <svg
25
+ viewBox={`0 0 ${frame} ${frame}`}
26
+ fill='none'
27
+ xmlns='http://www.w3.org/2000/svg'
28
+ className={cn(styles.spinner, className)}
29
+ {...extractSupportProps(rest)}
30
+ data-size={size}
31
+ >
32
+ <circle opacity={SPINNER_TRACK_OPACITY} cx={center} cy={center} r={radius} strokeWidth={strokeWidth} />
33
+ <path
34
+ d={buildQuarterArcPath(center, radius)}
35
+ strokeWidth={strokeWidth}
36
+ strokeLinecap='round'
37
+ strokeLinejoin='round'
38
+ />
39
+ </svg>
40
+ );
41
+ }
@@ -0,0 +1,26 @@
1
+ import { LOADER_SIZE } from '../constants';
2
+ import { LoaderSize } from '../types';
3
+
4
+ type SpinnerGeometry = {
5
+ /** Сторона квадратного кадра — `viewBox` иконки */
6
+ frame: number;
7
+ /** Диаметр кольца по центру обводки */
8
+ ring: number;
9
+ /** Толщина обводки кольца и дуги */
10
+ strokeWidth: number;
11
+ };
12
+
13
+ /**
14
+ * Геометрия кольца по размерам — снята с мастера Figma `loader/loaderSpinner`
15
+ * (страница `loader`, узел `2918:21302`).
16
+ */
17
+ export const SPINNER_GEOMETRY: Record<LoaderSize, SpinnerGeometry> = {
18
+ [LOADER_SIZE['2XS']]: { frame: 8, ring: 6, strokeWidth: 0.5 },
19
+ [LOADER_SIZE.XS]: { frame: 16, ring: 9, strokeWidth: 1.25 },
20
+ [LOADER_SIZE.S]: { frame: 24, ring: 13, strokeWidth: 1.5 },
21
+ [LOADER_SIZE.M]: { frame: 32, ring: 20, strokeWidth: 2 },
22
+ [LOADER_SIZE.L]: { frame: 40, ring: 30, strokeWidth: 2.5 },
23
+ };
24
+
25
+ /** Прозрачность трека — кольца под вращающейся дугой */
26
+ export const SPINNER_TRACK_OPACITY = 0.24;
@@ -0,0 +1 @@
1
+ export * from './Spinner';
@@ -0,0 +1,30 @@
1
+ @use '@cloud-ru/ds-figma-variables/build/scss/styles/styles.module' as base;
2
+
3
+ $sizes: '2xs', 'xs', 's', 'm', 'l';
4
+
5
+ .spinner {
6
+ pointer-events: none;
7
+ stroke: currentcolor;
8
+ animation: spin 1s ease-in-out infinite;
9
+
10
+ & > g > path {
11
+ fill: currentcolor;
12
+ }
13
+
14
+ & > mask {
15
+ mask-type: alpha;
16
+ }
17
+
18
+ @each $size in $sizes {
19
+ &[data-size="#{$size}"] {
20
+ width: base.simple-var(base.$sn-density, 'size', 'icon', $size);
21
+ height: base.simple-var(base.$sn-density, 'size', 'icon', $size);
22
+ }
23
+ }
24
+
25
+ @keyframes spin {
26
+ to {
27
+ transform: rotate(360deg);
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,21 @@
1
+ /** Отношение длины контрольного плеча к радиусу для четверти окружности, заданной кубической кривой Безье */
2
+ const QUARTER_ARC_HANDLE_RATIO = 0.5522847498;
3
+
4
+ function format(value: number): string {
5
+ return String(Number(value.toFixed(5)));
6
+ }
7
+
8
+ /**
9
+ * Путь четверти окружности — от левой точки кольца к верхней, против часовой стрелки.
10
+ * Так дуга спиннера повторяет `ToneAlpha1` из мастера Figma.
11
+ */
12
+ export function buildQuarterArcPath(center: number, radius: number): string {
13
+ const handle = radius * QUARTER_ARC_HANDLE_RATIO;
14
+
15
+ const start = `${format(center - radius)} ${format(center)}`;
16
+ const firstControl = `${format(center - radius)} ${format(center - handle)}`;
17
+ const secondControl = `${format(center - handle)} ${format(center - radius)}`;
18
+ const end = `${format(center)} ${format(center - radius)}`;
19
+
20
+ return `M${start}C${firstControl} ${secondControl} ${end}`;
21
+ }
@@ -0,0 +1,60 @@
1
+ import { extractSupportProps, WithSupportProps } from '@cloud-ru/ds-utils';
2
+ import cn from 'classnames';
3
+
4
+ import { LOADER_SIZE } from '../constants';
5
+ import { SunSize } from '../types';
6
+ import { SUN_STROKE_WIDTH } from './constants';
7
+ import styles from './styles.module.scss';
8
+
9
+ export type SunProps = WithSupportProps<{
10
+ /** Размер */
11
+ size?: SunSize;
12
+ /** CSS-класс */
13
+ className?: string;
14
+ }>;
15
+
16
+ /** Компонент спиннер */
17
+ export function Sun({ size = LOADER_SIZE.S, className, ...rest }: SunProps) {
18
+ const strokeWidth = SUN_STROKE_WIDTH[size];
19
+
20
+ return (
21
+ <svg
22
+ viewBox='0 0 24 24'
23
+ fill='none'
24
+ xmlns='http://www.w3.org/2000/svg'
25
+ id='SunSVG'
26
+ className={cn(styles.sun, className)}
27
+ {...extractSupportProps(rest)}
28
+ data-size={size}
29
+ >
30
+ <path d='M12 4V7' strokeWidth={strokeWidth} strokeLinecap='round' strokeLinejoin='round' />
31
+ <path
32
+ d='M6.34302 6.34314L8.46434 8.46446'
33
+ strokeWidth={strokeWidth}
34
+ strokeLinecap='round'
35
+ strokeLinejoin='round'
36
+ />
37
+ <path d='M4 12L7 12' strokeWidth={strokeWidth} strokeLinecap='round' strokeLinejoin='round' />
38
+ <path
39
+ d='M6.34302 17.6569L8.46434 15.5355'
40
+ strokeWidth={strokeWidth}
41
+ strokeLinecap='round'
42
+ strokeLinejoin='round'
43
+ />
44
+ <path d='M12 17V20' strokeWidth={strokeWidth} strokeLinecap='round' strokeLinejoin='round' />
45
+ <path
46
+ d='M15.5354 15.5355L17.6567 17.6568'
47
+ strokeWidth={strokeWidth}
48
+ strokeLinecap='round'
49
+ strokeLinejoin='round'
50
+ />
51
+ <path d='M17 12L20 12' strokeWidth={strokeWidth} strokeLinecap='round' strokeLinejoin='round' />
52
+ <path
53
+ d='M15.5354 8.46448L17.6567 6.34316'
54
+ strokeWidth={strokeWidth}
55
+ strokeLinecap='round'
56
+ strokeLinejoin='round'
57
+ />
58
+ </svg>
59
+ );
60
+ }
@@ -0,0 +1,25 @@
1
+ import { SUN_SIZE } from '../constants';
2
+ import { SunSize } from '../types';
3
+
4
+ /**
5
+ * Толщина луча по размерам, в единицах `viewBox` (кадр 24 у всех размеров).
6
+ *
7
+ * Пути солнца нарисованы в кадре 24, а сам `<svg>` масштабируется CSS'ом до размера
8
+ * иконки — значит видимая толщина равна `strokeWidth × размер / 24`. Поэтому число
9
+ * здесь пересчитано от эталона Figma, а не взято из макета напрямую:
10
+ *
11
+ * | размер | иконка | эталон Figma | `strokeWidth` |
12
+ * |--------|--------|--------------|---------------|
13
+ * | `xs` | 16 | 1.25 | 1.875 |
14
+ * | `s` | 24 | 1.5 | 1.5 |
15
+ * | `m` | 32 | 2 | 1.5 |
16
+ * | `l` | 40 | 2.5 | 1.5 |
17
+ *
18
+ * Без этой карты толщина выводилась из масштаба и при `xs` давала 1.0 вместо 1.25.
19
+ */
20
+ export const SUN_STROKE_WIDTH: Record<SunSize, number> = {
21
+ [SUN_SIZE.XS]: 1.875,
22
+ [SUN_SIZE.S]: 1.5,
23
+ [SUN_SIZE.M]: 1.5,
24
+ [SUN_SIZE.L]: 1.5,
25
+ };
@@ -0,0 +1 @@
1
+ export * from './Sun';
@@ -0,0 +1,72 @@
1
+ @use '@cloud-ru/ds-figma-variables/build/scss/styles/styles.module' as base;
2
+
3
+ $sizes: 'xs', 's', 'm', 'l';
4
+
5
+ .sun {
6
+ pointer-events: none;
7
+ fill: currentcolor;
8
+
9
+ @each $size in $sizes {
10
+ &[data-size="#{$size}"] {
11
+ width: base.simple-var(base.$sn-density, 'size', 'icon', $size);
12
+ height: base.simple-var(base.$sn-density, 'size', 'icon', $size);
13
+ }
14
+ }
15
+
16
+ & > path {
17
+ stroke: currentcolor;
18
+ animation-name: loading-wheel;
19
+ animation-timing-function: linear;
20
+ animation-iteration-count: infinite;
21
+
22
+ @for $i from 1 through 8 {
23
+ // Первый луч — верхний: у него нулевая задержка, поэтому в покое яркая
24
+ // голова стоит на нём, как в Figma. Порядок задержек не меняем, иначе
25
+ // перевернётся направление вращения.
26
+ &:nth-child(#{$i}) {
27
+ animation-duration: 1000ms;
28
+ animation-delay: #{-($i - 1) * 125}ms;
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+ // Прозрачности восьми лучей из Figma: яркая голова и резкий обрыв, а не пологий
35
+ // спад. Каждый шаг — 12.5% цикла, то есть один луч.
36
+ @keyframes loading-wheel {
37
+ 0% {
38
+ opacity: 1;
39
+ }
40
+
41
+ 12.5% {
42
+ opacity: 0.48;
43
+ }
44
+
45
+ 25% {
46
+ opacity: 0.4;
47
+ }
48
+
49
+ 37.5% {
50
+ opacity: 0.32;
51
+ }
52
+
53
+ 50% {
54
+ opacity: 0.24;
55
+ }
56
+
57
+ 62.5% {
58
+ opacity: 0.16;
59
+ }
60
+
61
+ 75% {
62
+ opacity: 0.08;
63
+ }
64
+
65
+ 87.5% {
66
+ opacity: 0.04;
67
+ }
68
+
69
+ 100% {
70
+ opacity: 1;
71
+ }
72
+ }
@@ -0,0 +1,14 @@
1
+ export const LOADER_SIZE = {
2
+ '2XS': '2xs',
3
+ XS: 'xs',
4
+ S: 's',
5
+ M: 'm',
6
+ L: 'l',
7
+ } as const;
8
+
9
+ export const SUN_SIZE = {
10
+ XS: 'xs',
11
+ S: 's',
12
+ M: 'm',
13
+ L: 'l',
14
+ } as const;
@@ -0,0 +1,4 @@
1
+ export * from './constants';
2
+ export * from './Spinner';
3
+ export * from './Sun';
4
+ export * from './types';
@@ -0,0 +1,6 @@
1
+ import { ValueOf } from '@cloud-ru/ds-utils';
2
+
3
+ import { LOADER_SIZE, SUN_SIZE } from './constants';
4
+
5
+ export type LoaderSize = ValueOf<typeof LOADER_SIZE>;
6
+ export type SunSize = ValueOf<typeof SUN_SIZE>;
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './components';