@topconsultnpm/sdkui-react 6.20.0-dev1.2 → 6.20.0-dev1.21

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 (49) hide show
  1. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +3 -3
  2. package/lib/components/NewComponents/ContextMenu/hooks.d.ts +1 -0
  3. package/lib/components/NewComponents/ContextMenu/hooks.js +8 -4
  4. package/lib/components/NewComponents/ContextMenu/styles.d.ts +4 -1
  5. package/lib/components/NewComponents/ContextMenu/styles.js +41 -8
  6. package/lib/components/NewComponents/ContextMenu/types.d.ts +1 -0
  7. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +38 -30
  8. package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +8 -0
  9. package/lib/components/NewComponents/FloatingMenuBar/styles.js +30 -19
  10. package/lib/components/base/TMAccordion.js +2 -2
  11. package/lib/components/base/TMCustomButton.js +0 -1
  12. package/lib/components/base/TMDataGrid.d.ts +2 -2
  13. package/lib/components/base/TMDataGrid.js +16 -5
  14. package/lib/components/editors/TMHtmlEditor.js +1 -1
  15. package/lib/components/editors/TMMetadataValues.js +20 -2
  16. package/lib/components/features/documents/TMDcmtBlog.d.ts +1 -7
  17. package/lib/components/features/documents/TMDcmtBlog.js +29 -2
  18. package/lib/components/features/documents/TMDcmtForm.js +270 -173
  19. package/lib/components/features/documents/TMDcmtPreview.js +100 -33
  20. package/lib/components/features/search/TMDcmtCheckoutInfoForm.d.ts +8 -0
  21. package/lib/components/features/search/{TMSearchResultCheckoutInfoForm.js → TMDcmtCheckoutInfoForm.js} +6 -11
  22. package/lib/components/features/search/TMSearchQueryPanel.js +13 -12
  23. package/lib/components/features/search/TMSearchResult.js +76 -114
  24. package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +1 -1
  25. package/lib/components/features/search/TMSearchResultsMenuItems.js +16 -17
  26. package/lib/components/features/search/TMViewHistoryDcmt.js +1 -1
  27. package/lib/components/forms/Login/TMLoginForm.js +2 -0
  28. package/lib/css/tm-sdkui.css +1 -1
  29. package/lib/helper/SDKUI_Globals.d.ts +13 -14
  30. package/lib/helper/SDKUI_Globals.js +9 -0
  31. package/lib/helper/SDKUI_Localizator.d.ts +8 -0
  32. package/lib/helper/SDKUI_Localizator.js +98 -0
  33. package/lib/helper/TMUtils.d.ts +3 -1
  34. package/lib/helper/TMUtils.js +51 -0
  35. package/lib/helper/checkinCheckoutManager.d.ts +85 -0
  36. package/lib/helper/checkinCheckoutManager.js +348 -0
  37. package/lib/helper/devextremeCustomMessages.d.ts +30 -0
  38. package/lib/helper/devextremeCustomMessages.js +30 -0
  39. package/lib/helper/helpers.js +7 -1
  40. package/lib/helper/index.d.ts +1 -0
  41. package/lib/helper/index.js +1 -0
  42. package/lib/helper/queryHelper.js +29 -0
  43. package/lib/hooks/useCheckInOutOperations.d.ts +28 -0
  44. package/lib/hooks/useCheckInOutOperations.js +223 -0
  45. package/lib/services/platform_services.d.ts +1 -1
  46. package/package.json +12 -10
  47. package/lib/components/features/search/TMSearchResultCheckoutInfoForm.d.ts +0 -8
  48. package/lib/helper/cicoHelper.d.ts +0 -31
  49. package/lib/helper/cicoHelper.js +0 -155
