@topconsultnpm/sdkui-react 6.20.0-dev1.12 → 6.20.0-dev1.120

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 (202) hide show
  1. package/lib/assets/Toppy-help-center.png +0 -0
  2. package/lib/assets/headergradient.svg +87 -0
  3. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +322 -30
  4. package/lib/components/NewComponents/ContextMenu/hooks.d.ts +8 -1
  5. package/lib/components/NewComponents/ContextMenu/hooks.js +80 -8
  6. package/lib/components/NewComponents/ContextMenu/index.d.ts +3 -0
  7. package/lib/components/NewComponents/ContextMenu/index.js +2 -0
  8. package/lib/components/NewComponents/ContextMenu/styles.d.ts +9 -1
  9. package/lib/components/NewComponents/ContextMenu/styles.js +159 -37
  10. package/lib/components/NewComponents/ContextMenu/types.d.ts +22 -3
  11. package/lib/components/NewComponents/ContextMenu/useLongPress.d.ts +21 -0
  12. package/lib/components/NewComponents/ContextMenu/useLongPress.js +112 -0
  13. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +803 -109
  14. package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +25 -5
  15. package/lib/components/NewComponents/FloatingMenuBar/styles.js +215 -59
  16. package/lib/components/NewComponents/FloatingMenuBar/types.d.ts +12 -2
  17. package/lib/components/base/TMAccordionNew.js +35 -14
  18. package/lib/components/base/TMButton.js +6 -0
  19. package/lib/components/base/TMClosableList.js +4 -0
  20. package/lib/components/base/TMCustomButton.js +61 -17
  21. package/lib/components/base/TMDataGrid.d.ts +7 -4
  22. package/lib/components/base/TMDataGrid.js +153 -11
  23. package/lib/components/base/TMDropDownMenu.js +21 -18
  24. package/lib/components/base/TMFileManager.d.ts +4 -3
  25. package/lib/components/base/TMFileManager.js +32 -24
  26. package/lib/components/base/TMFileManagerDataGridView.d.ts +3 -2
  27. package/lib/components/base/TMFileManagerDataGridView.js +1 -11
  28. package/lib/components/base/TMFileManagerThumbnailItems.d.ts +7 -1
  29. package/lib/components/base/TMFileManagerThumbnailItems.js +5 -2
  30. package/lib/components/base/TMFileManagerThumbnailsView.d.ts +17 -4
  31. package/lib/components/base/TMFileManagerThumbnailsView.js +18 -6
  32. package/lib/components/base/TMFileManagerUtils.d.ts +0 -12
  33. package/lib/components/base/TMListView.js +33 -15
  34. package/lib/components/base/TMPanel.d.ts +1 -1
  35. package/lib/components/base/TMPanel.js +3 -1
  36. package/lib/components/base/TMPopUp.js +6 -0
  37. package/lib/components/base/TMToolbarCard.js +2 -0
  38. package/lib/components/base/TMTreeView.d.ts +2 -1
  39. package/lib/components/base/TMTreeView.js +33 -26
  40. package/lib/components/choosers/TMDataListItemChooser.d.ts +2 -0
  41. package/lib/components/choosers/TMDataListItemChooser.js +8 -2
  42. package/lib/components/choosers/TMDcmtTypeChooser.d.ts +1 -0
  43. package/lib/components/choosers/TMDcmtTypeChooser.js +11 -3
  44. package/lib/components/choosers/TMDistinctValues.js +2 -2
  45. package/lib/components/choosers/TMDynDataListItemChooser.d.ts +2 -0
  46. package/lib/components/choosers/TMDynDataListItemChooser.js +8 -2
  47. package/lib/components/choosers/TMInvoiceRetrieveFormats.js +1 -1
  48. package/lib/components/choosers/TMMetadataChooser.d.ts +2 -0
  49. package/lib/components/choosers/TMMetadataChooser.js +19 -4
  50. package/lib/components/choosers/TMOrderRetrieveFormats.js +1 -1
  51. package/lib/components/choosers/TMUserChooser.d.ts +2 -5
  52. package/lib/components/choosers/TMUserChooser.js +33 -47
  53. package/lib/components/editors/TMCheckBox.js +2 -0
  54. package/lib/components/editors/TMDateBox.js +18 -9
  55. package/lib/components/editors/TMEditorStyled.js +7 -0
  56. package/lib/components/editors/TMLocalizedTextBox.d.ts +3 -1
  57. package/lib/components/editors/TMLocalizedTextBox.js +16 -14
  58. package/lib/components/editors/TMMetadataEditor.d.ts +1 -0
  59. package/lib/components/editors/TMMetadataEditor.js +4 -4
  60. package/lib/components/editors/TMMetadataTextBox.d.ts +9 -0
  61. package/lib/components/editors/TMMetadataTextBox.js +92 -0
  62. package/lib/components/editors/TMMetadataValues.d.ts +1 -0
  63. package/lib/components/editors/TMMetadataValues.js +25 -7
  64. package/lib/components/editors/TMRadioButton.js +2 -0
  65. package/lib/components/editors/TMTextArea.js +18 -30
  66. package/lib/components/editors/TMTextBox.d.ts +1 -1
  67. package/lib/components/editors/TMTextBox.js +29 -4
  68. package/lib/components/editors/TMTextExpression.js +6 -91
  69. package/lib/components/features/archive/TMArchive.js +2 -2
  70. package/lib/components/features/assistant/TMToppyDraggableHelpCenter.d.ts +15 -0
  71. package/lib/components/features/assistant/TMToppyDraggableHelpCenter.js +462 -0
  72. package/lib/components/features/assistant/TMToppySpeechBubble.d.ts +11 -0
  73. package/lib/components/features/assistant/TMToppySpeechBubble.js +126 -0
  74. package/lib/components/features/documents/TMDcmtBlog.js +1 -1
  75. package/lib/components/features/documents/TMDcmtForm.d.ts +14 -2
  76. package/lib/components/features/documents/TMDcmtForm.js +459 -208
  77. package/lib/components/features/documents/TMDcmtPreview.js +42 -155
  78. package/lib/components/features/documents/TMDcmtTasks.js +9 -9
  79. package/lib/components/features/documents/TMMasterDetailDcmts.js +38 -53
  80. package/lib/components/features/documents/TMRelationViewer.d.ts +1 -1
  81. package/lib/components/features/documents/TMRelationViewer.js +2 -2
  82. package/lib/components/features/search/TMDcmtCheckoutInfoForm.d.ts +8 -0
  83. package/lib/components/features/search/{TMSearchResultCheckoutInfoForm.js → TMDcmtCheckoutInfoForm.js} +2 -2
  84. package/lib/components/features/search/TMSavedQuerySelector.js +72 -67
  85. package/lib/components/features/search/TMSearch.d.ts +3 -0
  86. package/lib/components/features/search/TMSearch.js +50 -11
  87. package/lib/components/features/search/TMSearchQueryEditor.d.ts +1 -0
  88. package/lib/components/features/search/TMSearchQueryEditor.js +10 -10
  89. package/lib/components/features/search/TMSearchQueryPanel.d.ts +1 -0
  90. package/lib/components/features/search/TMSearchQueryPanel.js +40 -25
  91. package/lib/components/features/search/TMSearchResult.d.ts +3 -0
  92. package/lib/components/features/search/TMSearchResult.js +210 -250
  93. package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +3 -3
  94. package/lib/components/features/search/TMSearchResultsMenuItems.js +227 -171
  95. package/lib/components/features/search/TMSignSettingsForm.js +1 -1
  96. package/lib/components/features/search/TMSignatureInfoContent.d.ts +6 -0
  97. package/lib/components/features/search/TMSignatureInfoContent.js +140 -0
  98. package/lib/components/features/search/TMViewHistoryDcmt.js +2 -2
  99. package/lib/components/features/tasks/TMTaskForm.js +75 -25
  100. package/lib/components/features/tasks/TMTasksAgenda.d.ts +3 -1
  101. package/lib/components/features/tasks/TMTasksAgenda.js +48 -9
  102. package/lib/components/features/tasks/TMTasksCalendar.d.ts +2 -0
  103. package/lib/components/features/tasks/TMTasksCalendar.js +19 -7
  104. package/lib/components/features/tasks/TMTasksUtils.d.ts +2 -2
  105. package/lib/components/features/tasks/TMTasksUtils.js +57 -37
  106. package/lib/components/features/tasks/TMTasksView.js +28 -19
  107. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +33 -2
  108. package/lib/components/features/workflow/TMWorkflowPopup.js +139 -34
  109. package/lib/components/features/workflow/diagram/DiagramItemComponent.d.ts +2 -0
  110. package/lib/components/features/workflow/diagram/DiagramItemComponent.js +14 -7
  111. package/lib/components/features/workflow/diagram/DiagramItemForm.js +1 -1
  112. package/lib/components/features/workflow/diagram/RecipientList.js +3 -2
  113. package/lib/components/features/workflow/diagram/WFDiagram.d.ts +4 -0
  114. package/lib/components/features/workflow/diagram/WFDiagram.js +164 -13
  115. package/lib/components/forms/Login/LoginValidatorService.d.ts +2 -0
  116. package/lib/components/forms/Login/LoginValidatorService.js +7 -2
  117. package/lib/components/forms/Login/TMLoginForm.js +35 -7
  118. package/lib/components/forms/TMChooserForm.js +1 -1
  119. package/lib/components/grids/TMBlogsPost.js +56 -31
  120. package/lib/components/grids/TMRecentsManager.js +20 -10
  121. package/lib/components/grids/TMValidationItemsList.js +6 -0
  122. package/lib/components/index.d.ts +6 -3
  123. package/lib/components/index.js +6 -3
  124. package/lib/components/layout/panelManager/TMPanelManagerContext.js +13 -5
  125. package/lib/components/query/TMQueryEditor.d.ts +3 -1
  126. package/lib/components/query/TMQueryEditor.js +102 -100
  127. package/lib/components/settings/SettingsAppearance.d.ts +2 -1
  128. package/lib/components/settings/SettingsAppearance.js +99 -30
  129. package/lib/components/sidebar/TMHeader.js +11 -7
  130. package/lib/components/sidebar/TMSidebar.d.ts +0 -1
  131. package/lib/components/sidebar/TMSidebar.js +16 -44
  132. package/lib/components/sidebar/TMSidebarItem.js +36 -17
  133. package/lib/components/viewers/TMDataListItemViewer.d.ts +2 -1
  134. package/lib/components/viewers/TMDataListItemViewer.js +35 -71
  135. package/lib/components/viewers/TMDataUserIdItemViewer.d.ts +8 -0
  136. package/lib/components/viewers/TMDataUserIdItemViewer.js +39 -0
  137. package/lib/css/tm-sdkui.css +1 -1
  138. package/lib/helper/SDKUI_Globals.d.ts +22 -0
  139. package/lib/helper/SDKUI_Globals.js +10 -1
  140. package/lib/helper/SDKUI_Localizator.d.ts +20 -1
  141. package/lib/helper/SDKUI_Localizator.js +197 -1
  142. package/lib/helper/TMCommandsContextMenu.d.ts +4 -2
  143. package/lib/helper/TMCommandsContextMenu.js +15 -4
  144. package/lib/helper/TMIcons.d.ts +4 -0
  145. package/lib/helper/TMIcons.js +13 -3
  146. package/lib/helper/TMPdfViewer.d.ts +8 -0
  147. package/lib/helper/TMPdfViewer.js +373 -0
  148. package/lib/helper/TMToppyMessage.js +4 -0
  149. package/lib/helper/checkinCheckoutManager.d.ts +31 -1
  150. package/lib/helper/checkinCheckoutManager.js +112 -30
  151. package/lib/helper/devextremeCustomMessages.d.ts +30 -0
  152. package/lib/helper/devextremeCustomMessages.js +30 -0
  153. package/lib/helper/helpers.d.ts +30 -2
  154. package/lib/helper/helpers.js +131 -3
  155. package/lib/helper/index.d.ts +2 -0
  156. package/lib/helper/index.js +2 -0
  157. package/lib/helper/queryHelper.d.ts +1 -1
  158. package/lib/helper/queryHelper.js +33 -3
  159. package/lib/helper/workItemsHelper.d.ts +6 -0
  160. package/lib/helper/workItemsHelper.js +230 -0
  161. package/lib/hooks/useCheckInOutOperations.d.ts +28 -0
  162. package/lib/hooks/useCheckInOutOperations.js +223 -0
  163. package/lib/hooks/useDataListItem.d.ts +12 -0
  164. package/lib/hooks/useDataListItem.js +132 -0
  165. package/lib/hooks/useDataUserIdItem.d.ts +10 -0
  166. package/lib/hooks/useDataUserIdItem.js +96 -0
  167. package/lib/hooks/useFloatingBarPinnedItems.d.ts +11 -0
  168. package/lib/hooks/useFloatingBarPinnedItems.js +54 -0
  169. package/lib/hooks/useMetadataExpression.d.ts +19 -0
  170. package/lib/hooks/useMetadataExpression.js +99 -0
  171. package/lib/hooks/useSettingsFeedback.d.ts +11 -0
  172. package/lib/hooks/useSettingsFeedback.js +38 -0
  173. package/lib/hooks/useWorkflowApprove.d.ts +4 -0
  174. package/lib/hooks/useWorkflowApprove.js +14 -1
  175. package/lib/index.d.ts +1 -0
  176. package/lib/index.js +3 -2
  177. package/lib/services/platform_services.d.ts +3 -3
  178. package/lib/ts/types.d.ts +61 -1
  179. package/lib/utils/theme.d.ts +1 -1
  180. package/lib/utils/theme.js +1 -1
  181. package/package.json +7 -4
  182. package/lib/components/NewComponents/Notification/Notification.d.ts +0 -4
  183. package/lib/components/NewComponents/Notification/Notification.js +0 -60
  184. package/lib/components/NewComponents/Notification/NotificationContainer.d.ts +0 -8
  185. package/lib/components/NewComponents/Notification/NotificationContainer.js +0 -33
  186. package/lib/components/NewComponents/Notification/index.d.ts +0 -2
  187. package/lib/components/NewComponents/Notification/index.js +0 -2
  188. package/lib/components/NewComponents/Notification/styles.d.ts +0 -21
  189. package/lib/components/NewComponents/Notification/styles.js +0 -180
  190. package/lib/components/NewComponents/Notification/types.d.ts +0 -18
  191. package/lib/components/NewComponents/Notification/types.js +0 -1
  192. package/lib/components/base/TMContextMenu.d.ts +0 -25
  193. package/lib/components/base/TMContextMenu.js +0 -109
  194. package/lib/components/base/TMContextMenuOLD.d.ts +0 -26
  195. package/lib/components/base/TMContextMenuOLD.js +0 -56
  196. package/lib/components/base/TMFloatingToolbar.d.ts +0 -9
  197. package/lib/components/base/TMFloatingToolbar.js +0 -101
  198. package/lib/components/features/assistant/ToppyDraggableHelpCenter.d.ts +0 -30
  199. package/lib/components/features/assistant/ToppyDraggableHelpCenter.js +0 -482
  200. package/lib/components/features/assistant/ToppySpeechBubble.d.ts +0 -9
  201. package/lib/components/features/assistant/ToppySpeechBubble.js +0 -117
  202. package/lib/components/features/search/TMSearchResultCheckoutInfoForm.d.ts +0 -8
