@topconsultnpm/sdkui-react 6.22.0-dev2.2 → 6.22.0-dev2.20

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 (109) hide show
  1. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +1 -1
  2. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +1 -1
  3. package/lib/components/base/TMButton.d.ts +13 -0
  4. package/lib/components/base/TMButton.js +137 -5
  5. package/lib/components/base/TMDataGrid.d.ts +2 -0
  6. package/lib/components/base/TMDataGrid.js +68 -4
  7. package/lib/components/base/TMEditorBase.d.ts +2 -0
  8. package/lib/components/base/TMModal.d.ts +4 -0
  9. package/lib/components/base/TMModal.js +42 -11
  10. package/lib/components/base/TMPanel.d.ts +1 -0
  11. package/lib/components/base/TMPanel.js +79 -20
  12. package/lib/components/base/TMTooltip.d.ts +2 -1
  13. package/lib/components/base/TMTooltip.js +23 -6
  14. package/lib/components/base/TMTreeView.js +108 -67
  15. package/lib/components/choosers/TMDcmtTypeChooser.js +4 -3
  16. package/lib/components/choosers/TMDistinctValues.d.ts +9 -7
  17. package/lib/components/choosers/TMDistinctValues.js +149 -142
  18. package/lib/components/choosers/TMMetadataChooser.js +1 -1
  19. package/lib/components/choosers/TMQuickSearchInfo.d.ts +12 -0
  20. package/lib/components/choosers/TMQuickSearchInfo.js +279 -0
  21. package/lib/components/choosers/TMQuickSearchSettingsForm.d.ts +16 -0
  22. package/lib/components/choosers/TMQuickSearchSettingsForm.js +94 -0
  23. package/lib/components/choosers/TMSelectedValuesSummary.d.ts +13 -0
  24. package/lib/components/choosers/TMSelectedValuesSummary.js +91 -0
  25. package/lib/components/editors/TMDropDown.d.ts +3 -0
  26. package/lib/components/editors/TMDropDown.js +197 -5
  27. package/lib/components/editors/TMMetadataEditor.d.ts +5 -1
  28. package/lib/components/editors/TMMetadataEditor.js +8 -3
  29. package/lib/components/editors/TMTextBox.js +15 -15
  30. package/lib/components/features/documents/TMBatchUpdateForm.js +19 -5
  31. package/lib/components/features/documents/TMDcmtForm.d.ts +7 -0
  32. package/lib/components/features/documents/TMDcmtForm.js +104 -42
  33. package/lib/components/features/documents/TMDcmtFormActionButtons.d.ts +11 -0
  34. package/lib/components/features/documents/TMDcmtFormActionButtons.js +74 -7
  35. package/lib/components/features/documents/TMMasterDetailDcmts.js +95 -33
  36. package/lib/components/features/documents/TMMasterInfoFields.d.ts +19 -0
  37. package/lib/components/features/documents/TMMasterInfoFields.js +172 -0
  38. package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.d.ts +40 -0
  39. package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.js +256 -0
  40. package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.d.ts +352 -0
  41. package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.js +221 -0
  42. package/lib/components/features/documents/TMRelationViewer.d.ts +14 -1
  43. package/lib/components/features/documents/TMRelationViewer.js +69 -20
  44. package/lib/components/features/search/TMSearch.js +29 -16
  45. package/lib/components/features/search/TMSearchQueryEditor.js +5 -3
  46. package/lib/components/features/search/TMSearchQueryPanel.d.ts +1 -1
  47. package/lib/components/features/search/TMSearchQueryPanel.js +28 -7
  48. package/lib/components/features/search/TMSearchResult.d.ts +9 -0
  49. package/lib/components/features/search/TMSearchResult.js +323 -92
  50. package/lib/components/features/search/TMTreeSelector.js +18 -5
  51. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +10 -0
  52. package/lib/components/features/workflow/TMWorkflowPopup.js +8 -4
  53. package/lib/components/layout/panelManager/TMPanelManagerContainer.d.ts +1 -0
  54. package/lib/components/layout/panelManager/TMPanelManagerContainer.js +24 -14
  55. package/lib/components/layout/panelManager/TMPanelWrapper.js +2 -2
  56. package/lib/components/layout/panelManager/types.d.ts +3 -0
  57. package/lib/components/viewers/TMMidViewer.js +4 -1
  58. package/lib/components/viewers/TMTidViewer.js +25 -11
  59. package/lib/helper/SDKUI_Globals.d.ts +55 -0
  60. package/lib/helper/SDKUI_Globals.js +82 -0
  61. package/lib/helper/SDKUI_Localizator.d.ts +23 -0
  62. package/lib/helper/SDKUI_Localizator.js +230 -0
  63. package/lib/helper/TMIcons.d.ts +1 -0
  64. package/lib/helper/TMIcons.js +3 -0
  65. package/lib/helper/dataGridSearchHelper.d.ts +28 -0
  66. package/lib/helper/dataGridSearchHelper.js +51 -0
  67. package/lib/helper/dcmtsHelper.d.ts +20 -0
  68. package/lib/helper/dcmtsHelper.js +58 -1
  69. package/lib/helper/helpers.d.ts +20 -0
  70. package/lib/helper/helpers.js +40 -0
  71. package/lib/helper/index.d.ts +1 -0
  72. package/lib/helper/index.js +1 -0
  73. package/lib/helper/queryHelper.d.ts +2 -0
  74. package/lib/helper/queryHelper.js +3 -1
  75. package/lib/hooks/tmDistinctValuesGridHelper.d.ts +16 -0
  76. package/lib/hooks/tmDistinctValuesGridHelper.js +31 -0
  77. package/lib/hooks/useArchiveListForm.d.ts +39 -0
  78. package/lib/hooks/useArchiveListForm.js +46 -0
  79. package/lib/hooks/useCaseFlowApprove.d.ts +56 -0
  80. package/lib/hooks/useCaseFlowApprove.js +157 -0
  81. package/lib/hooks/useDataUserIdItem.d.ts +1 -0
  82. package/lib/hooks/useDataUserIdItem.js +1 -0
  83. package/lib/hooks/useDocumentOperations.d.ts +2 -0
  84. package/lib/hooks/useDocumentOperations.js +28 -5
  85. package/lib/hooks/useMultiMasterDetailDcmts.d.ts +97 -0
  86. package/lib/hooks/useMultiMasterDetailDcmts.js +555 -0
  87. package/lib/hooks/useRelatedDocuments.js +2 -26
  88. package/lib/hooks/useTMDistinctValuesMetadataDisplay.d.ts +18 -0
  89. package/lib/hooks/useTMDistinctValuesMetadataDisplay.js +103 -0
  90. package/lib/hooks/useTMDistinctValuesQuickSearch.d.ts +49 -0
  91. package/lib/hooks/useTMDistinctValuesQuickSearch.js +307 -0
  92. package/lib/hooks/useTMDistinctValuesSelection.d.ts +42 -0
  93. package/lib/hooks/useTMDistinctValuesSelection.js +103 -0
  94. package/lib/hooks/useTMDistinctValuesSource.d.ts +29 -0
  95. package/lib/hooks/useTMDistinctValuesSource.js +105 -0
  96. package/lib/index.d.ts +1 -0
  97. package/lib/index.js +1 -0
  98. package/lib/services/caseflow/CaseFlowService.d.ts +236 -0
  99. package/lib/services/caseflow/CaseFlowService.js +693 -0
  100. package/lib/services/caseflow/CaseFlowTemplateCacheService.d.ts +28 -0
  101. package/lib/services/caseflow/CaseFlowTemplateCacheService.js +121 -0
  102. package/lib/services/caseflow/caseFlowNameCache.d.ts +32 -0
  103. package/lib/services/caseflow/caseFlowNameCache.js +116 -0
  104. package/lib/services/caseflow/caseFlowWorkItemUtils.d.ts +61 -0
  105. package/lib/services/caseflow/caseFlowWorkItemUtils.js +113 -0
  106. package/lib/services/index.d.ts +4 -0
  107. package/lib/services/index.js +4 -0
  108. package/lib/services/platform_services.d.ts +1 -1
  109. package/package.json +66 -66