@@ -14,7 +14,7 @@ const TMContextMenu = ({ items, trigger = 'right', children }) => {
14
14
  const menuRef = useRef(null);
15
15
  const triggerRef = useRef(null);
16
16
  const submenuTimeoutRef = useRef(null);
17
- const { openLeft, openUp } = useMenuPosition(menuRef, menuState.position);
17
+ const { openLeft, openUp, isCalculated } = useMenuPosition(menuRef, menuState.position);
18
18
  const handleClose = () => {
19
19
  setMenuState(prev => ({
20
20
  ...prev,
@@ -173,7 +173,7 @@ const TMContextMenu = ({ items, trigger = 'right', children }) => {
173
173
  // if (item.disabled) return;
174
174
  item.onRightIconClick?.();
175
175
  };
176
- return (_jsxs(S.MenuItem, { "$disabled": item.disabled, "$hasSubmenu": !!item.submenu && item.submenu.length > 0, "$beginGroup": item.beginGroup, onMouseDown: handleClick, onMouseEnter: (e) => !isMobile && handleMouseEnter(item, e, depth + 1), onMouseLeave: () => !isMobile && handleMouseLeave(depth + 1), children: [_jsxs(S.MenuItemContent, { children: [item.icon && _jsx(S.IconWrapper, { children: item.icon }), _jsx(S.MenuItemName, { children: item.name })] }), item.rightIcon && item.onRightIconClick && (_jsx(S.RightIconButton, { onClick: handleRightIconClick, onMouseDown: (e) => e.stopPropagation(), "aria-label": `Action for ${item.name}`, children: item.rightIcon })), item.submenu && item.submenu.length > 0 && (_jsx(S.SubmenuIndicator, { "$isMobile": isMobile, children: isMobile ? '›' : '▸' }))] }, itemKey));
176
+ return (_jsxs(S.MenuItem, { "$disabled": item.disabled, "$hasSubmenu": !!item.submenu && item.submenu.length > 0, "$beginGroup": item.beginGroup, onMouseDown: handleClick, onMouseEnter: (e) => !isMobile && handleMouseEnter(item, e, depth + 1), onMouseLeave: () => !isMobile && handleMouseLeave(depth + 1), title: item.tooltip, children: [_jsxs(S.MenuItemContent, { children: [item.icon && _jsx(S.IconWrapper, { children: item.icon }), _jsx(S.MenuItemName, { children: item.name })] }), item.rightIcon && item.onRightIconClick && (_jsx(S.RightIconButton, { onClick: handleRightIconClick, onMouseDown: (e) => e.stopPropagation(), "aria-label": `Action for ${item.name}`, children: item.rightIcon })), item.submenu && item.submenu.length > 0 && (_jsx(S.SubmenuIndicator, { "$isMobile": isMobile, children: isMobile ? '›' : '▸' }))] }, itemKey));
177
177
  });
178
178
  };
179
179
  const currentMenu = menuState.submenuStack.at(-1) || items;
@@ -182,6 +182,6 @@ const TMContextMenu = ({ items, trigger = 'right', children }) => {
182
182
  if (e.key === 'Enter' || e.key === ' ') {
183
183
  handleClick(e);
184
184
  }
185
- }, role: "button", tabIndex: 0, style: { display: 'inline-block' }, children: children }), menuState.visible && (_jsxs(_Fragment, { children: [_jsx(S.Overlay, { onClick: handleClose }), _jsxs(S.MenuContainer, { ref: menuRef, "$x": menuState.position.x, "$y": menuState.position.y, "$openLeft": openLeft, "$openUp": openUp, children: [isMobile && menuState.parentNames.length > 0 && (_jsxs(S.MobileMenuHeader, { children: [_jsx(S.BackButton, { onClick: handleBack, "aria-label": "Go back", children: "\u2190" }), _jsx(S.HeaderTitle, { children: currentParentName })] })), renderMenuItems(currentMenu, 0)] }), !isMobile && hoveredSubmenus.map((submenu, idx) => (_jsx(S.Submenu, { "$parentRect": submenu.parentRect, "$openUp": submenu.openUp, "data-submenu": "true", onMouseEnter: handleSubmenuMouseEnter, onMouseLeave: () => handleMouseLeave(submenu.depth), children: renderMenuItems(submenu.items, submenu.depth) }, `submenu-${submenu.depth}-${idx}`)))] }))] }));
185
+ }, role: "button", tabIndex: 0, style: { display: 'inline-block' }, children: children }), menuState.visible && (_jsxs(_Fragment, { children: [_jsx(S.Overlay, { onClick: handleClose }), _jsxs(S.MenuContainer, { ref: menuRef, "$x": menuState.position.x, "$y": menuState.position.y, "$openLeft": openLeft, "$openUp": openUp, "$isPositioned": isCalculated, children: [isMobile && menuState.parentNames.length > 0 && (_jsxs(S.MobileMenuHeader, { children: [_jsx(S.BackButton, { onClick: handleBack, "aria-label": "Go back", children: "\u2190" }), _jsx(S.HeaderTitle, { children: currentParentName })] })), renderMenuItems(currentMenu, 0)] }), !isMobile && hoveredSubmenus.map((submenu, idx) => (_jsx(S.Submenu, { "$parentRect": submenu.parentRect, "$openUp": submenu.openUp, "data-submenu": "true", onMouseEnter: handleSubmenuMouseEnter, onMouseLeave: () => handleMouseLeave(submenu.depth), children: renderMenuItems(submenu.items, submenu.depth) }, `submenu-${submenu.depth}-${idx}`)))] }))] }));
186
186
  };
187
187
  export default TMContextMenu;
@@ -5,6 +5,7 @@ interface Position {
5
5
  y: number;
6
6
  }