@@ -1,4 +1,13 @@
1
- import { useState, useEffect, useRef } from 'react';
1
+ import { useState, useEffect, useLayoutEffect, useRef } from 'react';
2
+ export const useIsIOS = () => {
3
+ const [isIOS, setIsIOS] = useState(false);
4
+ useEffect(() => {
5
+ const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) ||
6
+ (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
7
+ setIsIOS(iOS);
8
+ }, []);
9
+ return isIOS;
10
+ };
2
11
  export const useIsMobile = () => {
3
12
  const [isMobile, setIsMobile] = useState(false);
4
13
  useEffect(() => {
@@ -29,20 +38,83 @@ export const useClickOutside = (callback) => {
29
38
  }, [callback]);
30
39
  return ref;
31
40
  };
32
- export const useMenuPosition = (menuRef, position) => {
33
- const [adjustedPosition, setAdjustedPosition] = useState({ openLeft: false, openUp: false });
34
- useEffect(() => {
35
- if (!menuRef.current)
41
+ export const useMenuPosition = (menuRef, position, itemsCount) => {
42
+ const [adjustedPosition, setAdjustedPosition] = useState({ openLeft: false, openUp: false, needsScroll: false, maxHeight: undefined });
43
+ const [isCalculated, setIsCalculated] = useState(false);
44
+ useLayoutEffect(() => {
45
+ if (!menuRef.current) {
46
+ setIsCalculated(false);
36
47
  return;
48
+ }
37
49
  const menuRect = menuRef.current.getBoundingClientRect();
38
50
  const viewportWidth = window.innerWidth;
39
51
  const viewportHeight = window.innerHeight;
52
+ const isMobile = viewportWidth <= 768;
40
53
  const spaceRight = viewportWidth - position.x;
41
54
  const spaceBottom = viewportHeight - position.y;
55
+ const spaceAbove = position.y;
56
+ const padding = 8; // Minimal padding from viewport edges - be more aggressive about using available space
57
+ // Use scrollHeight to get natural content height, not constrained height
58
+ const menuHeight = menuRef.current.scrollHeight;
59
+ // Mobile: Always calculate max-height based on position to prevent overflow
60
+ if (isMobile) {
61
+ const maxHeightFromBottom = spaceBottom - padding;
62
+ const maxHeightFromTop = spaceAbove - padding;
63
+ const mobileMaxHeight = Math.max(maxHeightFromBottom, maxHeightFromTop);
64
+ setAdjustedPosition({
65
+ openLeft: spaceRight < menuRect.width + 20,
66
+ openUp: maxHeightFromTop > maxHeightFromBottom && menuHeight > maxHeightFromBottom,
67
+ needsScroll: menuHeight > mobileMaxHeight,
68
+ maxHeight: mobileMaxHeight,
69
+ });
70
+ setIsCalculated(true);
71
+ return;
72
+ }
73
+ // Desktop: Check if menu is too tall to fit in either direction
74
+ const fitsBelow = menuHeight + padding <= spaceBottom;
75
+ const fitsAbove = menuHeight + padding <= spaceAbove;
76
+ const needsScroll = !fitsBelow && !fitsAbove;
77
+ // Calculate max height when scrolling is needed
78
+ let maxHeight = undefined;
79
+ let shouldOpenUp = false;
80
+ if (needsScroll) {
81
+ // When scrolling is needed, open in the direction with MORE space
82
+ const availableSpace = Math.max(spaceBottom, spaceAbove);
83
+ maxHeight = availableSpace - padding;
84
+ shouldOpenUp = spaceAbove > spaceBottom; // Open upward if more space above
85
+ }
86
+ else {
87
+ // Normal behavior: open up only if it fits above but not below
88
+ shouldOpenUp = !fitsBelow && fitsAbove;
89
+ }
42
90
  setAdjustedPosition({
43
91
  openLeft: spaceRight < menuRect.width + 20,
44
- openUp: spaceBottom < menuRect.height + 20,
92
+ openUp: shouldOpenUp,
93
+ needsScroll,
94
+ maxHeight,
45
95
  });
46
- }, [position, menuRef]);
47
- return adjustedPosition;
96
+ setIsCalculated(true);
97
+ }, [position, menuRef, itemsCount]); // Added itemsCount to recalculate when menu content changes
98
+ return { ...adjustedPosition, isCalculated };
99
+ };
100
+ export const getContextMenuTarget = (event, focusedItem, selectedItem, dataSource, idPrefix, isMobile) => {
101
+ if (!event)
102
+ return undefined;
103
+ let targetItem = focusedItem ?? selectedItem;
104
+ if (!focusedItem && isMobile) {
105
+ // Find the actual item that was long-pressed by traversing up from the event target
106
+ let element = event.target;
107
+ while (element && element !== event.currentTarget) {
108
+ if (element.id && element.id.startsWith(`${idPrefix}-`)) {
109
+ const itemId = element.id.replace(`${idPrefix}-`, '');
110
+ const foundItem = dataSource.find(item => item.id === itemId);
111
+ if (foundItem) {
112
+ targetItem = foundItem;
113
+ break;
114
+ }
115
+ }
116
+ element = element.parentElement;
117
+ }
118
+ }
119
+ return targetItem;
48
120
  };
@@ -1,2 +1,5 @@
1
1
  export { default as ContextMenu } from './TMContextMenu';
2
2
  export type { TMContextMenuItemProps, TMContextMenuProps } from './types';
3
+ export { useLongPress, triggerContextMenuEvent } from './useLongPress';
4
+ export type { UseLongPressOptions } from './useLongPress';
5
+ export { useIsIOS } from './hooks';
@@ -1 +1,3 @@
1
1
  export { default as ContextMenu } from './TMContextMenu';
2
+ export { useLongPress, triggerContextMenuEvent } from './useLongPress';
3
+ export { useIsIOS } from './hooks';
@@ -3,6 +3,10 @@ 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;
7
+ $externalControl?: boolean;
8
+ $needsScroll?: boolean;
9
+ $maxHeight?: number;
6
10
  }>> & string;
7
11
  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
12
  $disabled?: boolean;
@@ -12,13 +16,17 @@ export declare const MenuItem: import("styled-components/dist/types").IStyledCom
12
16
  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
17
  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
18
  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;
19
+ 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"> & {
20
+ 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;
21
+ }>, never>, never>> & string;
16
22
  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