@@ -0,0 +1,256 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useCallback, useMemo, useState } from "react";
3
+ import { LayoutModes } from "@topconsultnpm/sdk-ts";
4
+ import { LoadIndicator } from "devextreme-react/load-indicator";
5
+ import { SearchResultContext } from "../../../ts";
6
+ import { getFullFileExtension, getMultiDetailPanelStates, hasMultiDetailPanelStates, hoverStyle, IconArchive, IconDelete, IconDuplicate, IconEdit, IconEraser, IconMenuVertical, IconRefresh, IconSearch, IconSearchCheck, saveMultiDetailPanelStates, SDKUI_Localizator } from "../../../helper";
7
+ import { TMColors } from "../../../utils/theme";
8
+ import { TMLayoutWaitingContainer } from "../../base/TMWaitPanel";
9
+ import TMModal from "../../base/TMModal";
10
+ import TMDataGrid from "../../base/TMDataGrid";
11
+ import TMTooltip from "../../base/TMTooltip";
12
+ import { TMDcmtTypeIcon } from "../../viewers/TMTidViewer";
13
+ import { ContextMenu } from "../../NewComponents/ContextMenu";
14
+ import { TMPanelManagerWithPersistenceProvider } from "../../layout/panelManager/TMPanelManagerWithPersistenceProvider";
15
+ import TMPanelManagerContainer from "../../layout/panelManager/TMPanelManagerContainer";
16
+ import TMSearchResult from "../search/TMSearchResult";
17
+ import TMDcmtForm from "./TMDcmtForm";
18
+ import TMDcmtIcon from "./TMDcmtIcon";
19
+ import TMMasterInfoFields from "./TMMasterInfoFields";
20
+ import { MultiDetailArchivePhase, useMultiMasterDetailDcmts } from "../../../hooks/useMultiMasterDetailDcmts";
21
+ import { accordionStyles, getDtdDisplayName, INLINE_EDITABLE_CELL_CLASS, multiDetailStyles, PANEL_GUTTER_PX, renderAccordionHeader, renderSelectDcmtType, renderStepper, SECTION_HEADER_HEIGHT_PX, sectionPanelHeights, TMSectionPanelsHeights, TMSummarySectionSlot } from "./TMMultiMasterDetailDcmtsUtils";
22
+ // Stili delle sezioni in TMMultiMasterDetailDcmtsUtils (vedi accordionStyles e multiDetailStyles)
23
+ const styles = {
24
+ content: { display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0 },
25
+ header: { display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '6px 12px', borderBottom: `1px solid ${TMColors.card_background}`, flexShrink: 0 },
26
+ // Opzioni nella barra del titolo: stesse misure e colore della chiusura DevExtreme (.dx-popup-title .dx-closebutton)
27
+ titleMenuIcon: { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: '18px', height: '18px', margin: '1px 0 0', color: `var(--dx-color-text, ${TMColors.text_normal})`, cursor: 'pointer' },
28
+ loader: { display: 'flex', flex: 1, alignItems: 'center', justifyContent: 'center' },
29
+ summaryContainer: { display: 'flex', flexDirection: 'column', flex: 1, padding: '8px 12px 10px', minHeight: 0, gap: '8px' },
30
+ // I pannelli ripartiscono l'altezza in percentuale: serve un'altezza definita che non dipenda dal
31
+ // contenuto, da qui il riempimento in posizione assoluta dello spazio residuo
32
+ panelsHost: { position: 'relative', flex: 1, minHeight: 0, minWidth: 0 },
33
+ panelsHostFill: { position: 'absolute', top: 0, right: 0, bottom: 0, left: 0, display: 'flex' },
34
+ gridWrapper: { position: 'relative', flex: 1, minHeight: 0 },
35
+ actionsCell: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '14px' },
36
+ actionIcon: { cursor: 'pointer', display: 'flex' },
37
+ fileCell: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },
38
+ fab: { position: 'absolute', bottom: '18px', right: '20px', width: '42px', height: '42px', borderRadius: '50%', backgroundColor: TMColors.button_floating_background, color: '#fff', border: 'none', cursor: 'pointer', boxShadow: '0 2px 6px rgba(0,0,0,0.2)', zIndex: 1000, transition: 'background-color 0.3s ease, transform 0.2s ease', display: 'flex', justifyContent: 'center', alignItems: 'center' },
39
+ footer: { display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'center', flexWrap: 'wrap', gap: '14px', paddingTop: '8px', borderTop: `1px solid ${TMColors.card_background}`, flexShrink: 0 },
40
+ footerLabel: { display: 'inline-flex', alignItems: 'center', gap: '8px', cursor: 'pointer', color: TMColors.label_normal, fontSize: '12px', userSelect: 'none', padding: '5px 10px', borderRadius: '16px', background: 'transparent', border: `1px solid ${TMColors.card_background}`, transition: 'all 0.15s ease' },
41
+ archiveButton: { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: '8px', height: '38px', padding: '0 22px', border: 'none', borderRadius: '10px', fontSize: '14px', fontWeight: 600, letterSpacing: '0.2px', color: '#ffffff', cursor: 'pointer', transition: 'transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease' },
42
+ checkbox: { width: '16px', height: '16px', accentColor: TMColors.primary, cursor: 'pointer', margin: 0 },
43
+ };
44
+ const TMMultiMasterDetailDcmtsForm = (props) => {
45
+ const { dtd, masterDcmt, onClose, allTasks, getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, showDcmtFormSidebar, showTodoDcmtForm, openFileUploaderPdfEditor, graphometricManager, editPdfForm, openS4TViewer, showToppyDraggableHelpCenter, toppyHelpCenterUsePortal, fetchRemoteCertificates, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onReferenceClick, onTaskCreateRequest, onRefreshAfterAddDcmtToFavs, onFileOpened, passToArchiveCallback, openWGsCopyMoveForm } = props;
46
+ const { isLoading, isSummaryReady, phase, setPhase, detailRelationItems, selectedRelation, selectedItem, hasMultipleTypes, selectRelation, backToTypeSelection, isBackLocked, closeModal, sectionsOpen, setSectionOpen, clearLayout, layoutResetToken, canUpdateMaster, masterFieldsCount, getMasterMetadataAsync, masterInfoReloadToken, isOpenMasterForm, setIsOpenMasterForm, handleMasterSavedAsync, archivedDetailResults, archivedDetailsCount, isLoadingArchivedDetails, refreshArchivedDetailsAsync, detailColumns, detailSupportsFile, archiveRows, currentRows, focusedRowKey, setFocusedRowKey, selectedRowKeys, setSelectedRowKeys, isOpenAddForm, editingRowId, editingRow, formInputMids, openAddForm, openEditForm, closeAddForm, deleteRow, duplicateRow, upsertRow, updateRowValues, stopOnFirstError, setStopOnFirstError, isArchiving, archiveAllAsync, waitPanel, abortController, } = useMultiMasterDetailDcmts({ dtd, masterDcmt, onClose });
47
+ // Ricerca nella griglia dei dettagli da archiviare, come in TMSearch (vedi useDocumentOperations)
48
+ const [showGridSearch, setShowGridSearch] = useState(false);
49
+ const toggleGridSearchItem = {
50
+ name: showGridSearch ? SDKUI_Localizator.HideSearch : SDKUI_Localizator.ShowSearch,
51
+ icon: _jsx(IconSearch, { fontSize: 18 }),
52
+ beginGroup: true,
53
+ onClick: () => setShowGridSearch(prev => !prev),
54
+ };
55
+ const isSummaryPhase = phase === MultiDetailArchivePhase.ArchiveSummary;
56
+ const baseTitle = SDKUI_Localizator.ArchiveMultipleDetailDocuments;
57
+ // Con un solo tipo il nome è mostrato direttamente nel titolo del modale
58
+ const modalTitle = !hasMultipleTypes && selectedItem ? `${baseTitle}: ${getDtdDisplayName(selectedItem.detailDtd)}` : baseTitle;
59
+ const isArchiveDisabled = isArchiving || currentRows.length === 0;
60
+ const archiveButtonCaption = currentRows.length > 0
61
+ ? `${SDKUI_Localizator.Archive} ${currentRows.length} ${currentRows.length === 1 ? 'dettaglio' : 'dettagli'}`
62
+ : SDKUI_Localizator.Archive;
63
+ const steps = [
64
+ ...(hasMultipleTypes ? [{ phase: MultiDetailArchivePhase.SelectDcmtType, label: SDKUI_Localizator.DcmtType }] : []),
65
+ {
66
+ phase: MultiDetailArchivePhase.ArchiveSummary,
67
+ // Nel riepilogo lo step mostra il tipo selezionato (icona + nome)
68
+ label: selectedItem
69
+ ? (_jsxs("span", { style: multiDetailStyles.stepTypeLabel, children: [_jsx(TMDcmtTypeIcon, { dtd: selectedItem.detailDtd }), _jsx("span", { style: multiDetailStyles.stepTypeLabelText, children: getDtdDisplayName(selectedItem.detailDtd) })] }))
70
+ : SDKUI_Localizator.Summary,
71
+ },
72
+ ];
73
+ // Colonne della griglia: icona del documento, metadati del tipo, file e azioni
74
+ const gridColumns = useMemo(() => {
75
+ const iconColumn = {
76
+ caption: '', width: 50, alignment: 'center',
77
+ allowSorting: false, allowFiltering: false, allowResizing: false, allowReordering: false, allowHiding: false, allowEditing: false,
78
+ cellRender: (cell) => {
79
+ const file = cell.data?.__file;
80
+ return _jsx(TMDcmtIcon, { fileExtension: file ? getFullFileExtension(file.name) : undefined, fileCount: file ? 1 : 0, tooltipContent: file?.name });
81
+ },
82
+ };
83
+ const fileColumn = {
84
+ caption: 'File', width: 220, allowSorting: false, allowEditing: false,
85
+ cellRender: (cell) => {
86
+ const file = cell.data?.__file;
87
+ return _jsx("span", { style: { ...styles.fileCell, color: file ? TMColors.text_normal : TMColors.label_normal }, children: file ? file.name : '' });
88
+ },
89
+ };
90
+ const actionsColumn = {
91
+ caption: '', width: 110, alignment: 'center',
92
+ allowSorting: false, allowFiltering: false, allowHeaderFiltering: false, allowResizing: false,
93
+ allowReordering: false, allowHiding: false, showInColumnChooser: false, allowEditing: false,
94
+ cssClass: 'tm-row-actions',
95
+ cellRender: (cell) => (_jsxs("div", { style: styles.actionsCell, children: [_jsx("span", { style: styles.actionIcon, title: SDKUI_Localizator.Update, onClick: () => openEditForm(cell.data), children: _jsx(IconEdit, { fontSize: 18, color: TMColors.primary }) }), _jsx("span", { style: styles.actionIcon, title: SDKUI_Localizator.Duplicate, onClick: () => duplicateRow(cell.data), children: _jsx(IconDuplicate, { fontSize: 18, color: TMColors.tertiary }) }), _jsx("span", { style: styles.actionIcon, title: SDKUI_Localizator.Deletion, onClick: () => deleteRow(cell.data), children: _jsx(IconDelete, { fontSize: 18, color: TMColors.error }) })] })),
96
+ };
97
+ return [actionsColumn, iconColumn, ...detailColumns, ...(detailSupportsFile ? [fileColumn] : [])];
98
+ }, [detailColumns, detailSupportsFile]);
99
+ // ----- Griglia dei dettagli: opzioni e callback con identità stabile -------------------------
100
+ // Un nuovo riferimento a ogni render farebbe rifare a DevExtreme il setup di selezione/editing
101
+ const gridSelection = useMemo(() => ({ mode: 'single', showCheckBoxesMode: 'none' }), []);
102
+ const gridEditing = useMemo(() => ({
103
+ mode: 'cell', allowUpdating: true, allowAdding: false, allowDeleting: false, startEditAction: 'click', selectTextOnEditStart: true,
104
+ }), []);
105
+ const handleSelectionChanged = useCallback((e) => {
106
+ setSelectedRowKeys(e.selectedRowKeys ?? []);
107
+ }, [setSelectedRowKeys]);
108
+ const handleFocusedRowChanged = useCallback((e) => {
109
+ setFocusedRowKey(e.row?.key);
110
+ }, [setFocusedRowKey]);
111
+ const handleRowUpdating = useCallback((e) => {
112
+ updateRowValues(e.key, e.newData);
113
+ }, [updateRowValues]);
114
+ // Il doppio clic apre il form della riga, tranne su azioni e celle modificabili in linea
115
+ const handleCellDblClick = useCallback((e) => {
116
+ if (e.rowType !== 'data')
117
+ return;
118
+ const cssClass = e.column?.cssClass ?? '';
119
+ if (cssClass === 'tm-row-actions' || cssClass === INLINE_EDITABLE_CELL_CLASS)
120
+ return;
121
+ openEditForm(e.data);
122
+ }, [openEditForm]);
123
+ // Menu contestuale con le stesse azioni della colonna
124
+ const contextMenuItems = useMemo(() => [
125
+ { name: SDKUI_Localizator.Update, icon: _jsx(IconEdit, { fontSize: 18, color: TMColors.primary }), operationType: 'singleRow', onClick: (id) => openEditForm(archiveRows.find(r => r.id === id)) },
126
+ { name: SDKUI_Localizator.Duplicate, icon: _jsx(IconDuplicate, { fontSize: 18, color: TMColors.tertiary }), operationType: 'singleRow', onClick: (id) => duplicateRow(archiveRows.find(r => r.id === id)) },
127
+ { name: SDKUI_Localizator.Deletion, icon: _jsx(IconDelete, { fontSize: 18, color: TMColors.error }), operationType: 'singleRow', beginGroup: true, onClick: (id) => deleteRow(archiveRows.find(r => r.id === id)) },
128
+ toggleGridSearchItem,
129
+ ], [archiveRows, showGridSearch]);
130
+ // Menu delle opzioni del modale, aperto dal pulsante a tre punti nella barra del titolo
131
+ const optionsMenuItems = useMemo(() => [
132
+ { name: 'Cancella layout', icon: _jsx(IconEraser, { fontSize: 18, color: TMColors.error }), onClick: clearLayout },
133
+ ], [clearLayout]);
134
+ // Le opzioni riguardano i pannelli del riepilogo: fuori da quella fase non hanno effetto
135
+ const renderOptionsMenu = () => {
136
+ if (!isSummaryPhase)
137
+ return undefined;
138
+ return (_jsx(ContextMenu, { trigger: 'left', items: optionsMenuItems, children: _jsx("span", { style: styles.titleMenuIcon, title: SDKUI_Localizator.Options, "aria-label": SDKUI_Localizator.Options, children: _jsx(IconMenuVertical, { fontSize: 16, color: "white" }) }) }));
139
+ };
140
+ // ----- Sezione: informazioni del master -----------------------------------------------------
141
+ const renderMasterInfo = (panel) => {
142
+ const isOpen = sectionsOpen.masterInfo;
143
+ const editMasterButton = canUpdateMaster
144
+ ? (_jsx("button", { type: 'button', onClick: (e) => { e.stopPropagation(); setIsOpenMasterForm(true); }, style: accordionStyles.accordionExpandBtn, title: `${SDKUI_Localizator.Update}: ${getDtdDisplayName(dtd)}`, ...hoverStyle({ background: TMColors.primary_container, color: TMColors.primary }, { background: 'transparent', color: TMColors.label_normal }), children: _jsx(IconEdit, { fontSize: 16 }) }))
145
+ : undefined;
146
+ return (_jsxs("div", { style: { ...accordionStyles.accordion, ...accordionStyles.accordionInPanel }, children: [renderAccordionHeader({
147
+ section: 'masterInfo',
148
+ isOpen,
149
+ tooltip: isOpen ? SDKUI_Localizator.HideMasterInfo : SDKUI_Localizator.ShowMasterInfo,
150
+ count: masterFieldsCount,
151
+ title: (_jsxs(_Fragment, { children: [_jsx(TMDcmtTypeIcon, { dtd: dtd }), _jsxs("span", { style: multiDetailStyles.stepTypeLabelText, children: ["Master: ", getDtdDisplayName(dtd)] })] })),
152
+ actions: editMasterButton,
153
+ panel,
154
+ onToggleOpen: setSectionOpen,
155
+ }), isOpen && (_jsx(TMMasterInfoFields, { dtd: dtd, dcmt: masterDcmt, getValuesByMidAsync: getMasterMetadataAsync, reloadToken: masterInfoReloadToken, isExpandedView: panel.isMaximized }))] }));
156
+ };
157
+ // ----- Sezione: dettagli già archiviati -----------------------------------------------------
158
+ const renderArchivedDetails = (panel) => {
159
+ const isOpen = sectionsOpen.archivedDetails;
160
+ const hasResults = archivedDetailResults.length > 0 && archivedDetailsCount > 0;
161
+ // Ricarica i dettagli già archiviati: la sezione va aperta, altrimenti l'esito non sarebbe visibile
162
+ const refreshArchivedButton = (_jsx("button", { type: 'button', onClick: (e) => { e.stopPropagation(); setSectionOpen('archivedDetails', true); refreshArchivedDetailsAsync(); }, disabled: isLoadingArchivedDetails, style: { ...accordionStyles.accordionExpandBtn, ...(isLoadingArchivedDetails ? { cursor: 'default', opacity: 0.5 } : {}) }, title: SDKUI_Localizator.Refresh, "aria-label": SDKUI_Localizator.Refresh, ...(isLoadingArchivedDetails ? {} : hoverStyle({ background: TMColors.primary_container, color: TMColors.primary }, { background: 'transparent', color: TMColors.label_normal })), children: _jsx(IconRefresh, { fontSize: 16 }) }));
163
+ return (_jsxs("div", { style: { ...accordionStyles.accordion, ...accordionStyles.accordionInPanel }, children: [renderAccordionHeader({
164
+ section: 'archivedDetails',
165
+ isOpen,
166
+ tooltip: isOpen ? SDKUI_Localizator.HideArchivedDetails : SDKUI_Localizator.ShowArchivedDetails,
167
+ count: archivedDetailsCount,
168
+ title: (_jsxs(_Fragment, { children: [_jsx(IconSearchCheck, { fontSize: 15 }), _jsx("span", { style: multiDetailStyles.stepTypeLabelText, children: SDKUI_Localizator.ArchivedDetails })] })),
169
+ actions: refreshArchivedButton,
170
+ panel,
171
+ onToggleOpen: setSectionOpen,
172
+ }), isOpen && (_jsx("div", { style: { ...accordionStyles.accordionListBody, ...(panel.isMaximized ? { borderTop: 'none' } : {}) }, children: isLoadingArchivedDetails
173
+ ? _jsxs("div", { style: accordionStyles.accordionListPlaceholder, children: [_jsx(LoadIndicator, { height: 30, width: 30 }), SDKUI_Localizator.Loading] })
174
+ : (hasResults
175
+ ? _jsx(TMSearchResult, { showToolbarHeader: false, showCounterConfig: false, showActionsColumn: true, compactPager: !panel.isMaximized, context: SearchResultContext.METADATA_SEARCH, searchResults: archivedDetailResults, onClose: () => setSectionOpen('archivedDetails', false), showBackButton: false, showToolbarCloseButton: false, allowFloatingBar: false, allowRelations: false, openDcmtFormAsModal: true, showSearchResultSidebar: false, showDcmtFormSidebar: true, autoFocusFirstRow: false, onRefreshSearchAsyncDatagrid: refreshArchivedDetailsAsync, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, showTodoDcmtForm: showTodoDcmtForm, openFileUploaderPdfEditor: openFileUploaderPdfEditor, graphometricManager: graphometricManager, editPdfForm: editPdfForm, openS4TViewer: openS4TViewer, showToppyDraggableHelpCenter: showToppyDraggableHelpCenter, toppyHelpCenterUsePortal: toppyHelpCenterUsePortal, fetchRemoteCertificates: fetchRemoteCertificates, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, onReferenceClick: onReferenceClick, onTaskCreateRequest: onTaskCreateRequest, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, onFileOpened: onFileOpened, passToArchiveCallback: passToArchiveCallback, openWGsCopyMoveForm: openWGsCopyMoveForm })
176
+ : _jsx("div", { style: accordionStyles.accordionListPlaceholder, children: SDKUI_Localizator.NoDataToDisplay })) }))] }));
177
+ };
178
+ // ----- Sezione: dettagli da archiviare ------------------------------------------------------
179
+ const renderArchiveList = (panel) => {
180
+ const isOpen = sectionsOpen.archiveList;
181
+ return (_jsxs("div", { style: { ...accordionStyles.accordion, ...accordionStyles.accordionInPanel }, children: [renderAccordionHeader({
182
+ section: 'archiveList',
183
+ isOpen,
184
+ tooltip: isOpen ? SDKUI_Localizator.HideDetailsToArchive : SDKUI_Localizator.ShowDetailsToArchive,
185
+ count: currentRows.length,
186
+ title: (_jsxs(_Fragment, { children: [_jsx(IconArchive, { fontSize: 15 }), _jsx("span", { style: multiDetailStyles.stepTypeLabelText, children: SDKUI_Localizator.DetailsToArchive })] })),
187
+ panel,
188
+ onToggleOpen: setSectionOpen,
189
+ }), isOpen && (_jsxs("div", { style: { ...styles.gridWrapper, ...(panel.isMaximized ? {} : { borderTop: `1px solid ${TMColors.card_background}` }) }, children: [_jsx(TMDataGrid, { dataColumns: gridColumns, dataSource: currentRows, keyExpr: "id", height: "100%", showSearchPanel: showGridSearch, showGroupPanel: false, showFilterPanel: false, showHeaderFilter: true, selection: gridSelection, selectedRowKeys: selectedRowKeys, onSelectionChanged: handleSelectionChanged, focusedRowKey: focusedRowKey, onFocusedRowChanged: handleFocusedRowChanged, onCellDblClick: handleCellDblClick, editing: gridEditing, onRowUpdating: handleRowUpdating, customContextMenuItems: contextMenuItems }), _jsx("button", { type: "button", onClick: openAddForm, style: styles.fab, ...hoverStyle({ backgroundColor: '#D94A9F', transform: 'scale(1.1)', boxShadow: '0 4px 12px rgba(37, 89, 165, 0.6)' }, { backgroundColor: TMColors.button_floating_background, transform: 'scale(1)', boxShadow: '0 2px 6px rgba(0,0,0,0.2)' }), children: _jsx(TMTooltip, { content: SDKUI_Localizator.Add, children: _jsx("i", { className: "dx-icon-add", style: { fontSize: '22px' } }) }) })] }))] }));
190
+ };
191
+ // ----- Pannelli del riepilogo, uno per sezione ----------------------------------------------
192
+ const renderSectionsInPanels = () => {
193
+ const definitions = [
194
+ { section: 'masterInfo', name: `Master: ${getDtdDisplayName(dtd)}`, render: renderMasterInfo },
195
+ ...(selectedRelation?.detailTID !== undefined
196
+ ? [{ section: 'archivedDetails', name: SDKUI_Localizator.ArchivedDetails, render: renderArchivedDetails }]
197
+ : []),
198
+ { section: 'archiveList', name: SDKUI_Localizator.DetailsToArchive, render: renderArchiveList },
199
+ ];
200
+ const panels = definitions.map(definition => ({
201
+ id: definition.section,
202
+ name: definition.name,
203
+ currentGroupDirection: 'vertical',
204
+ contentOptions: {
205
+ // Ingrandire una sezione collassata la apre: altrimenti il pannello a tutto schermo sarebbe vuoto
206
+ component: _jsx(TMSummarySectionSlot, { section: definition.section, render: definition.render, onBeforeMaximize: (section) => setSectionOpen(section, true) }),
207
+ // Una sezione chiusa vale 0% di altezza: è questo minimo a tenerne a schermo la testata
208
+ minHeight: `${SECTION_HEADER_HEIGHT_PX}px`,
209
+ // La sezione collassata è alta quanto la sua testata: i separatori non la ingrandiscono
210
+ isCollapsed: !sectionsOpen[definition.section],
211
+ },
212
+ }));
213
+ const sections = panels.map(panel => panel.id);
214
+ // Le altezze salvate sono il punto di partenza, ma è il collasso corrente a decidere le quote
215
+ const savedStates = getMultiDetailPanelStates();
216
+ const savedDimensions = hasMultiDetailPanelStates()
217
+ ? sections.reduce((acc, section) => {
218
+ if (savedStates[section])
219
+ acc[section] = { width: savedStates[section].width, height: savedStates[section].height };
220
+ return acc;
221
+ }, {})
222
+ : undefined;
223
+ const initialDimensions = sectionPanelHeights(sections, sectionsOpen, savedDimensions);
224
+ const initialVisibility = sections.reduce((acc, section) => { acc[section] = true; return acc; }, {});
225
+ return (_jsx("div", { style: styles.panelsHost, children: _jsx("div", { style: styles.panelsHostFill, children: _jsxs(TMPanelManagerWithPersistenceProvider
226
+ // Le dimensioni sono lette solo al montaggio: dopo la cancellazione del layout i pannelli vanno rimontati
227
+ , { panels: panels, initialVisibility: initialVisibility, defaultDimensions: initialDimensions, initialDimensions: initialDimensions, initialMobilePanelId: 'archiveList', isPersistenceEnabled: true, persistPanelStates: saveMultiDetailPanelStates, children: [_jsx(TMSectionPanelsHeights, { sections: sections, sectionsOpen: sectionsOpen }), _jsx(TMPanelManagerContainer, { panels: panels, direction: 'vertical', showToolbar: false, minPanelSizePx: SECTION_HEADER_HEIGHT_PX, gutterSizePx: PANEL_GUTTER_PX })] }, layoutResetToken) }) }));
228
+ };
229
+ const renderArchiveSummary = () => (_jsxs("div", { style: styles.summaryContainer, children: [renderSectionsInPanels(), _jsxs("div", { style: styles.footer, children: [_jsxs("label", { style: styles.footerLabel, ...hoverStyle({ borderColor: TMColors.primary, color: TMColors.text_normal }, { borderColor: TMColors.card_background, color: TMColors.label_normal }), children: [_jsx("input", { type: "checkbox", checked: stopOnFirstError, onChange: (e) => setStopOnFirstError(e.target.checked), style: styles.checkbox }), "Ferma l'archiviazione al primo errore"] }), _jsxs("button", { type: "button", onClick: archiveAllAsync, disabled: isArchiveDisabled, style: {
230
+ ...styles.archiveButton,
231
+ background: isArchiveDisabled ? TMColors.disabled : TMColors.success,
232
+ boxShadow: isArchiveDisabled ? 'none' : `0 4px 14px ${TMColors.success}55`,
233
+ cursor: isArchiveDisabled ? 'default' : 'pointer',
234
+ opacity: isArchiveDisabled ? 0.6 : 1,
235
+ }, ...(isArchiveDisabled ? {} : hoverStyle({ transform: 'translateY(-2px)', boxShadow: `0 6px 20px ${TMColors.success}77`, filter: 'brightness(1.06)' }, { transform: 'translateY(0)', boxShadow: `0 4px 14px ${TMColors.success}55`, filter: 'brightness(1)' })), children: [_jsx(IconArchive, {}), archiveButtonCaption] })] })] }));
236
+ // ----- Render principale --------------------------------------------------------------------
237
+ if (isLoading)
238
+ return null;
239
+ return _jsxs(_Fragment, { children: [_jsx(TMLayoutWaitingContainer, { direction: 'vertical', ...waitPanel, isCancelable: true, abortController: abortController, usePortal: true, children: _jsx(TMModal, { width: isSummaryPhase ? '95%' : '720px', height: isSummaryPhase ? '95%' : 'auto', onClose: closeModal, title: modalTitle, hidePopup: false, askClosingConfirm: archiveRows.length > 0, recenterOnResize: true, titleActions: renderOptionsMenu(), children: _jsxs("div", { style: styles.content, children: [hasMultipleTypes && _jsx("div", { style: styles.header, children: renderStepper({
240
+ steps,
241
+ phase,
242
+ hasMultipleTypes,
243
+ isBackLocked,
244
+ showBackArrow: isSummaryPhase,
245
+ onBack: backToTypeSelection,
246
+ onStepClick: (stepPhase) => (stepPhase === MultiDetailArchivePhase.SelectDcmtType ? backToTypeSelection() : setPhase(stepPhase)),
247
+ }) }), !isSummaryPhase
248
+ ? renderSelectDcmtType({ detailRelationItems, selectedRelation, onSelectRelation: selectRelation })
249
+ : (isSummaryReady
250
+ ? renderArchiveSummary()
251
+ : _jsx("div", { style: styles.loader, children: _jsx(LoadIndicator, { height: 40, width: 40 }) }))] }) }) }), isOpenAddForm && selectedRelation?.detailTID && (_jsx(TMDcmtForm, { isModal: true, titleModal: getDtdDisplayName(selectedItem?.detailDtd), TID: selectedRelation.detailTID, layoutMode: LayoutModes.Ark, showBackButton: false, allowButtonsRefs: false, inputMids: formInputMids, inputFile: editingRow?.__file ?? null, archiveListMode: {
252
+ isEditingRow: editingRowId !== undefined,
253
+ onUpsertRow: (values, file) => upsertRow(values, file),
254
+ }, onClose: closeAddForm, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, showDcmtFormSidebar: showDcmtFormSidebar, showTodoDcmtForm: showTodoDcmtForm, openFileUploaderPdfEditor: openFileUploaderPdfEditor, graphometricManager: graphometricManager })), isOpenMasterForm && masterDcmt?.TID !== undefined && masterDcmt?.DID !== undefined && (_jsx(TMDcmtForm, { isModal: true, titleModal: `${SDKUI_Localizator.Update}: ${getDtdDisplayName(dtd)}`, TID: masterDcmt.TID, DID: masterDcmt.DID, layoutMode: LayoutModes.Update, showBackButton: false, allowRelations: false, allowButtonsRefs: false, onSavedAsyncCallback: handleMasterSavedAsync, onClose: () => setIsOpenMasterForm(false), allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, onTaskCreateRequest: onTaskCreateRequest, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, showDcmtFormSidebar: showDcmtFormSidebar, showTodoDcmtForm: showTodoDcmtForm, openFileUploaderPdfEditor: openFileUploaderPdfEditor, graphometricManager: graphometricManager, editPdfForm: editPdfForm, openS4TViewer: openS4TViewer, fetchRemoteCertificates: fetchRemoteCertificates, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, onReferenceClick: onReferenceClick }))] });
255
+ };
256
+ export default TMMultiMasterDetailDcmtsForm;
@@ -0,0 +1,352 @@
1
+ import React from 'react';
2
+ import { DataListViewModes, DcmtTypeDescriptor, MetadataDescriptor, RelationDescriptor } from '@topconsultnpm/sdk-ts';
3
+ import { DataGridTypes, IColumnProps } from 'devextreme-react/data-grid';
4
+ import { TMPanelDimensionsMap } from '../../layout/panelManager/types';
5
+ import { DcmtInfo, MetadataValueDescriptorEx } from '../../../ts';
6
+ /** Relazione di dettaglio con il relativo tipo documento */
7
+ export interface DetailRelationItem {
8
+ relation: RelationDescriptor;
9
+ detailDtd: DcmtTypeDescriptor | undefined;
10
+ }
11
+ export interface MultiDetailStep {
12
+ phase: number;
13
+ label: React.ReactNode;
14
+ }
15
+ export type AccordionSection = 'masterInfo' | 'archivedDetails' | 'archiveList';
16
+ /**
17
+ * Stato del pannello che ospita una sezione. Lo espone il panel manager, il cui contesto è leggibile
18
+ * solo dentro l'albero del provider: da qui passa alle testate (vedi TMSummarySectionSlot)
19
+ */
20
+ export type SectionPanelState = {
21
+ isMaximized: boolean;
22
+ toggleMaximize: () => void;
23
+ };
24
+ /** Valore di un metadato letto da un documento: una cella del risultato di ricerca */
25
+ export type MetadataScalarValue = string | number | boolean | Date | null | undefined;
26
+ /**
27
+ * Riga del riepilogo: oltre ai campi di servizio (prefisso `__`) porta i valori dei metadati
28
+ * indicizzati per mid (`String(mid)`), come richiesto dal dataField delle colonne della griglia
29
+ */
30
+ export interface ArchiveRow {
31
+ /** Chiave della riga in griglia */
32
+ id: number;
33
+ /** Tipo documento di dettaglio a cui appartiene la riga */
34
+ __tid: number;
35
+ /** Valori compilati nel form, nel formato richiesto dall'archiviazione */
36
+ __values: Array<MetadataValueDescriptorEx>;
37
+ /** File da archiviare, se il tipo documento lo prevede */
38
+ __file?: File;
39
+ /** Valore del metadato mostrato in colonna, indicizzato per mid */
40
+ [mid: string]: string | number | Array<MetadataValueDescriptorEx> | File | undefined;
41
+ }
42
+ /**
43
+ * Cella nel render delle colonne del riepilogo: i valori dei metadati arrivano dal form come
44
+ * stringhe, quindi il `value` generico di DevExtreme si restringe
45
+ */
46
+ export type ArchiveRowCell = Omit<DataGridTypes.ColumnCellTemplateData<ArchiveRow, number>, 'value'> & {
47
+ readonly value?: string;
48
+ };
49
+ /**
50
+ * Modifiche di una riga in arrivo dalla griglia (mid -> nuovo valore): in modifica diretta ci sono
51
+ * solo i metadati testuali (vedi isInlineEditableMetadata) e l'editor svuotato restituisce null
52
+ */
53
+ export type ArchiveRowChanges = Record<string, string | null | undefined>;
54
+ /** Aggiornamento di una riga della griglia, con le sole modifiche possibili in linea */
55
+ export type ArchiveRowUpdatingEvent = Omit<DataGridTypes.RowUpdatingEvent<ArchiveRow, number>, 'newData'> & {
56
+ newData: ArchiveRowChanges;
57
+ };
58
+ export declare const SECTION_WEIGHTS: Record<AccordionSection, number>;
59
+ export declare const SECTION_HEADER_HEIGHT_PX = 30;
60
+ export declare const PANEL_GUTTER_PX = 10;
61
+ /** Il master è modificabile solo se il tipo documento lo consente */
62
+ export declare const canUpdateMasterCallback: (dtd?: DcmtTypeDescriptor, masterDcmt?: DcmtInfo) => boolean;
63
+ /** Permesso di archiviazione sul tipo documento di dettaglio */
64
+ export declare const canArchive: (dtd?: DcmtTypeDescriptor) => boolean;
65
+ /**
66
+ * Marcatore delle celle modificabili direttamente in griglia: il doppio clic le porta in modifica,
67
+ * quindi non deve aprire anche il form della riga
68
+ */
69
+ export declare const INLINE_EDITABLE_CELL_CLASS = "tm-cell-inline-editable";
70
+ /**
71
+ * Modifica diretta in griglia: solo il testo libero. Liste dati, calcolati, numeratori e speciali
72
+ * hanno editor e vincoli propri, date e numeri una formattazione dedicata: restano al form
73
+ */
74
+ export declare const isInlineEditableMetadata: (md: MetadataDescriptor) => boolean;
75
+ /** Colonne della griglia di riepilogo dai metadati (utente) del tipo documento */
76
+ export declare const buildColumnsFromDtd: (dtd: DcmtTypeDescriptor | undefined, renderDataListCell: (value: string | Date | number | undefined, dataListID: number, viewMode: DataListViewModes) => React.ReactElement) => Array<IColumnProps>;
77
+ export declare const getDetailDtdAsync: (detailTID: number | undefined) => Promise<DcmtTypeDescriptor | undefined>;
78
+ /** Nome visualizzato del tipo documento (localizzato se richiesto) */
79
+ export declare const getDtdDisplayName: (dtd: DcmtTypeDescriptor | undefined) => string;
80
+ /** Messaggio del blocco: con righe inserite il tipo documento non è più modificabile */
81
+ export declare const getBackLockedTitle: () => string;
82
+ /**
83
+ * Altezze dei pannelli impilati a partire dalle sezioni aperte:
84
+ * una sezione chiusa vale 0% e resta a schermo con la sola testata
85
+ * le aperte si spartiscono tutto lo spazio
86
+ */
87
+ export declare const sectionPanelHeights: (sections: Array<AccordionSection>, sectionsOpen: Record<AccordionSection, boolean>, currentDimensions?: TMPanelDimensionsMap) => TMPanelDimensionsMap;
88
+ export declare const multiDetailStyles: {
89
+ stepper: {
90
+ display: "flex";
91
+ alignItems: "center";
92
+ justifyContent: "center";
93
+ gap: string;
94
+ };
95
+ backArrow: {
96
+ display: "flex";
97
+ alignItems: "center";
98
+ justifyContent: "center";
99
+ width: string;
100
+ height: string;
101
+ borderRadius: string;
102
+ border: string;
103
+ color: string;
104
+ cursor: "pointer";
105
+ marginRight: string;
106
+ transition: "all 0.18s ease";
107
+ };
108
+ stepPill: {
109
+ display: "flex";
110
+ alignItems: "center";
111
+ gap: string;
112
+ padding: string;
113
+ borderRadius: string;
114
+ transition: "all 0.18s ease";
115
+ };
116
+ stepCircle: {
117
+ width: string;
118
+ height: string;
119
+ borderRadius: string;
120
+ color: "#ffffff";
121
+ display: "flex";
122
+ alignItems: "center";
123
+ justifyContent: "center";
124
+ fontSize: string;
125
+ fontWeight: number;
126
+ flexShrink: number;
127
+ transition: "all 0.18s ease";
128
+ };
129
+ stepLabel: {
130
+ fontSize: string;
131
+ whiteSpace: "nowrap";
132
+ display: "flex";
133
+ alignItems: "center";
134
+ };
135
+ stepConnector: {
136
+ width: string;
137
+ height: string;
138
+ margin: string;
139
+ borderRadius: string;
140
+ flexShrink: number;
141
+ };
142
+ stepTypeLabel: {
143
+ display: "flex";
144
+ alignItems: "center";
145
+ gap: string;
146
+ maxWidth: string;
147
+ };
148
+ stepTypeLabelText: {
149
+ overflow: "hidden";
150
+ textOverflow: "ellipsis";
151
+ whiteSpace: "nowrap";
152
+ };
153
+ selectContainer: {
154
+ display: "flex";
155
+ flexDirection: "column";
156
+ alignItems: "center";
157
+ flex: number;
158
+ gap: string;
159
+ overflow: "auto";
160
+ padding: string;
161
+ };
162
+ selectTitle: {
163
+ fontSize: string;
164
+ fontWeight: number;
165
+ color: string;
166
+ textAlign: "center";
167
+ marginBottom: string;
168
+ };
169
+ selectList: {
170
+ display: "flex";
171
+ flexDirection: "column";
172
+ gap: string;
173
+ width: string;
174
+ maxWidth: string;
175
+ };
176
+ typeCard: {
177
+ display: "flex";
178
+ alignItems: "center";
179
+ gap: string;
180
+ padding: string;
181
+ borderRadius: string;
182
+ cursor: "pointer";
183
+ boxShadow: "0 1px 3px rgba(0, 0, 0, 0.06)";
184
+ transition: "all 0.15s ease";
185
+ };
186
+ typeCardIcon: {
187
+ width: string;
188
+ height: string;
189
+ borderRadius: string;
190
+ background: string;
191
+ display: "flex";
192
+ alignItems: "center";
193
+ justifyContent: "center";
194
+ flexShrink: number;
195
+ };
196
+ typeCardName: {
197
+ flex: number;
198
+ fontSize: string;
199
+ fontWeight: number;
200
+ color: string;
201
+ whiteSpace: "normal";
202
+ wordBreak: "break-word";
203
+ lineHeight: number;
204
+ };
205
+ };
206
+ /** Stili delle sezioni collassabili: qui perché la testata comune (renderAccordionHeader) vive in questo file */
207
+ export declare const accordionStyles: {
208
+ accordion: {
209
+ display: "flex";
210
+ flexDirection: "column";
211
+ minHeight: number;
212
+ borderRadius: string;
213
+ border: string;
214
+ background: string;
215
+ overflow: "hidden";
216
+ };
217
+ accordionInPanel: {
218
+ flex: number;
219
+ };
220
+ accordionHeader: {
221
+ display: "flex";
222
+ alignItems: "center";
223
+ gap: string;
224
+ padding: string;
225
+ cursor: "pointer";
226
+ userSelect: "none";
227
+ transition: "background 0.15s ease";
228
+ outline: string;
229
+ flexShrink: number;
230
+ minHeight: string;
231
+ };
232
+ accordionTitle: {
233
+ flex: number;
234
+ fontSize: string;
235
+ fontWeight: number;
236
+ color: string;
237
+ display: "flex";
238
+ alignItems: "center";
239
+ gap: string;
240
+ minWidth: number;
241
+ };
242
+ accordionBadge: {
243
+ display: "inline-flex";
244
+ alignItems: "center";
245
+ justifyContent: "center";
246
+ minWidth: string;
247
+ height: string;
248
+ padding: string;
249
+ borderRadius: string;
250
+ background: string;
251
+ color: string;
252
+ fontSize: string;
253
+ fontWeight: number;
254
+ flexShrink: number;
255
+ };
256
+ accordionListBody: {
257
+ position: "relative";
258
+ flex: number;
259
+ minHeight: number;
260
+ display: "flex";
261
+ flexDirection: "column";
262
+ borderTop: string;
263
+ };
264
+ accordionListPlaceholder: {
265
+ display: "flex";
266
+ flex: number;
267
+ alignItems: "center";
268
+ justifyContent: "center";
269
+ gap: string;
270
+ padding: string;
271
+ color: string;
272
+ fontSize: string;
273
+ };
274
+ accordionExpandBtn: {
275
+ display: "inline-flex";
276
+ alignItems: "center";
277
+ justifyContent: "center";
278
+ width: string;
279
+ height: string;
280
+ padding: number;
281
+ borderRadius: string;
282
+ border: string;
283
+ background: string;
284
+ color: string;
285
+ cursor: "pointer";
286
+ flexShrink: number;
287
+ transition: "background 0.15s ease, color 0.15s ease";
288
+ };
289
+ };
290
+ export interface RenderStepperParams {
291
+ /** Passi da mostrare, in ordine di fase */
292
+ steps: Array<MultiDetailStep>;
293
+ /** Fase corrente: i passi con fase minore sono completati */
294
+ phase: number;
295
+ /** Con un solo tipo documento il numero dello step non si mostra */
296
+ hasMultipleTypes: boolean;
297
+ /** Con righe inserite il ritorno alla scelta del tipo è bloccato (freccia e step completato) */
298
+ isBackLocked: boolean;
299
+ /** La freccia di ritorno si mostra solo dove ha senso tornare indietro */
300
+ showBackArrow: boolean;
301
+ /** Ritorno indietro dalla freccia */
302
+ onBack: () => void;
303
+ /** Click su uno step completato: riceve la fase di destinazione */
304
+ onStepClick: (phase: number) => void;
305
+ }
306
+ export declare const renderStepper: ({ steps, phase, hasMultipleTypes, isBackLocked, showBackArrow, onBack, onStepClick }: RenderStepperParams) => import("react/jsx-runtime").JSX.Element;
307
+ export interface RenderSelectDcmtTypeParams {
308
+ /** Relazioni di dettaglio fra cui scegliere */
309
+ detailRelationItems: Array<DetailRelationItem>;
310
+ /** Relazione attualmente selezionata */
311
+ selectedRelation: RelationDescriptor | undefined;
312
+ /** Selezione di una relazione */
313
+ onSelectRelation: (item: DetailRelationItem) => void;
314
+ }
315
+ export declare const renderSelectDcmtType: ({ detailRelationItems, selectedRelation, onSelectRelation }: RenderSelectDcmtTypeParams) => import("react/jsx-runtime").JSX.Element;
316
+ export interface RenderAccordionHeaderParams {
317
+ /** Sezione a cui appartiene la testata */
318
+ section: AccordionSection;
319
+ /** Sezione aperta o collassata */
320
+ isOpen: boolean;
321
+ /** Tooltip del collasso */
322
+ tooltip: string;
323
+ /** Conteggio mostrato nel badge */
324
+ count: number;
325
+ /** Titolo della sezione (icona + testo) */
326
+ title: React.ReactNode;
327
+ /** Pulsanti specifici della sezione, mostrati prima di quello di ingrandimento */
328
+ actions?: React.ReactNode;
329
+ /** Stato del pannello che ospita la sezione: l'ingrandimento è quello del panel manager */
330
+ panel: SectionPanelState;
331
+ /** Apre/chiude la sezione */
332
+ onToggleOpen: (section: AccordionSection, isOpen: boolean) => void;
333
+ }
334
+ export declare const renderAccordionHeader: ({ section, isOpen, tooltip, count, title, actions, panel, onToggleOpen }: RenderAccordionHeaderParams) => import("react/jsx-runtime").JSX.Element;
335
+ /**
336
+ * Contenuto di un pannello: il contesto del panel manager è leggibile solo dentro l'albero del
337
+ * provider, quindi è qui che si prende lo stato di ingrandimento da passare alla sezione
338
+ */
339
+ export declare const TMSummarySectionSlot: ({ section, render, onBeforeMaximize }: {
340
+ section: AccordionSection;
341
+ render: (panel: SectionPanelState) => React.ReactNode;
342
+ onBeforeMaximize?: (section: AccordionSection) => void;
343
+ }) => import("react/jsx-runtime").JSX.Element;
344
+ /**
345
+ * Tiene allineate le altezze dei pannelli al collasso delle sezioni: il panel manager non
346
+ * conosce il collasso, quindi è qui che l'apertura di una sezione si traduce nelle nuove quote.
347
+ * Vive dentro il provider perché il contesto è leggibile solo lì
348
+ */
349
+ export declare const TMSectionPanelsHeights: ({ sections, sectionsOpen }: {
350
+ sections: Array<AccordionSection>;
351
+ sectionsOpen: Record<AccordionSection, boolean>;
352
+ }) => null;