7
7
  export declare const useMenuPosition: (menuRef: React.RefObject<HTMLDivElement | null>, position: Position) => {
8
+ isCalculated: boolean;
8
9
  openLeft: boolean;
9
10
  openUp: boolean;
10
11
  };
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, useRef } from 'react';
1
+ import { useState, useEffect, useLayoutEffect, useRef } from 'react';
2
2
  export const useIsMobile = () => {
3
3
  const [isMobile, setIsMobile] = useState(false);
4
4
  useEffect(() => {
@@ -31,9 +31,12 @@ export const useClickOutside = (callback) => {
31
31
  };
32
32
  export const useMenuPosition = (menuRef, position) => {
33
33
  const [adjustedPosition, setAdjustedPosition] = useState({ openLeft: false, openUp: false });
34
- useEffect(() => {
35
- if (!menuRef.current)
34
+ const [isCalculated, setIsCalculated] = useState(false);
35
+ useLayoutEffect(() => {
36
+ if (!menuRef.current) {
37
+ setIsCalculated(false);
36
38
  return;
39
+ }
37
40
  const menuRect = menuRef.current.getBoundingClientRect();
38
41
  const viewportWidth = window.innerWidth;
39
42
  const viewportHeight = window.innerHeight;
@@ -43,6 +46,7 @@ export const useMenuPosition = (menuRef, position) => {
43
46
  openLeft: spaceRight < menuRect.width + 20,
44
47
  openUp: spaceBottom < menuRect.height + 20,
45
48
  });
49
+ setIsCalculated(true);
46
50
  }, [position, menuRef]);
47
- return adjustedPosition;
51
+ return { ...adjustedPosition, isCalculated };
48
52
  };
@@ -3,6 +3,7 @@ export declare const MenuContainer: import("styled-components/dist/types").IStyl
3
3
  $y: number;
4
4
  $openLeft: boolean;
5
5
  $openUp: boolean;
6
+ $isPositioned: boolean;
6
7
  }>> & string;
7
8
  export declare const MenuItem: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
8
9
  $disabled?: boolean;
@@ -12,7 +13,9 @@ export declare const MenuItem: import("styled-components/dist/types").IStyledCom
12
13
  export declare const MenuItemContent: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
13
14
  export declare const IconWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>> & string;
14
15
  export declare const MenuItemName: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>> & string;
15
- export declare const RightIconButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
16
+ export declare const RightIconButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
17
+ ref?: ((instance: HTMLButtonElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLButtonElement> | null | undefined;
18
+ }>, never>, never>> & string;
16
19
  export declare const SubmenuIndicator: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, {
17
20
  $isMobile?: boolean;
18
21
  }>> & string;
@@ -36,6 +36,13 @@ export const MenuContainer = styled.div `
36
36
  animation: ${fadeIn} 0.15s ease-out;
37
37
  backdrop-filter: blur(10px);
38
38
  border: 1px solid rgba(0, 0, 0, 0.06);
39
+ opacity: ${props => props.$isPositioned ? 1 : 0};
40
+ transition: opacity 0.05s ease-in;
41
+
42
+ /* Reset color inheritance from parent with !important to override panel header styles */
43
+ & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *) {
44
+ color: #1a1a1a !important;
45
+ }
39
46
 
40
47
  [data-theme='dark'] & {
41
48
  background: #2a2a2a;
@@ -43,6 +50,10 @@ export const MenuContainer = styled.div `
43
50
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4),
44
51
  0 2px 8px rgba(0, 0, 0, 0.3);
45
52
  }
53
+
54
+ [data-theme='dark'] & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *) {
55
+ color: #e0e0e0 !important;
56
+ }
46
57
  `;
47
58
  export const MenuItem = styled.div `
48
59
  display: flex;
@@ -50,7 +61,6 @@ export const MenuItem = styled.div `
50
61
  justify-content: space-between;
51
62
  padding: 4px 12px;
52
63
  cursor: ${props => props.$disabled ? 'not-allowed' : 'pointer'};
53
- opacity: ${props => props.$disabled ? 0.4 : 1};
54
64
  transition: all 0.15s ease;
55
65
  position: relative;
56
66
  user-select: none;
@@ -63,12 +73,26 @@ export const MenuItem = styled.div `
63
73
  padding-top: 8px;
64
74
  `}
65
75
 
76
+ /* Apply opacity only to direct children except right-icon-btn */
77
+ & > *:not(.right-icon-btn) {
78
+ opacity: ${props => props.$disabled ? 0.4 : 1};
79
+ }
80
+
81
+ /* Right icon button hidden by default, shown on hover */
82
+ & .right-icon-btn {
83
+ cursor: pointer !important;
84
+ }
85
+
66
86
  &:hover {
67
87
  ${props => !props.$disabled && `
68
88
  background: linear-gradient(90deg, #f0f7ff 0%, #e6f2ff 100%);
69
89
  color: #0066cc;
70
- padding-left: 14px;
71
90
  `}
91
+
92
+ /* Show right icon on hover */
93
+ & .right-icon-btn {
94
+ opacity: 1 !important;
95
+ }
72
96
  }
73
97
 
74
98
  &:active {
@@ -124,23 +148,23 @@ export const MenuItemName = styled.span `
124
148
  overflow-wrap: break-word;
125
149
  line-height: 1.4;
126
150
  `;
127
- export const RightIconButton = styled.button `
151
+ export const RightIconButton = styled.button.attrs({
152
+ className: 'right-icon-btn'
153
+ }) `
128
154
  display: flex;
129
155
  align-items: center;
130
156
  justify-content: center;
131
157
  background: transparent;
132
158
  border: none;
133
- cursor: pointer;
159
+ cursor: pointer !important;
134
160
  padding: 4px 8px;
135
161
  margin-left: 8px;
136
162
  border-radius: 6px;
137
- color: inherit;
138
163
  font-size: 14px;
139
- opacity: 0.6;
140
- transition: all 0.15s ease;
164
+ opacity: 0 !important;
165
+ transition: opacity 0.15s ease, background 0.15s ease, transform 0.15s ease;
141
166
 
142
167
  &:hover {
143
- opacity: 1;
144
168
  background: rgba(0, 0, 0, 0.05);
145
169
  transform: scale(1.1);
146
170
  }
@@ -223,12 +247,21 @@ export const Submenu = styled.div `
223
247
  background: transparent;
224
248
  }
225
249
 
250
+ /* Reset color inheritance from parent with !important to override panel header styles */
251
+ & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *) {
252
+ color: #1a1a1a !important;
253
+ }
254
+
226
255
  [data-theme='dark'] & {
227
256
  background: #2a2a2a;
228
257
  border-color: rgba(255, 255, 255, 0.1);
229
258
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4),
230
259
  0 2px 8px rgba(0, 0, 0, 0.3);
231
260
  }
261
+
262
+ [data-theme='dark'] & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *) {
263
+ color: #e0e0e0 !important;
264
+ }
232
265
  `;
233
266
  export const MobileMenuHeader = styled.div `
234
267
  display: flex;
@@ -8,6 +8,7 @@ export interface TMContextMenuItemProps {
8
8
  rightIcon?: React.ReactNode;
9
9
  onRightIconClick?: () => void;
10
10
  beginGroup?: boolean;
11
+ tooltip?: string;
11
12
  }
12
13
  export interface TMContextMenuProps {
13
14
  items: TMContextMenuItemProps[];
@@ -1,36 +1,40 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useState, useRef, useEffect, useCallback } from 'react';
3
3
  import { ContextMenu } from '../ContextMenu';
4
- import Notification from '../Notification';
4
+ import ShowAlert from '../../base/TMAlert';
5
5
  import TMTooltip from '../../base/TMTooltip';
6
6
  import * as S from './styles';