23
  $isMobile?: boolean;
18
24
  }>> & string;
19
25
  export declare const Submenu: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
20
26
  $parentRect: DOMRect;
21
27
  $openUp?: boolean;
28
+ $needsScroll?: boolean;
29
+ $maxHeight?: number;
22
30
  }>> & string;
23
31
  export declare const MobileMenuHeader: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
24
32
  export declare const BackButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
@@ -25,7 +25,7 @@ export const MenuContainer = styled.div `
25
25
  right: ${props => props.$openLeft ? `${window.innerWidth - props.$x}px` : 'auto'};
26
26
  top: ${props => props.$openUp ? 'auto' : `${props.$y}px`};
27
27
  bottom: ${props => props.$openUp ? `${window.innerHeight - props.$y}px` : 'auto'};
28
- z-index: 10000;
28
+ z-index: 10100;
29
29
  background: #ffffff;
30
30
  border-radius: 12px;
31
31
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12),
@@ -36,6 +36,42 @@ 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
+ /* Add scrolling when menu is too tall to fit in either direction */
43
+ ${props => props.$needsScroll && props.$maxHeight && `
44
+ max-height: ${props.$maxHeight}px;
45
+ overflow-y: auto;
46
+ overflow-x: hidden;
47
+
48
+ /* Smooth scrolling */
49
+ scroll-behavior: smooth;
50
+
51
+ /* Custom scrollbar styling */
52
+ &::-webkit-scrollbar {
53
+ width: 8px;
54
+ }
55
+
56
+ &::-webkit-scrollbar-track {
57
+ background: rgba(0, 0, 0, 0.05);
58
+ border-radius: 4px;
59
+ }
60
+
61
+ &::-webkit-scrollbar-thumb {
62
+ background: rgba(0, 0, 0, 0.2);
63
+ border-radius: 4px;
64
+ }
65
+
66
+ &::-webkit-scrollbar-thumb:hover {
67
+ background: rgba(0, 0, 0, 0.3);
68
+ }
69
+ `}
70
+
71
+ /* Reset color inheritance from parent with !important to override panel header styles */
72
+ & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *) {
73
+ color: #1a1a1a !important;
74
+ }
39
75
 
40
76
  [data-theme='dark'] & {
41
77
  background: #2a2a2a;
@@ -43,18 +79,33 @@ export const MenuContainer = styled.div `
43
79
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4),
44
80
  0 2px 8px rgba(0, 0, 0, 0.3);
