@bit.rhplus/ui2.ai-button 0.0.1 → 0.0.2

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.
package/dist/index.d.ts CHANGED
@@ -1,17 +1,3 @@
1
- export default AIButton;
2
- /**
3
- * AI Rainbow Button - Moderní tlačítko s rotujícím duhovým prstencem
4
- *
5
- * @param {Object} props
6
- * @param {string} [props.label='AI'] - Text zobrazený na tlačítku
7
- * @param {Function} [props.onClick] - Handler pro kliknutí
8
- * @param {string|number} [props.size='110px'] - Velikost tlačítka
9
- * @param {string|number} [props.ring='10px'] - Tloušťka duhového prstence
10
- * @param {string} [props.className] - Dodatečné CSS třídy
11
- * @param {string} [props.ariaLabel] - Aria label pro accessibility (výchozí je hodnota label)
12
- * @param {string} [props.type='button'] - Typ tlačítka
13
- * @param {Object} [props.style] - Inline styly pro tlačítko
14
- * @param {boolean} [props.disabled=false] - Zakázat tlačítko
15
- */
16
- declare const AIButton: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
1
+ declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<React.RefAttributes<any>>>;
2
+ export default _default;
17
3
  import React from 'react';
package/dist/index.js CHANGED
@@ -1,9 +1,16 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import React from 'react';
2
+ /* eslint-disable */
3
+ import React, { useEffect, useRef, useCallback } from 'react';
3
4
  import classnames from 'classnames';
4
5
  import './style.css';
5
6
  /**
6
7
  * AI Rainbow Button - Moderní tlačítko s rotujícím duhovým prstencem
8
+ * OPTIMALIZOVÁNO PRO MAXIMÁLNÍ VÝKON:
9
+ * - IntersectionObserver pro pause/resume animací
10
+ * - Box-shadow místo blur filter
11
+ * - GPU akcelerace a will-change hints
12
+ * - Sloučené animace
13
+ * - CSS containment
7
14
  *
8
15
  * @param {Object} props
9
16
  * @param {string} [props.label='AI'] - Text zobrazený na tlačítku
@@ -15,17 +22,52 @@ import './style.css';
15
22
  * @param {string} [props.type='button'] - Typ tlačítka
16
23
  * @param {Object} [props.style] - Inline styly pro tlačítko
17
24
  * @param {boolean} [props.disabled=false] - Zakázat tlačítko
25
+ * @param {boolean} [props.disableVisibilityOptimization=false] - Vypnout automatické pausování animací
18
26
  */
19
27
  const AIButton = React.forwardRef((props, ref) => {
20
- const { label = 'AI', onClick, size = '110px', ring = '10px', className, ariaLabel, type = 'button', style, disabled = false, ...restProps } = props;
28
+ const { label = 'AI', onClick, size = '110px', ring = '10px', className, ariaLabel, type = 'button', style, disabled = false, disableVisibilityOptimization = false, ...restProps } = props;
29
+ // Interní ref pro IntersectionObserver
30
+ const internalRef = useRef(null);
31
+ const [isPaused, setIsPaused] = React.useState(false);
32
+ // Kombinace external a internal ref
33
+ const setRefs = useCallback((node) => {
34
+ internalRef.current = node;
35
+ if (typeof ref === 'function') {
36
+ ref(node);
37
+ }
38
+ else if (ref) {
39
+ ref.current = node;
40
+ }
41
+ }, [ref]);
42
+ // IntersectionObserver - pausne animace když tlačítko není viditelné
43
+ useEffect(() => {
44
+ if (disableVisibilityOptimization || !internalRef.current)
45
+ return;
46
+ const observer = new IntersectionObserver((entries) => {
47
+ entries.forEach((entry) => {
48
+ // Pausne když není viditelné nebo je mimo viewport
49
+ setIsPaused(!entry.isIntersecting);
50
+ });
51
+ }, {
52
+ threshold: 0, // Spustí se hned jak zmizí z viewportu
53
+ rootMargin: '50px', // Trochu bufferu
54
+ });
55
+ observer.observe(internalRef.current);
56
+ return () => {
57
+ observer.disconnect();
58
+ };
59
+ }, [disableVisibilityOptimization]);
21
60
  // Inline CSS proměnné pro customizaci
22
61
  const buttonStyle = {
23
62
  '--size': typeof size === 'number' ? `${size}px` : size,
24
63
  '--ring': typeof ring === 'number' ? `${ring}px` : ring,
25
64
  ...style,
26
65
  };
27
- return (_jsx("button", { ref: ref, className: classnames('ai-btn', className), type: type, "aria-label": ariaLabel || label, onClick: onClick, style: buttonStyle, disabled: disabled, ...restProps, children: _jsx("div", { className: "ai-inner", children: _jsx("div", { className: "ai-label", children: label }) }) }));
66
+ return (_jsx("button", { ref: setRefs, className: classnames('ai-btn', className, {
67
+ 'ai-btn-paused': isPaused,
68
+ }), type: type, "aria-label": ariaLabel || label, onClick: onClick, style: buttonStyle, disabled: disabled, ...restProps, children: _jsx("div", { className: "ai-inner", children: _jsx("div", { className: "ai-label", children: label }) }) }));
28
69
  });