7
- import { IconApply, IconMenuKebab, IconMenuVertical, IconSettings, IconStar } from '../../../helper';
7
+ import { IconApply, IconMenuKebab, IconMenuVertical, IconPencil, IconPin, SDKUI_Globals } from '../../../helper';
8
8
  const IconDraggableDots = (props) => (_jsx("svg", { fontSize: 18, viewBox: "0 0 24 24", fill: "currentColor", height: "1em", width: "1em", ...props, children: _jsx("path", { d: "M9 3a2 2 0 11-4 0 2 2 0 014 0zm0 9a2 2 0 11-4 0 2 2 0 014 0zm0 9a2 2 0 11-4 0 2 2 0 014 0zm10-18a2 2 0 11-4 0 2 2 0 014 0zm0 9a2 2 0 11-4 0 2 2 0 014 0zm0 9a2 2 0 11-4 0 2 2 0 014 0z" }) }));
9
- const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], storageKey = 'floatingMenuBar-config', isConstrained = false, defaultPosition = { x: 100, y: 100 }, maxItems = 8, }) => {
9
+ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], storageKey = 'floatingMenuBar-config', // Kept for backward compatibility but not used
10
+ isConstrained = false, defaultPosition = { x: 100, y: 100 }, maxItems = 8, }) => {
10
11
  const loadConfig = () => {
11
12
  try {
12
- const saved = localStorage.getItem(storageKey);
13
- if (saved) {
14
- const config = JSON.parse(saved);
15
- return {
16
- orientation: config.orientation || 'horizontal',
17
- pinnedItemIds: new Set(config.pinnedItemIds || []),
18
- savedItemIds: config.itemIds || [],
19
- };
20
- }
13
+ const settings = SDKUI_Globals.userSettings.searchSettings.floatingMenuBar;
14
+ // Check if position was actually saved (not just the default class value)
15
+ const hasSavedPosition = settings.position &&
16
+ (settings.position.x !== 100 || settings.position.y !== 100 ||
17
+ (settings.itemIds && settings.itemIds.length > 0));
18
+ return {
19
+ orientation: settings.orientation || 'horizontal',
20
+ pinnedItemIds: new Set(settings.pinnedItemIds || []),
21
+ savedItemIds: settings.itemIds || [],
22
+ position: hasSavedPosition ? settings.position : defaultPosition,
23
+ };
21
24
  }
22
25
  catch (error) {
23
26
  console.error('Failed to load FloatingMenuBar config:', error);
27
+ return {
28
+ orientation: 'horizontal',
29
+ pinnedItemIds: new Set(),
30
+ savedItemIds: [],
31
+ position: defaultPosition,
32
+ };
24
33
  }
25
- return {
26
- orientation: 'horizontal',
27
- pinnedItemIds: new Set(),
28
- savedItemIds: [],
29
- };
30
34
  };
31
35
  const initialConfig = loadConfig();
32
36
  const [state, setState] = useState({
33
- position: defaultPosition,
37
+ position: initialConfig.position,
34
38
  isDragging: false,
35
39
  isConfigMode: false,
36
40
  orientation: initialConfig.orientation,
@@ -41,7 +45,6 @@ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], storageKey = '
41
45
  const dragOffset = useRef({ x: 0, y: 0 });
42
46
  const [pinnedItemIds, setPinnedItemIds] = useState(initialConfig.pinnedItemIds);
43
47
  const [dragOverIndex, setDragOverIndex] = useState(null);
44
- const [showMaxItemsNotification, setShowMaxItemsNotification] = useState(false);
45
48
  // Use refs to track item IDs without causing re-renders
46
49
  const floatingBarItemIds = useRef(new Set());
47
50
  const floatingBarItemNames = useRef(new Set());
@@ -60,7 +63,7 @@ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], storageKey = '
60
63
  result.push({
61
64
  id: itemId,
62
65
  name: item.name,
63
- icon: item.icon || _jsx(IconStar, {}),
66
+ icon: item.icon || _jsx(IconPin, {}),
64
67
  onClick: item.onClick,
65
68
  disabled: item.disabled,
66
69
  isPinned: pinnedItemIds.has(itemId),
@@ -98,8 +101,12 @@ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], storageKey = '
98
101
  else {
99
102
  // Add to floating bar
100
103
  if (s.items.length >= maxItems) {
101
- setShowMaxItemsNotification(true);
102
- setTimeout(() => setShowMaxItemsNotification(false), 3000);
104
+ ShowAlert({
105
+ mode: 'warning',
106
+ title: 'Limite Massimo Raggiunto',
107
+ message: `Hai raggiunto il massimo di ${maxItems} elementi. Rimuovine uno prima di aggiungerne altri.`,
108
+ duration: 4000,
109
+ });
103
110
  return s;
104
111
  }
105
112
  return { ...s, items: [...s.items, item] };
@@ -150,7 +157,7 @@ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], storageKey = '
150
157
  const isInFloatingBar = currentItemIds.has(itemId) || currentItemNames.has(item.name);
151
158
  const enhanced = {
152
159
  ...item,
153
- rightIcon: item.onClick && !item.submenu ? (isInFloatingBar ? _jsx(IconStar, { color: "#FFD700" }) : _jsx(IconStar, {})) : undefined,
160
+ rightIcon: item.onClick && !item.submenu ? (isInFloatingBar ? _jsx(IconPin, { color: "#e12a2a" }) : _jsx(IconPin, {})) : undefined,
154
161
  onRightIconClick: item.onClick && !item.submenu ? () => {
155
162
  if (flatItem) {
156
163
  togglePin(flatItem);
@@ -229,20 +236,21 @@ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], storageKey = '
229
236
  }
230
237
  return undefined;
231
238
  }, [state.isDragging, handleMouseMove, handleMouseUp]);
232
- // Save to localStorage whenever config changes (excluding position)
239
+ // Save to SDKUI_Globals.userSettings whenever config changes (including position)
233
240
  useEffect(() => {
234
241
  try {
235
- const config = {
242
+ // Replace the entire object to trigger the Proxy
243
+ SDKUI_Globals.userSettings.searchSettings.floatingMenuBar = {
236
244
  orientation: state.orientation,
237
245
  pinnedItemIds: Array.from(pinnedItemIds),
238
- itemIds: state.items.map(item => item.id), // Save only IDs, not functions
246
+ itemIds: state.items.map(item => item.id),
247
+ position: state.position,
239
248
  };
240
- localStorage.setItem(storageKey, JSON.stringify(config));
241
249
  }
242
250
  catch (error) {
243
251
  console.error('Failed to save FloatingMenuBar config:', error);
244
252
  }
245
- }, [state.orientation, state.items, pinnedItemIds, storageKey]);
253
+ }, [state.orientation, state.items, state.position, pinnedItemIds]);
246
254
  const toggleConfigMode = () => {
247
255
  setState(s => ({ ...s, isConfigMode: !s.isConfigMode }));
248
256
  };