45
81
  }
82
+
83
+ [data-theme='dark'] & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *) {
84
+ color: #e0e0e0 !important;
85
+ }
86
+
87
+ ${props => props.$externalControl && `
88
+ @media (max-width: 768px) {
89
+ left: 75px !important;
90
+ right: 75px !important;
91
+ max-width: calc(100vw - 150px);
92
+ width: auto;
93
+ min-width: auto;
94
+ }
95
+ `}
46
96
  `;
47
97
  export const MenuItem = styled.div `
48
98
  display: flex;
49
99
  align-items: center;
50
100
  justify-content: space-between;
51
101
  padding: 4px 12px;
52
- cursor: ${props => props.$disabled ? 'not-allowed' : 'pointer'};
53
- opacity: ${props => props.$disabled ? 0.4 : 1};
102
+ cursor: ${props => props.$disabled ? 'default' : 'pointer'};
54
103
  transition: all 0.15s ease;
55
104
  position: relative;
56
105
  user-select: none;
57
- font-size: 13px;
106
+ -webkit-touch-callout: none;
107
+ -webkit-user-select: none;
108
+ font-size: var(--base-font-size, 13px);
58
109
  color: ${props => props.$disabled ? '#999' : '#1a1a1a'};
59
110
  font-weight: 500;