29
70
  AIButton.displayName = 'AIButton';
30
- export default AIButton;
71
+ // Memoizace komponenty - zabrání zbytečným re-renderům
72
+ export default React.memo(AIButton);
31
73
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.jsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,aAAa,CAAC;AAErB;;;;;;;;;;;;;GAaG;AACH,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IAC/C,MAAM,EACJ,KAAK,GAAG,IAAI,EACZ,OAAO,EACP,IAAI,GAAG,OAAO,EACd,IAAI,GAAG,MAAM,EACb,SAAS,EACT,SAAS,EACT,IAAI,GAAG,QAAQ,EACf,KAAK,EACL,QAAQ,GAAG,KAAK,EAChB,GAAG,SAAS,EACb,GAAG,KAAK,CAAC;IAEV,sCAAsC;IACtC,MAAM,WAAW,GAAG;QAClB,QAAQ,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI;QACvD,QAAQ,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI;QACvD,GAAG,KAAK;KACT,CAAC;IAEF,OAAO,CACL,iBACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,EAC1C,IAAI,EAAE,IAAI,gBACE,SAAS,IAAI,KAAK,EAC9B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,QAAQ,KACd,SAAS,YAEb,cAAK,SAAS,EAAC,UAAU,YACvB,cAAK,SAAS,EAAC,UAAU,YAAE,KAAK,GAAO,GACnC,GACC,CACV,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,WAAW,GAAG,UAAU,CAAC;AAElC,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.jsx"],"names":[],"mappings":"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"}
package/dist/style.css CHANGED
@@ -1,4 +1,5 @@
1
1
  /* AI Rainbow Button - Duhové tlačítko s rotujícím prstencem */
2
+ /* OPTIMALIZOVÁNO PRO MAXIMÁLNÍ VÝKON */
2
3
 
3
4
  .ai-btn {
4
5
  /* CSS proměnné - lze přepsat pomocí inline style */
@@ -7,6 +8,19 @@
7
8
  --bg: #ffffff;
8
9
  --text: rgba(20, 20, 20, 0.92);
9
10
 
11
+ /* Sdílený gradient - použije se vícekrát */
12
+ --rainbow-gradient: conic-gradient(
13
+ from 0deg,
14
+ #ff004c,
15
+ #ff8a00,
16
+ #ffe600,
17
+ #35ff7a,
18
+ #00d4ff,
19
+ #6a5cff,
20
+ #ff4fd8,
21
+ #ff004c
22
+ );
23
+
10
24
  position: relative;
11
25
  width: var(--size);
12
26
  height: var(--size);
@@ -17,7 +31,11 @@
17
31
  padding: 0;
18
32
  outline: none;
19
33
  -webkit-tap-highlight-color: transparent;
34
+
35
+ /* GPU akcelerace + containment pro izolaci */
20
36
  transform: translateZ(0);
37
+ will-change: transform;
38
+ contain: layout style paint;
21
39
  transition: transform 0.15s ease;
22
40
  }