@@ -347,7 +355,7 @@ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], storageKey = '
347
355
  setState(s => ({ ...s, draggedItemIndex: null }));
348
356
  setDragOverIndex(null);
349
357
  };
350
- return (_jsxs(_Fragment, { children: [_jsx(S.Overlay, { "$visible": state.isConfigMode }), _jsxs(S.FloatingContainer, { ref: floatingRef, "$x": state.position.x, "$y": state.position.y, "$orientation": state.orientation, "$isDragging": state.isDragging, "$isConfigMode": state.isConfigMode, "$isConstrained": isConstrained, children: [_jsx(S.GripHandle, { "$orientation": state.orientation, onMouseDown: handleMouseDown, children: _jsx(IconDraggableDots, {}) }), _jsx(S.ConfigButton, { onClick: toggleConfigMode, "$isActive": state.isConfigMode, children: state.isConfigMode ? _jsx(IconApply, {}) : _jsx(IconSettings, {}) }), state.items.map((item, index) => {
358
+ return (_jsxs(_Fragment, { children: [_jsx(S.Overlay, { "$visible": state.isConfigMode }), _jsxs(S.FloatingContainer, { ref: floatingRef, "$x": state.position.x, "$y": state.position.y, "$orientation": state.orientation, "$isDragging": state.isDragging, "$isConfigMode": state.isConfigMode, "$isConstrained": isConstrained, children: [_jsx(S.GripHandle, { "$orientation": state.orientation, onMouseDown: handleMouseDown, children: _jsx(IconDraggableDots, {}) }), _jsx(S.Separator, { "$orientation": state.orientation }), state.items.map((item, index) => {
351
359
  // Get current state (disabled and onClick) from contextMenuItems
352
360
  const currentState = getCurrentItemState(item.name);
353
361
  const isDisabled = currentState.disabled || false;
@@ -365,6 +373,6 @@ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], storageKey = '
365
373
  currentOnClick();
366
374
  }
367
375
  }, disabled: isDisabled, children: item.icon }) })), state.isConfigMode && (_jsx(S.RemoveButton, { onClick: () => removeItem(item.id), children: "\u00D7" }))] }, item.id));
368
- }), !state.isConfigMode && contextMenuItems.length > 0 && (_jsx(ContextMenu, { items: enhancedContextMenuItems(), trigger: "left", children: _jsx(S.MenuButton, { children: _jsx(IconMenuVertical, {}) }) }, Array.from(pinnedItemIds).join(','))), !state.isConfigMode && (_jsx(S.OrientationToggle, { "$orientation": state.orientation, onClick: toggleOrientation, children: _jsx(IconMenuKebab, {}) }))] }), showMaxItemsNotification && (_jsx("div", { style: { position: 'fixed', top: '20px', left: '50%', transform: 'translateX(-50%)', zIndex: 100001 }, children: _jsx(Notification, { title: "Maximum Items Reached", message: `You have reached the maximum number of pinned items (${maxItems}). Please unpin an item before adding a new one.`, mode: "warning", position: "top-center", duration: 4000, closable: true, stopOnMouseEnter: true, hasProgress: true, onClose: () => setShowMaxItemsNotification(false) }) }))] }));
376
+ }), !state.isConfigMode && contextMenuItems.length > 0 && (_jsx(ContextMenu, { items: enhancedContextMenuItems(), trigger: "left", children: _jsx(S.ContextMenuButton, { children: _jsx(IconMenuVertical, {}) }) }, Array.from(pinnedItemIds).join(','))), _jsx(S.ConfigButton, { onClick: toggleConfigMode, "$isActive": state.isConfigMode, children: state.isConfigMode ? _jsx(IconApply, {}) : _jsx(IconPencil, {}) }), !state.isConfigMode && (_jsx(S.OrientationToggle, { "$orientation": state.orientation, onClick: toggleOrientation, children: _jsx(IconMenuKebab, {}) }))] })] }));
369
377
  };
370
378
  export default TMFloatingMenuBar;
@@ -21,12 +21,20 @@ export declare const FloatingContainer: import("styled-components/dist/types").I
21
21
  export declare const GripHandle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
22
22
  $orientation: "horizontal" | "vertical";
23
23
  }>> & string;
24
+ export declare const Separator: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
25
+ $orientation: "horizontal" | "vertical";
26
+ }>> & string;
24
27
  export declare const MenuButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {
25
28
  $isActive?: boolean;
26
29
  }>> & string;
27
30
  export declare const ConfigButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {
28
31
  $isActive?: boolean;
29
32
  }>> & string;
