@burdenoff/microfe-planmagnet 2026.930.25 → 2026.1001.2

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 (314) hide show
  1. package/dist/_virtual/__vite-browser-external.js +9 -0
  2. package/dist/_virtual/__vite-browser-external.js.map +1 -0
  3. package/dist/_virtual/_rolldown/runtime.js +5 -2
  4. package/dist/index.js +3 -1
  5. package/dist/node_modules/fflate/esm/browser.js +554 -0
  6. package/dist/node_modules/fflate/esm/browser.js.map +1 -0
  7. package/dist/node_modules/jszip/dist/jszip.min.js +3038 -0
  8. package/dist/node_modules/jszip/dist/jszip.min.js.map +1 -0
  9. package/dist/node_modules/pptxgenjs/dist/pptxgen.es.js +2151 -0
  10. package/dist/node_modules/pptxgenjs/dist/pptxgen.es.js.map +1 -0
  11. package/dist/node_modules/write-excel-file/browser/index.js +3 -0
  12. package/dist/node_modules/write-excel-file/modules/export/convertFileContentToUint8ArrayBrowser.js +13 -0
  13. package/dist/node_modules/write-excel-file/modules/export/convertFileContentToUint8ArrayBrowser.js.map +1 -0
  14. package/dist/node_modules/write-excel-file/modules/export/convertFilesContentToUint8Arrays.js +21 -0
  15. package/dist/node_modules/write-excel-file/modules/export/convertFilesContentToUint8Arrays.js.map +1 -0
  16. package/dist/node_modules/write-excel-file/modules/export/downloadBlob.js +11 -0
  17. package/dist/node_modules/write-excel-file/modules/export/downloadBlob.js.map +1 -0
  18. package/dist/node_modules/write-excel-file/modules/export/writeXlsxFileBrowser.js +23 -0
  19. package/dist/node_modules/write-excel-file/modules/export/writeXlsxFileBrowser.js.map +1 -0
  20. package/dist/node_modules/write-excel-file/modules/export/writeXlsxFileUniversal.js +22 -0
  21. package/dist/node_modules/write-excel-file/modules/export/writeXlsxFileUniversal.js.map +1 -0
  22. package/dist/node_modules/write-excel-file/modules/getSheetData/getSheetData.js +18 -0
  23. package/dist/node_modules/write-excel-file/modules/getSheetData/getSheetData.js.map +1 -0
  24. package/dist/node_modules/write-excel-file/modules/xlsx/features/conditionalFormatting.js +131 -0
  25. package/dist/node_modules/write-excel-file/modules/xlsx/features/conditionalFormatting.js.map +1 -0
  26. package/dist/node_modules/write-excel-file/modules/xlsx/features/images.js +188 -0
  27. package/dist/node_modules/write-excel-file/modules/xlsx/features/images.js.map +1 -0
  28. package/dist/node_modules/write-excel-file/modules/xlsx/features/stickyRowsOrColumns.js +52 -0
  29. package/dist/node_modules/write-excel-file/modules/xlsx/features/stickyRowsOrColumns.js.map +1 -0
  30. package/dist/node_modules/write-excel-file/modules/xlsx/files/_Content_Types_.xml.js +18 -0
  31. package/dist/node_modules/write-excel-file/modules/xlsx/files/_Content_Types_.xml.js.map +1 -0
  32. package/dist/node_modules/write-excel-file/modules/xlsx/files/drawing.xml.js +18 -0
  33. package/dist/node_modules/write-excel-file/modules/xlsx/files/drawing.xml.js.map +1 -0
  34. package/dist/node_modules/write-excel-file/modules/xlsx/files/drawing.xml.rels.js +17 -0
  35. package/dist/node_modules/write-excel-file/modules/xlsx/files/drawing.xml.rels.js.map +1 -0
  36. package/dist/node_modules/write-excel-file/modules/xlsx/files/rels.js +11 -0
  37. package/dist/node_modules/write-excel-file/modules/xlsx/files/rels.js.map +1 -0
  38. package/dist/node_modules/write-excel-file/modules/xlsx/files/sharedStrings.xml.js +42 -0
  39. package/dist/node_modules/write-excel-file/modules/xlsx/files/sharedStrings.xml.js.map +1 -0
  40. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/cell.js +102 -0
  41. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/cell.js.map +1 -0
  42. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/column.js +17 -0
  43. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/column.js.map +1 -0
  44. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/columns.js +15 -0
  45. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/columns.js.map +1 -0
  46. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/drawingReference.js +8 -0
  47. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/drawingReference.js.map +1 -0
  48. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/helpers/getCellStyleProperties.js +71 -0
  49. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/helpers/getCellStyleProperties.js.map +1 -0
  50. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/mergedCellsDescription.js +56 -0
  51. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/mergedCellsDescription.js.map +1 -0
  52. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/pageMargins.js +15 -0
  53. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/pageMargins.js.map +1 -0
  54. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/pageSetup.js +13 -0
  55. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/pageSetup.js.map +1 -0
  56. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/processMergedCells.js +44 -0
  57. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/processMergedCells.js.map +1 -0
  58. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/row.js +123 -0
  59. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/row.js.map +1 -0
  60. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/sheet.xml.js +41 -0
  61. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/sheet.xml.js.map +1 -0
  62. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/sheetData.js +11 -0
  63. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/sheetData.js.map +1 -0
  64. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/sheetViews.js +17 -0
  65. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml/sheetViews.js.map +1 -0
  66. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml.rels.js +20 -0
  67. package/dist/node_modules/write-excel-file/modules/xlsx/files/sheet.xml.rels.js.map +1 -0
  68. package/dist/node_modules/write-excel-file/modules/xlsx/files/styles.xml.js +77 -0
  69. package/dist/node_modules/write-excel-file/modules/xlsx/files/styles.xml.js.map +1 -0
  70. package/dist/node_modules/write-excel-file/modules/xlsx/files/workbook.xml.js +22 -0
  71. package/dist/node_modules/write-excel-file/modules/xlsx/files/workbook.xml.js.map +1 -0
  72. package/dist/node_modules/write-excel-file/modules/xlsx/files/workbook.xml.rels.js +13 -0
  73. package/dist/node_modules/write-excel-file/modules/xlsx/files/workbook.xml.rels.js.map +1 -0
  74. package/dist/node_modules/write-excel-file/modules/xlsx/generateXlsxFileContents.js +242 -0
  75. package/dist/node_modules/write-excel-file/modules/xlsx/generateXlsxFileContents.js.map +1 -0
  76. package/dist/node_modules/write-excel-file/modules/xlsx/getFeatures.js +29 -0
  77. package/dist/node_modules/write-excel-file/modules/xlsx/getFeatures.js.map +1 -0
  78. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/convertDateToSerialNumber.js +9 -0
  79. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/convertDateToSerialNumber.js.map +1 -0
  80. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/getAdditionalContent.js +42 -0
  81. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/getAdditionalContent.js.map +1 -0
  82. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/getElementXml.js +43 -0
  83. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/getElementXml.js.map +1 -0
  84. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/getWrittenFiles.js +93 -0
  85. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/getWrittenFiles.js.map +1 -0
  86. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/transformContent.js +39 -0
  87. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/features/transformContent.js.map +1 -0
  88. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getAlignmentXml.js +17 -0
  89. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getAlignmentXml.js.map +1 -0
  90. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getBorderXml.js +29 -0
  91. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getBorderXml.js.map +1 -0
  92. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getCellAddress.js +14 -0
  93. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getCellAddress.js.map +1 -0
  94. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getFileExtensionForContentType.js +11 -0
  95. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getFileExtensionForContentType.js.map +1 -0
  96. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getFillXml.js +14 -0
  97. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getFillXml.js.map +1 -0
  98. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getFontXml.js +12 -0
  99. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getFontXml.js.map +1 -0
  100. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getOrderOfSiblings.js +24 -0
  101. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getOrderOfSiblings.js.map +1 -0
  102. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getXlsxColorForHexColor.js +9 -0
  103. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/getXlsxColorForHexColor.js.map +1 -0
  104. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasAlignment.js +9 -0
  105. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasAlignment.js.map +1 -0
  106. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasBorder.js +9 -0
  107. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasBorder.js.map +1 -0
  108. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasFill.js +9 -0
  109. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasFill.js.map +1 -0
  110. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasFont.js +9 -0
  111. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/hasFont.js.map +1 -0
  112. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/isCellObject.js +9 -0
  113. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/isCellObject.js.map +1 -0
  114. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/isObject.js +9 -0
  115. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/isObject.js.map +1 -0
  116. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/orderOfSiblings.js +27 -0
  117. package/dist/node_modules/write-excel-file/modules/xlsx/helpers/orderOfSiblings.js.map +1 -0
  118. package/dist/node_modules/write-excel-file/modules/xlsx/initializeSharedStrings.js +17 -0
  119. package/dist/node_modules/write-excel-file/modules/xlsx/initializeSharedStrings.js.map +1 -0
  120. package/dist/node_modules/write-excel-file/modules/xlsx/initializeSheets.js +74 -0
  121. package/dist/node_modules/write-excel-file/modules/xlsx/initializeSheets.js.map +1 -0
  122. package/dist/node_modules/write-excel-file/modules/xlsx/initializeStyles.js +138 -0
  123. package/dist/node_modules/write-excel-file/modules/xlsx/initializeStyles.js.map +1 -0
  124. package/dist/node_modules/write-excel-file/modules/xlsx/validateSheetData.js +40 -0
  125. package/dist/node_modules/write-excel-file/modules/xlsx/validateSheetData.js.map +1 -0
  126. package/dist/node_modules/write-excel-file/modules/xlsx/validateSheetName.js +11 -0
  127. package/dist/node_modules/write-excel-file/modules/xlsx/validateSheetName.js.map +1 -0
  128. package/dist/node_modules/write-excel-file/modules/xml/appendMarkupInsideElement.js +9 -0
  129. package/dist/node_modules/write-excel-file/modules/xml/appendMarkupInsideElement.js.map +1 -0
  130. package/dist/node_modules/write-excel-file/modules/xml/applyEnclosingElementOffset.js +9 -0
  131. package/dist/node_modules/write-excel-file/modules/xml/applyEnclosingElementOffset.js.map +1 -0
  132. package/dist/node_modules/write-excel-file/modules/xml/escapeXmlSpecialCharacters.js +12 -0
  133. package/dist/node_modules/write-excel-file/modules/xml/escapeXmlSpecialCharacters.js.map +1 -0
  134. package/dist/node_modules/write-excel-file/modules/xml/findElement.js +12 -0
  135. package/dist/node_modules/write-excel-file/modules/xml/findElement.js.map +1 -0
  136. package/dist/node_modules/write-excel-file/modules/xml/findElementInsideElement.js +12 -0
  137. package/dist/node_modules/write-excel-file/modules/xml/findElementInsideElement.js.map +1 -0
  138. package/dist/node_modules/write-excel-file/modules/xml/findElementsNonRecursive_.js +41 -0
  139. package/dist/node_modules/write-excel-file/modules/xml/findElementsNonRecursive_.js.map +1 -0
  140. package/dist/node_modules/write-excel-file/modules/xml/getAttributesString.js +14 -0
  141. package/dist/node_modules/write-excel-file/modules/xml/getAttributesString.js.map +1 -0
  142. package/dist/node_modules/write-excel-file/modules/xml/getChildElements.js +42 -0
  143. package/dist/node_modules/write-excel-file/modules/xml/getChildElements.js.map +1 -0
  144. package/dist/node_modules/write-excel-file/modules/xml/getClosingTagMarkup.js +8 -0
  145. package/dist/node_modules/write-excel-file/modules/xml/getClosingTagMarkup.js.map +1 -0
  146. package/dist/node_modules/write-excel-file/modules/xml/getMarkupInsideElement.js +8 -0
  147. package/dist/node_modules/write-excel-file/modules/xml/getMarkupInsideElement.js.map +1 -0
  148. package/dist/node_modules/write-excel-file/modules/xml/getOpeningTagMarkup.js +9 -0
  149. package/dist/node_modules/write-excel-file/modules/xml/getOpeningTagMarkup.js.map +1 -0
  150. package/dist/node_modules/write-excel-file/modules/xml/getSelfClosingTagMarkup.js +9 -0
  151. package/dist/node_modules/write-excel-file/modules/xml/getSelfClosingTagMarkup.js.map +1 -0
  152. package/dist/node_modules/write-excel-file/modules/xml/insertElementMarkupAccordingToOrderOfSiblings.js +64 -0
  153. package/dist/node_modules/write-excel-file/modules/xml/insertElementMarkupAccordingToOrderOfSiblings.js.map +1 -0
  154. package/dist/node_modules/write-excel-file/modules/xml/prependMarkupInsideElement.js +9 -0
  155. package/dist/node_modules/write-excel-file/modules/xml/prependMarkupInsideElement.js.map +1 -0
  156. package/dist/node_modules/write-excel-file/modules/xml/removeInvalidXmlCharacters.js +9 -0
  157. package/dist/node_modules/write-excel-file/modules/xml/removeInvalidXmlCharacters.js.map +1 -0
  158. package/dist/node_modules/write-excel-file/modules/xml/replaceElement.js +8 -0
  159. package/dist/node_modules/write-excel-file/modules/xml/replaceElement.js.map +1 -0
  160. package/dist/node_modules/write-excel-file/modules/xml/sanitizeAttributeName.js +10 -0
  161. package/dist/node_modules/write-excel-file/modules/xml/sanitizeAttributeName.js.map +1 -0
  162. package/dist/node_modules/write-excel-file/modules/xml/sanitizeAttributeValue.js +11 -0
  163. package/dist/node_modules/write-excel-file/modules/xml/sanitizeAttributeValue.js.map +1 -0
  164. package/dist/node_modules/write-excel-file/modules/xml/sanitizeTextContent.js +11 -0
  165. package/dist/node_modules/write-excel-file/modules/xml/sanitizeTextContent.js.map +1 -0
  166. package/dist/node_modules/write-excel-file/modules/xml/setMarkupInsideElement.js +8 -0
  167. package/dist/node_modules/write-excel-file/modules/xml/setMarkupInsideElement.js.map +1 -0
  168. package/dist/node_modules/write-excel-file/modules/zip/zipToArrayBuffer.js +18 -0
  169. package/dist/node_modules/write-excel-file/modules/zip/zipToArrayBuffer.js.map +1 -0
  170. package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
  171. package/dist/planmagnet/PlanMagnetRoot.js +160 -147
  172. package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
  173. package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
  174. package/dist/planmagnet/PlanMagnetRoutes.js +126 -106
  175. package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
  176. package/dist/planmagnet/comments/CommentThread.js +36 -36
  177. package/dist/planmagnet/comments/RoadmapComments.js +21 -21
  178. package/dist/planmagnet/controls/AutomationRuleControls.js +24 -24
  179. package/dist/planmagnet/controls/FeatureControls.js +60 -60
  180. package/dist/planmagnet/controls/Pickers.d.ts +10 -0
  181. package/dist/planmagnet/controls/Pickers.d.ts.map +1 -1
  182. package/dist/planmagnet/controls/Pickers.js +75 -27
  183. package/dist/planmagnet/controls/Pickers.js.map +1 -1
  184. package/dist/planmagnet/controls/SyncControls.js +59 -59
  185. package/dist/planmagnet/discussion/WorkItemDiscussionPanel.js +15 -15
  186. package/dist/planmagnet/docs/DocSuggestionsPanel.js +12 -12
  187. package/dist/planmagnet/docs/DocVersionCompare.js +3 -3
  188. package/dist/planmagnet/forecast/DeliveryForecastCard.d.ts +12 -0
  189. package/dist/planmagnet/forecast/DeliveryForecastCard.d.ts.map +1 -0
  190. package/dist/planmagnet/forecast/DeliveryForecastCard.js +208 -0
  191. package/dist/planmagnet/forecast/DeliveryForecastCard.js.map +1 -0
  192. package/dist/planmagnet/forecast/ProjectOutlookCard.d.ts +5 -0
  193. package/dist/planmagnet/forecast/ProjectOutlookCard.d.ts.map +1 -0
  194. package/dist/planmagnet/forecast/ProjectOutlookCard.js +190 -0
  195. package/dist/planmagnet/forecast/ProjectOutlookCard.js.map +1 -0
  196. package/dist/planmagnet/forecast/ProjectRiskSummaryCard.d.ts +5 -0
  197. package/dist/planmagnet/forecast/ProjectRiskSummaryCard.d.ts.map +1 -0
  198. package/dist/planmagnet/forecast/ProjectRiskSummaryCard.js +99 -0
  199. package/dist/planmagnet/forecast/ProjectRiskSummaryCard.js.map +1 -0
  200. package/dist/planmagnet/forecast/ResourceForecastCard.d.ts +8 -0
  201. package/dist/planmagnet/forecast/ResourceForecastCard.d.ts.map +1 -0
  202. package/dist/planmagnet/forecast/ResourceForecastCard.js +185 -0
  203. package/dist/planmagnet/forecast/ResourceForecastCard.js.map +1 -0
  204. package/dist/planmagnet/forecast/riskFlags.d.ts +35 -0
  205. package/dist/planmagnet/forecast/riskFlags.d.ts.map +1 -0
  206. package/dist/planmagnet/forecast/riskFlags.js +37 -0
  207. package/dist/planmagnet/forecast/riskFlags.js.map +1 -0
  208. package/dist/planmagnet/index.d.ts +2 -0
  209. package/dist/planmagnet/index.d.ts.map +1 -1
  210. package/dist/planmagnet/index.js +2 -0
  211. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.d.ts.map +1 -1
  212. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js +216 -182
  213. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
  214. package/dist/planmagnet/pages/AutomationAutomationRuleDetailPagePage.js +11 -11
  215. package/dist/planmagnet/pages/AutomationCreateAutomationRulePagePage.js +4 -4
  216. package/dist/planmagnet/pages/DocsDocDetailPagePage.js +163 -163
  217. package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
  218. package/dist/planmagnet/pages/IntegrationsNewSyncPagePage.js +165 -165
  219. package/dist/planmagnet/pages/IntegrationsNewSyncPagePage.js.map +1 -1
  220. package/dist/planmagnet/pages/ProjectsAtRiskPagePage.d.ts +2 -0
  221. package/dist/planmagnet/pages/ProjectsAtRiskPagePage.d.ts.map +1 -0
  222. package/dist/planmagnet/pages/ProjectsAtRiskPagePage.js +234 -0
  223. package/dist/planmagnet/pages/ProjectsAtRiskPagePage.js.map +1 -0
  224. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
  225. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +206 -182
  226. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -1
  227. package/dist/planmagnet/pages/ReportsCreateReportPagePage.d.ts +6 -0
  228. package/dist/planmagnet/pages/ReportsCreateReportPagePage.d.ts.map +1 -1
  229. package/dist/planmagnet/pages/ReportsCreateReportPagePage.js +5 -177
  230. package/dist/planmagnet/pages/ReportsCreateReportPagePage.js.map +1 -1
  231. package/dist/planmagnet/pages/ReportsEditReportPagePage.d.ts +3 -0
  232. package/dist/planmagnet/pages/ReportsEditReportPagePage.d.ts.map +1 -0
  233. package/dist/planmagnet/pages/ReportsEditReportPagePage.js +15 -0
  234. package/dist/planmagnet/pages/ReportsEditReportPagePage.js.map +1 -0
  235. package/dist/planmagnet/pages/ReportsReportPagePage.d.ts +7 -0
  236. package/dist/planmagnet/pages/ReportsReportPagePage.d.ts.map +1 -0
  237. package/dist/planmagnet/pages/ReportsReportPagePage.js +226 -0
  238. package/dist/planmagnet/pages/ReportsReportPagePage.js.map +1 -0
  239. package/dist/planmagnet/pages/ReportsReportsPagePage.d.ts.map +1 -1
  240. package/dist/planmagnet/pages/ReportsReportsPagePage.js +224 -496
  241. package/dist/planmagnet/pages/ReportsReportsPagePage.js.map +1 -1
  242. package/dist/planmagnet/pages/TeamTeamDetailPagePage.d.ts.map +1 -1
  243. package/dist/planmagnet/pages/TeamTeamDetailPagePage.js +88 -83
  244. package/dist/planmagnet/pages/TeamTeamDetailPagePage.js.map +1 -1
  245. package/dist/planmagnet/pages/analytics/SprintDeliveryCards.d.ts.map +1 -1
  246. package/dist/planmagnet/pages/analytics/SprintDeliveryCards.js +139 -112
  247. package/dist/planmagnet/pages/analytics/SprintDeliveryCards.js.map +1 -1
  248. package/dist/planmagnet/pages/analytics/StatusFlowCard.js +21 -21
  249. package/dist/planmagnet/product/ProductControls.js +91 -91
  250. package/dist/planmagnet/reports/ExportMenu.d.ts +9 -0
  251. package/dist/planmagnet/reports/ExportMenu.d.ts.map +1 -0
  252. package/dist/planmagnet/reports/ExportMenu.js +116 -0
  253. package/dist/planmagnet/reports/ExportMenu.js.map +1 -0
  254. package/dist/planmagnet/reports/PrintReportView.d.ts +24 -0
  255. package/dist/planmagnet/reports/PrintReportView.d.ts.map +1 -0
  256. package/dist/planmagnet/reports/PrintReportView.js +75 -0
  257. package/dist/planmagnet/reports/PrintReportView.js.map +1 -0
  258. package/dist/planmagnet/reports/ReportBuilderCanvas.d.ts +8 -0
  259. package/dist/planmagnet/reports/ReportBuilderCanvas.d.ts.map +1 -0
  260. package/dist/planmagnet/reports/ReportBuilderCanvas.js +261 -0
  261. package/dist/planmagnet/reports/ReportBuilderCanvas.js.map +1 -0
  262. package/dist/planmagnet/reports/ReportBuilderPage.d.ts +5 -0
  263. package/dist/planmagnet/reports/ReportBuilderPage.d.ts.map +1 -0
  264. package/dist/planmagnet/reports/ReportBuilderPage.js +198 -0
  265. package/dist/planmagnet/reports/ReportBuilderPage.js.map +1 -0
  266. package/dist/planmagnet/reports/ReportRunHistory.d.ts +8 -0
  267. package/dist/planmagnet/reports/ReportRunHistory.d.ts.map +1 -0
  268. package/dist/planmagnet/reports/ReportRunHistory.js +63 -0
  269. package/dist/planmagnet/reports/ReportRunHistory.js.map +1 -0
  270. package/dist/planmagnet/reports/ReportWidgetRenderer.d.ts +7 -0
  271. package/dist/planmagnet/reports/ReportWidgetRenderer.d.ts.map +1 -0
  272. package/dist/planmagnet/reports/ReportWidgetRenderer.js +251 -0
  273. package/dist/planmagnet/reports/ReportWidgetRenderer.js.map +1 -0
  274. package/dist/planmagnet/reports/SchedulesPanel.d.ts +4 -0
  275. package/dist/planmagnet/reports/SchedulesPanel.d.ts.map +1 -0
  276. package/dist/planmagnet/reports/SchedulesPanel.js +457 -0
  277. package/dist/planmagnet/reports/SchedulesPanel.js.map +1 -0
  278. package/dist/planmagnet/reports/ShareDialog.d.ts +5 -0
  279. package/dist/planmagnet/reports/ShareDialog.d.ts.map +1 -0
  280. package/dist/planmagnet/reports/ShareDialog.js +234 -0
  281. package/dist/planmagnet/reports/ShareDialog.js.map +1 -0
  282. package/dist/planmagnet/reports/SharedReportPage.d.ts +4 -0
  283. package/dist/planmagnet/reports/SharedReportPage.d.ts.map +1 -0
  284. package/dist/planmagnet/reports/SharedReportPage.js +180 -0
  285. package/dist/planmagnet/reports/SharedReportPage.js.map +1 -0
  286. package/dist/planmagnet/reports/WidgetEditorDialog.d.ts +10 -0
  287. package/dist/planmagnet/reports/WidgetEditorDialog.d.ts.map +1 -0
  288. package/dist/planmagnet/reports/WidgetEditorDialog.js +220 -0
  289. package/dist/planmagnet/reports/WidgetEditorDialog.js.map +1 -0
  290. package/dist/planmagnet/reports/reportExportPptx.d.ts +4 -0
  291. package/dist/planmagnet/reports/reportExportPptx.d.ts.map +1 -0
  292. package/dist/planmagnet/reports/reportExportPptx.js +118 -0
  293. package/dist/planmagnet/reports/reportExportPptx.js.map +1 -0
  294. package/dist/planmagnet/reports/reportExportXlsx.d.ts +4 -0
  295. package/dist/planmagnet/reports/reportExportXlsx.d.ts.map +1 -0
  296. package/dist/planmagnet/reports/reportExportXlsx.js +42 -0
  297. package/dist/planmagnet/reports/reportExportXlsx.js.map +1 -0
  298. package/dist/planmagnet/reports/reportGraphql.d.ts +28 -0
  299. package/dist/planmagnet/reports/reportGraphql.d.ts.map +1 -0
  300. package/dist/planmagnet/reports/reportGraphql.js +360 -0
  301. package/dist/planmagnet/reports/reportGraphql.js.map +1 -0
  302. package/dist/planmagnet/reports/reportModel.d.ts +198 -0
  303. package/dist/planmagnet/reports/reportModel.d.ts.map +1 -0
  304. package/dist/planmagnet/reports/reportModel.js +328 -0
  305. package/dist/planmagnet/reports/reportModel.js.map +1 -0
  306. package/dist/planmagnet/reports/sharedReportRoute.d.ts +15 -0
  307. package/dist/planmagnet/reports/sharedReportRoute.d.ts.map +1 -0
  308. package/dist/planmagnet/reports/sharedReportRoute.js +9 -0
  309. package/dist/planmagnet/reports/sharedReportRoute.js.map +1 -0
  310. package/dist/planmagnet/roadmaps/RoadmapControls.js +60 -60
  311. package/dist/planmagnet/roadmaps/RoadmapNowNextLater.js +30 -30
  312. package/dist/planmagnet/roadmaps/RoadmapReviewPanel.js +21 -21
  313. package/dist/planmagnet/roadmaps/RoadmapVersionsPanel.js +22 -22
  314. package/package.json +6 -4
