@topconsultnpm/sdkui-react 6.20.0-test1 → 6.21.0-dev1.10

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 (127) hide show
  1. package/lib/components/NewComponents/ContextMenu/styles.d.ts +3 -1
  2. package/lib/components/NewComponents/ContextMenu/styles.js +7 -5
  3. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +7 -1
  4. package/lib/components/base/Styled.d.ts +4 -1
  5. package/lib/components/base/Styled.js +11 -3
  6. package/lib/components/base/TMPanel.js +6 -4
  7. package/lib/components/base/TMPopUp.js +4 -0
  8. package/lib/components/base/TMTreeView.d.ts +5 -2
  9. package/lib/components/base/TMTreeView.js +74 -22
  10. package/lib/components/base/TMWaitPanel.js +6 -5
  11. package/lib/components/choosers/TMDataListItemChooser.js +1 -1
  12. package/lib/components/choosers/TMDataListItemEditor.d.ts +11 -0
  13. package/lib/components/choosers/TMDataListItemEditor.js +130 -0
  14. package/lib/components/choosers/TMDataListItemFields.d.ts +11 -0
  15. package/lib/components/choosers/TMDataListItemFields.js +61 -0
  16. package/lib/components/choosers/TMDataListItemPicker.d.ts +2 -0
  17. package/lib/components/choosers/TMDataListItemPicker.js +182 -18
  18. package/lib/components/choosers/TMDynDataListItemChooser.js +11 -6
  19. package/lib/components/choosers/TMImageIDChooser.d.ts +16 -0
  20. package/lib/components/choosers/TMImageIDChooser.js +53 -0
  21. package/lib/components/choosers/TMMetadataChooser.js +1 -1
  22. package/lib/components/choosers/TMUserChooser.js +4 -2
  23. package/lib/components/editors/TMDateBox.js +1 -1
  24. package/lib/components/editors/TMHtmlEditor.js +1 -1
  25. package/lib/components/editors/TMLocalizedTextBox.d.ts +1 -0
  26. package/lib/components/editors/TMLocalizedTextBox.js +3 -3
  27. package/lib/components/editors/TMMetadataValues.js +203 -41
  28. package/lib/components/editors/TMTextArea.d.ts +1 -0
  29. package/lib/components/editors/TMTextArea.js +6 -6
  30. package/lib/components/editors/TMTextBox.js +9 -10
  31. package/lib/components/features/archive/TMArchive.d.ts +3 -1
  32. package/lib/components/features/archive/TMArchive.js +31 -44
  33. package/lib/components/features/blog/TMBlogCommentForm.d.ts +3 -0
  34. package/lib/components/features/blog/TMBlogCommentForm.js +42 -36
  35. package/lib/components/features/documents/TMDcmtBlog.d.ts +1 -0
  36. package/lib/components/features/documents/TMDcmtBlog.js +2 -1
  37. package/lib/components/features/documents/TMDcmtForm.d.ts +44 -34
  38. package/lib/components/features/documents/TMDcmtForm.js +367 -565
  39. package/lib/components/features/documents/TMDcmtFormActionButtons.d.ts +34 -0
  40. package/lib/components/features/documents/TMDcmtFormActionButtons.js +124 -0
  41. package/lib/components/features/documents/TMDcmtPreview.js +66 -13
  42. package/lib/components/features/documents/TMDcmtTasks.d.ts +3 -1
  43. package/lib/components/features/documents/TMDcmtTasks.js +2 -2
  44. package/lib/components/features/documents/TMFileUploader.d.ts +5 -0
  45. package/lib/components/features/documents/TMFileUploader.js +28 -6
  46. package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +27 -2
  47. package/lib/components/features/documents/TMMasterDetailDcmts.js +264 -97
  48. package/lib/components/features/documents/TMRelationViewer.d.ts +19 -2
  49. package/lib/components/features/documents/TMRelationViewer.js +540 -116
  50. package/lib/components/features/search/TMSearch.d.ts +3 -2
  51. package/lib/components/features/search/TMSearch.js +3 -3
  52. package/lib/components/features/search/TMSearchQueryPanel.js +6 -6
  53. package/lib/components/features/search/TMSearchResult.d.ts +29 -25
  54. package/lib/components/features/search/TMSearchResult.js +446 -562
  55. package/lib/components/features/search/TMSignatureInfoContent.js +10 -6
  56. package/lib/components/features/search/TMTreeSelector.js +1 -1
  57. package/lib/components/features/tasks/TMTaskForm.d.ts +3 -1
  58. package/lib/components/features/tasks/TMTaskForm.js +61 -193
  59. package/lib/components/features/tasks/TMTaskFormUtils.d.ts +80 -0
  60. package/lib/components/features/tasks/TMTaskFormUtils.js +559 -0
  61. package/lib/components/features/tasks/TMTasksUtils.d.ts +3 -1
  62. package/lib/components/features/tasks/TMTasksUtils.js +46 -16
  63. package/lib/components/features/tasks/TMTasksUtilsView.d.ts +0 -7
  64. package/lib/components/features/tasks/TMTasksUtilsView.js +7 -14
  65. package/lib/components/features/tasks/TMTasksView.js +5 -3
  66. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +20 -3
  67. package/lib/components/features/workflow/TMWorkflowPopup.js +21 -109
  68. package/lib/components/features/workflow/diagram/ConnectionComponent.d.ts +1 -0
  69. package/lib/components/features/workflow/diagram/ConnectionComponent.js +6 -2
  70. package/lib/components/features/workflow/diagram/DiagramItemForm.d.ts +2 -0
  71. package/lib/components/features/workflow/diagram/DiagramItemForm.js +32 -25
  72. package/lib/components/features/workflow/diagram/RecipientList.d.ts +3 -1
  73. package/lib/components/features/workflow/diagram/RecipientList.js +13 -9
  74. package/lib/components/features/workflow/diagram/WFDiagram.js +102 -5
  75. package/lib/components/features/workflow/diagram/workflowHelpers.js +31 -19
  76. package/lib/components/forms/Login/TMLoginForm.js +1 -1
  77. package/lib/components/forms/TMSaveForm.js +61 -13
  78. package/lib/components/grids/TMBlogsPost.js +8 -8
  79. package/lib/components/grids/TMBlogsPostUtils.js +2 -2
  80. package/lib/components/grids/TMRecentsManager.js +1 -1
  81. package/lib/components/index.d.ts +2 -0
  82. package/lib/components/index.js +2 -0
  83. package/lib/components/layout/panelManager/TMPanelManagerContainer.js +3 -2
  84. package/lib/components/pages/TMPage.js +4 -0
  85. package/lib/components/query/TMQueryEditor.d.ts +1 -0
  86. package/lib/components/query/TMQueryEditor.js +3 -3
  87. package/lib/components/viewers/TMMidViewer.js +2 -1
  88. package/lib/components/viewers/TMTidViewer.js +7 -3
  89. package/lib/helper/Enum_Localizator.js +5 -0
  90. package/lib/helper/GlobalStyles.js +3 -0
  91. package/lib/helper/SDKUI_Globals.d.ts +12 -0
  92. package/lib/helper/SDKUI_Globals.js +21 -1
  93. package/lib/helper/SDKUI_Localizator.d.ts +31 -7
  94. package/lib/helper/SDKUI_Localizator.js +286 -46
  95. package/lib/helper/TMIcons.d.ts +2 -1
  96. package/lib/helper/TMIcons.js +4 -1
  97. package/lib/helper/TMUtils.d.ts +33 -41
  98. package/lib/helper/TMUtils.js +157 -170
  99. package/lib/helper/checkinCheckoutManager.d.ts +1 -1
  100. package/lib/helper/checkinCheckoutManager.js +25 -6
  101. package/lib/helper/helpers.d.ts +6 -2
  102. package/lib/helper/helpers.js +24 -8
  103. package/lib/helper/index.d.ts +1 -0
  104. package/lib/helper/index.js +1 -0
  105. package/lib/helper/queryHelper.js +1 -1
  106. package/lib/hooks/useBetaFeatures.d.ts +1 -0
  107. package/lib/hooks/useBetaFeatures.js +41 -0
  108. package/lib/hooks/useCheckInOutOperations.d.ts +7 -6
  109. package/lib/hooks/useCheckInOutOperations.js +9 -16
  110. package/lib/hooks/useDataUserIdItem.js +2 -2
  111. package/lib/hooks/useDcmtOperations.d.ts +3 -2
  112. package/lib/hooks/useDcmtOperations.js +16 -4
  113. package/lib/hooks/useDocumentOperations.d.ts +140 -0
  114. package/lib/hooks/useDocumentOperations.js +1307 -0
  115. package/lib/hooks/useRelatedDocuments.d.ts +1 -1
  116. package/lib/hooks/useRelatedDocuments.js +64 -42
  117. package/lib/index.d.ts +1 -0
  118. package/lib/index.js +1 -0
  119. package/lib/services/platform_services.d.ts +1 -1
  120. package/lib/services/platform_services.js +4 -0
  121. package/lib/ts/types.d.ts +5 -1
  122. package/lib/ts/types.js +1 -0
  123. package/package.json +2 -2
  124. package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +0 -11
  125. package/lib/components/features/search/TMSearchResultsMenuItems.js +0 -770
  126. package/lib/components/features/search/TMSignSettingsForm.d.ts +0 -9
  127. package/lib/components/features/search/TMSignSettingsForm.js +0 -621