33
+ export declare const ContextMenuButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<Omit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "$isActive"> & {
34
+ $isActive?: boolean;
35
+ }, "ref"> & {
36
+ ref?: ((instance: HTMLButtonElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLButtonElement> | null | undefined;
37
+ }, never>> & string;
30
38
  export declare const RemoveButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
31
39
  export declare const OrientationToggle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {
32
40
  $orientation: "horizontal" | "vertical";
@@ -55,7 +55,7 @@ export const FloatingContainer = styled.div.attrs(props => ({
55
55
  transition: none;
56
56
 
57
57
  &:hover {
58
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
58
+ background: linear-gradient(135deg, #0071BC 0%, #1B1464 100%);
59
59
  border: 1px solid #667eea;
60
60
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3),
61
61
  0 6px 16px rgba(0, 0, 0, 0.2);
@@ -98,6 +98,13 @@ export const GripHandle = styled.div `
98
98
  height: 14px;
99
99
  }
100
100
  `;
101
+ export const Separator = styled.div `
102
+ background: rgba(255, 255, 255, 0.25);
103
+ width: ${props => props.$orientation === 'horizontal' ? '1px' : '100%'};
104
+ height: ${props => props.$orientation === 'horizontal' ? '24px' : '1px'};
105
+ margin: ${props => props.$orientation === 'horizontal' ? '0 4px' : '4px 0'};
106
+ flex-shrink: 0;
107
+ `;
101
108
  export const MenuButton = styled.button `
102
109
  display: flex;
103
110
  align-items: center;
@@ -110,36 +117,35 @@ export const MenuButton = styled.button `
110
117
  color: white;
111
118
  font-size: 16px;
112
119
  cursor: pointer;
113
- transition: all 0.2s ease;
120
+ transition: background 0.2s ease;
114
121
  position: relative;
115
122
 
116
123
  &:hover:not(:disabled) {
117
124
  background: rgba(255, 255, 255, 0.2);
118
- transform: scale(1.1);
119
125
  }
120
126
 
121
127
  &:active:not(:disabled) {
122
- transform: scale(0.95);
128
+ opacity: 0.8;
123
129
  }
124
130
 
125
131
  &:disabled {
126
- opacity: 0.3;
132
+ opacity: 0.5;
127
133
  cursor: not-allowed;
128
- background: rgba(255, 255, 255, 0.05);
129
- color: rgba(255, 255, 255, 0.4);
134
+ color: rgba(255, 255, 255, 0.6);
130
135
  }
131
136
 
132
137
  svg {
133
138
  width: 18px;
134
139
  height: 18px;
140
+ transform: translateY(2px);
135
141
  }
136
142
  `;
137
143
  export const ConfigButton = styled.button `
138
144
  display: flex;
139
145
  align-items: center;
140
146
  justify-content: center;
141
- width: 34px;
142
- height: 34px;
147
+ width: 28px;
148
+ height: 28px;
143
149
  background: ${props => props.$isActive
144
150
  ? 'rgba(0, 0, 0, 0.2)'
145
151
  : 'rgba(0, 0, 0, 0.1)'};
@@ -148,9 +154,9 @@ export const ConfigButton = styled.button `
148
154
  : 'rgba(255, 255, 255, 0.15)'};
149
155
  border-radius: 8px;
150
156
  color: white;
151
- font-size: 16px;
157
+ font-size: 14px;
152
158
  cursor: pointer;
153
- transition: all 0.2s ease;
159
+ transition: background 0.2s ease, border-color 0.2s ease;
154
160
  position: relative;
155
161
 
156
162
  &:hover {
@@ -158,16 +164,20 @@ export const ConfigButton = styled.button `
158
164
  ? 'rgba(0, 0, 0, 0.25)'
159
165
  : 'rgba(0, 0, 0, 0.15)'};
160
166
  border-color: rgba(255, 255, 255, 0.35);
161
- transform: scale(1.05);
162
167
  }
163
168
 
164
169
  &:active {
165
- transform: scale(0.95);
170
+ opacity: 0.8;
166
171
  }
167
172
 
168
173
  svg {
169
- width: 20px;
170
- height: 20px;
174
+ width: 16px;
175
+ height: 16px;
176
+ }
177
+ `;
178
+ export const ContextMenuButton = styled(MenuButton) `
179
+ svg {
180
+ transform: translateY(0);
171
181
  }
172
182
  `;
173
183
  export const RemoveButton = styled.button `
@@ -177,25 +187,26 @@ export const RemoveButton = styled.button `
177
187
  width: 20px;
178
188
  height: 20px;
179
189
  background: #ef4444;
180
- border: 2px solid white;
190
+ border: none;
181
191
  border-radius: 50%;
182
192
  color: white;
183
- font-size: 12px;
193
+ font-size: 14px;
184
194
  font-weight: bold;
195
+ line-height: 1;
185
196
  cursor: pointer;
186
197
  display: flex;
187
198
  align-items: center;
188
199
  justify-content: center;
200
+ padding: 0;
189
201
  transition: all 0.2s ease;
190
202
  z-index: 1;
191
203
 
192
204
  &:hover {
193
205
  background: #dc2626;
194
- transform: scale(1.15);
195
206
  }
196
207
 
197
208
  &:active {
198
- transform: scale(0.9);
209
+ background: #b91c1c;
199
210
  }
200
211
  `;
201
212
  export const OrientationToggle = styled.button `
@@ -47,12 +47,12 @@ const StyledGroupTemplate = styled.div `
47
47
  &::after {
48
48
  content: '';
49
49
  display: block;
50
- width: 90%;
50
+ width: calc(100% - 35px);
51
51
  margin: 0 auto;
52
52
  border-bottom: 1px solid #00A99D;
53
53
  margin-top: 8px;
54
54
  position: absolute;
55
- left: 5%;
55
+ left: 35px;
56
56
  bottom: 0;
57
57
  }
58
58
  `;
@@ -8,7 +8,6 @@ const IframeContainer = styled.div `
8
8
  display: flex;
9
9
  height: 100%;
10
10
  flex-direction: column;
11
- padding-left: 15px;
12
11
  `;
13
12
  const StyledIframe = styled.iframe `
14
13
  border: none;
@@ -39,8 +39,8 @@ export interface TMDataGridProps<T> extends IDataGridOptions {
39
39
  showFilterPanel?: boolean;
40
40
  /** Show the load panel */
41
41
  showLoadPanel?: boolean;
42
- /** Show the column chooser */
43
- showColumnChooser?: boolean;
42
+ /** Show the header column chooser in context menu */
43
+ showHeaderColumnChooser?: boolean;
44
44
  /** Show the search panel */
45
45
  showSearchPanel?: boolean;
46
46
  /** Show the group panel */
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';
3
- import DataGrid, { Column, HeaderFilter, Selection, Scrolling, LoadPanel, SearchPanel, Pager, Sorting, Paging, FilterPanel, ColumnChooser, Grouping, GroupPanel, Summary, Editing, FilterRow, StateStoring, RowDragging, MasterDetail } from 'devextreme-react/data-grid';
3
+ import DataGrid, { Column, HeaderFilter, Selection, Scrolling, LoadPanel, SearchPanel, Pager, Sorting, Paging, FilterPanel, ColumnChooser, Grouping, GroupPanel, Summary, Editing, FilterRow, StateStoring, RowDragging, MasterDetail, Position, ColumnChooserSearch, ColumnChooserSelection } from 'devextreme-react/data-grid';
4
4
  import DataSource from 'devextreme/data/data_source';
5
5
  import { IconAll, IconSelected, IconVisible, SDKUI_Globals, SDKUI_Localizator } from '../../helper';
6
6
  import TMCounterContainer, { CounterItemKey } from './TMCounterContainer';
@@ -16,9 +16,9 @@ const TMDataGrid = React.forwardRef((props, ref) => {
16
16
  // main properties
17
17
  keyExpr = 'id', dataSource, focusedRowEnabled = true, hoverStateEnabled = true, focusedRowKey, selectedRowKeys = [],
18
18
  // custom options
19
- dataColumns = [], pageSize = TMDataGridPageSize.Large, showHeaderFilter = true, showFilterPanel = true, showLoadPanel = true, showSearchPanel = true, searchPanelToolbarPosition = 'before', searchPanelFocusStarting = false, counterConfig = { show: false, items: new Map() }, onHasFiltersChange,
19
+ dataColumns = [], pageSize = TMDataGridPageSize.Large, showHeaderFilter = true, showFilterPanel = true, showHeaderColumnChooser = false, showLoadPanel = true, showSearchPanel = true, searchPanelToolbarPosition = 'before', searchPanelFocusStarting = false, counterConfig = { show: false, items: new Map() }, onHasFiltersChange,
20
20
  // events and callbacks
21
- onSelectionChanged, onFocusedRowChanged, onRowDblClick, onRowClick, onCellClick, onCellDblClick, onOptionChanged, onContentReady, onContextMenuPreparing, onInitialized, onEditorPreparing, onCellPrepared, onRowPrepared, onRowUpdating, onRowExpanded, onRowCollapsed, onRowUpdated, onSaved, onEditCanceled, onEditingStart, onEditingChange, customizeColumns, onKeyDown, scrolling = { mode: 'standard', useNative: SDKUI_Globals.userSettings?.themeSettings.gridSettings.useNativeScrollbar === 1 }, paging = { enabled: true, pageSize: pageSize }, pager = { visible: true, showInfo: true, showNavigationButtons: true }, selection = { mode: 'multiple', showCheckBoxesMode: "always", selectAllMode: "allPages" }, sorting, summary, stateStoring, columnChooser, grouping, groupPanel, filterRow, headerFilter, editing, rowDragging, masterDetail,
21
+ onSelectionChanged, onFocusedRowChanged, onRowDblClick, onRowClick, onCellClick, onCellDblClick, onOptionChanged, onContentReady, onContextMenuPreparing, onInitialized, onEditorPreparing, onCellPrepared, onRowPrepared, onRowUpdating, onRowExpanded, onRowCollapsed, onRowUpdated, onSaved, onEditCanceled, onEditingStart, onEditingChange, customizeColumns, onKeyDown, scrolling = { mode: 'standard', useNative: SDKUI_Globals.userSettings?.themeSettings.gridSettings.useNativeScrollbar === 1 }, paging = { enabled: true, pageSize: pageSize }, pager = { visible: true, showInfo: true, showNavigationButtons: true }, selection = { mode: 'multiple', showCheckBoxesMode: "always", selectAllMode: "allPages" }, sorting, summary, stateStoring, grouping, groupPanel, filterRow, headerFilter, editing, rowDragging, masterDetail,
22
22
  // other properties
23
23
  disabled = false, autoNavigateToFocusedRow = true, columnResizingMode = 'widget', columnHidingEnabled = true, columnAutoWidth = true, allowColumnResizing = true, allowColumnReordering = true, showBorders = true, showRowLines = SDKUI_Globals.userSettings?.themeSettings.gridSettings.showRowLines === 1, showColumnLines = SDKUI_Globals.userSettings?.themeSettings.gridSettings.showColumnLines === 1, showColumnHeaders = true, rowAlternationEnabled = false, wordWrapEnabled = false, noDataText,
24
24
  // styles
@@ -146,7 +146,18 @@ const TMDataGrid = React.forwardRef((props, ref) => {
146
146
  e.items = [...updatedContextMenuItems];
147
147
  }
148
148
  }
149
- }, [updateContextMenuItems, onContextMenuPreparing]);
149
+ // Add column chooser to header context menu
150
+ if (e.target === 'header' && showHeaderColumnChooser) {
151
+ e.items = e.items || [];
152
+ e.items.push({
153
+ text: SDKUI_Localizator.ShowColumnSelection,
154
+ icon: 'columnchooser',
155
+ onItemClick: () => {
156
+ internalRef.current?.instance().showColumnChooser();
157
+ }
158
+ });
159
+ }
160
+ }, [updateContextMenuItems, onContextMenuPreparing, showHeaderColumnChooser]);
150
161
  // Handle toolbar preparation, especially for the search panel
151
162
  const onToolbarPreparingCallback = useCallback((e) => {
152
163
  if (e === undefined || e.toolbarOptions === undefined || e.toolbarOptions.items === undefined)
@@ -223,7 +234,7 @@ const TMDataGrid = React.forwardRef((props, ref) => {
223
234
  // other properties
224
235
  disabled: disabled, autoNavigateToFocusedRow: autoNavigateToFocusedRow, focusedRowKey: focusedRowKey, columnHidingEnabled: columnHidingEnabled, columnResizingMode: columnResizingMode, columnAutoWidth: columnAutoWidth, allowColumnResizing: allowColumnResizing, allowColumnReordering: allowColumnReordering, showBorders: showBorders, showRowLines: showRowLines, showColumnLines: showColumnLines, showColumnHeaders: showColumnHeaders, rowAlternationEnabled: rowAlternationEnabled, wordWrapEnabled: wordWrapEnabled, noDataText: noDataText,
225
236
  // styles
226
- width: width, height: height, style: { userSelect: 'none' }, children: [dataColumns.map((column, index) => (_jsx(Column, { ...column }, column.caption + index.toString()))), sorting && _jsx(Sorting, { ...sorting }), selection && _jsx(Selection, { ...selection }), scrolling && _jsx(Scrolling, { ...scrolling }), summary && _jsx(Summary, { ...summary }), showHeaderFilter && _jsx(HeaderFilter, { visible: true, ...headerFilter }), rowDragging && _jsx(RowDragging, { ...rowDragging }), filterRow && _jsx(FilterRow, { ...filterRow }), showFilterPanel && _jsx(FilterPanel, { visible: true }), columnChooser && _jsx(ColumnChooser, { ...columnChooser }), stateStoring && _jsx(StateStoring, { ...stateStoring }), groupPanel && _jsx(GroupPanel, { ...groupPanel }), _jsx(Grouping, { contextMenuEnabled: true, ...grouping }), _jsx(LoadPanel, { enabled: showLoadPanel }), _jsx(SearchPanel, { visible: showSearchPanel, searchVisibleColumnsOnly: true, highlightSearchText: true }), editing && _jsx(Editing, { ...editing }), paging && _jsx(Paging, { ...paging }), pager && _jsx(Pager, { ...pager, visible: totalRecordCount > pageSize }), masterDetail && _jsx(MasterDetail, { ...masterDetail })] }) }), counterConfig.show && _jsx("div", { style: { width: "100%", height: "25px", display: "flex", alignItems: "center", gap: "15px", backgroundColor: "#e0e0e0" }, children: _jsx(TMCounterContainer, { items: counterValues, bgColorContainer: counterConfig.bgColorContainer, bgColorItem: counterConfig.bgColorItem, hoverColorItem: counterConfig.hoverColorItem, textColorItem: counterConfig.textColorItem }) })] });
237
+ width: width, height: height, style: { userSelect: 'none' }, children: [dataColumns.map((column, index) => (_jsx(Column, { ...column }, column.caption + index.toString()))), sorting && _jsx(Sorting, { ...sorting }), selection && _jsx(Selection, { ...selection }), scrolling && _jsx(Scrolling, { ...scrolling }), summary && _jsx(Summary, { ...summary }), showHeaderFilter && _jsx(HeaderFilter, { visible: true, ...headerFilter }), rowDragging && _jsx(RowDragging, { ...rowDragging }), filterRow && _jsx(FilterRow, { ...filterRow }), showFilterPanel && _jsx(FilterPanel, { visible: true }), showHeaderColumnChooser && _jsxs(ColumnChooser, { height: "400px", enabled: !showHeaderColumnChooser, mode: "select", children: [_jsx(Position, { my: "center", at: "center", of: window }), _jsx(ColumnChooserSearch, { enabled: true }), _jsx(ColumnChooserSelection, { allowSelectAll: false, selectByClick: true, recursive: true })] }), stateStoring && _jsx(StateStoring, { ...stateStoring }), groupPanel && _jsx(GroupPanel, { ...groupPanel }), _jsx(Grouping, { contextMenuEnabled: true, ...grouping }), _jsx(LoadPanel, { enabled: showLoadPanel }), _jsx(SearchPanel, { visible: showSearchPanel, searchVisibleColumnsOnly: true, highlightSearchText: true }), editing && _jsx(Editing, { ...editing }), paging && _jsx(Paging, { ...paging }), pager && _jsx(Pager, { ...pager, visible: totalRecordCount > pageSize }), masterDetail && _jsx(MasterDetail, { ...masterDetail })] }) }), counterConfig.show && _jsx("div", { style: { width: "100%", height: "25px", display: "flex", alignItems: "center", gap: "15px", backgroundColor: "#e0e0e0" }, children: _jsx(TMCounterContainer, { items: counterValues, bgColorContainer: counterConfig.bgColorContainer, bgColorItem: counterConfig.bgColorItem, hoverColorItem: counterConfig.hoverColorItem, textColorItem: counterConfig.textColorItem }) })] });
227
238
  });
228
239
  export default TMDataGrid;
229
240
  const getRecordCount = (dataSource) => {
@@ -170,7 +170,7 @@ const TMHtmlEditor = (props) => {
170
170
  justifyContent: 'flex-end',
171
171
  fontSize: 12,
172
172
  color: '#6c757d',
173
- marginTop: 4,
173
+ marginTop: showInfoIcon ? 0 : 4,
174
174
  gap: 4,
175
175
  }, children: [`${Math.max(charactersRemaining, 0)} ${SDKUI_Localizator.CharactersRemaining}`, showInfoIcon && (_jsx(TMTooltip, { content: 'Markup HTML', children: _jsx("span", { className: "dx-icon-codeblock", style: { fontSize: 22, cursor: 'pointer' }, onClick: () => {
176
176
  TMMessageBoxManager.show({