@bit.rhplus/ag-grid 0.0.49 → 0.0.51

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 (52) hide show
  1. package/BulkEdit/BulkEditButton.jsx +18 -7
  2. package/BulkEdit/BulkEditSelect.jsx +23 -7
  3. package/BulkEdit/useBulkCellEdit.js +230 -54
  4. package/BulkEdit/utils.js +87 -38
  5. package/Renderers/BooleanRenderer.jsx +53 -38
  6. package/Renderers/ButtonRenderer.jsx +61 -44
  7. package/Renderers/CheckboxRenderer.jsx +16 -8
  8. package/Renderers/CountrySelectRenderer.jsx +19 -12
  9. package/Renderers/IconRenderer.jsx +147 -117
  10. package/Renderers/ImageRenderer.jsx +31 -40
  11. package/Renderers/SelectRenderer.jsx +4 -2
  12. package/Renderers/StateRenderer.jsx +54 -52
  13. package/dist/BulkEdit/BulkEditButton.d.ts +1 -1
  14. package/dist/BulkEdit/BulkEditButton.js +19 -8
  15. package/dist/BulkEdit/BulkEditButton.js.map +1 -1
  16. package/dist/BulkEdit/BulkEditSelect.d.ts +2 -1
  17. package/dist/BulkEdit/BulkEditSelect.js +16 -6
  18. package/dist/BulkEdit/BulkEditSelect.js.map +1 -1
  19. package/dist/BulkEdit/useBulkCellEdit.js +195 -46
  20. package/dist/BulkEdit/useBulkCellEdit.js.map +1 -1
  21. package/dist/BulkEdit/utils.d.ts +1 -1
  22. package/dist/BulkEdit/utils.js +79 -33
  23. package/dist/BulkEdit/utils.js.map +1 -1
  24. package/dist/Renderers/BooleanRenderer.d.ts +4 -1
  25. package/dist/Renderers/BooleanRenderer.js +36 -31
  26. package/dist/Renderers/BooleanRenderer.js.map +1 -1
  27. package/dist/Renderers/ButtonRenderer.d.ts +3 -1
  28. package/dist/Renderers/ButtonRenderer.js +35 -25
  29. package/dist/Renderers/ButtonRenderer.js.map +1 -1
  30. package/dist/Renderers/CheckboxRenderer.d.ts +4 -1
  31. package/dist/Renderers/CheckboxRenderer.js +11 -8
  32. package/dist/Renderers/CheckboxRenderer.js.map +1 -1
  33. package/dist/Renderers/CountrySelectRenderer.d.ts +4 -1
  34. package/dist/Renderers/CountrySelectRenderer.js +15 -9
  35. package/dist/Renderers/CountrySelectRenderer.js.map +1 -1
  36. package/dist/Renderers/IconRenderer.d.ts +4 -1
  37. package/dist/Renderers/IconRenderer.js +114 -94
  38. package/dist/Renderers/IconRenderer.js.map +1 -1
  39. package/dist/Renderers/ImageRenderer.d.ts +4 -1
  40. package/dist/Renderers/ImageRenderer.js +24 -32
  41. package/dist/Renderers/ImageRenderer.js.map +1 -1
  42. package/dist/Renderers/SelectRenderer.d.ts +4 -1
  43. package/dist/Renderers/SelectRenderer.js +2 -1
  44. package/dist/Renderers/SelectRenderer.js.map +1 -1
  45. package/dist/Renderers/StateRenderer.d.ts +4 -1
  46. package/dist/Renderers/StateRenderer.js +38 -37
  47. package/dist/Renderers/StateRenderer.js.map +1 -1
  48. package/dist/index.js +6 -14
  49. package/dist/index.js.map +1 -1
  50. package/index.jsx +6 -15
  51. package/package.json +5 -5
  52. /package/dist/{preview-1761214842578.js → preview-1761923870469.js} +0 -0
@@ -1,10 +1,50 @@
1
1
  /* eslint-disable */
2
2
  import * as React from 'react';
3
3
  import { CircleHelp } from 'lucide-react';
4
+ import * as LucideIcons from 'lucide-react';
4
5
 