23
41
 
@@ -33,18 +51,8 @@
33
51
  inset: 0;
34
52
  border-radius: inherit;
35
53
 
36
- /* Duhový conic gradient */
37
- background: conic-gradient(
38
- from 0deg,
39
- #ff004c,
40
- #ff8a00,
41
- #ffe600,
42
- #35ff7a,
43
- #00d4ff,
44
- #6a5cff,
45
- #ff4fd8,
46
- #ff004c
47
- );
54
+ /* Použití sdíleného gradientu */
55
+ background: var(--rainbow-gradient);
48
56
 
49
57
  /* Vyříznutí vnitřku => prstenec */
50
58
  -webkit-mask: radial-gradient(
@@ -58,6 +66,10 @@
58
66
  #000 calc(100% - var(--ring) + 1px)
59
67
  );
60
68
 
69
+ /* GPU akcelerace pro rotaci */
70
+ transform: translateZ(0);
71
+ will-change: transform;
72
+
61
73
  /* Animace "točení" barev */
62
74
  animation: ai-btn-spin 3.2s linear infinite;
63
75
  filter: saturate(1.15) brightness(1.05);
@@ -68,27 +80,28 @@
68
80
  filter: saturate(0.5) brightness(0.8);
69
81
  }
70
82
 
71
- /* Glow aura kolem tlačítka */
83
+ /* Glow aura kolem tlačítka - OPTIMALIZOVÁNO: box-shadow místo blur */
72
84
  .ai-btn::after {
73
85
  content: '';
74
86
  position: absolute;
75
- inset: -18px;
87
+ inset: 0;
76
88
  border-radius: inherit;
77
- background: conic-gradient(
78
- from 0deg,
79
- #ff004c,
80
- #ff8a00,
81
- #ffe600,
82
- #35ff7a,
83
- #00d4ff,
84
- #6a5cff,
85
- #ff4fd8,
86
- #ff004c
87
- );
88
- opacity: 0.35;
89
- filter: blur(22px);
90
- animation: ai-btn-spin 3.2s linear infinite, ai-btn-breathe 2.6s ease-in-out infinite;
89
+
90
+ /* Použití sdíleného gradientu */
91
+ background: var(--rainbow-gradient);
92
+
93
+ /* GPU akcelerace */
91
94
  transform: translateZ(0);
95
+ will-change: transform, opacity;
96
+
97
+ /* Box-shadow glow místo blur filter (MNOHEM rychlejší) */
98
+ box-shadow: 0 0 30px 12px rgba(255, 0, 76, 0.4),
99
+ 0 0 50px 20px rgba(255, 138, 0, 0.3), 0 0 70px 28px rgba(0, 212, 255, 0.25),
100
+ 0 0 90px 35px rgba(106, 92, 255, 0.2);
101
+
102
+ /* Sloučená animace pro lepší výkon */
103
+ animation: ai-btn-glow 3.2s linear infinite;
104
+ opacity: 0.35;
92
105
  pointer-events: none;
93
106
  }
94
107
 
@@ -97,6 +110,12 @@
97
110
  opacity: 0.15;
98
111
  }
99
112
 
113
+ /* Pausnutí animací když není viditelné - řízeno IntersectionObserver */
114
+ .ai-btn.ai-btn-paused::before,
115
+ .ai-btn.ai-btn-paused::after {
116
+ animation-play-state: paused;
117
+ }
118
+
100
119
  /* Vnitřek tlačítka */