@@ -14,7 +14,9 @@ export declare const MenuItem: import("styled-components/dist/types").IStyledCom
14
14
  $beginGroup?: boolean;
15
15
  }>> & string;
16
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;
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;
17
+ export declare const IconWrapper: 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").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & {
18
+ ref?: ((instance: HTMLSpanElement | 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<HTMLSpanElement> | null | undefined;
19
+ }>, never>, never>> & string;
18
20
  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;
19
21
  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
22
  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;
@@ -69,7 +69,7 @@ export const MenuContainer = styled.div `
69
69
  `}
70
70
 
71
71
  /* Reset color inheritance from parent with !important to override panel header styles */
72
- & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *) {
72
+ & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *):not(.icon-wrapper):not(.icon-wrapper *) {
73
73
  color: #1a1a1a !important;
74
74
  }
75
75
 
@@ -80,7 +80,7 @@ export const MenuContainer = styled.div `
80
80
  0 2px 8px rgba(0, 0, 0, 0.3);
81
81
  }
82
82
 
83
- [data-theme='dark'] & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *) {
83
+ [data-theme='dark'] & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *):not(.icon-wrapper):not(.icon-wrapper *) {
84
84
  color: #e0e0e0 !important;
85
85
  }
86
86
 
@@ -174,7 +174,9 @@ export const MenuItemContent = styled.div `
174
174
  gap: 10px;
175
175
  flex: 1;
176
176
  `;
177
- export const IconWrapper = styled.span `
177
+ export const IconWrapper = styled.span.attrs({
178
+ className: 'icon-wrapper'
179
+ }) `
178
180
  display: flex;
179
181
  align-items: center;
180
182
  justify-content: center;
@@ -289,7 +291,7 @@ export const Submenu = styled.div `
289
291
  }
290
292
 
291
293
  /* Reset color inheritance from parent with !important to override panel header styles */
292
- & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *) {
294
+ & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *):not(.icon-wrapper):not(.icon-wrapper *) {
293
295
  color: #1a1a1a !important;
294
296
  }
295
297
 