@@ -1,7 +1,7 @@
1
1
  import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
2
- import { throwOnError as t } from "../utils/mutationResult.js";
3
- import { ErrorLine as n } from "../controls/ConfirmButton.js";
4
- import { isForbidden as r, mutationErrorMessage as i } from "../utils/graphqlErrors.js";
2
+ import { isForbidden as t, mutationErrorMessage as n } from "../utils/graphqlErrors.js";
3
+ import { throwOnError as r } from "../utils/mutationResult.js";
4
+ import { ErrorLine as i } from "../controls/ConfirmButton.js";
5
5
  import { useDeferredValue as a, useEffect as o, useState as s } from "react";
6
6
  import { ExternalLink as c, MessageCircle as l, MessagesSquare as u, Unlink as d } from "lucide-react";
7
7
  import { gql as f } from "@apollo/client";
@@ -46,19 +46,19 @@ function P({ workItemId: c, workItemKey: l, workItemTitle: d, assigneeId: f }) {
46
46
  if (_) {
47
47
  H(null);
48
48
  try {
49
- let e = await t(G({ variables: { input: {
49
+ let e = await r(G({ variables: { input: {
50
50
  workspaceId: _,
51
51
  type: "GROUP",
52
52
  title: `${l}: ${d}`,
53
53
  participantIds: [...z]
54
- } } })), n = e.data?.createConversation?.conversation?.id;
55
- if (!e.data?.createConversation?.success || !n) throw Error("The conversation could not be created.");
56
- await t(q({ variables: {
54
+ } } })), t = e.data?.createConversation?.conversation?.id;
55
+ if (!e.data?.createConversation?.success || !t) throw Error("The conversation could not be created.");
56
+ await r(q({ variables: {
57
57
  workItemId: c,
58
- conversationId: n
58
+ conversationId: t
59
59
  } })), F(!1), L("");
60
60
  } catch (e) {
61
- H(r(e) ? "Your role cannot start a conversation in this workspace." : i(e, "The discussion could not be started."));
61
+ H(t(e) ? "Your role cannot start a conversation in this workspace." : n(e, "The discussion could not be started."));
62
62
  }
63
63
  }
64
64
  };
@@ -142,7 +142,7 @@ function P({ workItemId: c, workItemKey: l, workItemTitle: d, assigneeId: f }) {
142
142
  })
143
143
  ]
144
144
  }),