101
120
  .ai-inner {
102
121
  position: absolute;
@@ -145,19 +164,30 @@
145
164
  /* Animace - rotace */
146
165
  @keyframes ai-btn-spin {
147
166
  to {
148
- transform: rotate(360deg);
167
+ transform: translateZ(0) rotate(360deg);
149
168
  }
150
169
  }
151
170
 
152
- /* Animace - dýchání (breathe) */
153
- @keyframes ai-btn-breathe {
154
- 0%,
155
- 100% {
171
+ /* Animace - sloučená glow (spin + breathe) pro lepší výkon */
172
+ @keyframes ai-btn-glow {
173
+ 0% {
174
+ transform: translateZ(0) rotate(0deg);
156
175
  opacity: 0.28;
157
176
  }
177
+ 25% {
178
+ opacity: 0.38;
179
+ }
158
180
  50% {
181
+ transform: translateZ(0) rotate(180deg);
159
182
  opacity: 0.46;
160
183
  }
184
+ 75% {
185
+ opacity: 0.38;
186
+ }
187
+ 100% {
188
+ transform: translateZ(0) rotate(360deg);
189
+ opacity: 0.28;
190
+ }
161
191
  }
162
192
 
163
193
  /* Respektovat uživatelské preference pro redukci pohybu */
package/index.jsx CHANGED
@@ -1,9 +1,16 @@
1
- import React from 'react';
1
+ /* eslint-disable */
2
+ import React, { useEffect, useRef, useCallback } from 'react';
2
3
  import classnames from 'classnames';
3
4
  import './style.css';
4
5
 
5
6
  /**
6
7
  * AI Rainbow Button - Moderní tlačítko s rotujícím duhovým prstencem
8
+ * OPTIMALIZOVÁNO PRO MAXIMÁLNÍ VÝKON:
9
+ * - IntersectionObserver pro pause/resume animací
10
+ * - Box-shadow místo blur filter
11
+ * - GPU akcelerace a will-change hints
12
+ * - Sloučené animace
13
+ * - CSS containment
7
14
  *
8
15
  * @param {Object} props
9
16
  * @param {string} [props.label='AI'] - Text zobrazený na tlačítku
@@ -15,6 +22,7 @@ import './style.css';
15
22
  * @param {string} [props.type='button'] - Typ tlačítka
16
23
  * @param {Object} [props.style] - Inline styly pro tlačítko
17
24
  * @param {boolean} [props.disabled=false] - Zakázat tlačítko
25
+ * @param {boolean} [props.disableVisibilityOptimization=false] - Vypnout automatické pausování animací
18
26
  */
19
27
  const AIButton = React.forwardRef((props, ref) => {
20
28
  const {
@@ -27,9 +35,51 @@ const AIButton = React.forwardRef((props, ref) => {
27
35
  type = 'button',
28
36
  style,
29
37
  disabled = false,
38
+ disableVisibilityOptimization = false,
30
39
  ...restProps
31
40
  } = props;
32
41
 
42
+ // Interní ref pro IntersectionObserver
43
+ const internalRef = useRef(null);
44
+ const [isPaused, setIsPaused] = React.useState(false);
45
+
46
+ // Kombinace external a internal ref
47
+ const setRefs = useCallback(
48
+ (node) => {
49
+ internalRef.current = node;
50
+ if (typeof ref === 'function') {
51
+ ref(node);
52
+ } else if (ref) {
53
+ ref.current = node;
54
+ }
55
+ },
56
+ [ref]
57
+ );
58
+
59
+ // IntersectionObserver - pausne animace když tlačítko není viditelné
60
+ useEffect(() => {
61
+ if (disableVisibilityOptimization || !internalRef.current) return;
62
+
63
+ const observer = new IntersectionObserver(
64
+ (entries) => {
65
+ entries.forEach((entry) => {
66
+ // Pausne když není viditelné nebo je mimo viewport
67
+ setIsPaused(!entry.isIntersecting);
68
+ });
69
+ },
70
+ {
71
+ threshold: 0, // Spustí se hned jak zmizí z viewportu
72
+ rootMargin: '50px', // Trochu bufferu
73
+ }
74
+ );
75
+
76
+ observer.observe(internalRef.current);
77
+
78
+ return () => {
79
+ observer.disconnect();
80
+ };
81
+ }, [disableVisibilityOptimization]);
82
+
33
83
  // Inline CSS proměnné pro customizaci
34
84
  const buttonStyle = {
35
85
  '--size': typeof size === 'number' ? `${size}px` : size,
@@ -39,8 +89,10 @@ const AIButton = React.forwardRef((props, ref) => {
39
89
 
40
90
  return (
41
91
  <button
42
- ref={ref}
43
- className={classnames('ai-btn', className)}
92
+ ref={setRefs}
93
+ className={classnames('ai-btn', className, {
94
+ 'ai-btn-paused': isPaused,
95
+ })}
44
96
  type={type}
45
97
  aria-label={ariaLabel || label}
46
98
  onClick={onClick}
@@ -57,4 +109,5 @@ const AIButton = React.forwardRef((props, ref) => {
57
109
 
58
110
  AIButton.displayName = 'AIButton';
59
111
 
60
- export default AIButton;
112
+ // Memoizace komponenty - zabrání zbytečným re-renderům
113
+ export default React.memo(AIButton);
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@bit.rhplus/ui2.ai-button",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
+ "homepage": "https://bit.cloud/remote-scope/ui2/ai-button",
4
5
  "main": "dist/index.js",
5
6
  "componentId": {
7
+ "scope": "remote-scope",
6
8
  "name": "ui2/ai-button",
7
- "version": "0.0.1",
8
- "scope": "remote-scope"
9
+ "version": "0.0.2"
9
10
  },
10
11
  "dependencies": {
11
12
  "classnames": "^2.5.1"
package/style.css CHANGED
@@ -1,4 +1,5 @@
1
1
  /* AI Rainbow Button - Duhové tlačítko s rotujícím prstencem */
2
+ /* OPTIMALIZOVÁNO PRO MAXIMÁLNÍ VÝKON */
2
3
 
3
4
  .ai-btn {
4
5
  /* CSS proměnné - lze přepsat pomocí inline style */
@@ -7,6 +8,19 @@
7
8
  --bg: #ffffff;
8
9
  --text: rgba(20, 20, 20, 0.92);
9
10
 
11
+ /* Sdílený gradient - použije se vícekrát */
12
+ --rainbow-gradient: conic-gradient(
13
+ from 0deg,
14
+ #ff004c,
15
+ #ff8a00,
16
+ #ffe600,
17
+ #35ff7a,
18
+ #00d4ff,
19
+ #6a5cff,
20
+ #ff4fd8,
21
+ #ff004c
22
+ );
23
+
10
24
  position: relative;
11
25
  width: var(--size);
12
26
  height: var(--size);
@@ -17,7 +31,11 @@
17
31
  padding: 0;
18
32
  outline: none;
19
33
  -webkit-tap-highlight-color: transparent;
34
+
35
+ /* GPU akcelerace + containment pro izolaci */
20
36
  transform: translateZ(0);
37
+ will-change: transform;
38
+ contain: layout style paint;
21
39
  transition: transform 0.15s ease;
22
40
  }
23
41
 
@@ -33,18 +51,8 @@
33
51
  inset: 0;
34
52
  border-radius: inherit;
35
53
 
36
- /* Duhový conic gradient */
37
- background: conic-gradient(
38
- from 0deg,
39
- #ff004c,
40
- #ff8a00,
41
- #ffe600,
42
- #35ff7a,
43
- #00d4ff,
44
- #6a5cff,
45
- #ff4fd8,
46
- #ff004c
47
- );
54
+ /* Použití sdíleného gradientu */
55
+ background: var(--rainbow-gradient);
48
56
 
49
57
  /* Vyříznutí vnitřku => prstenec */
50
58
  -webkit-mask: radial-gradient(
@@ -58,6 +66,10 @@
58
66
  #000 calc(100% - var(--ring) + 1px)
59
67
  );
60
68
 
69
+ /* GPU akcelerace pro rotaci */
70
+ transform: translateZ(0);
71
+ will-change: transform;
72
+
61
73
  /* Animace "točení" barev */
62
74
  animation: ai-btn-spin 3.2s linear infinite;
63
75
  filter: saturate(1.15) brightness(1.05);
@@ -68,27 +80,28 @@
68
80
  filter: saturate(0.5) brightness(0.8);
69
81
  }
70
82
 
71
- /* Glow aura kolem tlačítka */
83
+ /* Glow aura kolem tlačítka - OPTIMALIZOVÁNO: box-shadow místo blur */
72
84
  .ai-btn::after {
73
85
  content: '';
74
86
  position: absolute;
75
- inset: -18px;
87
+ inset: 0;
76
88
  border-radius: inherit;
77
- background: conic-gradient(
78
- from 0deg,
79
- #ff004c,
80
- #ff8a00,
81
- #ffe600,
82
- #35ff7a,
83
- #00d4ff,
84
- #6a5cff,
85
- #ff4fd8,
86
- #ff004c
87
- );
88
- opacity: 0.35;
89
- filter: blur(22px);
90
- animation: ai-btn-spin 3.2s linear infinite, ai-btn-breathe 2.6s ease-in-out infinite;
89
+
90
+ /* Použití sdíleného gradientu */
91
+ background: var(--rainbow-gradient);
92
+
93
+ /* GPU akcelerace */
91
94
  transform: translateZ(0);
95
+ will-change: transform, opacity;
96
+
97
+ /* Box-shadow glow místo blur filter (MNOHEM rychlejší) */
98
+ box-shadow: 0 0 30px 12px rgba(255, 0, 76, 0.4),
99
+ 0 0 50px 20px rgba(255, 138, 0, 0.3), 0 0 70px 28px rgba(0, 212, 255, 0.25),
100
+ 0 0 90px 35px rgba(106, 92, 255, 0.2);
101
+
102
+ /* Sloučená animace pro lepší výkon */
103
+ animation: ai-btn-glow 3.2s linear infinite;
104
+ opacity: 0.35;
92
105
  pointer-events: none;
93
106
  }
94
107
 
@@ -97,6 +110,12 @@
97
110
  opacity: 0.15;
98
111
  }
99
112
 
113
+ /* Pausnutí animací když není viditelné - řízeno IntersectionObserver */
114
+ .ai-btn.ai-btn-paused::before,
115
+ .ai-btn.ai-btn-paused::after {
116
+ animation-play-state: paused;
117
+ }
118
+
100
119
  /* Vnitřek tlačítka */
101
120
  .ai-inner {
102
121
  position: absolute;
@@ -145,19 +164,30 @@
145
164
  /* Animace - rotace */
146
165
  @keyframes ai-btn-spin {
147
166
  to {
148
- transform: rotate(360deg);
167
+ transform: translateZ(0) rotate(360deg);
149
168
  }
150
169
  }
151
170
 
152
- /* Animace - dýchání (breathe) */
153
- @keyframes ai-btn-breathe {
154
- 0%,
155
- 100% {
171
+ /* Animace - sloučená glow (spin + breathe) pro lepší výkon */
172
+ @keyframes ai-btn-glow {
173
+ 0% {
174
+ transform: translateZ(0) rotate(0deg);
156
175
  opacity: 0.28;
157
176
  }
177
+ 25% {
178
+ opacity: 0.38;
179
+ }
158
180
  50% {
181
+ transform: translateZ(0) rotate(180deg);
159
182
  opacity: 0.46;
160
183
  }
184
+ 75% {
185
+ opacity: 0.38;
186
+ }
187
+ 100% {
188
+ transform: translateZ(0) rotate(360deg);
189
+ opacity: 0.28;
190
+ }
161
191
  }
162
192
 
163
193
  /* Respektovat uživatelské preference pro redukci pohybu */