@@ -300,7 +302,7 @@ export const Submenu = styled.div `
300
302
  0 2px 8px rgba(0, 0, 0, 0.3);
301
303
  }
302
304
 
303
- [data-theme='dark'] & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *) {
305
+ [data-theme='dark'] & *:not(svg):not(.right-icon-btn):not(.right-icon-btn *):not(.icon-wrapper):not(.icon-wrapper *) {
304
306
  color: #e0e0e0 !important;
305
307
  }
306
308
 
@@ -146,6 +146,7 @@ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], isConstrained
146
146
  const isLocalChange = useRef(false);
147
147
  const dragStartPosition = useRef(null);
148
148
  const isItemsInitialized = useRef(false);
149
+ const hasReceivedNonEmptyExternalIds = useRef(false);
149
150
  useEffect(() => {
150
151
  floatingBarItemIds.current = new Set(state.items.map(i => i.id));
151
152
  floatingBarItemNames.current = new Set(state.items.map(i => i.name));
@@ -264,9 +265,14 @@ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], isConstrained
264
265
  }
265
266
  if (externalPinnedItemIds === undefined || !enableConfigMode)
266
267
  return;
268
+ // Track if we've ever received non-empty external IDs
269
+ if (externalPinnedItemIds.length > 0) {
270
+ hasReceivedNonEmptyExternalIds.current = true;
271
+ }
267
272
  // Skip sync if external is empty but we have initialized items (first login case)
268
273
  // The parent hook starts with [] but we've initialized with defaults
269
- if (externalPinnedItemIds.length === 0 && state.items.length > 0)
274
+ // However, once we've received non-empty pinnedItemIds, an empty array means user removed all items
275
+ if (externalPinnedItemIds.length === 0 && state.items.length > 0 && !hasReceivedNonEmptyExternalIds.current)
270
276
  return;
271
277
  const flatItems = flattenMenuItems(contextMenuItems);
272
278
  // Build items from external pinned IDs
@@ -7,7 +7,10 @@ export declare const StyledMultiViewPanel: import("styled-components/dist/types"
7
7
  }>> & string;
8
8
  export declare const StyledParagraph: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, never>> & string;
9
9
  export declare const StyledToolbarForm: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
10
- export declare const StyledReferenceButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
10
+ export declare const ReferencesContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
11
+ export declare const StyledReferenceButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {
12
+ $bgColor?: string;
13
+ }>> & string;
11
14
  export declare const StyledPanelPage: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
12
15
  $isOpen?: boolean;
13
16
  $padding?: string;
@@ -36,17 +36,25 @@ export const StyledToolbarForm = styled.div `
36
36
  gap: 2px;
37
37
  background-color: ${TMColors.toolbar_background};
38
38
  `;
39
+ export const ReferencesContainer = styled.div `
40
+ display: flex;
41
+ justify-content: center;
42
+ gap: 12px;
43
+ flex-wrap: wrap;
44
+ width: 100%;
45
+ height: 100%;
46
+ `;
39
47
  export const StyledReferenceButton = styled.button `
40
48
  display: flex;
41
49
  flex-direction: column;
42
50
  align-items: center;
43
51
  justify-content: center;
44
- padding: 10px 16px;
52
+ padding: 10px 25px;
45
53
  border-radius: 20px;
46
54
  border: none;
47
- background-color: ${TMColors.button_floating_background};
55
+ background-color: ${({ $bgColor }) => $bgColor || TMColors.button_floating_background};
48
56
  color: white;
49
- font-size: 0.9rem;
57
+ font-size: 0.95rem;
50
58
  font-weight: 500;
51
59
  cursor: pointer;
52
60
  transition: all 0.2s ease;
@@ -5,9 +5,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
5
  */
6
6
  import { useCallback, useRef, useState, forwardRef, useImperativeHandle } from 'react';
7
7
  import styled from 'styled-components';
8
- import { IconArrowLeft, IconClearButton, IconWindowMaximize, IconWindowMinimize, isPositiveNumber, SDKUI_Localizator } from '../../helper';
8
+ import { getAppModuleGradient, IconArrowLeft, IconClearButton, IconWindowMaximize, IconWindowMinimize, isPositiveNumber, SDKUI_Localizator } from '../../helper';
9
9
  import TMButton from './TMButton';
10
10
  import { Gutters } from '../../utils/theme';
11
+ import { AppModules, SDK_Globals } from '@topconsultnpm/sdk-ts';
11
12
  const StyledPanelContainer = styled.div `
12
13
  width: 100%;
13
14
  height: 100%;
@@ -34,8 +35,9 @@ const StyledPanelHeader = styled.div `
34
35
  align-items: center;
35
36
  justify-content: flex-start;
36
37
  padding: 4px 10px;
37
- background: ${({ $isActive, $backgroundColor }) => $isActive
38
- ? 'linear-gradient(270deg, #46B5A2 16%, #3BAABC 34%, #3BAABC 34%, #3681AD 54%, #3368A5 72%, #2F549D 88%, #304F99 100%)'
38
+ background: ${({ $isActive, $backgroundColor, $activeGradient }) => $isActive
39
+ ? ($activeGradient ??
40
+ 'linear-gradient(270deg, #46B5A2 16%, #3BAABC 34%, #3BAABC 34%, #3681AD 54%, #3368A5 72%, #2F549D 88%, #304F99 100%)')
39
41
  : ($backgroundColor ?? '#F4F4F4')};
40
42
  box-shadow: 3px 3px 5px #D3D3D3BF;
41
43
  color: ${({ $isActive, $color }) => $isActive ? '#FFFFFF' : ($color ?? '#2559A5')};
@@ -141,7 +143,7 @@ onActivate, onBack, onClose, onHeaderDoubleClick, onMaximize, onActiveChanged },
141
143
  onHeaderDoubleClick();
142
144
  else
143
145
  allowMaximize && handleMaximize();