145
- V && /* @__PURE__ */ m(n, { message: V }),
145
+ V && /* @__PURE__ */ m(i, { message: V }),
146
146
  /* @__PURE__ */ m(E, { children: /* @__PURE__ */ m(g, {
147
147
  onClick: () => void Z(),
148
148
  disabled: z.size === 0 || Y,
@@ -153,16 +153,16 @@ function P({ workItemId: c, workItemKey: l, workItemTitle: d, assigneeId: f }) {
153
153
  })]
154
154
  });
155
155
  }
156
- function F({ workItemId: e, workItemKey: r, workItemTitle: a, assigneeId: o, discussionConversationId: u }) {
156
+ function F({ workItemId: e, workItemKey: t, workItemTitle: a, assigneeId: o, discussionConversationId: u }) {
157
157
  let [f, x] = p(j, N), [S, C] = s(null), w = async () => {
158
158
  C(null);
159
159
  try {
160
- await t(f({ variables: {
160
+ await r(f({ variables: {
161
161
  workItemId: e,
162
162
  conversationId: null
163
163
  } }));
164
164
  } catch (e) {
165
- C(i(e, "The discussion could not be unlinked."));
165
+ C(n(e, "The discussion could not be unlinked."));
166
166
  }
167
167
  };
168
168
  return /* @__PURE__ */ h(_, {
@@ -175,7 +175,7 @@ function F({ workItemId: e, workItemKey: r, workItemTitle: a, assigneeId: o, dis
175
175
  }), "Discussion"]
176
176
  }) }), /* @__PURE__ */ h(v, {
177
177
  className: "space-y-3",
178
- children: [S && /* @__PURE__ */ m(n, { message: S }), u ? /* @__PURE__ */ h("div", {
178
+ children: [S && /* @__PURE__ */ m(i, { message: S }), u ? /* @__PURE__ */ h("div", {
179
179
  className: "flex flex-wrap items-center justify-between gap-2",
180
180
  children: [/* @__PURE__ */ h("a", {
181
181
  href: `/conversations/${encodeURIComponent(u)}`,
@@ -203,7 +203,7 @@ function F({ workItemId: e, workItemKey: r, workItemTitle: a, assigneeId: o, dis
203
203
  children: "Not linked to a conversation yet. Starting one creates a group chat for this task in Conversations."
204
204
  }), /* @__PURE__ */ m(P, {
205
205
  workItemId: e,
206
- workItemKey: r,
206
+ workItemKey: t,
207
207
  workItemTitle: a,
208
208
  assigneeId: o
209
209
  })]
@@ -1,7 +1,7 @@
1
1
  import { PersonName as e } from "../people/People.js";
2
- import { throwOnError as t } from "../utils/mutationResult.js";
3
- import { ConfirmButton as n, ErrorLine as r } from "../controls/ConfirmButton.js";
4
- import { isConflict as i, isForbidden as a, mutationErrorMessage as o } from "../utils/graphqlErrors.js";
2
+ import { isConflict as t, isForbidden as n, mutationErrorMessage as r } from "../utils/graphqlErrors.js";
3
+ import { throwOnError as i } from "../utils/mutationResult.js";
4
+ import { ConfirmButton as a, ErrorLine as o } from "../controls/ConfirmButton.js";
5
5
  import { lineDiff as s } from "../utils/lineDiff.js";
6
6
  import { DocDiffHunks as c } from "./DocDiffView.js";
7
7
  import { useState as l } from "react";
@@ -62,12 +62,12 @@ function N({ suggestion: u, docTitle: f, docContent: m, revisions: y, currentUse
62
62
  }), [D, k] = p(j, {
63
63
  refetchQueries: [O],
64
64
  awaitRefetchQueries: !0
65
- }), N = y.find((e) => e.version === u.baseVersion), P = N?.content ?? m, F = N?.title ?? f, I = s(P, u.proposedContent), L = u.proposedTitle !== null && u.proposedTitle !== F, R = u.authorId === b, z = async (e, n) => {
65
+ }), N = y.find((e) => e.version === u.baseVersion), P = N?.content ?? m, F = N?.title ?? f, I = s(P, u.proposedContent), L = u.proposedTitle !== null && u.proposedTitle !== F, R = u.authorId === b, z = async (e, a) => {
66
66
  w(null);
67
67
  try {
68
- await t(e());
68
+ await i(e());
69
69
  } catch (e) {
70
- w(a(e) ? "Your role cannot decide this suggestion." : i(e) ? "The doc changed since this was suggested." : o(e, n));
70
+ w(n(e) ? "Your role cannot decide this suggestion." : t(e) ? "The doc changed since this was suggested." : r(e, a));
71
71
  }
72
72
  };
73
73
  return /* @__PURE__ */ _("li", {
@@ -119,7 +119,7 @@ function N({ suggestion: u, docTitle: f, docContent: m, revisions: y, currentUse
119
119
  children: x ? "Hide diff" : "Show diff"
120
120
  })]
121
121
  }),
122
- C && /* @__PURE__ */ g(r, { message: C }),
122
+ C && /* @__PURE__ */ g(o, { message: C }),
123
123
  x && /* @__PURE__ */ _("div", {
124
124
  className: "space-y-1",
125
125
  children: [L && /* @__PURE__ */ _("p", {
@@ -147,7 +147,7 @@ function N({ suggestion: u, docTitle: f, docContent: m, revisions: y, currentUse
147
147
  u.status === "OPEN" && /* @__PURE__ */ _("div", {
148
148
  className: "flex flex-wrap justify-end gap-2 border-t border-border-default pt-2",
149
149
  children: [
150
- R && /* @__PURE__ */ g(n, {
150
+ R && /* @__PURE__ */ g(a, {
151
151
  label: "Withdraw",
152
152
  icon: /* @__PURE__ */ g(d, {
153
153
  className: "h-3.5 w-3.5",
@@ -187,7 +187,7 @@ function N({ suggestion: u, docTitle: f, docContent: m, revisions: y, currentUse
187
187
  ]
188
188
  });
189
189
  }
190
- function P({ docId: e, status: t, docTitle: n, docContent: i, revisions: o, currentUserId: s }) {
190
+ function P({ docId: e, status: t, docTitle: r, docContent: i, revisions: a, currentUserId: s }) {
191
191
  let [c, u] = l(!1), { data: d, loading: f, error: p, fetchMore: h } = m(k, {
192
192
  variables: {
193
193
  docId: e,
@@ -229,7 +229,7 @@ function P({ docId: e, status: t, docTitle: n, docContent: i, revisions: o, curr
229
229
  className: "text-sm text-muted-foreground",
230
230
  children: "Loading…"
231
231
  }),
232
- p && /* @__PURE__ */ g(r, { message: a(p) ? "Your role cannot see this doc’s suggestions." : `Suggestions could not be loaded: ${p.message}` }),
232
+ p && /* @__PURE__ */ g(o, { message: n(p) ? "Your role cannot see this doc’s suggestions." : `Suggestions could not be loaded: ${p.message}` }),
233
233
  y && b.length === 0 && /* @__PURE__ */ g("p", {
234
234
  className: "text-sm text-muted-foreground",
235
235
  children: t === "OPEN" ? "No open suggestions." : t === "ACCEPTED" ? "None accepted yet." : "None rejected yet."
@@ -238,9 +238,9 @@ function P({ docId: e, status: t, docTitle: n, docContent: i, revisions: o, curr
238
238
  className: "space-y-2",
239
239
  children: b.map((e) => /* @__PURE__ */ g(N, {
240
240
  suggestion: e,
241
- docTitle: n,
241
+ docTitle: r,
242
242
  docContent: i,
243
- revisions: o,
243
+ revisions: a,
244
244
  currentUserId: s
245
245
  }, e.id))
246
246
  }),
@@ -1,5 +1,5 @@
1
- import { ErrorLine as e } from "../controls/ConfirmButton.js";
2
- import { isForbidden as t } from "../utils/graphqlErrors.js";
1
+ import { isForbidden as e } from "../utils/graphqlErrors.js";
2
+ import { ErrorLine as t } from "../controls/ConfirmButton.js";
3
3
  import { DocDiffHunks as n } from "./DocDiffView.js";
4
4
  import { useState as r } from "react";
5
5
  import { GitCompare as i } from "lucide-react";
@@ -90,7 +90,7 @@ function f({ docId: a, versions: f }) {
90
90
  "data-testid": "doc-version-compare-run",
91
91
  children: y.loading ? "Comparing…" : "Compare"
92
92
  }),
93
- y.error && /* @__PURE__ */ c(e, { message: t(y.error) ? "Your role cannot compare versions of this doc." : `The comparison could not be loaded: ${y.error.message}` }),
93
+ y.error && /* @__PURE__ */ c(t, { message: e(y.error) ? "Your role cannot compare versions of this doc." : `The comparison could not be loaded: ${y.error.message}` }),
94
94
  x && /* @__PURE__ */ c(n, {
95
95
  hunks: x.hunks,
96
96
  truncated: x.truncated,
@@ -0,0 +1,12 @@
1
+ export declare function DeliveryForecastCard({ workspaceId, projectId,
2
+ /** When set, the card offers an "only this sprint's items" toggle that narrows
3
+ * `scope.sprintId` to this sprint instead of the project's full remaining scope. Pass the
4
+ * active/current sprint of whatever page hosts this card — omit it where no single sprint
5
+ * is in context (the card then always forecasts the project's full open scope). */
6
+ sprintId, sprintName, }: {
7
+ workspaceId?: string | null;
8
+ projectId: string;
9
+ sprintId?: string | null;
10
+ sprintName?: string | null;
11
+ }): import("react/jsx-runtime").JSX.Element;
12
+ //# sourceMappingURL=DeliveryForecastCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeliveryForecastCard.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/forecast/DeliveryForecastCard.tsx"],"names":[],"mappings":"AAkFA,wBAAgB,oBAAoB,CAAC,EACnC,WAAW,EACX,SAAS;AACT;;;oFAGoF;AACpF,QAAQ,EACR,UAAU,GACX,EAAE;IACD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,2CAwMA"}
@@ -0,0 +1,208 @@
1
+ import { isForbidden as e } from "../utils/graphqlErrors.js";
2
+ import { useState as t } from "react";
3
+ import { CalendarRange as n } from "lucide-react";
4
+ import { gql as r } from "@apollo/client";
5
+ import { useQuery as i } from "@apollo/client/react";
6
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
7
+ import { useI18n as s } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
8
+ import { Card as c, CardContent as l, CardHeader as u, CardTitle as d, Checkbox as f } from "@burdenoff/fe-libs/ui";
9
+ //#region src/planmagnet/forecast/DeliveryForecastCard.tsx
10
+ var p = r`
11
+ query PlanmagnetDeliveryForecast(
12
+ $workspaceId: ID!
13
+ $projectId: ID!
14
+ $scope: PlanmagnetForecastScopeInput
15
+ ) {
16
+ planmagnetForecastDelivery(workspaceId: $workspaceId, projectId: $projectId, scope: $scope) {
17
+ method
18
+ insufficientHistory
19
+ reason
20
+ remainingPoints
21
+ unestimatedItems
22
+ scopeTruncated
23
+ confidenceNote
24
+ sprintsNeeded {
25
+ p50
26
+ p85
27
+ p95
28
+ }
29
+ dates {
30
+ p50
31
+ p85
32
+ p95
33
+ }
34
+ inputRefs {
35
+ sprintId
36
+ name
37
+ completedPoints
38
+ endDate
39
+ }
40
+ }
41
+ }
42
+ `;
43
+ function m(e) {
44
+ return new Date(e).toLocaleDateString(void 0, {
45
+ timeZone: "UTC",
46
+ year: "numeric",
47
+ month: "short",
48
+ day: "numeric"
49
+ });
50
+ }
51
+ function h({ workspaceId: r, projectId: h, sprintId: g, sprintName: _ }) {
52
+ let { t: v } = s(), [y, b] = t(!1), x = y && !!g, { data: S, loading: C, error: w } = i(p, {
53
+ variables: {
54
+ workspaceId: r,
55
+ projectId: h,
56
+ scope: x && g ? { sprintId: g } : void 0
57
+ },
58
+ skip: !r || !h
59
+ }), T = S?.planmagnetForecastDelivery;
60
+ return /* @__PURE__ */ o(c, {
61
+ "data-testid": "forecast-card",
62
+ children: [/* @__PURE__ */ o(u, { children: [
63
+ /* @__PURE__ */ o(d, {
64
+ className: "flex items-center gap-2",
65
+ children: [/* @__PURE__ */ a(n, { className: "h-4 w-4" }), v("planmagnet.forecast.delivery.title", "Delivery forecast")]
66
+ }),
67
+ /* @__PURE__ */ a("p", {
68
+ className: "text-xs text-muted-foreground",
69
+ children: x ? v("planmagnet.forecast.delivery.subtitleSprint", "For the open items of {{sprint}} only.", { sprint: _ ?? v("planmagnet.forecast.delivery.thisSprint", "this sprint") }) : v("planmagnet.forecast.delivery.subtitle", "For this project's own open, estimated work items.")
70
+ }),
71
+ g && /* @__PURE__ */ o("label", {
72
+ htmlFor: `forecast-scope-sprint-${h}`,
73
+ className: "flex items-center gap-2 pt-1 text-xs font-normal text-muted-foreground",
74
+ children: [/* @__PURE__ */ a(f, {
75
+ id: `forecast-scope-sprint-${h}`,
76
+ checked: y,
77
+ onCheckedChange: (e) => b(e === !0)
78
+ }), v("planmagnet.forecast.delivery.scopeToggle", "Only this sprint's items ({{sprint}})", { sprint: _ ?? v("planmagnet.forecast.delivery.thisSprint", "this sprint") })]
79
+ })
80
+ ] }), /* @__PURE__ */ a(l, { children: h ? C && !S ? /* @__PURE__ */ a("div", {
81
+ className: "flex justify-center py-8",
82
+ children: /* @__PURE__ */ a("div", { className: "animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full" })
83
+ }) : w ? /* @__PURE__ */ a("p", {
84
+ className: "text-sm text-status-error-text",
85
+ children: e(w) ? v("planmagnet.forecast.delivery.forbidden", "You do not have access to the delivery forecast for this project.") : `${v("planmagnet.forecast.delivery.error", "Delivery forecast could not be loaded")}: ${w.message}`
86
+ }) : T ? T.insufficientHistory ? /* @__PURE__ */ o("div", {
87
+ className: "space-y-2",
88
+ "data-testid": "forecast-insufficient",
89
+ children: [/* @__PURE__ */ a("p", {
90
+ className: "text-sm text-muted-foreground",
91
+ children: T.reason ?? v("planmagnet.forecast.delivery.insufficientFallback", "Not enough completed-sprint history yet to forecast a delivery date.")
92
+ }), /* @__PURE__ */ a("p", {
93
+ className: "text-xs text-muted-foreground",
94
+ children: T.confidenceNote
95
+ })]
96
+ }) : /* @__PURE__ */ o("div", {
97
+ className: "space-y-4",
98
+ children: [
99
+ /* @__PURE__ */ o("dl", {
100
+ className: "grid grid-cols-3 gap-3 text-center",
101
+ "data-testid": "forecast-dates",
102
+ children: [
103
+ /* @__PURE__ */ o("div", {
104
+ className: "rounded-md border p-2.5",
105
+ children: [
106
+ /* @__PURE__ */ a("dt", {
107
+ className: "text-xs text-muted-foreground",
108
+ children: v("planmagnet.forecast.delivery.p50Label", "Likely by (p50)")
109
+ }),
110
+ /* @__PURE__ */ a("dd", {
111
+ className: "mt-1 text-sm font-semibold",
112
+ children: T.dates ? m(T.dates.p50) : "—"
113
+ }),
114
+ /* @__PURE__ */ a("dd", {
115
+ className: "text-xs text-muted-foreground",
116
+ children: T.sprintsNeeded ? v("planmagnet.forecast.delivery.sprints", "{{count}} sprint(s)", { count: T.sprintsNeeded.p50 }) : "—"
117
+ })
118
+ ]
119
+ }),
120
+ /* @__PURE__ */ o("div", {
121
+ className: "rounded-md border p-2.5",
122
+ children: [
123
+ /* @__PURE__ */ a("dt", {
124
+ className: "text-xs text-muted-foreground",
125
+ children: v("planmagnet.forecast.delivery.p85Label", "Confident by (p85)")
126
+ }),
127
+ /* @__PURE__ */ a("dd", {
128
+ className: "mt-1 text-sm font-semibold",
129
+ children: T.dates ? m(T.dates.p85) : "—"
130
+ }),
131
+ /* @__PURE__ */ a("dd", {
132
+ className: "text-xs text-muted-foreground",
133
+ children: T.sprintsNeeded ? v("planmagnet.forecast.delivery.sprints", "{{count}} sprint(s)", { count: T.sprintsNeeded.p85 }) : "—"
134
+ })
135
+ ]
136
+ }),
137
+ /* @__PURE__ */ o("div", {
138
+ className: "rounded-md border p-2.5",
139
+ children: [
140
+ /* @__PURE__ */ a("dt", {
141
+ className: "text-xs text-muted-foreground",
142
+ children: v("planmagnet.forecast.delivery.p95Label", "Very confident by (p95)")
143
+ }),
144
+ /* @__PURE__ */ a("dd", {
145
+ className: "mt-1 text-sm font-semibold",
146
+ children: T.dates ? m(T.dates.p95) : "—"
147
+ }),
148
+ /* @__PURE__ */ a("dd", {
149
+ className: "text-xs text-muted-foreground",
150
+ children: T.sprintsNeeded ? v("planmagnet.forecast.delivery.sprints", "{{count}} sprint(s)", { count: T.sprintsNeeded.p95 }) : "—"
151
+ })
152
+ ]
153
+ })
154
+ ]
155
+ }),
156
+ /* @__PURE__ */ o("div", {
157
+ className: "flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground",
158
+ children: [/* @__PURE__ */ a("span", { children: v("planmagnet.forecast.delivery.remaining", "Remaining: {{points}} pts", { points: T.remainingPoints }) }), T.unestimatedItems > 0 && /* @__PURE__ */ a("span", {
159
+ className: "text-status-warning-text",
160
+ children: v("planmagnet.forecast.delivery.unestimated", "{{count}} open item(s) have no estimate (counted as 0 pts)", { count: T.unestimatedItems })
161
+ })]
162
+ }),
163
+ T.scopeTruncated && /* @__PURE__ */ a("p", {
164
+ className: "text-xs text-status-warning-text",
165
+ children: v("planmagnet.forecast.delivery.truncated", "This scope is large enough that the scan stopped early — remaining points and unestimated items reflect only the first items found, not the whole project.")
166
+ }),
167
+ /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("h3", {
168
+ className: "mb-1 text-sm font-medium",
169
+ children: v("planmagnet.forecast.delivery.evidence", "Based on")
170
+ }), /* @__PURE__ */ o("ul", {
171
+ className: "space-y-1 text-xs text-muted-foreground",
172
+ "data-testid": "forecast-inputs",
173
+ children: [T.inputRefs.map((e) => /* @__PURE__ */ o("li", {
174
+ className: "flex items-center justify-between gap-2",
175
+ children: [/* @__PURE__ */ a("span", {
176
+ className: "truncate",
177
+ children: e.name
178
+ }), /* @__PURE__ */ o("span", {
179
+ className: "shrink-0 tabular-nums",
180
+ children: [v("planmagnet.forecast.delivery.evidenceRow", "{{points}} pts", { points: e.completedPoints }), e.endDate ? ` · ${m(e.endDate)}` : ""]
181
+ })]
182
+ }, e.sprintId)), T.inputRefs.length === 0 && /* @__PURE__ */ a("li", { children: v("planmagnet.forecast.delivery.noInputs", "No sprint history available.") })]
183
+ })] }),
184
+ /* @__PURE__ */ a("p", {
185
+ className: "text-xs text-muted-foreground",
186
+ children: T.confidenceNote
187
+ }),
188
+ /* @__PURE__ */ o("details", {
189
+ className: "text-xs text-muted-foreground",
190
+ children: [/* @__PURE__ */ a("summary", {
191
+ className: "cursor-pointer select-none font-medium text-foreground",
192
+ children: v("planmagnet.forecast.whatIsThis", "What is this?")
193
+ }), /* @__PURE__ */ a("p", {
194
+ className: "mt-1",
195
+ children: v("planmagnet.forecast.delivery.explainer", "Statistical forecast (Monte Carlo over past sprints): a simulation that resamples this project’s trailing completed sprints’ real velocities thousands of times to see how many more sprints the remaining work is likely to take. It is never an AI/LLM call, and it never invents a date from a sample it doesn’t trust — when history is too thin, it says so instead of guessing.")
196
+ })]
197
+ })
198
+ ]
199
+ }) : null : /* @__PURE__ */ a("p", {
200
+ className: "text-sm text-muted-foreground",
201
+ children: v("planmagnet.forecast.delivery.noProject", "Select a project to see its forecast.")
202
+ }) })]
203
+ });
204
+ }
205
+ //#endregion
206
+ export { h as DeliveryForecastCard };
207
+
208
+ //# sourceMappingURL=DeliveryForecastCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeliveryForecastCard.js","names":[],"sources":["../../../src/planmagnet/forecast/DeliveryForecastCard.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Checkbox } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { CalendarRange } from 'lucide-react';\nimport { isForbidden } from '../utils/graphqlErrors';\n\n/**\n * ANR-02: the Monte Carlo delivery forecast (`planmagnetForecastDelivery`) — how many more\n * sprints a project's (or one sprint's) remaining scope is likely to take, and the calendar\n * dates those sprint counts land on. Shared by the project detail page and the Analytics page\n * (both project-scoped) so the wording and the insufficient-history handling can never drift\n * between the two.\n *\n * NEVER an AI/LLM call — the server resamples the trailing completed sprints' real velocities\n * (2,000 seeded trials, deterministic). Labelled \"Statistical forecast (Monte Carlo over past\n * sprints)\" everywhere it appears, never presented as AI.\n */\n\nconst GET_DELIVERY_FORECAST = gql`\n query PlanmagnetDeliveryForecast(\n $workspaceId: ID!\n $projectId: ID!\n $scope: PlanmagnetForecastScopeInput\n ) {\n planmagnetForecastDelivery(workspaceId: $workspaceId, projectId: $projectId, scope: $scope) {\n method\n insufficientHistory\n reason\n remainingPoints\n unestimatedItems\n scopeTruncated\n confidenceNote\n sprintsNeeded {\n p50\n p85\n p95\n }\n dates {\n p50\n p85\n p95\n }\n inputRefs {\n sprintId\n name\n completedPoints\n endDate\n }\n }\n }\n`;\n\ninterface DeliveryForecast {\n method: 'MONTE_CARLO_VELOCITY';\n insufficientHistory: boolean;\n reason: string | null;\n remainingPoints: number;\n unestimatedItems: number;\n scopeTruncated: boolean;\n confidenceNote: string;\n sprintsNeeded: { p50: number; p85: number; p95: number } | null;\n dates: { p50: string; p85: string; p95: string } | null;\n inputRefs: { sprintId: string; name: string; completedPoints: number; endDate: string | null }[];\n}\n\ninterface DeliveryForecastData {\n planmagnetForecastDelivery: DeliveryForecast;\n}\n\n/** Forecast dates are calendar days (UTC midnight, derived from Sprint.endDate); show them\n * without a time-zone shift — same convention as SprintDates.tsx's `day()` helper. */\nfunction formatDate(iso: string): string {\n return new Date(iso).toLocaleDateString(undefined, {\n timeZone: 'UTC',\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n}\n\nexport function DeliveryForecastCard({\n workspaceId,\n projectId,\n /** When set, the card offers an \"only this sprint's items\" toggle that narrows\n * `scope.sprintId` to this sprint instead of the project's full remaining scope. Pass the\n * active/current sprint of whatever page hosts this card — omit it where no single sprint\n * is in context (the card then always forecasts the project's full open scope). */\n sprintId,\n sprintName,\n}: {\n workspaceId?: string | null;\n projectId: string;\n sprintId?: string | null;\n sprintName?: string | null;\n}) {\n const { t } = useI18n();\n const [scopeToSprint, setScopeToSprint] = useState(false);\n const effectiveScopeToSprint = scopeToSprint && Boolean(sprintId);\n const { data, loading, error } = useQuery<DeliveryForecastData>(GET_DELIVERY_FORECAST, {\n variables: {\n workspaceId,\n projectId,\n scope: effectiveScopeToSprint && sprintId ? { sprintId } : undefined,\n },\n skip: !workspaceId || !projectId,\n });\n const forecast = data?.planmagnetForecastDelivery;\n\n return (\n <Card data-testid=\"forecast-card\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <CalendarRange className=\"h-4 w-4\" />\n {t('planmagnet.forecast.delivery.title', 'Delivery forecast')}\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {effectiveScopeToSprint\n ? t(\n 'planmagnet.forecast.delivery.subtitleSprint',\n 'For the open items of {{sprint}} only.',\n {\n sprint: sprintName ?? t('planmagnet.forecast.delivery.thisSprint', 'this sprint'),\n }\n )\n : t(\n 'planmagnet.forecast.delivery.subtitle',\n \"For this project's own open, estimated work items.\"\n )}\n </p>\n {sprintId && (\n <label\n htmlFor={`forecast-scope-sprint-${projectId}`}\n className=\"flex items-center gap-2 pt-1 text-xs font-normal text-muted-foreground\"\n >\n <Checkbox\n id={`forecast-scope-sprint-${projectId}`}\n checked={scopeToSprint}\n onCheckedChange={(checked) => setScopeToSprint(checked === true)}\n />\n {t(\n 'planmagnet.forecast.delivery.scopeToggle',\n \"Only this sprint's items ({{sprint}})\",\n { sprint: sprintName ?? t('planmagnet.forecast.delivery.thisSprint', 'this sprint') }\n )}\n </label>\n )}\n </CardHeader>\n <CardContent>\n {!projectId ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.forecast.delivery.noProject', 'Select a project to see its forecast.')}\n </p>\n ) : loading && !data ? (\n <div className=\"flex justify-center py-8\">\n <div className=\"animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n ) : error ? (\n <p className=\"text-sm text-status-error-text\">\n {isForbidden(error)\n ? t(\n 'planmagnet.forecast.delivery.forbidden',\n 'You do not have access to the delivery forecast for this project.'\n )\n : `${t('planmagnet.forecast.delivery.error', 'Delivery forecast could not be loaded')}: ${error.message}`}\n </p>\n ) : !forecast ? null : forecast.insufficientHistory ? (\n <div className=\"space-y-2\" data-testid=\"forecast-insufficient\">\n <p className=\"text-sm text-muted-foreground\">\n {forecast.reason ??\n t(\n 'planmagnet.forecast.delivery.insufficientFallback',\n 'Not enough completed-sprint history yet to forecast a delivery date.'\n )}\n </p>\n <p className=\"text-xs text-muted-foreground\">{forecast.confidenceNote}</p>\n </div>\n ) : (\n <div className=\"space-y-4\">\n <dl className=\"grid grid-cols-3 gap-3 text-center\" data-testid=\"forecast-dates\">\n <div className=\"rounded-md border p-2.5\">\n <dt className=\"text-xs text-muted-foreground\">\n {t('planmagnet.forecast.delivery.p50Label', 'Likely by (p50)')}\n </dt>\n <dd className=\"mt-1 text-sm font-semibold\">\n {forecast.dates ? formatDate(forecast.dates.p50) : '—'}\n </dd>\n <dd className=\"text-xs text-muted-foreground\">\n {forecast.sprintsNeeded\n ? t('planmagnet.forecast.delivery.sprints', '{{count}} sprint(s)', {\n count: forecast.sprintsNeeded.p50,\n })\n : '—'}\n </dd>\n </div>\n <div className=\"rounded-md border p-2.5\">\n <dt className=\"text-xs text-muted-foreground\">\n {t('planmagnet.forecast.delivery.p85Label', 'Confident by (p85)')}\n </dt>\n <dd className=\"mt-1 text-sm font-semibold\">\n {forecast.dates ? formatDate(forecast.dates.p85) : '—'}\n </dd>\n <dd className=\"text-xs text-muted-foreground\">\n {forecast.sprintsNeeded\n ? t('planmagnet.forecast.delivery.sprints', '{{count}} sprint(s)', {\n count: forecast.sprintsNeeded.p85,\n })\n : '—'}\n </dd>\n </div>\n <div className=\"rounded-md border p-2.5\">\n <dt className=\"text-xs text-muted-foreground\">\n {t('planmagnet.forecast.delivery.p95Label', 'Very confident by (p95)')}\n </dt>\n <dd className=\"mt-1 text-sm font-semibold\">\n {forecast.dates ? formatDate(forecast.dates.p95) : '—'}\n </dd>\n <dd className=\"text-xs text-muted-foreground\">\n {forecast.sprintsNeeded\n ? t('planmagnet.forecast.delivery.sprints', '{{count}} sprint(s)', {\n count: forecast.sprintsNeeded.p95,\n })\n : '—'}\n </dd>\n </div>\n </dl>\n\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground\">\n <span>\n {t('planmagnet.forecast.delivery.remaining', 'Remaining: {{points}} pts', {\n points: forecast.remainingPoints,\n })}\n </span>\n {forecast.unestimatedItems > 0 && (\n <span className=\"text-status-warning-text\">\n {t(\n 'planmagnet.forecast.delivery.unestimated',\n '{{count}} open item(s) have no estimate (counted as 0 pts)',\n { count: forecast.unestimatedItems }\n )}\n </span>\n )}\n </div>\n\n {forecast.scopeTruncated && (\n <p className=\"text-xs text-status-warning-text\">\n {t(\n 'planmagnet.forecast.delivery.truncated',\n 'This scope is large enough that the scan stopped early — remaining points and unestimated items reflect only the first items found, not the whole project.'\n )}\n </p>\n )}\n\n <div>\n <h3 className=\"mb-1 text-sm font-medium\">\n {t('planmagnet.forecast.delivery.evidence', 'Based on')}\n </h3>\n <ul className=\"space-y-1 text-xs text-muted-foreground\" data-testid=\"forecast-inputs\">\n {forecast.inputRefs.map((ref) => (\n <li key={ref.sprintId} className=\"flex items-center justify-between gap-2\">\n <span className=\"truncate\">{ref.name}</span>\n <span className=\"shrink-0 tabular-nums\">\n {t('planmagnet.forecast.delivery.evidenceRow', '{{points}} pts', {\n points: ref.completedPoints,\n })}\n {ref.endDate ? ` · ${formatDate(ref.endDate)}` : ''}\n </span>\n </li>\n ))}\n {forecast.inputRefs.length === 0 && (\n <li>\n {t('planmagnet.forecast.delivery.noInputs', 'No sprint history available.')}\n </li>\n )}\n </ul>\n </div>\n\n <p className=\"text-xs text-muted-foreground\">{forecast.confidenceNote}</p>\n\n <details className=\"text-xs text-muted-foreground\">\n <summary className=\"cursor-pointer select-none font-medium text-foreground\">\n {t('planmagnet.forecast.whatIsThis', 'What is this?')}\n </summary>\n <p className=\"mt-1\">\n {t(\n 'planmagnet.forecast.delivery.explainer',\n 'Statistical forecast (Monte Carlo over past sprints): a simulation that resamples this project’s trailing completed sprints’ real velocities thousands of times to see how many more sprints the remaining work is likely to take. It is never an AI/LLM call, and it never invents a date from a sample it doesn’t trust — when history is too thin, it says so instead of guessing.'\n )}\n </p>\n </details>\n </div>\n )}\n </CardContent>\n </Card>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function ProjectOutlookCard({ workspaceId, projectId, }: {
2
+ workspaceId?: string | null;
3
+ projectId: string;
4
+ }): import("react/jsx-runtime").JSX.Element;
5
+ //# sourceMappingURL=ProjectOutlookCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProjectOutlookCard.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/forecast/ProjectOutlookCard.tsx"],"names":[],"mappings":"AAmHA,wBAAgB,kBAAkB,CAAC,EACjC,WAAW,EACX,SAAS,GACV,EAAE;IACD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB,2CAoMA"}
@@ -0,0 +1,190 @@
1
+ import { usePlanMagnetNavigate as e } from "../providers/PlanMagnetProvider.js";
2
+ import { isForbidden as t } from "../utils/graphqlErrors.js";
3
+ import { detailPath as n } from "../utils/rowNavigation.js";
4
+ import { Compass as r } from "lucide-react";
5
+ import { gql as i } from "@apollo/client";
6
+ import { useQuery as a } from "@apollo/client/react";
7
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
8
+ import { useI18n as c } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
9
+ import { Badge as l, Card as u, CardContent as d, CardHeader as f, CardTitle as p } from "@burdenoff/fe-libs/ui";
10
+ //#region src/planmagnet/forecast/ProjectOutlookCard.tsx
11
+ var m = i`
12
+ query PlanmagnetProjectOutlook($workspaceId: ID!, $projectId: ID!) {
13
+ planmagnetProjectOutlook(workspaceId: $workspaceId, projectId: $projectId) {
14
+ projectId
15
+ method
16
+ successLikelihood
17
+ successLikelihoodRule
18
+ timelineDeviationDays
19
+ qualityTrend {
20
+ recentDefectRatio
21
+ priorDefectRatio
22
+ trend
23
+ }
24
+ riskExposure {
25
+ totalExposure
26
+ topRisks {
27
+ riskId
28
+ title
29
+ likelihood
30
+ impact
31
+ exposure
32
+ }
33
+ }
34
+ budgetProjection {
35
+ budgetId
36
+ name
37
+ spentAmount
38
+ totalAmount
39
+ burnRatePerDay
40
+ projectedSpendAtForecastDate
41
+ projectedOverage
42
+ }
43
+ inputs
44
+ }
45
+ }
46
+ `, h = {
47
+ HIGH: "success",
48
+ MEDIUM: "warning",
49
+ LOW: "destructive"
50
+ }, g = {
51
+ IMPROVING: "success",
52
+ STABLE: "secondary",
53
+ WORSENING: "warning",
54
+ UNKNOWN: "outline"
55
+ };
56
+ function _(e) {
57
+ return e === null ? "—" : `${Math.round(e * 100)}%`;
58
+ }
59
+ function v({ workspaceId: i, projectId: v }) {
60
+ let { t: y } = c(), b = e(), { data: x, loading: S, error: C } = a(m, {
61
+ variables: {
62
+ workspaceId: i,
63
+ projectId: v
64
+ },
65
+ skip: !i || !v
66
+ }), w = x?.planmagnetProjectOutlook;
67
+ return /* @__PURE__ */ s(u, {
68
+ "data-testid": "outlook-card",
69
+ children: [/* @__PURE__ */ s(f, {
70
+ className: "flex flex-row items-start justify-between space-y-0",
71
+ children: [/* @__PURE__ */ s("div", { children: [/* @__PURE__ */ s(p, {
72
+ className: "flex items-center gap-2",
73
+ children: [/* @__PURE__ */ o(r, { className: "h-4 w-4" }), y("planmagnet.forecast.outlook.title", "Project outlook")]
74
+ }), /* @__PURE__ */ o("p", {
75
+ className: "text-xs text-muted-foreground",
76
+ children: y("planmagnet.forecast.outlook.subtitle", "Explicit rule-based heuristics over real data — never AI.")
77
+ })] }), /* @__PURE__ */ o(l, {
78
+ variant: "outline",
79
+ children: y("planmagnet.forecast.outlook.method", "HEURISTIC")
80
+ })]
81
+ }), /* @__PURE__ */ o(d, { children: S && !x ? /* @__PURE__ */ o("div", {
82
+ className: "flex justify-center py-8",
83
+ children: /* @__PURE__ */ o("div", { className: "animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full" })
84
+ }) : C ? /* @__PURE__ */ o("p", {
85
+ className: "text-sm text-status-error-text",
86
+ children: t(C) ? y("planmagnet.forecast.outlook.forbidden", "You do not have access to the outlook for this project.") : `${y("planmagnet.forecast.outlook.error", "Project outlook could not be loaded")}: ${C.message}`
87
+ }) : w ? /* @__PURE__ */ s("div", {
88
+ className: "space-y-4",
89
+ children: [
90
+ /* @__PURE__ */ s("div", {
91
+ className: "flex flex-wrap items-center gap-2",
92
+ children: [/* @__PURE__ */ o(l, {
93
+ variant: h[w.successLikelihood],
94
+ children: y("planmagnet.forecast.outlook.successLikelihood", "Success likelihood: {{level}}", { level: w.successLikelihood })
95
+ }), /* @__PURE__ */ o("span", {
96
+ className: "text-xs text-muted-foreground",
97
+ children: y("planmagnet.forecast.outlook.timelineDeviation", "Timeline: {{status}}", { status: w.timelineDeviationDays === null ? y("planmagnet.forecast.outlook.timelineUnknown", "no forecast/target to compare") : w.timelineDeviationDays > 0 ? y("planmagnet.forecast.outlook.timelineLate", "{{days}} day(s) late", { days: w.timelineDeviationDays }) : w.timelineDeviationDays < 0 ? y("planmagnet.forecast.outlook.timelineEarly", "{{days}} day(s) early", { days: Math.abs(w.timelineDeviationDays) }) : y("planmagnet.forecast.outlook.timelineOnTarget", "on target") })
98
+ })]
99
+ }),
100
+ /* @__PURE__ */ o("p", {
101
+ className: "text-xs text-muted-foreground",
102
+ children: w.successLikelihoodRule
103
+ }),
104
+ /* @__PURE__ */ s("div", {
105
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
106
+ children: [/* @__PURE__ */ s("div", {
107
+ className: "rounded-md border p-3",
108
+ children: [/* @__PURE__ */ s("h3", {
109
+ className: "mb-1 flex items-center gap-2 text-sm font-medium",
110
+ children: [y("planmagnet.forecast.outlook.quality", "Quality trend"), /* @__PURE__ */ o(l, {
111
+ variant: g[w.qualityTrend.trend],
112
+ children: w.qualityTrend.trend
113
+ })]
114
+ }), /* @__PURE__ */ o("p", {
115
+ className: "text-xs text-muted-foreground",
116
+ children: y("planmagnet.forecast.outlook.qualityRatios", "Recent 4wk defect ratio {{recent}}, prior 4wk {{prior}}", {
117
+ recent: _(w.qualityTrend.recentDefectRatio),
118
+ prior: _(w.qualityTrend.priorDefectRatio)
119
+ })
120
+ })]
121
+ }), /* @__PURE__ */ s("div", {
122
+ className: "rounded-md border p-3",
123
+ children: [
124
+ /* @__PURE__ */ o("h3", {
125
+ className: "mb-1 text-sm font-medium",
126
+ children: y("planmagnet.forecast.outlook.riskExposure", "Risk exposure")
127
+ }),
128
+ /* @__PURE__ */ o("p", {
129
+ className: "text-xs text-muted-foreground mb-1",
130
+ children: y("planmagnet.forecast.outlook.totalExposure", "Total (likelihood × impact): {{value}}", { value: w.riskExposure.totalExposure })
131
+ }),
132
+ /* @__PURE__ */ s("ul", {
133
+ className: "space-y-0.5",
134
+ children: [w.riskExposure.topRisks.map((e) => /* @__PURE__ */ o("li", { children: /* @__PURE__ */ s("button", {
135
+ type: "button",
136
+ className: "truncate text-left text-xs text-primary hover:underline",
137
+ onClick: () => b(n("/risks/risk-detail-page", e.riskId)),
138
+ children: [
139
+ e.title,
140
+ " (",
141
+ e.exposure,
142
+ ")"
143
+ ]
144
+ }) }, e.riskId)), w.riskExposure.topRisks.length === 0 && /* @__PURE__ */ o("li", {
145
+ className: "text-xs text-muted-foreground",
146
+ children: y("planmagnet.forecast.outlook.noOpenRisks", "No open risks.")
147
+ })]
148
+ })
149
+ ]
150
+ })]
151
+ }),
152
+ /* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("h3", {
153
+ className: "mb-1 text-sm font-medium",
154
+ children: y("planmagnet.forecast.outlook.budget", "Budget projection")
155
+ }), w.budgetProjection === null ? /* @__PURE__ */ o("p", {
156
+ className: "text-xs text-muted-foreground",
157
+ children: y("planmagnet.forecast.outlook.noBudgets", "This project has no budgets.")
158
+ }) : /* @__PURE__ */ o("ul", {
159
+ className: "space-y-1.5",
160
+ children: w.budgetProjection.map((e) => /* @__PURE__ */ s("li", {
161
+ className: "flex items-center justify-between gap-2 text-xs",
162
+ children: [/* @__PURE__ */ o("span", {
163
+ className: "truncate font-medium text-foreground",
164
+ children: e.name
165
+ }), /* @__PURE__ */ s("span", {
166
+ className: `shrink-0 tabular-nums ${e.projectedOverage !== null && e.projectedOverage > 0 ? "text-status-error-text" : "text-muted-foreground"}`,
167
+ children: [
168
+ e.spentAmount.toLocaleString(),
169
+ " / ",
170
+ e.totalAmount.toLocaleString(),
171
+ e.projectedOverage !== null && ` · ${e.projectedOverage > 0 ? y("planmagnet.forecast.outlook.projectedOver", "projected +{{amount}} over", { amount: Math.round(e.projectedOverage).toLocaleString() }) : y("planmagnet.forecast.outlook.projectedUnder", "projected within plan")}`
172
+ ]
173
+ })]
174
+ }, e.budgetId))
175
+ })] }),
176
+ w.inputs.length > 0 && /* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("h3", {
177
+ className: "mb-1 text-sm font-medium",
178
+ children: y("planmagnet.forecast.outlook.inputs", "What this is based on")
179
+ }), /* @__PURE__ */ o("ul", {
180
+ className: "list-inside list-disc space-y-0.5 text-xs text-muted-foreground",
181
+ children: w.inputs.map((e, t) => /* @__PURE__ */ o("li", { children: e }, `${t}-${e.slice(0, 24)}`))
182
+ })] })
183
+ ]
184
+ }) : null })]
185
+ });
186
+ }
187
+ //#endregion
188
+ export { v as ProjectOutlookCard };
189
+
190
+ //# sourceMappingURL=ProjectOutlookCard.js.map