60
111
  ${props => props.$beginGroup && `
@@ -63,12 +114,26 @@ export const MenuItem = styled.div `
63
114
  padding-top: 8px;
64
115
  `}
65
116
 
117
+ /* Apply opacity only to direct children except right-icon-btn */
118
+ & > *:not(.right-icon-btn) {
119
+ opacity: ${props => props.$disabled ? 0.4 : 1};
120
+ }
121
+
122
+ /* Right icon button hidden by default, shown on hover */
123
+ & .right-icon-btn {
124
+ cursor: pointer !important;
125
+ }
126
+
66
127
  &:hover {
67
128
  ${props => !props.$disabled && `
68
129
  background: linear-gradient(90deg, #f0f7ff 0%, #e6f2ff 100%);
69
130
  color: #0066cc;
70
- padding-left: 14px;
71
131
  `}
132
+
133
+ /* Show right icon on hover */
134
+ & .right-icon-btn {
135
+ opacity: 1 !important;
136
+ }
72
137
  }
73
138
 
74
139
  &:active {
@@ -99,8 +164,8 @@ export const MenuItem = styled.div `
99
164
  }
100
165
 
101
166
  @media (max-width: 768px) {
102
- padding: 14px 16px;
103
- font-size: 15px;
167
+ padding: 4px 10px;
168
+ font-size: calc(var(--base-font-size, 13px) * 0.92);
104
169
  }
105
170
  `;
106
171
  export const MenuItemContent = styled.div `
@@ -113,7 +178,7 @@ export const IconWrapper = styled.span `
113
178
  display: flex;
114
179
  align-items: center;
115
180
  justify-content: center;
116
- font-size: 14px;
181
+ font-size: calc(var(--base-font-size, 13px) * 1.08);
117
182
  width: 18px;
118
183
  height: 18px;
119
184
  `;
@@ -124,23 +189,23 @@ export const MenuItemName = styled.span `
124
189
  overflow-wrap: break-word;
125
190
  line-height: 1.4;
126
191
  `;
127
- export const RightIconButton = styled.button `
192
+ export const RightIconButton = styled.button.attrs({
193
+ className: 'right-icon-btn'
194
+ }) `
128
195
  display: flex;
129
196
  align-items: center;
130
197
  justify-content: center;
131
198
  background: transparent;
132
199
  border: none;
133
- cursor: pointer;
200
+ cursor: pointer !important;
134
201
  padding: 4px 8px;
135
202
  margin-left: 8px;
136
203
  border-radius: 6px;
137
- color: inherit;
138
- font-size: 14px;
139
- opacity: 0.6;
140
- transition: all 0.15s ease;
204
+ font-size: calc(var(--base-font-size, 13px) * 1.08);
205
+ opacity: 0 !important;
206
+ transition: opacity 0.15s ease, background 0.15s ease, transform 0.15s ease;
141
207
 
142
208
  &:hover {
143
- opacity: 1;
144
209
  background: rgba(0, 0, 0, 0.05);
145
210
  transform: scale(1.1);
146
211
  }
@@ -158,12 +223,12 @@ export const RightIconButton = styled.button `
158
223
  export const SubmenuIndicator = styled.span `
159
224
  display: flex;
160
225
  align-items: center;
161
- font-size: 12px;
226
+ font-size: calc(var(--base-font-size, 13px) * 0.92);
162
227
  margin-left: 8px;
163
228
  opacity: 0.6;
164
229
  transition: transform 0.15s ease;
165
230
 
166
- ${MenuItem}:hover & {
231
+ ${MenuItem}:hover:not([data-disabled="true"]) & {
167
232
  ${props => !props.$isMobile && `
168
233
  transform: translateX(2px);
169
234
  opacity: 1;
@@ -189,7 +254,7 @@ export const Submenu = styled.div `
189
254
  // If openUp is true, anchor to bottom and grow upward
190
255
  return props.$openUp ? `${globalThis.innerHeight - props.$parentRect.bottom - 8}px` : 'auto';
191
256
  }};
192
- z-index: 10001;
257
+ z-index: 10101;
193
258
  background: #ffffff;
194
259
  border-radius: 12px;
195
260
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12),
@@ -223,17 +288,89 @@ export const Submenu = styled.div `
223
288
  background: transparent;
224
289
  }
225
290
 
291
+ /* Reset color inheritance from parent with !important to override panel header styles */
292
+ & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *) {
293
+ color: #1a1a1a !important;
294
+ }
295
+
226
296
  [data-theme='dark'] & {
227
297
  background: #2a2a2a;
228
298
  border-color: rgba(255, 255, 255, 0.1);
229
299
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4),
230
300
  0 2px 8px rgba(0, 0, 0, 0.3);
231
301
  }
302
+
303
+ [data-theme='dark'] & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *) {
304
+ color: #e0e0e0 !important;
305
+ }
306
+
307
+ /* Dynamic scroll handling when submenu is too tall */
308
+ ${props => props.$needsScroll && props.$maxHeight ? `
309
+ max-height: ${props.$maxHeight}px;
310
+ overflow-y: auto;
311
+ overflow-x: hidden;
312
+
313
+ /* Custom scrollbar styling for submenus */
314
+ &::-webkit-scrollbar {
315
+ width: 8px;
316
+ }
317
+
318
+ &::-webkit-scrollbar-track {
319
+ background: rgba(0, 0, 0, 0.05);
320
+ border-radius: 4px;
321
+ }
322
+
323
+ &::-webkit-scrollbar-thumb {
324
+ background: rgba(0, 0, 0, 0.2);
325
+ border-radius: 4px;
326
+ }
327
+
328
+ &::-webkit-scrollbar-thumb:hover {
329
+ background: rgba(0, 0, 0, 0.3);
330
+ }
331
+ ` : `
332
+ /* Fallback max-height for submenus that fit */
333
+ max-height: calc(100vh - 40px);
334
+ overflow-y: auto;
335
+ overflow-x: hidden;
336
+
337
+ &::-webkit-scrollbar {
338
+ width: 8px;
339
+ }
340
+
341
+ &::-webkit-scrollbar-track {
342
+ background: rgba(0, 0, 0, 0.05);
343
+ border-radius: 4px;
344
+ }
345
+
346
+ &::-webkit-scrollbar-thumb {
347
+ background: rgba(0, 0, 0, 0.2);
348
+ border-radius: 4px;
349
+ }
350
+
351
+ &::-webkit-scrollbar-thumb:hover {
352
+ background: rgba(0, 0, 0, 0.3);
353
+ }
354
+ `}
355
+
356
+ [data-theme='dark'] & {
357
+ &::-webkit-scrollbar-track {
358
+ background: rgba(255, 255, 255, 0.05);
359
+ }
360
+
361
+ &::-webkit-scrollbar-thumb {
362
+ background: rgba(255, 255, 255, 0.2);
363
+ }
364
+
365
+ &::-webkit-scrollbar-thumb:hover {
366
+ background: rgba(255, 255, 255, 0.3);
367
+ }
368
+ }
232
369
  `;
233
370
  export const MobileMenuHeader = styled.div `
234
371
  display: flex;
235
372
  align-items: center;
236
- padding: 12px 16px;
373
+ padding: 4px 8px;
237
374
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
238
375
  margin-bottom: 8px;
239
376
  gap: 12px;
@@ -249,37 +386,22 @@ export const BackButton = styled.button `
249
386
  display: flex;
250
387
  align-items: center;
251
388
  justify-content: center;
252
- background: #0066cc;
253
- color: white;
254
389
  border: none;
255
390
  border-radius: 8px;
256
391
  width: 32px;
257
392
  height: 32px;
258
393
  cursor: pointer;
259
- font-size: 18px;
260
394
  transition: all 0.15s ease;
261
-
262
- &:hover {
263
- background: #0052a3;
264
- transform: scale(1.05);
265
- }
395
+ font-size: 16px;
396
+ transform: translateY(-2px);
266
397
 
267
398
  &:active {
268
399
  transform: scale(0.95);
269
400
  }
270
-
271
- [data-theme='dark'] & {
272
- background: #4db8ff;
273
- color: #1a1a1a;
274
-
275
- &:hover {
276
- background: #66c2ff;
277
- }
278
- }
279
401
  `;
280
402
  export const HeaderTitle = styled.h3 `
281
403
  margin: 0;
282
- font-size: 16px;
404
+ font-size: calc(var(--base-font-size, 13px) * 1.23);
283
405
  font-weight: 600;
284
406
  color: #1a1a1a;
285
407
  flex: 1;
@@ -1,18 +1,37 @@
1
+ export interface RightIconProps {
2
+ icon: React.ReactNode;
3
+ activeColor?: string;
4
+ inactiveColor?: string;
5
+ isActive?: boolean;
6
+ onClick?: () => void;
7
+ }
1
8
  export interface TMContextMenuItemProps {
9
+ id?: string;
2
10
  name: string;
3
11
  icon?: React.ReactNode;
4
12
  disabled?: boolean;
5
- onClick?: () => void;
13
+ onClick?: (data?: any) => void;
6
14
  submenu?: TMContextMenuItemProps[];
7
15
  visible?: boolean;
8
- rightIcon?: React.ReactNode;
9
- onRightIconClick?: () => void;
16
+ rightIconProps?: RightIconProps;
10
17
  beginGroup?: boolean;
18
+ tooltip?: string;
19
+ operationType?: 'singleRow' | 'multiRow';
11
20
  }
12
21
  export interface TMContextMenuProps {
13
22
  items: TMContextMenuItemProps[];
14
23
  trigger?: 'right' | 'left';
15
24
  children?: React.ReactNode;
25
+ target?: string;
26
+ externalControl?: {
27
+ visible: boolean;
28
+ position: {
29
+ x: number;
30
+ y: number;
31
+ };
32
+ onClose: () => void;
33
+ };
34
+ keepOpenOnClick?: boolean;
16
35
  }
17
36
  export interface Position {
18
37
  x: number;
@@ -0,0 +1,21 @@
1
+ export interface UseLongPressOptions {
2
+ containerRef: React.RefObject<HTMLElement>;
3
+ targetSelector: string | string[];
4
+ onLongPress: (event: {
5
+ clientX: number;
6
+ clientY: number;
7
+ target: HTMLElement;
8
+ }) => void;
9
+ onTouchStart?: (event: {
10
+ clientX: number;
11
+ clientY: number;
12
+ target: HTMLElement;
13
+ rowElement: HTMLElement;
14
+ }) => void;
15
+ duration?: number;
16
+ moveThreshold?: number;
17
+ hapticFeedback?: boolean;
18
+ enabled?: boolean;
19
+ }
20
+ export declare function useLongPress({ containerRef, targetSelector, onLongPress, onTouchStart, duration, moveThreshold, hapticFeedback, enabled, }: UseLongPressOptions): void;
21
+ export declare function triggerContextMenuEvent(target: HTMLElement, clientX: number, clientY: number): void;
@@ -0,0 +1,112 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { useIsIOS } from './hooks';
3
+ export function useLongPress({ containerRef, targetSelector, onLongPress, onTouchStart, duration = 500, moveThreshold = 10, hapticFeedback = true, enabled = true, }) {
4
+ const isIOS = useIsIOS();
5
+ const longPressTriggeredRef = useRef(false);
6
+ useEffect(() => {
7
+ if (!isIOS || !enabled || !containerRef.current)
8
+ return;
9
+ const container = containerRef.current;
10
+ let longPressTimeout = null;
11
+ let touchStartPos = null;
12
+ let longPressTarget = null;
13
+ const matchesSelector = (element) => {
14
+ const selectors = Array.isArray(targetSelector) ? targetSelector : [targetSelector];
15
+ for (const selector of selectors) {
16
+ const match = element.closest(selector);
17
+ if (match)
18
+ return match;
19
+ }
20
+ return null;
21
+ };
22
+ const handleTouchStart = (e) => {
23
+ const touch = e.touches[0];
24
+ const target = touch.target;
25
+ // Check if target matches any of the specified selectors
26
+ const matchedElement = matchesSelector(target);
27
+ if (!matchedElement)
28
+ return;
29
+ touchStartPos = { x: touch.clientX, y: touch.clientY };
30
+ longPressTriggeredRef.current = false;
31
+ longPressTarget = target;
32
+ // Call optional onTouchStart callback
33
+ if (onTouchStart) {
34
+ onTouchStart({
35
+ clientX: touch.clientX,
36
+ clientY: touch.clientY,
37
+ target,
38
+ rowElement: matchedElement,
39
+ });
40
+ }
41
+ if (longPressTimeout)
42
+ clearTimeout(longPressTimeout);
43
+ longPressTimeout = setTimeout(() => {
44
+ longPressTriggeredRef.current = true;
45
+ // Haptic feedback
46
+ if (hapticFeedback && 'vibrate' in navigator) {
47
+ navigator.vibrate(50);
48
+ }
49
+ // Call onLongPress callback
50
+ onLongPress({
51
+ clientX: touch.clientX,
52
+ clientY: touch.clientY,
53
+ target: longPressTarget,
54
+ });
55
+ longPressTimeout = null;
56
+ }, duration);
57
+ };
58
+ const handleTouchMove = (e) => {
59
+ if (!touchStartPos || !longPressTimeout)
60
+ return;
61
+ const touch = e.touches[0];
62
+ const dx = Math.abs(touch.clientX - touchStartPos.x);
63
+ const dy = Math.abs(touch.clientY - touchStartPos.y);
64
+ // Cancel long-press if finger moved too much
65
+ if (dx > moveThreshold || dy > moveThreshold) {
66
+ clearTimeout(longPressTimeout);
67
+ longPressTimeout = null;
68
+ }
69
+ };
70
+ const handleTouchEnd = () => {
71
+ if (longPressTimeout) {
72
+ clearTimeout(longPressTimeout);
73
+ longPressTimeout = null;
74
+ }
75
+ touchStartPos = null;
76
+ longPressTarget = null;
77
+ };
78
+ // Prevent click after long-press to avoid unintended actions
79
+ const handleClick = (e) => {
80
+ if (longPressTriggeredRef.current) {
81
+ e.preventDefault();
82
+ e.stopPropagation();
83
+ e.stopImmediatePropagation();
84
+ longPressTriggeredRef.current = false;
85
+ }
86
+ };
87
+ container.addEventListener('touchstart', handleTouchStart, { passive: true });
88
+ container.addEventListener('touchmove', handleTouchMove, { passive: true });
89
+ container.addEventListener('touchend', handleTouchEnd);
90
+ container.addEventListener('touchcancel', handleTouchEnd);
91
+ container.addEventListener('click', handleClick, { capture: true });
92
+ return () => {
93
+ if (longPressTimeout)
94
+ clearTimeout(longPressTimeout);
95
+ container.removeEventListener('touchstart', handleTouchStart);
96
+ container.removeEventListener('touchmove', handleTouchMove);
97
+ container.removeEventListener('touchend', handleTouchEnd);
98
+ container.removeEventListener('touchcancel', handleTouchEnd);
99
+ container.removeEventListener('click', handleClick, { capture: true });
100
+ };
101
+ }, [isIOS, enabled, containerRef, targetSelector, onLongPress, onTouchStart, duration, moveThreshold, hapticFeedback]);
102
+ }
103
+ export function triggerContextMenuEvent(target, clientX, clientY) {
104
+ const contextMenuEvent = new MouseEvent('contextmenu', {
105
+ bubbles: true,
106
+ cancelable: true,
107
+ clientX,
108
+ clientY,
109
+ button: 2,
110
+ });
111
+ target.dispatchEvent(contextMenuEvent);
112
+ }