144
- }, children: _jsxs("div", { style: {
146
+ }, "$activeGradient": getAppModuleGradient(SDK_Globals.tmSession?.SessionDescr?.appModuleID ?? AppModules.SURFER), children: _jsxs("div", { style: {
145
147
  display: 'flex',
146
148
  flexDirection: 'row',
147
149
  alignItems: 'center',
@@ -258,6 +258,10 @@ const TMMessageBox = ({ resizable = false, onButtonClick, title = 'TopMedia', me
258
258
  const el = document.getElementById('tm-messagebox-wrapper');
259
259
  if (el)
260
260
  el.style.zIndex = '20000';
261
+ // Blocca traduzione sul titolo
262
+ const titleEl = el?.querySelector('.dx-popup-title');
263
+ if (titleEl)
264
+ titleEl.setAttribute('translate', 'no');
261
265
  }, onResizeEnd: handleResizeEnd, wrapperAttr: { id: 'tm-messagebox-wrapper' }, children: _jsx(ResponsiveMessageBody, { message: message, isMobile: isMobile, MessageToolbar: MessageToolbar, showToppy: showToppy }) }));
262
266
  };
263
267
  const TMExceptionBox = ({ resizable = false, exception, title = `${SDK_Globals.appModule} v. ${SDK_Globals.appVersion}`, onClose }) => {
@@ -6,8 +6,9 @@ export interface ITMTreeItem {
6
6
  hidden?: boolean;
7
7
  isLoaded?: boolean;
8
8
  isContainer: boolean;
9
+ isExpandible?: boolean;
9
10
  items?: ITMTreeItem[];
10
- visibleItemsCount?: number;
11
+ currentPage?: number;
11
12
  totalItemsCount?: number;
12
13
  }
13
14
  interface ITMTreeViewProps<T extends ITMTreeItem> {
@@ -22,12 +23,14 @@ interface ITMTreeViewProps<T extends ITMTreeItem> {
22
23
  onNodeUpdate?: (updatedNode: T) => void;
23
24
  onDataChanged?: (items: T[]) => void;
24
25
  shouldDelayFocusOnEvent?: (node: T, event: React.MouseEvent) => boolean;
26
+ onItemContextMenu?: (item: T, e: React.MouseEvent) => void;
25
27
  autoSelectChildren?: boolean;
26
28
  itemsPerPage?: number;
27
29
  showLoadMoreButton?: boolean;
28
30
  }
29
- declare const TMTreeView: <T extends ITMTreeItem>({ dataSource, focusedItem, selectedItems, allowMultipleSelection, onDataChanged, calculateItemsForNode, itemRender, onNodeUpdate, onFocusedItemChanged, onSelectionChanged, shouldDelayFocusOnEvent, autoSelectChildren, itemsPerPage, showLoadMoreButton }: ITMTreeViewProps<T>) => import("react/jsx-runtime").JSX.Element;
31
+ declare const TMTreeView: <T extends ITMTreeItem>({ dataSource, focusedItem, selectedItems, allowMultipleSelection, onDataChanged, calculateItemsForNode, itemRender, onNodeUpdate, onFocusedItemChanged, onSelectionChanged, shouldDelayFocusOnEvent, onItemContextMenu, autoSelectChildren, itemsPerPage, showLoadMoreButton }: ITMTreeViewProps<T>) => import("react/jsx-runtime").JSX.Element;
30
32
  export default TMTreeView;
31
33
  export declare const StyledTreeNode: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
32
34
  $isSelected?: boolean;
33
35
  }>> & string;
36
+ export declare const StyledStickyPaginator: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useRef } from 'react';
3
3
  import styled from 'styled-components';
4
- import { IconChevronDown, IconChevronRight } from '../../helper';
4
+ import { IconArrowLeft, IconArrowRight, IconChevronDown, IconChevronRight, SDKUI_Localizator } from '../../helper';
5
5
  import TMButton from './TMButton';
6
- const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMultipleSelection, onDataChanged, calculateItemsForNode, itemRender, onNodeUpdate, onFocusedItemChanged, onSelectionChanged, shouldDelayFocusOnEvent, autoSelectChildren = true, itemsPerPage = 100, showLoadMoreButton = true }) => {
6
+ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMultipleSelection, onDataChanged, calculateItemsForNode, itemRender, onNodeUpdate, onFocusedItemChanged, onSelectionChanged, shouldDelayFocusOnEvent, onItemContextMenu, autoSelectChildren = true, itemsPerPage = 100, showLoadMoreButton = true }) => {
7
7
  useEffect(() => {
8
8
  const handleKeyDown = (event) => {
9
9
  if (!focusedItem)
@@ -85,7 +85,9 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
85
85
  let newItems = node.items;
86
86
  // Solo se calculateItemsForNode è definito E (ctrl è premuto O non è già caricato)
87
87
  if (calculateItemsForNode && (ctrlKey || !node.isLoaded)) {
88
- newItems = await calculateItemsForNode(node);
88
+ // Se ctrl è premuto, passa un nodo con isLoaded resettato per forzare il refresh
89
+ const nodeForCalculation = ctrlKey ? { ...node, isLoaded: false } : node;
90
+ newItems = await calculateItemsForNode(nodeForCalculation);
89
91
  const updatedNode = { ...node, expanded: true, items: newItems, isLoaded: true };
90
92
  onNodeUpdate?.(updatedNode);
91
93
  return updatedNode;
@@ -274,53 +276,62 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
274
276
  return childKeys.every(key => selectedChildKeys.includes(key));
275
277
  };
276
278
  const hasVisibleItems = (node) => {
279
+ // If node has explicit isExpandible value, use that
280
+ if (node.isExpandible !== undefined) {
281
+ return node.isExpandible;
282
+ }
283
+ // Fallback: check if node has visible items
277
284
  if (!node.items)
278
285
  return false;
279
286
  if (node.items.length <= 0)
280
287
  return false;
281
288
  return node.items.filter(o => !o.hidden).length > 0;
282
289
  };
283
- // Gestisce il caricamento di più items per un nodo
284
- const handleLoadMoreItems = useCallback((nodeKey) => {
285
- const updateNodeVisibleCount = (nodes) => {
290
+ // Gestisce il cambio di pagina per un nodo
291
+ const handlePageChange = useCallback((nodeKey, newPage) => {
292
+ const updateNodePage = (nodes) => {
286
293
  return nodes.map(node => {
287
294
  if (node.key === nodeKey) {
288
- const currentVisible = node.visibleItemsCount ?? itemsPerPage;
289
- const newVisible = Math.min(currentVisible + itemsPerPage, node.totalItemsCount ?? node.items?.length ?? 0);
290
- const updatedNode = { ...node, visibleItemsCount: newVisible };
295
+ const updatedNode = { ...node, currentPage: newPage };
291
296
  onNodeUpdate?.(updatedNode);
292
297
  return updatedNode;
293
298
  }
294
299
  if (node.items) {
295
- return { ...node, items: updateNodeVisibleCount(node.items) };
300
+ return { ...node, items: updateNodePage(node.items) };
296
301
  }
297
302
  return node;
298
303
  });
299
304
  };
300
- const updatedData = updateNodeVisibleCount(dataSource);
305
+ const updatedData = updateNodePage(dataSource);
301
306
  onDataChanged?.(updatedData);
302
- }, [dataSource, itemsPerPage, onDataChanged, onNodeUpdate]);
307
+ }, [dataSource, onDataChanged, onNodeUpdate]);
303
308
  // Filtra gli items da mostrare in base alla paginazione
304
309
  const getVisibleItems = useCallback((node) => {
305
310
  if (!node.items)
306
311
  return [];
307
312
  const totalItems = node.items.length;
308
- const visibleCount = node.visibleItemsCount ?? itemsPerPage;
309
313
  // Se non c'è paginazione attiva o gli items sono pochi, mostra tutti
310
314
  if (totalItems <= itemsPerPage || !showLoadMoreButton) {
311
315
  return node.items;
312
316
  }
313
- // Altrimenti mostra solo i primi N items
314
- return node.items.slice(0, visibleCount);
317
+ // Altrimenti mostra solo gli items della pagina corrente
318
+ const currentPage = node.currentPage ?? 0;
319
+ const startIndex = currentPage * itemsPerPage;
320
+ const endIndex = startIndex + itemsPerPage;
321
+ return node.items.slice(startIndex, endIndex);
315
322
  }, [itemsPerPage, showLoadMoreButton]);
316
- // Verifica se c'è bisogno del bottone "Load More"
317
- const needsLoadMoreButton = useCallback((node) => {
323
+ // Verifica se c'è bisogno del paginatore
324
+ const needsPagination = useCallback((node) => {
318
325
  if (!showLoadMoreButton || !node.items)
319
326
  return false;
320
- const totalItems = node.items.length;
321
- const visibleCount = node.visibleItemsCount ?? itemsPerPage;
322
- return totalItems > itemsPerPage && visibleCount < totalItems;
327
+ return node.items.length > itemsPerPage;
323
328
  }, [itemsPerPage, showLoadMoreButton]);
329
+ // Calcola il numero totale di pagine per un nodo
330
+ const getTotalPages = useCallback((node) => {
331
+ if (!node.items)
332
+ return 0;
333
+ return Math.ceil(node.items.length / itemsPerPage);
334
+ }, [itemsPerPage]);
324
335
  const renderTree = useCallback((nodes) => {
325
336
  return nodes.map(node => !node.hidden && (_jsxs("div", { style: { width: '100%', margin: 0, padding: 0 }, children: [_jsxs(StyledTreeNode, { "$isSelected": node.key === focusedItem?.key, children: [_jsx("div", { style: {
326
337
  display: 'flex',
@@ -339,8 +350,13 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
339
350
  if (input) {
340
351
  input.indeterminate = isIndeterminate(node);
341
352
  }
342
- } })), _jsx("div", { style: { display: 'flex', alignItems: 'center', flex: 1, minWidth: 0 }, onClick: (e) => { handleNodeClick(node, e); }, children: itemRender(node) })] }), node.expanded && node.items && (_jsxs("div", { style: { paddingLeft: 20, width: '100%' }, children: [renderTree(getVisibleItems(node)), needsLoadMoreButton(node) && (_jsx("div", { style: { display: 'flex', justifyContent: 'center', margin: '5px 0' }, children: _jsx(TMButton, { onClick: () => handleLoadMoreItems(node.key), showTooltip: false, caption: `Carica altri ${itemsPerPage}... (${node.visibleItemsCount ?? itemsPerPage} / ${node.items?.length ?? 0})` }) }))] }))] }, node.key)));
343
- }, [handleNodeClick, handleNodeToggle, handleCheckboxChange, focusedItem, selectedItems, allowMultipleSelection, getVisibleItems, needsLoadMoreButton, handleLoadMoreItems, itemsPerPage]);
353
+ } })), _jsx("div", { style: { display: 'flex', alignItems: 'center', flex: 1, minWidth: 0 }, onClick: (e) => { handleNodeClick(node, e); }, onContextMenu: (e) => {
354
+ if (onItemContextMenu) {
355
+ e.preventDefault();
356
+ onItemContextMenu(node, e);
357
+ }
358
+ }, children: itemRender(node) })] }), node.expanded && node.items && (_jsxs("div", { style: { paddingLeft: 20, width: '100%' }, children: [renderTree(getVisibleItems(node)), needsPagination(node) && (_jsxs(StyledStickyPaginator, { children: [_jsx(TMButton, { btnStyle: 'icon', onClick: () => handlePageChange(node.key, (node.currentPage ?? 0) - 1), showTooltip: false, caption: "\u25C4", icon: _jsx(IconArrowLeft, { color: 'white' }), disabled: (node.currentPage ?? 0) <= 0 }), _jsx("span", { style: { fontSize: '11px', whiteSpace: 'nowrap', fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', minWidth: 0, color: 'white' }, children: SDKUI_Localizator.PaginationInfo.replaceParams((node.currentPage ?? 0) + 1, getTotalPages(node), node.items?.length ?? 0) }), _jsx(TMButton, { btnStyle: 'icon', onClick: () => handlePageChange(node.key, (node.currentPage ?? 0) + 1), showTooltip: false, caption: "\u25BA", icon: _jsx(IconArrowRight, { color: 'white' }), disabled: (node.currentPage ?? 0) >= getTotalPages(node) - 1 })] }))] }))] }, node.key)));
359
+ }, [handleNodeClick, handleNodeToggle, handleCheckboxChange, focusedItem, selectedItems, allowMultipleSelection, getVisibleItems, needsPagination, handlePageChange, getTotalPages, onItemContextMenu]);
344
360
  return (_jsx("div", { style: { height: '100%', width: '100%', overflowY: 'auto', overflowX: 'hidden', padding: '0px 5px 2px 2px' }, children: renderTree(dataSource) }));
345
361
  };
346
362
  export default TMTreeView;
@@ -361,3 +377,39 @@ export const StyledTreeNode = styled.div `
361
377
  background: ${() => `oklch(from var(--dx-color-primary) l c h / .1)`};
362
378
  }
363
379
  `;
380
+ export const StyledStickyPaginator = styled.div `
381
+ position: sticky;
382
+ bottom: 0;
383
+ display: flex;
384
+ align-items: center;
385
+ justify-content: center;
386
+ width: fit-content;
387
+ margin: 3px auto;
388
+ gap: 15px;
389
+ padding: 4px 10px;
390
+ background: oklch(from var(--dx-color-primary) l c h / .85);
391
+ border: 1px solid oklch(from var(--dx-color-primary) l c h / .9);
392
+ border-radius: 3px;
393
+ box-shadow: 0 -1px 4px oklch(from var(--dx-color-primary) l c h / .15);
394
+ transition: all 0.2s ease;
395
+ min-width: 0;
396
+ z-index: 10;
397
+
398
+ & > button {
399
+ flex-shrink: 0;
400
+ min-width: 24px !important;
401
+ min-height: 20px !important;
402
+ padding: 2px 6px !important;
403
+ }
404
+
405
+ & > span {
406
+ flex: 1 1 auto;
407
+ min-width: 0;
408
+ }
409
+
410
+ &:hover {
411
+ background: oklch(from var(--dx-color-primary) l c h / .95);
412
+ border-color: oklch(from var(--dx-color-primary) l c h / 1);
413
+ box-shadow: 0 -1px 6px oklch(from var(--dx-color-primary) l c h / .2);
414
+ }
415
+ `;
@@ -33,17 +33,18 @@ const StyledProgressText = styled.p ` font-weight: bold; color: #333; margin: 0;
33
33
  const StyledMessage = styled.p ` color: #666; font-size: 0.9em; margin-top: 10px; `;
34
34
  const StyledAbortButton = styled.button ` background: #ff4d4d; color: white; border: none; border-radius: 5px; padding: 10px 20px; font-size: 1em; cursor: pointer; margin-top: 20px; &:hover { background: #ff6666; } `;
35
35
  export const TMWaitPanel = (props) => {
36
+ const { title, showPrimary, textPrimary, valuePrimary, maxValuePrimary, showSecondary, textSecondary, valueSecondary, maxValueSecondary, isCancelable, abortController, onAbortClick } = props;
36
37
  const calculateProgress = (value = 0, maxValue = 0) => {
37
38
  if (maxValue === 0)
38
39
  return 0;
39
40
  const progress = (value / maxValue) * 100;
40
41
  return Number.isFinite(progress) ? progress : 0;
41
42
  };
42
- let progressValue1 = calculateProgress(props.valuePrimary, props.maxValuePrimary);
43
- let progressValue2 = calculateProgress(props.valueSecondary, props.maxValueSecondary);
44
- return (_jsx(StyledWaitPanelOverlay, { children: _jsxs(StyledWaitPanel, { "$height": (props.showPrimary && props.showSecondary) ? '350px' : '250px', children: [_jsx(StyledTitle, { children: props.title }), props.showPrimary &&
45
- _jsxs("div", { style: { width: '100%', height: '100px' }, children: [_jsx(StyledProgressBarContainer, { children: _jsx(StyledProgressBar, { style: { width: `${progressValue1.toFixed(2)}%` } }) }), _jsxs(StyledProgressText, { children: [progressValue1.toFixed(2), "%"] }), _jsx(StyledMessage, { children: props.textPrimary })] }), props.showSecondary &&
46
- _jsxs("div", { style: { width: '100%', height: '100px' }, children: [_jsx(StyledProgressBarContainer, { children: _jsx(StyledProgressBar, { style: { width: `${progressValue2.toFixed(2)}%` } }) }), _jsxs(StyledProgressText, { children: [progressValue2.toFixed(2), "%"] }), _jsx(StyledMessage, { children: props.textSecondary })] }), props.isCancelable && _jsx(StyledAbortButton, { onClick: () => props.onAbortClick?.(props.abortController), children: SDKUI_Localizator.Abort })] }) }));
43
+ let progressValue1 = calculateProgress(valuePrimary, maxValuePrimary);
44
+ let progressValue2 = calculateProgress(valueSecondary, maxValueSecondary);
45
+ return (_jsx(StyledWaitPanelOverlay, { children: _jsxs(StyledWaitPanel, { "$height": (showPrimary && showSecondary) ? '350px' : '250px', children: [_jsx(StyledTitle, { children: title }), showPrimary &&
46
+ _jsxs("div", { style: { width: '100%', height: '100px' }, children: [_jsx(StyledProgressBarContainer, { children: _jsx(StyledProgressBar, { style: { width: `${progressValue1.toFixed(2)}%` } }) }), _jsxs(StyledProgressText, { children: [progressValue1.toFixed(2), "%"] }), _jsx(StyledMessage, { children: textPrimary })] }), showSecondary &&
47
+ _jsxs("div", { style: { width: '100%', height: '100px' }, children: [_jsx(StyledProgressBarContainer, { children: _jsx(StyledProgressBar, { style: { width: `${progressValue2.toFixed(2)}%` } }) }), _jsxs(StyledProgressText, { children: [progressValue2.toFixed(2), "%"] }), _jsx(StyledMessage, { children: textSecondary })] }), isCancelable && _jsx(StyledAbortButton, { onClick: () => onAbortClick?.(abortController), children: SDKUI_Localizator.Abort })] }) }));
47
48
  };
48
49
  export const TMLayoutWaitingContainer = ({ showWaitPanel, showWaitPanelPrimary, showWaitPanelSecondary, waitPanelTitle, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, isCancelable, abortController, gap = 3, onClick, justifyContent = 'flex-start', alignItems = 'flex-start', children, direction = 'vertical' }) => {
49
50
  return (_jsxs(TMLayoutContainer, { gap: gap, justifyContent: justifyContent, alignItems: alignItems, direction: direction, children: [children, showWaitPanel && (_jsx(TMWaitPanel, { title: waitPanelTitle, showPrimary: showWaitPanelPrimary, textPrimary: waitPanelTextPrimary, valuePrimary: waitPanelValuePrimary, maxValuePrimary: waitPanelMaxValuePrimary, showSecondary: showWaitPanelSecondary, textSecondary: waitPanelTextSecondary, valueSecondary: waitPanelValueSecondary, maxValueSecondary: waitPanelMaxValueSecondary, isCancelable: isCancelable, abortController: abortController, onAbortClick: (abortController) => { setTimeout(() => { abortController?.abort(); }, 1000); } }))] }));
@@ -31,7 +31,7 @@ const cellRenderIcon = (data) => _jsx(TMImageLibrary, { imageID: data.data?.imag
31
31
  export const TMDataListItemChooserForm = (props) => {
32
32
  const dataColumns = useMemo(() => {
33
33
  return [
34
- { dataField: 'value', caption: SDKUI_Localizator.Value },
34
+ { dataField: 'value', caption: SDKUI_Localizator.Value, visible: false },
35
35
  { dataField: 'name', caption: SDKUI_Localizator.Description }
36
36
  ];
37
37
  }, []);
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { DataListItemDescriptor } from '@topconsultnpm/sdk-ts';
3
+ interface TMDataListItemEditorProps {
4
+ isOpen: boolean;
5
+ item?: DataListItemDescriptor;
6
+ isCreating: boolean;
7
+ onClose: () => void;
8
+ onSave: (item: DataListItemDescriptor) => void;
9
+ }
10
+ declare const TMDataListItemEditor: React.FC<TMDataListItemEditorProps>;
11
+ export default TMDataListItemEditor;
@@ -0,0 +1,130 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from 'react';
3
+ import styled from 'styled-components';
4
+ import { DataListItemDescriptor, NamesLoc3, PlatformObjectValidator } from '@topconsultnpm/sdk-ts';
5
+ import { IconCloseOutline, IconSave, IconUndo, SDKUI_Localizator } from '../../helper';
6
+ import TMButton from '../base/TMButton';
7
+ import TMModal from '../base/TMModal';
8
+ import TMDataListItemFields from './TMDataListItemFields';
9
+ import { TMColors } from '../../utils/theme';
10
+ const FormContainer = styled.div `
11
+ display: flex;
12
+ flex-direction: column;
13
+ gap: 15px;
14
+ padding: 20px;
15
+ `;
16
+ const ButtonsContainer = styled.div `
17
+ display: flex;
18
+ justify-content: flex-end;
19
+ gap: 10px;
20
+ margin-top: 10px;
21
+ `;
22
+ const TMDataListItemEditor = ({ isOpen, item, isCreating, onClose, onSave }) => {
23
+ const [editedItem, setEditedItem] = useState(null);
24
+ const [editedItemOrig, setEditedItemOrig] = useState(null);
25
+ const [validationItems, setValidationItems] = useState([]);
26
+ useEffect(() => {
27
+ if (!editedItem)
28
+ return;
29
+ let vil = [];
30
+ PlatformObjectValidator.DataListItemValidator(editedItem, vil);
31
+ setValidationItems(vil);
32
+ }, [editedItem]);
33
+ // Funzione helper per clonare un DataListItemDescriptor
34
+ const cloneItem = (source) => {
35
+ const clone = new DataListItemDescriptor();
36
+ Object.assign(clone, source);
37
+ if (source.namesLoc) {
38
+ const namesLocClone = new NamesLoc3();
39
+ namesLocClone.init(source.namesLoc);
40
+ clone.namesLoc = namesLocClone;
41
+ }
42
+ return clone;
43
+ };
44
+ useEffect(() => {
45
+ if (isOpen) {
46
+ if (item) {
47
+ // Crea una copia dell'item per editarlo
48
+ const clone = cloneItem(item);
49
+ setEditedItem(clone);
50
+ // Salva anche l'originale per il confronto e l'undo
51
+ const original = cloneItem(item);
52
+ setEditedItemOrig(original);
53
+ }
54
+ else {
55
+ // Nuovo item vuoto
56
+ const newItem = new DataListItemDescriptor();
57
+ newItem.value = '';
58
+ newItem.name = '';
59
+ setEditedItem(newItem);
60
+ setEditedItemOrig(cloneItem(newItem));
61
+ }
62
+ }
63
+ }, [isOpen, item]);
64
+ // Funzione per verificare se ci sono modifiche rispetto all'originale
65
+ const hasChanges = () => {
66
+ if (!editedItem || !editedItemOrig)
67
+ return false;
68
+ // Confronta i campi principali
69
+ if (editedItem.value !== editedItemOrig.value)
70
+ return true;
71
+ if (editedItem.name !== editedItemOrig.name)
72
+ return true;
73
+ if (editedItem.imageID !== editedItemOrig.imageID)
74
+ return true;
75
+ // Confronta namesLoc
76
+ const namesLoc1 = editedItem.namesLoc;
77
+ const namesLoc2 = editedItemOrig.namesLoc;
78
+ if (!namesLoc1 && !namesLoc2)
79
+ return false;
80
+ if (!namesLoc1 || !namesLoc2)
81
+ return true;
82
+ if (namesLoc1.it_IT !== namesLoc2.it_IT)
83
+ return true;
84
+ if (namesLoc1.en_US !== namesLoc2.en_US)
85
+ return true;
86
+ if (namesLoc1.fr_FR !== namesLoc2.fr_FR)
87
+ return true;
88
+ if (namesLoc1.pt_PT !== namesLoc2.pt_PT)
89
+ return true;
90
+ if (namesLoc1.es_ES !== namesLoc2.es_ES)
91
+ return true;
92
+ if (namesLoc1.de_DE !== namesLoc2.de_DE)
93
+ return true;
94
+ return false;
95
+ };
96
+ const handleUndo = () => {
97
+ if (!editedItemOrig)
98
+ return;
99
+ // Ripristina l'item originale clonandolo
100
+ const restored = cloneItem(editedItemOrig);
101
+ setEditedItem(restored);
102
+ };
103
+ const handleSave = () => {
104
+ if (!editedItem)
105
+ return;
106
+ // Pulisci namesLoc rimuovendo valori undefined o vuoti, mantenendo l'istanza della classe
107
+ if (editedItem.namesLoc) {
108
+ const cleanedData = {};
109
+ Object.entries(editedItem.namesLoc).forEach(([key, value]) => {
110
+ if (value !== undefined && value !== '') {
111
+ cleanedData[key] = value;
112
+ }
113
+ });
114
+ // Crea una nuova istanza di NamesLoc3 con i dati puliti
115
+ if (Object.keys(cleanedData).length > 0) {
116
+ const cleanedNamesLoc = new NamesLoc3();
117
+ cleanedNamesLoc.init(cleanedData);
118
+ editedItem.namesLoc = cleanedNamesLoc;
119
+ }
120
+ else {
121
+ editedItem.namesLoc = undefined;
122
+ }
123
+ }
124
+ onSave(editedItem);
125
+ };
126
+ if (!isOpen || !editedItem)
127
+ return null;
128
+ return (_jsx(TMModal, { title: isCreating ? SDKUI_Localizator.NewMale : SDKUI_Localizator.Update, width: "400px", height: "auto", isModal: true, onClose: onClose, children: _jsxs(FormContainer, { children: [_jsx(TMDataListItemFields, { item: editedItem, originalItem: editedItemOrig || undefined, onItemChanged: setEditedItem, validationItems: validationItems }), _jsxs(ButtonsContainer, { children: [_jsx(TMButton, { caption: SDKUI_Localizator.Save, btnStyle: 'advanced', advancedColor: TMColors.primary, icon: _jsx(IconSave, {}), showTooltip: false, onClick: handleSave }), _jsx(TMButton, { caption: SDKUI_Localizator.Undo, btnStyle: 'toolbar', color: 'primary', icon: _jsx(IconUndo, {}), showTooltip: false, disabled: !hasChanges(), onClick: handleUndo }), _jsx(TMButton, { caption: SDKUI_Localizator.Cancel, btnStyle: 'advanced', advancedColor: TMColors.primary, icon: _jsx(IconCloseOutline, {}), showTooltip: false, onClick: onClose })] })] }) }));
129
+ };
130
+ export default TMDataListItemEditor;
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { DataListItemDescriptor, ValidationItem } from '@topconsultnpm/sdk-ts';
3
+ interface TMDataListItemFieldsProps {
4
+ item: DataListItemDescriptor;
5
+ originalItem?: DataListItemDescriptor;
6
+ onItemChanged: (item: DataListItemDescriptor) => void;
7
+ validationItems?: ValidationItem[];
8
+ readOnly?: boolean;
9
+ }
10
+ declare const TMDataListItemFields: React.FC<TMDataListItemFieldsProps>;
11
+ export default TMDataListItemFields;
@@ -0,0 +1,61 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import styled from 'styled-components';
3
+ import { DataListItemDescriptor, CultureIDs, NamesLoc3 } from '@topconsultnpm/sdk-ts';
4
+ import { SDKUI_Localizator } from '../../helper';
5
+ import TMTextBox from '../editors/TMTextBox';
6
+ import TMLocalizedTextBox from '../editors/TMLocalizedTextBox';
7
+ import TMImageIDChooser from './TMImageIDChooser';
8
+ const FieldsContainer = styled.div `
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: 15px;
12
+ `;
13
+ const TMDataListItemFields = ({ item, originalItem, onItemChanged, validationItems = [], readOnly = false }) => {
14
+ const handleLocalizedNameChange = (lang, newValue) => {
15
+ if (!item.namesLoc) {
16
+ item.namesLoc = new NamesLoc3();
17
+ }
18
+ const namesLoc = item.namesLoc; // Non-null assertion
19
+ switch (lang) {
20
+ case CultureIDs.It_IT:
21
+ namesLoc.it_IT = newValue;
22
+ break;
23
+ case CultureIDs.En_US:
24
+ namesLoc.en_US = newValue;
25
+ break;
26
+ case CultureIDs.Fr_FR:
27
+ namesLoc.fr_FR = newValue;
28
+ break;
29
+ case CultureIDs.Pt_PT:
30
+ namesLoc.pt_PT = newValue;
31
+ break;
32
+ case CultureIDs.Es_ES:
33
+ namesLoc.es_ES = newValue;
34
+ break;
35
+ case CultureIDs.De_DE:
36
+ namesLoc.de_DE = newValue;
37
+ break;
38
+ default:
39
+ item.name = newValue;
40
+ break;
41
+ }
42
+ // Forza il re-render clonando l'oggetto
43
+ const clone = new DataListItemDescriptor();
44
+ Object.assign(clone, item);
45
+ onItemChanged(clone);
46
+ };
47
+ const handleValueChange = (e) => {
48
+ item.value = e.target.value || '';
49
+ const clone = new DataListItemDescriptor();
50
+ Object.assign(clone, item);
51
+ onItemChanged(clone);
52
+ };
53
+ const handleImageIDChange = (imageID) => {
54
+ item.imageID = imageID;
55
+ const clone = new DataListItemDescriptor();
56
+ Object.assign(clone, item);
57
+ onItemChanged(clone);
58
+ };
59
+ return (_jsxs(FieldsContainer, { children: [_jsx(TMTextBox, { label: SDKUI_Localizator.Value, value: item.value, isModifiedWhen: (item.value || '') != (originalItem?.value || ''), validationItems: validationItems.filter(o => o.PropertyName === "value"), readOnly: readOnly, autoFocus: true, onValueChanged: handleValueChange }), _jsx(TMLocalizedTextBox, { label: SDKUI_Localizator.Description, value: item.name, isModifiedWhen: (item.name || '') != (originalItem?.name || ''), validationItems: validationItems.filter(o => o.PropertyName === "itemName"), readOnly: readOnly, value_IT: item.namesLoc?.it_IT, value_EN: item.namesLoc?.en_US, value_FR: item.namesLoc?.fr_FR, value_PT: item.namesLoc?.pt_PT, value_ES: item.namesLoc?.es_ES, value_DE: item.namesLoc?.de_DE, onValueChanged: handleLocalizedNameChange }), _jsx(TMImageIDChooser, { elementStyle: { marginBottom: '10px' }, label: "Immagine", value: item.imageID, isModifiedWhen: (item.imageID || '') != (originalItem?.imageID || ''), validationItems: validationItems.filter(o => o.PropertyName === "imageID"), readOnly: readOnly, onValueChanged: handleImageIDChange })] }));
60
+ };
61
+ export default TMDataListItemFields;
@@ -4,6 +4,8 @@ interface TMDataListItemPickerProps {
4
4
  dataListID: number | undefined;
5
5
  selectedValue: string | undefined;
6
6
  onItemSelect: (item: DataListItemDescriptor) => void;
7
+ onItemEdited?: (originalItem: DataListItemDescriptor, editedItem: DataListItemDescriptor) => void;
8
+ allowEdit?: boolean;
7
9
  }
8
10
  declare const TMDataListItemPicker: React.FC<TMDataListItemPickerProps>;
9
11
  export default TMDataListItemPicker;