5
- export default function IconRenderer(props) {
6
- const { data, value, colDef: { iconRendererParams = {} } = {} } = props;
6
+ // Helper funkce pro získání hodnoty z nested path (např. 'accountingType.icon')
7
+ const getValueByPath = (obj, path) => {
8
+ if (!path || !obj) return undefined;
9
+ return path.split('.').reduce((acc, part) => acc?.[part], obj);
10
+ };
11
+
12
+ // Style constants
13
+ const ICON_WRAPPER_STYLE = {
14
+ display: 'inline-flex',
15
+ alignItems: 'center',
16
+ height: '100%',
17
+ flexShrink: 0,
18
+ };
19
+
20
+ const TEXT_WRAPPER_STYLE = {
21
+ flexShrink: 1,
22
+ minWidth: 0,
23
+ };
24
+
25
+ const BADGE_CONTAINER_BASE_STYLE = {
26
+ position: 'relative',
27
+ display: 'inline-flex',
28
+ alignItems: 'center',
29
+ justifyContent: 'center',
30
+ };
31
+
32
+ const BADGE_BASE_STYLE = {
33
+ position: 'absolute',
34
+ borderRadius: '50%',
35
+ minWidth: '16px',
36
+ height: '16px',
37
+ fontSize: '10px',
38
+ display: 'flex',
39
+ alignItems: 'center',
40
+ justifyContent: 'center',
41
+ fontWeight: 'bold',
42
+ lineHeight: 1,
43
+ zIndex: 1
44
+ };
7
45
 
46
+ function IconRenderer(props) {
47
+ const { data, value, colDef: { iconRendererParams = {} } = {} } = props;
8
48
 
9
49
  if (!iconRendererParams) return null;
10
50
 
@@ -13,40 +53,38 @@ export default function IconRenderer(props) {
13
53
  visibleGetter,
14
54
  showOnGroup,
15
55
  icon, // Komponenta nebo funkce pro ikonu
56
+ iconField, // Cesta k poli s názvem ikony (např. 'accountingType.icon')
16
57
  iconColor, // Barva ikony nebo funkce vracející barvu
17
58
  badge, // Číslo nebo funkce pro badge
18
59
  showZero = false, // Zda zobrazit badge když je hodnota 0
19
60
  size = 16,
20
- // Nové props
21
- iconLeft = false, // Zda zobrazit ikonu vlevo
22
- iconRight = false, // Zda zobrazit ikonu vpravo
23
- showText = true, // Zda zobrazit text (default true pro zpětnou kompatibilitu)
24
- textGap = 5, // Mezera mezi ikonou a textem
25
- // Badge styling props
26
- badgeColor = '#dc3545', // Barva pozadí badge
27
- badgeTextColor = 'white', // Barva textu badge
28
- badgePosition = 'top-right', // Pozice badge
61
+ iconLeft = false,
62
+ iconRight = false,
63
+ showText = true,
64
+ textGap = 5,
65
+ badgeColor = '#dc3545',
66
+ badgeTextColor = 'white',
67
+ badgePosition = 'top-right',
29
68
  } = iconRendererParams;
30
69
 
31
- const visibleResult = visibleGetter ? visibleGetter(data) : true;
70
+ const visibleResult = React.useMemo(() =>
71
+ visibleGetter ? visibleGetter(data) : true,
72
+ [visibleGetter, data]
73
+ );
32
74
 
33
- const getIconColor = () => {
75
+ const getIconColor = React.useCallback(() => {
34
76
  if (!iconColor) return undefined;
35
-
36
- // Pokud je iconColor funkce, zavolej ji s daty
77
+
37
78
  if (typeof iconColor === 'function') {
38
79
  return iconColor({ data, value, props });
39
80
  }
40
-
41
- // Pokud je iconColor string/hodnota
81
+
42
82
  return iconColor;
43
- };
83
+ }, [iconColor, data, value, props]);
44
84
 
45
- const renderIcon = (IconComponent, iconProps = {}) => {
85
+ const renderIcon = React.useCallback((IconComponent, iconProps = {}) => {
46
86
  const computedIconColor = getIconColor();
47
-
48
-
49
- // Vytvoř finální style objekt s !important pro override
87
+
50
88
  const finalStyle = {
51
89
  fontSize: size,
52
90
  ...(iconProps.style || {}),
@@ -56,25 +94,21 @@ export default function IconRenderer(props) {
56
94
  const finalIconProps = {
57
95
  size,
58
96
  style: finalStyle,
59
- ...(computedIconColor && { color: computedIconColor }), // Pro Lucide ikony
97
+ ...(computedIconColor && { color: computedIconColor }),
60
98
  ...iconProps
61
99
  };
62
100
 
63
101
  let iconElement;
64
-
65
- // Pokud je IconComponent funkce, zavoláme ji s daty
102
+
66
103
  if (typeof IconComponent === 'function') {
67
104
  iconElement = IconComponent({ data, value, ...finalIconProps });
68
105
  }
69
- // Pokud je IconComponent React komponenta
70
106
  else if (React.isValidElement(IconComponent)) {
71
107
  iconElement = React.cloneElement(IconComponent, finalIconProps);
72
108
  }
73
- // Pokud je IconComponent konstruktor komponenty
74
109
  else if (IconComponent && typeof IconComponent === 'object' && IconComponent.$$typeof) {
75
110
  iconElement = <IconComponent {...finalIconProps} />;
76
111
  }
77
- // Pokud je IconComponent string (pro emoji nebo text)
78
112
  else if (typeof IconComponent === 'string') {
79
113
  iconElement = <span style={finalStyle}>{IconComponent}</span>;
80
114
  }
@@ -82,123 +116,118 @@ export default function IconRenderer(props) {
82
116
  return null;
83
117
  }
84
118
 
85
- // Pokud máme barvu, wrap ikonu ve vlastním spanu pro lepší kontrolu barvy
86
119
  if (computedIconColor) {
87
120
  return (
88
- <span style={{ color: computedIconColor, display: 'inline-flex', alignItems: 'center' }}>
121
+ <span style={{
122
+ color: computedIconColor,
123
+ display: 'inline-flex',
124
+ alignItems: 'center',
125
+ height: '100%'
126
+ }}>
89
127
  {iconElement}
90
128
  </span>
91
129
  );
92
130
  }
93
131
 
94
132
  return iconElement;
95
- };
133
+ }, [size, getIconColor, data, value]);
96
134
 
97
- const getBadgeValue = () => {
135
+ const badgeValue = React.useMemo(() => {
98
136
  if (!badge) return null;
99
-
100
- // Pokud je badge funkce, zavolej ji s daty
137
+
101
138
  if (typeof badge === 'function') {
102
139
  return badge({ data, value });
103
140
  }
104
-
105
- // Pokud je badge číslo nebo string
141
+
106
142
  return badge;
107
- };
143
+ }, [badge, data, value]);
144
+
145
+ const badgePositionStyle = React.useMemo(() => {
146
+ const positions = {
147
+ 'top-right': { top: '2px', right: '-2px' },
148
+ 'top-left': { top: '2px', left: '-2px' },
149
+ 'bottom-right': { bottom: '2px', right: '-2px' },
150
+ 'bottom-left': { bottom: '2px', left: '-2px' }
151
+ };
152
+ return positions[badgePosition] || positions['top-right'];
153
+ }, [badgePosition]);
154
+
155
+ const badgeStyle = React.useMemo(() => ({
156
+ ...BADGE_BASE_STYLE,
157
+ ...badgePositionStyle,
158
+ backgroundColor: badgeColor,
159
+ color: badgeTextColor,
160
+ border: `1px solid ${badgeTextColor}`,
161
+ }), [badgePositionStyle, badgeColor, badgeTextColor]);
108
162
 
109
- const Icon = ({ ...restProps }) => {
110
- const badgeValue = getBadgeValue();
163
+ const Icon = React.useMemo(() => {
111
164
  const iconElement = (() => {
112
- // Pokud je definována icon funkce/komponenta, použij ji
165
+ // Priorita 1: Pokud je definován iconField, získej název ikony z dat a načti z Lucide
166
+ if (iconField) {
167
+ const iconName = getValueByPath(data, iconField);
168
+ console.log('🎨 IconRenderer - iconField:', {
169
+ iconField,
170
+ iconName,
171
+ data,
172
+ hasLucideIcon: iconName ? !!LucideIcons[iconName] : false
173
+ });
174
+ if (iconName) {
175
+ const LucideIcon = LucideIcons[iconName];
176
+ if (LucideIcon) {
177
+ return <LucideIcon size={size} />;
178
+ }
179
+ }
180
+ // Pokud ikona z iconField neexistuje, vrať null (nic nezobrazit)
181
+ return null;
182
+ }
183
+
184
+ // Priorita 2: Použij icon prop (funkce nebo komponenta)
113
185
  if (icon) {
114
- return renderIcon(icon, { ...restProps });
186
+ return renderIcon(icon, {});
115
187
  }
116
188
 
117
- // Fallback na CircleHelp
118
- return <CircleHelp size={size} {...restProps} />;
189
+ // Priorita 3: Default - nic nezobrazit pokud není ani iconField ani icon
190
+ return null;
119
191
  })();
120
192
 
121
- // Pokud není badge, vrať jen ikonu
122
193
  if (!badgeValue && (badgeValue !== 0 || !showZero)) {
123
194
  return iconElement;
124
195
  }
125
196
 
126
- // Vrať ikonu s badge
127
197
  return (
128
- <div
129
- style={{
130
- position: 'relative',
131
- display: 'inline-flex',
132
- alignItems: 'center',
133
- justifyContent: 'center',
134
- height: '100%'
135
- }}
136
- >
198
+ <div style={BADGE_CONTAINER_BASE_STYLE}>
137
199
  {iconElement}
138
- <span
139
- style={{
140
- position: 'absolute',
141
- ...(badgePosition === 'top-right' && { top: '2px', right: '-2px' }),
142
- ...(badgePosition === 'top-left' && { top: '2px', left: '-2px' }),
143
- ...(badgePosition === 'bottom-right' && { bottom: '2px', right: '-2px' }),
144
- ...(badgePosition === 'bottom-left' && { bottom: '2px', left: '-2px' }),
145
- backgroundColor: badgeColor,
146
- color: badgeTextColor,
147
- borderRadius: '50%',
148
- minWidth: '16px',
149
- height: '16px',
150
- fontSize: '10px',
151
- display: 'flex',
152
- alignItems: 'center',
153
- justifyContent: 'center',
154
- fontWeight: 'bold',
155
- border: `1px solid ${badgeTextColor}`,
156
- lineHeight: 1,
157
- zIndex: 1
158
- }}
159
- >
200
+ <span style={badgeStyle}>
160
201
  {badgeValue > 99 ? '99+' : badgeValue}
161
202
  </span>
162
203
  </div>
163
204
  );
164
- };
205
+ }, [icon, iconField, renderIcon, badgeValue, showZero, badgeStyle, size, data]);
165
206
 
166
- const showCondition = () => {
207
+ const showCondition = React.useMemo(() => {
167
208
  const newItem = (data && data._rh_plus_ag_grid_new_item) || false;
168
209
  return !newItem && (showOnGroup || !!data) && visibleResult;
169
- };
210
+ }, [data, showOnGroup, visibleResult]);
170
211
 
171
- if (!showCondition()) return null;
212
+ if (!showCondition) return null;
172
213
 
173
- // Určíme, jestli máme zobrazit ikonu a text
174
- const hasIcon = iconLeft || iconRight || (!iconLeft && !iconRight); // Pokud není specifikováno, zobrazí se ikona (zpětná kompatibilita)
214
+ const hasIcon = iconLeft || iconRight || (!iconLeft && !iconRight);
175
215
  const hasText = showText && value != null && value !== '';
176
216
 
177
- // Pokud nemáme ani ikonu ani text, nevrací nic
178
217
  if (!hasIcon && !hasText) return null;
179
218
 
180
- // Určíme pořadí elementů
181
- const renderContent = () => {
219
+ const content = React.useMemo(() => {
182
220
  const iconElement = hasIcon ? (
183
- <Icon
184
- style={{
185
- display: 'inline-block',
186
- flexShrink: 0,
187
- }}
188
- />
221
+ <div style={ICON_WRAPPER_STYLE}>{Icon}</div>
189
222
  ) : null;
190
223
 
191
224
  const textElement = hasText ? (
192
- <span style={{ flexShrink: 1, minWidth: 0 }}>
193
- {value}
194
- </span>
225
+ <span style={TEXT_WRAPPER_STYLE}>{value}</span>
195
226
  ) : null;
196
227
 
197
- // Pokud máme jen ikonu nebo jen text
198
228
  if (!hasIcon) return textElement;
199
229
  if (!hasText) return iconElement;
200
230
 
201
- // Pokud máme obojí, určíme pořadí
202
231
  if (iconRight) {
203
232
  return (
204
233
  <>
@@ -206,29 +235,30 @@ export default function IconRenderer(props) {
206
235
  {iconElement}
207
236
  </>
208
237
  );
209
- } else {
210
- // iconLeft nebo default (vlevo)
211
- return (
212
- <>
213
- {iconElement}
214
- {textElement}
215
- </>
216
- );
217
238
  }
218
- };
239
+
240
+ return (
241
+ <>
242
+ {iconElement}
243
+ {textElement}
244
+ </>
245
+ );
246
+ }, [hasIcon, hasText, Icon, value, iconRight]);
247
+
248
+ const containerStyle = React.useMemo(() => ({
249
+ width: '100%',
250
+ display: 'flex',
251
+ justifyContent: cellAlign ?? (hasText ? 'flex-start' : 'center'),
252
+ alignItems: 'center',
253
+ height: '100%',
254
+ gap: hasIcon && hasText ? `${textGap}px` : '0',
255
+ }), [cellAlign, hasText, hasIcon, textGap]);
219
256
 
220
257
  return (
221
- <span
222
- style={{
223
- width: '100%',
224
- display: 'flex',
225
- justifyContent: cellAlign ?? (hasText ? 'flex-start' : 'center'), // Pokud má text, defaultně vlevo
226
- alignItems: 'center',
227
- height: '100%',
228
- gap: hasIcon && hasText ? `${textGap}px` : '0',
229
- }}
230
- >
231
- {renderContent()}
258
+ <span style={containerStyle}>
259
+ {content}
232
260
  </span>
233
261
  );
234
- }
262
+ }
263
+
264
+ export default React.memo(IconRenderer);
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable */
2
2
  import * as React from 'react';
3
3
 
4
- export default function ImageRenderer(props) {
4
+ function ImageRenderer(props) {
5
5
  const { data, value, colDef: { imageRendererParams = {} } = {} } = props;
6
6
 
7
7
  if (!imageRendererParams) return null;
@@ -19,17 +19,20 @@ export default function ImageRenderer(props) {
19
19
 
20
20
  const [hasError, setHasError] = React.useState(false);
21
21
 
22
- const visibleResult = visibleGetter ? visibleGetter(data) : true;
22
+ const visibleResult = React.useMemo(() =>
23
+ visibleGetter ? visibleGetter(data) : true,
24
+ [visibleGetter, data]
25
+ );
23
26
 
24
- const getImageUrl = () => {
27
+ const computedImageUrl = React.useMemo(() => {
25
28
  if (!imageUrl) return null;
26
-
29
+
27
30
  if (typeof imageUrl === 'function') {
28
31
  return imageUrl({ data, value, props });
29
32
  }
30
-
33
+
31
34
  return imageUrl;
32
- };
35
+ }, [imageUrl, data, value, props]);
33
36
 
34
37
  const handleImageError = React.useCallback(() => {
35
38
  setHasError(true);
@@ -37,29 +40,34 @@ export default function ImageRenderer(props) {
37
40
 
38
41
  React.useEffect(() => {
39
42
  setHasError(false);
40
- }, [getImageUrl()]);
43
+ }, [computedImageUrl]);
41
44
 
42
- const showCondition = () => {
45
+ const showCondition = React.useMemo(() => {
43
46
  const newItem = (data && data._rh_plus_ag_grid_new_item) || false;
44
47
  return !newItem && (showOnGroup || !!data) && visibleResult;
45
- };
48
+ }, [data, showOnGroup, visibleResult]);
49
+
50
+ const containerStyle = React.useMemo(() => ({
51
+ width: '100%',
52
+ display: 'flex',
53
+ justifyContent: cellAlign || 'center',
54
+ alignItems: 'center',
55
+ height: '100%',
56
+ }), [cellAlign]);
46
57
 
47
- if (!showCondition()) return null;
58
+ const finalImageStyle = React.useMemo(() => ({
59
+ width: imageSize,
60
+ height: imageSize,
61
+ objectFit: 'contain',
62
+ ...(typeof imageStyle === 'function' ? imageStyle({ data, value, props }) : imageStyle || {}),
63
+ }), [imageSize, imageStyle, data, value, props]);
48
64
 
49
- const computedImageUrl = getImageUrl();
65
+ if (!showCondition) return null;
50
66
 
51
67
  if (hasError || !computedImageUrl) {
52
68
  if (fallbackText && value) {
53
69
  return (
54
- <span
55
- style={{
56
- width: '100%',
57
- display: 'flex',
58
- justifyContent: cellAlign || 'center',
59
- alignItems: 'center',
60
- height: '100%',
61
- }}
62
- >
70
+ <span style={containerStyle}>
63
71
  {value}
64
72
  </span>
65
73
  );
@@ -67,27 +75,8 @@ export default function ImageRenderer(props) {
67
75
  return null;
68
76
  }
69
77
 
70
- const defaultImageStyle = {
71
- width: imageSize,
72
- height: imageSize,
73
- objectFit: 'contain',
74
- };
75
-
76
- const finalImageStyle = {
77
- ...defaultImageStyle,
78
- ...(typeof imageStyle === 'function' ? imageStyle({ data, value, props }) : imageStyle || {}),
79
- };
80
-
81
78
  return (
82
- <span
83
- style={{
84
- width: '100%',
85
- display: 'flex',
86
- justifyContent: cellAlign || 'center',
87
- alignItems: 'center',
88
- height: '100%',
89
- }}
90
- >
79
+ <span style={containerStyle}>
91
80
  <img
92
81
  src={computedImageUrl}
93
82
  alt={alt || value || 'Image'}
@@ -98,3 +87,5 @@ export default function ImageRenderer(props) {
98
87
  </span>
99
88
  );
100
89
  }
90
+
91
+ export default React.memo(ImageRenderer);
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
 
3
- export default function SelectRenderer(params) {
3
+ function SelectRenderer(params) {
4
4
  const {value, value: {name} = {}} = params;
5
5
 
6
6
  if (!value)
@@ -12,4 +12,6 @@ export default function SelectRenderer(params) {
12
12
  // imageUrl = `https://rhplus.blob.core.windows.net/countries/${params.value.toUpperCase()}.png`;
13
13
 
14
14
  return <div>{name}</div>;
15
- }
15
+ }
16
+
17
+ export default React.memo(SelectRenderer);
@@ -1,12 +1,13 @@
1
1
  /* eslint-disable */
2
2
  import * as React from 'react';
3
3
 
4
+ // Helper function moved outside component
4
5
  function getValueByPath(obj, path) {
5
6
  if (!obj || !path) return null;
6
7
  return path.split('.').reduce((o, k) => (o && o[k] !== undefined) ? o[k] : null, obj);
7
8
  }
8
9
 
9
- export default function StateRenderer(props) {
10
+ function StateRenderer(props) {
10
11
  const { data, value, colDef: { stateRendererParams = {} } = {} } = props;
11
12
 
12
13
 
@@ -31,106 +32,107 @@ export default function StateRenderer(props) {
31
32
  const finalColor = color || textColor || 'white';
32
33
  const finalColorField = colorField || textColorField;
33
34
 
34
- const visibleResult = visibleGetter ? visibleGetter(data) : true;
35
+ const visibleResult = React.useMemo(() =>
36
+ visibleGetter ? visibleGetter(data) : true,
37
+ [visibleGetter, data]
38
+ );
35
39
 
36
- const getBgColor = () => {
40
+ const computedBgColor = React.useMemo(() => {
37
41
  // Priorita: bgColorField (hodnota z dat) -> bgColor (funkce nebo string)
38
42
  if (bgColorField && data) {
39
43
  const fieldValue = getValueByPath(data, bgColorField);
40
44
  if (fieldValue) return fieldValue;
41
45
  }
42
-
46
+
43
47
  if (!bgColor) return '#666'; // default barva
44
-
48
+
45
49
  // Pokud je bgColor funkce, zavolej ji s daty
46
50
  if (typeof bgColor === 'function') {
47
51
  return bgColor({ data, value, props });
48
52
  }
49
-
53
+
50
54
  // Pokud je bgColor string/hodnota
51
55
  return bgColor;
52
- };
56
+ }, [bgColor, bgColorField, data, value, props]);
53
57
 
54
- const getTextColor = () => {
58
+ const computedTextColor = React.useMemo(() => {
55
59
  // Priorita: colorField/textColorField (hodnota z dat) -> color/textColor (funkce nebo string)
56
60
  if (finalColorField && data) {
57
61
  const fieldValue = getValueByPath(data, finalColorField);
58
62
  if (fieldValue) return fieldValue;
59
63
  }
60
-
64
+
61
65
  if (!finalColor) return 'white'; // default barva
62
-
66
+
63
67
  // Pokud je finalColor funkce, zavolej ji s daty
64
68
  if (typeof finalColor === 'function') {
65
69
  return finalColor({ data, value, props });
66
70
  }
67
-
71
+
68
72
  // Pokud je finalColor string/hodnota
69
73
  return finalColor;
70
- };
74
+ }, [finalColor, finalColorField, data, value, props]);
71
75
 
72
- const getDisplayText = () => {
76
+ const displayText = React.useMemo(() => {
73
77
  if (displayField) {
74
78
  // Pokud je displayField funkce
75
79
  if (typeof displayField === 'function') {
76
80
  return displayField({ data, value, props });
77
81
  }
78
-
82
+
79
83
  // Pokud je displayField string (název pole)
80
84
  if (typeof displayField === 'string') {
81
85
  return data?.[displayField] || value;
82
86
  }
83
87
  }
84
-
88
+
85
89
  // Fallback na value
86
90
  return value || '';
87
- };
91
+ }, [displayField, data, value, props]);
88
92
 
89
- const showCondition = () => {
93
+ const showCondition = React.useMemo(() => {
90
94
  const newItem = (data && data._rh_plus_ag_grid_new_item) || false;
91
95
  return !newItem && (showOnGroup || !!data) && visibleResult;
92
- };
96
+ }, [data, showOnGroup, visibleResult]);
93
97
 
94
- if (!showCondition()) return null;
95
-
96
- const computedBgColor = getBgColor();
97
- const computedTextColor = getTextColor();
98
- const displayText = getDisplayText();
98
+ if (!showCondition) return null;
99
99
 
100
100
  // Pokud nemáme text k zobrazení, nevrací nic
101
101
  if (!displayText) return null;
102
102
 
103
+ const containerStyle = React.useMemo(() => ({
104
+ width: '100%',
105
+ display: 'flex',
106
+ justifyContent: cellAlign === 'center' ? 'center' : cellAlign === 'right' ? 'flex-end' : 'flex-start',
107
+ alignItems: 'center',
108
+ height: '100%',
109
+ }), [cellAlign]);
110
+
111
+ const badgeStyle = React.useMemo(() => ({
112
+ backgroundColor: computedBgColor,
113
+ color: computedTextColor,
114
+ borderRadius: '20px',
115
+ padding: '2px 8px',
116
+ minWidth: `${minWidth}px`,
117
+ fontSize: `${fontSize}px`,
118
+ fontWeight: '500',
119
+ textAlign: 'center',
120
+ display: 'inline-block',
121
+ whiteSpace: 'nowrap',
122
+ overflow: 'hidden',
123
+ textOverflow: 'ellipsis',
124
+ boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
125
+ lineHeight: '1.2',
126
+ height: 'auto',
127
+ }), [computedBgColor, computedTextColor, minWidth, fontSize]);
128
+
103
129
  return (
104
- <div
105
- style={{
106
- width: '100%',
107
- display: 'flex',
108
- justifyContent: cellAlign === 'center' ? 'center' : cellAlign === 'right' ? 'flex-end' : 'flex-start',
109
- alignItems: 'center',
110
- height: '100%',
111
- }}
112
- >
113
- <span
114
- style={{
115
- backgroundColor: computedBgColor,
116
- color: computedTextColor,
117
- borderRadius: '20px',
118
- padding: '2px 8px',
119
- minWidth: `${minWidth}px`,
120
- fontSize: `${fontSize}px`,
121
- fontWeight: '500',
122
- textAlign: 'center',
123
- display: 'inline-block',
124
- whiteSpace: 'nowrap',
125
- overflow: 'hidden',
126
- textOverflow: 'ellipsis',
127
- boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
128
- lineHeight: '1.2',
129
- height: 'auto',
130
- }}
131
- >
130
+ <div style={containerStyle}>
131
+ <span style={badgeStyle}>
132
132
  {displayText}
133
133
  </span>
134
134
  </div>
135
135
  );
136
- }
136
+ }
137
+
138
+ export default React.memo(StateRenderer);
@@ -13,7 +13,7 @@ export default BulkEditButton;
13
13
  * @param {Function} props.onSubmit - Handler pro submit
14
14
  * @param {Function} props.onCancel - Handler pro cancel
15
15
  */
16
- declare function BulkEditButton({ visible, position, range, column, cellCount, editPopover, onOpenPopover, onValueChange, onSubmit, onCancel, }: {
16
+ declare function BulkEditButton({ visible, position, range, column, cellCount, rowsContainer, editPopover, onOpenPopover, onValueChange, onSubmit, onCancel, }: {
17
17
  visible: boolean;
18
18
  position: Object;
19
19
  range: Object;