@splunk/visualizations 28.7.0 → 28.9.0

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 (375) hide show
  1. package/Area.config.js +2 -4
  2. package/Area.config.js.map +2 -2
  3. package/Area.js +245 -147
  4. package/Area.js.map +4 -4
  5. package/Bar.config.js +2 -4
  6. package/Bar.config.js.map +2 -2
  7. package/Bar.js +246 -148
  8. package/Bar.js.map +4 -4
  9. package/Bubble/Bubble.d.ts +3 -1
  10. package/Bubble/Bubble.d.ts.map +1 -1
  11. package/Bubble.js +216 -108
  12. package/Bubble.js.map +4 -4
  13. package/CHANGELOG.external.md +56 -0
  14. package/ChoroplethSvg/ChoroplethSvg.d.ts +3 -1
  15. package/ChoroplethSvg/ChoroplethSvg.d.ts.map +1 -1
  16. package/ChoroplethSvg/PureChoroplethSvg/PureChoroplethSvg.d.ts.map +1 -1
  17. package/ChoroplethSvg/PureChoroplethSvg/SvgMutator.d.ts.map +1 -1
  18. package/ChoroplethSvg.js +638 -209
  19. package/ChoroplethSvg.js.map +4 -4
  20. package/Column.config.js +2 -4
  21. package/Column.config.js.map +2 -2
  22. package/Column.js +246 -148
  23. package/Column.js.map +4 -4
  24. package/Ellipse/Ellipse.d.ts +3 -1
  25. package/Ellipse/Ellipse.d.ts.map +1 -1
  26. package/Ellipse.js +216 -105
  27. package/Ellipse.js.map +4 -4
  28. package/Events/Events.d.ts +5 -3
  29. package/Events/Events.d.ts.map +1 -1
  30. package/Events/PureEvents/FieldSummaryTooltip.d.ts.map +1 -1
  31. package/Events/PureEvents/PureEvents.d.ts +0 -1
  32. package/Events/PureEvents/PureEvents.d.ts.map +1 -1
  33. package/Events.js +270 -157
  34. package/Events.js.map +4 -4
  35. package/FillerGauge.js +251 -143
  36. package/FillerGauge.js.map +4 -4
  37. package/Image/Image.d.ts +3 -1
  38. package/Image/Image.d.ts.map +1 -1
  39. package/Image.js +217 -106
  40. package/Image.js.map +4 -4
  41. package/Line.config.js +2 -4
  42. package/Line.config.js.map +2 -2
  43. package/Line.js +246 -148
  44. package/Line.js.map +4 -4
  45. package/LinkGraph/LinkGraph.d.ts +3 -1
  46. package/LinkGraph/LinkGraph.d.ts.map +1 -1
  47. package/LinkGraph/PureLinkGraph/PureLinkGraphUtils.d.ts.map +1 -1
  48. package/LinkGraph/PureLinkGraph/components/Node.d.ts.map +1 -1
  49. package/LinkGraph.config.js +1 -1
  50. package/LinkGraph.config.js.map +2 -2
  51. package/LinkGraph.js +802 -682
  52. package/LinkGraph.js.map +4 -4
  53. package/Map/Map.d.ts +10 -9
  54. package/Map/Map.d.ts.map +1 -1
  55. package/Map/PureMap/BubbleLayer.d.ts.map +1 -1
  56. package/Map/PureMap/ClusterLayer.d.ts.map +1 -1
  57. package/Map/PureMap/MapUtils.d.ts.map +1 -1
  58. package/Map/PureMap/MarkerWrapper.d.ts.map +1 -1
  59. package/Map/PureMap/PureMap.d.ts +8 -65
  60. package/Map/PureMap/PureMap.d.ts.map +1 -1
  61. package/Map.config.js +1 -1
  62. package/Map.config.js.map +2 -2
  63. package/Map.js +363 -313
  64. package/Map.js.map +4 -4
  65. package/Markdown/Markdown.d.ts +9 -1
  66. package/Markdown/Markdown.d.ts.map +1 -1
  67. package/Markdown/config.d.ts.map +1 -1
  68. package/Markdown.config.js +6 -1
  69. package/Markdown.config.js.map +2 -2
  70. package/Markdown.js +226 -95
  71. package/Markdown.js.map +3 -3
  72. package/MarkerGauge.js +247 -137
  73. package/MarkerGauge.js.map +4 -4
  74. package/NetworkGraph/PureNetworkGraph/PureNetworkGraph.d.ts.map +1 -1
  75. package/NetworkGraph/PureNetworkGraph/components/NetworkGraphSvg.d.ts +1 -0
  76. package/NetworkGraph/PureNetworkGraph/components/NetworkGraphSvg.d.ts.map +1 -1
  77. package/NetworkGraph/PureNetworkGraph/components/Node.d.ts +1 -0
  78. package/NetworkGraph/PureNetworkGraph/components/Node.d.ts.map +1 -1
  79. package/NetworkGraph/PureNetworkGraph/utils/networkGraphUtils.d.ts +3 -5
  80. package/NetworkGraph/PureNetworkGraph/utils/networkGraphUtils.d.ts.map +1 -1
  81. package/NetworkGraph.config.js +4 -2
  82. package/NetworkGraph.config.js.map +2 -2
  83. package/NetworkGraph.js +327 -188
  84. package/NetworkGraph.js.map +4 -4
  85. package/ParallelCoordinates/ParallelCoordinates.d.ts +3 -1
  86. package/ParallelCoordinates/ParallelCoordinates.d.ts.map +1 -1
  87. package/ParallelCoordinates.js +239 -128
  88. package/ParallelCoordinates.js.map +4 -4
  89. package/Pie/config.d.ts.map +1 -1
  90. package/Pie/pieUtils.d.ts.map +1 -1
  91. package/Pie.config.js +4 -2
  92. package/Pie.config.js.map +2 -2
  93. package/Pie.js +228 -125
  94. package/Pie.js.map +3 -3
  95. package/ProcessTree/ProcessTree.d.ts +3 -1
  96. package/ProcessTree/ProcessTree.d.ts.map +1 -1
  97. package/ProcessTree/PureProcessTree/PureProcessTree.d.ts +1 -0
  98. package/ProcessTree/PureProcessTree/PureProcessTree.d.ts.map +1 -1
  99. package/ProcessTree/PureProcessTree/components/ProcessTreeLeftPanel.d.ts +1 -0
  100. package/ProcessTree/PureProcessTree/components/ProcessTreeLeftPanel.d.ts.map +1 -1
  101. package/ProcessTree/PureProcessTree/hooks/useProcessTreeGraphData.d.ts +2 -1
  102. package/ProcessTree/PureProcessTree/hooks/useProcessTreeGraphData.d.ts.map +1 -1
  103. package/ProcessTree/PureProcessTree/utils/iconLoader.d.ts +2 -0
  104. package/ProcessTree/PureProcessTree/utils/iconLoader.d.ts.map +1 -1
  105. package/ProcessTree/PureProcessTree/utils/processTreeUtils.d.ts +5 -1
  106. package/ProcessTree/PureProcessTree/utils/processTreeUtils.d.ts.map +1 -1
  107. package/ProcessTree.js +435 -192
  108. package/ProcessTree.js.map +4 -4
  109. package/Punchcard/Punchcard.d.ts +3 -1
  110. package/Punchcard/Punchcard.d.ts.map +1 -1
  111. package/Punchcard.js +238 -129
  112. package/Punchcard.js.map +4 -4
  113. package/Rectangle/Rectangle.d.ts +3 -1
  114. package/Rectangle/Rectangle.d.ts.map +1 -1
  115. package/Rectangle.js +218 -116
  116. package/Rectangle.js.map +4 -4
  117. package/RichText/PureRichText/Editor/EditorPanel.d.ts +1 -4
  118. package/RichText/PureRichText/Editor/EditorPanel.d.ts.map +1 -1
  119. package/RichText/PureRichText/Editor/hooks/useConfigPanelFocus.d.ts +14 -0
  120. package/RichText/PureRichText/Editor/hooks/useConfigPanelFocus.d.ts.map +1 -0
  121. package/RichText/PureRichText/Editor/hooks/useEditorPanelSync.d.ts +15 -0
  122. package/RichText/PureRichText/Editor/hooks/useEditorPanelSync.d.ts.map +1 -0
  123. package/RichText/PureRichText/Editor/hooks/useLinkHandlers.d.ts.map +1 -1
  124. package/RichText/PureRichText/Editor/hooks/usePortalTarget.d.ts +9 -0
  125. package/RichText/PureRichText/Editor/hooks/usePortalTarget.d.ts.map +1 -0
  126. package/RichText/PureRichText/InnerEditor.d.ts +20 -4
  127. package/RichText/PureRichText/InnerEditor.d.ts.map +1 -1
  128. package/RichText/PureRichText/PureRichText.d.ts +21 -9
  129. package/RichText/PureRichText/PureRichText.d.ts.map +1 -1
  130. package/RichText/PureRichText/PureRichTextContext.d.ts +3 -6
  131. package/RichText/PureRichText/PureRichTextContext.d.ts.map +1 -1
  132. package/RichText/PureRichText/RichTextStyles.d.ts +5 -4
  133. package/RichText/PureRichText/RichTextStyles.d.ts.map +1 -1
  134. package/RichText/PureRichText/activeInstance.d.ts +6 -7
  135. package/RichText/PureRichText/activeInstance.d.ts.map +1 -1
  136. package/RichText/PureRichText/config.d.ts.map +1 -1
  137. package/RichText/PureRichText/hooks/useContentSave.d.ts +6 -0
  138. package/RichText/PureRichText/hooks/useContentSave.d.ts.map +1 -1
  139. package/RichText/PureRichText/hooks/useContentSync.d.ts +13 -1
  140. package/RichText/PureRichText/hooks/useContentSync.d.ts.map +1 -1
  141. package/RichText/PureRichText/hooks/useDashboardKeyboardNav.d.ts +2 -7
  142. package/RichText/PureRichText/hooks/useDashboardKeyboardNav.d.ts.map +1 -1
  143. package/RichText/PureRichText/hooks/useEditorSetup.d.ts +8 -4
  144. package/RichText/PureRichText/hooks/useEditorSetup.d.ts.map +1 -1
  145. package/RichText/PureRichText/hooks/useFakeHighlight.d.ts +1 -16
  146. package/RichText/PureRichText/hooks/useFakeHighlight.d.ts.map +1 -1
  147. package/RichText/PureRichText/hooks/useFocusHandlers.d.ts +2 -4
  148. package/RichText/PureRichText/hooks/useFocusHandlers.d.ts.map +1 -1
  149. package/RichText/PureRichText/hooks/useKeyboardShortcuts.d.ts.map +1 -1
  150. package/RichText/PureRichText/hooks/useMouseHandlers.d.ts +3 -7
  151. package/RichText/PureRichText/hooks/useMouseHandlers.d.ts.map +1 -1
  152. package/RichText/PureRichText/hooks/useStepFontSize.d.ts +2 -2
  153. package/RichText/PureRichText/hooks/useStepLineSpacing.d.ts +2 -3
  154. package/RichText/PureRichText/hooks/useStepLineSpacing.d.ts.map +1 -1
  155. package/RichText/PureRichText/hooks/useTokenMap.d.ts +31 -40
  156. package/RichText/PureRichText/hooks/useTokenMap.d.ts.map +1 -1
  157. package/RichText/PureRichText/renderers/ElementRenderer.d.ts +2 -5
  158. package/RichText/PureRichText/renderers/ElementRenderer.d.ts.map +1 -1
  159. package/RichText/PureRichText/renderers/LeafRenderer.d.ts +0 -4
  160. package/RichText/PureRichText/renderers/LeafRenderer.d.ts.map +1 -1
  161. package/RichText/PureRichText/types.d.ts +21 -0
  162. package/RichText/PureRichText/types.d.ts.map +1 -1
  163. package/RichText/PureRichText/utils/slateUtils.d.ts +26 -2
  164. package/RichText/PureRichText/utils/slateUtils.d.ts.map +1 -1
  165. package/RichText/RichText.d.ts +5 -1
  166. package/RichText/RichText.d.ts.map +1 -1
  167. package/RichText/config.d.ts.map +1 -1
  168. package/RichText.config.js +19 -1
  169. package/RichText.config.js.map +2 -2
  170. package/RichText.js +2311 -835
  171. package/RichText.js.map +4 -4
  172. package/Sankey/PureSankey/PureSankey.d.ts +2 -0
  173. package/Sankey/PureSankey/PureSankey.d.ts.map +1 -1
  174. package/Sankey/PureSankey/SankeyLink.d.ts +3 -1
  175. package/Sankey/PureSankey/SankeyLink.d.ts.map +1 -1
  176. package/Sankey/PureSankey/SankeyNode.d.ts +5 -2
  177. package/Sankey/PureSankey/SankeyNode.d.ts.map +1 -1
  178. package/Sankey/PureSankey/SankeyUtils.d.ts.map +1 -1
  179. package/Sankey/Sankey.d.ts +3 -1
  180. package/Sankey/Sankey.d.ts.map +1 -1
  181. package/Sankey.js +508 -219
  182. package/Sankey.js.map +4 -4
  183. package/Scatter.config.js +3 -5
  184. package/Scatter.config.js.map +2 -2
  185. package/Scatter.js +244 -146
  186. package/Scatter.js.map +4 -4
  187. package/SingleValue/SingleValue.d.ts.map +1 -1
  188. package/SingleValue.js +273 -173
  189. package/SingleValue.js.map +4 -4
  190. package/SingleValueBasic.js +4 -4
  191. package/SingleValueBasic.js.map +2 -2
  192. package/SingleValueIcon/SingleValueIcon.d.ts.map +1 -1
  193. package/SingleValueIcon.js +264 -164
  194. package/SingleValueIcon.js.map +4 -4
  195. package/SingleValueRadial.js +267 -167
  196. package/SingleValueRadial.js.map +4 -4
  197. package/SparkLine/SparkLine.d.ts.map +1 -1
  198. package/SparkLine.js.map +2 -2
  199. package/Table/PureTable.d.ts +2 -0
  200. package/Table/PureTable.d.ts.map +1 -1
  201. package/Table/Table.d.ts +2 -5
  202. package/Table/Table.d.ts.map +1 -1
  203. package/Table/config.d.ts.map +1 -1
  204. package/Table/hooks.d.ts.map +1 -1
  205. package/Table.config.js +8 -1
  206. package/Table.config.js.map +2 -2
  207. package/Table.js +374 -270
  208. package/Table.js.map +4 -4
  209. package/Timeline/PureTimeline/PureTimeline.d.ts +6 -5
  210. package/Timeline/PureTimeline/PureTimeline.d.ts.map +1 -1
  211. package/Timeline/PureTimeline/src/CursorPlugin.d.ts +1 -0
  212. package/Timeline/PureTimeline/src/CursorPlugin.d.ts.map +1 -1
  213. package/Timeline/PureTimeline/src/TimelineLegend.d.ts +10 -7
  214. package/Timeline/PureTimeline/src/TimelineLegend.d.ts.map +1 -1
  215. package/Timeline/PureTimeline/src/TimelineTooltip.d.ts +5 -1
  216. package/Timeline/PureTimeline/src/TimelineTooltip.d.ts.map +1 -1
  217. package/Timeline/PureTimeline/src/TimelineUplot.d.ts +19 -2
  218. package/Timeline/PureTimeline/src/TimelineUplot.d.ts.map +1 -1
  219. package/Timeline/PureTimeline/src/TimelineYAxis.d.ts.map +1 -1
  220. package/Timeline/PureTimeline/src/XAxisPlugin.d.ts +1 -0
  221. package/Timeline/PureTimeline/src/XAxisPlugin.d.ts.map +1 -1
  222. package/Timeline/PureTimeline/src/utils/timelineUtils.d.ts +8 -0
  223. package/Timeline/PureTimeline/src/utils/timelineUtils.d.ts.map +1 -1
  224. package/Timeline/Timeline.d.ts +3 -1
  225. package/Timeline/Timeline.d.ts.map +1 -1
  226. package/Timeline.config.js +2 -2
  227. package/Timeline.config.js.map +2 -2
  228. package/Timeline.js +713 -351
  229. package/Timeline.js.map +4 -4
  230. package/Treemap/PureTreemap/components/PureTreemap.d.ts +42 -0
  231. package/Treemap/PureTreemap/components/PureTreemap.d.ts.map +1 -0
  232. package/Treemap/PureTreemap/components/TreemapBreadcrumb.d.ts +10 -0
  233. package/Treemap/PureTreemap/components/TreemapBreadcrumb.d.ts.map +1 -0
  234. package/Treemap/PureTreemap/components/TreemapChildCell.d.ts +28 -0
  235. package/Treemap/PureTreemap/components/TreemapChildCell.d.ts.map +1 -0
  236. package/Treemap/PureTreemap/components/TreemapHeader.d.ts +19 -0
  237. package/Treemap/PureTreemap/components/TreemapHeader.d.ts.map +1 -0
  238. package/Treemap/PureTreemap/components/TreemapHoverTarget.d.ts +17 -0
  239. package/Treemap/PureTreemap/components/TreemapHoverTarget.d.ts.map +1 -0
  240. package/Treemap/PureTreemap/components/TreemapLegend.d.ts +20 -0
  241. package/Treemap/PureTreemap/components/TreemapLegend.d.ts.map +1 -0
  242. package/Treemap/PureTreemap/components/TreemapNode.d.ts +5 -0
  243. package/Treemap/PureTreemap/components/TreemapNode.d.ts.map +1 -0
  244. package/Treemap/PureTreemap/components/TreemapParentNode.d.ts +10 -0
  245. package/Treemap/PureTreemap/components/TreemapParentNode.d.ts.map +1 -0
  246. package/Treemap/PureTreemap/components/TreemapStandaloneNode.d.ts +6 -0
  247. package/Treemap/PureTreemap/components/TreemapStandaloneNode.d.ts.map +1 -0
  248. package/Treemap/PureTreemap/components/TreemapTooltip.d.ts +17 -0
  249. package/Treemap/PureTreemap/components/TreemapTooltip.d.ts.map +1 -0
  250. package/Treemap/PureTreemap/mockdata/data.d.ts +90 -0
  251. package/Treemap/PureTreemap/mockdata/data.d.ts.map +1 -0
  252. package/Treemap/PureTreemap/utils/treemapColorUtils.d.ts +67 -0
  253. package/Treemap/PureTreemap/utils/treemapColorUtils.d.ts.map +1 -0
  254. package/Treemap/PureTreemap/utils/treemapDataColorUtils.d.ts +5 -0
  255. package/Treemap/PureTreemap/utils/treemapDataColorUtils.d.ts.map +1 -0
  256. package/Treemap/PureTreemap/utils/treemapDataUtils.d.ts +14 -0
  257. package/Treemap/PureTreemap/utils/treemapDataUtils.d.ts.map +1 -0
  258. package/Treemap/PureTreemap/utils/treemapLayout.d.ts +49 -0
  259. package/Treemap/PureTreemap/utils/treemapLayout.d.ts.map +1 -0
  260. package/Treemap/PureTreemap/utils/treemapNodeUtils.d.ts +81 -0
  261. package/Treemap/PureTreemap/utils/treemapNodeUtils.d.ts.map +1 -0
  262. package/Treemap/PureTreemap/utils/treemapTypes.d.ts +37 -0
  263. package/Treemap/PureTreemap/utils/treemapTypes.d.ts.map +1 -0
  264. package/Treemap/PureTreemap/utils/treemapUtils.d.ts +76 -0
  265. package/Treemap/PureTreemap/utils/treemapUtils.d.ts.map +1 -0
  266. package/Treemap/Treemap.d.ts +14 -0
  267. package/Treemap/Treemap.d.ts.map +1 -0
  268. package/Treemap/config.d.ts +4 -0
  269. package/Treemap/config.d.ts.map +1 -0
  270. package/Treemap/index.d.ts +3 -0
  271. package/Treemap/index.d.ts.map +1 -0
  272. package/Treemap.config.js +465 -0
  273. package/Treemap.config.js.map +7 -0
  274. package/Treemap.js +6349 -0
  275. package/Treemap.js.map +7 -0
  276. package/common/Charting.js +8 -10
  277. package/common/Charting.js.map +2 -2
  278. package/common/ChartingApi.d.ts.map +1 -1
  279. package/common/ChartingApi.js +5 -2
  280. package/common/ChartingApi.js.map +2 -2
  281. package/common/DocExampleWithVizSandbox.js +3 -3
  282. package/common/DocExampleWithVizSandbox.js.map +2 -2
  283. package/common/GaugeMajorTicks.js.map +2 -2
  284. package/common/GaugeValueMarker.js +1 -0
  285. package/common/GaugeValueMarker.js.map +2 -2
  286. package/common/OptionsDoc.js +1 -1
  287. package/common/OptionsDoc.js.map +2 -2
  288. package/common/OverviewDoc.js +3 -3
  289. package/common/OverviewDoc.js.map +2 -2
  290. package/common/ThemesDoc.js.map +2 -2
  291. package/common/TimeSeriesChartWrapper.js +10 -9
  292. package/common/TimeSeriesChartWrapper.js.map +2 -2
  293. package/common/chartingUtils.d.ts.map +1 -1
  294. package/common/chartingUtils.js +12 -11
  295. package/common/chartingUtils.js.map +2 -2
  296. package/common/components/IconPlaceholder.d.ts.map +1 -1
  297. package/common/docUtils.d.ts.map +1 -1
  298. package/common/docUtils.js +16 -14
  299. package/common/docUtils.js.map +2 -2
  300. package/common/editorConfig/AxesChartDataDisplay.d.ts.map +1 -1
  301. package/common/gaugeUtils.d.ts.map +1 -1
  302. package/common/gaugeUtils.js +11 -5
  303. package/common/gaugeUtils.js.map +2 -2
  304. package/common/hocs/FixedSizeContainer.d.ts.map +1 -1
  305. package/common/hooks/useDynamicHeight.d.ts +67 -0
  306. package/common/hooks/useDynamicHeight.d.ts.map +1 -0
  307. package/common/hooks/useSorting.d.ts.map +1 -1
  308. package/common/interfaces/VizCategory.d.ts +2 -1
  309. package/common/interfaces/VizCategory.d.ts.map +1 -1
  310. package/common/interfaces/VizEvent.d.ts +7 -0
  311. package/common/interfaces/VizEvent.d.ts.map +1 -1
  312. package/common/utils/dataUtils.d.ts.map +1 -1
  313. package/common/utils/dataUtils.js +6 -10
  314. package/common/utils/dataUtils.js.map +2 -2
  315. package/common/utils/featureFlagUtils.js +2 -2
  316. package/common/utils/featureFlagUtils.js.map +2 -2
  317. package/common/utils/focusUtils.js +1 -1
  318. package/common/utils/focusUtils.js.map +2 -2
  319. package/common/utils/mapUtils.d.ts.map +1 -1
  320. package/common/utils/mapUtils.js +14 -18
  321. package/common/utils/mapUtils.js.map +2 -2
  322. package/common/utils/singleValueUtils.js +22 -25
  323. package/common/utils/singleValueUtils.js.map +2 -2
  324. package/common/utils/textUtils.d.ts.map +1 -1
  325. package/common/utils/textUtils.js +37 -23
  326. package/common/utils/textUtils.js.map +2 -2
  327. package/common/utils/trellisUtils.d.ts.map +1 -1
  328. package/common/utils/trellisUtils.js +18 -17
  329. package/common/utils/trellisUtils.js.map +2 -2
  330. package/common/utils/urlUtils.js.map +2 -2
  331. package/common/utils/visualizationTheme.d.ts +15 -0
  332. package/common/utils/visualizationTheme.d.ts.map +1 -0
  333. package/common/utils/visualizationTheme.js +72 -0
  334. package/common/utils/visualizationTheme.js.map +7 -0
  335. package/common/withDashboardViz.d.ts +3 -1
  336. package/common/withDashboardViz.d.ts.map +1 -1
  337. package/common/withDashboardViz.js +216 -105
  338. package/common/withDashboardViz.js.map +4 -4
  339. package/docs-llm/INDEX.md +1 -0
  340. package/docs-llm/area/options.md +84 -84
  341. package/docs-llm/bar/options.md +77 -77
  342. package/docs-llm/bubble/options.md +51 -51
  343. package/docs-llm/choropleth-svg/options.md +5 -5
  344. package/docs-llm/column/options.md +82 -82
  345. package/docs-llm/ellipse/options.md +6 -6
  346. package/docs-llm/events/options.md +6 -6
  347. package/docs-llm/filler-gauge/options.md +16 -16
  348. package/docs-llm/image/options.md +3 -3
  349. package/docs-llm/line/options.md +82 -82
  350. package/docs-llm/link-graph/options.md +16 -16
  351. package/docs-llm/map/options.md +12 -12
  352. package/docs-llm/markdown/options.md +7 -7
  353. package/docs-llm/marker-gauge/options.md +16 -16
  354. package/docs-llm/network-graph/options.md +39 -39
  355. package/docs-llm/parallel-coordinates/options.md +4 -4
  356. package/docs-llm/pie/examples-json.md +195 -0
  357. package/docs-llm/pie/examples-react.md +123 -0
  358. package/docs-llm/pie/options.md +23 -23
  359. package/docs-llm/process-tree/options.md +23 -22
  360. package/docs-llm/punchcard/options.md +23 -23
  361. package/docs-llm/pure-rich-text/options.md +6 -5
  362. package/docs-llm/rectangle/options.md +9 -9
  363. package/docs-llm/rich-text/options.md +6 -5
  364. package/docs-llm/sankey/options.md +9 -9
  365. package/docs-llm/scatter/options.md +57 -57
  366. package/docs-llm/single-value/options.md +39 -39
  367. package/docs-llm/single-value-icon/options.md +33 -33
  368. package/docs-llm/single-value-radial/options.md +31 -31
  369. package/docs-llm/table/options.md +14 -13
  370. package/docs-llm/timeline/options.md +17 -17
  371. package/docs-llm/treemap/examples-json.md +5 -0
  372. package/docs-llm/treemap/examples-react.md +5 -0
  373. package/docs-llm/treemap/options.md +26 -0
  374. package/docs-llm/treemap/overview.md +27 -0
  375. package/package.json +31 -30
package/RichText.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["src/RichText/index.ts", "esm-externals:@splunk/visualization-schemas", "esm-externals:@splunk/ui-utils/i18n", "esm-externals:@splunk/themes", "esm-externals:@splunk/visualization-icons/RichText", "esm-externals:@splunk/visualization-icons/placeholders/RichText", "esm-externals:lodash", "esm-externals:@splunk/visualizations-shared/configUtils", "src/common/utils/configUtils.ts", "src/common/editorConfig/BackgroundColor.ts", "src/RichText/config.ts", "esm-externals:react", "esm-externals:@splunk/themes/getSettingsFromThemedProps", "esm-externals:@splunk/visualization-encoding/Options", "esm-externals:@splunk/visualizations-shared/SanitizeProps", "esm-externals:@splunk/visualization-context/TimezoneContext", "esm-externals:@splunk/moment", "esm-externals:@splunk/visualization-context/FeatureFlagContext", "esm-externals:styled-components", "esm-externals:@splunk/visualizations-shared/hocUtils", "esm-externals:@splunk/visualizations-shared/JSONSchemaUtils", "esm-externals:@splunk/async-dynamic-options-evaluator", "esm-externals:@splunk/ui-utils/id", "esm-externals:prop-types", "src/common/interfaces/VizActionHandler.ts", "src/common/SplunkVisualization.tsx", "src/common/interfaces/DataSource.ts", "src/common/hooks/useSorting.ts", "src/common/hooks/usePagination.ts", "src/common/hooks/useDeepMemo.ts", "esm-externals:@splunk/visualizations-shared/Message", "esm-externals:@splunk/visualizations-shared/SizeAwareWrapper", "src/common/components/MissingPropsMessage.tsx", "src/common/utils/hocUtils.ts", "src/common/hocs/withEditModeCover.tsx", "esm-externals:@splunk/visualizations-shared/colorUtils", "esm-externals:@splunk/themes/variables", "esm-externals:@splunk/visualizations-shared/style", "src/common/hocs/FixedSizeContainer.tsx", "src/common/components/IconPlaceholder.tsx", "src/common/hocs/withPlaceholder.tsx", "esm-externals:@splunk/visualizations-shared/numberUtils", "src/common/utils/dataUtils.ts", "src/common/hooks/usePrevious.ts", "src/common/hooks/useGetXAndYFields.tsx", "src/common/hooks/useDownsampleDataSources.tsx", "esm-externals:@splunk/visualization-context/FeatureFlags", "src/common/utils/featureFlagUtils.ts", "esm-externals:@splunk/visualizations-shared/trellisUtils", "src/common/utils/trellisUtils.ts", "esm-externals:@splunk/visualization-canvas", "src/common/components/VizStyleWrapper.jsx", "esm-externals:@splunk/react-icons/Triangle", "esm-externals:@splunk/visualizations-shared/propUtils", "esm-externals:@splunk/visualizations-shared/simpleXMLOptions", "src/common/chartingUtils.ts", "src/common/hooks/useTrellisEnabled.ts", "src/common/components/TrellisTitle.tsx", "src/common/TimeSeriesChartWrapper.tsx", "src/common/withDashboardViz.tsx", "esm-externals:@splunk/dashboard-context", "esm-externals:slate-react", "src/RichText/PureRichText/activeInstance.ts", "esm-externals:slate", "src/RichText/PureRichText/types.ts", "esm-externals:dompurify", "src/RichText/PureRichText/utils/slateUtils.ts", "src/RichText/PureRichText/utils/a11yUtils.ts", "src/RichText/PureRichText/PureRichTextContext.tsx", "esm-externals:@splunk/react-ui/ScreenReaderContent", "src/RichText/PureRichText/Editor/FormatButton.tsx", "esm-externals:@splunk/react-ui/ControlGroup", "esm-externals:@splunk/react-ui/Select", "src/RichText/PureRichText/Editor/FontSelector.tsx", "esm-externals:react-dom", "esm-externals:@splunk/react-ui/Button", "esm-externals:@splunk/react-ui/RadioBar", "esm-externals:@splunk/react-ui/Color", "esm-externals:@splunk/react-ui/Text", "esm-externals:@splunk/react-ui/Number", "esm-externals:@splunk/react-ui/Popover", "esm-externals:@splunk/react-icons/Chain", "esm-externals:@splunk/react-icons/List", "esm-externals:@splunk/react-icons/ListNumbered", "esm-externals:@splunk/react-icons/TextBBold", "esm-externals:@splunk/react-icons/TextIItalic", "esm-externals:@splunk/react-icons/TextUUnderline", "esm-externals:@splunk/react-icons/TextSStrikethrough", "esm-externals:@splunk/react-icons/TextAlignLeft", "esm-externals:@splunk/react-icons/TextAlignCenter", "esm-externals:@splunk/react-icons/TextAlignRight", "esm-externals:@splunk/react-icons/TextAlignTop", "esm-externals:@splunk/react-icons/TextAlignVerticalCenter", "esm-externals:@splunk/react-icons/TextAlignBottom", "esm-externals:@splunk/react-icons/ArrowTurnBackLeft", "src/RichText/PureRichText/Editor/EditorPanelStyles.tsx", "src/RichText/PureRichText/Editor/editorPanelUtils.ts", "src/RichText/PureRichText/Editor/hooks/useLinkHandlers.ts", "src/RichText/PureRichText/Editor/hooks/useLineSpacing.ts", "src/RichText/PureRichText/Editor/EditorPanel.tsx", "src/RichText/PureRichText/RichTextStyles.tsx", "src/RichText/PureRichText/renderers/ElementRenderer.tsx", "src/RichText/PureRichText/renderers/LeafRenderer.tsx", "src/RichText/PureRichText/utils/fontSize.ts", "src/RichText/PureRichText/hooks/useEditorSetup.ts", "src/RichText/PureRichText/hooks/useFakeHighlight.ts", "src/RichText/PureRichText/hooks/useContentSync.ts", "src/RichText/PureRichText/hooks/useKeyboardShortcuts.ts", "src/RichText/PureRichText/hooks/useStepFontSize.ts", "src/RichText/PureRichText/hooks/useStepLineSpacing.ts", "src/RichText/PureRichText/hooks/useFocusHandlers.ts", "src/RichText/PureRichText/hooks/useMouseHandlers.ts", "src/RichText/PureRichText/hooks/useEditModeEffect.ts", "src/RichText/PureRichText/InnerEditor.tsx", "src/RichText/PureRichText/hooks/useRichTextState.ts", "src/RichText/PureRichText/hooks/useTokenMap.ts", "src/RichText/PureRichText/hooks/useContentSave.ts", "src/RichText/PureRichText/hooks/useDashboardKeyboardNav.ts", "src/RichText/PureRichText/PureRichText.tsx", "src/RichText/RichText.tsx"],
4
- "sourcesContent": ["/**\n * RichText Visualization\n * Dashboard wrapper for PureRichText\n */\n\nexport * from './RichText';\nexport { default } from './RichText';\n", "\nimport * as defaultImport from \"@splunk/visualization-schemas\";\nexport * from \"@splunk/visualization-schemas\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/ui-utils/i18n\";\nexport * from \"@splunk/ui-utils/i18n\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/themes\";\nexport * from \"@splunk/themes\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-icons/RichText\";\nexport * from \"@splunk/visualization-icons/RichText\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-icons/placeholders/RichText\";\nexport * from \"@splunk/visualization-icons/placeholders/RichText\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"lodash\";\nexport * from \"lodash\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/configUtils\";\nexport * from \"@splunk/visualizations-shared/configUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import { get, range } from 'lodash';\nimport { isDynamicOption } from '@splunk/visualizations-shared/configUtils';\nimport { VizConfig } from '../interfaces/VizConfig';\nimport { EditorLayoutConfig, EditorConfig } from '../interfaces/Editor';\n\n// included for backwards compatibility\nexport { enhanceOptionsSchemaWithDynamicOptions } from '@splunk/visualization-schemas';\n\nexport interface PresetEntry {\n name: string;\n value: any;\n label: string;\n}\n\n/**\n * Helper function to enhance a Visualization Config as needed based on behaviors specified in supports block\n * this function also collapse all editor panels\n * @param vizConfig a Visualization Config\n * @returns an enhanced Visualization Config containing updated config entries based on behaviors it supports\n * and containing `open: false` for all editor panels in editorConfig\n */\nfunction enhanceConfig(vizConfig: VizConfig): VizConfig {\n const enhancedConfig: VizConfig = { ...vizConfig };\n\n enhancedConfig.editorConfig = vizConfig.editorConfig.map((config: EditorConfig): EditorConfig => {\n return { ...config, open: config.open || false };\n });\n return enhancedConfig;\n}\n\n/**\n * Helper function to uncollapse all editor panels by adding `open: true` to the editorConfig\n * Created for editor unit tests\n * @param vizConfig a Visualization Config\n * @returns a Visualization Config containing `open: true` for all editor panels in editorConfig\n */\nfunction uncollapseEditorConfig(vizConfig: VizConfig): VizConfig {\n const editorPanelUncollapsedConfig: VizConfig = { ...vizConfig };\n editorPanelUncollapsedConfig.editorConfig = vizConfig.editorConfig.map(\n (config: EditorConfig): EditorConfig => {\n return { ...config, open: true };\n }\n );\n return editorPanelUncollapsedConfig;\n}\n\n// private helpers to improve readability of getInitialPreset\n// this shouldn't be tested since this util isn't something that we expect to use outside of getInitialPreset\n\n/**\n * this checks to make sure that all values within vizContext are compatible with the given preset's context to determine the initialPreset\n * if a preset has explicitly specified a key as being undefined, the vizContext must also has that key as undefined, or else this CANNOT be the initialPreset\n * the inverse is true; if a preset has key is NOT undefined, it must also be NOT undefined in the corresponding vizContext\n * the internal config contents are irrelevant (as the user could customize them in source), just as long as the presence of `undefined`s match up\n *\n * Since the presetConfigs have explicit undefined keys to override the existing config, we need to explicitly check the undefined values\n */\nfunction hasCompatibleContexts(\n vizContext: { [configKey: string]: any },\n presetContext: { [configKey: string]: any }\n): boolean {\n const presetContextKeys = Object.keys(presetContext);\n return presetContextKeys.every(\n (contextKey): boolean =>\n (presetContext[contextKey] === undefined && vizContext[contextKey] === undefined) ||\n (presetContext[contextKey] !== undefined && vizContext[contextKey] !== undefined)\n );\n}\n\n/**\n * Checks to make sure that dynamic (non-dynamic) options in a given preset are also dynamic (non-dynamic) in the vizOptions\n */\nfunction hasCompatibleOptions(\n vizOptions: { [configKey: string]: any },\n presetOptions: { [configKey: string]: any }\n): boolean {\n const presetOptionKeys = Object.keys(presetOptions);\n return presetOptionKeys.every(\n (optionKey): boolean =>\n isDynamicOption(presetOptions[optionKey]) === isDynamicOption(vizOptions[optionKey])\n );\n}\n\n/**\n * Evaluates whether there is an initialPreset that fits the current state of vizContext + vizOptions\n * This function ignores extraneous vizOptions or vizContext keys, as they could be outside the scope of what the preset is intended to configure\n *\n * @param {Object} vizContext - the current vizContext definition\n * @param {Object} vizOptions - the current vizOptions definition\n * @param {PresetEntry[]} presets - the list of presets, one of which can be considered an initialPreset\n */\nfunction getInitialPreset(\n vizContext: { [configKey: string]: any },\n vizOptions: { [configKey: string]: any },\n presets: PresetEntry[]\n): PresetEntry | null {\n return presets.find((preset): boolean => {\n const presetContext = get(preset, ['value', 'context'], {});\n const presetOptions = get(preset, ['value', 'options'], {});\n const presetContextKeys = Object.keys(presetContext);\n const presetOptionKeys = Object.keys(presetOptions);\n\n // all presets have to explicitly specify which options to reset (i.e. need explicitly undefined keys)\n // if not, then the preset is invalid in config.ts\n if (presetContextKeys.length === 0 || presetOptionKeys.length === 0) return false;\n\n return (\n hasCompatibleContexts(vizContext, presetContext) &&\n hasCompatibleOptions(vizOptions, presetOptions)\n );\n });\n}\n\ninterface PrecisionOption {\n label: string;\n value: number;\n}\n\n/**\n * generates number precision values for a Select editor\n *\n * @param {Number} numPrecisionValues - number of integer precision values to generate\n * @returns {{ label: string; value; string }[]} array of { label, value } tuples\n */\nfunction generatePrecisionValues(numPrecisionValues: number): PrecisionOption[] {\n return range(0, numPrecisionValues + 1).map(\n (i): PrecisionOption => ({\n label: `${i} (0${i > 0 ? '.' : ''}${'0'.repeat(i)})`, // e.g. 0.000 for numPrecisionValues = 3\n value: i,\n })\n );\n}\n\nexport { enhanceConfig, getInitialPreset, generatePrecisionValues, uncollapseEditorConfig, isDynamicOption };\n\n/**\n * insert layout in layout array, return a new layout array instead of updating the original\n *\n * @param {EditorLayoutConfig[][]} layout - editor layout\n * @param {Number} index - the index to insert layout item(s)\n * @param {EditorLayoutConfig[][]} layoutItems - the item(s) to insert\n * @returns {EditorLayoutConfig[][]} new editor layout with insertion\n */\nexport const insertLayout = (\n layout: EditorLayoutConfig[][],\n index: number,\n ...layoutItems: EditorLayoutConfig[][]\n): EditorLayoutConfig[][] => [\n // copy part of the array before the specified index\n ...layout.slice(0, index),\n // inserted layout item\n ...layoutItems,\n // copy part of the array after the specified index\n ...layout.slice(index),\n];\n", "import { _ } from '@splunk/ui-utils/i18n';\nimport { EditorLayoutConfig } from '../interfaces/Editor';\nimport { ThemedDefaults } from '../interfaces/ThemedDefaults';\n\ninterface BackgroundEditorProps {\n label?: string;\n themes: ThemedDefaults;\n labelPosition?: string;\n}\n\nconst background: ({ label, themes, labelPosition }: BackgroundEditorProps) => EditorLayoutConfig[] = ({\n label,\n themes,\n labelPosition,\n}) => [\n {\n label: _(label || 'Background color'),\n option: 'backgroundColor',\n editor: 'editor.color',\n editorProps: {\n labelPosition: labelPosition || 'top',\n themes,\n },\n },\n];\n\nexport default background;\n", "import { richTextOptionsSchema as optionsSchema } from '@splunk/visualization-schemas';\nimport { _ } from '@splunk/ui-utils/i18n';\nimport { pick, variables } from '@splunk/themes';\nimport RichTextIcon from '@splunk/visualization-icons/RichText';\nimport RichTextPlaceholderIcon from '@splunk/visualization-icons/placeholders/RichText';\n\nimport { DataContract } from '../common/interfaces/DataContract';\nimport { DefaultContext } from '../common/interfaces/DefaultContext';\nimport { EditorConfig } from '../common/interfaces/Editor';\nimport { ThemedDefaults } from '../common/interfaces/ThemedDefaults';\nimport { VizBehavior } from '../common/interfaces/VizBehavior';\nimport { VizCategory } from '../common/interfaces/VizCategory';\nimport { VizConfig } from '../common/interfaces/VizConfig';\nimport { VizSize } from '../common/interfaces/VizSize';\nimport { enhanceConfig } from '../common/utils/configUtils';\nimport getBackgroundColorEditor from '../common/editorConfig/BackgroundColor';\n\nconst dataContract: DataContract = {\n requiredDataSources: [],\n optionalDataSources: [],\n initialRequestParams: {\n primary: { offset: 0, count: 10000 },\n },\n};\n\nconst size: VizSize = {\n initialWidth: 300,\n initialHeight: 200,\n};\n\nconst defaultContext: DefaultContext = {};\n\nconst themes: ThemedDefaults = {\n defaultFontColor: (props: any) =>\n pick({\n enterprise: {\n dark: variables.textColor(props),\n light: variables.textColor(props),\n },\n prisma: variables.contentColorDefault(props),\n })(props),\n defaultBackgroundColor: () => 'transparent',\n};\n\nconst editorConfig: EditorConfig[] = [\n {\n label: _('Color and style'),\n open: true,\n layout: [\n [...getBackgroundColorEditor({ label: 'Background color', themes })],\n [\n {\n label: _('Border color'),\n option: 'border.color',\n editor: 'editor.color',\n editorProps: {\n labelPosition: 'top',\n },\n },\n {\n label: _('Border width (px)'),\n option: 'border.width',\n editor: 'editor.number',\n editorProps: {\n min: 0,\n max: 20,\n step: 1,\n labelPosition: 'top',\n },\n },\n ],\n [\n {\n label: '',\n option: 'richTextContent',\n editor: 'editor.text',\n editorProps: {\n multiline: false,\n style: { display: 'none' },\n },\n },\n ],\n [\n {\n label: _('Padding (px)'),\n option: 'padding',\n editor: 'editor.number',\n editorProps: {\n min: 0,\n max: 100,\n step: 1,\n labelPosition: 'top',\n },\n },\n ],\n [\n {\n label: _('Corner radius (px)'),\n option: 'border.radius',\n editor: 'editor.number',\n editorProps: {\n min: 0,\n max: 100,\n step: 1,\n labelPosition: 'top',\n },\n },\n ],\n ],\n },\n];\n\n/**\n * visualization configuration\n */\nconst config: VizConfig = {\n /**\n * unique viz key\n */\n key: 'splunk.richtext',\n /**\n * viz name\n */\n name: _('Text'),\n category: VizCategory.COMPARISONS,\n status: 'preview',\n /**\n * viz icon\n */\n icon: RichTextIcon,\n dataContract,\n size,\n defaultContext,\n optionsSchema,\n editorConfig,\n events: {\n 'richtext.click': {\n description: 'triggered when user clicks on rich text area not formatted as a link',\n },\n },\n supports: [VizBehavior.DYNAMIC_OPTIONS, VizBehavior.EVENTS],\n themes,\n placeholderIcon: RichTextPlaceholderIcon,\n};\n\nexport default enhanceConfig(config);\n", "\nimport * as defaultImport from \"react\";\nexport * from \"react\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/themes/getSettingsFromThemedProps\";\nexport * from \"@splunk/themes/getSettingsFromThemedProps\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-encoding/Options\";\nexport * from \"@splunk/visualization-encoding/Options\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/SanitizeProps\";\nexport * from \"@splunk/visualizations-shared/SanitizeProps\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-context/TimezoneContext\";\nexport * from \"@splunk/visualization-context/TimezoneContext\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/moment\";\nexport * from \"@splunk/moment\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-context/FeatureFlagContext\";\nexport * from \"@splunk/visualization-context/FeatureFlagContext\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"styled-components\";\nexport * from \"styled-components\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/hocUtils\";\nexport * from \"@splunk/visualizations-shared/hocUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/JSONSchemaUtils\";\nexport * from \"@splunk/visualizations-shared/JSONSchemaUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/async-dynamic-options-evaluator\";\nexport * from \"@splunk/async-dynamic-options-evaluator\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/ui-utils/id\";\nexport * from \"@splunk/ui-utils/id\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"prop-types\";\nexport * from \"prop-types\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "/* eslint-disable class-methods-use-this */\nexport interface VizActionHandler {\n /**\n * put focus on the visualization\n */\n focus(): void;\n\n /**\n * compute snapshot of this visualization\n */\n snapshot(): Record<string, unknown>; // (This is for pdf export)\n}\n\nexport class DefaultVizActionHandler {\n focus(): void {\n // noop\n }\n\n snapshot(): Record<string, unknown> {\n return null; // noop\n }\n}\n", "/* eslint-disable react/no-unused-prop-types,react/prefer-stateless-function */\nimport * as T from 'prop-types';\nimport { noop } from 'lodash';\nimport { DashboardVizProps } from './interfaces/DashboardVizProps';\nimport { DefaultVizActionHandler } from './interfaces/VizActionHandler';\n\n// this is identical to the initial height and width we use in BaseVisualization in dashboard-visualizations\nexport const INITIAL_WIDTH = 250;\nexport const INITIAL_HEIGHT = 250;\n\n/**\n * A Splunk visualization\n */\nclass SplunkVisualization {\n static readonly propTypes: Record<keyof DashboardVizProps, T.Validator<any>> = {\n /**\n * display mode\n */\n mode: T.oneOf(['view', 'edit', 'export']).isRequired,\n /**\n * width in pixel or string, defaults to 100%\n */\n width: T.oneOfType([T.string, T.number]).isRequired,\n /**\n * height in pixel or string\n */\n height: T.oneOfType([T.string, T.number]).isRequired,\n /**\n * visualization context used for dynamic option evaluation\n */\n context: T.object,\n /**\n * visualization formatting options\n */\n options: T.object,\n /**\n * A callback to update formatting options\n */\n onOptionsChange: T.func,\n /**\n * datasource state which include data and request params, object key indicate the datasource type.\n */\n dataSources: T.objectOf(\n T.shape({\n /**\n * current request params\n */\n requestParams: T.object,\n /**\n * current dataset\n */\n data: T.shape({\n fields: T.array,\n columns: T.array,\n }),\n /**\n * error\n */\n error: T.shape({\n level: T.string,\n message: T.string,\n }),\n /**\n * meta data that came with the dataset\n */\n meta: T.object,\n })\n ),\n /**\n * A callback to trigger event\n */\n onEventTrigger: T.func,\n /**\n * Inform viz if there are handlers listening to events\n */\n hasEventHandlers: T.bool,\n /**\n * A callback to communicate computed props to a consumer\n */\n onComputedProps: T.func,\n /**\n * A callback to obtain visualization api\n */\n vizActionHandlerRef: T.func,\n\n loading: T.bool,\n theme: T.object,\n /**\n * A callback to request new data with updated request params\n */\n onRequestParamsChange: T.func,\n };\n\n /**\n *\n */\n public static readonly defaults: DashboardVizProps = {\n // BaseVisualization in dashboard-visualizations uses 100% for width but 250 for height\n width: '100%',\n height: INITIAL_HEIGHT,\n dataSources: {},\n onEventTrigger: (): Record<string, unknown> => ({}),\n mode: 'view',\n hasEventHandlers: false,\n options: {},\n context: {},\n onOptionsChange: (): Record<string, unknown> => ({}),\n vizActionHandlerRef: (): DefaultVizActionHandler => new DefaultVizActionHandler(),\n onComputedProps: (): Record<string, unknown> => ({}),\n loading: false,\n onRequestParamsChange: noop,\n };\n}\n\nexport default SplunkVisualization;\n", "import { FieldEntry } from '@splunk/visualizations-shared/dataSourceUtils';\nimport { validSegmentationModes } from '@splunk/visualization-schemas';\n\nexport interface JsonColumnData {\n fields: FieldEntry[] | string[];\n columns: (string | number | null)[][];\n}\n\nexport type HighlightedSourceMap = Record<string, Record<string, boolean>>;\nexport type TagsMap = Record<string, Record<string, string[]>>;\n\nexport interface Meta {\n totalCount: number;\n sid: string;\n app: string;\n highlighted?: HighlightedSourceMap;\n tags?: TagsMap;\n}\n\nexport const validSortDirs = ['asc', 'desc', 'none'] as const;\nexport type SortDirType = (typeof validSortDirs)[number];\nexport type SegmentationType = (typeof validSegmentationModes)[number];\nexport const validOutputModes = ['json_cols', 'json'] as const;\nexport type OutputModeType = (typeof validOutputModes)[number];\n\nexport interface RequestParams {\n count?: number;\n offset?: number;\n sort?: {\n [sortKey: string]: SortDirType;\n };\n segmentation?: SegmentationType;\n // eslint-disable-next-line camelcase\n output_mode?: OutputModeType;\n}\n\nexport interface DataSource {\n requestParams: Partial<RequestParams>;\n onRequestParamsChange?: (p: Record<string, unknown>) => void;\n data: JsonColumnData;\n error?: { level: string; message: string };\n meta: Partial<Meta>;\n}\n\nexport interface DataSourceMeta {\n requestParams: Partial<RequestParams>;\n meta: Partial<Meta>;\n onRequestParamsChange: (payload: RequestParams) => void;\n}\n", "import * as T from 'prop-types';\nimport { has } from 'lodash';\nimport { DataSourceMeta, SortDirType, validSortDirs } from '../interfaces/DataSource';\n\nexport interface SortParams {\n currentSortKey?: string;\n currentSortDir?: SortDirType;\n onSort?: (e: MouseEvent, { sortKey, sortDir }: { sortKey: string; sortDir: SortDirType }) => void;\n}\n\nexport const SortParamsPropTypes = T.shape({\n currentSortKey: T.string,\n currentSortDir: T.oneOf(validSortDirs),\n onSort: T.func,\n});\n\nexport const useSortingParams = ({ requestParams, onRequestParamsChange }: DataSourceMeta): SortParams => {\n let currentSortKey: string | undefined;\n let currentSortDir: SortDirType | undefined;\n\n const nextSortDirMap: Record<SortDirType, SortDirType> = {\n asc: 'desc',\n desc: 'asc',\n none: 'asc',\n };\n\n let onSort: SortParams['onSort'];\n if (typeof onRequestParamsChange === 'function') {\n if (requestParams && has(requestParams, 'sort')) {\n currentSortKey = Object.keys(requestParams.sort).shift();\n currentSortDir = requestParams.sort[currentSortKey];\n }\n\n // undid memoization since there is a dependency on requestParams, which is a deeply nested object\n onSort = (e, { sortKey, sortDir }): void => {\n if (typeof sortKey === 'string') {\n const nextSortDir = has(nextSortDirMap, sortDir) ? nextSortDirMap[sortDir] : 'none';\n onRequestParamsChange({\n ...requestParams,\n ...{ offset: 0, sort: { [sortKey]: nextSortDir } },\n });\n } else {\n onRequestParamsChange(requestParams);\n }\n };\n }\n\n return {\n currentSortKey,\n currentSortDir,\n onSort,\n };\n};\n", "import * as T from 'prop-types';\nimport { cloneDeep, noop } from 'lodash';\nimport * as React from 'react';\nimport { DataSourceMeta, RequestParams } from '../interfaces/DataSource';\n\nexport interface OnChangeParams {\n page?: number;\n count?: number;\n}\nexport interface PaginatorParams {\n isPaging?: boolean;\n current?: number;\n totalPages?: number;\n onChange?: (event: React.MouseEvent<HTMLButtonElement>, data: OnChangeParams) => void;\n}\n\nexport const PaginatorParamsPropTypes = T.shape({\n isPaging: T.bool,\n current: T.number,\n totalPages: T.number,\n onChange: T.func,\n});\n\nexport const usePaginationParams = ({\n requestParams,\n meta,\n onRequestParamsChange,\n}: DataSourceMeta): PaginatorParams => {\n const totalCount = meta?.totalCount || 0;\n const offset = requestParams?.offset || 0;\n const count = requestParams?.count;\n const totalPages = typeof count === 'number' && count > 0 ? Math.ceil(totalCount / count) : 0;\n const current = typeof count === 'number' && count > 0 ? Math.floor(offset / count) + 1 : 0;\n const isPaging = totalPages > 1 && typeof onRequestParamsChange === 'function';\n\n const onChangeHandler = (e, { page, count: countArg }: OnChangeParams): void => {\n const newParams: RequestParams = cloneDeep(requestParams);\n\n if (typeof countArg === 'number') {\n newParams.count = countArg;\n newParams.offset = 0;\n }\n\n const pageCount = typeof newParams.count === 'number' ? newParams.count : 10;\n if (typeof page === 'number' && page > 0) {\n newParams.count = pageCount;\n newParams.offset = (page - 1) * pageCount;\n }\n\n onRequestParamsChange(newParams);\n };\n\n return {\n isPaging,\n current,\n totalPages,\n onChange: typeof onRequestParamsChange === 'function' ? onChangeHandler : noop,\n };\n};\n", "import { useRef } from 'react';\nimport { isEqual } from 'lodash';\n\n/**\n * This hook evaluates and stores the result of a passed function and only\n * re-evaluates the function when passed dependencies change.\n *\n * It is different from the internal React useMemo in the following aspects:\n * - it only stores the last evaluated result\n * - it uses a deep equality check to determine if dependencies have changed\n *\n * Inspired by apollo-client's useDeepMemo\n *\n * @param fn the function to be executed and\n * @param dependencies an array of dependencies\n */\nexport const useDeepMemo = <FnReturnType, DepType>(\n fn: () => FnReturnType,\n dependencies: DepType\n): FnReturnType => {\n const ref = useRef<{ dependencies: DepType; value: FnReturnType }>();\n if (!ref.current || !isEqual(dependencies, ref.current.dependencies)) {\n ref.current = {\n dependencies,\n value: fn(),\n };\n }\n return ref.current.value;\n};\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/Message\";\nexport * from \"@splunk/visualizations-shared/Message\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/SizeAwareWrapper\";\nexport * from \"@splunk/visualizations-shared/SizeAwareWrapper\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import * as React from 'react';\nimport { _ } from '@splunk/ui-utils/i18n';\nimport Message from '@splunk/visualizations-shared/Message';\nimport SizeAwareWrapper from '@splunk/visualizations-shared/SizeAwareWrapper';\nimport SplunkVisualization from '../SplunkVisualization';\n\n/**\n * @method isMissing\n * @param {any} v\n * @returns {boolean} true if the input value === null or undefined\n */\nexport const isMissing = (v): boolean => {\n return v === null || v === undefined;\n};\n\n/**\n * @method misskingKeys\n * @param {string[]} keys\n * @param {object} target\n * @returns {string[]} the keys of missing required props\n */\nexport const missingKeys = (keys: string[], target: Record<string, unknown>): string[] =>\n keys.filter(k => isMissing(target[k]));\n\nexport interface MissingPropsProps {\n width?: string | number;\n height?: string | number;\n missingProps: string[];\n backgroundColor?: string;\n}\n\n/**\n * @method MissingPropsMessage\n * @param {MissingPropsProps} props\n * @returns {React.ReactElement}\n */\nexport const MissingPropsMessage = (props: MissingPropsProps): React.ReactElement => {\n const {\n width = SplunkVisualization.defaults.width,\n height = SplunkVisualization.defaults.height,\n missingProps,\n backgroundColor,\n } = props;\n const cachedHandleResize = React.useCallback((w, h) => {\n setContainerWidth(w);\n setContainerHeight(h);\n }, []);\n const [containerWidth, setContainerWidth] = React.useState<number>(Number(width));\n const [containerHeight, setContainerHeight] = React.useState<number>(Number(height));\n return (\n <div style={{ width: containerWidth, height: containerHeight, background: backgroundColor }}>\n <SizeAwareWrapper width={width} height={height} onResize={cachedHandleResize} />\n <Message\n data-test=\"message\"\n width={width}\n height={height}\n message={_(`Missing property: ${missingProps.join(', ')}`)}\n level=\"error\"\n />\n </div>\n );\n};\n\nexport default MissingPropsMessage;\n", "import { DashboardVizProps } from '../interfaces/DashboardVizProps';\n\nexport type DashboardVizType = React.ComponentType<DashboardVizProps>;\n\n/**\n * @method extendStaticWrapperProps\n * @param {Object} props\n * @param {DashboardVizType} props.Wrapper\n * @param {DashboardVizType} props.Visualization\n */\nexport const extendStaticWrapperProps = ({\n Wrapper,\n Visualization,\n}: {\n [key: string]: DashboardVizType;\n}): void => {\n const extendProperties = ['propTypes', 'config'];\n extendProperties.forEach((prop: string): void => {\n if (Visualization[prop]) {\n // eslint-disable-next-line no-param-reassign\n Wrapper[prop] = Visualization[prop];\n }\n });\n};\n", "import * as React from 'react';\nimport styled from 'styled-components';\nimport { DashboardVizProps } from '../interfaces/DashboardVizProps';\nimport { ExtendedDashViz } from '../interfaces/ExtendedDashViz';\nimport { extendStaticWrapperProps } from '../utils/hocUtils';\n\n// Global provided via webpack\n// eslint-disable-next-line no-underscore-dangle\ndeclare const __VISION_VERSION__: string;\n\nconst Cover = styled.div`\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n`;\n\nconst Blocker = styled.div.attrs({\n 'data-splunk-visualization-version': __VISION_VERSION__,\n})`\n position: relative;\n width: 100%;\n height: 100%;\n`;\n\n/**\n * HOC that renders a cover layer in edit mode\n * @method withEditModeCover\n * @param {ExtendedDashViz} Visualization\n * @returns {ExtendedDashViz} Wrapper\n */\nconst withEditModeCover = (\n Visualization: ExtendedDashViz,\n disableEditModeCover?: boolean\n): ExtendedDashViz => {\n const Wrapper = (props: DashboardVizProps): React.ReactElement<DashboardVizProps> => {\n const { mode } = props;\n const showEditCover = mode === 'edit' && !disableEditModeCover;\n\n return (\n <Blocker>\n <Visualization {...props} />\n {showEditCover && <Cover data-test=\"edit-mode-cover\" />}\n </Blocker>\n );\n };\n extendStaticWrapperProps({ Wrapper, Visualization });\n return Wrapper as ExtendedDashViz;\n};\n\nexport default withEditModeCover;\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/colorUtils\";\nexport * from \"@splunk/visualizations-shared/colorUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/themes/variables\";\nexport * from \"@splunk/themes/variables\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/style\";\nexport * from \"@splunk/visualizations-shared/style\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import * as React from 'react';\nimport styled from 'styled-components';\nimport { toPx } from '@splunk/visualizations-shared/style';\nimport { isColor } from '@splunk/visualizations-shared/colorUtils';\nimport SizeAwareWrapper from '@splunk/visualizations-shared/SizeAwareWrapper';\n\n// Global provided via webpack\n// eslint-disable-next-line no-underscore-dangle\ndeclare const __VISION_VERSION__: string;\n\ninterface ItemProps {\n backgroundColor?: string;\n width?: string | number;\n}\n\nconst Item = styled.div.attrs<ItemProps>(({ width }) => ({\n style: {\n width: toPx(width),\n },\n}))<ItemProps>`\n position: relative;\n background-color: ${(props): string =>\n (isColor(props.backgroundColor) && props.backgroundColor) || props.theme.defaultBackgroundColor}};\n`;\n\ninterface FixSizeItemProps {\n backgroundColor?: string;\n height?: string | number;\n width?: string | number;\n}\n\n// Use `.attrs()` for highly dynamic styles. Ref: https://github.com/styled-components/styled-components/issues/134#issuecomment-312415291\nconst FixSizeItem = styled.div.attrs<FixSizeItemProps>(\n ({\n width,\n height,\n }): {\n style: { width?: string; height?: string };\n } => {\n // Ensure height is never negative (browsers ignore negative height)\n const validHeight = typeof height === 'number' ? Math.max(height, 1) : height;\n return {\n style: {\n ...(width && { width: toPx(width) }),\n ...(validHeight && { height: toPx(validHeight) }),\n },\n };\n }\n)<FixSizeItemProps>`\n position: relative;\n flex-direction: column;\n flex: 1;\n display: flex;\n overflow: hidden !important;\n background-color: ${(props): string =>\n (isColor(props.backgroundColor) && props.backgroundColor) || props.theme.defaultBackgroundColor}};\n`;\n\nconst ItemContent = styled.div`\n position: relative;\n min-height: 100px;\n width: 100%;\n`;\n\nconst FixSizeItemContent = styled.div`\n min-height: 0px;\n flex: 1;\n position: relative;\n box-sizing: border-box;\n overflow: hidden !important;\n`;\n\ninterface HeightAndWidthProps {\n width?: string | number;\n height?: string | number;\n backgroundColor?: string;\n}\n\nconst withFixedSizeContainer = <P extends HeightAndWidthProps>(\n Viz: React.ComponentType<P>\n): React.ComponentType<P> => {\n const FixedSizeContainer = (props: P): React.ReactElement => {\n const { width, height, backgroundColor } = props;\n const cachedHandleResize = React.useCallback((w, h) => {\n setContainerWidth(w);\n setContainerHeight(h);\n }, []);\n const [containerWidth, setContainerWidth] = React.useState<number>(Number(props.width));\n const [containerHeight, setContainerHeight] = React.useState<number>(Number(props.height));\n if (!height) {\n return (\n <Item data-test=\"item\" width={width} backgroundColor={backgroundColor}>\n <ItemContent>\n <Viz {...props} />\n </ItemContent>\n </Item>\n );\n }\n return (\n <FixSizeItem\n data-test=\"fix-size-item\"\n data-splunk-visualization-version={__VISION_VERSION__}\n width={width}\n height={height}\n backgroundColor={backgroundColor}\n >\n <FixSizeItemContent>\n <SizeAwareWrapper width={width} height={height} onResize={cachedHandleResize} />\n <Viz {...props} width={containerWidth} height={containerHeight} />\n </FixSizeItemContent>\n </FixSizeItem>\n );\n };\n FixedSizeContainer.displayName = 'withFixedSizeContainer';\n return FixedSizeContainer;\n};\n\nexport default withFixedSizeContainer;\n", "import * as React from 'react';\nimport { get } from 'lodash';\nimport { _ } from '@splunk/ui-utils/i18n';\nimport Message from '@splunk/visualizations-shared/Message';\nimport { DataSource } from '../interfaces/DataSource';\nimport withFixedSizeContainer from '../hocs/FixedSizeContainer';\nimport SplunkVisualization from '../SplunkVisualization';\n\n/**\n * @method shouldShowIconPlaceholder\n * @param {object} dataSources\n * @param {boolean} loading\n * @returns {boolean}\n */\nexport const shouldShowIconPlaceholder = (\n dataSources: { [name: string]: DataSource },\n loading = false\n): boolean => {\n const data = get(dataSources, 'primary.data.columns[0]', undefined);\n const noData = data === undefined;\n const fields = get(dataSources, 'primary.data.fields[0]', undefined);\n const noFields = fields === undefined;\n return loading || noData || noFields;\n};\n\nexport interface IconPlaceholderProps {\n icon?: React.ComponentType<any>;\n width?: string | number;\n height?: string | number;\n iconColor?: string;\n backgroundColor: string;\n}\n\n/**\n * @method IconPlaceholder\n * @param {IconPlaceholderProps} props\n * @returns {React.ReactElement}\n */\nconst IconPlaceholder = (props: IconPlaceholderProps): React.ReactElement => {\n const {\n width = SplunkVisualization.defaults.width,\n height = SplunkVisualization.defaults.height,\n icon,\n iconColor,\n backgroundColor,\n } = props;\n\n let content = (\n <Message width={width} height={height} level=\"warning\" message={_('No DataSource Connected')} />\n );\n if (icon) {\n content = React.createElement(icon, {\n style: {\n left: '50%',\n top: '50%',\n color: iconColor,\n opacity: 0.15,\n position: 'absolute',\n transform: 'translate(-50%, -50%)',\n },\n width: '50%',\n height: '50%',\n 'data-test': 'icon-placeholder',\n });\n }\n\n return <div style={{ width, height, background: backgroundColor }}>{content}</div>;\n};\n\nexport default withFixedSizeContainer(IconPlaceholder);\n", "import * as React from 'react';\nimport { isColor } from '@splunk/visualizations-shared/colorUtils';\nimport variables from '@splunk/themes/variables';\nimport IconPlaceholder, { shouldShowIconPlaceholder } from '../components/IconPlaceholder';\nimport { VizBehavior } from '../interfaces/VizBehavior';\nimport { DashboardVizProps } from '../interfaces/DashboardVizProps';\nimport { DataSource } from '../interfaces/DataSource';\nimport { ExtendedDashViz } from '../interfaces/ExtendedDashViz';\nimport { extendStaticWrapperProps } from '../utils/hocUtils';\nimport SplunkVisualization from '../SplunkVisualization';\n\ntype useIconPlaceholderType = (\n dataSources: { [name: string]: DataSource },\n loading: boolean,\n options: Record<string, unknown>\n) => boolean;\n\nconst withPlaceholder = (\n Visualization: ExtendedDashViz,\n useIconPlaceholder: useIconPlaceholderType = shouldShowIconPlaceholder\n): ExtendedDashViz => {\n const { config } = Visualization;\n const { themes } = config;\n\n const Wrapper = (props: DashboardVizProps): React.ReactElement<DashboardVizProps> => {\n const {\n dataSources,\n loading,\n options,\n height = SplunkVisualization.defaults.height,\n width = SplunkVisualization.defaults.width,\n } = props;\n\n const showPlaceholder = useIconPlaceholder(dataSources, loading, options);\n const icon = config.placeholderIcon ?? config.icon;\n const iconColor = variables.contentColorActive(props);\n const bgColorFromTheme = isColor(options?.backgroundColor)\n ? options?.backgroundColor\n : themes?.defaultBackgroundColor?.(props);\n\n if (config.supports.includes(VizBehavior.PLACEHOLDER) && showPlaceholder) {\n return (\n <IconPlaceholder\n data-test=\"icon-placeholder\"\n icon={icon}\n width={width}\n height={height}\n backgroundColor={bgColorFromTheme}\n iconColor={iconColor}\n />\n );\n }\n\n return <Visualization {...props} />;\n };\n extendStaticWrapperProps({ Wrapper, Visualization });\n return Wrapper as ExtendedDashViz;\n};\n\nexport default withPlaceholder;\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/numberUtils\";\nexport * from \"@splunk/visualizations-shared/numberUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import type { FieldEntry } from '@splunk/visualizations-shared/dataSourceUtils';\nimport { startsWithNumber } from '@splunk/visualizations-shared/numberUtils';\nimport type { DashboardVizProps, DataSource, VizConfig } from '../interfaces';\nimport { VizBehavior } from '../interfaces';\nimport { ChartEvent } from '../interfaces/ChartEvent';\n\nexport const convertToArrOfObjects = (columns: (string | any[])[], fields: any[]): any[] => {\n if (!columns?.[0]?.length) return [];\n\n const data = [];\n\n for (let i = 0; i < columns[0].length; i += 1) {\n const newObj = {};\n fields.forEach((field, index) => {\n const fieldName = getFieldName(field);\n if (columns[index][i] === '') {\n newObj[fieldName] = null;\n } else {\n newObj[fieldName] = columns[index][i];\n }\n });\n data.push(newObj);\n }\n\n return data;\n};\n\nconst getFieldName = (field: FieldEntry | string): string => (typeof field === 'string' ? field : field.name);\n\n// LTTB algorithm which can be used to downsample time series data while striving to maintain\n// the spikes and overall shape of the chart\n// Copied from https://github.com/sveinn-steinarsson/flot-downsample/blob/0815010016fc94b1bbc6a010afb8aad13ada6d0d/jquery.flot.downsample.js\n// Modifications include:\n// 1) Convert to modern JavaScript(use const, let, and use array.push to push to last element of array)\n// 2) Convert to camel case\n// 3) Convert to TS and also return the indices of the points that are in the downsampled result.\n// 4) Add a new parameter preferredDownsampleIndices that correspond to the indices of points\n// that should be used in case of a tie of the max area in a bucket\nconst largestTriangleThreeBuckets = (\n data: [Date | number, number][],\n threshold: number,\n preferredDownsampleIndices: Set<number>\n): {\n downsampledData: [Date | number, number][];\n downsampledIndices: number[];\n} => {\n const dataLength = data.length;\n const downsampledIndices = [];\n if (threshold >= dataLength || threshold === 0) {\n const allIndices = data.map((values, index) => index);\n return { downsampledData: data, downsampledIndices: allIndices }; // Nothing to do\n }\n\n const sampled: [Date | number, number][] = [];\n let sampledIndex = 0;\n\n // Bucket size. Leave room for start and end data points\n const every = (dataLength - 2) / (threshold - 2);\n\n let a = 0; // Initially a is the first point in the triangle\n let maxAreaPoint: [Date | number, number];\n let maxArea: number | undefined;\n let area: number | undefined;\n let nextA: number | undefined;\n\n sampled.push(data[a]); // Always add the first point\n downsampledIndices.push(0);\n\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < threshold - 2; i++) {\n // Calculate point average for next bucket (containing c)\n let avgX = 0;\n let avgY = 0;\n let avgRangeStart = Math.floor((i + 1) * every) + 1;\n let avgRangeEnd = Math.floor((i + 2) * every) + 1;\n avgRangeEnd = avgRangeEnd < dataLength ? avgRangeEnd : dataLength;\n\n const avgRangeLength = avgRangeEnd - avgRangeStart;\n\n // eslint-disable-next-line no-plusplus\n for (; avgRangeStart < avgRangeEnd; avgRangeStart++) {\n avgX += Number(data[avgRangeStart][0]); // * 1 enforces Number (value may be Date)\n avgY += data[avgRangeStart][1] * 1;\n }\n avgX /= avgRangeLength;\n avgY /= avgRangeLength;\n\n // Get the range for this bucket\n let rangeOffs = Math.floor((i + 0) * every) + 1;\n const rangeTo = Math.floor((i + 1) * every) + 1;\n\n // Point a\n const pointAX = Number(data[a][0]); // Enforce Number (value may be Date)\n const pointAY = data[a][1] * 1;\n\n // eslint-disable-next-line no-multi-assign\n maxArea = area = -1;\n let maxAreaIndex = rangeOffs;\n\n // eslint-disable-next-line no-plusplus\n for (; rangeOffs < rangeTo; rangeOffs++) {\n // Calculate triangle area over three buckets\n area =\n Math.abs(\n (pointAX - avgX) * (data[rangeOffs][1] - pointAY) -\n (pointAX - Number(data[rangeOffs][0])) * (avgY - pointAY)\n ) * 0.5;\n // Modification: try to downsample the least amount of points possible when there are multiple series\n // If all points in a bucket have the same area, prioritize the one with an x index\n // that also existed from another series so we don't add another point unnecessarily.\n // By default LTTB picks the leftmost point in the bucket\n if (area > maxArea || (area === maxArea && preferredDownsampleIndices.has(rangeOffs))) {\n maxArea = area;\n maxAreaPoint = data[rangeOffs];\n nextA = rangeOffs; // Next a is this b\n // Modification: save the index of the point with the most area\n maxAreaIndex = rangeOffs;\n }\n }\n\n // eslint-disable-next-line no-plusplus\n sampled[sampledIndex++] = maxAreaPoint; // Pick this point from the bucket\n downsampledIndices.push(maxAreaIndex);\n a = nextA; // This a is the next a (chosen b)\n }\n\n // eslint-disable-next-line no-plusplus\n sampled[sampledIndex++] = data[dataLength - 1]; // Always add last\n downsampledIndices.push(dataLength - 1);\n\n return { downsampledData: sampled, downsampledIndices };\n};\n\nexport type DownsampleOptions = { threshold: number } & Pick<DashboardVizProps, 'dataSources' | 'options'>;\n\ntype CoerceYColumnResult = {\n canDownsampleColumn: boolean;\n canLooselyCoerceSomeValues: boolean;\n coercedColumn: number[];\n};\n\n/**\n * Strictly coerces the entire column to numbers if it only consists of numeric strings or numbers. Also determines\n * if at least one of the values in the column can be loosely coerced to a number.\n * If the column cannot be strictly downsampled (if it contains nulls or non-numeric strings), returns an empty array and\n * returns that it cannot downsample the column.\n */\nconst strictlyCoerceYColumn = (\n column: (string | number)[] | number[],\n options: DownsampleOptions['options']\n): CoerceYColumnResult => {\n const isNullCoercionEnabled = options.nullValueDisplay === 'zero';\n // Splunk charting allows for numbers in formats such as negative hex that\n // Number() does not support and also allows loose coercion of hex numbers (but not other formats)\n // We want to identify columns which contain at least one value that can be loosely coerced\n const canLooselyCoerceSomeValues =\n column.findIndex(\n value => startsWithNumber(`${value}`) || (isNullCoercionEnabled && value === null)\n ) >= 0;\n\n // If not all values in column can be strictly coerced to a number, we do not downsample\n const coercedColumn: number[] = [];\n const canDownsampleColumn = !column.some(value => {\n const coercedValue = Number(value);\n const coerceValueToZero = isNullCoercionEnabled && value === null;\n\n // if it can't be parsed or isn't safe, fail\n if (\n Number.isNaN(coercedValue) ||\n coercedValue <= Number.MIN_SAFE_INTEGER ||\n coercedValue >= Number.MAX_SAFE_INTEGER ||\n (typeof value !== 'string' && typeof value !== 'number' && !coerceValueToZero)\n ) {\n return true;\n }\n // save value and continue to next\n coercedColumn.push(coercedValue);\n return false;\n });\n\n return {\n canDownsampleColumn,\n canLooselyCoerceSomeValues,\n coercedColumn: canDownsampleColumn ? coercedColumn : [],\n };\n};\n\n/**\n * Tries to coerce the x-column to numbers or dates, if it is eligible for downsampling.\n * Only strictly increasing x-columns are eligible for downsampling.\n * If the column is not eligible for downsampling, returns an empty array.\n */\nconst strictlyCoerceXColumn = (column: (string | number)[], fieldType: string): Date[] | number[] => {\n if (fieldType === 'number') {\n const coercedXColumn = column.map(xValue => Number(xValue));\n if (isColumnStrictlyIncreasing(coercedXColumn, fieldType)) {\n return coercedXColumn;\n }\n } else if (fieldType === 'time') {\n const coercedXColumn = column.map(xValue => new Date(xValue));\n if (isColumnStrictlyIncreasing(coercedXColumn, fieldType)) {\n return coercedXColumn;\n }\n }\n return [];\n};\n\nexport const isDownsamplingEnabledForViz = ({ vizConfig }: { vizConfig: VizConfig }) => {\n return vizConfig.supports?.includes(VizBehavior.DOWNSAMPLING);\n};\n\nexport const calculateThresholdOnRangeSelect = ({\n firstIndex,\n lastIndex,\n dataSources,\n width,\n}: Pick<DashboardVizProps, 'dataSources'> & {\n firstIndex: number;\n lastIndex: number;\n width: number | string;\n}): number => {\n const window = lastIndex - firstIndex + 1;\n // eslint-disable-next-line no-unsafe-optional-chaining\n const ratio = Math.round(Number(dataSources?.primary?.data?.columns[0]?.length / window) * 10) / 10;\n return Math.round(ratio * Number(width));\n};\n\n/**\n * Calculates the downsampling threshold based on the range selection. If search zoom is enabled or there is no selection,\n * then returns the width of the visualization.\n *\n * Otherwise calculates the threshold based on the ratio of the window selected compared to the size of the non-downsampled\n * data sources. Returns null if the chart event's dataset does not match the passed in primary data source or if the chart is zoomed\n * in for a categorical chart.\n */\nexport const calculateDownsamplingThreshold = ({\n enableSearchZoom,\n dataSources,\n selectChartEvent,\n width,\n xField,\n}: {\n enableSearchZoom: boolean;\n dataSources: Record<string, DataSource> | null;\n selectChartEvent: ChartEvent<'chartRangeSelect'> | null;\n width: number;\n xField: string;\n}): number | null => {\n if (enableSearchZoom || !selectChartEvent) {\n return Number(width);\n }\n\n const primaryDataSource = dataSources?.primary;\n if (!primaryDataSource) {\n return null;\n }\n\n const { startXIndex, endXIndex, currentTarget } = selectChartEvent;\n\n try {\n const xFieldIndex = primaryDataSource?.data?.fields.findIndex(field => {\n const name = typeof field === 'string' ? field : field.name;\n return name === xField;\n });\n const downsampledXFieldIndex = currentTarget.dataSet?.fields.findIndex(field => field === xField);\n\n if (xFieldIndex === -1 || downsampledXFieldIndex === -1) {\n return null;\n }\n\n const fullSeries = primaryDataSource?.data?.columns[xFieldIndex];\n const downsampledSeries = currentTarget.dataSet.seriesList[downsampledXFieldIndex];\n\n const firstIndex = fullSeries.findIndex(x => {\n return downsampledSeries[startXIndex] === x;\n });\n const lastIndex = fullSeries.findIndex(x => {\n return downsampledSeries[endXIndex] === x;\n });\n\n if (firstIndex >= 0 && lastIndex >= 0 && firstIndex <= lastIndex) {\n return calculateThresholdOnRangeSelect({\n firstIndex,\n lastIndex,\n dataSources,\n width,\n });\n }\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error('Error occurred while setting downsample threshold on range select event', e);\n }\n\n return null;\n};\n\nconst isColumnStrictlyIncreasing = (column: (number | Date)[], fieldType: 'number' | 'time') => {\n return column.every((value, index) => {\n if (fieldType === 'number') {\n if (Number.isNaN(value)) {\n return false;\n }\n }\n\n if (fieldType === 'time') {\n if (Number.isNaN((value as Date).getTime())) {\n return false;\n }\n }\n if (index === 0) {\n return true;\n }\n return value > column[index - 1];\n });\n};\n\n/**\n * Verifies that all of the columns that are displayed in a chart can be downsampled. Valid columns that can be\n * displayed are those that contain at least one number. We can only downsample columns that only consist of numbers.\n *\n * If all columns can be downsampled, returns the x column coerced to time/number and y columns coerced to numbers.\n * If not all columns can be downsampled, then returns empty arrays for both x and y\n */\nconst tryToCoerceAllDisplayedFields = (\n ds: DataSource,\n xField: string,\n yFields: Set<string>,\n fieldTypes: string[],\n options: DownsampleOptions['options']\n): { xColumn: Date[] | number[]; yColumns: number[][] } => {\n let xColumn: Date[] | number[] = [];\n const yColumns: number[][] = [];\n\n const canDownsample = !ds.data.fields.some((field, index) => {\n const fieldName = getFieldName(field);\n const fieldType = fieldTypes[index] ?? 'unknown';\n const column = ds.data.columns[index];\n let hasDisplayedColumnThatCantBeDownsampled = false;\n\n if (fieldName === xField) {\n xColumn = strictlyCoerceXColumn(column, fieldType);\n } else if (yFields.has(fieldName)) {\n const { coercedColumn, canLooselyCoerceSomeValues, canDownsampleColumn } = strictlyCoerceYColumn(\n ds.data.columns[index],\n options\n );\n // do not perform downsampling if a column can possibly be displayed but cannot\n // be downsampled using LTTB\n hasDisplayedColumnThatCantBeDownsampled = canLooselyCoerceSomeValues && !canDownsampleColumn;\n if (hasDisplayedColumnThatCantBeDownsampled) {\n return true;\n }\n if (canDownsampleColumn) {\n yColumns.push(coercedColumn);\n }\n }\n return false;\n });\n\n if (canDownsample) {\n return { xColumn, yColumns };\n }\n return { xColumn: [], yColumns: [] };\n};\n\nconst pickIndicesFromDataSource = (ds: DataSource, indices: Set<number>): DataSource => {\n const sortedIndices = Array.from(indices).sort((a: number, b: number) => a - b);\n const slicedColumns = [];\n ds.data.columns.forEach(column => {\n const slicedColumn = [];\n sortedIndices.forEach(index => {\n slicedColumn.push(column[index]);\n });\n slicedColumns.push(slicedColumn);\n });\n\n // update data columns with downsampled columns\n return {\n ...ds,\n data: {\n ...ds.data,\n columns: slicedColumns,\n },\n };\n};\n\nexport const downsampleDataSources = ({ dataSources, threshold, options }: DownsampleOptions) => {\n const primaryDS = dataSources?.primary;\n // only downsample time series when number of data points are over threshold\n const numPoints = primaryDS?.data?.columns[0]?.length ?? 0;\n if (Number.isNaN(threshold) || numPoints <= threshold || threshold < 2) {\n return dataSources;\n }\n\n const { xField, yFields, fieldTypes } = options;\n if (!xField || !yFields?.length || !fieldTypes?.length) {\n return dataSources;\n }\n\n const nonInternalYFields = new Set<string>(yFields.filter(yField => !yField.startsWith('_')));\n const maxPointsInDownsample = Math.min(nonInternalYFields.size * threshold, numPoints);\n\n // Do not try to downsample if there are too many downsampled pts\n // At the worst case, each series has non-overlapping downsampled pts\n // which will mean that all points will be included in the downsampled result\n // This will just lead to additional overhead due to coercing each\n // x and y field to number\n if (maxPointsInDownsample >= numPoints) {\n return dataSources;\n }\n\n const { xColumn, yColumns } = tryToCoerceAllDisplayedFields(\n primaryDS,\n xField,\n nonInternalYFields,\n fieldTypes,\n options\n );\n\n if (!yColumns.length || !xColumn.length) {\n return dataSources;\n }\n\n const downsampledDataSources = { ...dataSources };\n const downsampledIndices = new Set<number>();\n\n yColumns.forEach((yColumn, columnIndex) => {\n // perform LTTB downsampling for current series, LTTB takes an [x, y] pair\n const xyPair: [Date | number, number][] = yColumn.map((yValue, index) => {\n return [xColumn[index], yValue];\n });\n\n try {\n const { downsampledIndices: downsampledIndicesForSeries } = largestTriangleThreeBuckets(\n xyPair,\n threshold,\n downsampledIndices\n );\n downsampledIndicesForSeries.forEach(downsampleIndex => downsampledIndices.add(downsampleIndex));\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(`Error occurred while downsampling column ${columnIndex}`, e);\n }\n });\n // update data columns with downsampled columns\n downsampledDataSources.primary = pickIndicesFromDataSource(primaryDS, downsampledIndices);\n\n return downsampledDataSources;\n};\n", "import { useEffect, useRef } from 'react';\n\nexport default function usePrevious<T>(value: T): T | undefined {\n const ref = useRef<T>();\n useEffect(() => {\n ref.current = value;\n });\n return ref.current;\n}\n", "import { useMemo } from 'react';\nimport { Options as Opts } from '@splunk/visualization-encoding/Options';\nimport type { DashboardVizProps } from '../interfaces';\n\n/**\n * Hook that evaluates the DSL for subset of a viz's options needed to determine\n * its x and y fields as well as the types of all its fields.\n */\nconst useGetXAndYFields = ({\n shouldEvaluateDSL,\n options,\n context,\n dataSources,\n}: Pick<DashboardVizProps, 'dataSources' | 'options' | 'context'> & {\n shouldEvaluateDSL: boolean;\n}) => {\n const { dataSourcesWithOnlyOnePoint, dataFrameWithOnlyOnePoint } = useMemo(() => {\n if (!shouldEvaluateDSL) {\n return {\n dataSourcesWithOnlyOnePoint: null,\n dataFrameWithOnlyOnePoint: null,\n };\n }\n\n if (!dataSources?.primary?.data?.columns?.length) {\n return {\n dataSourcesWithOnlyOnePoint: null,\n dataFrameWithOnlyOnePoint: null,\n };\n }\n const { primary: primaryDS } = dataSources;\n\n const columnsWithOnlyOnePoint = primaryDS.data.columns.map(column => {\n return [column[0]];\n });\n\n const filteredDataSources = {\n primary: {\n ...primaryDS,\n data: {\n ...primaryDS.data,\n columns: columnsWithOnlyOnePoint,\n },\n },\n };\n\n return {\n dataSourcesWithOnlyOnePoint: filteredDataSources,\n dataFrameWithOnlyOnePoint: Opts.dataFrameFromDataSource(filteredDataSources),\n };\n }, [dataSources, shouldEvaluateDSL]);\n\n const xAndYFieldsWithTypes = useMemo(() => {\n try {\n if (!dataSourcesWithOnlyOnePoint || !dataFrameWithOnlyOnePoint) {\n return options;\n }\n\n if (!options?.x || (!options?.y && !options?.y2)) {\n return options;\n }\n\n const optionsToEvaluate = {\n x: options.x,\n xField: '> x | getField()',\n y: options.y,\n yFields: options.y ? '> y | getField()' : undefined,\n y2: options.y2,\n y2Fields: options.y2 ? '> y2 | getField()' : undefined,\n fieldTypes: '> primary | getType()',\n };\n\n const {\n xField = '',\n yFields = [],\n y2Fields = [],\n fieldTypes,\n } = Opts.evaluate(\n { options: optionsToEvaluate, context },\n dataSourcesWithOnlyOnePoint,\n () => {},\n dataFrameWithOnlyOnePoint\n );\n return {\n xField,\n yFields: [...yFields, ...y2Fields],\n fieldTypes,\n };\n } catch (e) {\n return {\n xField: undefined,\n yFields: [],\n fieldTypes: [],\n };\n }\n }, [options, context, dataSourcesWithOnlyOnePoint, dataFrameWithOnlyOnePoint]);\n\n return xAndYFieldsWithTypes;\n};\n\nexport default useGetXAndYFields;\n", "import { useRef, useMemo, useEffect, useState } from 'react';\nimport { debounce, isEqual, pick } from 'lodash';\nimport type { DashboardVizProps } from '../interfaces';\nimport type { DownsampleOptions } from '../utils/dataUtils';\nimport { downsampleDataSources } from '../utils/dataUtils';\nimport usePrevious from './usePrevious';\nimport useGetXAndYFields from './useGetXAndYFields';\n\n// Options properties which impact/require re-downsample on change.\nconst downsampleVizOptionProperties = ['nullValueDisplay'];\n\nconst useDownsampleDataSources = ({\n dataSources,\n options,\n context,\n threshold,\n isDownsamplingEnabled,\n}: Pick<DashboardVizProps, 'dataSources' | 'options' | 'context'> & {\n threshold: number;\n isDownsamplingEnabled?: boolean;\n}) => {\n const isFirstUseEffectCall = useRef(true);\n\n const xAndYFieldsWithTypes = useGetXAndYFields({\n shouldEvaluateDSL: isDownsamplingEnabled,\n options,\n context,\n dataSources,\n });\n\n // Extract viz options that impact downsampling.\n const downsampleVizOptions = useMemo(() => pick(options, downsampleVizOptionProperties), [options]);\n const downsampleDSOptions = useMemo(\n () => ({\n ...downsampleVizOptions,\n ...xAndYFieldsWithTypes,\n }),\n [xAndYFieldsWithTypes, downsampleVizOptions]\n );\n\n const previousDownsampleDSOptions = usePrevious(downsampleDSOptions);\n const previousDataSources = usePrevious(dataSources);\n const previousThreshold = usePrevious(threshold);\n\n const [downsampledDataSources, setDownsampledDataSources] = useState(() => {\n return isDownsamplingEnabled\n ? downsampleDataSources({\n dataSources,\n threshold,\n options: downsampleDSOptions,\n })\n : dataSources;\n });\n\n const debouncedDownsampleDataSources = useMemo(() => {\n return debounce(\n (downsampleOptions: DownsampleOptions) => {\n const downsampledResult = downsampleDataSources(downsampleOptions);\n setDownsampledDataSources(downsampledResult);\n },\n 100,\n { trailing: true }\n );\n }, []);\n\n useEffect(() => {\n // don't downsample again on the use effect call that happened due to the initial render\n // this is since we already downsampled as part of the useState call\n if (isFirstUseEffectCall.current) {\n isFirstUseEffectCall.current = false;\n return;\n }\n\n if (!isDownsamplingEnabled) {\n setDownsampledDataSources(dataSources);\n return;\n }\n\n if (\n isEqual(previousDownsampleDSOptions, downsampleDSOptions) &&\n previousDataSources === dataSources &&\n previousThreshold === threshold\n ) {\n return;\n }\n\n // Debounce the downsampling so we don't have to downsample and execute DSL multiple times\n // while the viz is being resized\n debouncedDownsampleDataSources({\n dataSources,\n options: downsampleDSOptions, // Dont want to re-downsample everytime the options change\n threshold,\n });\n\n // need to detect if this runs as part of the initial render\n }, [\n dataSources,\n downsampleDSOptions,\n debouncedDownsampleDataSources,\n xAndYFieldsWithTypes,\n threshold,\n isDownsamplingEnabled,\n previousDataSources,\n previousThreshold,\n previousDownsampleDSOptions,\n ]);\n\n return downsampledDataSources;\n};\n\nexport default useDownsampleDataSources;\n", "\nimport * as defaultImport from \"@splunk/visualization-context/FeatureFlags\";\nexport * from \"@splunk/visualization-context/FeatureFlags\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import * as React from 'react';\nimport FeatureFlags from '@splunk/visualization-context/FeatureFlags';\n\nexport const getFeatureFlag = (\n context: React.Context<any> | null | undefined | Record<keyof typeof FeatureFlags, boolean>,\n flagName: string\n): boolean => {\n // look for feature flag in context first\n if (context && Object.keys(context).find(key => key === flagName)) {\n return context[flagName];\n }\n\n // fall back to defaults\n if (Object.keys(FeatureFlags).find(key => key === flagName)) {\n return FeatureFlags[flagName];\n }\n\n // fall back to false\n return false;\n};\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/trellisUtils\";\nexport * from \"@splunk/visualizations-shared/trellisUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import { cloneDeep, omit } from 'lodash';\nimport { FieldEntry } from '@splunk/visualizations-shared/dataSourceUtils';\nimport {\n DataSplitMode,\n CHART,\n TIMECHART,\n STATS,\n UNKNOWN,\n extractDataSourceAggregationKeysChart,\n extractDataSourceAggregationKeysStats,\n extractSplitByFieldsChartFields,\n extractSplitByFieldsForStats,\n extractSplitByFieldsForUnknown,\n} from '@splunk/visualizations-shared/trellisUtils';\nimport { DataSource } from '../interfaces/DataSource';\n\nexport type SplitDataSource = { [key: string]: { [name: string]: DataSource } };\nexport interface DataSplitResult {\n splitDataSources: SplitDataSource;\n errorCode: 'UNKNOWN_DATA_SPLIT_MODE' | 'INVALID_SPLIT_BY_FIELD' | 'UNKNOWN';\n}\nexport const AGGREGATIONS = 'aggregations';\n\n/**\n * There can be certain SPL cmds that can produce dataSource without a specific field meta info (like group_by_rank, split_by_field etc),\n * to categorize it,\n * Example1:- `index = \"_internal\" | chart count`\n * Example2:- `index=_internal | chart avg(count), max(count)`\n * Example3:- `index = \"_internal\" | stats count`\n * Example4:- `index=_internal | stats avg(count), max(count)`\n */\nexport const dataSourcesSplitByAggregationsUnknown = (dataSource: {\n [name: string]: DataSource;\n}): DataSplitResult => {\n const fields = toFieldEntries(dataSource?.primary?.data?.fields);\n const columns = dataSource?.primary?.data?.columns;\n let splitDataSources = null;\n let errorCode = null;\n\n if (fields?.length) {\n splitDataSources = {};\n for (let i = 0; i < fields.length; i += 1) {\n const fieldName = fields[i].name;\n if (!fieldName?.startsWith('_')) {\n splitDataSources[fieldName] = cloneDeep(\n omit(dataSource, ['primary.data.fields', 'primary.data.columns'])\n );\n splitDataSources[fieldName].primary.data.fields = [fields[i]];\n splitDataSources[fieldName].primary.data.columns = [columns[i]];\n }\n }\n } else {\n errorCode = 'INVALID_SPLIT_BY_FIELD';\n }\n return { splitDataSources, errorCode };\n};\n\nconst toFieldEntries = (fields: FieldEntry[] | string[] = []): FieldEntry[] => {\n return fields.map(field => {\n if (typeof field === 'string') {\n return { name: field };\n }\n return field;\n });\n};\n\nexport const dataSourcesSplitByAggregationsTimechartAndChart = (dataSource: {\n [name: string]: DataSource;\n}): DataSplitResult => {\n const fields = toFieldEntries(dataSource?.primary?.data?.fields);\n const columns = dataSource?.primary?.data?.columns;\n let splitDataSources = null;\n let splitByFields = [];\n let errorCode = null;\n\n if (fields.length > 0) {\n splitByFields = extractDataSourceAggregationKeysChart(fields);\n }\n\n if (splitByFields && splitByFields.length > 0) {\n splitDataSources = {};\n splitByFields.forEach(splitByField => {\n splitDataSources[splitByField] = cloneDeep(\n omit(dataSource, ['primary.data.fields', 'primary.data.columns'])\n );\n splitDataSources[splitByField].primary.data.fields = [fields[0]];\n splitDataSources[splitByField].primary.data.columns = [columns[0]];\n fields.forEach((field: FieldEntry, idx) => {\n const fieldName = field?.name;\n if (\n fieldName !== '_time' &&\n !fieldName?.startsWith('_') &&\n field.data_source === splitByField\n ) {\n splitDataSources[splitByField].primary.data.fields.push(field);\n splitDataSources[splitByField].primary.data.columns.push(columns[idx]);\n }\n });\n });\n } else if (!splitByFields?.length && fields.length > 1) {\n // handle where data_source doesnot exist in fields\n // example1 :- index=_internal | timechart count\n // example2 :- index=_internal | timechart max(count) avg(count)\n splitDataSources = {};\n for (let i = 1; i < fields.length; i += 1) {\n const fieldName = fields[i].name;\n if (!fieldName?.startsWith('_')) {\n splitDataSources[fieldName] = cloneDeep(\n omit(dataSource, ['primary.data.fields', 'primary.data.columns'])\n );\n splitDataSources[fieldName].primary.data.fields = [fields[0], fields[i]];\n splitDataSources[fieldName].primary.data.columns = [columns[0], columns[i]];\n }\n }\n } else {\n errorCode = 'INVALID_SPLIT_BY_FIELD';\n }\n return { splitDataSources, errorCode };\n};\n\nexport const dataSourcesSplitByAggregationsStats = (dataSource: {\n [name: string]: DataSource;\n}): DataSplitResult => {\n const fields = toFieldEntries(dataSource?.primary?.data?.fields);\n const columns = dataSource?.primary?.data?.columns;\n let splitDataSources = null;\n let splitByFields = [];\n let errorCode = null;\n if (fields.length > 0) {\n splitByFields = extractDataSourceAggregationKeysStats(fields);\n }\n\n if (splitByFields && splitByFields.length > 0) {\n splitDataSources = {};\n splitByFields.forEach(splitByField => {\n splitDataSources[splitByField] = cloneDeep(\n omit(dataSource, ['primary.data.fields', 'primary.data.columns'])\n );\n splitDataSources[splitByField].primary.data.fields = [fields[0]];\n splitDataSources[splitByField].primary.data.columns = [columns[0]];\n const idx = fields.findIndex(field => field.name === splitByField);\n if (idx > 0) {\n splitDataSources[splitByField].primary.data.fields.push(fields[idx]);\n splitDataSources[splitByField].primary.data.columns.push(columns[idx]);\n }\n });\n } else {\n errorCode = 'INVALID_SPLIT_BY_FIELD';\n }\n return { splitDataSources, errorCode };\n};\n\nexport const dataSourcesSplitByModeTimechart = (\n dataSource: { [name: string]: DataSource },\n splitBy: string\n): DataSplitResult => {\n const fields = toFieldEntries(dataSource?.primary?.data?.fields);\n const columns = dataSource?.primary?.data?.columns;\n let splitDataSources = null;\n let splitByFields = [];\n let errorCode = null;\n if (fields.length > 0) {\n splitByFields = extractSplitByFieldsChartFields(fields);\n }\n if (splitByFields?.includes(splitBy)) {\n splitDataSources = {};\n const dataSourceKeys = extractDataSourceAggregationKeysChart(fields);\n const valueKeys = [];\n for (let i = 1; i < fields.length; i += 1) {\n // not including internal fields\n if (!fields[i].name?.startsWith('_')) {\n valueKeys.push(fields[i].splitby_value ? fields[i].splitby_value : fields[i].name);\n }\n }\n valueKeys.forEach(val => {\n splitDataSources[val] = cloneDeep(\n omit(dataSource, ['primary.data.fields', 'primary.data.columns'])\n );\n splitDataSources[val].primary.data.fields = [{ name: fields[0].name }];\n splitDataSources[val].primary.data.columns = [[...columns[0]]];\n dataSourceKeys.forEach(dsKey => {\n fields.forEach((field, idx) => {\n if (field.data_source === dsKey && (field.splitby_value === val || field.name === val)) {\n // only push valid fields for the current split by valueKey, instead of all fields.\n splitDataSources[val].primary.data.fields.push({\n name: dsKey,\n });\n splitDataSources[val].primary.data.columns.push([...columns[idx]]);\n }\n });\n });\n });\n } else {\n errorCode = 'INVALID_SPLIT_BY_FIELD';\n }\n return { splitDataSources, errorCode };\n};\n\nconst splitRowWise = (\n dataSource: { [name: string]: DataSource },\n columns,\n fields,\n otherSplitBy: string[],\n dataSourceKeys: string[],\n nonDataSourceAggregations: string[]\n) => {\n const splitDataSources = {};\n const valueKeys = cloneDeep(columns[0]);\n valueKeys.forEach((val, idx) => {\n splitDataSources[val] = cloneDeep(omit(dataSource, ['primary.data.fields', 'primary.data.columns']));\n splitDataSources[val].primary.data.fields = [];\n if (otherSplitBy.length) {\n splitDataSources[val].primary.data.fields = [{ name: otherSplitBy[0] }];\n }\n if (dataSourceKeys.length) {\n const columnValues = [[]];\n splitDataSources[val].primary.data.fields = [\n ...splitDataSources[val].primary.data.fields,\n ...dataSourceKeys.map(k => ({ name: k })),\n ];\n dataSourceKeys.forEach(() => {\n columnValues.push([]);\n });\n for (let i = 1; i <= Math.ceil((fields.length - 1) / dataSourceKeys.length); i += 1) {\n columnValues[0].push(fields[i].splitby_value ? fields[i].splitby_value : fields[i].name);\n dataSourceKeys.forEach((dskey, dsIndx) => {\n const mul = (fields.length - 1) / dataSourceKeys.length;\n columnValues[dsIndx + 1].push(columns[i + dsIndx * mul][idx]);\n });\n }\n splitDataSources[val].primary.data.columns = columnValues;\n } else if (nonDataSourceAggregations.length) {\n const columnValues = [];\n fields.forEach((aggregationField, fieldIdx) => {\n if (fieldIdx > 0) {\n splitDataSources[val].primary.data.fields.push(aggregationField);\n columnValues.push([columns[fieldIdx][idx]]);\n }\n });\n splitDataSources[val].primary.data.columns = columnValues;\n }\n });\n return splitDataSources;\n};\n\nconst splitColumnWise = (\n dataSource: { [name: string]: DataSource },\n columns,\n fields,\n otherSplitBy: string[],\n dataSourceKeys: string[]\n) => {\n const splitDataSources = {};\n const valueKeys = [];\n for (let i = 1; i < fields.length; i += 1) {\n valueKeys.push(fields[i].splitby_value ? fields[i].splitby_value : fields[i].name);\n }\n valueKeys.forEach(val => {\n splitDataSources[val] = cloneDeep(omit(dataSource, ['primary.data.fields', 'primary.data.columns']));\n splitDataSources[val].primary.data.fields = [\n { name: otherSplitBy[0] },\n ...dataSourceKeys.map(k => ({ name: k })),\n ];\n splitDataSources[val].primary.data.columns = [[...columns[0]]];\n dataSourceKeys.forEach(dsKey => {\n fields.forEach((field, idx) => {\n if (field.data_source === dsKey && (field.splitby_value === val || field.name === val)) {\n splitDataSources[val].primary.data.columns.push([...columns[idx]]);\n }\n });\n });\n });\n return splitDataSources;\n};\n\nexport const dataSourcesSplitByModeChart = (\n dataSource: { [name: string]: DataSource },\n splitBy: string\n): DataSplitResult => {\n const fields = toFieldEntries(dataSource?.primary?.data?.fields);\n const columns = dataSource?.primary?.data?.columns;\n let splitDataSources = null;\n let splitByFields = [];\n let errorCode = null;\n if (fields.length > 0) {\n splitByFields = extractSplitByFieldsChartFields(fields);\n }\n if (splitByFields?.includes(splitBy)) {\n const splitByFieldIdx = splitByFields.findIndex(f => f === splitBy);\n const otherSplitBy = splitByFields.filter(f => f !== splitBy);\n const dataSourceKeys = extractDataSourceAggregationKeysChart(fields);\n const nonDataSourceAggregations = [];\n if (\n !dataSourceKeys.length &&\n fields[0].groupby_rank === '0' &&\n fields.length &&\n !fields[1].groupby_rank\n ) {\n for (let i = 1; i < fields.length; i += 1) {\n nonDataSourceAggregations.push(fields[i].name);\n }\n }\n if (splitByFieldIdx === 0) {\n splitDataSources = splitRowWise(\n dataSource,\n columns,\n fields,\n otherSplitBy,\n dataSourceKeys,\n nonDataSourceAggregations\n );\n } else {\n splitDataSources = splitColumnWise(dataSource, columns, fields, otherSplitBy, dataSourceKeys);\n }\n } else {\n errorCode = 'INVALID_SPLIT_BY_FIELD';\n }\n return { splitDataSources, errorCode };\n};\n\n/**\n * This method does datasplitting for 'stats' and generic cmds('makeresults','table' etc - categoried as 'unknown' splitMode).\n * The main difference is for 'stats' cmd possible splitBy fields have 'group_by_rank' in field meta info, whereas for 'unknown' cmd it can be any fieldnames\n */\nexport const dataSourcesSplitByModeStatsorUnknown = (\n dataSource: { [name: string]: DataSource },\n splitBy: string,\n splitMode?: DataSplitMode\n): DataSplitResult => {\n const fields = toFieldEntries(dataSource?.primary?.data?.fields);\n const columns = dataSource?.primary?.data?.columns;\n let splitDataSources = null;\n let splitByFields = [];\n let errorCode = null;\n if (fields.length > 0) {\n splitByFields =\n splitMode !== UNKNOWN\n ? extractSplitByFieldsForStats(fields)\n : extractSplitByFieldsForUnknown(fields);\n }\n const splitByIndex = fields.findIndex(field => field.name === splitBy);\n if (splitByFields?.includes(splitBy)) {\n const splitByColumn = dataSource?.primary?.data?.columns[splitByIndex];\n splitDataSources = {};\n splitByColumn.forEach((val, idx) => {\n if (!splitDataSources[val]) {\n splitDataSources[val] = [idx];\n } else {\n splitDataSources[val].push(idx);\n }\n });\n const cloneFields = cloneDeep(fields);\n cloneFields.splice(splitByIndex, 1);\n const valueKeys = Object.keys(splitDataSources);\n valueKeys.forEach(val => {\n const valIndices = cloneDeep(splitDataSources[val]);\n splitDataSources[val] = cloneDeep(\n omit(dataSource, ['primary.data.fields', 'primary.data.columns'])\n );\n splitDataSources[val].primary.data.fields = cloneFields;\n splitDataSources[val].primary.data.columns = [];\n columns.forEach((col, idx) => {\n if (idx !== splitByIndex) {\n const newCol = valIndices.map(valIdx => col[valIdx]);\n splitDataSources[val].primary.data.columns.push(newCol);\n }\n });\n });\n } else {\n errorCode = 'INVALID_SPLIT_BY_FIELD';\n }\n return { splitDataSources, errorCode };\n};\n\nexport const getTrellisDataSourcesBySplitMode = (\n splitMode: DataSplitMode,\n dataSources: { [name: string]: DataSource },\n trellisSplitBy: string\n): DataSplitResult => {\n let result: DataSplitResult = null;\n try {\n if (splitMode === TIMECHART) {\n result =\n trellisSplitBy === AGGREGATIONS\n ? dataSourcesSplitByAggregationsTimechartAndChart(dataSources)\n : dataSourcesSplitByModeTimechart(dataSources, trellisSplitBy);\n } else if (splitMode === STATS) {\n result =\n trellisSplitBy === AGGREGATIONS\n ? dataSourcesSplitByAggregationsStats(dataSources)\n : dataSourcesSplitByModeStatsorUnknown(dataSources, trellisSplitBy, STATS);\n } else if (splitMode === CHART) {\n result =\n trellisSplitBy === AGGREGATIONS\n ? dataSourcesSplitByAggregationsTimechartAndChart(dataSources)\n : dataSourcesSplitByModeChart(dataSources, trellisSplitBy);\n } else if (splitMode === UNKNOWN) {\n result =\n trellisSplitBy === AGGREGATIONS\n ? dataSourcesSplitByAggregationsUnknown(dataSources)\n : dataSourcesSplitByModeStatsorUnknown(dataSources, trellisSplitBy, UNKNOWN);\n }\n } catch (ex) {\n // eslint-disable-next-line no-console\n console.error('getTrellisDataSourcesBySplitMode ', ex);\n result = { splitDataSources: null, errorCode: 'UNKNOWN' };\n }\n return result;\n};\n\n/**\n * sets legendDisplay to off when a visualization is in trellis mode and not set by the user\n * @param {Boolean} isTrellisOn\n * @param {DashboardVizOpts} options\n * @param {DashboardVizOpts} defaultOptions\n * @returns { {'legendDisplay', 'off'} or {} }\n */\nexport const turnOffLegendDisplayWhenTrellisIsOn = (\n isTrellisOn: boolean,\n options: Record<string, any>\n): Record<string, string> => {\n if (isTrellisOn && !options.legendDisplay) {\n return {\n legendDisplay: 'off',\n };\n }\n return {};\n};\n\n/**\n * helper fn that calculates shared min and max from the split data in trellis mode\n * @param {splitData} SplitDataSource\n * @returns {Array<number>} [min, max]\n */\nconst calculateSharedMinMax = (splitData: SplitDataSource): Array<number> => {\n let max = -Infinity;\n let min = Infinity;\n\n Object.keys(splitData).forEach(splitByKey => {\n const datasources = splitData[splitByKey];\n Object.keys(datasources).forEach(datasourceName => {\n const dataColumns = datasources[datasourceName].data.columns;\n dataColumns.forEach(column => {\n column.forEach(point => {\n // Convert the string to a number. Non-numeric strings are converted to 'nan' and will be ignored.\n const pointNumber = Number(point);\n if (pointNumber > max) {\n max = pointNumber;\n }\n if (pointNumber < min) {\n min = pointNumber;\n }\n });\n });\n });\n });\n\n return [min, max];\n};\n\n/**\n * determines min and max to use in trellis mode\n * @param {splitData} SplitDataSource\n * @returns {Array<number | string>} [min, max]\n */\nexport const determineMinMax = (\n splitData: SplitDataSource,\n trellisSharedScale: boolean,\n yAxisMin: number | string,\n yAxisMax: number | string,\n stackMode?: string\n) => {\n if (!trellisSharedScale || stackMode === 'stacked100' || (yAxisMin !== 'auto' && yAxisMax !== 'auto'))\n return [yAxisMin, yAxisMax];\n\n const [sharedMin, sharedMax] = calculateSharedMinMax(splitData);\n\n const shouldUseSharedMax = sharedMax !== -Infinity && yAxisMax === 'auto';\n const shouldUseSharedMin = sharedMin !== Infinity && yAxisMin === 'auto';\n\n return [shouldUseSharedMin ? sharedMin : yAxisMin, shouldUseSharedMax ? sharedMax : yAxisMax];\n};\n", "\nimport * as defaultImport from \"@splunk/visualization-canvas\";\nexport * from \"@splunk/visualization-canvas\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import styled from 'styled-components';\n\nconst VizStyleWrapper = styled.div.attrs(({ dataTestKey }) => ({\n 'data-test': dataTestKey,\n 'data-testid': dataTestKey,\n}))`\n display: flex;\n justify-content: center;\n flex-direction: column;\n width: 100%;\n height: 100%;\n background-color: ${props => props.backgroundColor};\n`;\n\nVizStyleWrapper.displayName = 'VizStyleWrapper';\n\nexport default VizStyleWrapper;\n", "\nimport * as defaultImport from \"@splunk/react-icons/Triangle\";\nexport * from \"@splunk/react-icons/Triangle\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/propUtils\";\nexport * from \"@splunk/visualizations-shared/propUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/simpleXMLOptions\";\nexport * from \"@splunk/visualizations-shared/simpleXMLOptions\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import { has, isArray, isUndefined } from 'lodash';\nimport React from 'react';\nimport styled from 'styled-components';\nimport variables from '@splunk/themes/variables';\nimport Triangle from '@splunk/react-icons/Triangle';\nimport { adjustOptionsToSchema } from '@splunk/visualizations-shared/propUtils';\nimport { getSimpleXMLOptionsForProps } from '@splunk/visualizations-shared/simpleXMLOptions';\nimport {\n BottomLegendFactory,\n Legend,\n SideLegendFactory,\n LeftLegendFactory,\n TopLegendFactory,\n ScaleConfig,\n shortenNumber,\n SeriesConfig,\n EventAnnotation,\n EventAnnotationRendererProps,\n} from '@splunk/visualization-canvas';\nimport type { LegendTruncation } from '@splunk/visualization-canvas';\nimport type { JsonColumnData } from './interfaces/DataSource';\n\ninterface ChartOptions {\n [key: string]: any;\n}\n\ninterface TransformAxisChartOptionsParams {\n originalOptions: Record<string, any>;\n optionsSchema: Record<string, any>;\n chart: string;\n convertToSCProps: (options: Record<string, any>) => Record<string, any>;\n preservedProps: string[];\n}\n\nexport const SHARED_AXIS_CHART_CANVAS_SPECIFIC_PROPS = [\n 'yAxisMin',\n 'yAxisMax',\n 'y2AxisMin',\n 'y2AxisMax',\n 'showXMajorGridLines',\n 'showYMajorGridLines',\n 'showY2MajorGridLines',\n 'showYMinorGridLines',\n 'showY2MinorGridLines',\n 'xAxisMajorTickVisibility',\n 'xAxisMajorTickSize',\n 'yAxisMajorTickVisibility',\n 'y2AxisMajorTickVisibility',\n 'yAxisMajorTickSize',\n 'y2AxisMajorTickSize',\n 'yAxisMinorTickVisibility',\n 'y2AxisMinorTickVisibility',\n 'yAxisMinorTickSize',\n 'y2AxisMinorTickSize',\n 'legendMode',\n 'legendTruncation',\n];\n\nexport const transformAxisChartOptions = ({\n originalOptions,\n optionsSchema,\n chart,\n convertToSCProps,\n preservedProps,\n}: TransformAxisChartOptionsParams): Record<string, any> => {\n const returnOptions = adjustOptionsToSchema(originalOptions, optionsSchema);\n const convertedOptions = convertToSCProps(returnOptions);\n const transformed = {\n ...getSimpleXMLOptionsForProps(convertedOptions),\n chart,\n };\n\n const preserved = preservedProps.reduce(\n (acc, prop) => {\n if (returnOptions[prop] !== undefined) {\n acc[prop] = returnOptions[prop];\n }\n return acc;\n },\n {} as Record<string, any>\n );\n\n // Preserve legendLabels as stringified JSON (converted in convertTo*SCProperties)\n if (convertedOptions.legendLabels !== undefined) {\n preserved.legendLabels = convertedOptions.legendLabels;\n }\n\n return { ...transformed, ...preserved };\n};\n\nexport const DEFAULT_LINE_WIDTH = 2;\n/**\n * Get formatted annotations - highcharts expects annotations in a specific format\n * @method getAnnotations\n * @param {Object} options\n * @param {Array} options.annotationX\n * @param {Array} options.annotationColor\n * @param {Array} options.annotationLabel\n * @returns {Array}\n */\nexport const getAnnotations = ({ annotationX, annotationColor, annotationLabel }) =>\n annotationX?.length\n ? annotationX.map((timestamp, i) => ({\n color: annotationColor?.[i],\n label: annotationLabel?.[i],\n time: timestamp,\n }))\n : [];\n\n/**\n * Get formatted annotations for canvas - viz-canvas timeseries expects annotations in a specific format\n * @method getAnnotationsForCanvas\n * @param {Object} options\n * @param {Array} options.annotationX\n * @param {Array} options.annotationColor\n * @param {Array} options.annotationLabel\n * @returns {Array}\n */\nexport const getAnnotationsForCanvas = ({\n annotationX,\n annotationColor,\n annotationLabel,\n}): EventAnnotation[] =>\n annotationX?.length\n ? annotationX.map((timestamp, i) => ({\n key: annotationLabel?.[i],\n time: timestamp,\n color: annotationColor?.[i],\n }))\n : [];\n\n/**\n * Styled Triangle component for event annotations with default severityColorNotice\n */\nconst StyledTriangle = styled(Triangle)<{ eventColor?: string }>`\n color: ${props => props.eventColor || variables.severityColorNotice(props)};\n`;\n\n/**\n * Custom event annotation renderer using Triangle icon from @splunk/react-icons\n * @method triangleEventAnnotationRenderer\n * @param {EventAnnotationRendererProps} props\n * @returns {ReactElement}\n */\nexport const triangleEventAnnotationRenderer: React.FC<EventAnnotationRendererProps> = ({\n event,\n dimensions,\n}) => {\n const eventWithColor = event as EventAnnotation & { color?: string };\n return React.createElement(StyledTriangle, {\n width: `${dimensions.width}px`,\n height: `${dimensions.height}px`,\n viewBox: '0 0 24 24',\n variant: 'filled',\n eventColor: eventWithColor.color,\n });\n};\n\n/**\n * Truncate the result set to given limit\n * @method truncateData\n * @param {Object} dataSet - dataSources.primary.data\n * @param {Number|String} truncationLimit - options['chart.resultTruncationLimit']\n * @returns {Object}\n */\nexport const truncateData = (dataSet, truncationLimit): Record<string, any[]> => {\n if (!dataSet) {\n return null;\n }\n\n const limit = parseInt(truncationLimit, 10);\n if (!limit || limit <= 0) {\n return dataSet;\n }\n\n const truncatedData: Record<string, Array<string[] | number[]>> = {\n ...dataSet,\n };\n truncatedData.columns = truncatedData.columns.map(columnData =>\n columnData && Array.isArray(columnData) ? columnData.slice(0, limit) : columnData\n );\n return truncatedData;\n};\n\n/**\n * Helper method to update the option values into the values that SC accepts\n * @method mapToValues\n * @param {Object} options\n * @returns {Object}\n */\nexport const mapToValues = (optionValuesSCMapping: Record<string, any>) => options => {\n const convertedOptions: Record<string, any> = { ...options };\n Object.keys(optionValuesSCMapping).forEach(key => {\n if (has(options, key)) {\n const updatedValue = optionValuesSCMapping[key][options[key]];\n if (!isUndefined(updatedValue)) {\n convertedOptions[key] = updatedValue;\n }\n }\n });\n return convertedOptions;\n};\n\ninterface Y2AxisOptions extends ChartOptions {\n y2Fields?: string | string[];\n}\n\n/**\n * Helper method to process options related to y2Fields\n * @method convertY2AxisOptions\n * @param {Object} originalOptions\n * @returns {Object}\n */\nexport const convertY2AxisOptions = ({\n y2Fields,\n ...originalOptions\n}: Y2AxisOptions): Record<string, any> => {\n const convertedOptions: Record<string, any> = {\n ...originalOptions,\n };\n if (y2Fields) {\n convertedOptions['axisY2.enabled'] = true;\n convertedOptions['axisY2.fields'] = isArray(y2Fields)\n ? y2Fields.filter(name => name).join(',')\n : y2Fields;\n }\n return convertedOptions;\n};\n\n/**\n * Helper method to format value for overlayFields\n * @method convertOverlayFields\n * @param {Object} originalOptions\n * @returns {Object}\n */\nexport const convertOverlayFields = (originalOptions: ChartOptions): ChartOptions => {\n const convertedOptions: ChartOptions = {\n ...originalOptions,\n };\n const { overlayFields } = originalOptions;\n if (overlayFields) {\n convertedOptions.overlayFields = Array.isArray(overlayFields)\n ? overlayFields\n .filter(field => field)\n .map(field => field.trim())\n .join(',')\n : overlayFields;\n }\n return convertedOptions;\n};\n\n/**\n * checks whether data is multi series data\n * @param {array} data array\n * @return {Boolean}\n */\nexport const isMultiSeriesData = (data: string[] | string[][]): boolean =>\n Array.isArray(data) && Array.isArray(data[0]);\n/**\n * checks whether data is multi series data and returns value as array\n * @param {array} data array\n * @param {*} value to return as array\n * @return {array}\n */\nexport const toArrayForSeries = (data, value): any[] => {\n if (isMultiSeriesData(data)) {\n return Array.isArray(value) ? value : [value];\n }\n return [value];\n};\ninterface ConstructFieldsAndColumnsParams {\n x: string[];\n y: string[] | string[][];\n xField: string;\n yFields: string | string[];\n y2?: string[] | string[][];\n y2Fields?: string | string[];\n}\nexport const constructFieldsAndColumns = ({\n x = [],\n y = [],\n xField,\n yFields,\n y2,\n y2Fields,\n}: ConstructFieldsAndColumnsParams): JsonColumnData => {\n const columns = [x.map(String), ...toArrayForSeries(y, y).map(series => series.map(String))];\n const yFieldsArray = toArrayForSeries(y, yFields);\n const fields = [{ name: xField }, ...yFieldsArray.map(field => ({ name: field }))];\n // splunk-charting requires y2 to be part of columns\n // when y & y2 options are configured with different (mutually exclusive) series\n // y2 columns need to be added to columns\n if (y2Fields) {\n const y2FieldsArray = toArrayForSeries(y2, y2Fields);\n const y2AsArray = toArrayForSeries(y2, y2).map(series => series?.map(String));\n y2FieldsArray.forEach((y2Field, index) => {\n if (yFieldsArray.indexOf(y2Field) === -1 && y2AsArray[index]) {\n fields.push({\n name: y2Field,\n });\n columns.push(y2AsArray[index]);\n }\n });\n }\n return {\n columns,\n fields,\n };\n};\n\nexport function constructAdditionalTooltipFieldsMap({ fields, columns, additionalTooltipFields }) {\n const map = {};\n\n additionalTooltipFields?.forEach(fieldName => {\n const index = fields.findIndex(f => f.name === fieldName);\n if (index !== -1) {\n map[fieldName] = columns[index];\n }\n });\n\n return map;\n}\n\n/**\n * Extracts additional tooltip values from columns and fields into an array of objects.\n * Each object in the array represents the values at a specific data point index.\n * This follows the same pattern used by Timeline visualization.\n *\n * @param columns - Array of column data\n * @param fields - Array of field definitions with name property\n * @param additionalTooltipFields - Array of field names to extract\n * @returns Array of objects, where each object maps field names to values at that index\n */\n// Type alias for a single tooltip field value record\ntype TooltipFieldRecord = Record<string, string | number | null>;\n\nexport function extractAdditionalTooltipValues(\n columns: (string | number | null)[][],\n fields: { name: string }[],\n additionalTooltipFields: string[]\n): TooltipFieldRecord[] {\n if (!additionalTooltipFields?.length || !columns?.length || !fields?.length) {\n return [];\n }\n\n // Create a mapping of field names to their column indices\n const fieldIndexMap = fields.reduce<Record<string, number>>((acc, field, index) => {\n acc[field.name] = index;\n return acc;\n }, {});\n\n const numRows = columns[0]?.length || 0;\n const additionalTooltipValuesArray: TooltipFieldRecord[] = [];\n\n for (let i = 0; i < numRows; i += 1) {\n const tooltipObject: TooltipFieldRecord = {};\n\n additionalTooltipFields.forEach(fieldName => {\n if (fieldName in fieldIndexMap) {\n const columnIndex = fieldIndexMap[fieldName];\n tooltipObject[fieldName] = columns[columnIndex]?.[i] ?? null;\n } else {\n tooltipObject[fieldName] = null;\n }\n });\n\n additionalTooltipValuesArray.push(tooltipObject);\n }\n\n return additionalTooltipValuesArray;\n}\n\nexport type AdditionalTooltipResult = TooltipFieldRecord[];\n\ntype AdditionalTooltipValuesCache = {\n columns: unknown;\n fields: unknown;\n additionalTooltipFields: string[] | undefined;\n result: AdditionalTooltipResult | undefined;\n};\n\nexport const areStringArraysEqual = (a: string[] | undefined, b: string[] | undefined): boolean => {\n if (a === b) return true;\n if (!a || !b) return false;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i += 1) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n};\n\nexport const createAdditionalTooltipValuesMemoizer = () => {\n let cache: AdditionalTooltipValuesCache = {\n columns: null,\n fields: null,\n additionalTooltipFields: undefined,\n result: undefined,\n };\n\n return (\n columns: (string | number | null)[][],\n fields: { name: string }[],\n additionalTooltipFields: string[] | undefined\n ): AdditionalTooltipResult | undefined => {\n if (\n cache.columns === columns &&\n cache.fields === fields &&\n areStringArraysEqual(cache.additionalTooltipFields, additionalTooltipFields)\n ) {\n return cache.result;\n }\n\n let result: AdditionalTooltipResult | undefined;\n if (additionalTooltipFields?.length && columns && fields) {\n result = extractAdditionalTooltipValues(columns, fields, additionalTooltipFields);\n }\n\n cache = {\n columns,\n fields,\n additionalTooltipFields,\n result,\n };\n\n return result;\n };\n};\n\n// Note: we are making the assumption that attaching a range.select listener means the user wants to enable search zoom\n// This is because we don't know if the time range tokens being updated by the drilldown is used by the current viz.\n// In the future we are considering using a shared context to pass this information from UDF to Viz.\ninterface OptionsProps {\n events?: string[];\n selectedItemId?: string;\n [key: string]: unknown;\n}\ninterface EventHandler {\n type: string;\n options: OptionsProps;\n}\n\nexport const shouldEnableSearchZoom = (eventHandlers: EventHandler[] = [], xField = '') => {\n const rangeSelectEventHandler = eventHandlers.find(eventHandler =>\n eventHandler.options.events?.includes('range.select')\n );\n // Check if xField is _time. This is how splunk-charting distinguishes a time chart from categorical.\n // Note: search zoom will be buggy if the x axis uses timestamp values but is not _time\n const xAxisIsTime = xField === '_time';\n\n return !!rangeSelectEventHandler && xAxisIsTime;\n};\n\nconst canvasSupportedTimeSeriesCharts = ['splunk.line', 'splunk.area'];\nexport const isTimeSeriesCanvasRenderSupported = (vizConfigKey: string): boolean => {\n return canvasSupportedTimeSeriesCharts.includes(vizConfigKey);\n};\n\ntype ChartData = {\n fields: (string | { name: string })[];\n columns: (string | number)[][];\n};\n\n// Filter all internal fields and columns except for _time fild\nexport const filterChartDataFromInternalFields = (chartData: ChartData): ChartData => {\n const { fields, columns } = chartData;\n\n // Determine the indexes to keep\n const keepIndexes = fields.reduce<number[]>((acc, field, index) => {\n const fieldName = typeof field === 'object' ? field?.name : field;\n if (!fieldName?.startsWith('_') || fieldName === '_time') {\n acc.push(index);\n }\n return acc;\n }, []);\n\n // Filter fields and columns\n const filteredFields = keepIndexes.map(index => fields[index]);\n const filteredColumns = keepIndexes.map(index => columns[index]);\n\n return { fields: filteredFields, columns: filteredColumns };\n};\n\nexport const isTimeField = (field): boolean => {\n return (\n (typeof field === 'object' && field?.name === '_time') ||\n (typeof field === 'string' && field === '_time')\n );\n};\n\nexport const convert2DArrayToNumbers = arr => {\n return arr.map(subArray => subArray.map(element => parseFloat(element)));\n};\n\nexport const convertTimeStringToUnix = arr => {\n return arr.map(timeStr => parseInt((new Date(timeStr).getTime() / 1000).toFixed(0), 10));\n};\n\n/**\n * Parses an axis value that may be 'auto', null, undefined, empty string, or a numeric value.\n * Returns undefined for non-numeric values, allowing the renderer to auto-calculate the range.\n * @param {any} val - The value to parse (string, number, null, undefined)\n * @returns {number | undefined} - Parsed number or undefined\n */\nexport const parseAxisValue = (val: any): number | undefined => {\n if (val === undefined || val === null || val === 'auto' || val === '') {\n return undefined;\n }\n const num = typeof val === 'number' ? val : Number.parseFloat(val);\n return Number.isNaN(num) ? undefined : num;\n};\n\n/**\n * Parses X-axis line visibility option from string to boolean or undefined.\n * @param {string | undefined} visibility - The visibility option ('hide', 'show', or other)\n * @returns {boolean | undefined} - false for 'hide', true for 'show', undefined otherwise\n */\nexport const parseXAxisLineVisibility = (visibility?: string): boolean | undefined => {\n if (visibility === 'hide') return false;\n if (visibility === 'show') return true;\n return undefined;\n};\n\n// Legend placement logic for canvas render, used in TimeseriesChartWrapper\nexport const getLegend = (props: {\n legendDisplay: string;\n isSeriesCompare: boolean;\n legendTruncation?: LegendTruncation;\n}): Legend | false => {\n const legendPlacement = props?.legendDisplay;\n const { isSeriesCompare, legendTruncation } = props;\n const commonLegendProps = {\n center: true,\n fontSize: 12,\n largerTiles: true,\n hideSeriesValue: !isSeriesCompare, // Show values if in seriesCompare mode\n legendTruncation,\n };\n\n // \"right\" | \"left\" | \"top\" | \"bottom\" | \"off\"\n switch (legendPlacement) {\n case 'off':\n return false;\n case 'left':\n return LeftLegendFactory({\n ...commonLegendProps,\n });\n case 'bottom':\n return BottomLegendFactory({\n wrap: true,\n ...commonLegendProps,\n });\n case 'top':\n return TopLegendFactory({\n wrap: true,\n ...commonLegendProps,\n });\n // Note: By default, use right legend\n default:\n return SideLegendFactory({\n ...commonLegendProps,\n });\n }\n};\n\nexport const getComputedAxisTitles = (\n inputAxisTitle: string,\n fields: string[],\n axisTitleVisibility: 'show' | 'collapsed'\n): string => {\n if (axisTitleVisibility === 'collapsed') {\n return '';\n }\n let fieldTitle = fields.length > 1 ? '' : fields[0]; // If more than one series (multi-series) default empty title\n if (!fieldTitle) {\n fieldTitle = '';\n }\n return inputAxisTitle?.length ? inputAxisTitle.trim() : fieldTitle;\n};\n\n/**\n * Truncates Y-axis title based on available container height and font metrics\n * @param axisTitle - The title text to potentially truncate\n * @param containerSpacing - Available height/ width in pixels depending on axis orientation\n * @param fontSize - Font size in pixels (default: 12)\n * @returns Truncated title with ellipsis if needed\n */\nexport const ellipsisAxisTitle = (axisTitle: string, containerSpacing: number, fontSize = 12): string => {\n if (!axisTitle) {\n return '';\n }\n if (Number.isNaN(containerSpacing) || containerSpacing <= 0) {\n return axisTitle;\n }\n // Calculate available height for text (leave 40% margin)\n const availableHeight = containerSpacing * 0.6;\n\n // Use a generic character width ratio that works across most fonts\n // 0.55 is a reasonable average for most fonts\n const avgCharWidth = fontSize * 0.55;\n\n // Calculate maximum characters that fit in available height\n const maxChars = Math.floor(availableHeight / avgCharWidth);\n\n // If title fits, return as-is\n if (axisTitle.length <= maxChars) {\n return axisTitle;\n }\n\n // Need to truncate - use middle ellipsis for better context\n if (maxChars <= 3) {\n return '...'; // Not enough space for meaningful text\n }\n\n // Reserve 3 characters for ellipsis\n const availableChars = maxChars - 3;\n const halfChars = Math.floor(availableChars / 2);\n\n // Create truncated title with middle ellipsis\n const start = axisTitle.slice(0, halfChars);\n const end = axisTitle.slice(-halfChars);\n\n return `${start}...${end}`;\n};\n\nexport type FieldObject = {\n name: string;\n};\n\nexport const getFieldName = (field: string | FieldObject): string => {\n const fieldName = typeof field === 'object' ? (field as unknown as FieldObject)?.name : field;\n return fieldName;\n};\n\nexport const getFieldNames = (fields: (string | FieldObject)[]): string[] => {\n return fields.map(field => getFieldName(field));\n};\n\n/**\n * Type alias for axis label visibility options\n */\nexport type AxisLabelVisibility = 'hide' | 'show' | 'auto';\n\n/**\n * Returns X scale config for viz-canvas charts\n * @param label\n * @param xAxisLabelVisibility\n * @returns\n */\nexport const getXScaleConfig = (\n label: string,\n xAxisLabelVisibility?: AxisLabelVisibility,\n xAxisLabelRotation?: -90 | -45 | 0 | 45 | 90\n): ScaleConfig => {\n const xConfig: ScaleConfig = { x: {} };\n xConfig.x.label = label;\n // Set hideLabels to true when xAxisLabelVisibility is \"hide\"\n if (xAxisLabelVisibility === 'hide') {\n xConfig.x.hideLabels = true;\n }\n // Set labelRotation if provided\n if (xAxisLabelRotation !== undefined) {\n xConfig.x.labelRotation = xAxisLabelRotation;\n }\n return xConfig;\n};\n\n/**\n * Returns Y scale config for viz-canvas charts\n * @param label\n * @param yAxisAbbreviation\n * @param yAxisScale\n * @param yAxisLabelVisibility\n * @param yAxisMin\n * @param yAxisMax\n * @returns\n */\nexport const getYScaleConfig = (\n label: string,\n yAxisAbbreviation: string,\n yAxisScale?: 'linear' | 'log',\n yAxisLabelVisibility?: AxisLabelVisibility,\n yAxisMin?: number,\n yAxisMax?: number\n): ScaleConfig => {\n const scaleType = yAxisScale ?? 'linear';\n const yConfig: ScaleConfig = { y: {} };\n yConfig.y.label = label;\n yConfig.y.type = scaleType;\n if (yAxisAbbreviation !== 'none') {\n yConfig.y.tickFmt = (v): string => shortenNumber(v, 1);\n }\n // Only set fixed width when abbreviation is ON\n // When abbreviation is OFF, width remains undefined to allow dynamic sizing in uplot-utils\n // based on actual data label lengths\n if (yAxisAbbreviation !== 'none') {\n yConfig.y.width = label && label.length > 0 ? 30 : 10;\n }\n if (yAxisLabelVisibility === 'hide') {\n yConfig.y.hideLabels = true;\n }\n if (yAxisMin !== undefined || yAxisMax !== undefined) {\n yConfig.y.range = (u, dataMin, dataMax) => {\n const min = yAxisMin ?? dataMin;\n const max = yAxisMax ?? dataMax;\n return [min, max];\n };\n }\n return yConfig;\n};\n/**\n * Returns Y2 scale config for viz-canvas charts\n * @param label\n * @param axisAbbreviation\n * @param axisScale\n * @param roundAxisLabelsToInteger\n * @param y2AxisLabelVisibility\n * @param y2AxisMin\n * @param y2AxisMax\n * @returns\n */\nexport const getY2ScaleConfig = (\n label: string,\n axisAbbreviation: string,\n axisScale?: 'linear' | 'log',\n roundAxisLabelsToInteger?: boolean,\n y2AxisLabelVisibility?: AxisLabelVisibility,\n y2AxisMin?: number,\n y2AxisMax?: number\n): ScaleConfig => {\n const y2Config: ScaleConfig = { y2: {} };\n const scaleType = axisScale ?? 'linear';\n y2Config.y2.label = label;\n y2Config.y2.side = 'right';\n // Note: showGrid is intentionally not set here so that the top-level\n // showY2MajorGridLines prop can control it (defaults to false)\n y2Config.y2.type = scaleType;\n if (axisAbbreviation !== 'none') {\n y2Config.y2.tickFmt = (v): string => shortenNumber(v, 1, roundAxisLabelsToInteger);\n // Set width for abbreviated Y2 axis\n // Y2 needs more width (50px) than Y-axis (30px) because of rotated title positioning\n // Width will be used to detect abbreviation setting in padding calculations\n y2Config.y2.width = label && label.length > 0 ? 50 : 10;\n } else if (roundAxisLabelsToInteger) {\n y2Config.y2.tickFmt = (v): string =>\n roundAxisLabelsToInteger ? Math.round(v).toString() : v.toString();\n }\n if (y2AxisLabelVisibility === 'hide') {\n y2Config.y2.hideLabels = true;\n }\n if (y2AxisMin !== undefined || y2AxisMax !== undefined) {\n y2Config.y2.range = (u, dataMin, dataMax) => {\n const min = y2AxisMin ?? dataMin;\n const max = y2AxisMax ?? dataMax;\n return [min, max];\n };\n }\n return y2Config;\n};\n\n/**\n * Add series overrides for viz-canvas charts (for eg:- line width)\n */\nconst getSeriesType = (\n isOverlay: boolean,\n isAreaChart: boolean,\n isStacked: boolean\n): SeriesConfig[string]['type'] | undefined => {\n if (isOverlay) return 'line';\n if (!isAreaChart) return undefined;\n return isStacked ? 'stacked-area' : 'area';\n};\n\nconst getY2Scale = (\n field: string,\n y2fields: string[] | undefined,\n overlayFields: string[] | undefined\n): 'y' | 'y2' => {\n const assignToY2 =\n (y2fields?.length > 0 && y2fields.includes(field)) ||\n (!y2fields?.length && overlayFields?.includes(field));\n return assignToY2 ? 'y2' : 'y';\n};\n\nexport const getSeriesOverrides = (opts: {\n yfields: string[];\n y2fields?: string[];\n lineWidth?: number;\n overlayFields?: string[];\n y2Enabled?: boolean;\n nullValueMode?: 'gaps' | 'connect' | 'zero';\n markerDisplay?: 'off' | 'filled' | 'outlined';\n lineDashStyle?: string;\n lineDashStylesByField?: Record<string, string>;\n stepPosition?: 'off' | 'before' | 'after';\n stepPositionsByField?: Record<string, 'off' | 'before' | 'after'>;\n type?: 'line' | 'area';\n stackMode?: 'auto' | 'stacked' | 'stacked100';\n showLines?: boolean;\n}): SeriesConfig => {\n const {\n yfields,\n y2fields,\n lineWidth,\n overlayFields,\n y2Enabled,\n nullValueMode,\n markerDisplay,\n lineDashStyle,\n lineDashStylesByField,\n stepPosition,\n stepPositionsByField,\n type,\n stackMode,\n showLines,\n } = opts;\n const seriesConfig: SeriesConfig = {};\n\n let spanGaps: boolean | undefined;\n if (nullValueMode === 'gaps') {\n spanGaps = false;\n } else if (nullValueMode != null) {\n spanGaps = true;\n } else {\n spanGaps = undefined;\n }\n const replaceNullsWithZero = nullValueMode === 'zero' ? true : undefined;\n\n const isAreaChart = type === 'area';\n const isStacked = isAreaChart && (stackMode === 'stacked' || stackMode === 'stacked100');\n\n // Non-overlay area fields first, then overlay fields - so overlays render on top\n const areaFields = isAreaChart ? yfields.filter(f => !overlayFields?.includes(f)) : yfields;\n const overlayFieldsInOrder = overlayFields?.filter(f => yfields.includes(f)) ?? [];\n const orderedFields = isAreaChart ? [...areaFields, ...overlayFieldsInOrder] : yfields;\n\n orderedFields.forEach(field => {\n const isOverlay = overlayFields?.includes(field) ?? false;\n const isPercent = isAreaChart && stackMode === 'stacked100' && !isOverlay;\n const shouldHideAreaOutline = isAreaChart && showLines === false && !isOverlay;\n\n seriesConfig[field] = {\n overrides: {\n width: shouldHideAreaOutline ? 0 : (lineWidth ?? DEFAULT_LINE_WIDTH),\n ...(isPercent ? ({ stacking: { mode: 'percent', group: 'A' } } as object) : {}),\n } as SeriesConfig[string]['overrides'],\n };\n\n const seriesType = getSeriesType(isOverlay, isAreaChart, isStacked);\n if (seriesType !== undefined) seriesConfig[field].type = seriesType;\n\n if (spanGaps !== undefined) seriesConfig[field].overrides.spanGaps = spanGaps;\n\n if (y2Enabled) seriesConfig[field].overrides.scale = getY2Scale(field, y2fields, overlayFields);\n\n if (markerDisplay !== undefined) seriesConfig[field].markerDisplay = markerDisplay;\n\n if (!isAreaChart || isOverlay) {\n const fieldDashStyle = lineDashStylesByField?.[field] || lineDashStyle;\n if (fieldDashStyle) seriesConfig[field].lineDashStyle = fieldDashStyle as any;\n }\n\n const hasFieldStepPosition = Object.hasOwn(stepPositionsByField || {}, field);\n const fieldStepPosition = hasFieldStepPosition ? stepPositionsByField?.[field] : stepPosition;\n if (fieldStepPosition && fieldStepPosition !== 'off') {\n (seriesConfig[field] as SeriesConfig[string] & { stepPosition?: string }).stepPosition =\n fieldStepPosition;\n }\n\n if (replaceNullsWithZero !== undefined) {\n (\n seriesConfig[field] as SeriesConfig[string] & { replaceNullsWithZero?: boolean }\n ).replaceNullsWithZero = replaceNullsWithZero;\n }\n });\n\n return seriesConfig;\n};\n\n/**\n * Finds the start and end indices in time series data for a given range.\n * @param xData - Array of time values (can be ISO strings or epoch timestamps)\n * @param startValue - Start value of the range (epoch timestamp)\n * @param endValue - End value of the range (epoch timestamp)\n * @returns Object with startXIndex (first index where time >= startValue) and endXIndex (last index where time <= endValue)\n */\nexport const findRangeIndices = (\n xData: (string | number)[],\n startValue: number,\n endValue: number\n): { startXIndex: number; endXIndex: number } => {\n let startXIndex = -1;\n let endXIndex = -1;\n\n // Convert xData to epoch timestamps if they are ISO strings\n const xDataEpoch = xData.map(val => {\n if (typeof val === 'string') {\n return new Date(val).getTime() / 1000; // Convert to epoch seconds\n }\n return val;\n });\n\n // Find the closest time value >= startValue\n for (let i = 0; i < xDataEpoch.length; i += 1) {\n if (xDataEpoch[i] >= startValue) {\n startXIndex = i;\n break;\n }\n }\n\n // If no value >= startValue found, use the last index (all values are less)\n if (startXIndex === -1 && xDataEpoch.length > 0) {\n startXIndex = xDataEpoch.length - 1;\n }\n\n // Find the closest time value <= endValue\n for (let i = xDataEpoch.length - 1; i >= 0; i -= 1) {\n if (xDataEpoch[i] <= endValue) {\n endXIndex = i;\n break;\n }\n }\n\n // If no value <= endValue found, use the first index (all values are greater)\n if (endXIndex === -1 && xDataEpoch.length > 0) {\n endXIndex = 0;\n }\n\n return { startXIndex, endXIndex };\n};\n", "import { useContext } from 'react';\nimport FeatureFlagContext from '@splunk/visualization-context/FeatureFlagContext';\nimport { LAYOUT_TYPE } from '@splunk/visualization-schemas';\n\nexport const useTrellisFeatureFlagOn = (): boolean => {\n const context = useContext(FeatureFlagContext) as Record<string, unknown>;\n return Boolean(context?.visualizations_enableTrellis);\n};\n\nexport const useTrellisEnabled = (layoutType = LAYOUT_TYPE.Off): boolean => {\n const trellisFeatureEnabled = useTrellisFeatureFlagOn();\n return trellisFeatureEnabled && layoutType === LAYOUT_TYPE.Trellis;\n};\n", "import * as React from 'react';\nimport styled from 'styled-components';\n\nexport const TRELLIS_TITLE_HEIGHT = 28;\n\nconst TrellisTitleText = styled.div`\n margin-left: 10px;\n margin-right: 10px;\n padding-top: 8px;\n text-overflow: ellipsis;\n white-space: nowrap;\n overflow: hidden;\n`;\n\nconst TrellisTitleDiv = styled.div<{\n fontColor: string;\n backgroundColor: string;\n}>`\n height: ${TRELLIS_TITLE_HEIGHT}px;\n font-size: 14px;\n font-weight: 700;\n color: ${props => props.fontColor};\n background-color: ${props => props.backgroundColor};\n box-shadow: 0 1px ${props => props.backgroundColor}; // this is added to avoid a 1px gap between title and viz divs that showed up intermittently because of pixel rounding error in chrome.\n`;\n\ninterface TrellisTitleProps {\n fontColor: string;\n backgroundColor: string;\n trellisKey: unknown;\n}\n\nconst formatTrellisKey = (value: TrellisTitleProps['trellisKey']): string => {\n if (value === null || value === undefined) {\n return '';\n }\n if (typeof value === 'string') {\n return value;\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return value.toString();\n }\n if (typeof value === 'symbol') {\n return value.toString();\n }\n try {\n return JSON.stringify(value);\n } catch {\n // JSON.stringify throws for BigInt and circular references\n return typeof value === 'bigint' ? value.toString() : '';\n }\n};\n\nexport const TrellisTitle = (props: TrellisTitleProps) => {\n const titleText = formatTrellisKey(props.trellisKey);\n return (\n <TrellisTitleDiv\n fontColor={props.fontColor}\n backgroundColor={props.backgroundColor}\n data-test=\"trellis-title\"\n title={titleText}\n >\n <TrellisTitleText>{titleText}</TrellisTitleText>\n </TrellisTitleDiv>\n );\n};\n", "import * as React from 'react';\nimport { useMemo, useRef } from 'react';\nimport { pick } from 'lodash';\nimport styled from 'styled-components';\nimport SizeAwareWrapper from '@splunk/visualizations-shared/SizeAwareWrapper';\nimport { TimeSeriesChart, RangeSelectionProvider } from '@splunk/visualization-canvas';\nimport { toDimension } from '@splunk/visualizations-shared/style';\nimport type { GenericDataSet } from '@splunk/visualization-canvas/types/types';\nimport VizStyleWrapper from './components/VizStyleWrapper';\nimport { ChartingProps } from './Charting';\nimport {\n convert2DArrayToNumbers,\n filterChartDataFromInternalFields,\n getComputedAxisTitles,\n getFieldName,\n getFieldNames,\n getLegend,\n getSeriesOverrides,\n getXScaleConfig,\n getYScaleConfig,\n getY2ScaleConfig,\n ellipsisAxisTitle,\n getAnnotationsForCanvas,\n triangleEventAnnotationRenderer,\n parseAxisValue,\n parseXAxisLineVisibility,\n findRangeIndices,\n shouldEnableSearchZoom,\n} from './chartingUtils';\nimport { useTrellisEnabled } from './hooks/useTrellisEnabled';\nimport { TrellisTitle, TRELLIS_TITLE_HEIGHT } from './components/TrellisTitle';\n\nconst TimeSeriesChartContainer = styled.div<{\n width: number | string;\n height: number | string;\n}>`\n overflow: hidden;\n ${props => toDimension(pick(props, ['width', 'height']))};\n\n canvas {\n position: absolute !important; // This is needed for canvas element export pdf/png to work correctly\n }\n`;\n\n/**\n * Adds trellis information to event payload\n * @param payload - The event payload object to modify\n * @param trellisKey - The current trellis key value (e.g., \"200\", \"404\")\n * @param trellisSplitBy - The field name being split by (e.g., \"status\")\n */\nexport const appendTrellisToPayload = (\n payload: Record<string, unknown>,\n trellisKey?: string,\n trellisSplitBy?: string\n): Record<string, unknown> => {\n const result = { ...payload };\n if (trellisSplitBy) {\n result['trellis.name'] = trellisSplitBy;\n }\n if (trellisKey) {\n result['trellis.value'] = trellisKey;\n }\n return result;\n};\n\n/**\n * Checks if the mouseover payload has changed compared to the previous payload\n * @param currentPayload - The current event payload\n * @param previousPayload - The previous event payload\n * @returns true if the payload has changed, false otherwise\n */\nexport const hasMouseoverPayloadChanged = (\n currentPayload: Record<string, unknown>,\n previousPayload: Record<string, unknown> | null\n): boolean => {\n if (!previousPayload) {\n return true;\n }\n\n // Check if data point index changed - this is the primary indicator of hovering a different point\n if (currentPayload.index !== previousPayload.index) {\n return true;\n }\n\n // Check if seriesIndex changed\n if (currentPayload.seriesIndex !== previousPayload.seriesIndex) {\n return true;\n }\n\n // Check if trellis fields changed (for trellis mode)\n if (currentPayload['trellis.name'] !== previousPayload['trellis.name']) {\n return true;\n }\n if (currentPayload['trellis.value'] !== previousPayload['trellis.value']) {\n return true;\n }\n\n return false;\n};\n\nexport const handleClick = (chartEvent, onClick, trellisKey?: string, trellisSplitBy?: string) => {\n const payload = {\n ...pick(chartEvent, 'value', 'seriesKey'),\n name: chartEvent.seriesKey,\n };\n delete payload.seriesKey;\n\n // Add row context fields in the format: row.${fieldName}.value\n if (chartEvent.rowContext) {\n Object.assign(\n payload,\n Object.keys(chartEvent.rowContext).reduce((acc, fieldName) => {\n acc[`row.${fieldName}.value`] = chartEvent.rowContext[fieldName];\n return acc;\n }, {})\n );\n }\n\n const updatedPayload = appendTrellisToPayload(payload, trellisKey, trellisSplitBy);\n\n if (onClick) {\n onClick({\n type: 'point.click',\n originalEvent: chartEvent,\n payload: updatedPayload,\n });\n }\n};\n\nexport const handleLegendClick = (chartEvent, onClick, trellisKey?: string, trellisSplitBy?: string) => {\n const payload = {\n name: chartEvent,\n };\n\n const updatedPayload = appendTrellisToPayload(payload, trellisKey, trellisSplitBy);\n\n if (onClick) {\n onClick({\n type: 'legend.click',\n originalEvent: chartEvent,\n payload: updatedPayload,\n });\n }\n};\n\nexport const handleRangeSelection = (\n rangeEvent,\n onSelect,\n chartData,\n trellisKey?: string,\n trellisSplitBy?: string\n) => {\n // Handle undefined range (clearing selection)\n if (!rangeEvent) {\n return;\n }\n\n // Find the indices in the data array that correspond to the start and end timestamps\n const xData = chartData?.columns?.[0] || [];\n const { startXIndex, endXIndex } = findRangeIndices(xData, rangeEvent.start, rangeEvent.end);\n\n const payload = {\n startXIndex,\n startXValue: rangeEvent.start,\n endXIndex,\n endXValue: rangeEvent.end,\n };\n\n const updatedPayload = appendTrellisToPayload(payload, trellisKey, trellisSplitBy);\n\n if (onSelect) {\n onSelect({\n type: 'range.selectBeforeZoom',\n originalEvent: rangeEvent,\n payload: updatedPayload,\n });\n }\n};\n\nexport const handleRangeZoom = (\n rangeEvent,\n onSelect,\n chartData,\n trellisKey?: string,\n trellisSplitBy?: string\n) => {\n // Find the indices in the data array that correspond to the start and end timestamps\n const xData = chartData?.columns?.[0] || [];\n const { startXIndex, endXIndex } = findRangeIndices(xData, rangeEvent.start, rangeEvent.end);\n\n const payload = {\n startXIndex,\n startXValue: rangeEvent.start,\n endXIndex,\n endXValue: rangeEvent.end,\n };\n\n const updatedPayload = appendTrellisToPayload(payload, trellisKey, trellisSplitBy);\n\n if (onSelect) {\n onSelect({\n type: 'range.select',\n originalEvent: rangeEvent,\n payload: updatedPayload,\n });\n }\n};\n\nexport const handleCrosshairChange = (\n chartEvent,\n onPointMouseOver,\n onPointMouseOut,\n trellisKey?: string,\n trellisSplitBy?: string,\n lastPayload = null,\n lastOriginalEvent = null\n) => {\n // Handle mouseout when chartEvent is undefined\n if (!chartEvent) {\n if (onPointMouseOut && lastPayload) {\n onPointMouseOut({\n type: 'point.mouseout',\n originalEvent: lastOriginalEvent,\n payload: lastPayload,\n });\n }\n return { payload: null, originalEvent: null };\n }\n\n // Handle mouseover\n const payload = {\n ...pick(chartEvent, 'value', 'seriesKey', 'time', 'index', 'seriesIndex'),\n name: chartEvent.seriesKey,\n };\n delete payload.seriesKey;\n\n // Add row context fields in the format: row.${fieldName}.value\n if (chartEvent.rowContext) {\n Object.assign(\n payload,\n Object.keys(chartEvent.rowContext).reduce((acc, fieldName) => {\n acc[`row.${fieldName}.value`] = chartEvent.rowContext[fieldName];\n return acc;\n }, {})\n );\n }\n\n const updatedPayload = appendTrellisToPayload(payload, trellisKey, trellisSplitBy);\n\n if (onPointMouseOver) {\n onPointMouseOver({\n type: 'point.mouseover',\n originalEvent: chartEvent,\n payload: updatedPayload,\n });\n }\n\n // Return payload and originalEvent for caller to store\n return { payload: updatedPayload, originalEvent: chartEvent };\n};\n\n/**\n * Helper function to parse array options that may be stringified JSON or already arrays\n */\nexport const parseArrayOption = (\n value: string[] | string | undefined | null\n): string[] | undefined | null => {\n if (Array.isArray(value)) {\n return value;\n }\n if (value) {\n return JSON.parse(value);\n }\n return undefined;\n};\n\nconst getAreaOpacityForCanvas = (areaOpacity: number | undefined | null): number | undefined | null =>\n // Preserve legacy visualizations behavior where area opacity is squared to match charting output.\n areaOpacity !== undefined && areaOpacity !== null ? areaOpacity ** 2 : areaOpacity;\n\nconst parseTickIntervalOption = (\n simpleXMLValue?: string | number,\n canvasValue?: number\n): number | undefined => {\n if (simpleXMLValue) return Number(simpleXMLValue);\n if (canvasValue) return Number(canvasValue);\n return undefined;\n};\n\nconst getYAxisTitles = ({\n y2Enabled,\n yFields,\n y2Fields,\n overlayFields,\n yAxisTitleText,\n yAxisTitleVisibility,\n y2AxisTitleText,\n y2AxisTitleVisibility,\n containerHeight,\n}: {\n y2Enabled: boolean;\n yFields: string[];\n y2Fields: string[];\n overlayFields: string[];\n yAxisTitleText?: string;\n yAxisTitleVisibility?: 'show' | 'collapsed';\n y2AxisTitleText?: string;\n y2AxisTitleVisibility?: 'show' | 'collapsed';\n containerHeight: number;\n}) => {\n const yFieldsForTitle = y2Enabled ? yFields.filter(field => !y2Fields.includes(field)) : yFields;\n const fieldsForY2Axis = y2Fields.length > 0 ? y2Fields : overlayFields;\n\n const yAxisTitle = ellipsisAxisTitle(\n getComputedAxisTitles(yAxisTitleText, yFieldsForTitle, yAxisTitleVisibility),\n containerHeight\n );\n const y2AxisTitle = ellipsisAxisTitle(\n getComputedAxisTitles(y2AxisTitleText, fieldsForY2Axis, y2AxisTitleVisibility),\n containerHeight\n );\n\n return { yAxisTitle, y2AxisTitle };\n};\n\nconst TimeSeriesChartWrapper = (props: ChartingProps) => {\n const {\n width,\n height,\n chartData,\n options,\n userLocale,\n annotationX,\n annotationLabel,\n annotationColor,\n legendDisplay,\n markerDisplay,\n onClick,\n onPointMouseOver,\n onPointMouseOut,\n onSelect,\n splitByLayout,\n trellisKey,\n trellisSplitBy,\n backgroundColor,\n defaultFontColor,\n additionalTooltipValues,\n // Extract axis line visibility options from props\n xAxisLineVisibility,\n yAxisLineVisibility,\n y2AxisLineVisibility,\n // Extract showYAxisWithZero directly from props for accelerated render mode\n showYAxisWithZero: showYAxisWithZeroFromProps,\n showY2AxisWithZero: showY2AxisWithZeroFromProps,\n ...otherOptions\n } = props as ChartingProps & {\n showYAxisWithZero?: boolean;\n showY2AxisWithZero?: boolean;\n xAxisLineVisibility?: string;\n yAxisLineVisibility?: string;\n y2AxisLineVisibility?: string;\n };\n const { eventHandlers, xField: xFieldFromProps } = otherOptions;\n const trellisEnabled = useTrellisEnabled(splitByLayout);\n const {\n backgroundColor: bgColorFromOptions,\n seriesColors: seriesColorsStr,\n fieldColors,\n legendLabels: legendLabelsStr,\n legendMode,\n legendTruncation,\n 'axisTitleX.text': xAxisTitleText,\n 'axisTitleY.text': yAxisTitleText,\n 'axisTitleY2.text': y2AxisTitleText,\n 'axisTitleX.visibility': xAxisTitleVisibility,\n 'axisTitleY.visibility': yAxisTitleVisibility,\n 'axisTitleY2.visibility': y2AxisTitleVisibility,\n 'axisLabelsX.majorLabelVisibility': xAxisLabelVisibility,\n 'axisLabelsX.majorLabelStyle.rotation': xAxisLabelRotation,\n 'axisLabelsX.maxLabelParts': xAxisMaxLabelParts,\n 'axisLabelsY.majorLabelVisibility': yAxisLabelVisibility,\n 'axisLabelsY.majorUnit': yAxisMajorUnitFromSimpleXML,\n 'axisLabelsY2.majorLabelVisibility': y2AxisLabelVisibility,\n 'axisLabelsY2.majorUnit': y2AxisMajorUnitFromSimpleXML,\n 'axisY.abbreviation': yAxisAbbreviation,\n 'axisY.scale': yAxisScale,\n 'axisY2.abbreviation': y2AxisAbbreviation,\n 'axisY2.fields': y2FieldsStr,\n 'axisY2.scale': y2AxisScale,\n 'axisY2.enabled': y2Enabled,\n 'axisLabelsY2.integerUnits': y2IntegerUnits,\n 'chart.overlayFields': overlayFieldsStr,\n 'chart.nullValueMode': nullValueMode,\n 'chart.showDataLabels': showDataLabels,\n 'chart.showLines': showLines,\n 'chart.stackMode': stackMode,\n lineWidth,\n lineDashStyle,\n fieldDashStyles: lineDashStylesByFieldStr,\n stepPosition,\n fieldStepPositions: stepPositionsByFieldStr,\n yAxisMin: yAxisMinRaw,\n yAxisMax: yAxisMaxRaw,\n y2AxisMin: y2AxisMinRaw,\n y2AxisMax: y2AxisMaxRaw,\n showXMajorGridLines,\n showYMajorGridLines,\n showY2MajorGridLines,\n showYMinorGridLines,\n showY2MinorGridLines,\n showLineSmoothing,\n xAxisMajorTickVisibility,\n xAxisMajorTickSize,\n yAxisMajorTickVisibility,\n y2AxisMajorTickVisibility,\n yAxisMajorTickSize,\n y2AxisMajorTickSize,\n yAxisMajorTickInterval,\n y2AxisMajorTickInterval,\n yAxisMinorTickVisibility,\n y2AxisMinorTickVisibility,\n yAxisMinorTickSize,\n y2AxisMinorTickSize,\n showYAxisWithZero: showYAxisWithZeroFromOptions,\n showY2AxisWithZero: showY2AxisWithZeroFromOptions,\n // area only props\n areaFillOpacity: areaOpacity,\n chart: chartType,\n } = options;\n\n // Map showDataLabels back to dataValuesDisplay format for canvas mode\n const dataValuesDisplay = showDataLabels === 'none' ? 'off' : showDataLabels;\n\n // Get showYAxisWithZero from top-level props first (accelerated render mode),\n // then fall back to options object (non-accelerated render mode)\n const showYAxisWithZero = showYAxisWithZeroFromProps ?? showYAxisWithZeroFromOptions;\n const showY2AxisWithZero = showY2AxisWithZeroFromProps ?? showY2AxisWithZeroFromOptions;\n\n // Convert visibility to boolean for canvas renderer\n // X-axis ticks default to true (shown) when 'auto' or 'show', false when 'hide'\n const showXMajorTicks = xAxisMajorTickVisibility !== 'hide';\n const showYMajorTicks = yAxisMajorTickVisibility === 'show';\n const showY2MajorTicks = y2AxisMajorTickVisibility === 'show';\n const showYMinorTicks = yAxisMinorTickVisibility === 'show';\n const showY2MinorTicks = y2AxisMinorTickVisibility === 'show';\n // X-axis line defaults to true (shown) for backwards compatibility\n const showXAxisLine = parseXAxisLineVisibility(xAxisLineVisibility);\n const showYAxisLine = yAxisLineVisibility === 'show';\n const showY2AxisLine = y2AxisLineVisibility === 'show';\n\n // Parse axis values - convert strings to numbers\n const yAxisMin = parseAxisValue(yAxisMinRaw);\n const yAxisMax = parseAxisValue(yAxisMaxRaw);\n const y2AxisMin = parseAxisValue(y2AxisMinRaw);\n const y2AxisMax = parseAxisValue(y2AxisMaxRaw);\n\n // Parse tick interval and size values - convert strings to numbers\n // Priority: SimpleXML props (from transformed options) > canvas-specific props\n const yAxisMajorTickIntervalNum = parseTickIntervalOption(\n yAxisMajorUnitFromSimpleXML,\n yAxisMajorTickInterval\n );\n const y2AxisMajorTickIntervalNum = parseTickIntervalOption(\n y2AxisMajorUnitFromSimpleXML,\n y2AxisMajorTickInterval\n );\n const xAxisMajorTickSizeNum = xAxisMajorTickSize != null ? Number(xAxisMajorTickSize) : undefined;\n const yAxisMajorTickSizeNum = yAxisMajorTickSize != null ? Number(yAxisMajorTickSize) : undefined;\n const y2AxisMajorTickSizeNum = y2AxisMajorTickSize != null ? Number(y2AxisMajorTickSize) : undefined;\n const yAxisMinorTickSizeNum = yAxisMinorTickSize != null ? Number(yAxisMinorTickSize) : undefined;\n const y2AxisMinorTickSizeNum = y2AxisMinorTickSize != null ? Number(y2AxisMinorTickSize) : undefined;\n // Preserve legacy visualizations behavior where area opacity is squared to match charting output.\n const areaOpacityForCanvas = getAreaOpacityForCanvas(areaOpacity);\n const seriesColors = seriesColorsStr ? JSON.parse(seriesColorsStr) : undefined;\n const seriesColorsByField = fieldColors ? JSON.parse(fieldColors) : undefined;\n const lineDashStylesByField = lineDashStylesByFieldStr ? JSON.parse(lineDashStylesByFieldStr) : undefined;\n const stepPositionsByField = stepPositionsByFieldStr ? JSON.parse(stepPositionsByFieldStr) : undefined;\n const legendLabels = parseArrayOption(legendLabelsStr);\n const bgColor = backgroundColor || bgColorFromOptions;\n const [containerWidth, setContainerWidth] = React.useState(Number(props.width));\n const [containerHeight, setContainerHeight] = React.useState(Number(props.height));\n const cachedHandleResize = React.useCallback((w, h) => {\n setContainerWidth(w);\n setContainerHeight(h);\n }, []);\n const filteredChartData = filterChartDataFromInternalFields({\n fields: chartData.fields,\n columns: chartData.seriesList,\n });\n\n const xField = getFieldName(filteredChartData.fields[0]);\n const yFields = getFieldNames(\n filteredChartData.fields.length > 1 ? filteredChartData.fields.slice(1) : []\n );\n const y2Fields = useMemo(\n () => (y2FieldsStr ? y2FieldsStr.split(',').map(f => f.trim()) : []),\n [y2FieldsStr]\n );\n const overlayFields = useMemo(\n () => (overlayFieldsStr ? overlayFieldsStr.split(',').map(f => f.trim()) : []),\n [overlayFieldsStr]\n );\n\n let xAxisTitle = getComputedAxisTitles(xAxisTitleText, [xField], xAxisTitleVisibility);\n xAxisTitle = ellipsisAxisTitle(xAxisTitle, containerWidth);\n const { yAxisTitle, y2AxisTitle } = getYAxisTitles({\n y2Enabled,\n yFields,\n y2Fields,\n overlayFields,\n yAxisTitleText,\n yAxisTitleVisibility,\n y2AxisTitleText,\n y2AxisTitleVisibility,\n containerHeight,\n });\n\n const xScaleConfig = useMemo(\n () => getXScaleConfig(xAxisTitle, xAxisLabelVisibility, xAxisLabelRotation),\n [xAxisTitle, xAxisLabelVisibility, xAxisLabelRotation]\n );\n const isStacked100 = stackMode === 'stacked100';\n const yScaleConfig = useMemo(\n () => {\n const config = getYScaleConfig(\n yAxisTitle,\n yAxisAbbreviation,\n yAxisScale,\n yAxisLabelVisibility,\n yAxisMin,\n yAxisMax\n );\n // For stacked100, override tick formatter to show percentage labels (0-100%)\n // uPlot stores stacked100 values as 0-1 fractions after processPercentStacking\n if (isStacked100) {\n config.y.tickFmt = (v): string => `${Math.round(v * 100)}%`;\n config.y.range = () => [0, 1];\n }\n return config;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [yAxisTitle, yAxisAbbreviation, yAxisScale, yAxisLabelVisibility, yAxisMin, yAxisMax, isStacked100]\n );\n const y2ScaleConfig = useMemo(() => {\n if (y2Enabled) {\n return getY2ScaleConfig(\n y2AxisTitle,\n y2AxisAbbreviation,\n y2AxisScale,\n y2IntegerUnits,\n y2AxisLabelVisibility,\n y2AxisMin,\n y2AxisMax\n );\n }\n return {};\n }, [\n y2Enabled,\n y2AxisTitle,\n y2AxisAbbreviation,\n y2AxisScale,\n y2IntegerUnits,\n y2AxisLabelVisibility,\n y2AxisMin,\n y2AxisMax,\n ]);\n const uplotContainerElement = useRef(null);\n\n const seriesDataFormatted = [\n filteredChartData.columns[0],\n ...convert2DArrayToNumbers(filteredChartData.columns.slice(1)),\n ];\n chartData.fields = filteredChartData.fields;\n chartData.columns = seriesDataFormatted;\n\n // Map SimpleXML stackMode value ('default' | 'stacked' | 'stacked100') to getSeriesOverrides param\n const normalizedStackMode = stackMode === 'stacked' || stackMode === 'stacked100' ? stackMode : 'auto';\n\n // Memoize seriesOverrides to prevent unnecessary recreations\n const seriesOverrides = useMemo(\n () =>\n getSeriesOverrides({\n yfields: yFields,\n y2fields: y2Fields,\n lineWidth,\n overlayFields,\n y2Enabled,\n nullValueMode,\n markerDisplay,\n lineDashStyle,\n lineDashStylesByField,\n stepPosition,\n stepPositionsByField,\n type: chartType,\n stackMode: normalizedStackMode,\n showLines,\n }),\n [\n yFields,\n y2Fields,\n lineWidth,\n overlayFields,\n y2Enabled,\n nullValueMode,\n markerDisplay,\n lineDashStyle,\n lineDashStylesByField,\n stepPosition,\n stepPositionsByField,\n chartType,\n normalizedStackMode,\n showLines,\n ]\n );\n\n // Memoize annotations to prevent unnecessary recreations\n const chartingEventAnnotations = useMemo(\n () =>\n getAnnotationsForCanvas({\n annotationX,\n annotationColor,\n annotationLabel,\n }),\n [annotationX, annotationColor, annotationLabel]\n );\n\n // Memoize scaleConfig to prevent unnecessary recreations\n const scaleConfig = useMemo(\n () => ({ ...xScaleConfig, ...yScaleConfig, ...y2ScaleConfig }),\n [xScaleConfig, yScaleConfig, y2ScaleConfig]\n );\n\n // Memoize legend configuration\n // In seriesCompare mode, force the legend to the right side so that the legend's\n // fixed width (needed to prevent jitter when hover values appear/disappear) doesn't\n // affect layouts that would otherwise place it on the left.\n const isSeriesCompare = legendMode === 'seriesCompare';\n const legend = useMemo(\n () =>\n getLegend({\n legendDisplay: isSeriesCompare && legendDisplay !== 'off' ? 'right' : legendDisplay,\n isSeriesCompare,\n legendTruncation,\n }),\n [legendDisplay, isSeriesCompare, legendTruncation]\n );\n\n // Memoize click handlers to avoid recreating them on every render\n const handleChartClick = React.useCallback(\n event => {\n // Only invoke if onClick is defined to avoid unnecessary work\n if (onClick) {\n handleClick(event, onClick, trellisKey, trellisSplitBy);\n }\n },\n [onClick, trellisKey, trellisSplitBy]\n );\n\n const handleChartLegendClick = React.useCallback(\n event => {\n // Only invoke if onClick is defined to avoid unnecessary work\n if (onClick) {\n handleLegendClick(event, onClick, trellisKey, trellisSplitBy);\n }\n },\n [onClick, trellisKey, trellisSplitBy]\n );\n\n const handleChartRangeSelection = React.useCallback(\n range => {\n // Only invoke if onSelect is defined to avoid unnecessary work\n if (onSelect) {\n handleRangeSelection(range, onSelect, chartData, trellisKey, trellisSplitBy);\n }\n // Always allow range selection UI to appear, even if onSelect is undefined\n },\n [onSelect, chartData, trellisKey, trellisSplitBy]\n );\n\n const handleChartRangeZoom = React.useCallback(\n range => {\n // Only invoke if onSelect is defined to avoid unnecessary work\n if (onSelect) {\n handleRangeZoom(range, onSelect, chartData, trellisKey, trellisSplitBy);\n }\n },\n [onSelect, chartData, trellisKey, trellisSplitBy]\n );\n\n // Determine if search zoom should be enabled based on eventHandlers and xField\n // Use xFieldFromProps if available, otherwise fall back to computed xField from chartData\n const xFieldToUse = xFieldFromProps || xField;\n const enableSearchZoom = React.useMemo(\n () => shouldEnableSearchZoom(eventHandlers, xFieldToUse),\n [eventHandlers, xFieldToUse]\n );\n\n // Store the last payload and originalEvent to return on mouseout\n const lastPayloadRef = React.useRef<Record<string, any> | null>(null);\n const lastOriginalEventRef = React.useRef<any>(null);\n // Store the previous mouseover payload to check for changes\n const previousMouseoverPayloadRef = React.useRef<Record<string, unknown> | null>(null);\n // Store additionalTooltipValues in a ref to avoid chart remounts when it changes\n // The chart reads from this ref, so changes update the tooltip without remounting\n const additionalTooltipValuesRef = React.useRef(additionalTooltipValues);\n React.useEffect(() => {\n additionalTooltipValuesRef.current = additionalTooltipValues;\n }, [additionalTooltipValues]);\n\n const handleCrosshairMouseout = React.useCallback(() => {\n if (onPointMouseOut && lastPayloadRef.current) {\n onPointMouseOut({\n type: 'point.mouseout',\n originalEvent: lastOriginalEventRef.current,\n payload: lastPayloadRef.current,\n });\n }\n previousMouseoverPayloadRef.current = null;\n }, [onPointMouseOut]);\n\n const handleChartCrosshairChange = React.useCallback(\n event => {\n // Only invoke if onPointMouseOver or onPointMouseOut is defined to avoid unnecessary work\n if (!onPointMouseOver && !onPointMouseOut) {\n return;\n }\n\n // Handle mouseout when event is undefined\n if (!event) {\n handleCrosshairMouseout();\n return;\n }\n\n // Handle mouseover\n const payload = {\n ...pick(event, 'value', 'seriesKey', 'time', 'index', 'seriesIndex'),\n name: event.seriesKey,\n };\n delete payload.seriesKey;\n\n // Add row context fields in the format: row.${fieldName}.value\n if (event.rowContext) {\n Object.assign(\n payload,\n Object.keys(event.rowContext).reduce((acc, fieldName) => {\n acc[`row.${fieldName}.value`] = event.rowContext[fieldName];\n return acc;\n }, {})\n );\n }\n\n const updatedPayload = appendTrellisToPayload(payload, trellisKey, trellisSplitBy);\n\n // Check if the payload has actually changed to avoid emitting duplicate events\n if (!hasMouseoverPayloadChanged(updatedPayload, previousMouseoverPayloadRef.current)) {\n return;\n }\n\n // Store payload and originalEvent for mouseout\n lastPayloadRef.current = updatedPayload;\n lastOriginalEventRef.current = event;\n // Store current payload for next comparison\n previousMouseoverPayloadRef.current = { ...updatedPayload };\n\n if (onPointMouseOver) {\n onPointMouseOver({\n type: 'point.mouseover',\n originalEvent: event,\n payload: updatedPayload,\n });\n }\n },\n [onPointMouseOver, onPointMouseOut, trellisKey, trellisSplitBy, handleCrosshairMouseout]\n );\n\n // Create a key to reset RangeSelectionProvider when data changes\n const dataKey = `${chartData.columns[0]?.[0]}-${chartData.columns[0]?.[chartData.columns[0].length - 1]}-${chartData.columns[0]?.length}`;\n\n const memoizedChart = useMemo(() => {\n // Always pass zoom handler when onSelect exists, serverSideZoom controls behavior\n const computedOnRangeZoom = onSelect ? handleChartRangeZoom : undefined;\n\n return (\n <RangeSelectionProvider key={dataKey}>\n <TimeSeriesChart\n data={chartData as GenericDataSet}\n width={containerWidth}\n height={containerHeight}\n seriesColors={seriesColors}\n seriesColorsByField={seriesColorsByField}\n seriesConfig={seriesOverrides}\n legend={legend}\n legendLabels={legendLabels}\n legendTruncation={legendTruncation}\n isSeriesCompare={legendMode === 'seriesCompare'}\n maxSeriesFocus={legendMode === 'seriesCompare' ? 0 : undefined}\n scaleConfig={scaleConfig}\n timestampFormat=\"expanded\"\n onCrosshairClick={onClick ? handleChartClick : undefined}\n onCrosshairChange={\n onPointMouseOver || onPointMouseOut ? handleChartCrosshairChange : undefined\n }\n onSeriesClick={onClick ? handleChartLegendClick : undefined}\n onRangeSelection={handleChartRangeSelection}\n onRangeZoom={computedOnRangeZoom}\n serverSideZoom={enableSearchZoom}\n userLocale={userLocale}\n events={chartingEventAnnotations}\n eventsConfig={{ renderer: triangleEventAnnotationRenderer }}\n additionalTooltipValuesRef={additionalTooltipValuesRef}\n showXMajorGridLines={showXMajorGridLines}\n showYMajorGridLines={showYMajorGridLines}\n showY2MajorGridLines={showY2MajorGridLines}\n showYMinorGridLines={showYMinorGridLines}\n showY2MinorGridLines={showY2MinorGridLines}\n showLineSmoothing={showLineSmoothing}\n dataValuesDisplay={dataValuesDisplay}\n showXMajorTicks={showXMajorTicks}\n xAxisMajorTickSize={xAxisMajorTickSizeNum}\n showYMajorTicks={showYMajorTicks}\n showY2MajorTicks={showY2MajorTicks}\n yAxisMajorTickSize={yAxisMajorTickSizeNum}\n y2AxisMajorTickSize={y2AxisMajorTickSizeNum}\n yAxisMajorTickInterval={yAxisMajorTickIntervalNum}\n y2AxisMajorTickInterval={y2AxisMajorTickIntervalNum}\n showYMinorTicks={showYMinorTicks}\n showY2MinorTicks={showY2MinorTicks}\n yAxisMinorTickSize={yAxisMinorTickSizeNum}\n y2AxisMinorTickSize={y2AxisMinorTickSizeNum}\n showYAxisWithZero={showYAxisWithZero}\n showY2AxisWithZero={showY2AxisWithZero}\n showXAxisLine={showXAxisLine}\n showYAxisLine={showYAxisLine}\n showY2AxisLine={showY2AxisLine}\n xAxisMaxLabelParts={xAxisMaxLabelParts}\n areaOpacity={areaOpacityForCanvas}\n />\n </RangeSelectionProvider>\n );\n // Note: additionalTooltipValues passed via ref to avoid chart remount when switching stories.\n // The ref is updated via useEffect, so tooltip gets latest values without remounting chart.\n }, [\n onSelect,\n handleChartRangeZoom,\n dataKey,\n chartData,\n containerWidth,\n containerHeight,\n seriesColors,\n seriesColorsByField,\n seriesOverrides,\n legend,\n legendLabels,\n legendTruncation,\n scaleConfig,\n onClick,\n handleChartClick,\n onPointMouseOver,\n onPointMouseOut,\n handleChartCrosshairChange,\n handleChartLegendClick,\n handleChartRangeSelection,\n enableSearchZoom,\n userLocale,\n chartingEventAnnotations,\n showXMajorGridLines,\n showYMajorGridLines,\n showY2MajorGridLines,\n showYMinorGridLines,\n showY2MinorGridLines,\n showLineSmoothing,\n dataValuesDisplay,\n showXMajorTicks,\n xAxisMajorTickSizeNum,\n showYMajorTicks,\n showY2MajorTicks,\n yAxisMajorTickSizeNum,\n y2AxisMajorTickSizeNum,\n yAxisMajorTickIntervalNum,\n y2AxisMajorTickIntervalNum,\n showYMinorTicks,\n showY2MinorTicks,\n yAxisMinorTickSizeNum,\n y2AxisMinorTickSizeNum,\n showYAxisWithZero,\n showY2AxisWithZero,\n showXAxisLine,\n showYAxisLine,\n showY2AxisLine,\n legendMode,\n xAxisMaxLabelParts,\n areaOpacityForCanvas,\n ]);\n\n const memoizedVisualization = useMemo(() => {\n return <VizStyleWrapper backgroundColor={bgColor}>{memoizedChart}</VizStyleWrapper>;\n }, [bgColor, memoizedChart]);\n\n return (\n <>\n {trellisEnabled && (\n <TrellisTitle\n trellisKey={trellisKey}\n backgroundColor={bgColor}\n fontColor={defaultFontColor}\n />\n )}\n <TimeSeriesChartContainer\n height={trellisEnabled ? Number(height) - TRELLIS_TITLE_HEIGHT : height}\n width={width}\n ref={uplotContainerElement}\n data-test=\"timeseries-chart-wrapper\"\n >\n <SizeAwareWrapper width={width} height={height} onResize={cachedHandleResize} />\n {memoizedVisualization}\n </TimeSeriesChartContainer>\n </>\n );\n};\n\nexport default TimeSeriesChartWrapper;\n", "import * as React from 'react';\nimport { camelCase, has, get, defaultsDeep, noop } from 'lodash';\nimport getSettingsFromThemedProps from '@splunk/themes/getSettingsFromThemedProps';\nimport { Options as Opts } from '@splunk/visualization-encoding/Options';\nimport { withSanitizedProps } from '@splunk/visualizations-shared/SanitizeProps';\nimport type { TimezoneContextInterface } from '@splunk/visualization-context/TimezoneContext';\nimport TimezoneContext from '@splunk/visualization-context/TimezoneContext';\nimport moment from '@splunk/moment';\nimport FeatureFlagContext from '@splunk/visualization-context/FeatureFlagContext';\nimport { withTheme } from 'styled-components';\nimport { deepMergeWithArrayPrimitiveOverrides } from '@splunk/visualizations-shared/hocUtils';\nimport { pickFieldFromJSONSchema } from '@splunk/visualizations-shared/JSONSchemaUtils';\nimport AsyncDynamicOptionsEvaluator, {\n AsyncDynamicOptionsEvaluatorParams,\n} from '@splunk/async-dynamic-options-evaluator';\nimport { createGUID } from '@splunk/ui-utils/id';\nimport type { Frames } from '@splunk/visualization-encoding/EncodingExecutor';\nimport SplunkVisualization from './SplunkVisualization';\nimport type { DashboardVizProps, DataSource, VizConfig, VizProps } from './interfaces';\nimport { VizBehavior } from './interfaces/VizBehavior';\nimport { useSortingParams } from './hooks/useSorting';\nimport { usePaginationParams } from './hooks/usePagination';\nimport { useDeepMemo } from './hooks/useDeepMemo';\nimport MissingPropsMessage, { missingKeys } from './components/MissingPropsMessage';\nimport withEditModeCover from './hocs/withEditModeCover';\nimport withPlaceholder from './hocs/withPlaceholder';\nimport { ChartingProps } from './Charting';\nimport useDownsampleDataSources from './hooks/useDownsampleDataSources';\nimport { isDownsamplingEnabledForViz } from './utils/dataUtils';\nimport { getFeatureFlag } from '../common/utils/featureFlagUtils';\nimport { turnOffLegendDisplayWhenTrellisIsOn } from '../common/utils/trellisUtils';\nimport TimeSeriesChartWrapper from './TimeSeriesChartWrapper';\nimport { isTimeSeriesCanvasRenderSupported } from './chartingUtils';\n\n// Create the sanitized version once, outside the component to prevent remounting\nconst SanitizedTimeSeriesChartWrapper = withSanitizedProps(TimeSeriesChartWrapper);\n\ntype FeatureFlagContextValue = Record<string, boolean | undefined> | null;\n\ntype HOC = React.ComponentType<DashboardVizProps>;\nexport interface DashboardVizOpts {\n ReactViz: React.ComponentType<ChartingProps | VizProps>; // we will wrap this in DashboardViz (see const DashboardViz = ...)\n vizConfig: VizConfig;\n computeVizProps?: (props) => any;\n computeVizPropsBeforeEval?: (props) => any;\n computeDataFrames?: (args: {\n dataSources: { [key: string]: DataSource };\n options: Record<string, unknown>;\n }) => Partial<Frames>;\n disableEditModeCover?: boolean;\n useIconPlaceholder?: (\n dataSources: { [name: string]: DataSource },\n loading: boolean,\n options: Record<string, unknown>\n ) => boolean;\n}\n\nconst buildEventCallbackProps = (\n supportedEvents,\n evaluatedOptionsToUse,\n onEventTrigger\n): Record<string, unknown> => {\n const result = {};\n Object.keys(supportedEvents).forEach((eventName): void => {\n const { parentKeys, payloadKeys } = supportedEvents[eventName];\n const eventCallbackPropName = camelCase(`on.${eventName}`);\n\n let payload = {};\n if (Array.isArray(payloadKeys) && payloadKeys.length) {\n payloadKeys.forEach(p => {\n payload[p] = evaluatedOptionsToUse[p];\n });\n }\n\n result[eventCallbackPropName] = (ev): Record<string, unknown> => {\n if (ev?.payload) {\n payload = { ...ev.payload };\n }\n return onEventTrigger({\n originalEvent: ev,\n payload,\n type: eventName,\n });\n };\n\n if (parentKeys) {\n for (let i = parentKeys.length - 1; i >= 0; i -= 1) {\n const newObject = {};\n newObject[parentKeys[i]] = result[eventCallbackPropName];\n result[eventCallbackPropName] = newObject;\n }\n }\n });\n return result;\n};\n\n/**\n * hoc that wraps a pure react visualization in a Dashboard visualization\n * @param {DashboardVizOpts} opts\n * @returns {HOC}\n */\nconst withDashboardViz = (opts: DashboardVizOpts): HOC => {\n const {\n ReactViz,\n vizConfig,\n computeVizProps = () => {},\n computeVizPropsBeforeEval = () => {},\n computeDataFrames,\n disableEditModeCover,\n useIconPlaceholder,\n } = opts;\n\n // sanitizing props before sending them to reactviz.\n const SanitizedReactViz = withSanitizedProps(ReactViz); // Default assigned to ReactViz\n const defaultOptions = pickFieldFromJSONSchema(vizConfig.optionsSchema, 'default');\n\n const DashboardViz = (props: DashboardVizProps): React.ReactElement<DashboardVizProps> => {\n const {\n mode = 'view',\n hasEventHandlers,\n dataSources, // type of { [key: string]: DataSource }\n options = {},\n context = {},\n width,\n height,\n onComputedProps = noop,\n onEventTrigger = SplunkVisualization.defaults.onEventTrigger,\n theme,\n onRequestParamsChange = noop,\n } = props;\n const localeContext = React.useContext<TimezoneContextInterface>(TimezoneContext);\n if (localeContext.serializedTimezone) {\n /*\n @splunk/moment currently does not allow us to customize the timezone on a per visualization basis.\n This ensures that if a timezone was provided via TimezoneContext @splunk/moment time formatting\n will use it.\n */\n if (!moment.getDefaultSplunkTimezone()) {\n moment.setDefaultSplunkTimezone(localeContext.serializedTimezone);\n }\n }\n\n const themeFunc = themeVar => vizConfig.themes[themeVar]?.(props);\n const {\n family: currentThemeFamily,\n colorScheme: currentThemeColorScheme,\n density: currentThemeDensity,\n } = getSettingsFromThemedProps({ theme });\n let evaluatedOptions: Record<string, unknown> = {}; // evaluatedOptions need to be initialized as an empty object\n const [evaluatedOptionsAsync, setEvaluatedOptionsAsync] = React.useState({}); // evaluatedOptions need to be initialized as an empty object\n const featureFlagContext = React.useContext<FeatureFlagContextValue>(FeatureFlagContext);\n\n const [visualizationID] = React.useState(`${vizConfig.name} - ${createGUID()}`);\n\n const [dataSourcesInState, setDataSourcesInState] = React.useState({});\n const [dataFramesInState, setDataFramesInState] = React.useState<Frames | undefined>();\n\n const [useAsyncEvaluatedOptions, setUseAsyncEvaluatedOptions] = React.useState(\n Boolean(getFeatureFlag(featureFlagContext, 'visualizations_useWebWorkersForDSL'))\n );\n const isDownsamplingEnabledByFeatureFlag = Boolean(\n featureFlagContext?.visualizations_enableDownsampling\n );\n const isTrellisFeatureFlagOn = Boolean(featureFlagContext?.visualizations_enableTrellis);\n const isTrellisOn =\n isTrellisFeatureFlagOn &&\n vizConfig?.supports?.includes(VizBehavior.TRELLIS) &&\n options?.splitByLayout === VizBehavior.TRELLIS;\n\n const isAcceleratedRenderFeatureFlagOn = Boolean(\n featureFlagContext?.visualizations_enableAcceleratedRender\n );\n const isAcceleratedRenderOn =\n isAcceleratedRenderFeatureFlagOn &&\n isTimeSeriesCanvasRenderSupported(vizConfig.key) &&\n options?.acceleratedRender === true;\n const isMounted = React.useRef(true);\n const optionsToEvaluate = React.useMemo(() => {\n const legendDisplay = turnOffLegendDisplayWhenTrellisIsOn(isTrellisOn, options);\n // computeVizPropsBeforeEval will run before DSL gets evaluated\n const computedOptions = computeVizPropsBeforeEval(options) ?? {};\n return {\n context: defaultsDeep({}, context, vizConfig.defaultContext),\n options: deepMergeWithArrayPrimitiveOverrides(\n {},\n legendDisplay,\n computedOptions,\n options,\n defaultOptions\n ),\n };\n }, [isTrellisOn, options, context]);\n\n const [threshold, setThreshold] = React.useState(Number(width));\n const onDownsamplingThresholdChange = React.useCallback((newThreshold: number) => {\n setThreshold(newThreshold);\n }, []);\n const isDownsamplingEnabled = React.useMemo(() => {\n return isDownsamplingEnabledByFeatureFlag && isDownsamplingEnabledForViz({ vizConfig });\n }, [isDownsamplingEnabledByFeatureFlag]);\n\n const downsamplingProps = React.useMemo(() => {\n if (!isDownsamplingEnabled) {\n return {};\n }\n return {\n onDownsamplingThresholdChange,\n originalDataSources: dataSources,\n };\n }, [dataSources, isDownsamplingEnabled, onDownsamplingThresholdChange]);\n const downsampledDataSources = useDownsampleDataSources({\n options: optionsToEvaluate.options,\n context: optionsToEvaluate.context,\n dataSources,\n threshold,\n isDownsamplingEnabled,\n });\n\n evaluatedOptions = useDeepMemo(() => {\n try {\n if (useAsyncEvaluatedOptions) {\n const asyncDynamicOptionsEvaluatorParams: AsyncDynamicOptionsEvaluatorParams = {\n visualizationID,\n props,\n options: optionsToEvaluate,\n dataSources: downsampledDataSources,\n theme: vizConfig.themes,\n bypassCloneDeepOptionScope: Boolean(\n getFeatureFlag(featureFlagContext, 'visualizations_bypassCloneDeepOptionScope')\n ),\n lazyLoadingDataFrame: Boolean(\n getFeatureFlag(featureFlagContext, 'visualizations_lazyLoadingDataFrame')\n ),\n };\n AsyncDynamicOptionsEvaluator.evaluate(asyncDynamicOptionsEvaluatorParams)\n .then(results => {\n setEvaluatedOptionsAsync(results.results);\n })\n .catch(() => {\n if (isMounted.current) {\n setUseAsyncEvaluatedOptions(false);\n }\n });\n } else {\n let dataFrames: Frames | undefined = dataFramesInState;\n if (downsampledDataSources !== dataSourcesInState) {\n setDataSourcesInState(downsampledDataSources);\n dataFrames = Opts.dataFrameFromDataSource(\n downsampledDataSources,\n getFeatureFlag(featureFlagContext, 'visualizations_lazyLoadingDataFrame')\n );\n setDataFramesInState(dataFrames);\n }\n // Merge derived frames when provided\n let mergedFrames = dataFrames;\n if (computeDataFrames && dataFrames) {\n const derivedFrames = computeDataFrames({\n dataSources: downsampledDataSources,\n options: optionsToEvaluate.options,\n });\n mergedFrames = { ...dataFrames, ...derivedFrames };\n }\n const result = Opts.evaluate(\n optionsToEvaluate,\n downsampledDataSources,\n themeFunc,\n mergedFrames,\n getFeatureFlag(featureFlagContext, 'visualizations_bypassCloneDeepOptionScope')\n );\n return result;\n }\n } catch (e) {\n if (e instanceof Error) {\n // eslint-disable-next-line no-console\n console.error(`unexpected error evaluating options: ${e.message}`);\n }\n return {};\n }\n return {};\n }, [\n currentThemeFamily,\n currentThemeColorScheme,\n currentThemeDensity,\n optionsToEvaluate,\n downsampledDataSources,\n localeContext.serializedTimezone,\n useAsyncEvaluatedOptions,\n ]);\n\n const evaluatedOptionsToUse = !useAsyncEvaluatedOptions ? evaluatedOptions : evaluatedOptionsAsync;\n\n /**\n * PAGE_AND_SORT behavior\n *\n * Some visualizations, like table, requires metadata about the datasource,\n * like total number of results, current count, offset, and sort, for rendering\n * paginator and sorting direction. In this approach, the visualization\n * allow users to set 'paginateDataSourceKey' to select which datasource\n * should the visualization extract the metadata from. It defaults to 'primary' datasource.\n * The visualization config should set the PAGE_AND_SORT behavior to receive\n * 'requestParams', 'meta' and onRequestParams callback as props.\n *\n * In future, we could automatically detect which all datasources are being used\n * and bind those magically to pagination/sorting behavior.\n */\n let dataSourceMetadata = {};\n const OptionKey = 'paginateDataSourceKey';\n const optsKey = has(evaluatedOptionsToUse, OptionKey) && evaluatedOptionsToUse[OptionKey];\n const paginateDataSourceKey = typeof optsKey === 'string' ? optsKey : 'primary';\n\n const requestParams = get(dataSources, [paginateDataSourceKey, 'requestParams'], {});\n const meta = get(dataSources, [paginateDataSourceKey, 'meta'], {});\n const handleRequestParamsChange = (payload: Record<string, unknown>): void =>\n onRequestParamsChange(paginateDataSourceKey, payload);\n\n const sortParams = useSortingParams({\n requestParams,\n meta,\n onRequestParamsChange: handleRequestParamsChange,\n });\n\n const paginatorParams = usePaginationParams({\n requestParams,\n meta,\n onRequestParamsChange: handleRequestParamsChange,\n });\n\n dataSourceMetadata = {\n sortParams,\n paginatorParams,\n };\n\n if (\n vizConfig.supports.indexOf(VizBehavior.PAGE_AND_SORT) === -1 &&\n !has(dataSources, paginateDataSourceKey)\n ) {\n dataSourceMetadata = {};\n }\n\n // trellis specific backgroundColor update for onComputedProps\n // if trellis is enabled following these three criteria - 1) trellis feature flag is enabled 2) vizConfig supports array has 'trellis' 3) option 'splitByLayout' is set to 'trellis\n // onComputedProps api should return back trellisBackgroundColor value for backgroundColor option to support coloring of sibling panels (for eg:- title/ description on UDF side)\n const clonedEvaluatedOptions: Record<string, unknown> = { ...evaluatedOptionsToUse };\n if (isTrellisOn) {\n clonedEvaluatedOptions.backgroundColor = clonedEvaluatedOptions?.trellisBackgroundColor;\n }\n // useEffect hook needs to be initialized before any early returns\n // this is in accordance with the order of hook calls being the same on each render https://reactjs.org/docs/hooks-rules.html#explanation\n React.useEffect((): void => {\n onComputedProps(clonedEvaluatedOptions);\n });\n\n React.useEffect((): (() => void) => {\n return () => {\n if (useAsyncEvaluatedOptions) {\n isMounted.current = false;\n AsyncDynamicOptionsEvaluator.reset(visualizationID);\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // present warning message if any required props are missing\n const { requiredProps = [], supports } = vizConfig;\n const missing = missingKeys(requiredProps, evaluatedOptionsToUse);\n if (\n missing.length > 0 &&\n supports.includes(VizBehavior.PLACEHOLDER) &&\n vizConfig.key !== 'splunk.singlevalue' // For SV missing props msg is not displayed if required props majorValue is missing, instead this will be handled from the component, instead handled within component\n ) {\n return (\n <MissingPropsMessage\n data-test=\"missing-props-message\"\n width={width}\n height={height}\n missingProps={missing}\n backgroundColor={themeFunc('defaultBackgroundColor')}\n />\n );\n }\n\n // events\n const eventCallbackProps =\n hasEventHandlers && mode === 'view' && vizConfig.supports.includes(VizBehavior.EVENTS)\n ? buildEventCallbackProps(vizConfig.events, evaluatedOptionsToUse, onEventTrigger)\n : {};\n\n // compute pure viz props which are not from options\n const computedVizProps = computeVizProps({\n ...props,\n ...evaluatedOptionsToUse,\n // Align option transformation with the actual renderer selected below.\n // This prevents canvas-only option preservation from leaking into Highcharts mode.\n isAcceleratedRenderOn,\n ...eventCallbackProps,\n themeFunc,\n });\n\n // if were using webworkers and this is the first render we dont want to show a viz with missing data so we return null\n if (useAsyncEvaluatedOptions && Object.keys(evaluatedOptionsToUse).length === 0) {\n return null;\n }\n\n // if acceleratedRender mode is on, then use canvas viz\n const SanitizedViz = isAcceleratedRenderOn ? SanitizedTimeSeriesChartWrapper : SanitizedReactViz;\n\n return (\n <SanitizedViz\n {...SplunkVisualization.defaults}\n mode={mode}\n width={width || SplunkVisualization.defaults.width}\n height={height || SplunkVisualization.defaults.height}\n userLocale={localeContext}\n {...downsamplingProps}\n {...evaluatedOptionsToUse}\n {...computedVizProps}\n {...eventCallbackProps}\n {...dataSourceMetadata}\n />\n );\n };\n\n DashboardViz.propTypes = {\n ...SplunkVisualization.propTypes,\n ...ReactViz.propTypes,\n };\n\n DashboardViz.defaultProps = {\n ...ReactViz.defaultProps, // we still need ReactViz.defaultProps for the visualizations that still have them\n onEventTrigger: SplunkVisualization.defaults.onEventTrigger,\n };\n\n // attach viz config\n DashboardViz.config = vizConfig;\n\n return withTheme(\n withPlaceholder(withEditModeCover(DashboardViz, disableEditModeCover), useIconPlaceholder)\n );\n};\n\nexport default withDashboardViz;\n", "\nimport * as defaultImport from \"@splunk/dashboard-context\";\nexport * from \"@splunk/dashboard-context\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"slate-react\";\nexport * from \"slate-react\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "/**\n * Module-level tracker for the currently active (focused) PureRichText instance.\n *\n * Kept in a separate file so both PureRichText.tsx and EditorPanel.tsx can import\n * from it without creating a circular dependency.\n */\n\nimport { Editor } from 'slate';\nimport { ReactEditor } from 'slate-react';\n\nlet activeRichTextId: string | null = null;\nlet activeEditableElement: HTMLDivElement | null = null;\nlet activeSlateEditor: Editor | null = null;\nconst activeRichTextListeners = new Set<() => void>();\n\nexport function registerActiveRichText(\n id: string,\n editable: HTMLDivElement | null,\n editor: Editor | null\n): void {\n activeRichTextId = id;\n activeEditableElement = editable;\n activeSlateEditor = editor;\n activeRichTextListeners.forEach(fn => fn());\n}\n\nexport function clearActiveRichText(id: string): void {\n if (activeRichTextId === id) {\n activeRichTextId = null;\n activeEditableElement = null;\n activeSlateEditor = null;\n activeRichTextListeners.forEach(fn => fn());\n }\n}\n\nexport function getActiveRichTextId(): string | null {\n return activeRichTextId;\n}\n\nexport function getActiveSlateEditor(): Editor | null {\n return activeSlateEditor;\n}\n\n/**\n * Restore focus and caret on the active Slate editor.\n * Uses ReactEditor.focus() which properly restores both DOM focus and the\n * Slate selection into window.getSelection(), making the caret visible again.\n */\nexport function focusActiveEditable(): void {\n if (activeSlateEditor) {\n try {\n ReactEditor.focus(activeSlateEditor as ReactEditor);\n } catch {\n activeEditableElement?.focus();\n }\n } else {\n activeEditableElement?.focus();\n }\n}\n\nexport function subscribeActiveRichText(callback: () => void): () => void {\n activeRichTextListeners.add(callback);\n return () => activeRichTextListeners.delete(callback);\n}\n\n// Flag to suppress blur-deactivation while a popover (link editor, etc.)\n// is open. The popover is portaled to the document body and is not inside the\n// config panel or viz-item, so handleBlur cannot detect it via DOM containment.\nlet suppressBlurDeactivation = false;\nexport function setSuppressBlurDeactivation(value: boolean): void {\n suppressBlurDeactivation = value;\n}\nexport function isSuppressBlurDeactivation(): boolean {\n return suppressBlurDeactivation;\n}\n\n// Flag to suppress blur-deactivation during mouse-drag text selection.\n// Separate from suppressBlurDeactivation so popover logic is not affected.\nlet mouseSelecting = false;\nexport function setMouseSelecting(value: boolean): void {\n mouseSelecting = value;\n}\nexport function isMouseSelecting(): boolean {\n return mouseSelecting;\n}\n", "\nimport * as defaultImport from \"slate\";\nexport * from \"slate\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "/**\n * Types for PureRichText visualization\n * Slate.js-based rich text editor implementation\n */\n\nimport { BaseEditor, Descendant } from 'slate';\nimport { ReactEditor } from 'slate-react';\n\n// ============================================\n// Element Types\n// ============================================\n\n/** Custom element types supported by the editor */\nexport type CustomElementType = 'paragraph' | 'bulleted-list' | 'numbered-list' | 'list-item' | 'link';\n\n/** Horizontal text alignment options */\nexport type TextAlign = 'left' | 'center' | 'right' | 'justify';\n\n/** Vertical alignment options */\nexport type VerticalAlign = 'top' | 'middle' | 'bottom';\n\n/** List type options */\nexport type ListType = 'unordered' | 'ordered' | null;\n\n/** Font size preset options */\nexport type FontSizePreset = 'extraSmall' | 'small' | 'default' | 'large' | 'extraLarge' | 'custom';\n\n// ============================================\n// Slate Custom Types\n// ============================================\n\n/** Custom element with formatting properties */\nexport interface CustomElement {\n type: CustomElementType;\n align?: TextAlign;\n lineHeight?: string; // Per-paragraph line height (e.g., \"1.5\", \"2\")\n children: (CustomText | CustomElement)[];\n url?: string; // For link elements\n}\n\n/** Custom text node with marks (inline formatting) */\nexport interface CustomText {\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n color?: string;\n backgroundColor?: string;\n fontSize?: string;\n fontFamily?: string;\n tokenName?: string; // marks this text as a resolved token value\n}\n\n// Extend Slate's type system\ndeclare module 'slate' {\n interface CustomTypes {\n Editor: BaseEditor & ReactEditor;\n Element: CustomElement;\n Text: CustomText;\n }\n}\n\n// ============================================\n// Text Styles Interface\n// ============================================\n\n/** Complete text styles state */\nexport interface TextStyles {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikethrough: boolean;\n color: string | null;\n backgroundColor: string | null;\n fontSize: string | null;\n fontFamily: string | null;\n textAlign: TextAlign | null;\n verticalAlign?: VerticalAlign | null;\n lineHeight?: string | null;\n listType: ListType;\n}\n\n/** Default text styles */\nexport const DEFAULT_TEXT_STYLES: TextStyles = {\n bold: false,\n italic: false,\n underline: false,\n strikethrough: false,\n color: '#ffffff',\n backgroundColor: 'transparent',\n fontSize: '14px',\n fontFamily: 'Splunk Data Sans',\n textAlign: 'left',\n verticalAlign: 'top',\n lineHeight: '1.5',\n listType: null,\n};\n\n// ============================================\n// Format Commands\n// ============================================\n\n/** All supported format commands */\nexport type FormatCommand =\n | 'bold'\n | 'italic'\n | 'underline'\n | 'strikethrough'\n | 'foreColor'\n | 'backColor'\n | 'fontSize'\n | 'fontName'\n | 'fontFamily'\n | 'justifyLeft'\n | 'justifyCenter'\n | 'justifyRight'\n | 'justifyFull'\n | 'lineHeight'\n | 'insertUnorderedList'\n | 'insertOrderedList'\n | 'createLink'\n | 'unlink'\n | 'formatBlock'\n | 'verticalAlign'\n | 'undo';\n\n/** Mark types for inline formatting */\nexport type MarkType =\n | 'bold'\n | 'italic'\n | 'underline'\n | 'strikethrough'\n | 'color'\n | 'backgroundColor'\n | 'fontSize'\n | 'fontFamily';\n\n// ============================================\n// Border Configuration\n// ============================================\n\n/** Border configuration for the container */\nexport interface BorderConfig {\n color?: string;\n width?: number;\n style?: 'solid' | 'dashed' | 'dotted' | 'none';\n radius?: number;\n}\n\n// ============================================\n// Padding Configuration\n// ============================================\n\n/** Padding configuration (can be a single value or array) */\nexport type PaddingConfig = number | [number, number] | [number, number, number, number];\n\n// ============================================\n// Component Props\n// ============================================\n\n/** Props for the PureRichText component */\nexport interface PureRichTextProps {\n // Dimensions\n width?: string | number;\n height?: string | number;\n\n // Content\n richTextContent?: string;\n\n // Container styling\n backgroundColor?: string;\n verticalAlign?: VerticalAlign;\n border?: BorderConfig;\n padding?: PaddingConfig;\n\n // Default text styling\n fontColor?: string;\n highlightColor?: string;\n fontFamily?: string;\n fontSize?: FontSizePreset;\n customFontSize?: number;\n lineHeight?: string | number;\n\n // Text formatting defaults\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n\n // Default text styles (aggregated from individual props)\n defaultTextStyles?: Partial<TextStyles>;\n\n // List and alignment\n listType?: ListType;\n horizontalAlignment?: TextAlign;\n\n // Link support\n link?: string;\n\n // Edit mode\n mode?: 'view' | 'edit';\n\n // Callbacks\n onOptionsChange?: (options: Record<string, unknown>) => void;\n onRichtextClick?: (event: unknown) => void;\n\n // Event handlers flag\n hasEventHandlers?: boolean;\n}\n\n// ============================================\n// Constants\n// ============================================\n\n/** Initial empty Slate value */\nexport const EMPTY_SLATE_VALUE: Descendant[] = [\n {\n type: 'paragraph',\n children: [{ text: '' }],\n },\n];\n\n/** Font size preset values in pixels */\nexport const FONT_SIZE_PRESETS: Record<FontSizePreset, number> = {\n extraSmall: 10,\n small: 12,\n default: 14,\n large: 16,\n extraLarge: 20,\n custom: 14,\n};\n\n/** Preloaded system fonts available by default */\nexport const PRELOADED_FONTS = [\n 'Splunk Data Sans',\n 'Splunk Platform Sans Mono',\n 'Arial',\n 'Helvetica',\n 'Times New Roman',\n 'Comic Sans MS',\n] as const;\n\n/** Font family with fallbacks */\nexport const FONT_FAMILY_WITH_FALLBACKS: Record<string, string> = {\n 'Splunk Data Sans':\n '\"Splunk Data Sans\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif',\n 'Splunk Platform Sans Mono': '\"Splunk Platform Sans Mono\", \"Courier New\", Courier, monospace',\n Arial: 'Arial, Helvetica, sans-serif',\n Helvetica: 'Helvetica, Arial, sans-serif',\n 'Times New Roman': '\"Times New Roman\", Times, serif',\n 'Comic Sans MS': '\"Comic Sans MS\", \"Comic Sans\", cursive, sans-serif',\n};\n", "\nimport * as defaultImport from \"dompurify\";\nexport * from \"dompurify\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "/**\n * Slate.js utility functions for PureRichText\n */\n\nimport {\n Editor,\n Transforms,\n Element as SlateElement,\n Text,\n Node as SlateNode,\n Range,\n Descendant,\n Point,\n} from 'slate';\nimport DOMPurify from 'dompurify';\nimport {\n CustomElement,\n CustomText,\n TextAlign,\n MarkType,\n EMPTY_SLATE_VALUE,\n FONT_FAMILY_WITH_FALLBACKS,\n} from '../types';\n\n// ============================================\n// Safe selection utilities\n// ============================================\n\n/**\n * Select the end of the document, silently catching errors from empty/invalid content.\n */\nexport function safeSelectEnd(editor: Editor): void {\n try {\n const end = Editor.end(editor, []);\n Transforms.select(editor, end);\n } catch {\n // ignore - content may be empty or paths invalid\n }\n}\n\n/**\n * Deselect the editor, silently catching errors from stale selection state.\n */\nexport function safeDeselect(editor: Editor): void {\n try {\n Transforms.deselect(editor);\n } catch {\n // ignore - selection may already be null or paths stale\n }\n}\n\n// ============================================\n// Mark (inline formatting) utilities\n// ============================================\n\nexport function isMarkActive(editor: Editor, format: MarkType): boolean {\n // Editor.marks() returns pending marks when they exist, otherwise reads\n // from the document. This single call is the source of truth for whether\n // a mark is active, matching how Slate's addMark/removeMark work.\n const marks = Editor.marks(editor);\n return marks !== null && Boolean(marks[format]);\n}\n\nexport function toggleMark(editor: Editor, format: MarkType): void {\n const isActive = isMarkActive(editor, format);\n if (isActive) {\n Editor.removeMark(editor, format);\n } else {\n Editor.addMark(editor, format, true);\n }\n}\n\n// ============================================\n// Block (paragraph-level) utilities\n// ============================================\n\n// Helper: Save selection, run function, restore selection\nfunction withSelectionRestore(editor: Editor, fn: () => void): void {\n const saved = editor.selection ? structuredClone(editor.selection) : null;\n fn();\n if (saved) {\n try {\n Transforms.select(editor, saved);\n } catch {\n // Selection restoration failed\n }\n }\n}\n\nexport function getBlockAlignment(editor: Editor): TextAlign {\n const { selection } = editor;\n if (!selection) return 'left';\n\n // First, check if we're in a list item\n const [listItemMatch] = Array.from(\n Editor.nodes(editor, {\n at: Editor.unhangRange(editor, selection),\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === 'list-item',\n })\n );\n\n if (listItemMatch) {\n const [node] = listItemMatch;\n return (node as CustomElement).align || 'left';\n }\n\n // Otherwise, get the first block element's alignment\n const [match] = Array.from(\n Editor.nodes(editor, {\n at: Editor.unhangRange(editor, selection),\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n),\n })\n );\n\n if (match) {\n const [node] = match;\n return (node as CustomElement).align || 'left';\n }\n\n return 'left';\n}\n\n/**\n * Toggle alignment for current block\n * For lists, apply alignment to list items rather than the list container\n */\nexport function toggleAlignment(editor: Editor, align: TextAlign): void {\n const { selection } = editor;\n if (!selection) return;\n\n withSelectionRestore(editor, () => {\n // Apply alignment to all block-level elements except list containers\n // (alignment belongs on list-item and paragraph nodes, not bulleted-list/numbered-list).\n Transforms.setNodes<SlateElement>(\n editor,\n { align },\n {\n match: n =>\n !Editor.isEditor(n) &&\n SlateElement.isElement(n) &&\n Editor.isBlock(editor, n) &&\n n.type !== 'bulleted-list' &&\n n.type !== 'numbered-list',\n }\n );\n });\n}\n\nexport function getBlockLineHeight(editor: Editor): string {\n const { selection } = editor;\n if (!selection) return '1.5';\n\n const [match] = Array.from(\n Editor.nodes(editor, {\n at: Editor.unhangRange(editor, selection),\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n),\n })\n );\n\n if (match) {\n const [node] = match;\n return (node as CustomElement).lineHeight || '1.5';\n }\n\n return '1.5';\n}\n\n/**\n * Set line height for current block(s)\n * Applies to all paragraphs that contain any part of the selection\n */\nexport function setBlockLineHeight(editor: Editor, lineHeight: string): void {\n const { selection } = editor;\n if (!selection) return;\n\n withSelectionRestore(editor, () => {\n // Use unhangRange to properly handle selections that span multiple blocks\n const at = Editor.unhangRange(editor, selection);\n\n Transforms.setNodes<SlateElement>(\n editor,\n { lineHeight },\n {\n at,\n match: n =>\n !Editor.isEditor(n) &&\n SlateElement.isElement(n) &&\n Editor.isBlock(editor, n) &&\n isLeafBlock(editor, n),\n }\n );\n });\n}\n\n/**\n * Check if currently in a list\n */\nexport function isListActive(editor: Editor, listType: 'bulleted-list' | 'numbered-list'): boolean {\n const { selection } = editor;\n if (!selection) return false;\n\n const [match] = Array.from(\n Editor.nodes(editor, {\n at: Editor.unhangRange(editor, selection),\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === listType,\n })\n );\n\n return !!match;\n}\n\nexport function toggleList(editor: Editor, listType: 'bulleted-list' | 'numbered-list'): void {\n const { selection } = editor;\n if (!selection) return;\n\n const isActive = isListActive(editor, listType);\n const isList = listType === 'bulleted-list' || listType === 'numbered-list';\n\n Transforms.unwrapNodes(editor, {\n match: n =>\n !Editor.isEditor(n) &&\n SlateElement.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n split: true,\n });\n\n let newType: string;\n if (isActive) {\n newType = 'paragraph';\n } else if (isList) {\n newType = 'list-item';\n } else {\n newType = listType;\n }\n\n Transforms.setNodes<SlateElement>(editor, {\n type: newType as CustomElement['type'],\n });\n\n if (!isActive && isList) {\n const block: CustomElement = { type: listType, children: [] };\n Transforms.wrapNodes(editor, block);\n }\n\n // Don't manually restore selection - let Slate handle it naturally\n // The saved selection path becomes invalid after unwrap/wrap operations\n}\n\nexport function getListType(editor: Editor): 'unordered' | 'ordered' | null {\n if (isListActive(editor, 'bulleted-list')) return 'unordered';\n if (isListActive(editor, 'numbered-list')) return 'ordered';\n return null;\n}\n\n// ============================================\n// Link utilities\n// ============================================\n\nexport function isLinkActive(editor: Editor): boolean {\n const [link] = Editor.nodes(editor, {\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === 'link',\n });\n return !!link;\n}\n\nexport function getSelectedText(editor: Editor): string {\n if (!editor.selection || Range.isCollapsed(editor.selection)) return '';\n return SlateNode.string({ children: Array.from(Editor.fragment(editor, editor.selection)) } as SlateNode);\n}\n\nexport function getActiveLink(editor: Editor): { url: string; text: string } | null {\n const [link] = Editor.nodes(editor, {\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === 'link',\n });\n\n if (link) {\n const [node] = link;\n const element = node as CustomElement;\n const text = SlateNode.string(element);\n return { url: element.url || '', text };\n }\n\n return null;\n}\n\n/**\n * Extract plain text from a Slate node tree. Used for screenreader content.\n */\nexport function slateToPlainText(nodes: Descendant[]): string {\n return SlateNode.string({ children: nodes } as SlateNode);\n}\n\n/**\n * Normalize a URL so it always has a protocol. Prevents links from being\n * treated as relative paths (e.g. \"google.com\" -> \"https://google.com\").\n */\nexport function normalizeUrl(url: string): string {\n const trimmed = url.trim();\n if (!trimmed) return trimmed;\n if (/^https?:\\/\\//i.test(trimmed) || /^mailto:/i.test(trimmed) || /^tel:/i.test(trimmed)) {\n return trimmed;\n }\n return `https://${trimmed}`;\n}\n\n/**\n * Insert or update a link\n */\nexport function insertLink(editor: Editor, url: string, text?: string): void {\n if (isLinkActive(editor)) {\n unwrapLink(editor);\n }\n\n const { selection } = editor;\n if (!selection) return;\n\n const normalizedUrl = normalizeUrl(url);\n const isCollapsed = Range.isCollapsed(selection);\n\n // For collapsed selections, inherit current marks so the link text matches\n // the styling at the insertion point (font, size, color, bold, etc.)\n let linkChild: CustomText = { text: text || normalizedUrl };\n if (isCollapsed) {\n const marks = Editor.marks(editor);\n if (marks) {\n linkChild = { ...linkChild, ...marks };\n }\n }\n\n const link: CustomElement = {\n type: 'link',\n url: normalizedUrl,\n children: isCollapsed ? [linkChild] : [],\n };\n\n if (isCollapsed) {\n // Capture marks before insertion so we can restore them after\n const marksBeforeInsert = Editor.marks(editor);\n Transforms.insertNodes(editor, link);\n // Move cursor to after the link so the next typed character is outside it\n Transforms.move(editor, { unit: 'offset' });\n // Restore marks so text typed after the link inherits the same styles\n if (marksBeforeInsert) {\n Object.entries(marksBeforeInsert).forEach(([key, value]) => {\n if (value !== undefined && value !== null && key !== 'text') {\n Editor.addMark(editor, key, value);\n }\n });\n }\n } else {\n // Replace the selected text with the new link text if provided and different\n if (text) {\n Transforms.insertText(editor, text);\n // Re-select the newly inserted text\n if (!editor.selection) return;\n const { anchor } = editor.selection;\n Transforms.select(editor, {\n anchor: { path: anchor.path, offset: anchor.offset - text.length },\n focus: anchor,\n });\n }\n Transforms.wrapNodes(editor, link, { split: true });\n Transforms.collapse(editor, { edge: 'end' });\n }\n}\n\n/**\n * Remove link\n */\nexport function unwrapLink(editor: Editor): void {\n Transforms.unwrapNodes(editor, {\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === 'link',\n });\n}\n\n// ============================================\n// Style extraction utilities\n// ============================================\n\n// Helper: Build a mark object from a node\nfunction buildMarkObject(node: any): Partial<CustomText> {\n return {\n bold: !!node.bold,\n italic: !!node.italic,\n underline: !!node.underline,\n strikethrough: !!node.strikethrough,\n color: node.color,\n backgroundColor: node.backgroundColor,\n fontSize: node.fontSize,\n fontFamily: node.fontFamily,\n };\n}\n\n// Helper: Extract marks from text node by path traversal\nfunction extractNodeMarksByPath(editor: Editor, path: number[]): Partial<CustomText> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let current: any = editor;\n for (const index of path) {\n if (current.children && Array.isArray(current.children)) {\n current = current.children[index];\n } else {\n break;\n }\n }\n\n if (current && typeof current.text === 'string') {\n return buildMarkObject(current);\n }\n } catch {\n // Path traversal failed\n }\n return {};\n}\n\n// Helper: Extract marks using Editor.leaf\nfunction extractNodeMarksByLeaf(editor: Editor, point: Point): Partial<CustomText> {\n try {\n const [leaf] = Editor.leaf(editor, point);\n if (leaf) {\n return buildMarkObject(leaf);\n }\n } catch {\n // Editor.leaf failed\n }\n return {};\n}\n\n// Helper: Get marks from the actual text node at cursor\nfunction getNodeMarks(editor: Editor): Partial<CustomText> {\n if (!editor.selection) return {};\n\n const { path } = editor.selection.focus;\n let marks = extractNodeMarksByPath(editor, path);\n\n // Fallback to Editor.leaf if path traversal didn't work\n if (Object.keys(marks).length === 0) {\n marks = extractNodeMarksByLeaf(editor, editor.selection.focus);\n }\n\n return marks;\n}\n\n// Helper: Get pending marks that will be applied to new text.\n// Returns { marks, hasPendingMarks } \u2014 hasPendingMarks is true when editor.marks is a\n// non-null object, meaning the user has explicitly set (or removed) marks at the cursor.\n// editor.marks is null after cursor moves; it is set to {} or { key: val } after addMark/removeMark.\nfunction getPendingMarks(editor: Editor): { marks: Partial<CustomText>; hasPendingMarks: boolean } {\n try {\n // editor.marks is the internal pending-marks store \u2014 null = use leaf, {} = user explicitly cleared marks\n const internalMarks = (editor as Editor & { marks: Partial<CustomText> | null }).marks;\n if (internalMarks !== null && internalMarks !== undefined) {\n return { marks: internalMarks as Partial<CustomText>, hasPendingMarks: true };\n }\n return { marks: {}, hasPendingMarks: false };\n } catch {\n return { marks: {}, hasPendingMarks: false };\n }\n}\n\n// Helper: Merge node marks with pending marks.\n// When hasPendingMarks is true, boolean marks absent from pendingMarks were explicitly\n// removed (Editor.removeMark) and should be treated as false \u2014 not inherited from the node.\nfunction mergeMarks(\n nodeMarks: Partial<CustomText>,\n pendingMarksResult: { marks: Partial<CustomText>; hasPendingMarks: boolean }\n): Partial<CustomText> {\n const { marks: pendingMarks, hasPendingMarks } = pendingMarksResult;\n const marks: Partial<CustomText> = { ...nodeMarks };\n\n // Boolean marks: if pending marks exist, the pending object is the full source of truth\n // (absent key = explicitly removed). Override node marks accordingly.\n if (hasPendingMarks) {\n marks.bold = pendingMarks.bold ?? false;\n marks.italic = pendingMarks.italic ?? false;\n marks.underline = pendingMarks.underline ?? false;\n marks.strikethrough = pendingMarks.strikethrough ?? false;\n } else {\n // No pending marks \u2014 keep node marks for booleans (reading existing text)\n if (pendingMarks.bold !== undefined) marks.bold = pendingMarks.bold;\n if (pendingMarks.italic !== undefined) marks.italic = pendingMarks.italic;\n if (pendingMarks.underline !== undefined) marks.underline = pendingMarks.underline;\n if (pendingMarks.strikethrough !== undefined) marks.strikethrough = pendingMarks.strikethrough;\n }\n\n // Non-boolean marks always override when explicitly set\n if (pendingMarks.color !== undefined) marks.color = pendingMarks.color;\n if (pendingMarks.backgroundColor !== undefined) marks.backgroundColor = pendingMarks.backgroundColor;\n if (pendingMarks.fontSize !== undefined) marks.fontSize = pendingMarks.fontSize;\n if (pendingMarks.fontFamily !== undefined) marks.fontFamily = pendingMarks.fontFamily;\n\n return marks;\n}\n\n/** Collect unique text-level style values from non-whitespace text nodes. */\nfunction collectTextStyles(editor: Editor, selection: Range) {\n const colors = new Set<string>();\n const bgColors = new Set<string>();\n const fontSizes = new Set<string>();\n const fontFamilies = new Set<string>();\n\n for (const [node] of Editor.nodes(editor, {\n at: selection,\n match: n => Text.isText(n),\n })) {\n const textNode = node;\n if (textNode.text && textNode.text.trim().length > 0) {\n colors.add(textNode.color || '');\n bgColors.add(textNode.backgroundColor || '');\n fontSizes.add(textNode.fontSize || '');\n const normalizedFont = textNode.fontFamily\n ? normalizeFontFamilyName(textNode.fontFamily) || ''\n : '';\n fontFamilies.add(normalizedFont);\n }\n }\n\n return { colors, bgColors, fontSizes, fontFamilies };\n}\n\n/** True when every child of the element is inline (text or inline element). */\nfunction isLeafBlock(editor: Editor, node: SlateElement): boolean {\n return node.children.every(child => Text.isText(child) || editor.isInline(child));\n}\n\n/** Collect unique block-level line height values, normalized to avoid \"1.5\" vs \"1.50\". */\nfunction collectBlockLineHeights(editor: Editor, selection: Range): Set<string> {\n const lineHeights = new Set<string>();\n for (const [node] of Editor.nodes(editor, {\n at: Editor.unhangRange(editor, selection),\n match: n =>\n !Editor.isEditor(n) &&\n SlateElement.isElement(n) &&\n Editor.isBlock(editor, n) &&\n isLeafBlock(editor, n),\n })) {\n const blockNode = node as CustomElement;\n const lh = Number.parseFloat(blockNode.lineHeight || '1.5');\n lineHeights.add(Number.isNaN(lh) ? '1.5' : String(lh));\n }\n return lineHeights;\n}\n\n// Helper: Check if selection has mixed style values\nfunction checkMixedStyles(editor: Editor, selection: Range) {\n if (Range.isCollapsed(selection)) return undefined;\n\n const { colors, bgColors, fontSizes, fontFamilies } = collectTextStyles(editor, selection);\n const lineHeights = collectBlockLineHeights(editor, selection);\n\n const mixed: Record<string, boolean> = {};\n if (colors.size > 1) mixed.color = true;\n if (bgColors.size > 1) mixed.backgroundColor = true;\n if (fontSizes.size > 1) mixed.fontSize = true;\n if (fontFamilies.size > 1) mixed.fontFamily = true;\n if (lineHeights.size > 1) mixed.lineHeight = true;\n\n return Object.keys(mixed).length > 0 ? mixed : undefined;\n}\n\n// Helper: Normalize font family to base name\nfunction normalizeFontFamilyName(fontFamily: string | undefined): string | null {\n if (typeof fontFamily !== 'string') return null;\n\n // Remove quotes and normalize whitespace for comparison\n const normalizeForComparison = (font: string): string => {\n return font.replaceAll(/[\"']/g, '').trim().toLowerCase();\n };\n\n const normalizedInput = normalizeForComparison(fontFamily);\n\n // Try to match against known fallback patterns\n const matchingFont = Object.entries(FONT_FAMILY_WITH_FALLBACKS).find(([baseName, fullValue]) => {\n const normalizedFull = normalizeForComparison(fullValue);\n const normalizedBase = normalizeForComparison(baseName);\n\n // Check if input matches the full fallback string or just the base name\n return normalizedInput === normalizedFull || normalizedInput === normalizedBase;\n });\n\n return matchingFont ? matchingFont[0] : fontFamily.split(',')[0].trim().replaceAll(/[\"']/g, '');\n}\n\n/**\n * Get current text styles at cursor/selection\n */\nexport function getCurrentStyles(editor: Editor): {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikethrough: boolean;\n color: string | null;\n backgroundColor: string | null;\n fontSize: string | null;\n fontFamily: string | null;\n textAlign: TextAlign;\n lineHeight: string | null;\n listType: 'unordered' | 'ordered' | null;\n isMixed?: {\n color?: boolean;\n backgroundColor?: boolean;\n fontSize?: boolean;\n fontFamily?: boolean;\n lineHeight?: boolean;\n };\n} {\n // Get marks from text node and pending marks\n const nodeMarks = getNodeMarks(editor);\n const pendingMarksResult = getPendingMarks(editor);\n const marks = mergeMarks(nodeMarks, pendingMarksResult);\n\n // Check for mixed styles in selection\n const isMixed = editor.selection ? checkMixedStyles(editor, editor.selection) : undefined;\n\n return {\n bold: Boolean(marks.bold),\n italic: Boolean(marks.italic),\n underline: Boolean(marks.underline),\n strikethrough: Boolean(marks.strikethrough),\n color: typeof marks.color === 'string' ? normalizeColor(marks.color) : null,\n backgroundColor:\n typeof marks.backgroundColor === 'string' ? normalizeColor(marks.backgroundColor) : null,\n fontSize: typeof marks.fontSize === 'string' ? marks.fontSize : null,\n fontFamily: normalizeFontFamilyName(marks.fontFamily),\n textAlign: getBlockAlignment(editor),\n lineHeight: getBlockLineHeight(editor),\n listType: getListType(editor),\n isMixed,\n };\n}\n\n// ============================================\n// HTML conversion utilities\n// ============================================\n\n/**\n * Convert Slate value to HTML\n */\nexport function slateToHtml(value: Descendant[]): string {\n // Escape HTML special characters\n const escapeHtml = (text: string): string => {\n return text.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;');\n };\n\n // Build inline styles for text nodes\n const buildTextStyles = (node: CustomText): string[] => {\n const styles: string[] = [];\n if (node.color) styles.push(`color: ${node.color}`);\n if (node.backgroundColor && node.backgroundColor !== 'transparent') {\n styles.push(`background-color: ${node.backgroundColor}`);\n }\n if (node.fontSize) styles.push(`font-size: ${node.fontSize}`);\n if (node.fontFamily) styles.push(`font-family: ${node.fontFamily}`);\n return styles;\n };\n\n // Apply text formatting tags\n const applyTextFormatting = (text: string, node: CustomText): string => {\n let result = text;\n if (node.bold) result = `<strong>${result}</strong>`;\n if (node.italic) result = `<em>${result}</em>`;\n if (node.underline) result = `<u>${result}</u>`;\n if (node.strikethrough) result = `<s>${result}</s>`;\n return result;\n };\n\n // Serialize text node.\n // When text is empty but has inline styles (color, backgroundColor, fontSize,\n // fontFamily), emit an empty styled <span> so the marks survive the HTML\n // round-trip. Without this, pressing Enter at the end of a styled list item\n // creates an empty text node whose marks are silently dropped, and the list\n // marker reverts to the default color after the debounce save fires.\n const serializeTextNode = (node: CustomText): string => {\n const styles = buildTextStyles(node);\n let { text } = node;\n if (!text) {\n return styles.length > 0 ? `<span style=\"${styles.join('; ')}\"></span>` : '';\n }\n\n text = escapeHtml(text);\n text = applyTextFormatting(text, node);\n\n if (styles.length > 0) {\n text = `<span style=\"${styles.join('; ')}\">${text}</span>`;\n }\n\n return text;\n };\n\n // Build block-level style attribute\n const buildBlockStyleAttr = (element: CustomElement): string => {\n const styles: string[] = [];\n if (element.align) styles.push(`text-align: ${element.align}`);\n if (element.lineHeight) styles.push(`line-height: ${element.lineHeight}`);\n return styles.length > 0 ? ` style=\"${styles.join('; ')}\"` : '';\n };\n\n // Serialize element node\n const serializeElement = (\n element: CustomElement & { children: Descendant[] },\n children: string\n ): string => {\n const styleAttr = buildBlockStyleAttr(element);\n\n switch (element.type) {\n case 'paragraph':\n return `<p${styleAttr}>${children || '<br>'}</p>`;\n case 'bulleted-list':\n return `<ul${styleAttr}>${children}</ul>`;\n case 'numbered-list':\n return `<ol${styleAttr}>${children}</ol>`;\n case 'list-item':\n return `<li${styleAttr}>${children}</li>`;\n case 'link':\n return `<a href=\"${normalizeUrl(element.url || '') || '#'}\"${styleAttr}>${children}</a>`;\n default:\n return `<p${styleAttr}>${children}</p>`;\n }\n };\n\n const serializeNode = (node: Descendant): string => {\n if (Text.isText(node)) {\n return serializeTextNode(node);\n }\n\n const element = node as CustomElement & { children: Descendant[] };\n const children = element.children.map(serializeNode).join('');\n return serializeElement(element, children);\n };\n\n return value.map(serializeNode).join('');\n}\n\n/**\n * Convert HTML to Slate value\n *\n * Note: This is a simplified parser. Complex HTML from other approaches may not\n * render exactly the same due to Slate's block/inline model differences.\n */\nexport function htmlToSlate(html: string): Descendant[] {\n if (!html || html.trim() === '') {\n return EMPTY_SLATE_VALUE;\n }\n\n // Type alias for deserialization result\n type DeserializeResult = Descendant | Descendant[] | null;\n\n // Sanitize HTML first - include font tag\n const sanitized = DOMPurify.sanitize(html, {\n ALLOWED_TAGS: [\n 'p',\n 'br',\n 'strong',\n 'b',\n 'em',\n 'i',\n 'u',\n 's',\n 'strike',\n 'span',\n 'a',\n 'ul',\n 'ol',\n 'li',\n 'div',\n 'font',\n ],\n ALLOWED_ATTR: ['style', 'href', 'color', 'face', 'size'],\n });\n\n const parser = new DOMParser();\n const doc = parser.parseFromString(`<body>${sanitized}</body>`, 'text/html');\n\n // Helper to apply marks to all text children\n const applyMarksToChildren = (children: Descendant[], marks: Partial<CustomText>): Descendant[] => {\n return children.map(child => {\n if (Text.isText(child)) {\n return { ...child, ...marks };\n }\n return child;\n });\n };\n\n // Extract block-level styles from element\n const extractBlockStyles = (style: string) => {\n const alignMatch = /text-align:\\s*(left|center|right|justify)/i.exec(style);\n const align = alignMatch ? (alignMatch[1] as TextAlign) : undefined;\n const lineHeightMatch = /line-height:\\s*([^;]+)/i.exec(style);\n const lineHeight = lineHeightMatch ? lineHeightMatch[1].trim() : undefined;\n return { align, lineHeight };\n };\n\n // Extract inline styles from span element\n const extractSpanMarks = (style: string): Partial<CustomText> => {\n const marks: Partial<CustomText> = {};\n const colorMatch = /(?:^|;)\\s*color:\\s*([^;]+)/i.exec(style);\n const bgMatch = /background-color:\\s*([^;]+)/i.exec(style);\n const fontSizeMatch = /font-size:\\s*([^;]+)/i.exec(style);\n const fontFamilyMatch = /font-family:\\s*([^;]+)/i.exec(style);\n const fontWeightMatch = /font-weight:\\s*([^;]+)/i.exec(style);\n const fontStyleMatch = /font-style:\\s*([^;]+)/i.exec(style);\n const textDecorationMatch = /text-decoration:\\s*([^;]+)/i.exec(style);\n\n if (colorMatch) marks.color = colorMatch[1].trim();\n if (bgMatch) marks.backgroundColor = bgMatch[1].trim();\n if (fontSizeMatch) marks.fontSize = fontSizeMatch[1].trim();\n if (fontFamilyMatch) marks.fontFamily = fontFamilyMatch[1].trim().replaceAll(/[\"']/g, '');\n if (fontWeightMatch?.[1].trim() === 'bold') marks.bold = true;\n if (fontStyleMatch?.[1].trim() === 'italic') marks.italic = true;\n\n if (textDecorationMatch) {\n const decoration = textDecorationMatch[1].trim().toLowerCase();\n if (decoration.includes('underline')) marks.underline = true;\n if (decoration.includes('line-through')) marks.strikethrough = true;\n }\n\n return marks;\n };\n\n // Extract marks from font element\n const extractFontMarks = (element: HTMLElement): Partial<CustomText> => {\n const marks: Partial<CustomText> = {};\n const fontColor = element.getAttribute('color');\n const fontFace = element.getAttribute('face');\n if (fontColor) marks.color = fontColor;\n if (fontFace) marks.fontFamily = fontFace;\n return marks;\n };\n\n // Process children of an element\n const processChildren = (\n element: HTMLElement,\n deserializeFn: (node: ChildNode) => DeserializeResult\n ): Descendant[] => {\n let children: Descendant[] = [];\n element.childNodes.forEach(child => {\n const result = deserializeFn(child);\n if (result) {\n if (Array.isArray(result)) {\n children.push(...result);\n } else {\n children.push(result);\n }\n }\n });\n\n // Ensure we have at least one child for block elements\n if (children.length === 0) {\n children = [{ text: '' }];\n }\n\n return children;\n };\n\n // Handle different HTML tags\n const handleTag = (\n tagName: string,\n element: HTMLElement,\n children: Descendant[],\n blockStyles: { align?: TextAlign; lineHeight?: string }\n ): DeserializeResult => {\n const { align, lineHeight } = blockStyles;\n\n switch (tagName) {\n case 'body':\n case 'div':\n return children;\n\n case 'p':\n return { type: 'paragraph', align, lineHeight, children } as CustomElement;\n\n case 'ul':\n return { type: 'bulleted-list', align, lineHeight, children } as CustomElement;\n\n case 'ol':\n return { type: 'numbered-list', align, lineHeight, children } as CustomElement;\n\n case 'li':\n return { type: 'list-item', align, lineHeight, children } as CustomElement;\n\n case 'a':\n return {\n type: 'link',\n url: normalizeUrl(element.getAttribute('href') || ''),\n children,\n } as CustomElement;\n\n case 'strong':\n case 'b':\n return applyMarksToChildren(children, { bold: true });\n\n case 'em':\n case 'i':\n return applyMarksToChildren(children, { italic: true });\n\n case 'u':\n return applyMarksToChildren(children, { underline: true });\n\n case 's':\n case 'strike':\n return applyMarksToChildren(children, { strikethrough: true });\n\n case 'font':\n return applyMarksToChildren(children, extractFontMarks(element));\n\n case 'span': {\n const style = element.getAttribute('style') || '';\n return applyMarksToChildren(children, extractSpanMarks(style));\n }\n\n case 'br':\n return { text: '\\n' };\n\n default:\n return children;\n }\n };\n\n const deserialize = (el: ChildNode): DeserializeResult => {\n // Use global Node constants (not Slate's Node)\n if (el.nodeType === globalThis.Node.TEXT_NODE) {\n const text = el.textContent || '';\n if (!text) return null;\n return { text };\n }\n\n if (el.nodeType !== globalThis.Node.ELEMENT_NODE) {\n return null;\n }\n\n const element = el as HTMLElement;\n const tagName = element.tagName.toLowerCase();\n const style = element.getAttribute('style') || '';\n\n const children = processChildren(element, deserialize);\n const blockStyles = extractBlockStyles(style);\n\n return handleTag(tagName, element, children, blockStyles);\n };\n\n const result = deserialize(doc.body);\n if (!result) return EMPTY_SLATE_VALUE;\n\n const nodes = Array.isArray(result) ? result : [result];\n\n // Normalize: group consecutive text nodes into paragraphs\n const normalized: Descendant[] = [];\n let currentTextNodes: CustomText[] = [];\n\n const flushTextNodes = (): void => {\n if (currentTextNodes.length > 0) {\n normalized.push({ type: 'paragraph', children: currentTextNodes } as CustomElement);\n currentTextNodes = [];\n }\n };\n\n for (const node of nodes) {\n if (Text.isText(node)) {\n currentTextNodes.push(node);\n } else {\n flushTextNodes();\n normalized.push(node);\n }\n }\n flushTextNodes();\n\n return normalized.length > 0 ? normalized : EMPTY_SLATE_VALUE;\n}\n\n/**\n * Normalize color to hex format\n */\nexport function normalizeColor(color: string | null | undefined): string | null {\n if (!color || color === 'transparent') return null;\n\n // Already hex\n if (color.startsWith('#')) {\n return color.toLowerCase();\n }\n\n // RGB/RGBA\n const rgbMatch = /rgba?\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/i.exec(color);\n if (rgbMatch) {\n const r = Number.parseInt(rgbMatch[1], 10);\n const g = Number.parseInt(rgbMatch[2], 10);\n const b = Number.parseInt(rgbMatch[3], 10);\n return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`.toLowerCase();\n }\n\n return color;\n}\n\n/**\n * Parse padding value to array format [top, right, bottom, left]\n */\nexport function parsePadding(\n padding: number | [number, number] | [number, number, number, number] | undefined\n): [number, number, number, number] {\n if (padding === undefined) {\n return [8, 8, 8, 8];\n }\n\n if (typeof padding === 'number') {\n return [padding, padding, padding, padding];\n }\n\n if (padding.length === 2) {\n return [padding[0], padding[1], padding[0], padding[1]];\n }\n\n return padding;\n}\n", "/**\n * Accessibility utilities for PureRichText.\n */\n\nimport type { FormatCommand } from '../types';\n\n/**\n * Generate a screenreader announcement for a format command.\n */\nexport function generateFormatAnnouncement(command: FormatCommand, value?: string): string {\n switch (command) {\n case 'bold':\n return 'Bold toggled';\n case 'italic':\n return 'Italic toggled';\n case 'underline':\n return 'Underline toggled';\n case 'strikethrough':\n return 'Strikethrough toggled';\n case 'fontSize':\n return `Font size changed to ${value}`;\n case 'fontName':\n case 'fontFamily':\n return `Font changed to ${value}`;\n case 'foreColor':\n return 'Font color changed';\n case 'backColor':\n return 'Highlight color changed';\n case 'justifyLeft':\n return 'Aligned left';\n case 'justifyCenter':\n return 'Aligned center';\n case 'justifyRight':\n return 'Aligned right';\n case 'justifyFull':\n return 'Aligned justify';\n case 'lineHeight':\n return 'Line spacing changed';\n case 'insertOrderedList':\n return 'Numbered list toggled';\n case 'insertUnorderedList':\n return 'Bulleted list toggled';\n case 'createLink':\n return 'Link inserted';\n case 'unlink':\n return 'Link removed';\n default:\n return 'Format applied';\n }\n}\n", "/**\n * PureRichText Context - Simplified\n *\n * activeTextStyles: active > user defaults > system defaults\n * - Starts with user defaults || system defaults\n * - Updates when cursor moves or user makes changes\n * - Reset button restores to user defaults\n */\n\nimport React, { createContext, useContext, useCallback, useState, useRef, useMemo, useEffect } from 'react';\nimport { Editor, Range, Transforms, Element as SlateElement, Text } from 'slate';\nimport { TextStyles, DEFAULT_TEXT_STYLES, FormatCommand } from './types';\nimport {\n toggleMark,\n toggleAlignment,\n setBlockLineHeight,\n toggleList,\n getCurrentStyles,\n insertLink,\n unwrapLink,\n isLinkActive,\n getActiveLink,\n getSelectedText,\n} from './utils/slateUtils';\nimport { generateFormatAnnouncement } from './utils/a11yUtils';\n\ntype EditorWithMarks = Editor & { marks: Record<string, unknown> | null };\ntype LinkInfo = { url: string; text: string };\ntype BooleanMarkFormat = 'bold' | 'italic' | 'underline' | 'strikethrough';\ntype BoolMarkOverride = Partial<Record<BooleanMarkFormat, boolean>>;\n\nexport type ActiveTextStyles = TextStyles & {\n isMixed?: {\n color?: boolean;\n backgroundColor?: boolean;\n fontSize?: boolean;\n fontFamily?: boolean;\n lineHeight?: boolean;\n };\n};\n\nexport interface PureRichTextContextValue {\n // Active text styles (source of truth for editor panel)\n activeTextStyles: ActiveTextStyles;\n\n // User default styles (for reset)\n userDefaultStyles: TextStyles;\n\n // Slate editor instance\n editor: Editor | null;\n setEditor: (editor: Editor) => void;\n\n // Update active styles from cursor position.\n // Pass isContentChange=true when text content changed (not just selection) to clear mark overrides.\n updateActiveStyles: (isContentChange?: boolean) => void;\n\n // Save current selection before focus leaves the editable\n saveSelection: () => void;\n\n // Format application\n applyFormat: (command: FormatCommand, value?: string) => void;\n resetToDefault: () => void;\n stepFontSize: (delta: number) => void;\n registerStepFontSize: (fn: (delta: number) => void) => void;\n stepLineSpacing: (delta: number) => void;\n registerStepLineSpacing: (fn: (delta: number) => void) => void;\n /** Register callback invoked after each applyFormat with the post-format selection. */\n registerOnFormatApplied: (fn: (selection: Editor['selection']) => void) => void;\n /** Register callback for screenreader announcements on format changes. */\n registerAnnouncement: (fn: (message: string) => void) => void;\n\n // Link helpers\n openLinkPopover: () => void;\n registerOpenLinkPopover: (fn: () => void) => void;\n isInLink: () => boolean;\n getLinkInfo: () => LinkInfo | null;\n createOrUpdateLink: (url: string, text?: string) => void;\n removeLink: () => void;\n}\n\nconst PureRichTextContext = createContext<PureRichTextContextValue | null>(null);\n\nexport function usePureRichText(): PureRichTextContextValue {\n const context = useContext(PureRichTextContext);\n if (!context) {\n throw new Error('usePureRichText must be used within a PureRichTextProvider');\n }\n return context;\n}\n\nexport function usePureRichTextOptional(): PureRichTextContextValue | null {\n return useContext(PureRichTextContext);\n}\n\ninterface PureRichTextProviderProps {\n children: React.ReactNode;\n defaultColor?: string;\n defaultBackgroundColor?: string;\n defaultFontFamily?: string;\n defaultFontSize?: string;\n defaultBold?: boolean;\n defaultItalic?: boolean;\n defaultUnderline?: boolean;\n defaultStrikethrough?: boolean;\n}\n\nexport function PureRichTextProvider({\n children,\n defaultColor,\n defaultBackgroundColor,\n defaultFontFamily,\n defaultFontSize,\n defaultBold,\n defaultItalic,\n defaultUnderline,\n defaultStrikethrough,\n}: Readonly<PureRichTextProviderProps>): JSX.Element {\n // User default styles - memoize based on props\n const userDefaultStyles: TextStyles = useMemo(\n () => ({\n ...DEFAULT_TEXT_STYLES,\n color: defaultColor || DEFAULT_TEXT_STYLES.color,\n backgroundColor: defaultBackgroundColor || DEFAULT_TEXT_STYLES.backgroundColor,\n fontFamily: defaultFontFamily || DEFAULT_TEXT_STYLES.fontFamily,\n fontSize: defaultFontSize || DEFAULT_TEXT_STYLES.fontSize,\n bold: defaultBold ?? DEFAULT_TEXT_STYLES.bold,\n italic: defaultItalic ?? DEFAULT_TEXT_STYLES.italic,\n underline: defaultUnderline ?? DEFAULT_TEXT_STYLES.underline,\n strikethrough: defaultStrikethrough ?? DEFAULT_TEXT_STYLES.strikethrough,\n }),\n [\n defaultColor,\n defaultBackgroundColor,\n defaultFontFamily,\n defaultFontSize,\n defaultBold,\n defaultItalic,\n defaultUnderline,\n defaultStrikethrough,\n ]\n );\n\n // Active text styles - starts with user defaults, updates from cursor/changes\n const [activeTextStyles, setActiveTextStyles] = useState<ActiveTextStyles>(userDefaultStyles);\n\n // Update activeTextStyles when userDefaultStyles changes (on mount or prop change)\n useEffect(() => {\n setActiveTextStyles(userDefaultStyles);\n }, [userDefaultStyles]);\n\n // Editor instance\n const editorRef = useRef<Editor | null>(null);\n\n // Saved selection \u2014 updated on every selection change, used to restore\n // selection before applying formats when toolbar controls steal focus\n const savedSelectionRef = useRef<Editor['selection']>(null);\n\n // After applyFormat toggles a boolean mark, the subsequent focus restoration calls\n // focusActiveEditable() \u2192 ReactEditor.focus() \u2192 set_selection \u2192 editor.marks = null.\n // The following onChange \u2192 updateActiveStyles() would then read from the leaf (which hasn't\n // changed) and revert the panel state. This ref holds explicit boolean mark overrides set\n // by applyFormat. The override is cleared when a content-change (not selection-only) update\n // arrives, indicating the user typed and the leaf now reflects the correct state.\n const boolMarkOverrideRef = useRef<BoolMarkOverride | null>(null);\n\n const setEditor = useCallback((editor: Editor) => {\n editorRef.current = editor;\n }, []);\n\n // Save the current selection explicitly \u2014 called from handleBlur before Slate clears it\n const saveSelection = useCallback(() => {\n const editor = editorRef.current;\n if (editor?.selection) {\n savedSelectionRef.current = editor.selection;\n }\n }, []);\n\n // Resolve a boolean mark: explicit override > slate value > user default (for empty editor)\n // Extracted to reduce cognitive complexity of updateActiveStyles.\n const resolveBooleanMark = useCallback(\n (\n format: BooleanMarkFormat,\n slateValue: boolean,\n hasAnyLeafContent: boolean,\n hasPendingMarks: boolean\n ): boolean => {\n // If an explicit override is set (from applyFormat toggle), use it to prevent the\n // focus-restoration set_selection from reverting the panel toggle button state.\n if (boolMarkOverrideRef.current !== null && format in boolMarkOverrideRef.current) {\n return Boolean(boolMarkOverrideRef.current[format]);\n }\n // If there's actual content OR pending marks exist (user has made a toggle), trust slate\n if (hasAnyLeafContent || hasPendingMarks) return slateValue;\n // Empty editor with no pending marks \u2014 use user default as the \"will type\" preview\n return userDefaultStyles[format] ?? false;\n },\n [userDefaultStyles]\n );\n\n // Update active styles from Slate editor at cursor position.\n // Pass isContentChange=true when a real text operation occurred (not just a selection move)\n // so the boolean mark override (set by applyFormat) is cleared after content is committed.\n const updateActiveStyles = useCallback(\n (isContentChange?: boolean) => {\n const editor = editorRef.current;\n if (!editor?.selection) {\n return;\n }\n\n // Get current styles from Slate at cursor\n const slateStyles = getCurrentStyles(editor);\n\n // editor.marks (internal Slate property) is null after cursor moves (no pending marks)\n // and is a plain object (possibly {}) after addMark/removeMark.\n const editorWithMarks: EditorWithMarks = editor;\n const internalPendingMarks = editorWithMarks.marks;\n const hasPendingMarks = internalPendingMarks !== null && internalPendingMarks !== undefined;\n const hasAnyLeafContent = editor.children.some(\n n => SlateElement.isElement(n) && n.children.some(c => Text.isText(c) && c.text !== '')\n );\n\n // Clear the override when content actually changes (user typed, paste, etc.)\n if (isContentChange) {\n boolMarkOverrideRef.current = null;\n }\n\n const newActiveStyles: ActiveTextStyles = {\n bold: resolveBooleanMark('bold', slateStyles.bold, hasAnyLeafContent, hasPendingMarks),\n italic: resolveBooleanMark('italic', slateStyles.italic, hasAnyLeafContent, hasPendingMarks),\n underline: resolveBooleanMark(\n 'underline',\n slateStyles.underline,\n hasAnyLeafContent,\n hasPendingMarks\n ),\n strikethrough: resolveBooleanMark(\n 'strikethrough',\n slateStyles.strikethrough,\n hasAnyLeafContent,\n hasPendingMarks\n ),\n color: slateStyles.color || userDefaultStyles.color,\n backgroundColor:\n slateStyles.backgroundColor ??\n (hasAnyLeafContent || hasPendingMarks ? null : userDefaultStyles.backgroundColor),\n fontSize: slateStyles.fontSize || userDefaultStyles.fontSize,\n fontFamily: slateStyles.fontFamily || userDefaultStyles.fontFamily,\n textAlign: slateStyles.textAlign || userDefaultStyles.textAlign,\n verticalAlign: userDefaultStyles.verticalAlign,\n lineHeight: slateStyles.lineHeight || userDefaultStyles.lineHeight,\n listType: slateStyles.listType ?? userDefaultStyles.listType,\n };\n\n if (slateStyles.isMixed && Object.keys(slateStyles.isMixed).length > 0) {\n newActiveStyles.isMixed = slateStyles.isMixed;\n }\n\n setActiveTextStyles(newActiveStyles);\n },\n [userDefaultStyles, resolveBooleanMark]\n );\n\n // Toggle a boolean mark and record an override so the panel reflects the toggle\n // immediately (before focus restoration would otherwise revert it).\n const toggleBooleanMark = useCallback((editor: Editor, format: BooleanMarkFormat): void => {\n toggleMark(editor, format);\n if (editor.selection && Range.isCollapsed(editor.selection)) {\n const editorWithMarks: EditorWithMarks = editor;\n const internalMarks = editorWithMarks.marks;\n const newValue = internalMarks !== null ? Boolean(internalMarks[format]) : false;\n boolMarkOverrideRef.current = {\n ...(boolMarkOverrideRef.current ?? {}),\n [format]: newValue,\n };\n }\n }, []);\n\n // Map a justify/alignment command to the Slate alignment value and apply it.\n const applyAlignmentCommand = useCallback((editor: Editor, command: FormatCommand): void => {\n const alignMap: Partial<Record<FormatCommand, 'left' | 'center' | 'right' | 'justify'>> = {\n justifyLeft: 'left',\n justifyCenter: 'center',\n justifyRight: 'right',\n justifyFull: 'justify',\n };\n const align = alignMap[command];\n if (align) toggleAlignment(editor, align);\n }, []);\n\n // Dispatch a format command to the appropriate Slate operation.\n // Extracted to reduce cognitive complexity of applyFormat.\n const dispatchFormatCommand = useCallback(\n (editor: Editor, command: FormatCommand, value?: string): void => {\n const boolFormats = ['bold', 'italic', 'underline', 'strikethrough'];\n if (boolFormats.includes(command)) {\n toggleBooleanMark(editor, command as BooleanMarkFormat);\n } else if (command === 'foreColor' && value) {\n Editor.addMark(editor, 'color', value);\n } else if (command === 'backColor' && value) {\n Editor.addMark(editor, 'backgroundColor', value);\n } else if (command === 'fontSize' && value) {\n Editor.addMark(editor, 'fontSize', value);\n } else if ((command === 'fontName' || command === 'fontFamily') && value) {\n Editor.addMark(editor, 'fontFamily', value);\n } else if (['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull'].includes(command)) {\n applyAlignmentCommand(editor, command);\n } else if (command === 'lineHeight' && value) {\n setBlockLineHeight(editor, value);\n } else if (command === 'insertUnorderedList') {\n toggleList(editor, 'bulleted-list');\n } else if (command === 'insertOrderedList') {\n toggleList(editor, 'numbered-list');\n }\n },\n [toggleBooleanMark, applyAlignmentCommand]\n );\n\n // Apply format command\n const applyFormat = useCallback(\n (command: FormatCommand, value?: string) => {\n const editor = editorRef.current;\n if (!editor) return;\n\n // If focus left the editable (toolbar control stole it), editor.selection\n // will be null. Restore the last known selection so the format applies correctly.\n // Preserve pending marks across the restore because Transforms.select resets\n // editor.marks, which would make the next toggle read stale leaf marks.\n if (!editor.selection && savedSelectionRef.current) {\n const pendingMarks = editor.marks;\n Transforms.select(editor, savedSelectionRef.current);\n if (pendingMarks) {\n editor.marks = pendingMarks;\n }\n }\n\n if (!editor.selection) return;\n\n try {\n dispatchFormatCommand(editor, command, value);\n // Update saved selection after format so subsequent format\n // changes (e.g. second font-family pick) use the post-format\n // selection. addMark/removeMark can split/merge text nodes,\n // making the pre-format selection stale. Meanwhile Slate-React's\n // onDOMSelectionChange may deselect the editor when focus is on\n // the panel, so the next applyFormat falls back to savedSelection.\n if (editor.selection) {\n savedSelectionRef.current = editor.selection;\n onFormatAppliedRef.current?.(editor.selection);\n }\n updateActiveStyles();\n onAnnouncementRef.current?.(generateFormatAnnouncement(command, value));\n } catch (error) {\n // Silently catch errors\n }\n },\n [updateActiveStyles, dispatchFormatCommand]\n );\n\n // Mark style helpers: apply or reset style/boolean marks to editor\n const applyDefaultMarks = useCallback(\n (editor: Editor): void => {\n Editor.addMark(editor, 'color', userDefaultStyles.color);\n Editor.addMark(editor, 'backgroundColor', userDefaultStyles.backgroundColor);\n Editor.addMark(editor, 'fontSize', userDefaultStyles.fontSize);\n Editor.addMark(editor, 'fontFamily', userDefaultStyles.fontFamily);\n if (userDefaultStyles.bold) Editor.addMark(editor, 'bold', true);\n if (userDefaultStyles.italic) Editor.addMark(editor, 'italic', true);\n if (userDefaultStyles.underline) Editor.addMark(editor, 'underline', true);\n if (userDefaultStyles.strikethrough) Editor.addMark(editor, 'strikethrough', true);\n },\n [userDefaultStyles]\n );\n\n const resetCollapsedCursorMarks = useCallback(\n (editor: Editor): void => {\n Editor.removeMark(editor, 'color');\n Editor.removeMark(editor, 'backgroundColor');\n Editor.removeMark(editor, 'fontSize');\n Editor.removeMark(editor, 'fontFamily');\n applyDefaultMarks(editor);\n },\n [applyDefaultMarks]\n );\n\n // Reset to user defaults\n const resetToDefault = useCallback(() => {\n const editor = editorRef.current;\n if (!editor) return;\n\n // Restore saved selection if focus left the editable (e.g. clicking reset button)\n if (!editor.selection && savedSelectionRef.current) {\n Transforms.select(editor, savedSelectionRef.current);\n }\n\n if (!editor.selection) return;\n\n try {\n const hasSelection = !Range.isCollapsed(editor.selection);\n\n if (isLinkActive(editor)) {\n unwrapLink(editor);\n }\n\n // Remove all boolean marks first\n Editor.removeMark(editor, 'bold');\n Editor.removeMark(editor, 'italic');\n Editor.removeMark(editor, 'underline');\n Editor.removeMark(editor, 'strikethrough');\n\n if (hasSelection) {\n // For a range selection: restore all style marks and block properties\n applyDefaultMarks(editor);\n Transforms.setNodes(\n editor,\n { align: userDefaultStyles.textAlign, lineHeight: userDefaultStyles.lineHeight },\n { match: n => !Editor.isEditor(n) && SlateElement.isElement(n) }\n );\n } else {\n // For a collapsed cursor: remove all marks then apply defaults as pending marks\n resetCollapsedCursorMarks(editor);\n }\n\n setActiveTextStyles(userDefaultStyles);\n updateActiveStyles();\n } catch (error) {\n // Silently catch errors\n }\n }, [userDefaultStyles, applyDefaultMarks, resetCollapsedCursorMarks, updateActiveStyles]);\n\n // Link helpers\n const isInLink = useCallback(() => {\n const editor = editorRef.current;\n return editor ? isLinkActive(editor) : false;\n }, []);\n\n const getLinkInfo = useCallback((): LinkInfo | null => {\n const editor = editorRef.current;\n if (!editor) return null;\n // If cursor is inside an existing link, return its info\n const activeLink = getActiveLink(editor);\n if (activeLink) return activeLink;\n // Otherwise return selected text so the popover can prefill the link text field\n const selectedText = getSelectedText(editor);\n if (selectedText) return { url: '', text: selectedText };\n return null;\n }, []);\n\n const createOrUpdateLink = useCallback(\n (url: string, text?: string) => {\n const editor = editorRef.current;\n if (!editor) return;\n\n try {\n // Restore saved selection if focus left the editable (e.g. typing in the link popover URL input).\n // Use try/catch in case savedSelectionRef is stale (e.g. after content reset via undo).\n if (!editor.selection && savedSelectionRef.current) {\n try {\n Transforms.select(editor, savedSelectionRef.current);\n } catch {\n // Stale selection \u2014 fall back to selecting the full document\n savedSelectionRef.current = null;\n Transforms.select(editor, {\n anchor: Editor.start(editor, []),\n focus: Editor.end(editor, []),\n });\n }\n }\n\n if (isLinkActive(editor)) {\n unwrapLink(editor);\n }\n insertLink(editor, url, text);\n updateActiveStyles();\n } catch (error) {\n // Silently catch errors\n }\n },\n [updateActiveStyles]\n );\n\n const removeLink = useCallback(() => {\n const editor = editorRef.current;\n if (!editor) return;\n\n try {\n unwrapLink(editor);\n updateActiveStyles();\n } catch (error) {\n // Silently catch errors\n }\n }, [updateActiveStyles]);\n\n // Ref-based callback so EditorPanel can register its link popover opener\n // and InnerEditor can call it via Cmd+K without prop drilling.\n const openLinkPopoverRef = useRef<() => void>(() => {});\n const openLinkPopover = useCallback(() => {\n openLinkPopoverRef.current();\n }, []);\n const registerOpenLinkPopover = useCallback((fn: () => void) => {\n openLinkPopoverRef.current = fn;\n }, []);\n\n // Ref-based callback so EditorPanel can call stepFontSize (implemented in InnerEditor)\n // for per-node font size increment/decrement in mixed selections.\n const stepFontSizeRef = useRef<(delta: number) => void>(() => {});\n const stepFontSize = useCallback((delta: number) => {\n stepFontSizeRef.current(delta);\n }, []);\n const registerStepFontSize = useCallback((fn: (delta: number) => void) => {\n stepFontSizeRef.current = fn;\n }, []);\n\n // Same pattern for line spacing: per-block increment/decrement in mixed selections.\n const stepLineSpacingRef = useRef<(delta: number) => void>(() => {});\n const stepLineSpacing = useCallback((delta: number) => {\n stepLineSpacingRef.current(delta);\n }, []);\n const registerStepLineSpacing = useCallback((fn: (delta: number) => void) => {\n stepLineSpacingRef.current = fn;\n }, []);\n\n // Callback invoked after each applyFormat with the post-format selection.\n // PureRichText registers this to keep preEditSelection up-to-date so that\n // Escape-from-panel restores the correct caret position after format ops.\n const onFormatAppliedRef = useRef<((selection: Editor['selection']) => void) | null>(null);\n const registerOnFormatApplied = useCallback((fn: (selection: Editor['selection']) => void) => {\n onFormatAppliedRef.current = fn;\n }, []);\n\n // Screenreader announcement callback, registered by InnerEditor.\n const onAnnouncementRef = useRef<((message: string) => void) | null>(null);\n const registerAnnouncement = useCallback((fn: (message: string) => void) => {\n onAnnouncementRef.current = fn;\n }, []);\n\n const contextValue: PureRichTextContextValue = useMemo(\n () => ({\n activeTextStyles,\n userDefaultStyles,\n editor: editorRef.current,\n setEditor,\n updateActiveStyles,\n saveSelection,\n applyFormat,\n resetToDefault,\n stepFontSize,\n registerStepFontSize,\n stepLineSpacing,\n registerStepLineSpacing,\n registerOnFormatApplied,\n registerAnnouncement,\n openLinkPopover,\n registerOpenLinkPopover,\n isInLink,\n getLinkInfo,\n createOrUpdateLink,\n removeLink,\n }),\n [\n activeTextStyles,\n userDefaultStyles,\n setEditor,\n updateActiveStyles,\n saveSelection,\n applyFormat,\n resetToDefault,\n stepFontSize,\n registerStepFontSize,\n stepLineSpacing,\n registerStepLineSpacing,\n registerOnFormatApplied,\n registerAnnouncement,\n openLinkPopover,\n registerOpenLinkPopover,\n isInLink,\n getLinkInfo,\n createOrUpdateLink,\n removeLink,\n ]\n );\n\n return <PureRichTextContext.Provider value={contextValue}>{children}</PureRichTextContext.Provider>;\n}\n", "\nimport * as defaultImport from \"@splunk/react-ui/ScreenReaderContent\";\nexport * from \"@splunk/react-ui/ScreenReaderContent\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "/**\n * FormatButton Component\n *\n * A styled button for formatting actions in the rich text editor toolbar.\n */\n\nimport React from 'react';\nimport styled from 'styled-components';\nimport { variables } from '@splunk/themes';\nimport ScreenReaderContent from '@splunk/react-ui/ScreenReaderContent';\n\nconst StyledButton = styled.button<{ $isActive?: boolean }>`\n min-width: 24px;\n height: 24px;\n width: 24px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n border: 1px solid transparent;\n background: ${props => (props.$isActive ? variables.interactiveColorOverlaySelected : 'transparent')};\n cursor: pointer;\n transition: all 0.2s ease;\n\n svg {\n fill: ${props => (props.$isActive ? variables.contentColorActive : variables.contentColorMuted)};\n width: 16px;\n height: 16px;\n transition: fill 0.2s ease;\n }\n\n &:hover {\n background: ${variables.interactiveColorOverlaySelected};\n\n svg {\n fill: ${variables.contentColorActive};\n }\n }\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n`;\n\nexport interface FormatButtonProps {\n /** Icon to display in the button */\n icon: React.ReactNode;\n /** Whether the format is currently active */\n isActive?: boolean;\n /** Click handler */\n onClick: () => void;\n /** Tooltip title */\n title: string;\n /** Accessible label for screen readers */\n ariaLabel?: string;\n /** Whether the button is disabled */\n disabled?: boolean;\n}\n\nexport const FormatButton: React.FC<FormatButtonProps> = ({\n icon,\n isActive = false,\n onClick,\n title,\n ariaLabel,\n disabled = false,\n}) => {\n const handleMouseDown = (e: React.MouseEvent): void => {\n // Prevent the button click from causing the contentEditable to lose focus\n // This preserves the selection/cursor position\n e.preventDefault();\n };\n\n return (\n <StyledButton\n $isActive={isActive}\n onClick={onClick}\n onMouseDown={handleMouseDown}\n title={title}\n type=\"button\"\n disabled={disabled}\n >\n {icon}\n {ariaLabel && <ScreenReaderContent>{ariaLabel}</ScreenReaderContent>}\n </StyledButton>\n );\n};\n\nexport default FormatButton;\n", "\nimport * as defaultImport from \"@splunk/react-ui/ControlGroup\";\nexport * from \"@splunk/react-ui/ControlGroup\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Select\";\nexport * from \"@splunk/react-ui/Select\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "/**\n * FontSelector Component\n *\n * A font family selector with support for preloaded system fonts.\n * MVP version - web fonts support will be added in future releases.\n */\n\nimport React, { useCallback } from 'react';\nimport styled from 'styled-components';\nimport ControlGroup from '@splunk/react-ui/ControlGroup';\nimport Select from '@splunk/react-ui/Select';\nimport { PRELOADED_FONTS } from '../types';\n\n// ============================================\n// Styled Components - minimal\n// ============================================\n\nconst FontSelectorContainer = styled.div`\n display: flex;\n align-items: center;\n gap: 4px;\n width: 100%;\n`;\n\nconst SelectWrapper = styled.div`\n flex: 1;\n width: 100%;\n min-width: 0;\n\n /* Target Select component wrapper */\n & > div {\n width: 100%;\n }\n\n /* Target the actual select button */\n button {\n width: 100%;\n }\n`;\n\n// ============================================\n// Component Props\n// ============================================\n\ninterface FontSelectorProps {\n value: string;\n onChange: (fontFamily: string) => void;\n onBeforeChange?: () => void;\n}\n\n// ============================================\n// Component\n// ============================================\n\nexport const FontSelector: React.FC<FontSelectorProps> = ({ value, onChange, onBeforeChange }) => {\n const handleFontChange = useCallback(\n (_e: React.SyntheticEvent, { value: val }: { value: string }) => {\n onChange(val);\n },\n [onChange]\n );\n\n // Save selection when user clicks to open the dropdown (before focus is lost)\n const handleMouseDown = useCallback(() => {\n if (onBeforeChange) {\n onBeforeChange();\n }\n }, [onBeforeChange]);\n\n // Empty value indicates mixed fonts in selection - show placeholder\n const isMixed = !value;\n const displayValue = isMixed ? '' : value;\n const placeholder = isMixed ? 'Mixed fonts' : undefined;\n\n return (\n <ControlGroup label=\"Font family\" labelPosition=\"top\">\n <FontSelectorContainer onMouseDownCapture={handleMouseDown}>\n <SelectWrapper>\n <Select\n value={displayValue}\n onChange={handleFontChange}\n placeholder={placeholder}\n style={{ width: '100%' }}\n >\n {PRELOADED_FONTS.map(font => (\n <Select.Option key={font} label={font} value={font} />\n ))}\n </Select>\n </SelectWrapper>\n </FontSelectorContainer>\n </ControlGroup>\n );\n};\n\nexport default FontSelector;\n", "\nimport * as defaultImport from \"react-dom\";\nexport * from \"react-dom\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Button\";\nexport * from \"@splunk/react-ui/Button\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/RadioBar\";\nexport * from \"@splunk/react-ui/RadioBar\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Color\";\nexport * from \"@splunk/react-ui/Color\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Text\";\nexport * from \"@splunk/react-ui/Text\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Number\";\nexport * from \"@splunk/react-ui/Number\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Popover\";\nexport * from \"@splunk/react-ui/Popover\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/Chain\";\nexport * from \"@splunk/react-icons/Chain\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/List\";\nexport * from \"@splunk/react-icons/List\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/ListNumbered\";\nexport * from \"@splunk/react-icons/ListNumbered\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextBBold\";\nexport * from \"@splunk/react-icons/TextBBold\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextIItalic\";\nexport * from \"@splunk/react-icons/TextIItalic\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextUUnderline\";\nexport * from \"@splunk/react-icons/TextUUnderline\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextSStrikethrough\";\nexport * from \"@splunk/react-icons/TextSStrikethrough\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextAlignLeft\";\nexport * from \"@splunk/react-icons/TextAlignLeft\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextAlignCenter\";\nexport * from \"@splunk/react-icons/TextAlignCenter\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextAlignRight\";\nexport * from \"@splunk/react-icons/TextAlignRight\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextAlignTop\";\nexport * from \"@splunk/react-icons/TextAlignTop\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextAlignVerticalCenter\";\nexport * from \"@splunk/react-icons/TextAlignVerticalCenter\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextAlignBottom\";\nexport * from \"@splunk/react-icons/TextAlignBottom\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/ArrowTurnBackLeft\";\nexport * from \"@splunk/react-icons/ArrowTurnBackLeft\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import styled from 'styled-components';\nimport { variables } from '@splunk/themes';\nimport Button from '@splunk/react-ui/Button';\n\nexport const EditorContainer = styled.div`\n display: flex;\n flex-direction: column;\n width: 100%;\n max-width: 100%;\n overflow-x: hidden;\n gap: 8px;\n`;\n\nexport const Row = styled.div`\n display: flex;\n gap: 4px;\n align-items: center;\n width: 100%;\n`;\n\nexport const ColorRow = styled.div`\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 4px;\n width: 100%;\n\n /* Ensure grid children stay within bounds */\n & > * {\n min-width: 0;\n }\n\n /* Make Color component fill its container properly */\n & [data-test='color'] {\n width: 100%;\n max-width: 100%;\n\n /* Inner flex container */\n & > div {\n width: 100%;\n max-width: 100%;\n display: flex;\n\n /* Text input wrapper - fill remaining space after swatch */\n & > div:last-child {\n flex: 1 1 auto;\n min-width: 0;\n max-width: calc(100% - 40px);\n\n /* The actual input inside */\n & input {\n width: 100%;\n }\n }\n }\n }\n`;\n\nexport const ButtonRow = styled.div`\n display: flex;\n gap: 4px;\n align-items: center;\n flex-wrap: wrap;\n width: 100%;\n justify-content: space-between;\n`;\n\nexport const LineSpacingWrapper = styled.div`\n position: relative;\n width: 100%;\n\n /* Make the Number component fill the width */\n & > div {\n width: 100%;\n }\n\n /* Style the % to appear right after the number */\n & > span {\n position: absolute;\n left: 42px; /* Position right after typical 3-digit number */\n top: 50%;\n transform: translateY(-50%);\n pointer-events: none;\n color: ${variables.contentColorDefault};\n font-size: 14px;\n }\n`;\n\n// Wrapper for Color component when selection has mixed values.\n// Makes the hex input text invisible (replaced by \"Mixed\" label) while\n// keeping the swatch and input fully interactive and focusable.\nexport const MixedLabel = styled.div`\n position: absolute;\n left: 40px;\n top: 50%;\n transform: translateY(-50%);\n pointer-events: none;\n color: ${variables.contentColorDefault};\n font-size: 14px;\n`;\n\nexport const MixedColorWrapper = styled.div<{ $isMixed?: boolean }>`\n position: relative;\n\n ${props =>\n props.$isMixed &&\n `\n & [data-test=\"color\"] input {\n color: transparent;\n caret-color: transparent;\n }\n & [data-test=\"color\"] input:focus {\n color: inherit;\n caret-color: auto;\n }\n `}\n\n &:focus-within ${MixedLabel} {\n display: none;\n }\n`;\n\n// Styled button to match Figma design - square with rounded corners\nexport const FormatToggleButton = styled(Button)<{ $isActive?: boolean }>`\n && {\n min-width: 32px;\n height: 32px;\n padding: 0;\n border-radius: 8px;\n background: ${props => (props.$isActive ? variables.interactiveColorOverlaySelected : 'transparent')};\n border: 1px solid ${props => (props.$isActive ? variables.borderColor : 'transparent')};\n\n &:hover {\n background: ${variables.interactiveColorOverlayHover};\n }\n\n &:focus-visible {\n box-shadow: 0 0 0 2px ${variables.focusColor};\n }\n\n svg {\n width: 16px;\n height: 16px;\n fill: ${props => (props.$isActive ? variables.contentColorActive : variables.contentColorMuted)};\n }\n }\n`;\n\nexport const AlignmentSection = styled.div`\n display: flex;\n gap: 12px;\n width: 100%;\n`;\n\nexport const HorizontalAlignmentRadioBar = styled.div`\n flex: 4;\n min-width: 0;\n\n /* Make RadioBar fill width and buttons expand equally */\n & > div {\n width: 100%;\n\n & > label {\n flex: 1;\n }\n }\n`;\n\nexport const VerticalAlignmentRadioBar = styled.div`\n flex: 3;\n min-width: 0;\n\n /* Make RadioBar fill width and buttons expand equally */\n & > div {\n width: 100%;\n\n & > label {\n flex: 1;\n }\n }\n`;\n\nexport const LinkPopoverContent = styled.div`\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-width: 280px;\n`;\n", "// Portal target for PureRichText - portals into config panel or sidebar\nexport const getEditorPanelTarget = (): Element | null => {\n // First try config panel (from dynamic-editors richtext editor)\n const configPanelTarget = document.querySelector('[data-test=\"editor-richTextContent\"]');\n if (configPanelTarget) {\n return configPanelTarget;\n }\n // Fallback to sidebar target\n return document.querySelector('[data-test=\"editor-purerichtext\"]');\n};\n\nexport const FONT_SIZE_OPTIONS = [\n { label: 'Extra small', value: '10' },\n { label: 'Small', value: '12' },\n { label: 'Default', value: '14' },\n { label: 'Large', value: '16' },\n { label: 'Extra large', value: '20' },\n] as const;\n\nexport const getFontSizePreset = (fontSize: number): string => {\n const preset = FONT_SIZE_OPTIONS.find(p => p.value === String(fontSize));\n return preset ? preset.value : 'custom';\n};\n", "import { useCallback, useEffect, useState, useRef } from 'react';\nimport {\n focusActiveEditable,\n setSuppressBlurDeactivation,\n isSuppressBlurDeactivation,\n} from '../../activeInstance';\n\ninterface UseLinkHandlersParams {\n isInLink: (() => boolean) | undefined;\n getLinkInfo: (() => { text: string; url: string } | null) | undefined;\n createOrUpdateLink: ((url: string, text?: string) => void) | undefined;\n removeLink: (() => void) | undefined;\n}\n\n// Hook for link popover state and handlers\nexport function useLinkHandlers(handlers: UseLinkHandlersParams) {\n const { isInLink, getLinkInfo, createOrUpdateLink, removeLink } = handlers;\n const [linkPopoverOpen, setLinkPopoverOpen] = useState(false);\n const [linkText, setLinkText] = useState('');\n const [linkUrl, setLinkUrl] = useState('');\n const linkButtonRef = useRef<HTMLButtonElement>(null);\n const linkPopoverRef = useRef<HTMLDivElement>(null);\n const linkIsActive = isInLink?.() || false;\n\n const handleLinkButtonClick = useCallback(() => {\n const linkInfo = getLinkInfo?.();\n if (linkInfo) {\n setLinkText(linkInfo.text);\n setLinkUrl(linkInfo.url);\n } else {\n setLinkText('');\n setLinkUrl('');\n }\n setSuppressBlurDeactivation(true);\n setLinkPopoverOpen(true);\n }, [getLinkInfo]);\n\n const resetLinkState = useCallback(() => {\n setSuppressBlurDeactivation(false);\n setLinkPopoverOpen(false);\n setLinkText('');\n setLinkUrl('');\n }, []);\n\n const handleLinkPopoverClose = useCallback(() => {\n resetLinkState();\n setTimeout(() => {\n focusActiveEditable();\n }, 0);\n }, [resetLinkState]);\n\n const handleLinkSave = useCallback(() => {\n if (linkUrl && createOrUpdateLink) {\n createOrUpdateLink(linkUrl, linkText || undefined);\n }\n resetLinkState();\n setTimeout(() => {\n linkButtonRef.current?.focus();\n }, 0);\n }, [linkUrl, linkText, createOrUpdateLink, resetLinkState]);\n\n const handleLinkRemove = useCallback(() => {\n if (removeLink) {\n removeLink();\n }\n resetLinkState();\n setTimeout(() => {\n linkButtonRef.current?.focus();\n }, 0);\n }, [removeLink, resetLinkState]);\n\n const handleLinkKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleLinkSave();\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n e.nativeEvent.stopImmediatePropagation();\n resetLinkState();\n // Return focus to the link button in the config panel\n setTimeout(() => {\n linkButtonRef.current?.focus();\n }, 0);\n }\n },\n [handleLinkSave, resetLinkState]\n );\n\n // Auto-focus the first input when the link popover opens\n useEffect(() => {\n if (!linkPopoverOpen) return undefined;\n // The Popover renders asynchronously (portaled), so wait a frame\n const timer = setTimeout(() => {\n linkPopoverRef.current?.querySelector<HTMLInputElement>('input')?.focus();\n }, 50);\n return () => clearTimeout(timer);\n }, [linkPopoverOpen]);\n\n // Reset the global suppress flag if the component unmounts while the popover is open\n // (e.g. leaving edit mode or switching panels). Without this, the flag stays true\n // and subsequent editor blur events would be skipped.\n useEffect(\n () => () => {\n if (isSuppressBlurDeactivation()) {\n setSuppressBlurDeactivation(false);\n }\n },\n []\n );\n\n return {\n linkIsActive,\n linkPopoverOpen,\n linkPopoverRef,\n linkText,\n linkUrl,\n linkButtonRef,\n setLinkText,\n setLinkUrl,\n handleLinkButtonClick,\n handleLinkPopoverClose,\n handleLinkSave,\n handleLinkRemove,\n handleLinkKeyDown,\n };\n}\n", "import { useCallback, useEffect, useRef, useState } from 'react';\nimport { FormatCommand } from '../../types';\n\n// Hook for line spacing state and handlers\nexport function useLineSpacing(\n lineHeight: string,\n displayLineHeight: string | undefined,\n isLineHeightMixed: boolean,\n applyFormat: ((command: FormatCommand, value?: string) => void) | undefined,\n handleFormat: (command: FormatCommand, value?: string) => void,\n stepLineSpacing?: (delta: number) => void\n) {\n const [lineSpacingPercent, setLineSpacingPercent] = useState<number>(() => {\n const num = Number.parseFloat(lineHeight);\n return Number.isNaN(num) ? 100 : Math.round(num * 100);\n });\n\n // Tracks whether the user has typed a value (overrides Mixed display)\n const dirtyRef = useRef(false);\n const [isDirty, setIsDirty] = useState(false);\n\n // Sync line spacing from displayStyles or prop\n useEffect(() => {\n if (isLineHeightMixed && !dirtyRef.current) return;\n\n const lh = displayLineHeight || lineHeight;\n const num = Number.parseFloat(String(lh));\n if (!Number.isNaN(num)) {\n setLineSpacingPercent(Math.round(num * 100));\n }\n dirtyRef.current = false;\n setIsDirty(false);\n }, [displayLineHeight, lineHeight, isLineHeightMixed]);\n\n const handleLineSpacingChange = useCallback(\n (_e: unknown, data: { value?: number; reason?: 'input' | 'stepButton' }) => {\n const { value, reason } = data;\n if (value !== undefined && value !== null) {\n setLineSpacingPercent(value);\n if (reason === 'input') {\n dirtyRef.current = true;\n setIsDirty(true);\n }\n if (reason === 'stepButton' && applyFormat) {\n // When mixed, use stepLineSpacing to step each block independently\n if (isLineHeightMixed && stepLineSpacing) {\n const target = (_e as React.MouseEvent)?.currentTarget;\n const testId =\n (target as HTMLElement)?.getAttribute?.('data-test') ||\n (target as HTMLElement)?.getAttribute?.('data-testid') ||\n '';\n const isDecrement = testId === 'decrement' || testId.includes('down');\n stepLineSpacing(isDecrement ? -1 : 1);\n return;\n }\n const newLineHeight = Math.max(1, value / 100).toFixed(2);\n handleFormat('lineHeight', newLineHeight);\n }\n }\n },\n [applyFormat, handleFormat, isLineHeightMixed, stepLineSpacing]\n );\n\n const handleLineSpacingBlur = useCallback(() => {\n if (!dirtyRef.current && isLineHeightMixed) return;\n dirtyRef.current = false;\n setIsDirty(false);\n const multiplier = Math.max(1, lineSpacingPercent / 100);\n handleFormat('lineHeight', String(multiplier));\n }, [lineSpacingPercent, handleFormat, isLineHeightMixed]);\n\n // When mixed and not dirty, show undefined (placeholder \"Mixed\").\n // When dirty (user typed a value), show the typed value.\n const showMixed = isLineHeightMixed && !isDirty;\n\n return {\n lineSpacingPercent,\n showMixed,\n handleLineSpacingChange,\n handleLineSpacingBlur,\n };\n}\n", "/**\n * EditorPanel Component\n *\n * Editor panel toolbar for the Slate.js-based rich text editor.\n * Portals to data-test=\"editor-purerichtext\" in the editor sidebar.\n */\n\nimport React, { useCallback, useEffect, useState, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport Button from '@splunk/react-ui/Button';\nimport RadioBar from '@splunk/react-ui/RadioBar';\nimport Color, { defaultPalette } from '@splunk/react-ui/Color';\nimport Text from '@splunk/react-ui/Text';\nimport NumberInput from '@splunk/react-ui/Number';\nimport Select from '@splunk/react-ui/Select';\nimport ControlGroup from '@splunk/react-ui/ControlGroup';\nimport Popover from '@splunk/react-ui/Popover';\nimport Chain from '@splunk/react-icons/Chain';\nimport List from '@splunk/react-icons/List';\nimport ListNumbered from '@splunk/react-icons/ListNumbered';\nimport TextBBold from '@splunk/react-icons/TextBBold';\nimport TextIItalic from '@splunk/react-icons/TextIItalic';\nimport TextUUnderline from '@splunk/react-icons/TextUUnderline';\nimport TextSStrikethrough from '@splunk/react-icons/TextSStrikethrough';\nimport TextAlignLeft from '@splunk/react-icons/TextAlignLeft';\nimport TextAlignCenter from '@splunk/react-icons/TextAlignCenter';\nimport TextAlignRight from '@splunk/react-icons/TextAlignRight';\nimport TextAlignTop from '@splunk/react-icons/TextAlignTop';\nimport TextAlignVerticalCenter from '@splunk/react-icons/TextAlignVerticalCenter';\nimport TextAlignBottom from '@splunk/react-icons/TextAlignBottom';\nimport ArrowTurnBackLeft from '@splunk/react-icons/ArrowTurnBackLeft';\nimport ScreenReaderContent from '@splunk/react-ui/ScreenReaderContent';\nimport { usePureRichTextOptional, ActiveTextStyles } from '../PureRichTextContext';\nimport { focusActiveEditable } from '../activeInstance';\nimport { DEFAULT_TEXT_STYLES, FormatCommand, VerticalAlign, TextAlign } from '../types';\nimport { FontSelector } from './FontSelector';\nimport {\n EditorContainer,\n Row,\n ColorRow,\n ButtonRow,\n LineSpacingWrapper,\n MixedColorWrapper,\n MixedLabel,\n FormatToggleButton,\n AlignmentSection,\n HorizontalAlignmentRadioBar,\n VerticalAlignmentRadioBar,\n LinkPopoverContent,\n} from './EditorPanelStyles';\nimport { getEditorPanelTarget, FONT_SIZE_OPTIONS, getFontSizePreset } from './editorPanelUtils';\nimport { useLinkHandlers } from './hooks/useLinkHandlers';\nimport { useLineSpacing } from './hooks/useLineSpacing';\n\n// TextAlignJustified is not available in the installed @splunk/react-icons version.\n// Inline SVG matching the Splunk icon style (24x24 viewBox, 1.5 stroke, currentColor).\nconst TextAlignJustified: React.FC = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M3 6h18M3 10h18M3 14h18M3 18h18\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n);\n\nconst preventDefaultMouseDown = (e: React.MouseEvent): void => e.preventDefault();\n\nconst focusMixedSwatch = (selector: string): void => {\n setTimeout(() => {\n document.querySelector<HTMLButtonElement>(selector)?.focus();\n }, 50);\n};\n\nexport interface EditorPanelProps {\n isEditMode: boolean;\n isActive?: boolean;\n fontColor?: string;\n fontSize?: number;\n lineHeight?: string;\n verticalAlign?: VerticalAlign;\n onVerticalAlignChange?: (align: VerticalAlign) => void;\n}\n\nexport const EditorPanel: React.FC<EditorPanelProps> = ({\n isEditMode,\n isActive = false,\n fontColor = '#ffffff',\n fontSize: fontSizeProp = 14,\n lineHeight = '1.5',\n verticalAlign: verticalAlignProp = 'top',\n onVerticalAlignChange,\n}) => {\n const portalTargetRef = useRef<HTMLElement | null>(null);\n // renderTick increments each time the portal target is found/cleared, triggering a re-render\n const [renderTick, forceUpdate] = React.useReducer((n: number) => n + 1, 0);\n const portalReady = renderTick >= 0 && portalTargetRef.current !== null;\n\n const contextValue = usePureRichTextOptional();\n const activeTextStyles: ActiveTextStyles = contextValue?.activeTextStyles || DEFAULT_TEXT_STYLES;\n const applyFormat = contextValue?.applyFormat;\n const resetToDefault = contextValue?.resetToDefault;\n const stepFontSize = contextValue?.stepFontSize;\n const stepLineSpacing = contextValue?.stepLineSpacing;\n const isInLink = contextValue?.isInLink;\n const getLinkInfo = contextValue?.getLinkInfo;\n const createOrUpdateLink = contextValue?.createOrUpdateLink;\n const removeLink = contextValue?.removeLink;\n const registerOpenLinkPopover = contextValue?.registerOpenLinkPopover;\n\n const [align, setAlign] = useState<TextAlign>('left');\n const [verticalAlign, setVerticalAlign] = useState<VerticalAlign>(verticalAlignProp);\n const [currentFontSize, setCurrentFontSize] = useState<number>(fontSizeProp);\n const [fontSizePreset, setFontSizePreset] = useState<string>(() => getFontSizePreset(fontSizeProp));\n const fontSizeDirtyRef = useRef(false);\n\n const {\n linkIsActive,\n linkPopoverOpen,\n linkPopoverRef,\n linkText,\n linkUrl,\n linkButtonRef,\n setLinkText,\n setLinkUrl,\n handleLinkButtonClick,\n handleLinkPopoverClose,\n handleLinkSave,\n handleLinkRemove,\n handleLinkKeyDown,\n } = useLinkHandlers({\n isInLink,\n getLinkInfo,\n createOrUpdateLink,\n removeLink,\n });\n\n useEffect(() => {\n registerOpenLinkPopover?.(handleLinkButtonClick);\n }, [registerOpenLinkPopover, handleLinkButtonClick]);\n\n const wasMouseRef = useRef(false);\n\n const handleFormat = useCallback(\n (command: FormatCommand, value?: string) => {\n if (!applyFormat) return;\n applyFormat(command, value);\n if (wasMouseRef.current) {\n setTimeout(() => {\n focusActiveEditable();\n }, 0);\n }\n },\n [applyFormat]\n );\n\n const isLineHeightMixed = activeTextStyles.isMixed?.lineHeight === true;\n\n const {\n lineSpacingPercent,\n showMixed: showLineSpacingMixed,\n handleLineSpacingChange,\n handleLineSpacingBlur,\n } = useLineSpacing(\n lineHeight,\n activeTextStyles.lineHeight,\n isLineHeightMixed,\n applyFormat,\n handleFormat,\n stepLineSpacing\n );\n\n const handleFontFamilyChange = useCallback(\n (fontFamily: string) => handleFormat('fontName', fontFamily),\n [handleFormat]\n );\n\n useEffect(() => {\n if (!isEditMode) {\n portalTargetRef.current = null;\n forceUpdate();\n return undefined;\n }\n\n const findTarget = (): void => {\n const target = getEditorPanelTarget();\n if (target && target !== portalTargetRef.current) {\n portalTargetRef.current = target as HTMLElement;\n forceUpdate();\n }\n };\n\n findTarget();\n const interval = setInterval(findTarget, 100);\n\n return (): void => {\n clearInterval(interval);\n portalTargetRef.current = null;\n };\n }, [isEditMode]);\n\n useEffect(() => {\n if (activeTextStyles.textAlign) {\n setAlign(activeTextStyles.textAlign);\n }\n }, [activeTextStyles.textAlign]);\n\n useEffect(() => {\n setVerticalAlign(verticalAlignProp);\n }, [verticalAlignProp]);\n\n useEffect(() => {\n fontSizeDirtyRef.current = false;\n if (activeTextStyles.fontSize) {\n const size = Number.parseInt(String(activeTextStyles.fontSize), 10) || 14;\n setCurrentFontSize(size);\n setFontSizePreset(getFontSizePreset(size));\n }\n }, [activeTextStyles.fontSize]);\n\n const handleVerticalAlignChange = useCallback(\n (newAlign: VerticalAlign) => {\n setVerticalAlign(newAlign);\n onVerticalAlignChange?.(newAlign);\n },\n [onVerticalAlignChange]\n );\n\n const isMixedStyles = activeTextStyles.isMixed || {};\n const isColorMixed = isMixedStyles.color === true;\n const isHighlightMixed = isMixedStyles.backgroundColor === true;\n const isFontSizeMixed = isMixedStyles.fontSize === true;\n const isFontFamilyMixed = isMixedStyles.fontFamily === true;\n\n const displayTextColor = isColorMixed ? '' : activeTextStyles.color || fontColor;\n const displayHighlightColor = isHighlightMixed ? '' : (activeTextStyles.backgroundColor ?? 'transparent');\n const displayFontFamily = isFontFamilyMixed ? '' : activeTextStyles.fontFamily || 'Splunk Data Sans';\n\n const editorContainerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!isEditMode || !isActive) return undefined;\n\n const handleMouseDown = (e: MouseEvent): void => {\n const container = editorContainerRef.current;\n if (!container) return;\n const target = e.target as HTMLElement;\n if (!container.contains(target)) return;\n wasMouseRef.current = true;\n const tag = target.tagName;\n if (tag !== 'INPUT' && tag !== 'TEXTAREA') {\n e.preventDefault();\n }\n };\n\n const handleKeyDown = (e: KeyboardEvent): void => {\n const container = editorContainerRef.current;\n if (!container) return;\n const target = e.target as HTMLElement;\n if (container.contains(target)) {\n wasMouseRef.current = false;\n }\n };\n\n document.addEventListener('mousedown', handleMouseDown, true);\n document.addEventListener('keydown', handleKeyDown, true);\n return () => {\n document.removeEventListener('mousedown', handleMouseDown, true);\n document.removeEventListener('keydown', handleKeyDown, true);\n };\n }, [isEditMode, isActive]);\n\n useEffect(() => {\n if (!isEditMode || !isActive) return undefined;\n\n const FOCUS_RING_ATTR = 'data-trap-focused';\n let lastFocused: HTMLElement | null = null;\n\n const applyFocusRing = (el: HTMLElement): void => {\n removeFocusRing();\n if (el.getAttribute('tabindex') === '-1') {\n el.setAttribute(FOCUS_RING_ATTR, 'true');\n // eslint-disable-next-line no-param-reassign\n el.style.outline = '2px solid #3b82f6';\n // eslint-disable-next-line no-param-reassign\n el.style.outlineOffset = '-2px';\n // eslint-disable-next-line no-param-reassign\n el.style.position = 'relative';\n // eslint-disable-next-line no-param-reassign\n el.style.zIndex = '1';\n lastFocused = el;\n }\n };\n\n const removeFocusRing = (): void => {\n if (lastFocused?.hasAttribute(FOCUS_RING_ATTR)) {\n lastFocused.removeAttribute(FOCUS_RING_ATTR);\n lastFocused.style.outline = '';\n lastFocused.style.outlineOffset = '';\n lastFocused.style.position = '';\n lastFocused.style.zIndex = '';\n lastFocused = null;\n }\n };\n\n const handleBlurCleanup = (): void => {\n removeFocusRing();\n };\n\n const getConfigPanel = (): HTMLElement | null => editorContainerRef.current;\n\n const getFocusableElements = (panel: HTMLElement): HTMLElement[] => {\n const selector =\n 'button:not([disabled]):not([aria-disabled=\"true\"]), ' +\n 'input:not([disabled]), ' +\n 'select:not([disabled]), ' +\n 'textarea:not([disabled]), ' +\n 'a[href]:not([disabled])';\n return Array.from(panel.querySelectorAll<HTMLElement>(selector)).filter(\n el => el.offsetParent !== null && el.offsetWidth > 0 && el.offsetHeight > 0\n );\n };\n\n const handleConfigPanelKeyDown = (e: KeyboardEvent): void => {\n const target = e.target as HTMLElement;\n\n // Escape is handled by PureRichText's document keydown handler which\n // sets isTextEditing=true before focusing. Only clean up the focus ring here.\n if (e.key === 'Escape') {\n removeFocusRing();\n return;\n }\n\n // Tab / Shift+Tab: manually move focus within our panel so that\n // tabindex=\"-1\" step buttons are reachable. At the boundaries, let\n // the browser's default Tab behaviour move focus to the next/previous\n // section in the config sidebar (no wrapping).\n const configPanel = getConfigPanel();\n if (!configPanel) return;\n if (!configPanel.contains(target)) return;\n if (e.key !== 'Tab') return;\n\n const focusable = getFocusableElements(configPanel);\n if (focusable.length === 0) return;\n\n const currentIndex = focusable.indexOf(target);\n if (currentIndex === -1) {\n removeFocusRing();\n return;\n }\n if (e.shiftKey) {\n if (currentIndex <= 0) {\n removeFocusRing();\n return;\n }\n e.preventDefault();\n const nextEl = focusable[currentIndex - 1];\n nextEl.focus();\n applyFocusRing(nextEl);\n } else {\n if (currentIndex >= focusable.length - 1) {\n removeFocusRing();\n return;\n }\n e.preventDefault();\n const nextEl = focusable[currentIndex + 1];\n nextEl.focus();\n applyFocusRing(nextEl);\n }\n };\n\n document.addEventListener('keydown', handleConfigPanelKeyDown, true);\n document.addEventListener('focusout', handleBlurCleanup, true);\n return () => {\n document.removeEventListener('keydown', handleConfigPanelKeyDown, true);\n document.removeEventListener('focusout', handleBlurCleanup, true);\n removeFocusRing();\n };\n }, [isEditMode, isActive]);\n\n if (!isEditMode) return null;\n\n const editor = (\n <EditorContainer ref={editorContainerRef} data-test=\"editor-purerichtext-content\">\n <FontSelector value={displayFontFamily} onChange={handleFontFamilyChange} />\n <ControlGroup label=\"Font size\" labelPosition=\"top\">\n <Row style={{ gap: '12px' }}>\n <Select\n value={isFontSizeMixed ? undefined : fontSizePreset}\n placeholder={isFontSizeMixed ? 'Mixed' : undefined}\n onChange={(_e, { value: val }): void => {\n const preset = FONT_SIZE_OPTIONS.find(p => p.value === val);\n if (preset) {\n setCurrentFontSize(Number.parseInt(preset.value, 10));\n setFontSizePreset(val as string);\n handleFormat('fontSize', `${preset.value}px`);\n } else {\n setFontSizePreset('custom');\n }\n }}\n style={{ flex: 1, minWidth: 100 }}\n >\n {FONT_SIZE_OPTIONS.map(({ label, value }) => (\n <Select.Option key={value} label={label} value={value} />\n ))}\n <Select.Option label=\"Custom\" value=\"custom\" />\n </Select>\n <div style={{ width: '80px', flexShrink: 0 }}>\n <NumberInput\n aria-label=\"Font size in pixels\"\n value={isFontSizeMixed ? (undefined as unknown as number) : currentFontSize}\n onFocus={(): void => {\n fontSizeDirtyRef.current = false;\n }}\n onChange={(_e, { value: val, reason }): void => {\n if (reason === 'stepButton') {\n if (!stepFontSize) {\n if (val != null) {\n setCurrentFontSize(val);\n setFontSizePreset(getFontSizePreset(val));\n handleFormat('fontSize', `${val}px`);\n }\n return;\n }\n // Always use stepFontSize for step buttons -- it\n // correctly preserves the fake highlight for both\n // mixed and uniform font sizes.\n const target = (_e as React.MouseEvent)?.currentTarget;\n const testId =\n (target as HTMLElement)?.getAttribute?.('data-test') ||\n (target as HTMLElement)?.getAttribute?.('data-testid') ||\n '';\n const isDecrement = testId === 'decrement' || testId.includes('down');\n stepFontSize(isDecrement ? -2 : 2);\n if (wasMouseRef.current) {\n setTimeout(() => {\n focusActiveEditable();\n }, 0);\n }\n return;\n }\n if (val != null) {\n fontSizeDirtyRef.current = true;\n setCurrentFontSize(val);\n setFontSizePreset(getFontSizePreset(val));\n }\n }}\n onKeyDown={(e: React.KeyboardEvent): void => {\n if (e.key === 'Enter' && currentFontSize) {\n e.preventDefault();\n e.stopPropagation();\n fontSizeDirtyRef.current = false;\n handleFormat('fontSize', `${currentFontSize}px`);\n }\n if (isFontSizeMixed) {\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n stepFontSize?.(2);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n stepFontSize?.(-2);\n }\n }\n }}\n onBlur={(): void => {\n if (fontSizeDirtyRef.current && currentFontSize) {\n handleFormat('fontSize', `${currentFontSize}px`);\n }\n fontSizeDirtyRef.current = false;\n }}\n min={8}\n max={200}\n step={1}\n inline\n />\n </div>\n </Row>\n </ControlGroup>\n\n <ColorRow>\n <ControlGroup label=\"Font color\" labelPosition=\"top\">\n <MixedColorWrapper\n $isMixed={isColorMixed}\n onClick={(): void => {\n if (isColorMixed) focusMixedSwatch('[data-test=\"textbox-swatch\"]');\n }}\n >\n <Color\n value={displayTextColor}\n onChange={(data): void => handleFormat('foreColor', data.value || '')}\n style={{ width: '100%' }}\n />\n {isColorMixed && <MixedLabel>Mixed</MixedLabel>}\n </MixedColorWrapper>\n </ControlGroup>\n <ControlGroup label=\"Highlight color\" labelPosition=\"top\">\n <MixedColorWrapper\n $isMixed={isHighlightMixed}\n onClick={(): void => {\n if (isHighlightMixed) focusMixedSwatch('[data-test=\"textbox-swatch\"]');\n }}\n >\n <Color\n value={displayHighlightColor}\n onChange={(data): void => handleFormat('backColor', data.value || 'transparent')}\n palette={\n isHighlightMixed\n ? [...defaultPalette, 'transparent']\n : ['transparent', ...defaultPalette]\n }\n style={{ width: '100%' }}\n />\n {isHighlightMixed && <MixedLabel>Mixed</MixedLabel>}\n </MixedColorWrapper>\n </ControlGroup>\n </ColorRow>\n\n <ButtonRow>\n {[\n { isActive: activeTextStyles.bold, command: 'bold', icon: <TextBBold />, label: 'Bold' },\n {\n isActive: activeTextStyles.italic,\n command: 'italic',\n icon: <TextIItalic />,\n label: 'Italic',\n },\n {\n isActive: activeTextStyles.underline,\n command: 'underline',\n icon: <TextUUnderline />,\n label: 'Underline',\n },\n {\n isActive: activeTextStyles.strikethrough,\n command: 'strikethrough',\n icon: <TextSStrikethrough />,\n label: 'Strikethrough',\n },\n ].map(({ isActive: active, command, icon, label }) => (\n <FormatToggleButton\n key={command}\n $isActive={active}\n appearance=\"secondary\"\n onMouseDown={preventDefaultMouseDown}\n onClick={(): void => handleFormat(command as FormatCommand)}\n icon={icon}\n aria-label={label}\n />\n ))}\n <FormatToggleButton\n ref={linkButtonRef}\n $isActive={linkIsActive}\n appearance=\"secondary\"\n onMouseDown={preventDefaultMouseDown}\n onClick={handleLinkButtonClick}\n icon={<Chain />}\n aria-label=\"Link\"\n />\n <FormatToggleButton\n $isActive={activeTextStyles.listType === 'unordered'}\n appearance=\"secondary\"\n onMouseDown={preventDefaultMouseDown}\n onClick={(): void => handleFormat('insertUnorderedList')}\n icon={<List />}\n aria-label=\"Bulleted list\"\n />\n <FormatToggleButton\n $isActive={activeTextStyles.listType === 'ordered'}\n appearance=\"secondary\"\n onMouseDown={preventDefaultMouseDown}\n onClick={(): void => handleFormat('insertOrderedList')}\n icon={<ListNumbered />}\n aria-label=\"Numbered list\"\n />\n <FormatToggleButton\n $isActive={false}\n appearance=\"secondary\"\n onMouseDown={preventDefaultMouseDown}\n onClick={(): void => {\n resetToDefault?.();\n if (wasMouseRef.current) {\n setTimeout(() => {\n focusActiveEditable();\n }, 0);\n }\n }}\n icon={<ArrowTurnBackLeft />}\n aria-label=\"Reset to default\"\n />\n </ButtonRow>\n\n {/* Link Popover */}\n <Popover\n open={linkPopoverOpen}\n anchor={linkButtonRef.current}\n onRequestClose={handleLinkPopoverClose}\n >\n <LinkPopoverContent ref={linkPopoverRef} onKeyDown={handleLinkKeyDown}>\n <ControlGroup label=\"Text\" labelPosition=\"top\">\n <Text\n value={linkText}\n onChange={(_e, { value: v }): void => setLinkText(v)}\n placeholder=\"Link text\"\n />\n </ControlGroup>\n <ControlGroup label=\"URL\" labelPosition=\"top\">\n <Text\n value={linkUrl}\n onChange={(_e, { value: v }): void => setLinkUrl(v)}\n placeholder=\"https://...\"\n />\n </ControlGroup>\n <Row>\n <Button appearance=\"primary\" onClick={handleLinkSave} label=\"Save\" />\n {linkIsActive && <Button onClick={handleLinkRemove} label=\"Remove\" />}\n <Button onClick={handleLinkPopoverClose} label=\"Cancel\" />\n </Row>\n </LinkPopoverContent>\n </Popover>\n\n <ControlGroup label=\"Alignment\" labelPosition=\"top\">\n <AlignmentSection>\n <HorizontalAlignmentRadioBar>\n <RadioBar\n value={align}\n onChange={(_e, { value: val }): void => {\n const newAlign = val as TextAlign;\n setAlign(newAlign);\n if (newAlign === 'left') handleFormat('justifyLeft');\n else if (newAlign === 'center') handleFormat('justifyCenter');\n else if (newAlign === 'right') handleFormat('justifyRight');\n else if (newAlign === 'justify') handleFormat('justifyFull');\n }}\n >\n <RadioBar.Option\n value=\"left\"\n startAdornment={\n <>\n <TextAlignLeft />\n <ScreenReaderContent>Align left</ScreenReaderContent>\n </>\n }\n />\n <RadioBar.Option\n value=\"center\"\n startAdornment={\n <>\n <TextAlignCenter />\n <ScreenReaderContent>Align center</ScreenReaderContent>\n </>\n }\n />\n <RadioBar.Option\n value=\"right\"\n startAdornment={\n <>\n <TextAlignRight />\n <ScreenReaderContent>Align right</ScreenReaderContent>\n </>\n }\n />\n <RadioBar.Option\n value=\"justify\"\n startAdornment={\n <>\n <TextAlignJustified />\n <ScreenReaderContent>Justify</ScreenReaderContent>\n </>\n }\n />\n </RadioBar>\n </HorizontalAlignmentRadioBar>\n <VerticalAlignmentRadioBar>\n <RadioBar\n value={verticalAlign}\n onChange={(_e, { value: val }): void => {\n handleVerticalAlignChange(val as VerticalAlign);\n }}\n >\n <RadioBar.Option\n value=\"top\"\n startAdornment={\n <>\n <TextAlignTop />\n <ScreenReaderContent>Align top</ScreenReaderContent>\n </>\n }\n />\n <RadioBar.Option\n value=\"middle\"\n startAdornment={\n <>\n <TextAlignVerticalCenter />\n <ScreenReaderContent>Align middle</ScreenReaderContent>\n </>\n }\n />\n <RadioBar.Option\n value=\"bottom\"\n startAdornment={\n <>\n <TextAlignBottom />\n <ScreenReaderContent>Align bottom</ScreenReaderContent>\n </>\n }\n />\n </RadioBar>\n </VerticalAlignmentRadioBar>\n </AlignmentSection>\n </ControlGroup>\n <ControlGroup label=\"Line spacing\" labelPosition=\"top\">\n <div role=\"none\">\n <LineSpacingWrapper>\n <NumberInput\n aria-label=\"Line spacing percentage\"\n value={showLineSpacingMixed ? ('' as unknown as number) : lineSpacingPercent}\n onChange={handleLineSpacingChange}\n onBlur={handleLineSpacingBlur}\n onKeyDown={(e: React.KeyboardEvent): void => {\n if (e.key === 'Enter') {\n handleLineSpacingBlur();\n }\n if (isLineHeightMixed && stepLineSpacing) {\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n stepLineSpacing(1);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n stepLineSpacing(-1);\n }\n }\n }}\n min={100}\n max={300}\n step={10}\n roundTo={0}\n />\n {showLineSpacingMixed ? <span aria-hidden=\"true\">Mixed</span> : <span>%</span>}\n </LineSpacingWrapper>\n </div>\n </ControlGroup>\n </EditorContainer>\n );\n\n if (portalReady && isActive) {\n return createPortal(editor, portalTargetRef.current as HTMLElement);\n }\n\n return null;\n};\n\nexport default EditorPanel;\n", "import styled, { css } from 'styled-components';\nimport { mixins, variables } from '@splunk/themes';\nimport Button from '@splunk/react-ui/Button';\nimport { VerticalAlign } from './types';\n\nexport const PureRichTextContainer = styled.div<{\n $backgroundColor?: string;\n $verticalAlign?: VerticalAlign;\n $borderColor?: string;\n $borderWidth?: number;\n $borderStyle?: string;\n $borderRadius?: number;\n $padding: [number, number, number, number];\n $isTextEditing?: boolean;\n $hasEventHandlers?: boolean;\n}>`\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: ${props => {\n switch (props.$verticalAlign) {\n case 'top':\n return 'flex-start';\n case 'bottom':\n return 'flex-end';\n case 'middle':\n default:\n return 'center';\n }\n }};\n background-color: ${props => props.$backgroundColor || 'transparent'};\n border: ${props =>\n props.$borderWidth && props.$borderColor\n ? `${props.$borderWidth}px ${props.$borderStyle || 'solid'} ${props.$borderColor}`\n : 'none'};\n border-radius: ${props => (props.$borderRadius ? `${props.$borderRadius}px` : '0')};\n padding: ${props =>\n `${props.$padding[0]}px ${props.$padding[1]}px ${props.$padding[2]}px ${props.$padding[3]}px`};\n box-sizing: border-box;\n overflow: hidden;\n position: relative;\n /* Show an inset ring when actively editing text so the user can click the border to deactivate */\n ${props => props.$isTextEditing && `box-shadow: inset 0 0 0 2px ${variables.focusColor};`}\n /* When event handlers are bound (view mode), show pointer cursor to signal clickability */\n ${props =>\n props.$hasEventHandlers &&\n !props.$isTextEditing &&\n css`\n cursor: pointer;\n `}\n`;\n\n/**\n * Skip-link styled drilldown button shown when consumer has bound a richtext.click handler.\n * Mirrors the Markdown viz pattern so screen-reader / keyboard users can reach the click action.\n */\nexport const DrilldownButton = styled(Button)`\n ${mixins.skipLink()}\n /**\n * Override the secondary Button's transparent default so the skip-link is visible when focused.\n */\n &:not([disabled], [aria-disabled='true']) {\n background-color: ${variables.backgroundColorSection};\n }\n`;\n\nexport const EditorWrapper = styled.div<{\n $isEditMode: boolean;\n $isTextEditing: boolean;\n $lineHeight?: string;\n}>`\n width: 100%;\n min-height: 0;\n max-height: 100%;\n overflow: auto;\n cursor: ${props => (props.$isTextEditing ? 'text' : 'default')};\n\n /* Styling for the Slate editor */\n [data-slate-editor] {\n outline: none;\n min-height: 100%;\n }\n\n /* Underline styling - match text color */\n u {\n text-decoration-color: currentColor;\n }\n\n /* Link styling */\n a {\n cursor: pointer;\n text-decoration: underline;\n color: ${variables.contentColorLink};\n\n &:hover {\n opacity: 0.8;\n }\n }\n\n /* List styling */\n ul,\n ol {\n margin: 0;\n padding-left: 24px;\n }\n\n /* Nested numbered list sub-numbering: 1 -> a -> i -> A -> I */\n ol ol {\n list-style-type: lower-alpha;\n }\n ol ol ol {\n list-style-type: lower-roman;\n }\n ol ol ol ol {\n list-style-type: upper-alpha;\n }\n ol ol ol ol ol {\n list-style-type: upper-roman;\n }\n\n li {\n margin: 4px 0;\n }\n\n /* Paragraph spacing */\n p {\n margin: 0 0 8px 0;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n`;\n\n/** Visually hidden live region for screenreader announcements. */\nexport const LiveRegion = styled.div`\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n`;\n", "import * as React from 'react';\nimport { RenderElementProps } from 'slate-react';\nimport { CustomText } from '../types';\nimport { normalizeUrl } from '../utils/slateUtils';\n\n/**\n * Create Element renderer with edit mode awareness.\n * Returns a React component that renders Slate elements (paragraphs, lists, links).\n */\nexport const createElementRenderer = (\n isEditMode: boolean,\n defaultLineHeight: string\n): React.FC<RenderElementProps> => {\n return function ElementRenderer({ attributes, children, element }): JSX.Element {\n const customElement = element;\n // Base style for alignment\n const baseStyle: React.CSSProperties = {\n textAlign: customElement.align,\n };\n // Style with line height for block elements\n const blockStyle: React.CSSProperties = {\n ...baseStyle,\n lineHeight: customElement.lineHeight || defaultLineHeight,\n };\n\n switch (customElement.type) {\n case 'bulleted-list': {\n return <ul {...attributes}>{children}</ul>;\n }\n case 'numbered-list': {\n return <ol {...attributes}>{children}</ol>;\n }\n case 'list-item': {\n const listItemStyle: React.CSSProperties = { ...blockStyle };\n // Set color and fontSize on <li> so the ::marker (bullet/number) inherits them\n const firstLeaf = customElement.children[0] as CustomText | undefined;\n if (firstLeaf?.color) {\n listItemStyle.color = firstLeaf.color;\n }\n if (firstLeaf?.fontSize) {\n listItemStyle.fontSize = firstLeaf.fontSize;\n }\n // Use inside positioning when aligned or when font is large\n // enough that the marker would overflow the fixed padding gutter\n const fontSize = parseInt(String(firstLeaf?.fontSize || '0'), 10);\n if (customElement.align === 'center' || customElement.align === 'right' || fontSize > 24) {\n listItemStyle.listStylePosition = 'inside';\n }\n return (\n <li style={listItemStyle} {...attributes}>\n {children}\n </li>\n );\n }\n case 'link': {\n const normalizedHref = normalizeUrl(customElement.url || '');\n return (\n <a\n href={normalizedHref}\n style={{ display: 'inline' }}\n {...attributes}\n target={isEditMode ? undefined : '_blank'}\n rel={isEditMode ? undefined : 'noopener noreferrer'}\n tabIndex={isEditMode ? undefined : 0}\n onClick={(e): void => {\n if (isEditMode) {\n e.preventDefault();\n return;\n }\n // In view mode, prevent link clicks from bubbling to the\n // container's richtext.click handler (matches Markdown viz).\n e.stopPropagation();\n }}\n onKeyDown={(e): void => {\n if (!isEditMode && e.key === 'Enter') {\n window.open(normalizedHref, '_blank', 'noopener,noreferrer');\n }\n }}\n >\n {children}\n </a>\n );\n }\n case 'paragraph':\n default:\n return (\n <p style={blockStyle} {...attributes}>\n {children}\n </p>\n );\n }\n };\n};\n", "import * as React from 'react';\nimport { RenderLeafProps } from 'slate-react';\nimport { CustomText, FONT_FAMILY_WITH_FALLBACKS } from '../types';\n\n/**\n * Leaf renderer for Slate.js.\n * Renders inline formatting (bold, italic, underline, strikethrough, colors, fonts).\n */\nexport const Leaf: React.FC<RenderLeafProps> = ({ attributes, children, leaf }) => {\n const customLeaf = leaf as CustomText & { fakeHighlight?: boolean };\n const style: React.CSSProperties = {};\n\n if (customLeaf.fakeHighlight) {\n style.backgroundColor = 'rgba(0, 120, 215, 0.35)';\n } else if (customLeaf.backgroundColor && customLeaf.backgroundColor !== 'transparent') {\n style.backgroundColor = customLeaf.backgroundColor;\n }\n if (customLeaf.color) {\n style.color = customLeaf.color;\n }\n if (customLeaf.fontSize) {\n style.fontSize = customLeaf.fontSize;\n }\n if (customLeaf.fontFamily) {\n style.fontFamily = FONT_FAMILY_WITH_FALLBACKS[customLeaf.fontFamily] || customLeaf.fontFamily;\n }\n\n let content: React.ReactNode = children;\n\n if (customLeaf.bold) {\n content = <strong>{content}</strong>;\n }\n if (customLeaf.italic) {\n content = <em>{content}</em>;\n }\n if (customLeaf.underline) {\n content = <u>{content}</u>;\n }\n if (customLeaf.strikethrough) {\n content = <s>{content}</s>;\n }\n\n return (\n <span {...attributes} style={style}>\n {content}\n </span>\n );\n};\n", "import { FONT_SIZE_PRESETS, FontSizePreset } from '../types';\n\n/**\n * Get font size in pixels based on preset or custom value\n */\nexport const getFontSizeInPx = (fontSize?: FontSizePreset, customFontSize?: number): number => {\n if (fontSize === 'custom' && customFontSize) {\n return customFontSize;\n }\n return FONT_SIZE_PRESETS[fontSize || 'default'];\n};\n", "/**\n * useEditorSetup - Creates and configures the Slate editor instance.\n *\n * Handles: inline links, markdown autoformat, empty list-item Enter,\n * and stale selection recovery on onChange.\n */\n\nimport { useMemo, useRef, useEffect } from 'react';\nimport { createEditor, Editor, Transforms, Text, Element, Range, Node as SlateNode, Point } from 'slate';\nimport { withReact } from 'slate-react';\nimport { isLinkActive, toggleList } from '../utils/slateUtils';\nimport { CustomElement, CustomText } from '../types';\n\n/** If the cursor is at the end of a link, move it past the link before inserting. */\nfunction exitLinkBeforeInsert(e: Editor): void {\n const { selection } = e;\n if (!selection || !Range.isCollapsed(selection)) return;\n const above = Editor.above(e, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'link',\n });\n if (!above) return;\n const [, linkPath] = above;\n if (!Editor.isEnd(e, selection.anchor, linkPath)) return;\n const after = Editor.after(e, linkPath);\n if (after) {\n Transforms.select(e, after);\n }\n}\n\n/** Check if a list item node is empty (single empty text child). */\nfunction isEmptyListItem(node: Element): boolean {\n return node.children.length === 1 && Text.isText(node.children[0]) && node.children[0].text === '';\n}\n\n/** Returns true if the editor contains a single empty paragraph. */\nexport function isEditorEmpty(e: Editor): boolean {\n return (\n e.children.length === 1 &&\n Element.isElement(e.children[0]) &&\n isEmptyListItem(e.children[0] as Element)\n );\n}\n\n/** Apply defaultTextStyle marks so the first typed character inherits them. */\nexport function applyInitialMarks(\n e: Editor,\n style: {\n color?: string;\n backgroundColor?: string;\n fontSize?: string;\n fontFamily?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n }\n): void {\n if (style.color) Editor.addMark(e, 'color', style.color);\n if (style.backgroundColor) Editor.addMark(e, 'backgroundColor', style.backgroundColor);\n if (style.fontSize) Editor.addMark(e, 'fontSize', style.fontSize);\n if (style.fontFamily) Editor.addMark(e, 'fontFamily', style.fontFamily);\n if (style.bold) Editor.addMark(e, 'bold', true);\n if (style.italic) Editor.addMark(e, 'italic', true);\n if (style.underline) Editor.addMark(e, 'underline', true);\n if (style.strikethrough) Editor.addMark(e, 'strikethrough', true);\n}\n\ninterface DefaultTextStyleRef {\n current: {\n color?: string;\n backgroundColor?: string;\n fontSize?: string;\n fontFamily?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n };\n}\n\n/** Build a fallback marks object from default text style. */\nfunction buildFallbackMarks(s: DefaultTextStyleRef['current']): Record<string, unknown> {\n const fallback: Record<string, unknown> = {};\n if (s.color) fallback.color = s.color;\n if (s.backgroundColor) fallback.backgroundColor = s.backgroundColor;\n if (s.fontSize) fallback.fontSize = s.fontSize;\n if (s.fontFamily) fallback.fontFamily = s.fontFamily;\n if (s.bold) fallback.bold = true;\n if (s.italic) fallback.italic = true;\n if (s.underline) fallback.underline = true;\n if (s.strikethrough) fallback.strikethrough = true;\n return fallback;\n}\n\n/** Handle markdown autoformat: space after a trigger prefix at line start. */\nfunction handleAutoformat(e: Editor, defaultTextStyleRef: DefaultTextStyleRef): boolean {\n if (!e.selection || !Range.isCollapsed(e.selection)) return false;\n const { anchor } = e.selection;\n const block = Editor.above(e, {\n match: n => Element.isElement(n) && Editor.isBlock(e, n),\n });\n if (!block) return false;\n\n const [blockNode, blockPath] = block;\n\n const start = Editor.start(e, blockPath);\n const beforeText = Editor.string(e, { anchor, focus: start }).trim();\n\n let listType: 'bulleted-list' | 'numbered-list' | null = null;\n if (beforeText === '*' || beforeText === '-' || beforeText === '\\u2022') {\n listType = 'bulleted-list';\n } else if (/^\\d+\\.$/.test(beforeText)) {\n listType = 'numbered-list';\n }\n if (!listType) return false;\n\n // Inside a list item, only allow autoformat when the entire content is the\n // trigger text (e.g. user typed \"* \" from an empty item to switch list type).\n // This prevents \"2.\" mid-sentence from being re-interpreted as a list trigger.\n if (Element.isElement(blockNode) && blockNode.type === 'list-item') {\n const fullText = Editor.string(e, blockPath).trim();\n if (fullText !== beforeText) return false;\n\n // If already in the same list type, skip autoformat to avoid toggling it off.\n const [parentList] = Editor.nodes(e, {\n at: blockPath,\n match: n =>\n !Editor.isEditor(n) &&\n Element.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n });\n if (parentList && (parentList[0] as CustomElement).type === listType) return false;\n }\n\n let marks = Editor.marks(e);\n const hasStyleMarks = marks && Object.keys(marks).some(k => k !== 'text');\n if (!hasStyleMarks) {\n marks = buildFallbackMarks(defaultTextStyleRef.current);\n }\n Transforms.select(e, { anchor, focus: start });\n Transforms.delete(e);\n toggleList(e, listType);\n if (marks) {\n Object.entries(marks).forEach(([key, val]) => {\n if (key !== 'text') {\n e.addMark(key, val);\n }\n });\n }\n return true;\n}\n\n/**\n * If the given point sits inside a text node with a `tokenName` mark, return\n * the full range of that text node. Returns null if the point is not in a token.\n */\nfunction getTokenRangeAtPoint(e: Editor, point: Point): Range | null {\n const [node, path] = Editor.node(e, point);\n if (!Text.isText(node)) return null;\n const custom = node as CustomText;\n if (!custom.tokenName) return null;\n return {\n anchor: { path, offset: 0 },\n focus: { path, offset: custom.text.length },\n };\n}\n\n/**\n * If the given point sits inside a link element, return the full range of\n * that link. Returns null if the point is not in a link.\n */\nfunction getLinkRangeAtPoint(e: Editor, point: Point): Range | null {\n const linkEntry = Editor.above(e, {\n at: point,\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'link',\n });\n if (!linkEntry) return null;\n const [, linkPath] = linkEntry;\n return Editor.range(e, linkPath);\n}\n\n/**\n * Get the range of an atomic node (token or link) at a point.\n * Returns null if the point is not inside an atomic node.\n */\nfunction getAtomicRangeAtPoint(e: Editor, point: Point): Range | null {\n return getTokenRangeAtPoint(e, point) || getLinkRangeAtPoint(e, point);\n}\n\n/**\n * True when the point is strictly interior to an atomic node (token text or\n * link element) -- not at the very start or end edge. Edge positions are\n * valid caret positions for editing beside the node.\n */\nfunction isStrictlyInsideAtomic(e: Editor, point: Point): boolean {\n // Check token first (text-level mark)\n const [node] = Editor.node(e, point);\n if (Text.isText(node) && (node as CustomText).tokenName) {\n return point.offset > 0 && point.offset < node.text.length;\n }\n // Check link (element-level)\n const linkEntry = Editor.above(e, {\n at: point,\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'link',\n });\n if (!linkEntry) return false;\n const [, linkPath] = linkEntry;\n const linkRange = Editor.range(e, linkPath);\n const atStart = Point.equals(point, linkRange.anchor);\n const atEnd = Point.equals(point, linkRange.focus);\n return !atStart && !atEnd;\n}\n\n/**\n * Get a point just AFTER the atomic node at the given point. For tokens (text\n * marks) this is the end of the text node. For links (elements) this is the\n * point after the link element so inserted text lands outside the link.\n */\nfunction getPointAfterAtomic(e: Editor, point: Point): Point | null {\n // Check link first (element-level)\n const linkEntry = Editor.above(e, {\n at: point,\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'link',\n });\n if (linkEntry) {\n const [, linkPath] = linkEntry;\n return Editor.after(e, linkPath) || null;\n }\n // Token: end of the text node\n const tokenRange = getTokenRangeAtPoint(e, point);\n if (tokenRange) return tokenRange.focus;\n return null;\n}\n\n/**\n * When an endpoint of an expanded selection is strictly inside an atomic node,\n * determine which edge of the atomic range to snap to and which selection\n * endpoint (anchor or focus) to move. Returns null if no adjustment needed.\n */\nfunction getAtomicExpansion(\n atomicRange: Range,\n isAnchorEndpoint: boolean,\n isBackward: boolean\n): { adjustAnchor: boolean; target: Point } | null {\n // Backward: anchor is after focus. Forward: anchor is before focus.\n // When anchor is inside: backward -> move focus to atomicRange.focus;\n // forward -> move anchor to atomicRange.anchor\n // When focus is inside: backward -> move anchor to atomicRange.anchor;\n // forward -> move focus to atomicRange.focus\n const adjustAnchor = isAnchorEndpoint ? !isBackward : isBackward;\n const target = adjustAnchor ? atomicRange.anchor : atomicRange.focus;\n return { adjustAnchor, target };\n}\n\n/**\n * Snap one endpoint of a selection to an atomic node boundary.\n * Returns the updated anchor/focus and whether a change was made.\n */\nfunction snapEndpointToAtomic(\n e: Editor,\n point: Point,\n isAnchorEndpoint: boolean,\n anchor: Point,\n focus: Point,\n isBackward: boolean\n): { anchor: Point; focus: Point; changed: boolean } | null {\n const atomicRange = getAtomicRangeAtPoint(e, point);\n if (!atomicRange) return null;\n const exp = getAtomicExpansion(atomicRange, isAnchorEndpoint, isBackward);\n if (!exp) return null;\n const current = exp.adjustAnchor ? anchor : focus;\n if (Point.compare(current, exp.target) === 0) return null;\n return {\n anchor: exp.adjustAnchor ? exp.target : anchor,\n focus: exp.adjustAnchor ? focus : exp.target,\n changed: true,\n };\n}\n\n/**\n * If the current selection has an endpoint strictly inside an atomic node\n * (token or link), expand it to cover the full node. Edge positions are\n * valid caret positions for editing beside the node.\n */\nfunction expandSelectionToAtomic(e: Editor): void {\n const { selection } = e;\n if (!selection) return;\n\n let { anchor, focus } = selection;\n let changed = false;\n\n if (isStrictlyInsideAtomic(e, anchor)) {\n const anchorRange = getAtomicRangeAtPoint(e, anchor);\n if (!anchorRange) return;\n if (Range.isCollapsed(selection)) {\n Transforms.select(e, anchorRange);\n return;\n }\n const result = snapEndpointToAtomic(e, anchor, true, anchor, focus, Range.isBackward(selection));\n if (result) {\n ({ anchor, focus, changed } = result);\n }\n }\n\n if (isStrictlyInsideAtomic(e, focus)) {\n const focusRange = getAtomicRangeAtPoint(e, focus);\n if (!focusRange) return;\n const result = snapEndpointToAtomic(e, focus, false, anchor, focus, Range.isBackward(selection));\n if (result) {\n ({ anchor, focus, changed } = result);\n }\n }\n\n if (changed) {\n Transforms.select(e, { anchor, focus });\n }\n}\n\n/**\n * If the cursor is collapsed strictly inside an atomic node (token or link),\n * move it past the node so subsequent edits land outside.\n */\nfunction moveCursorPastAtomicIfNeeded(e: Editor): void {\n if (!e.selection || !Range.isCollapsed(e.selection)) return;\n if (!isStrictlyInsideAtomic(e, e.selection.anchor)) return;\n const after = getPointAfterAtomic(e, e.selection.anchor);\n if (after) {\n Transforms.select(e, after);\n }\n}\n\n/** If the caret is in an empty top-level list item, exit the list to a paragraph. */\nfunction tryExitEmptyListItem(e: Editor): boolean {\n const { selection } = e;\n if (!selection || !Range.isCollapsed(selection)) return false;\n const above = Editor.above(e, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n if (!above) return false;\n const [itemNode] = above;\n if (!Element.isElement(itemNode) || !isEmptyListItem(itemNode)) return false;\n Transforms.unwrapNodes(e, {\n match: n =>\n !Editor.isEditor(n) &&\n Element.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n split: true,\n });\n Transforms.setNodes(e, { type: 'paragraph' } as Partial<CustomElement>);\n return true;\n}\n\n/**\n * Try to delete an atomic node near the cursor for backspace.\n * Checks: strictly inside, at end edge, or right after an atomic node.\n * Returns true if an atomic deletion was performed.\n */\nfunction tryDeleteAtomicBackward(ed: Editor, anchor: Point): boolean {\n if (isStrictlyInsideAtomic(ed, anchor)) {\n const range = getAtomicRangeAtPoint(ed, anchor);\n if (range) Transforms.delete(ed, { at: range });\n return true;\n }\n const currentRange = getAtomicRangeAtPoint(ed, anchor);\n if (currentRange && Point.equals(anchor, currentRange.focus)) {\n Transforms.delete(ed, { at: currentRange });\n return true;\n }\n if (currentRange) return false;\n const before = Editor.before(ed, anchor);\n const prevRange = before ? getAtomicRangeAtPoint(ed, before) : null;\n if (!prevRange) return false;\n Transforms.delete(ed, { at: prevRange });\n return true;\n}\n\n/** Unwrap a list item at the start of a line back to a paragraph, or un-indent if nested. */\nfunction tryUnwrapListItem(ed: Editor, anchor: Point): boolean {\n const [listItemMatch] = Editor.nodes(ed, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n if (!listItemMatch) return false;\n const [, listItemPath] = listItemMatch;\n if (!Editor.isStart(ed, anchor, listItemPath)) return false;\n\n const listAncestors = Array.from(\n Editor.nodes(ed, {\n at: listItemPath,\n match: n =>\n !Editor.isEditor(n) &&\n Element.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n })\n );\n\n if (listAncestors.length > 1) {\n Transforms.liftNodes(ed, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n return true;\n }\n\n Transforms.unwrapNodes(ed, {\n match: n =>\n !Editor.isEditor(n) &&\n Element.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n split: true,\n });\n Transforms.setNodes(ed, { type: 'paragraph' } as Partial<CustomElement>);\n return true;\n}\n\n/**\n * Try to delete an atomic node near the cursor for forward-delete.\n * Checks: strictly inside, at start edge, or right before an atomic node.\n * Returns true if an atomic deletion was performed.\n */\nfunction tryDeleteAtomicForward(ed: Editor, anchor: Point): boolean {\n if (isStrictlyInsideAtomic(ed, anchor)) {\n const range = getAtomicRangeAtPoint(ed, anchor);\n if (range) Transforms.delete(ed, { at: range });\n return true;\n }\n const fwdRange = getAtomicRangeAtPoint(ed, anchor);\n if (fwdRange && Point.equals(anchor, fwdRange.anchor)) {\n Transforms.delete(ed, { at: fwdRange });\n return true;\n }\n if (fwdRange) return false;\n const after = Editor.after(ed, anchor);\n const nextRange = after ? getAtomicRangeAtPoint(ed, after) : null;\n if (!nextRange) return false;\n Transforms.delete(ed, { at: nextRange });\n return true;\n}\n\n/** Recover from stale selection paths after tree-restructuring operations. */\nfunction recoverStaleSelection(e: Editor): void {\n if (!e.selection) return;\n try {\n SlateNode.get(e, e.selection.anchor.path);\n SlateNode.get(e, e.selection.focus.path);\n return;\n } catch {\n // fall through to recovery\n }\n try {\n e.selection = { anchor: Editor.end(e, []), focus: Editor.end(e, []) };\n } catch {\n e.selection = null;\n }\n}\n\n/** Expand selection to atomic node bounds while preserving editor.marks. */\nfunction expandAtomicPreservingMarks(e: Editor): void {\n if (!e.selection) return;\n const savedMarks = e.marks;\n expandSelectionToAtomic(e);\n if (savedMarks) {\n e.marks = savedMarks;\n }\n}\n\n/** Install custom insertText / insertBreak overrides on the editor. */\nfunction installInsertOverrides(\n e: Editor,\n defaultTextStyleRef: DefaultTextStyleRef,\n onBeforeBreak: () => void\n): void {\n const { insertText, insertBreak } = e;\n\n e.insertText = text => {\n if (text && isLinkActive(e)) {\n exitLinkBeforeInsert(e);\n }\n if (text === ' ' && handleAutoformat(e, defaultTextStyleRef)) {\n return;\n }\n moveCursorPastAtomicIfNeeded(e);\n insertText(text);\n };\n\n e.insertBreak = () => {\n moveCursorPastAtomicIfNeeded(e);\n if (tryExitEmptyListItem(e)) return;\n onBeforeBreak();\n insertBreak();\n };\n}\n\n/** Install custom deleteBackward / deleteForward overrides on the editor. */\nfunction installDeleteOverrides(e: Editor): void {\n const { deleteBackward, deleteForward } = e;\n\n e.deleteBackward = unit => {\n const { selection } = e;\n if (selection && Range.isCollapsed(selection)) {\n if (tryDeleteAtomicBackward(e, selection.anchor)) return;\n if (tryUnwrapListItem(e, selection.anchor)) return;\n }\n deleteBackward(unit);\n };\n\n e.deleteForward = unit => {\n const { selection } = e;\n if (selection && Range.isCollapsed(selection)) {\n if (tryDeleteAtomicForward(e, selection.anchor)) return;\n }\n deleteForward(unit);\n };\n}\n\n/** Install custom onChange override on the editor. */\nfunction installOnChangeOverride(\n e: Editor,\n getSavedMarks: () => ReturnType<typeof Editor.marks>,\n clearSavedMarks: () => void\n): void {\n const { onChange } = e;\n e.onChange = () => {\n recoverStaleSelection(e);\n // Restore marks saved before insertBreak so updateActiveStyles\n // (triggered by onChange -> React render) reads the correct marks.\n const saved = getSavedMarks();\n if (saved) {\n e.marks = saved;\n clearSavedMarks();\n }\n onChange();\n // After onChange fires, expand selection to atomic node boundaries.\n // Preserve editor.marks because Transforms.select resets them,\n // which would break mark toggles (bold, italic, etc.).\n expandAtomicPreservingMarks(e);\n };\n}\n\nexport function useEditorSetup(defaultTextStyleRef: DefaultTextStyleRef): Editor {\n const editor = useMemo(() => {\n const e = withReact(createEditor());\n\n const { isInline } = e;\n e.isInline = element => (element.type === 'link' ? true : isInline(element));\n\n // Marks saved before insertBreak so onChange can restore them.\n // insertBreak triggers set_selection ops that clear editor.marks to null,\n // causing updateActiveStyles to read stale leaf marks instead of the\n // user's intended formatting.\n let savedMarksForOnChange: ReturnType<typeof Editor.marks> = null;\n\n installInsertOverrides(e, defaultTextStyleRef, () => {\n savedMarksForOnChange = Editor.marks(e);\n });\n installDeleteOverrides(e);\n installOnChangeOverride(\n e,\n () => savedMarksForOnChange,\n () => {\n savedMarksForOnChange = null;\n }\n );\n\n return e;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return editor;\n}\n\nexport function useInitialMarks(\n editor: Editor,\n isEditMode: boolean,\n defaultTextStyle: DefaultTextStyleRef['current']\n): void {\n const hasInitializedMarksRef = useRef(false);\n useEffect(() => {\n if (hasInitializedMarksRef.current) return;\n if (isEditMode && isEditorEmpty(editor)) {\n applyInitialMarks(editor, defaultTextStyle);\n hasInitializedMarksRef.current = true;\n }\n // Only run on mount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isEditMode, editor]);\n}\n", "/**\n * useFakeHighlight - Manages fake selection highlight via absolute character offsets.\n *\n * When the editor loses focus to the config panel, a styled \"fake\" selection\n * highlight is shown via Slate decorations so the user can see what text\n * their formatting changes apply to.\n *\n * Absolute offsets are immune to node splitting from addMark/setNodes\n * because the total text content is unchanged -- only node boundaries move.\n */\n\nimport { useState, useCallback, useRef } from 'react';\nimport { Editor, Text, Range, Point, Path, Node as SlateNode } from 'slate';\n\nexport type AbsRange = { absStart: number; absEnd: number };\n\n/** Compute the absolute offset of a single Point by walking text nodes. */\nfunction pointAbsOffset(editor: Editor, point: Point): number {\n let abs = 0;\n for (const [textNode, path] of Editor.nodes<Text>(editor, {\n at: [],\n match: n => Text.isText(n),\n })) {\n if (Path.equals(path, point.path)) return abs + point.offset;\n abs += textNode.text.length;\n }\n return abs;\n}\n\n/** Convert a Slate Range to absolute character offsets. */\nfunction rangeToAbsOffsets(editor: Editor, range: Range): AbsRange {\n const [start, end] = Range.edges(range);\n return {\n absStart: pointAbsOffset(editor, start),\n absEnd: pointAbsOffset(editor, end),\n };\n}\n\n/** Compute the absolute character offset of a Point by walking all text nodes. */\nexport function pointToAbsOffset(editor: Editor, point: Point): number {\n let offset = 0;\n for (const [textNode, path] of Editor.nodes<Text>(editor, {\n at: [],\n match: n => Text.isText(n),\n })) {\n if (Path.equals(path, point.path)) return offset + point.offset;\n offset += textNode.text.length;\n }\n return offset;\n}\n\n/**\n * Resolve an absolute character offset back to a Point in the current tree.\n * When isStart is true and the offset falls exactly at a node boundary,\n * prefer the start of the NEXT node (so the selection doesn't include the\n * preceding node that may have different formatting).\n */\nexport function absOffsetToPoint(editor: Editor, absOffset: number, isStart = false): Point | null {\n let seen = 0;\n for (const [textNode, path] of Editor.nodes<Text>(editor, {\n at: [],\n match: n => Text.isText(n),\n })) {\n const len = textNode.text.length;\n if (isStart ? seen + len > absOffset : seen + len >= absOffset) {\n return { path, offset: absOffset - seen };\n }\n seen += len;\n }\n return null;\n}\n\nexport interface FakeHighlightResult {\n fakeHighlightAbs: AbsRange | null;\n fakeHighlightAbsRef: React.MutableRefObject<AbsRange | null>;\n updateFakeHighlight: (range: Range | null) => void;\n updateFakeHighlightAbs: (abs: AbsRange | null) => void;\n decorate: ([node, path]: [SlateNode, Path]) => Range[];\n}\n\nexport function useFakeHighlight(editor: Editor): FakeHighlightResult {\n const [fakeHighlightAbs, setFakeHighlightAbs] = useState<AbsRange | null>(null);\n const fakeHighlightAbsRef = useRef<AbsRange | null>(null);\n\n const updateFakeHighlight = useCallback(\n (range: Range | null) => {\n if (!range) {\n fakeHighlightAbsRef.current = null;\n setFakeHighlightAbs(null);\n return;\n }\n const abs = rangeToAbsOffsets(editor, range);\n fakeHighlightAbsRef.current = abs;\n setFakeHighlightAbs(abs);\n },\n [editor]\n );\n\n const updateFakeHighlightAbs = useCallback((abs: AbsRange | null) => {\n fakeHighlightAbsRef.current = abs;\n setFakeHighlightAbs(abs);\n }, []);\n\n const decorate = useCallback(\n ([node, path]: [SlateNode, Path]): Range[] => {\n if (!fakeHighlightAbs || !Text.isText(node)) return [];\n const { absStart, absEnd } = fakeHighlightAbs;\n let nodeAbsStart = 0;\n for (const [n, p] of Editor.nodes<Text>(editor, {\n at: [],\n match: nd => Text.isText(nd),\n })) {\n if (Path.equals(p, path)) break;\n nodeAbsStart += n.text.length;\n }\n const nodeAbsEnd = nodeAbsStart + node.text.length;\n const overlapStart = Math.max(absStart, nodeAbsStart);\n const overlapEnd = Math.min(absEnd, nodeAbsEnd);\n if (overlapStart >= overlapEnd) return [];\n return [\n {\n anchor: { path, offset: overlapStart - nodeAbsStart },\n focus: { path, offset: overlapEnd - nodeAbsStart },\n fakeHighlight: true,\n } as Range & { fakeHighlight: boolean },\n ];\n },\n [fakeHighlightAbs, editor]\n );\n\n return {\n fakeHighlightAbs,\n fakeHighlightAbsRef,\n updateFakeHighlight,\n updateFakeHighlightAbs,\n decorate,\n };\n}\n", "/**\n * useContentSync - Manages editor value state, external content syncing,\n * and the onChange handler with history tracking.\n */\n\nimport { useState, useCallback, useRef, useEffect } from 'react';\nimport { Descendant, Editor, Transforms, Range, Node as SlateNode, Text, Point } from 'slate';\nimport { slateToHtml, htmlToSlate } from '../utils/slateUtils';\nimport type { AbsRange } from './useFakeHighlight';\n\n/** Clamp a Point so its path and offset are valid within the current tree. */\nfunction clampPoint(editor: Editor, point: Point): Point {\n try {\n const node = SlateNode.get(editor, point.path);\n if (Text.isText(node)) {\n return { path: point.path, offset: Math.min(point.offset, node.text.length) };\n }\n } catch {\n // Path doesn't exist in the new tree\n }\n // Fall back to the end of the document\n return Editor.end(editor, []);\n}\n\n/** Clamp a Selection so both anchor and focus are valid within the current tree. */\nfunction clampSelection(editor: Editor, selection: Range): Range {\n return {\n anchor: clampPoint(editor, selection.anchor),\n focus: clampPoint(editor, selection.focus),\n };\n}\n\n/** Safely restore a selection, falling back to end-of-document if the path is invalid. */\nfunction safeRestoreSelection(editor: Editor, selection: Range | null): void {\n try {\n if (selection) {\n Transforms.select(editor, clampSelection(editor, selection));\n } else {\n Transforms.select(editor, Editor.end(editor, []));\n }\n } catch {\n try {\n Transforms.select(editor, Editor.end(editor, []));\n } catch {\n // ignore - editor may be empty\n }\n }\n}\n\ntype HistoryEntry = {\n html: string;\n /** Selection after this edit was applied. */\n selection: Editor['selection'];\n /** Selection before this edit was applied (used to restore cursor on undo). */\n preSelection: Editor['selection'];\n};\n\ninterface ContentSyncArgs {\n editor: Editor;\n initialValue: Descendant[];\n richTextContent: string;\n onContentChange: (html: string, immediate?: boolean) => void;\n updateActiveStyles: (isContentChange?: boolean) => void;\n updateFakeHighlightAbs: (abs: AbsRange | null) => void;\n fakeHighlightAbsRef: React.MutableRefObject<AbsRange | null>;\n hasFocusRef: React.MutableRefObject<boolean>;\n lastSelectionRef: React.MutableRefObject<Editor['selection']>;\n /** Set by useContentSave; checked to detect round-trips and skip tree resets. */\n recentSavesRef?: React.MutableRefObject<Set<string>>;\n /** When true, accept the next external content change even if the editor has focus (e.g. Cmd+Z undo). */\n forceNextSyncRef?: React.MutableRefObject<boolean>;\n}\n\ninterface ContentSyncResult {\n value: Descendant[];\n handleChange: (newValue: Descendant[]) => void;\n}\n\n/** Consume the forceSync flag if set, returning its value. */\nfunction consumeForceSync(ref?: React.MutableRefObject<boolean>): boolean {\n const value = ref?.current ?? false;\n if (value && ref) {\n // eslint-disable-next-line no-param-reassign\n ref.current = false;\n }\n return value;\n}\n\n/**\n * Determine whether the sync effect should skip the tree reset.\n * Returns true when the incoming content is a known round-trip or\n * the editor is authoritative (has focus).\n */\nfunction shouldSkipSync(\n forceSync: boolean,\n richTextContent: string,\n lastEmittedHtml: string,\n recentSavesRef: React.MutableRefObject<Set<string>> | undefined,\n hasFocusRef: React.MutableRefObject<boolean>\n): boolean {\n if (forceSync) return false;\n if (recentSavesRef?.current.has(richTextContent)) return true;\n if (hasFocusRef.current) return true;\n return false;\n}\n\n/** Find the most recent history entry matching the given HTML. */\nfunction findHistoryIndex(history: HistoryEntry[], html: string): number {\n for (let i = history.length - 1; i >= 0; i -= 1) {\n if (history[i].html === html) return i;\n }\n return -1;\n}\n\nexport function useContentSync({\n editor,\n initialValue,\n richTextContent,\n onContentChange,\n updateActiveStyles,\n updateFakeHighlightAbs,\n fakeHighlightAbsRef,\n hasFocusRef,\n lastSelectionRef,\n recentSavesRef,\n forceNextSyncRef,\n}: ContentSyncArgs): ContentSyncResult {\n const [value, setValue] = useState<Descendant[]>(initialValue);\n const lastEmittedHtmlRef = useRef<string>(richTextContent);\n const emittedHistoryRef = useRef<HistoryEntry[]>([\n { html: richTextContent, selection: null, preSelection: null },\n ]);\n const historyPosRef = useRef<number>(0);\n const lastInitialValueRef = useRef<Descendant[]>(initialValue);\n\n // Sync with external content changes (e.g. dashboard Cmd+Z undo / Cmd+Shift+Z redo)\n // Also re-syncs when initialValue changes without richTextContent changing\n // (e.g. token marks added after mount).\n useEffect(() => {\n const initialValueChanged = initialValue !== lastInitialValueRef.current;\n lastInitialValueRef.current = initialValue;\n if (!initialValueChanged && richTextContent === lastEmittedHtmlRef.current) return;\n\n const forceSync = consumeForceSync(forceNextSyncRef);\n\n if (\n shouldSkipSync(\n forceSync,\n richTextContent,\n lastEmittedHtmlRef.current,\n recentSavesRef,\n hasFocusRef\n )\n ) {\n lastEmittedHtmlRef.current = richTextContent;\n return;\n }\n\n const history = emittedHistoryRef.current;\n const incomingIdx = findHistoryIndex(history, richTextContent);\n\n // When richTextContent matches what we last emitted, only initialValue\n // changed (e.g. token marks applied after mount). Preserve pending marks\n // so in-progress format toggles (bold on collapsed cursor) are not lost.\n const isExternalContentChange = richTextContent !== lastEmittedHtmlRef.current;\n const pendingMarks = isExternalContentChange ? null : editor.marks;\n\n lastEmittedHtmlRef.current = richTextContent;\n if (incomingIdx !== -1) {\n historyPosRef.current = incomingIdx;\n }\n\n // On undo, restore the cursor to where it was BEFORE the undone edit.\n const undoneEntry = incomingIdx !== -1 ? history[incomingIdx + 1] : null;\n const savedSelection =\n undoneEntry?.preSelection ||\n (incomingIdx !== -1 ? history[incomingIdx].selection : null) ||\n lastSelectionRef.current;\n\n // When forceSync is active, initialValue may be stale (parent memo\n // skips recomputation while isTextEditing is true). Parse HTML directly.\n const treeToApply = forceSync && richTextContent ? htmlToSlate(richTextContent) : initialValue;\n setValue(treeToApply);\n // eslint-disable-next-line no-param-reassign\n editor.children = treeToApply;\n // eslint-disable-next-line no-param-reassign\n editor.selection = null;\n\n // Only restore selection when content actually changed (external\n // undo/redo, forceSync). Skip when only initialValue changed from an\n // isTextEditing toggle to avoid re-creating a stale expanded selection.\n if (isExternalContentChange || forceSync) {\n safeRestoreSelection(editor, savedSelection);\n }\n\n if (pendingMarks) {\n // eslint-disable-next-line no-param-reassign\n editor.marks = pendingMarks;\n }\n }, [initialValue, richTextContent, editor, lastSelectionRef]);\n\n const handleChange = useCallback(\n (newValue: Descendant[]) => {\n setValue(newValue);\n\n const prevSelection = lastSelectionRef.current;\n if (editor.selection) {\n // eslint-disable-next-line no-param-reassign\n lastSelectionRef.current = editor.selection;\n }\n\n const isContentChange = editor.operations.some(op => op.type !== 'set_selection');\n\n if (isContentChange) {\n const html = slateToHtml(newValue);\n if (html !== lastEmittedHtmlRef.current) {\n // Classify: if all content ops are insert_text / remove_text, it's typing.\n // Structural ops (split_node, merge_node, set_node, etc.) save immediately.\n const isTypingOnly = editor.operations.every(\n op =>\n op.type === 'set_selection' ||\n op.type === 'insert_text' ||\n op.type === 'remove_text'\n );\n const pos = historyPosRef.current;\n lastEmittedHtmlRef.current = html;\n emittedHistoryRef.current = [\n ...emittedHistoryRef.current.slice(0, pos + 1),\n { html, selection: editor.selection, preSelection: prevSelection },\n ];\n historyPosRef.current = emittedHistoryRef.current.length - 1;\n onContentChange(html, !isTypingOnly);\n }\n }\n\n if (hasFocusRef.current || editor.selection) {\n updateActiveStyles(isContentChange);\n }\n\n if (isContentChange && fakeHighlightAbsRef.current && hasFocusRef.current && editor.selection) {\n if (Range.isCollapsed(editor.selection)) {\n updateFakeHighlightAbs(null);\n }\n }\n },\n [\n editor,\n onContentChange,\n updateActiveStyles,\n updateFakeHighlightAbs,\n fakeHighlightAbsRef,\n hasFocusRef,\n lastSelectionRef,\n ]\n );\n\n return { value, handleChange };\n}\n", "/**\n * useKeyboardShortcuts - Handles keyboard shortcuts, Enter/Tab in lists,\n * and select-all within the Slate editor.\n */\n\nimport { useCallback } from 'react';\nimport { Editor, Transforms, Element, Text } from 'slate';\nimport { CustomElement, FormatCommand } from '../types';\n\ninterface KeyboardShortcutsArgs {\n editor: Editor;\n applyFormat: (command: FormatCommand, value?: string) => void;\n resetToDefault: () => void;\n openLinkPopover: () => void;\n stepFontSize: (delta: number) => void;\n}\n\n/** Handle Enter key: lift empty nested list items to parent. */\nfunction handleEnterKey(editor: Editor, event: React.KeyboardEvent): void {\n if (!editor.selection) return;\n\n const [listItemMatch] = Editor.nodes(editor, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n if (!listItemMatch) return;\n\n const [listItemNode, listItemPath] = listItemMatch;\n const isEmpty =\n Element.isElement(listItemNode) &&\n listItemNode.children.length === 1 &&\n Text.isText(listItemNode.children[0]) &&\n listItemNode.children[0].text === '';\n if (!isEmpty) return;\n\n const [parentList] = Editor.nodes(editor, {\n at: listItemPath,\n match: n =>\n !Editor.isEditor(n) &&\n Element.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n });\n if (!parentList) return;\n\n const [, parentListPath] = parentList;\n const [grandparentListItem] = Editor.nodes(editor, {\n at: parentListPath,\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n if (!grandparentListItem) return;\n\n event.preventDefault();\n Transforms.liftNodes(editor, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n}\n\n/** Handle Tab key: indent list item by wrapping in a nested list. */\nfunction handleTabKey(editor: Editor, event: React.KeyboardEvent): void {\n if (!editor.selection) return;\n\n const [match] = Editor.nodes(editor, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n if (!match) return;\n\n event.preventDefault();\n const [, listItemPath] = match;\n\n const [parentList] = Editor.nodes(editor, {\n at: listItemPath,\n match: n =>\n !Editor.isEditor(n) &&\n Element.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n });\n if (!parentList) return;\n\n const [parentListNode] = parentList;\n const parentListElement = parentListNode as CustomElement;\n const listType: 'bulleted-list' | 'numbered-list' =\n parentListElement.type === 'numbered-list' ? 'numbered-list' : 'bulleted-list';\n Transforms.wrapNodes(editor, { type: listType, children: [] } as CustomElement, {\n at: listItemPath,\n });\n}\n\n/** Cycle text alignment: left -> center -> right -> justify -> left */\nfunction cycleAlignment(editor: Editor, applyFormat: (cmd: FormatCommand) => void): void {\n const cycle: Record<string, FormatCommand> = {\n left: 'justifyCenter',\n center: 'justifyRight',\n right: 'justifyFull',\n justify: 'justifyLeft',\n };\n\n const [listItemMatch] = Editor.nodes(editor, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n const [blockMatch] = Editor.nodes(editor, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && Editor.isBlock(editor, n),\n });\n\n const node = listItemMatch?.[0] || blockMatch?.[0];\n const current = (node as { align?: string })?.align || 'left';\n applyFormat(cycle[current] || 'justifyCenter');\n}\n\nexport function useKeyboardShortcuts({\n editor,\n applyFormat,\n resetToDefault,\n openLinkPopover,\n stepFontSize,\n}: KeyboardShortcutsArgs): {\n handleKeyDown: (event: React.KeyboardEvent) => void;\n} {\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n const mod = event.metaKey || event.ctrlKey;\n\n if (event.key === 'a' && mod) {\n event.preventDefault();\n Transforms.select(editor, {\n anchor: Editor.start(editor, []),\n focus: Editor.end(editor, []),\n });\n return;\n }\n\n // Cmd+key (no Shift)\n if (mod && !event.shiftKey) {\n const cmdHandled = handleModShortcut(event, applyFormat, openLinkPopover, resetToDefault);\n if (cmdHandled) return;\n }\n\n // Cmd+Shift+key\n if (mod && event.shiftKey) {\n const shiftHandled = handleModShiftShortcut(event, editor, applyFormat, stepFontSize);\n if (shiftHandled) return;\n }\n\n if (event.key === 'Enter') {\n handleEnterKey(editor, event);\n return;\n }\n if (event.key === 'Tab' && !event.shiftKey) {\n handleTabKey(editor, event);\n // If handleTabKey didn't preventDefault (cursor not in a list),\n // insert a tab character so Tab never leaves the editor.\n if (!event.defaultPrevented) {\n event.preventDefault();\n editor.insertText('\\t');\n }\n }\n },\n [editor, applyFormat, resetToDefault, openLinkPopover, stepFontSize]\n );\n\n return { handleKeyDown };\n}\n\n/** Cmd+key shortcuts (without Shift). Returns true if handled. */\nfunction handleModShortcut(\n event: React.KeyboardEvent,\n applyFormat: (cmd: FormatCommand) => void,\n openLinkPopover: () => void,\n resetToDefault: () => void\n): boolean {\n switch (event.key) {\n case 'b':\n event.preventDefault();\n applyFormat('bold');\n return true;\n case 'i':\n event.preventDefault();\n applyFormat('italic');\n return true;\n case 'u':\n event.preventDefault();\n applyFormat('underline');\n return true;\n case 'k':\n event.preventDefault();\n openLinkPopover();\n return true;\n default:\n break;\n }\n if (event.key === '\\\\' || event.code === 'Backslash') {\n event.preventDefault();\n resetToDefault();\n return true;\n }\n return false;\n}\n\n/** Cmd+Shift+key shortcuts. Returns true if handled. */\nfunction handleModShiftShortcut(\n event: React.KeyboardEvent,\n editor: Editor,\n applyFormat: (cmd: FormatCommand) => void,\n stepFontSize: (delta: number) => void\n): boolean {\n const key = event.key.toLowerCase();\n if (key === 'x') {\n event.preventDefault();\n applyFormat('strikethrough');\n return true;\n }\n if (event.key === ',' || event.key === '<') {\n event.preventDefault();\n stepFontSize(-2);\n return true;\n }\n if (event.key === '.' || event.key === '>') {\n event.preventDefault();\n stepFontSize(2);\n return true;\n }\n if (key === 'l') {\n event.preventDefault();\n cycleAlignment(editor, applyFormat);\n return true;\n }\n // Cmd+Shift+7 -> numbered list (event.key is '&' on Mac with Shift+7)\n if (event.key === '&' || event.key === '7') {\n event.preventDefault();\n applyFormat('insertOrderedList');\n return true;\n }\n // Cmd+Shift+8 -> bulleted list (event.key is '*' on Mac with Shift+8)\n if (event.key === '*' || event.key === '8') {\n event.preventDefault();\n applyFormat('insertUnorderedList');\n return true;\n }\n return false;\n}\n", "/**\n * useStepFontSize - Step font size up or down by delta px, clamped to [8, 96].\n * When the selection spans mixed sizes, each text node is stepped independently.\n */\n\nimport { useCallback, useEffect } from 'react';\nimport { Editor, Transforms, Text, Range, Point } from 'slate';\nimport { pointToAbsOffset, absOffsetToPoint } from './useFakeHighlight';\nimport type { AbsRange } from './useFakeHighlight';\n\nconst MIN_FONT_SIZE = 8;\nconst MAX_FONT_SIZE = 96;\n\nfunction clampFontSize(size: number): number {\n return Math.min(MAX_FONT_SIZE, Math.max(MIN_FONT_SIZE, size));\n}\n\n/** Restore editor.selection from abs highlight or last known selection. */\nfunction restoreSelection(\n editor: Editor,\n fakeHighlightAbsRef: React.MutableRefObject<AbsRange | null>,\n lastSelectionRef: React.MutableRefObject<Editor['selection']>\n): void {\n if (!editor.selection && fakeHighlightAbsRef.current) {\n const s = absOffsetToPoint(editor, fakeHighlightAbsRef.current.absStart, true);\n const e = absOffsetToPoint(editor, fakeHighlightAbsRef.current.absEnd);\n // eslint-disable-next-line no-param-reassign\n if (s && e) editor.selection = { anchor: s, focus: e };\n }\n if (!editor.selection && lastSelectionRef.current) {\n // eslint-disable-next-line no-param-reassign\n editor.selection = lastSelectionRef.current;\n }\n}\n\n/** Step font size for a collapsed cursor (no range selection). */\nfunction stepCollapsed(editor: Editor, delta: number, updateActiveStyles: () => void): void {\n const marks = Editor.marks(editor);\n const current = marks?.fontSize ? parseInt(String(marks.fontSize), 10) : 14;\n Editor.addMark(editor, 'fontSize', `${clampFontSize(current + delta)}px`);\n updateActiveStyles();\n}\n\n/** Collect per-node font sizes and ranges for a range selection. */\nfunction collectTextEntries(editor: Editor): { size: number; start: Point; end: Point }[] {\n if (!editor.selection) return [];\n const [selStart, selEnd] = Range.edges(editor.selection);\n const entries: { size: number; start: Point; end: Point }[] = [];\n for (const [node, path] of Editor.nodes<Text>(editor, {\n at: editor.selection,\n match: n => Text.isText(n),\n })) {\n const fontSize = (node as unknown as Record<string, unknown>).fontSize as string | undefined;\n const cur = fontSize ? parseInt(fontSize, 10) : 14;\n const nodeStart = Editor.start(editor, path);\n const nodeEnd = Editor.end(editor, path);\n const start = Point.compare(nodeStart, selStart) >= 0 ? nodeStart : selStart;\n const end = Point.compare(nodeEnd, selEnd) <= 0 ? nodeEnd : selEnd;\n entries.push({ size: cur, start, end });\n }\n return entries;\n}\n\n/** Apply font size delta to each text entry in reverse order. */\nfunction applyFontSizeEntries(\n editor: Editor,\n entries: { size: number; start: Point; end: Point }[],\n delta: number\n): void {\n for (let i = entries.length - 1; i >= 0; i -= 1) {\n const { size, start, end } = entries[i];\n Transforms.setNodes(editor, { fontSize: `${clampFontSize(size + delta)}px` } as Partial<Text>, {\n at: { anchor: start, focus: end },\n match: n => Text.isText(n),\n split: true,\n });\n }\n}\n\ninterface StepFontSizeArgs {\n editor: Editor;\n fakeHighlightAbsRef: React.MutableRefObject<AbsRange | null>;\n lastSelectionRef: React.MutableRefObject<Editor['selection']>;\n updateFakeHighlightAbs: (abs: AbsRange | null) => void;\n updateActiveStyles: () => void;\n registerStepFontSize: (fn: (delta: number) => void) => void;\n}\n\nexport function useStepFontSize({\n editor,\n fakeHighlightAbsRef,\n lastSelectionRef,\n updateFakeHighlightAbs,\n updateActiveStyles,\n registerStepFontSize,\n}: StepFontSizeArgs): (delta: number) => void {\n const stepFontSize = useCallback(\n (delta: number) => {\n restoreSelection(editor, fakeHighlightAbsRef, lastSelectionRef);\n if (!editor.selection) return;\n\n if (Range.isCollapsed(editor.selection)) {\n stepCollapsed(editor, delta, updateActiveStyles);\n return;\n }\n\n const absStart = fakeHighlightAbsRef.current\n ? fakeHighlightAbsRef.current.absStart\n : pointToAbsOffset(editor, Range.edges(editor.selection)[0]);\n const absEnd = fakeHighlightAbsRef.current\n ? fakeHighlightAbsRef.current.absEnd\n : pointToAbsOffset(editor, Range.edges(editor.selection)[1]);\n\n const entries = collectTextEntries(editor);\n applyFontSizeEntries(editor, entries, delta);\n\n updateFakeHighlightAbs({ absStart, absEnd });\n const newStart = absOffsetToPoint(editor, absStart, true);\n const newEnd = absOffsetToPoint(editor, absEnd);\n if (newStart && newEnd) {\n // eslint-disable-next-line no-param-reassign\n editor.selection = { anchor: newStart, focus: newEnd };\n updateActiveStyles();\n }\n window.getSelection()?.removeAllRanges();\n },\n [editor, fakeHighlightAbsRef, lastSelectionRef, updateFakeHighlightAbs, updateActiveStyles]\n );\n\n useEffect(() => {\n registerStepFontSize(stepFontSize);\n }, [registerStepFontSize, stepFontSize]);\n\n return stepFontSize;\n}\n", "/**\n * useStepLineSpacing - Step line spacing up or down by delta (0.10 = 10%),\n * clamped to [1.00, 3.00]. When the selection spans blocks with mixed line\n * heights, each block is stepped independently (same pattern as useStepFontSize).\n */\n\nimport { useCallback, useEffect } from 'react';\nimport { Editor, Transforms, Range, Element as SlateElement, Text } from 'slate';\nimport { pointToAbsOffset, absOffsetToPoint } from './useFakeHighlight';\nimport type { AbsRange } from './useFakeHighlight';\n\nconst MIN_LINE_HEIGHT = 1.0;\nconst MAX_LINE_HEIGHT = 3.0;\nconst LINE_HEIGHT_STEP = 0.1;\n\nfunction clampLineHeight(value: number): number {\n return Math.min(MAX_LINE_HEIGHT, Math.max(MIN_LINE_HEIGHT, value));\n}\n\n/** True when every child of the element is inline (text or inline element). */\nfunction isLeafBlock(editor: Editor, node: SlateElement): boolean {\n return node.children.every(child => Text.isText(child) || editor.isInline(child));\n}\n\n/** Round to 2 decimal places to avoid floating-point drift. */\nfunction roundLineHeight(value: number): string {\n return clampLineHeight(value).toFixed(2);\n}\n\ninterface StepLineSpacingArgs {\n editor: Editor;\n fakeHighlightAbsRef: React.MutableRefObject<AbsRange | null>;\n lastSelectionRef: React.MutableRefObject<Editor['selection']>;\n updateFakeHighlightAbs: (abs: AbsRange | null) => void;\n updateActiveStyles: () => void;\n registerStepLineSpacing: (fn: (delta: number) => void) => void;\n}\n\nexport function useStepLineSpacing({\n editor,\n fakeHighlightAbsRef,\n lastSelectionRef,\n updateFakeHighlightAbs,\n updateActiveStyles,\n registerStepLineSpacing,\n}: StepLineSpacingArgs): (delta: number) => void {\n const stepLineSpacing = useCallback(\n (delta: number) => {\n // Restore selection from fake highlight or last known selection\n if (!editor.selection && fakeHighlightAbsRef.current) {\n const s = absOffsetToPoint(editor, fakeHighlightAbsRef.current.absStart, true);\n const e = absOffsetToPoint(editor, fakeHighlightAbsRef.current.absEnd);\n if (s && e) {\n // eslint-disable-next-line no-param-reassign\n editor.selection = { anchor: s, focus: e };\n }\n }\n if (!editor.selection && lastSelectionRef.current) {\n // eslint-disable-next-line no-param-reassign\n editor.selection = lastSelectionRef.current;\n }\n if (!editor.selection) return;\n\n const at = Range.isCollapsed(editor.selection)\n ? editor.selection\n : Editor.unhangRange(editor, editor.selection);\n\n // Save abs offsets before modifying the tree\n const absStart = fakeHighlightAbsRef.current\n ? fakeHighlightAbsRef.current.absStart\n : pointToAbsOffset(editor, Range.edges(editor.selection)[0]);\n const absEnd = fakeHighlightAbsRef.current\n ? fakeHighlightAbsRef.current.absEnd\n : pointToAbsOffset(editor, Range.edges(editor.selection)[1]);\n\n // Collect leaf blocks (blocks whose children are all inline) and step each independently\n const blocks = Array.from(\n Editor.nodes(editor, {\n at,\n match: n =>\n !Editor.isEditor(n) &&\n SlateElement.isElement(n) &&\n Editor.isBlock(editor, n) &&\n isLeafBlock(editor, n),\n })\n );\n\n const step = delta > 0 ? LINE_HEIGHT_STEP : -LINE_HEIGHT_STEP;\n for (let i = blocks.length - 1; i >= 0; i -= 1) {\n const [node, path] = blocks[i];\n const current = Number.parseFloat(\n (node as SlateElement & { lineHeight?: string }).lineHeight || '1.5'\n );\n Transforms.setNodes(\n editor,\n { lineHeight: roundLineHeight(current + step) } as Partial<SlateElement>,\n { at: path }\n );\n }\n\n // Preserve fake highlight\n updateFakeHighlightAbs({ absStart, absEnd });\n const newStart = absOffsetToPoint(editor, absStart, true);\n const newEnd = absOffsetToPoint(editor, absEnd);\n if (newStart && newEnd) {\n // eslint-disable-next-line no-param-reassign\n editor.selection = { anchor: newStart, focus: newEnd };\n updateActiveStyles();\n }\n window.getSelection()?.removeAllRanges();\n },\n [editor, fakeHighlightAbsRef, lastSelectionRef, updateFakeHighlightAbs, updateActiveStyles]\n );\n\n useEffect(() => {\n registerStepLineSpacing(stepLineSpacing);\n }, [registerStepLineSpacing, stepLineSpacing]);\n\n return stepLineSpacing;\n}\n", "/**\n * useFocusHandlers - Focus/blur management for the Slate editor.\n *\n * Handles: focus gating when not text-editing, blur deactivation with\n * configPanel detection, fake highlight on blur.\n */\n\nimport { useCallback } from 'react';\nimport { Editor, Range } from 'slate';\nimport { isSuppressBlurDeactivation, isMouseSelecting } from '../activeInstance';\nimport { safeDeselect } from '../utils/slateUtils';\n\ninterface FocusHandlersArgs {\n editor: Editor;\n editableRef: React.RefObject<HTMLDivElement | null>;\n hasFocusRef: React.MutableRefObject<boolean>;\n isTextEditingRef: React.MutableRefObject<boolean>;\n wasTextEditingRef: React.MutableRefObject<boolean>;\n /** Fallback selection ref -- continuously updated in handleChange. */\n lastSelectionRef: React.MutableRefObject<Editor['selection']>;\n /** When true, the fake highlight was explicitly dismissed and must not\n * reappear until the user makes a fresh expanded selection. */\n highlightDismissedRef: React.MutableRefObject<boolean>;\n saveSelection: () => void;\n onEnterSkipLinkFlow?: (selection: Range | null) => void;\n /** Save selection for Escape-from-panel without deactivating text editing. */\n onSavePreEditSelection?: (selection: Range | null) => void;\n updateFakeHighlight: (sel: Range | null) => void;\n updateFakeHighlightAbs: (abs: null) => void;\n onFocusGained?: (editable: HTMLDivElement | null, editor: Editor | null) => void;\n onFocusLost?: () => void;\n onDeactivateTextEditing?: () => void;\n}\n\ninterface FocusHandlersResult {\n handleFocus: () => void;\n handleBlur: (e: React.FocusEvent) => void;\n}\n\n/** Find the editor config panel element in the DOM. */\nfunction findConfigPanel(): Element | null {\n return (\n document\n .querySelector('[data-test=\"editor-richTextContent\"]')\n ?.closest('[class*=\"StyledInsetWrapper\"]') ||\n document.querySelector('[data-test=\"editor-richTextContent\"]') ||\n document.querySelector('[data-test=\"editor-purerichtext\"]') ||\n document.querySelector('[data-test=\"sidebar-content\"]') ||\n null\n );\n}\n\n/** Check if blur target is within a known panel UI element. */\nfunction isFocusInPanelUI(relatedTarget: HTMLElement | null, configPanel: Element | null): boolean {\n if (!relatedTarget) return false;\n const isSkipLink = relatedTarget.closest('[data-test=\"skip-link-config\"]') != null;\n const isPopover = relatedTarget.closest('[data-test=\"popover\"], [data-test-popover-id]') != null;\n const isMenu = relatedTarget.closest('[data-test=\"menu\"]') != null;\n const isSidebar = relatedTarget.closest('[data-test=\"sidebar-content\"]') != null;\n const isCollapsiblePanel = relatedTarget.closest('[data-test=\"collapsible-panel\"]') != null;\n const isVizConfigPanel = relatedTarget.closest('[data-test=\"viz-config-panel\"]') != null;\n const isFlyoutPane = relatedTarget.closest('[data-test=\"flyout-pane\"]') != null;\n return (\n Boolean(configPanel?.contains(relatedTarget)) ||\n isSkipLink ||\n isPopover ||\n isMenu ||\n isSidebar ||\n isCollapsiblePanel ||\n isVizConfigPanel ||\n isFlyoutPane\n );\n}\n\nexport function useFocusHandlers({\n editor,\n editableRef,\n hasFocusRef,\n isTextEditingRef,\n wasTextEditingRef,\n lastSelectionRef,\n highlightDismissedRef,\n saveSelection,\n onSavePreEditSelection,\n updateFakeHighlight,\n updateFakeHighlightAbs,\n onFocusGained,\n onFocusLost,\n onDeactivateTextEditing,\n}: FocusHandlersArgs): FocusHandlersResult {\n const handleFocus = useCallback(() => {\n if (wasTextEditingRef.current) {\n // Returning from config panel. For the Escape path the outer\n // component clears the highlight after restoring the selection\n // inside a rAF. For every other path (click back into editor,\n // focus via Tab, etc.) clear it now so it doesn't persist.\n // The Escape rAF runs after this and will set its own selection,\n // so a redundant clear here is harmless.\n updateFakeHighlightAbs(null);\n // eslint-disable-next-line no-param-reassign\n wasTextEditingRef.current = false;\n }\n if (!isTextEditingRef.current) {\n editableRef.current?.blur();\n safeDeselect(editor);\n window.getSelection()?.removeAllRanges();\n return;\n }\n // eslint-disable-next-line no-param-reassign\n hasFocusRef.current = true;\n onFocusGained?.(editableRef.current, editor);\n }, [onFocusGained, editor, editableRef, hasFocusRef, wasTextEditingRef, updateFakeHighlightAbs]);\n\n const handleBlur = useCallback(\n (e: React.FocusEvent) => {\n saveSelection();\n // eslint-disable-next-line no-param-reassign\n hasFocusRef.current = false;\n\n // Use the current editor selection, falling back to\n // lastSelectionRef (continuously updated in handleChange).\n const sel = editor.selection\n ? { anchor: { ...editor.selection.anchor }, focus: { ...editor.selection.focus } }\n : lastSelectionRef.current;\n\n // Only show fake highlight if:\n // - we are still text-editing\n // - the selection is expanded (not collapsed)\n // - the highlight was not explicitly dismissed (Escape / arrow key)\n const canShowFakeHighlight =\n isTextEditingRef.current && !highlightDismissedRef.current && sel && !Range.isCollapsed(sel);\n\n if (isSuppressBlurDeactivation()) {\n if (canShowFakeHighlight) {\n updateFakeHighlight(sel);\n }\n return;\n }\n\n if (isMouseSelecting()) {\n onFocusLost?.();\n return;\n }\n\n const relatedTarget = e.relatedTarget instanceof HTMLElement ? e.relatedTarget : null;\n const configPanel = findConfigPanel();\n const focusStaysInPanel = isFocusInPanelUI(relatedTarget, configPanel);\n\n if (focusStaysInPanel) {\n // Save selection for Escape-from-panel restoration.\n // Use savePreEditSelection (not enterSkipLinkFlow) so that\n // isTextEditing stays true -- keeps the Editable non-readOnly\n // and the caret visible while the user interacts with panel controls.\n onSavePreEditSelection?.(sel);\n if (canShowFakeHighlight) {\n updateFakeHighlight(sel);\n }\n window.getSelection()?.removeAllRanges();\n }\n\n if (!focusStaysInPanel) {\n updateFakeHighlight(null);\n // eslint-disable-next-line no-param-reassign\n wasTextEditingRef.current = false;\n // eslint-disable-next-line no-param-reassign\n lastSelectionRef.current = null;\n safeDeselect(editor);\n window.getSelection()?.removeAllRanges();\n onDeactivateTextEditing?.();\n }\n\n onFocusLost?.();\n },\n [\n saveSelection,\n hasFocusRef,\n editor,\n lastSelectionRef,\n isTextEditingRef,\n highlightDismissedRef,\n onFocusLost,\n updateFakeHighlight,\n onSavePreEditSelection,\n wasTextEditingRef,\n onDeactivateTextEditing,\n ]\n );\n\n return { handleFocus, handleBlur };\n}\n", "/**\n * useMouseHandlers - Mouse event handlers for the Slate editor.\n *\n * Handles: mousedown (text editing activation, drag-to-select stopPropagation),\n * empty-space click (caret placement), and drag prevention.\n */\n\nimport { useCallback } from 'react';\nimport { Editor, Range, Transforms } from 'slate';\nimport { setMouseSelecting, isMouseSelecting } from '../activeInstance';\nimport { safeSelectEnd } from '../utils/slateUtils';\n\ninterface MouseHandlersArgs {\n editor: Editor;\n editableRef: React.RefObject<HTMLDivElement | null>;\n containerRef: React.RefObject<HTMLDivElement | null>;\n isEditMode: boolean;\n isTextEditing: boolean;\n onActivateTextEditing?: () => void;\n clearFakeHighlight: () => void;\n}\n\ninterface MouseHandlersResult {\n handleMouseDown: (e: React.MouseEvent) => void;\n handleEmptySpaceClick: (e: React.MouseEvent) => void;\n handleDragStart: (e: React.DragEvent) => void;\n}\n\nexport function useMouseHandlers({\n editor,\n editableRef,\n isEditMode,\n isTextEditing,\n onActivateTextEditing,\n clearFakeHighlight,\n}: MouseHandlersArgs): MouseHandlersResult {\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n if (isEditMode && !isTextEditing) {\n onActivateTextEditing?.();\n setMouseSelecting(true);\n const onMouseUp = (): void => {\n document.removeEventListener('mouseup', onMouseUp, true);\n requestAnimationFrame(() => {\n setMouseSelecting(false);\n });\n };\n document.addEventListener('mouseup', onMouseUp, true);\n setTimeout(() => {\n editableRef.current?.focus({ preventScroll: true });\n }, 0);\n return;\n }\n\n if (isTextEditing) {\n clearFakeHighlight();\n e.stopPropagation();\n\n if (editor.selection && !Range.isCollapsed(editor.selection)) {\n Transforms.collapse(editor, { edge: 'focus' });\n window.getSelection()?.removeAllRanges();\n }\n\n setMouseSelecting(true);\n const onMouseUp = (ev: MouseEvent): void => {\n document.removeEventListener('mouseup', onMouseUp, true);\n ev.stopPropagation();\n requestAnimationFrame(() => {\n setMouseSelecting(false);\n });\n };\n document.addEventListener('mouseup', onMouseUp, true);\n }\n },\n [isEditMode, isTextEditing, onActivateTextEditing, editableRef, clearFakeHighlight]\n );\n\n const handleEmptySpaceClick = useCallback(\n (e: React.MouseEvent) => {\n if (!isTextEditing || !editableRef.current) return;\n if (isMouseSelecting()) return;\n const target = e.target as HTMLElement;\n if (target.closest('[data-slate-node]')) return;\n editableRef.current.focus({ preventScroll: true });\n safeSelectEnd(editor);\n },\n [isTextEditing, editor, editableRef]\n );\n\n const handleDragStart = useCallback(\n (e: React.DragEvent) => {\n if (isEditMode) {\n e.preventDefault();\n e.stopPropagation();\n }\n },\n [isEditMode]\n );\n\n return { handleMouseDown, handleEmptySpaceClick, handleDragStart };\n}\n", "/**\n * useEditModeEffect - Handles transitions out of edit mode.\n *\n * When leaving edit mode: deselects and blurs.\n * Text editing is NOT auto-activated on edit mode entry; the user must\n * explicitly press Enter.\n */\n\nimport { useRef, useEffect } from 'react';\nimport { Editor } from 'slate';\nimport { safeDeselect } from '../utils/slateUtils';\n\nexport function useEditModeEffect(\n editor: Editor,\n editableRef: React.RefObject<HTMLDivElement | null>,\n isEditMode: boolean\n): void {\n const prevIsEditModeRef = useRef(isEditMode);\n\n useEffect(() => {\n const wasEditMode = prevIsEditModeRef.current;\n prevIsEditModeRef.current = isEditMode;\n\n if (wasEditMode && !isEditMode) {\n safeDeselect(editor);\n editableRef.current?.blur();\n }\n }, [isEditMode, editor, editableRef]);\n}\n", "/**\n * InnerEditor - Slate editor wrapper with all editing hooks.\n *\n * Handles: editor setup, content sync, keyboard shortcuts, focus/blur,\n * mouse events, fake highlight, font size stepping, and edit mode transitions.\n */\n\nimport * as React from 'react';\nimport { useCallback, useMemo, useRef, useEffect } from 'react';\nimport { Descendant, Editor, Transforms } from 'slate';\nimport { Slate, Editable, RenderElementProps, RenderLeafProps } from 'slate-react';\nimport { usePureRichText } from './PureRichTextContext';\nimport { createElementRenderer } from './renderers/ElementRenderer';\nimport { Leaf } from './renderers/LeafRenderer';\nimport { FONT_FAMILY_WITH_FALLBACKS } from './types';\nimport { useEditorSetup, useInitialMarks } from './hooks/useEditorSetup';\nimport { useFakeHighlight } from './hooks/useFakeHighlight';\nimport { useContentSync } from './hooks/useContentSync';\nimport { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';\nimport { useStepFontSize } from './hooks/useStepFontSize';\nimport { useStepLineSpacing } from './hooks/useStepLineSpacing';\nimport { useFocusHandlers } from './hooks/useFocusHandlers';\nimport { useMouseHandlers } from './hooks/useMouseHandlers';\nimport { useEditModeEffect } from './hooks/useEditModeEffect';\nimport type { RichTextStateResult } from './hooks/useRichTextState';\n\nexport interface InnerEditorProps {\n initialValue: Descendant[];\n richTextContent: string;\n isEditMode: boolean;\n isTextEditing: boolean;\n containerRef: React.RefObject<HTMLDivElement | null>;\n defaultTextStyle: {\n color?: string;\n backgroundColor?: string;\n fontSize?: string;\n fontFamily?: string;\n lineHeight?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n };\n onContentChange: (html: string, immediate?: boolean) => void;\n onFocusGained?: (editable: HTMLDivElement | null, editor: Editor | null) => void;\n onFocusLost?: () => void;\n /** Consolidated text-editing lifecycle from useRichTextState. */\n richTextState?: Partial<RichTextStateResult>;\n onEditorReady?: (editor: Editor) => void;\n updateActiveStylesRef?: React.MutableRefObject<(() => void) | null>;\n clearFakeHighlightRef?: React.MutableRefObject<(() => void) | null>;\n /** Set by useContentSave; checked to detect round-trips and skip tree resets. */\n recentSavesRef?: React.MutableRefObject<Set<string>>;\n /** Callback for screenreader announcements on format changes. */\n onAnnouncement?: (message: string) => void;\n}\n\nexport const InnerEditor: React.FC<InnerEditorProps> = ({\n initialValue,\n richTextContent,\n isEditMode,\n isTextEditing,\n containerRef,\n defaultTextStyle,\n onContentChange,\n onFocusGained,\n onFocusLost,\n richTextState: richTextStateProp,\n onEditorReady,\n updateActiveStylesRef,\n clearFakeHighlightRef,\n recentSavesRef,\n onAnnouncement,\n}) => {\n const {\n setEditor,\n updateActiveStyles,\n saveSelection,\n applyFormat,\n resetToDefault,\n openLinkPopover,\n registerStepFontSize,\n registerStepLineSpacing,\n registerOnFormatApplied,\n registerAnnouncement,\n } = usePureRichText();\n\n // Extract richTextState callbacks. Fallback refs for tests that render\n // InnerEditor without the full richTextState object.\n const fallbackIsTextEditingRef = useRef(false);\n fallbackIsTextEditingRef.current = isTextEditing;\n const isTextEditingRef = richTextStateProp?.isTextEditingRef || fallbackIsTextEditingRef;\n const fallbackWasTextEditingRef = useRef(false);\n const wasTextEditingRef = richTextStateProp?.wasTextEditingRef || fallbackWasTextEditingRef;\n const onActivateTextEditing = richTextStateProp?.activateTextEditing;\n const onDeactivateTextEditing = richTextStateProp?.deactivateTextEditing;\n const onEnterSkipLinkFlow = richTextStateProp?.enterSkipLinkFlow;\n const onSavePreEditSelection = richTextStateProp?.savePreEditSelection;\n\n // Keep defaultTextStyle accessible to the editor's insertText override via ref\n const defaultTextStyleRef = useRef(defaultTextStyle);\n defaultTextStyleRef.current = defaultTextStyle;\n\n // Create editor instance with inline element support\n const editor = useEditorSetup(defaultTextStyleRef);\n\n // Set editor in context and notify parent\n useEffect(() => {\n setEditor(editor);\n onEditorReady?.(editor);\n }, [editor, setEditor, onEditorReady]);\n\n // Expose updateActiveStyles to parent via ref\n useEffect(() => {\n if (updateActiveStylesRef) {\n // eslint-disable-next-line no-param-reassign\n updateActiveStylesRef.current = updateActiveStyles;\n }\n }, [updateActiveStyles, updateActiveStylesRef]);\n\n // Register callback so applyFormat keeps preEditSelection up-to-date.\n // Without this, Escape-from-panel after a format change (especially with\n // a collapsed caret) would use the stale preEditSelection from Shift+Tab\n // time, causing the caret to jump to the wrong position.\n useEffect(() => {\n if (onSavePreEditSelection) {\n registerOnFormatApplied(onSavePreEditSelection);\n }\n }, [registerOnFormatApplied, onSavePreEditSelection]);\n\n // Register screenreader announcement callback so format changes\n // are announced via the aria-live region in PureRichText.\n useEffect(() => {\n if (onAnnouncement) {\n registerAnnouncement(onAnnouncement);\n }\n }, [registerAnnouncement, onAnnouncement]);\n\n // Initialize marks for empty editor (only once on mount)\n useInitialMarks(editor, isEditMode, defaultTextStyle);\n\n // Ref to the editable DOM element\n const editableRef = useRef<HTMLDivElement | null>(null);\n\n // Last known selection -- used by stepFontSize when editor.selection is null\n const lastSelectionRef = useRef<Editor['selection']>(null);\n\n // Handle edit mode transitions (deselect/blur on leave)\n useEditModeEffect(editor, editableRef, isEditMode);\n\n // Track if editor has focus\n const hasFocusRef = useRef(false);\n // Flag to bypass the hasFocusRef guard in useContentSync for in-editor undo/redo\n const forceNextSyncRef = useRef(false);\n\n // Fake highlight system\n const { fakeHighlightAbsRef, updateFakeHighlight, updateFakeHighlightAbs, decorate } =\n useFakeHighlight(editor);\n\n // When true, the fake highlight was explicitly dismissed (Escape, arrow key)\n // and must not reappear until the user makes a fresh expanded selection.\n const highlightDismissedRef = useRef(false);\n\n // Expose clearFakeHighlight to parent via ref.\n // Only clears the visual fake highlight and lastSelectionRef.\n // Does NOT set highlightDismissedRef or touch editor.selection.\n // Callers that want a permanent dismiss (Escape on skip-link)\n // handle those separately.\n useEffect(() => {\n if (clearFakeHighlightRef) {\n // eslint-disable-next-line no-param-reassign\n clearFakeHighlightRef.current = () => {\n updateFakeHighlightAbs(null);\n lastSelectionRef.current = null;\n };\n }\n }, [clearFakeHighlightRef, updateFakeHighlightAbs]);\n\n // Content sync and onChange handler\n const { value, handleChange } = useContentSync({\n editor,\n initialValue,\n richTextContent,\n onContentChange,\n updateActiveStyles,\n updateFakeHighlightAbs,\n fakeHighlightAbsRef,\n hasFocusRef,\n lastSelectionRef,\n recentSavesRef,\n forceNextSyncRef,\n });\n\n // Step font size (registers itself via registerStepFontSize)\n const stepFontSize = useStepFontSize({\n editor,\n fakeHighlightAbsRef,\n lastSelectionRef,\n updateFakeHighlightAbs,\n updateActiveStyles,\n registerStepFontSize,\n });\n\n // Step line spacing (registers itself via registerStepLineSpacing)\n useStepLineSpacing({\n editor,\n fakeHighlightAbsRef,\n lastSelectionRef,\n updateFakeHighlightAbs,\n updateActiveStyles,\n registerStepLineSpacing,\n });\n\n // Keyboard shortcuts\n const { handleKeyDown: handleKeyboardShortcuts } = useKeyboardShortcuts({\n editor,\n applyFormat,\n resetToDefault,\n openLinkPopover,\n stepFontSize,\n });\n\n // Focus and blur handlers\n const { handleFocus, handleBlur } = useFocusHandlers({\n editor,\n editableRef,\n hasFocusRef,\n isTextEditingRef,\n wasTextEditingRef,\n lastSelectionRef,\n highlightDismissedRef,\n saveSelection,\n onEnterSkipLinkFlow,\n onSavePreEditSelection,\n updateFakeHighlight,\n updateFakeHighlightAbs,\n onFocusGained,\n onFocusLost,\n onDeactivateTextEditing,\n });\n\n // Mouse event handlers\n const {\n handleMouseDown: baseHandleMouseDown,\n handleEmptySpaceClick,\n handleDragStart,\n } = useMouseHandlers({\n editor,\n editableRef,\n containerRef,\n isEditMode,\n isTextEditing,\n onActivateTextEditing,\n clearFakeHighlight: () => updateFakeHighlightAbs(null),\n });\n\n // Wrap mouseDown to also reset the highlight-dismissed flag so the next\n // Shift+Tab after a fresh mouse selection will show the fake highlight.\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n highlightDismissedRef.current = false;\n baseHandleMouseDown(e);\n },\n [baseHandleMouseDown]\n );\n\n // Wrap handleKeyDown: Escape exits text editing, Tab exits editing.\n // Returns true when Slate should skip its own processing for this key.\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent): boolean | void => {\n if (!isTextEditingRef.current) {\n return undefined;\n }\n if (event.key === 'Escape') {\n event.preventDefault();\n highlightDismissedRef.current = true;\n try {\n Transforms.deselect(editor);\n } catch (e) {\n // Ignore if editor is empty\n }\n window.getSelection()?.removeAllRanges();\n onDeactivateTextEditing?.();\n editableRef.current?.blur();\n const selectOutline = editableRef.current?.closest<HTMLElement>(\n '[data-test=\"select-outline\"]'\n );\n if (selectOutline) {\n if (!selectOutline.getAttribute('tabindex')) {\n selectOutline.setAttribute('tabindex', '-1');\n }\n selectOutline.focus({ preventScroll: true });\n }\n return undefined;\n }\n if (event.key === 'Tab' && event.shiftKey) {\n // Shift+Tab: allow fake highlight for this blur cycle, save\n // selection for Escape-from-panel restoration, then let the\n // document capture handler focus the skip link.\n // isTextEditing stays true so:\n // 1. Parent's initialValue memo stays guarded (prevents tree resets)\n // 2. Editable stays non-readOnly (caret visible via fake highlight)\n highlightDismissedRef.current = false;\n onSavePreEditSelection?.(editor.selection);\n if (wasTextEditingRef) {\n // eslint-disable-next-line no-param-reassign\n wasTextEditingRef.current = true;\n }\n return undefined;\n }\n // Cmd+Z / Cmd+Shift+Z: delegate undo/redo to the dashboard.\n // Flush pending saves so the dashboard has the latest state, then\n // set forceNextSyncRef so useContentSync accepts the reverted\n // richTextContent prop even though the editor retains focus.\n // Return true so Slate skips its own undo handler (which calls\n // preventDefault and would swallow the event).\n const mod = event.metaKey || event.ctrlKey;\n if (mod && event.key.toLowerCase() === 'z') {\n onFocusLost?.();\n forceNextSyncRef.current = true;\n return true;\n }\n handleKeyboardShortcuts(event);\n return undefined;\n },\n [\n editor,\n editableRef,\n handleKeyboardShortcuts,\n onDeactivateTextEditing,\n onFocusLost,\n onSavePreEditSelection,\n wasTextEditingRef,\n ]\n );\n\n // Render element callback\n const ElementRenderer = useMemo(\n () => createElementRenderer(isEditMode, defaultTextStyle.lineHeight || '1.5'),\n [isEditMode, defaultTextStyle.lineHeight]\n );\n const renderElement = useCallback(\n (props: RenderElementProps) => <ElementRenderer {...props} />,\n [ElementRenderer]\n );\n\n // Render leaf callback\n const renderLeaf = useCallback((props: RenderLeafProps) => <Leaf {...props} />, []);\n\n // Default styling for the editable area\n const editableStyle: React.CSSProperties = {\n color: defaultTextStyle.color || '#ffffff',\n fontSize: defaultTextStyle.fontSize || '14px',\n fontFamily:\n FONT_FAMILY_WITH_FALLBACKS[defaultTextStyle.fontFamily] ||\n defaultTextStyle.fontFamily ||\n FONT_FAMILY_WITH_FALLBACKS['Splunk Data Sans'],\n lineHeight: defaultTextStyle.lineHeight || '1.5',\n };\n\n return (\n <div\n role=\"none\"\n suppressContentEditableWarning\n onMouseDown={handleMouseDown}\n onClick={handleEmptySpaceClick}\n style={\n isTextEditing ? undefined : { minHeight: '100%', caretColor: 'transparent', outline: 'none' }\n }\n >\n <Slate editor={editor} initialValue={value} onChange={handleChange}>\n <Editable\n readOnly={!isTextEditing}\n tabIndex={isTextEditing ? 0 : -1}\n aria-label=\"Rich text editor\"\n decorate={decorate}\n renderElement={renderElement}\n renderLeaf={renderLeaf}\n style={editableStyle}\n ref={editableRef}\n onKeyDown={handleKeyDown}\n onDragStart={handleDragStart}\n onFocus={handleFocus}\n onBlur={handleBlur}\n placeholder={isTextEditing ? 'Enter text...' : ''}\n spellCheck={false}\n draggable={false}\n />\n </Slate>\n </div>\n );\n};\n", "/**\n * useRichTextState - Centralized state management for RichText editing lifecycle.\n *\n * Replaces scattered isTextEditing / isTextEditingRef / wasTextEditingRef / activateTextEditing\n * with a single hook that co-locates state, refs, and transition functions.\n *\n * Stores preEditSelection so Escape-from-config-panel can restore the caret reliably.\n */\n\nimport { useState, useCallback, useRef } from 'react';\nimport { flushSync } from 'react-dom';\nimport { Range } from 'slate';\n\nexport interface RichTextStateResult {\n /** Whether the user is actively editing text (caret visible). */\n isTextEditing: boolean;\n /** Imperative ref always in sync with isTextEditing (for event handlers that read mid-render). */\n isTextEditingRef: React.MutableRefObject<boolean>;\n /** Whether the user was text-editing before entering the skip-link/config-panel flow.\n * Exposed as a ref so document-level event listeners (stale closures) read the latest value. */\n wasTextEditingRef: React.MutableRefObject<boolean>;\n /** Activate text editing (Enter-to-edit, click-to-edit). */\n activateTextEditing: () => void;\n /** Deactivate text editing (Escape, blur, etc.). Clears preEditSelection. */\n deactivateTextEditing: () => void;\n /** Transition from text-editing to skip-link/config-panel flow.\n * Stores the current selection so it can be restored on Escape-from-panel.\n * Sets wasTextEditing = true and isTextEditing = false. */\n enterSkipLinkFlow: (selection: Range | null) => void;\n /** Re-enter text editing from config panel (Escape-from-panel).\n * Sets isTextEditing = true. preEditSelection is preserved for the caller to read. */\n returnFromConfigPanel: () => void;\n /** Save the pre-edit selection without changing isTextEditing or wasTextEditing.\n * Used when focus moves to the panel via mouse click (caret should stay visible). */\n savePreEditSelection: (selection: Range | null) => void;\n /** Read the selection that was saved when entering the skip-link flow. */\n getPreEditSelection: () => Range | null;\n /** Reset wasTextEditing to false (after skip-link Enter handler consumes it). */\n clearWasTextEditing: () => void;\n}\n\nexport function useRichTextState(): RichTextStateResult {\n const [isTextEditing, setIsTextEditing] = useState(false);\n const isTextEditingRef = useRef(false);\n // Keep ref in sync on every render\n isTextEditingRef.current = isTextEditing;\n\n const wasTextEditingRef = useRef(false);\n const preEditSelectionRef = useRef<Range | null>(null);\n\n const activateTextEditing = useCallback(() => {\n setIsTextEditing(true);\n isTextEditingRef.current = true;\n }, []);\n\n const deactivateTextEditing = useCallback(() => {\n setIsTextEditing(false);\n isTextEditingRef.current = false;\n // Only clear the saved selection if we are NOT in the skip-link/config-panel\n // flow. During that flow enterSkipLinkFlow() stores the selection so\n // Escape-from-panel can restore it; a subsequent blur-triggered deactivate\n // must not wipe it.\n if (!wasTextEditingRef.current) {\n preEditSelectionRef.current = null;\n }\n }, []);\n\n const enterSkipLinkFlow = useCallback((selection: Range | null) => {\n preEditSelectionRef.current = selection\n ? { anchor: { ...selection.anchor }, focus: { ...selection.focus } }\n : null;\n wasTextEditingRef.current = true;\n setIsTextEditing(false);\n isTextEditingRef.current = false;\n }, []);\n\n const returnFromConfigPanel = useCallback(() => {\n // preEditSelection is intentionally preserved so the caller can read it\n // after this transition to restore the caret position.\n // flushSync forces React to commit the state update synchronously so\n // that <Editable readOnly={false}> is in the DOM before the caller\n // focuses and restores the selection. Without this, React 18 batches\n // the update and the editor may still be readOnly when focus() runs,\n // causing Slate-React's onDOMSelectionChange to deselect.\n isTextEditingRef.current = true;\n flushSync(() => {\n setIsTextEditing(true);\n });\n }, []);\n\n const savePreEditSelection = useCallback((selection: Range | null) => {\n preEditSelectionRef.current = selection\n ? { anchor: { ...selection.anchor }, focus: { ...selection.focus } }\n : null;\n }, []);\n\n const getPreEditSelection = useCallback((): Range | null => {\n return preEditSelectionRef.current;\n }, []);\n\n const clearWasTextEditing = useCallback(() => {\n wasTextEditingRef.current = false;\n }, []);\n\n return {\n isTextEditing,\n isTextEditingRef,\n wasTextEditingRef,\n activateTextEditing,\n deactivateTextEditing,\n enterSkipLinkFlow,\n returnFromConfigPanel,\n savePreEditSelection,\n getPreEditSelection,\n clearWasTextEditing,\n };\n}\n", "/**\n * useTokenMap - Builds a mapping of resolved token values back to their\n * $token$ patterns by comparing the raw dashboard definition against the\n * resolved richTextContent prop.\n *\n * This allows the editor to work with resolved content (what the user sees)\n * while saving HTML that preserves $token$ patterns in the dashboard definition.\n */\n\nimport { useMemo, useState, useEffect } from 'react';\nimport { Descendant, Text, Element } from 'slate';\nimport type { CustomElement, CustomText } from '../types';\n\n/** Regex that matches $token_name$ patterns. */\nconst TOKEN_PATTERN = /\\$([a-zA-Z_]\\w*)\\$/g;\n\ninterface DashboardCoreApi {\n getDefinition?: () => {\n visualizations?: Record<string, { options?: Record<string, unknown> }>;\n };\n}\n\n/**\n * Extract the viz ID from the DOM by walking up to the nearest viz-item.\n */\nfunction getVizIdFromDom(containerRef: React.RefObject<HTMLDivElement | null>): string | null {\n const vizItem = containerRef.current?.closest<HTMLElement>('[data-test=\"viz-item\"]');\n return vizItem?.dataset?.id ?? null;\n}\n\n/**\n * Read the raw richTextContent from the dashboard definition.\n */\nfunction getRawContent(\n api: DashboardCoreApi | null,\n containerRef: React.RefObject<HTMLDivElement | null>\n): string | null {\n if (!api?.getDefinition) return null;\n const vizId = getVizIdFromDom(containerRef);\n if (!vizId) return null;\n try {\n const def = api.getDefinition();\n const rawContent = def?.visualizations?.[vizId]?.options?.richTextContent;\n return typeof rawContent === 'string' ? rawContent : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Build a token map by comparing raw content (with $token$ patterns) against\n * resolved content (with actual values). Returns a map of resolvedValue -> $tokenName$.\n *\n * Works by escaping the raw content as a regex, replacing $token$ patterns with\n * capture groups, and matching against the resolved content.\n */\nexport function buildTokenMap(rawContent: string, resolvedContent: string): Map<string, string> {\n const map = new Map<string, string>();\n const tokens: string[] = [];\n\n // Collect all token names in order\n let match: RegExpExecArray | null;\n const re = new RegExp(TOKEN_PATTERN.source, 'g');\n match = re.exec(rawContent);\n while (match !== null) {\n tokens.push(match[1]);\n match = re.exec(rawContent);\n }\n if (tokens.length === 0) return map;\n\n // Build a regex from the raw content: escape everything, then replace\n // each $token$ with a capture group that matches the resolved value.\n const escapedParts = rawContent.split(TOKEN_PATTERN);\n // split produces: [before, name1, between, name2, between, ...]\n // We want to rebuild as: escaped(before) + (.*?) + escaped(between) + ...\n let pattern = '';\n for (let i = 0; i < escapedParts.length; i += 1) {\n if (i % 2 === 0) {\n // Literal part -- escape for regex\n pattern += escapedParts[i].replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n } else {\n // Token name part -- replace with capture group\n pattern += '([\\\\s\\\\S]*?)';\n }\n }\n\n const fullMatch = new RegExp(`^${pattern}$`).exec(resolvedContent);\n if (!fullMatch) return map;\n\n for (let i = 0; i < tokens.length; i += 1) {\n const resolved = fullMatch[i + 1];\n if (resolved !== undefined) {\n map.set(resolved, `$${tokens[i]}$`);\n }\n }\n return map;\n}\n\n/**\n * Replace resolved token values in HTML back to their $token$ patterns.\n * Replaces all occurrences of each resolved value.\n */\nexport function restoreTokens(html: string, tokenMap: Map<string, string>): string {\n if (tokenMap.size === 0) return html;\n let result = html;\n // Sort by longest resolved value first to avoid partial replacements.\n // Filter out empty resolutions to avoid infinite splits.\n const entries = [...tokenMap.entries()]\n .filter(([resolved]) => resolved !== '')\n .sort((a, b) => b[0].length - a[0].length);\n for (const [resolved, tokenPattern] of entries) {\n result = result.split(resolved).join(tokenPattern);\n }\n return result;\n}\n\n/**\n * Walk a Slate tree and mark resolved token values with a `tokenName` text\n * mark. This allows the editor to treat them as regular styled text (bold,\n * color, etc. all work) while identifying which spans are tokens for\n * save-time restoration.\n */\nexport function wrapTokensInTree(nodes: Descendant[], tokenMap: Map<string, string>): Descendant[] {\n if (tokenMap.size === 0) return nodes;\n\n // Build lookup: resolvedValue -> tokenName (without $ delimiters)\n const resolvedToName = new Map<string, string>();\n for (const [resolved, pattern] of tokenMap) {\n if (resolved === '') return nodes;\n const name = pattern.slice(1, -1); // strip $ delimiters\n resolvedToName.set(resolved, name);\n }\n\n const processNode = (node: Descendant): Descendant[] => {\n if (Text.isText(node)) {\n return splitTextByTokens(node as CustomText, resolvedToName);\n }\n if (Element.isElement(node)) {\n const el = node as CustomElement;\n return [{ ...el, children: el.children.flatMap(processNode) } as CustomElement];\n }\n return [node];\n };\n\n return nodes.flatMap(processNode);\n}\n\n/**\n * Split a text node at token boundaries, producing regular text nodes and\n * token-marked text nodes. The token-marked text node has `tokenName` set\n * and retains all existing marks (bold, color, etc.).\n */\nfunction splitTextByTokens(textNode: CustomText, resolvedToName: Map<string, string>): Descendant[] {\n const { text, ...marks } = textNode;\n if (!text) return [textNode];\n\n // Sort by longest resolved value first to avoid partial matches\n const entries = [...resolvedToName.entries()].sort((a, b) => b[0].length - a[0].length);\n\n // Find the first token match in the text\n let earliestIdx = -1;\n let matchedResolved = '';\n let matchedName = '';\n\n for (const [resolved, name] of entries) {\n const idx = text.indexOf(resolved);\n if (idx !== -1 && (earliestIdx === -1 || idx < earliestIdx)) {\n earliestIdx = idx;\n matchedResolved = resolved;\n matchedName = name;\n }\n }\n\n if (earliestIdx === -1) return [textNode]; // no tokens in this text\n\n const result: Descendant[] = [];\n\n // Text before the token\n if (earliestIdx > 0) {\n result.push({ text: text.slice(0, earliestIdx), ...marks } as CustomText);\n }\n\n // Token text node -- regular text with tokenName mark added\n result.push({ text: matchedResolved, ...marks, tokenName: matchedName } as CustomText);\n\n // Recursively process remaining text after the token\n const after = text.slice(earliestIdx + matchedResolved.length);\n if (after) {\n const afterNode = { text: after, ...marks } as CustomText;\n result.push(...splitTextByTokens(afterNode, resolvedToName));\n }\n\n return result;\n}\n\nexport interface TokenMapResult {\n /** Replace resolved token values in HTML back to $token$ patterns. */\n restoreTokensInHtml: (html: string) => string;\n /** The raw token map (resolvedValue -> $tokenName$). */\n tokenMap: Map<string, string>;\n}\n\n/**\n * Hook that maintains a token map from the raw dashboard definition.\n * Returns a function to restore $token$ patterns in editor-emitted HTML.\n */\nconst EMPTY_MAP = new Map<string, string>();\n\nexport function useTokenMap(\n dashboardCoreApi: DashboardCoreApi | null,\n containerRef: React.RefObject<HTMLDivElement | null>,\n resolvedContent: string\n): TokenMapResult {\n const [tokenMap, setTokenMap] = useState<Map<string, string>>(EMPTY_MAP);\n\n useEffect(() => {\n const raw = getRawContent(dashboardCoreApi, containerRef);\n if (!raw) {\n setTokenMap(prev => (prev.size === 0 ? prev : EMPTY_MAP));\n return;\n }\n const map = buildTokenMap(raw, resolvedContent);\n setTokenMap(map);\n }, [dashboardCoreApi, resolvedContent, containerRef]);\n\n const restoreTokensInHtml = useMemo(() => {\n if (tokenMap.size === 0) return (html: string) => html;\n return (html: string) => restoreTokens(html, tokenMap);\n }, [tokenMap]);\n\n return { restoreTokensInHtml, tokenMap };\n}\n", "/**\n * useContentSave - Synchronous content save with smart typing batches.\n *\n * Replaces useDebouncedSave. Key differences:\n * - Format and structural changes (Enter, Delete, bold, alignment) save immediately\n * - Typing batches with a short idle timer so undo reverts a chunk, not one char\n * - Token restoration before every save\n * - recentSavesRef (Set) for round-trip detection in useContentSync\n */\n\nimport { useCallback, useRef, useEffect } from 'react';\n\ninterface ContentSaveArgs {\n richTextContent: string;\n onOptionsChange?: (options: Record<string, unknown>) => void;\n restoreTokensInHtml: (html: string) => string;\n}\n\ninterface ContentSaveResult {\n /** Called by useContentSync on every content change. immediate=true skips batching. */\n handleContentChange: (html: string, immediate?: boolean) => void;\n /** Flush any pending batched typing content (blur, unmount). */\n flushPendingChanges: () => void;\n /** Tracks recently saved HTML values for round-trip detection. */\n recentSavesRef: React.MutableRefObject<Set<string>>;\n}\n\n/** Idle timeout for typing batches (ms). Balances undo granularity with responsiveness. */\nconst TYPING_IDLE_MS = 300;\n\nexport function useContentSave({\n richTextContent,\n onOptionsChange,\n restoreTokensInHtml,\n}: ContentSaveArgs): ContentSaveResult {\n const idleTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingHtmlRef = useRef<string | null>(null);\n // Track all in-flight save values so round-trips are detected even when\n // multiple saves overlap (e.g. rapid typing produces batch N and N+1 before\n // round-trip N arrives). Values are removed as round-trips are consumed.\n const recentSavesRef = useRef<Set<string>>(new Set());\n\n // Keep current values in refs so `save` has a stable identity.\n // Without this, `save` would depend on richTextContent/onOptionsChange/\n // restoreTokensInHtml, causing flushPendingChanges to change identity on\n // every save round-trip, which re-runs the cleanup effect in PureRichText\n // and clears the active instance (panel disappears).\n const richTextContentRef = useRef(richTextContent);\n richTextContentRef.current = richTextContent;\n const onOptionsChangeRef = useRef(onOptionsChange);\n onOptionsChangeRef.current = onOptionsChange;\n const restoreTokensInHtmlRef = useRef(restoreTokensInHtml);\n restoreTokensInHtmlRef.current = restoreTokensInHtml;\n\n // Cancel pending batch when richTextContent changes externally (undo/redo).\n // Skip cancellation for our own save round-trips so that characters typed\n // between a batch send and its round-trip are not silently dropped.\n useEffect(() => {\n if (recentSavesRef.current.has(richTextContent)) {\n // Round-trip from our own save -- consume it and keep in-flight batches.\n recentSavesRef.current.delete(richTextContent);\n return;\n }\n // External change (undo/redo) -- cancel pending batch and clear all tracked saves.\n recentSavesRef.current.clear();\n if (idleTimerRef.current) {\n clearTimeout(idleTimerRef.current);\n idleTimerRef.current = null;\n }\n pendingHtmlRef.current = null;\n }, [richTextContent]);\n\n // Core save: restore tokens and dispatch to dashboard.\n // Stable identity -- reads props from refs.\n const save = useCallback((html: string): void => {\n if (!onOptionsChangeRef.current) return;\n const htmlWithTokens = restoreTokensInHtmlRef.current(html);\n if (htmlWithTokens === richTextContentRef.current) return;\n recentSavesRef.current.add(htmlWithTokens);\n onOptionsChangeRef.current({ richTextContent: htmlWithTokens });\n }, []);\n\n // Handle content change from the editor.\n // immediate=true for structural/format ops; false (default) for typing.\n const handleContentChange = useCallback(\n (html: string, immediate?: boolean): void => {\n if (immediate) {\n // Clear any pending typing batch -- the structural change supersedes it\n if (idleTimerRef.current) {\n clearTimeout(idleTimerRef.current);\n idleTimerRef.current = null;\n }\n pendingHtmlRef.current = null;\n save(html);\n return;\n }\n // Typing: batch with idle timer\n pendingHtmlRef.current = html;\n if (idleTimerRef.current) {\n clearTimeout(idleTimerRef.current);\n }\n idleTimerRef.current = setTimeout(() => {\n if (pendingHtmlRef.current !== null) {\n save(pendingHtmlRef.current);\n pendingHtmlRef.current = null;\n }\n }, TYPING_IDLE_MS);\n },\n [save]\n );\n\n // Flush pending typing content immediately (blur, unmount)\n const flushPendingChanges = useCallback((): void => {\n if (idleTimerRef.current) {\n clearTimeout(idleTimerRef.current);\n idleTimerRef.current = null;\n }\n if (pendingHtmlRef.current) {\n save(pendingHtmlRef.current);\n pendingHtmlRef.current = null;\n }\n }, [save]);\n\n return { handleContentChange, flushPendingChanges, recentSavesRef };\n}\n", "/**\n * useDashboardKeyboardNav - Document-level keyboard navigation for PureRichText.\n *\n * Handles: Tab/Shift+Tab skip-link behavior, Escape from sidebar,\n * Enter-to-edit activation, skip-link activation, focus-out deselection,\n * and viz-item selection observation.\n *\n * See keyboard reference sections D and E in the component knowledge base.\n */\n\nimport { useEffect, useRef } from 'react';\nimport { Editor, Transforms } from 'slate';\nimport { ReactEditor } from 'slate-react';\nimport { registerActiveRichText } from '../activeInstance';\nimport { safeDeselect, safeSelectEnd } from '../utils/slateUtils';\n\ninterface DashboardKeyboardNavArgs {\n isEditMode: boolean;\n containerRef: React.RefObject<HTMLDivElement | null>;\n instanceId: string;\n slateEditorRef: React.MutableRefObject<Editor | null>;\n isTextEditingRef: React.MutableRefObject<boolean>;\n wasTextEditingRef: React.MutableRefObject<boolean>;\n clearFakeHighlightRef: React.MutableRefObject<(() => void) | null>;\n updateActiveStylesFnRef: React.MutableRefObject<(() => void) | null>;\n activateTextEditing: () => void;\n richTextState: {\n deactivateTextEditing: () => void;\n getPreEditSelection: () => Editor['selection'];\n returnFromConfigPanel: () => void;\n clearWasTextEditing: () => void;\n };\n dashboardCoreApi: {\n updateSelectedItems: (items?: unknown[]) => void;\n } | null;\n}\n\ninterface SkipLinkAndFocusOutArgs {\n isEditMode: boolean;\n containerRef: React.RefObject<HTMLDivElement | null>;\n slateEditorRef: React.MutableRefObject<Editor | null>;\n wasTextEditingRef: React.MutableRefObject<boolean>;\n clearFakeHighlightRef: React.MutableRefObject<(() => void) | null>;\n deactivateTextEditing: () => void;\n dashboardCoreApi: DashboardKeyboardNavArgs['dashboardCoreApi'];\n}\n\n/**\n * Listener 1: Skip-link Tab/Shift+Tab behavior and focusout deselection.\n *\n * - Escape on skip-link: hide link, deselect viz\n * - Shift+Tab on skip-link: hide, let focus leave\n * - Shift+Tab elsewhere in viz: show & focus skip-link\n * - Forward Tab: hide skip links\n * - focusout: deselect if focus leaves viz (unless to sidebar/panel/popover)\n */\nfunction useSkipLinkAndFocusOut({\n isEditMode,\n containerRef,\n slateEditorRef,\n wasTextEditingRef,\n clearFakeHighlightRef,\n deactivateTextEditing,\n dashboardCoreApi,\n}: SkipLinkAndFocusOutArgs): void {\n useEffect(() => {\n if (!isEditMode) return undefined;\n\n const vizItem = containerRef.current?.closest<HTMLElement>('[data-test=\"viz-item\"]');\n if (!vizItem) return undefined;\n\n const handleEscapeOnSkipLink = (configLink: HTMLElement | null): void => {\n if (configLink) configLink.setAttribute('tabindex', '-1');\n clearFakeHighlightRef.current?.();\n // Clear the editor selection so a subsequent Shift+Tab cannot\n // re-create the fake highlight from a stale expanded selection.\n const ed = slateEditorRef.current;\n if (ed) {\n safeDeselect(ed);\n }\n // Fully exit text editing so the Editable becomes readOnly and\n // the parent's initialValue memo re-gates behind isTextEditing.\n deactivateTextEditing();\n // eslint-disable-next-line no-param-reassign\n wasTextEditingRef.current = false;\n if (dashboardCoreApi) {\n dashboardCoreApi.updateSelectedItems([]);\n }\n };\n\n // When the user Shift+Tabs OFF the skip link, focus lands on the\n // viz-item. The next Shift+Tab should let focus leave the viz entirely\n // rather than re-showing the skip link.\n let skipLinkJustHidden = false;\n\n const handleShiftTab = (\n e: KeyboardEvent,\n target: HTMLElement,\n configLink: HTMLElement | null\n ): void => {\n // If on the skip link, hide it and let focus leave backward.\n if (target.closest('[data-test=\"skip-link-config\"]')) {\n if (configLink) configLink.setAttribute('tabindex', '-1');\n skipLinkJustHidden = true;\n return;\n }\n // If we just hid the skip link, don't re-show it -- let focus\n // leave the viz naturally.\n if (skipLinkJustHidden) {\n skipLinkJustHidden = false;\n return;\n }\n // Shift+Tab from anywhere else in the viz: focus the skip link.\n if (configLink) {\n e.preventDefault();\n configLink.setAttribute('tabindex', '0');\n configLink.focus();\n }\n };\n\n const handleForwardTab = (configLink: HTMLElement | null): void => {\n if (configLink) configLink.setAttribute('tabindex', '-1');\n const actionMenuLink = vizItem.querySelector<HTMLElement>('[data-test=\"skip-link-action-menu\"]');\n if (actionMenuLink) actionMenuLink.setAttribute('tabindex', '-1');\n };\n\n const handleKeyDown = (e: KeyboardEvent): void => {\n if (!vizItem.contains(e.target as HTMLElement)) return;\n const target = e.target as HTMLElement;\n const configLink = vizItem.querySelector<HTMLElement>('[data-test=\"skip-link-config\"]');\n\n if (e.key === 'Escape' && target.closest('[data-test=\"skip-link-config\"]')) {\n e.preventDefault();\n handleEscapeOnSkipLink(configLink);\n return;\n }\n\n if (e.key !== 'Tab') return;\n\n if (e.shiftKey) {\n handleShiftTab(e, target, configLink);\n } else {\n handleForwardTab(configLink);\n }\n };\n\n const handleFocusOut = (e: FocusEvent): void => {\n const relatedTarget = e.relatedTarget as HTMLElement | null;\n if (!relatedTarget) return;\n if (vizItem.contains(relatedTarget)) return;\n // Don't deselect if focus moved to the editor sidebar or a popover\n // (color picker, select dropdown, link editor, etc. are portaled to the body)\n if (\n relatedTarget.closest('[data-test=\"sidebar-content\"]') ||\n relatedTarget.id === 'configuration-back-button' ||\n relatedTarget.closest('#configuration-back-button') ||\n relatedTarget.closest('[data-test=\"popover\"]') ||\n relatedTarget.closest('[data-test-popover-id]') ||\n relatedTarget.closest('[data-test=\"menu\"]') ||\n relatedTarget.closest('[role=\"dialog\"]') ||\n relatedTarget.closest('[data-layer]') ||\n relatedTarget.closest('[data-test=\"flyout-pane\"]') ||\n relatedTarget.closest('[data-test=\"collapsible-panel\"]') ||\n relatedTarget.closest('[data-test=\"viz-config-panel\"]')\n ) {\n return;\n }\n // Don't deselect if focus moved to a resize handle or block outline\n if (relatedTarget.closest('[data-test=\"handle\"]')) return;\n // Focus left the viz -- deselect\n if (dashboardCoreApi) {\n dashboardCoreApi.updateSelectedItems([]);\n }\n // Re-hide config link for next interaction\n const configLink = vizItem.querySelector<HTMLElement>('[data-test=\"skip-link-config\"]');\n if (configLink) configLink.setAttribute('tabindex', '-1');\n };\n\n document.addEventListener('keydown', handleKeyDown, true);\n vizItem.addEventListener('focusout', handleFocusOut);\n return () => {\n document.removeEventListener('keydown', handleKeyDown, true);\n vizItem.removeEventListener('focusout', handleFocusOut);\n };\n }, [isEditMode, dashboardCoreApi]); // eslint-disable-line react-hooks/exhaustive-deps\n}\n\n/**\n * Listener 2: Sidebar Escape, skip-link activation, Enter-to-edit.\n *\n * - Escape in sidebar: restore selection, return to editor\n * - Enter/Space on skip-link: select-all (if not was-editing), focus config\n * - Enter on viz-item (not editing): activate text editing\n * - Click on skip-link: prevent <a> navigation\n */\nfunction useSidebarAndEditActivation({\n isEditMode,\n containerRef,\n instanceId,\n slateEditorRef,\n isTextEditingRef,\n wasTextEditingRef,\n clearFakeHighlightRef,\n updateActiveStylesFnRef,\n activateTextEditing,\n richTextState,\n}: Omit<DashboardKeyboardNavArgs, 'dashboardCoreApi'>): void {\n const activateTextEditingRef = useRef(activateTextEditing);\n activateTextEditingRef.current = activateTextEditing;\n\n useEffect(() => {\n if (!isEditMode) return undefined;\n\n const getOurVizItem = (): HTMLElement | null =>\n containerRef.current?.closest<HTMLElement>('[data-test=\"viz-item\"]') ?? null;\n\n const isTargetInSidebar = (target: HTMLElement, vizItem: HTMLElement | null): boolean =>\n !vizItem?.contains(target) &&\n Boolean(\n target.closest('[data-test=\"sidebar-content\"]') ||\n target.closest('[data-test=\"header\"]') ||\n target.id === 'configuration-back-button' ||\n target.closest('#configuration-back-button') ||\n target.closest('[data-test=\"popover\"]') ||\n target.closest('[data-test-popover-id]')\n );\n\n const handleEscapeFromSidebar = (e: KeyboardEvent): void => {\n const isSelected = containerRef.current?.closest('[data-selected=\"true\"]') != null;\n if (!isSelected) return;\n e.preventDefault();\n e.stopImmediatePropagation();\n registerActiveRichText(instanceId, null, slateEditorRef.current);\n // Prefer the editor's current selection (updated by applyFormat after\n // each format change) over preEditSelection which may be stale if\n // format ops restructured the tree (e.g. addMark splits text nodes).\n const selToRestore = slateEditorRef.current?.selection || richTextState.getPreEditSelection();\n // returnFromConfigPanel uses flushSync to commit isTextEditing=true\n // synchronously, ensuring <Editable readOnly={false}> is in the DOM\n // before we focus and restore the selection.\n richTextState.returnFromConfigPanel();\n requestAnimationFrame(() => {\n const editable = containerRef.current?.querySelector<HTMLElement>('[data-slate-editor]');\n editable?.focus();\n const ed = slateEditorRef.current;\n if (ed && selToRestore) {\n try {\n Transforms.select(ed, selToRestore);\n // Sync the DOM selection immediately so Slate-React's\n // throttled onDOMSelectionChange reads the correct\n // position instead of the stale browser-default (start\n // of contenteditable) from the focus() call above.\n const domRange = ReactEditor.toDOMRange(ed, selToRestore);\n const domSel = window.getSelection();\n domSel?.removeAllRanges();\n domSel?.addRange(domRange);\n } catch {\n safeSelectEnd(ed);\n }\n } else if (ed) {\n safeSelectEnd(ed);\n }\n clearFakeHighlightRef.current?.();\n richTextState.clearWasTextEditing();\n });\n };\n\n const handleSkipLinkActivate = (e: KeyboardEvent): void => {\n e.preventDefault();\n e.stopImmediatePropagation();\n registerActiveRichText(instanceId, null, slateEditorRef.current);\n if (!wasTextEditingRef.current) {\n const slateEditor = slateEditorRef.current;\n if (slateEditor) {\n try {\n Transforms.select(slateEditor, {\n anchor: Editor.start(slateEditor, []),\n focus: Editor.end(slateEditor, []),\n });\n } catch {\n // Ignore if editor is empty\n }\n }\n updateActiveStylesFnRef.current?.();\n }\n richTextState.clearWasTextEditing();\n const configBtn = document.getElementById('configuration-back-button');\n if (configBtn) {\n configBtn.focus();\n }\n };\n\n const handleKeyDown = (e: KeyboardEvent): void => {\n const target = e.target as HTMLElement;\n const ourVizItem = getOurVizItem();\n\n if (e.key === 'Escape' && isTargetInSidebar(target, ourVizItem)) {\n handleEscapeFromSidebar(e);\n return;\n }\n\n if (!ourVizItem?.contains(target)) return;\n\n if ((e.key === 'Enter' || e.key === ' ') && target.closest('[data-test=\"skip-link-config\"]')) {\n handleSkipLinkActivate(e);\n return;\n }\n\n if (e.key === 'Enter' && !isTextEditingRef.current) {\n const isVizSelected = containerRef.current?.closest('[data-selected=\"true\"]') != null;\n if (!isVizSelected) return;\n e.preventDefault();\n e.stopImmediatePropagation();\n activateTextEditingRef.current();\n }\n };\n\n // Also intercept click on skip link to prevent <a> navigation\n const handleClick = (e: Event): void => {\n const link = (e.target as HTMLElement)?.closest('[data-test=\"skip-link-config\"]');\n if (!link) return;\n const ourVizItem = getOurVizItem();\n if (!ourVizItem?.contains(link)) return;\n e.preventDefault();\n e.stopImmediatePropagation();\n const configBtn = document.getElementById('configuration-back-button');\n if (configBtn) {\n configBtn.focus();\n }\n };\n\n document.addEventListener('keydown', handleKeyDown, true);\n document.addEventListener('click', handleClick, true);\n return () => {\n document.removeEventListener('keydown', handleKeyDown, true);\n document.removeEventListener('click', handleClick, true);\n };\n }, [isEditMode]); // eslint-disable-line react-hooks/exhaustive-deps\n}\n\nexport function useDashboardKeyboardNav(args: DashboardKeyboardNavArgs): void {\n useSkipLinkAndFocusOut({\n isEditMode: args.isEditMode,\n containerRef: args.containerRef,\n slateEditorRef: args.slateEditorRef,\n wasTextEditingRef: args.wasTextEditingRef,\n clearFakeHighlightRef: args.clearFakeHighlightRef,\n deactivateTextEditing: args.richTextState.deactivateTextEditing,\n dashboardCoreApi: args.dashboardCoreApi,\n });\n\n useSidebarAndEditActivation(args);\n}\n", "/**\n * PureRichText - Slate.js based rich text visualization\n *\n * A production-ready rich text editor component with full formatting support.\n * Uses Slate.js for robust text editing capabilities.\n */\n\nimport * as React from 'react';\nimport { useCallback, useMemo, useState, useRef, useEffect, useId, useSyncExternalStore } from 'react';\n\nimport { useSplunkTheme } from '@splunk/themes';\n// eslint-disable-next-line import/no-extraneous-dependencies\nimport { DashboardCoreApiContext } from '@splunk/dashboard-context';\nimport { Descendant, Editor } from 'slate';\nimport { noop } from 'lodash';\nimport {\n registerActiveRichText,\n clearActiveRichText,\n getActiveRichTextId,\n getActiveSlateEditor,\n subscribeActiveRichText,\n isMouseSelecting,\n} from './activeInstance';\nimport { PureRichTextProvider } from './PureRichTextContext';\nimport { EditorPanel } from './Editor';\nimport { EMPTY_SLATE_VALUE, VerticalAlign, PureRichTextProps } from './types';\nimport { htmlToSlate, parsePadding, safeSelectEnd, slateToPlainText } from './utils/slateUtils';\nimport { PureRichTextContainer, DrilldownButton, EditorWrapper, LiveRegion } from './RichTextStyles';\nimport { createElementRenderer } from './renderers/ElementRenderer';\nimport { Leaf } from './renderers/LeafRenderer';\nimport { getFontSizeInPx } from './utils/fontSize';\nimport { InnerEditor } from './InnerEditor';\nimport { useRichTextState } from './hooks/useRichTextState';\nimport { useTokenMap, wrapTokensInTree } from './hooks/useTokenMap';\nimport { useContentSave } from './hooks/useContentSave';\nimport { useDashboardKeyboardNav } from './hooks/useDashboardKeyboardNav';\n\nfunction useIsActiveRichText(id: string): boolean {\n return useSyncExternalStore(\n callback => subscribeActiveRichText(callback),\n () => getActiveRichTextId() === id\n );\n}\n\nconst PureRichText = React.forwardRef<HTMLDivElement, PureRichTextProps>((props, ref) => {\n // Get theme for default colors\n const theme = useSplunkTheme();\n const themeTextColor = theme.contentColorDefault;\n\n const {\n richTextContent = '',\n fontColor,\n highlightColor,\n fontFamily = 'Splunk Data Sans',\n fontSize = 'default',\n customFontSize = 14,\n backgroundColor = 'transparent',\n verticalAlign = 'top',\n lineHeight = '1.5',\n border,\n padding,\n mode = 'view',\n onOptionsChange,\n onRichtextClick = noop,\n hasEventHandlers = false,\n bold = false,\n italic = false,\n underline = false,\n strikethrough = false,\n defaultTextStyles,\n } = props;\n\n // Apply defaultTextStyles overrides on top of individual props\n const effectiveFontColorFromStyles = defaultTextStyles?.color || fontColor;\n const effectiveHighlightColor = defaultTextStyles?.backgroundColor || highlightColor;\n const effectiveFontFamily = defaultTextStyles?.fontFamily || fontFamily;\n const effectiveBold = defaultTextStyles?.bold ?? bold;\n const effectiveItalic = defaultTextStyles?.italic ?? italic;\n const effectiveUnderline = defaultTextStyles?.underline ?? underline;\n const effectiveStrikethrough = defaultTextStyles?.strikethrough ?? strikethrough;\n\n // Handle defaultTextStyles.fontSize which may be a px string\n let effectiveFontSize = fontSize;\n let effectiveCustomFontSize = customFontSize;\n if (defaultTextStyles?.fontSize) {\n const dtsFs = defaultTextStyles.fontSize;\n if (typeof dtsFs === 'string' && dtsFs.endsWith('px')) {\n effectiveCustomFontSize = parseInt(dtsFs, 10);\n effectiveFontSize = 'custom';\n }\n }\n\n // Use theme color as default if fontColor not provided\n const effectiveFontColor = effectiveFontColorFromStyles || themeTextColor;\n\n const isEditMode = mode === 'edit';\n const containerRef = useRef<HTMLDivElement>(null);\n const slateEditorRef = useRef<Editor | null>(null);\n const updateActiveStylesFnRef = useRef<(() => void) | null>(null);\n const clearFakeHighlightRef = useRef<(() => void) | null>(null);\n // Callback ref that sets both the forwarded ref and our internal containerRef\n const setContainerRef = useCallback(\n (node: HTMLDivElement | null) => {\n containerRef.current = node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n // eslint-disable-next-line no-param-reassign\n ref.current = node;\n }\n },\n [ref]\n );\n const [currentVerticalAlign, setCurrentVerticalAlign] = useState<VerticalAlign>(verticalAlign);\n // Centralized text-editing lifecycle state.\n const richTextState = useRichTextState();\n const { isTextEditing, isTextEditingRef, wasTextEditingRef } = richTextState;\n const [currentLineHeight, setCurrentLineHeight] = useState<string>(String(lineHeight));\n const [announcement, setAnnouncement] = useState('');\n // Clear-then-set so repeated identical announcements still trigger the live region.\n const handleAnnouncement = useCallback((msg: string) => {\n setAnnouncement('');\n requestAnimationFrame(() => setAnnouncement(msg));\n }, []);\n\n // Stable ID for this instance \u2014 used to track which richtext owns the editor panel\n const instanceId = useId();\n const isActive = useIsActiveRichText(instanceId);\n\n // When entering edit mode, register as active so the panel shows immediately.\n // If the viz is already selected, focus the viz-item so Enter-to-edit works.\n // When leaving edit mode, deactivate so panel is hidden and reset text editing state.\n useEffect(() => {\n if (isEditMode) {\n registerActiveRichText(instanceId, null, slateEditorRef.current);\n } else {\n clearActiveRichText(instanceId);\n richTextState.deactivateTextEditing();\n }\n }, [isEditMode, instanceId]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Register as active RichText when selected so the editor panel shows.\n // Do NOT steal focus -- the dashboard framework manages focus on\n // select-outline so that Cmd+A (select all vizs) works.\n useEffect(() => {\n if (!isEditMode || isTextEditing) return undefined;\n\n const checkAndRegister = (): void => {\n const isSelected = containerRef.current?.closest('[data-selected=\"true\"]') != null;\n if (isSelected) {\n registerActiveRichText(instanceId, null, slateEditorRef.current);\n }\n };\n\n const selectedAncestor = containerRef.current?.closest('[data-selected]');\n let observer: MutationObserver | null = null;\n if (selectedAncestor) {\n observer = new MutationObserver(checkAndRegister);\n observer.observe(selectedAncestor, {\n attributes: true,\n attributeFilter: ['data-selected'],\n });\n }\n\n checkAndRegister();\n\n return () => {\n observer?.disconnect();\n };\n }, [instanceId, isEditMode, isTextEditing]);\n\n // Deactivate text editing when the viz is deselected externally (e.g.\n // closing the config panel calls updateSelectedItems([])). Without this,\n // isTextEditing stays true and data-no-drag persists, causing the next\n // click to drag instead of select.\n useEffect(() => {\n if (!isEditMode || !isTextEditing) return undefined;\n\n const selectedAncestor = containerRef.current?.closest('[data-selected]');\n if (!selectedAncestor) return undefined;\n\n const observer = new MutationObserver(() => {\n const isSelected = selectedAncestor.getAttribute('data-selected') === 'true';\n if (!isSelected) {\n richTextState.deactivateTextEditing();\n }\n });\n observer.observe(selectedAncestor, {\n attributes: true,\n attributeFilter: ['data-selected'],\n });\n\n return () => {\n observer.disconnect();\n };\n }, [isEditMode, isTextEditing, richTextState]);\n\n // Dashboard API for programmatic deselection and raw definition access.\n const dashboardCoreApi = React.useContext(DashboardCoreApiContext) as {\n updateSelectedItems: (items?: unknown[]) => void;\n getDefinition?: () => {\n visualizations?: Record<string, { options?: Record<string, unknown> }>;\n };\n } | null;\n\n // Sync verticalAlign and lineHeight props to local state\n useEffect(() => {\n setCurrentVerticalAlign(verticalAlign);\n setCurrentLineHeight(String(lineHeight));\n }, [verticalAlign, lineHeight]);\n\n // Compute font size\n const fontSizeInPx = getFontSizeInPx(effectiveFontSize, effectiveCustomFontSize);\n\n // Parse border config\n const borderConfig = border || {};\n const borderColor = borderConfig.color;\n const borderWidth = borderConfig.width;\n const borderStyle = borderConfig.style || 'solid';\n const borderRadius = borderConfig.radius || 0;\n\n // Parse padding\n const paddingValues = parsePadding(padding);\n\n // Token preservation: build a map of resolved values -> $token$ patterns from\n // the raw dashboard definition. Used at save time to restore token patterns.\n const { restoreTokensInHtml, tokenMap } = useTokenMap(dashboardCoreApi, containerRef, richTextContent);\n\n // Content save: immediate for structural/format ops, batched for typing\n const { handleContentChange, flushPendingChanges, recentSavesRef } = useContentSave({\n richTextContent,\n onOptionsChange,\n restoreTokensInHtml,\n });\n\n // Parse HTML to Slate value, then wrap resolved token values in inline\n // void elements so they behave as atomic units in the editor.\n // Skip recomputation for our own save round-trips: the editor already has\n // the correct tree and recomputing would cause an unnecessary re-render of\n // InnerEditor + Slate, which drops keystrokes during fast typing.\n const initialValueRef = useRef<Descendant[]>(EMPTY_SLATE_VALUE);\n const initialValue = useMemo(() => {\n // While the user is actively editing, the editor's tree is authoritative.\n // Skip recomputation for save round-trips (detected via recentSavesRef)\n // and also for any prop change while editing (the dashboard may normalize\n // HTML slightly differently, causing exact-match detection to miss).\n if (recentSavesRef.current.has(richTextContent) || isTextEditingRef.current) {\n return initialValueRef.current;\n }\n if (!richTextContent) {\n initialValueRef.current = EMPTY_SLATE_VALUE;\n return EMPTY_SLATE_VALUE;\n }\n const tree = htmlToSlate(richTextContent);\n const result = wrapTokensInTree(tree, tokenMap);\n initialValueRef.current = result;\n return result;\n }, [richTextContent, tokenMap]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Handle focus gained: register this instance as active (displacing any other).\n const handleFocusGained = useCallback(\n (editable: HTMLDivElement | null, slateEditor: Editor | null) => {\n registerActiveRichText(instanceId, editable, slateEditor);\n },\n [instanceId]\n );\n\n // Handle focus lost: do NOT clear active \u2014 the active instance only changes when\n // another instance gains focus. This prevents panel inputs (color pickers, number\n // fields) from disrupting the active state when they temporarily steal DOM focus.\n const handleFocusLost = useCallback(() => {\n flushPendingChanges();\n }, [flushPendingChanges]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n flushPendingChanges();\n clearActiveRichText(instanceId);\n };\n }, [flushPendingChanges, instanceId]);\n\n // Handle vertical alignment change\n const handleVerticalAlignChange = useCallback(\n (align: VerticalAlign) => {\n setCurrentVerticalAlign(align);\n onOptionsChange?.({ verticalAlign: align });\n },\n [onOptionsChange]\n );\n\n // Default text style object\n const defaultTextStyle = useMemo(\n () => ({\n color: effectiveFontColor,\n backgroundColor: effectiveHighlightColor,\n fontSize: `${fontSizeInPx}px`,\n fontFamily: effectiveFontFamily,\n lineHeight: currentLineHeight,\n bold: effectiveBold,\n italic: effectiveItalic,\n underline: effectiveUnderline,\n strikethrough: effectiveStrikethrough,\n }),\n [\n effectiveFontColor,\n effectiveHighlightColor,\n fontSizeInPx,\n effectiveFontFamily,\n currentLineHeight,\n effectiveBold,\n effectiveItalic,\n effectiveUnderline,\n effectiveStrikethrough,\n ]\n );\n\n const activateTextEditing = useCallback(() => {\n richTextState.activateTextEditing();\n requestAnimationFrame(() => {\n const editable = containerRef.current?.querySelector<HTMLElement>('[data-slate-editor]');\n editable?.focus({ preventScroll: true });\n if (slateEditorRef.current && !slateEditorRef.current.selection) {\n safeSelectEnd(slateEditorRef.current);\n }\n });\n }, [richTextState]);\n\n // Dashboard keyboard navigation: skip-links, Escape-from-sidebar, Enter-to-edit, focusout\n useDashboardKeyboardNav({\n isEditMode,\n containerRef,\n instanceId,\n slateEditorRef,\n isTextEditingRef,\n wasTextEditingRef,\n clearFakeHighlightRef,\n updateActiveStylesFnRef,\n activateTextEditing,\n richTextState,\n dashboardCoreApi,\n });\n\n // Grid layout fix: the grid canvas registers a capture-phase mousedown\n // handler (captureSelectionState) that calls event.preventDefault() when\n // the target is not \"interactive\" (contentEditable/input/button). Slate's\n // Editable is NOT contentEditable when readOnly, so the preventDefault\n // fires and blocks focus, text selection, and click-to-place-caret.\n //\n // Check the live DOM (data-selected, isTextEditingRef) rather than React\n // state to avoid stale closures after external deselection (e.g. closing\n // the config panel calls updateSelectedItems([]) without a blur cycle).\n useEffect(() => {\n if (!isEditMode) return undefined;\n\n const guard = (e: MouseEvent): void => {\n const target = e.target as HTMLElement;\n if (!containerRef.current?.contains(target)) return;\n const isVizSelected = containerRef.current.closest('[data-selected=\"true\"]') != null;\n if (!isVizSelected) return;\n if (!isTextEditingRef.current) {\n e.preventDefault = () => {};\n return;\n }\n const isOnSlateContent = target.closest('[data-slate-node]') != null;\n if (isOnSlateContent) {\n e.preventDefault = () => {};\n }\n };\n document.addEventListener('mousedown', guard, true);\n return () => document.removeEventListener('mousedown', guard, true);\n }, [isEditMode]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const handleContainerClick = useCallback(\n (e: React.MouseEvent) => {\n if (hasEventHandlers && !isEditMode) {\n onRichtextClick(e);\n }\n\n if (isEditMode && !isTextEditing && containerRef.current) {\n const isVizSelected = containerRef.current.closest('[data-selected=\"true\"]') != null;\n if (!isVizSelected) return;\n registerActiveRichText(instanceId, null, slateEditorRef.current);\n activateTextEditing();\n return;\n }\n\n if (!isTextEditing || !containerRef.current || isMouseSelecting()) return;\n const editable = containerRef.current.querySelector<HTMLElement>('[data-slate-editor]');\n if (!editable || editable.contains(e.target as Node)) return;\n editable.focus({ preventScroll: true });\n const slateEditor = getActiveSlateEditor();\n if (slateEditor) {\n safeSelectEnd(slateEditor);\n }\n },\n [hasEventHandlers, isEditMode, isTextEditing, onRichtextClick]\n );\n\n return (\n <PureRichTextProvider\n defaultColor={effectiveFontColor}\n defaultBackgroundColor={effectiveHighlightColor || 'transparent'}\n defaultFontFamily={effectiveFontFamily}\n defaultFontSize={`${fontSizeInPx}px`}\n defaultBold={effectiveBold}\n defaultItalic={effectiveItalic}\n defaultUnderline={effectiveUnderline}\n defaultStrikethrough={effectiveStrikethrough}\n >\n <PureRichTextContainer\n ref={setContainerRef}\n $backgroundColor={backgroundColor}\n $verticalAlign={currentVerticalAlign}\n $borderColor={borderColor}\n $borderWidth={borderWidth}\n $borderStyle={borderStyle}\n $borderRadius={borderRadius}\n $padding={paddingValues}\n $isTextEditing={isTextEditing}\n $hasEventHandlers={hasEventHandlers && !isEditMode}\n data-no-drag={isTextEditing ? 'true' : undefined}\n data-text-editor={isTextEditing ? 'true' : undefined}\n data-test=\"purerichtext-container\"\n role={!isEditMode ? 'region' : undefined}\n aria-label={!isEditMode ? slateToPlainText(initialValue) || 'Empty rich text' : undefined}\n onClick={handleContainerClick}\n >\n {hasEventHandlers && !isEditMode && (\n <DrilldownButton\n onClick={(e: React.MouseEvent) => {\n e.stopPropagation();\n onRichtextClick(e);\n }}\n appearance=\"secondary\"\n data-test=\"richtext-drilldown\"\n >\n Drilldown\n </DrilldownButton>\n )}\n <EditorWrapper\n $isEditMode={isEditMode}\n $isTextEditing={isTextEditing}\n $lineHeight={currentLineHeight}\n data-richtext-editor-wrapper\n onMouseDown={\n isTextEditing\n ? (e: React.MouseEvent) => {\n // Stop propagation when the user clicks the scrollbar (target is\n // the wrapper itself, not a child). This prevents dnd-kit from\n // interpreting the scrollbar drag as a viz drag.\n if (e.target === e.currentTarget) {\n e.stopPropagation();\n }\n }\n : undefined\n }\n >\n <InnerEditor\n initialValue={initialValue}\n richTextContent={richTextContent}\n isEditMode={isEditMode}\n isTextEditing={isTextEditing}\n containerRef={containerRef}\n defaultTextStyle={defaultTextStyle}\n onContentChange={handleContentChange}\n onFocusGained={handleFocusGained}\n onFocusLost={handleFocusLost}\n richTextState={richTextState}\n onEditorReady={ed => {\n slateEditorRef.current = ed;\n }}\n updateActiveStylesRef={updateActiveStylesFnRef}\n clearFakeHighlightRef={clearFakeHighlightRef}\n recentSavesRef={recentSavesRef}\n onAnnouncement={handleAnnouncement}\n />\n </EditorWrapper>\n <LiveRegion aria-live=\"polite\" aria-atomic=\"true\">\n {announcement}\n </LiveRegion>\n </PureRichTextContainer>\n\n {/* Editor Panel - portals into editor sidebar only when this instance is focused */}\n <EditorPanel\n isEditMode={isEditMode}\n isActive={isActive}\n fontColor={effectiveFontColor}\n fontSize={fontSizeInPx}\n lineHeight={currentLineHeight}\n verticalAlign={currentVerticalAlign}\n onVerticalAlignChange={handleVerticalAlignChange}\n />\n </PureRichTextProvider>\n );\n});\n\nPureRichText.displayName = 'PureRichText';\n\n// Export the pure component and utility functions\nexport { Leaf, createElementRenderer, getFontSizeInPx };\nexport { InnerEditor } from './InnerEditor';\nexport type { InnerEditorProps } from './InnerEditor';\nexport type { PureRichTextProps };\n// Export as both PureRichText and PureRichTextPure for compatibility with stories\nexport { PureRichText as PureRichTextPure };\nexport default PureRichText;\n", "import { richTextOptionsSchema as optionsSchema } from '@splunk/visualization-schemas';\nimport vizConfig from './config';\nimport withDashboardViz from '../common/withDashboardViz';\nimport PureRichText, { PureRichTextProps } from './PureRichText/PureRichText';\nimport { FontSizePreset } from './PureRichText/types';\n\nconst validOptions = Object.keys(optionsSchema);\n\ntype ComputeVizPropsFn = (props: {\n options: Record<string, any>;\n dataSources: any;\n mode?: 'view' | 'edit';\n onRichtextClick?: (...args: any) => void;\n onOptionsChange?: (options: Record<string, unknown>) => void;\n richTextContent?: string;\n hasEventHandlers?: boolean;\n [key: string]: any;\n}) => Partial<PureRichTextProps>;\n\n// Pick valid options from the raw options map.\nfunction pickValidOptions(options: Record<string, any>): Record<string, any> {\n const picked: Record<string, any> = {};\n validOptions.forEach(key => {\n if (options[key] !== undefined) {\n picked[key] = options[key];\n }\n });\n return picked;\n}\n\n// Build the border config from options, supporting both nested and flat shapes.\nfunction buildBorderConfig(\n pickedOptions: Record<string, any>,\n options: Record<string, any>\n): Record<string, any> | undefined {\n if (pickedOptions.border) return pickedOptions.border;\n if (options.borderColor || options.borderWidth) {\n return {\n color: options.borderColor,\n width: options.borderWidth,\n style: options.borderStyle || 'solid',\n radius: options.borderRadius || 0,\n };\n }\n return undefined;\n}\n\n// Build defaultTextStyles from options, supporting both nested object and individual props.\nfunction buildDefaultTextStyles(\n pickedOptions: Record<string, any>,\n options: Record<string, any>\n): Record<string, any> {\n if (options.defaultTextStyles && typeof options.defaultTextStyles === 'object') {\n return { ...options.defaultTextStyles };\n }\n const styles: Record<string, any> = {};\n if (pickedOptions.fontColor) styles.color = pickedOptions.fontColor;\n if (pickedOptions.highlightColor) styles.backgroundColor = pickedOptions.highlightColor;\n if (pickedOptions.fontFamily) styles.fontFamily = pickedOptions.fontFamily;\n if (pickedOptions.fontSize || pickedOptions.customFontSize) {\n const fontSize = pickedOptions.fontSize || 'default';\n const customFontSize = pickedOptions.customFontSize || 14;\n styles.fontSize = fontSize === 'custom' ? `${customFontSize}px` : undefined;\n }\n if (pickedOptions.bold) styles.bold = true;\n if (pickedOptions.italic) styles.italic = true;\n if (pickedOptions.underline) styles.underline = true;\n if (pickedOptions.strikethrough) styles.strikethrough = true;\n return styles;\n}\n\n// Resolve fontSize and customFontSize \u2014 handles the case where fontSize is a px string.\nfunction resolveFontSize(\n defaultTextStyles: Record<string, any>,\n pickedOptions: Record<string, any>\n): { fontSize: FontSizePreset | undefined; customFontSize: number | undefined } {\n let fontSize: FontSizePreset | undefined = defaultTextStyles.fontSize || pickedOptions.fontSize;\n let customFontSize: number | undefined = defaultTextStyles.customFontSize || pickedOptions.customFontSize;\n if (typeof fontSize === 'string' && fontSize.endsWith('px')) {\n customFontSize = parseInt(fontSize, 10);\n fontSize = 'custom';\n }\n return { fontSize, customFontSize };\n}\n\nexport const computeVizProps: ComputeVizPropsFn = ({\n options,\n mode,\n onRichtextClick,\n onOptionsChange,\n richTextContent: richTextContentProp,\n hasEventHandlers = false,\n}) => {\n const pickedOptions = pickValidOptions(options);\n const border = buildBorderConfig(pickedOptions, options);\n const defaultTextStyles = buildDefaultTextStyles(pickedOptions, options);\n\n const fontColor = defaultTextStyles.color || pickedOptions.fontColor;\n const highlightColor =\n defaultTextStyles.highlightColor || defaultTextStyles.backgroundColor || pickedOptions.highlightColor;\n const fontFamily = defaultTextStyles.fontFamily || pickedOptions.fontFamily;\n const { fontSize, customFontSize } = resolveFontSize(defaultTextStyles, pickedOptions);\n\n const bold = defaultTextStyles.bold ?? pickedOptions.bold ?? false;\n const italic = defaultTextStyles.italic ?? pickedOptions.italic ?? false;\n const underline = defaultTextStyles.underline ?? pickedOptions.underline ?? false;\n const strikethrough = defaultTextStyles.strikethrough ?? pickedOptions.strikethrough ?? false;\n\n return {\n richTextContent: richTextContentProp || '',\n fontColor,\n highlightColor,\n fontFamily,\n fontSize,\n customFontSize,\n backgroundColor: pickedOptions.backgroundColor || 'transparent',\n verticalAlign: pickedOptions.verticalAlign,\n lineHeight: pickedOptions.lineHeight,\n border,\n padding: pickedOptions.padding,\n mode,\n onRichtextClick,\n onOptionsChange,\n defaultTextStyles,\n bold,\n italic,\n underline,\n strikethrough,\n hasEventHandlers,\n };\n};\n\nconst RichText = withDashboardViz({\n ReactViz: PureRichText as any,\n computeVizProps,\n vizConfig,\n disableEditModeCover: true,\n});\n\nexport const { themes } = vizConfig;\nexport const config = vizConfig;\nexport default RichText;\n"],
5
- "mappings": "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",
6
- "names": ["RichText_exports", "config", "RichText_default", "themes", "defaultImport", "defaultImport", "defaultImport", "RichText_exports", "RichText_default", "defaultImport", "RichText_exports", "RichText_default", "defaultImport", "defaultImport", "config", "themes", "optionsSchema", "RichText_default", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "config", "themes", "defaultImport", "Opts", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "getFieldName", "_a", "getFieldName", "config", "range", "computeVizProps", "_a", "Opts", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "SlateElement", "SlateNode", "result", "SlateElement", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "size", "_a", "_b", "range", "SlateNode", "e", "range", "SlateNode", "e", "size", "isLeafBlock", "SlateElement", "_a", "_a", "_b", "e", "handleClick", "_a", "optionsSchema", "themes", "config", "RichText_default"]
3
+ "sources": ["src/RichText/index.ts", "esm-externals:@splunk/visualization-schemas", "esm-externals:@splunk/ui-utils/i18n", "esm-externals:@splunk/themes", "esm-externals:@splunk/visualization-icons/RichText", "esm-externals:@splunk/visualization-icons/placeholders/RichText", "esm-externals:lodash", "esm-externals:@splunk/visualizations-shared/configUtils", "src/common/utils/configUtils.ts", "src/common/editorConfig/BackgroundColor.ts", "src/RichText/config.ts", "esm-externals:react", "esm-externals:@splunk/themes/getSettingsFromThemedProps", "esm-externals:@splunk/visualization-encoding/Options", "esm-externals:@splunk/visualizations-shared/SanitizeProps", "esm-externals:@splunk/visualization-context/TimezoneContext", "esm-externals:@splunk/moment", "esm-externals:@splunk/visualization-context/FeatureFlagContext", "esm-externals:styled-components", "esm-externals:@splunk/visualizations-shared/hocUtils", "esm-externals:@splunk/visualizations-shared/JSONSchemaUtils", "esm-externals:@splunk/async-dynamic-options-evaluator", "esm-externals:@splunk/ui-utils/id", "esm-externals:prop-types", "src/common/interfaces/VizActionHandler.ts", "src/common/SplunkVisualization.tsx", "src/common/interfaces/DataSource.ts", "src/common/hooks/useSorting.ts", "src/common/hooks/usePagination.ts", "src/common/hooks/useDeepMemo.ts", "esm-externals:@splunk/visualizations-shared/Message", "esm-externals:@splunk/visualizations-shared/SizeAwareWrapper", "src/common/components/MissingPropsMessage.tsx", "src/common/utils/hocUtils.ts", "src/common/hocs/withEditModeCover.tsx", "esm-externals:@splunk/visualizations-shared/colorUtils", "esm-externals:@splunk/themes/variables", "esm-externals:@splunk/visualizations-shared/style", "src/common/hocs/FixedSizeContainer.tsx", "src/common/components/IconPlaceholder.tsx", "src/common/hocs/withPlaceholder.tsx", "esm-externals:@splunk/visualizations-shared/numberUtils", "src/common/utils/dataUtils.ts", "src/common/hooks/usePrevious.ts", "src/common/hooks/useGetXAndYFields.tsx", "src/common/hooks/useDownsampleDataSources.tsx", "esm-externals:@splunk/visualization-context/FeatureFlags", "src/common/utils/featureFlagUtils.ts", "esm-externals:@splunk/visualizations-shared/trellisUtils", "src/common/utils/trellisUtils.ts", "esm-externals:@splunk/visualization-canvas", "src/common/components/VizStyleWrapper.jsx", "esm-externals:@splunk/react-icons/Triangle", "esm-externals:@splunk/visualizations-shared/propUtils", "esm-externals:@splunk/visualizations-shared/simpleXMLOptions", "src/common/chartingUtils.ts", "src/common/hooks/useTrellisEnabled.ts", "src/common/components/TrellisTitle.tsx", "src/common/TimeSeriesChartWrapper.tsx", "src/common/withDashboardViz.tsx", "esm-externals:@splunk/dashboard-context", "esm-externals:slate", "esm-externals:slate-react", "src/RichText/PureRichText/activeInstance.ts", "src/RichText/PureRichText/types.ts", "esm-externals:dompurify", "src/RichText/PureRichText/hooks/useTokenMap.ts", "src/RichText/PureRichText/utils/slateUtils.ts", "src/RichText/PureRichText/utils/a11yUtils.ts", "src/RichText/PureRichText/PureRichTextContext.tsx", "esm-externals:@splunk/react-ui/ScreenReaderContent", "src/RichText/PureRichText/Editor/FormatButton.tsx", "esm-externals:@splunk/react-ui/ControlGroup", "esm-externals:@splunk/react-ui/Select", "src/RichText/PureRichText/Editor/FontSelector.tsx", "esm-externals:react-dom", "esm-externals:@splunk/react-ui/Button", "esm-externals:@splunk/react-ui/RadioBar", "esm-externals:@splunk/react-ui/Color", "esm-externals:@splunk/react-ui/Text", "esm-externals:@splunk/react-ui/Number", "esm-externals:@splunk/react-ui/Popover", "esm-externals:@splunk/react-icons/Chain", "esm-externals:@splunk/react-icons/List", "esm-externals:@splunk/react-icons/ListNumbered", "esm-externals:@splunk/react-icons/TextBBold", "esm-externals:@splunk/react-icons/TextIItalic", "esm-externals:@splunk/react-icons/TextUUnderline", "esm-externals:@splunk/react-icons/TextSStrikethrough", "esm-externals:@splunk/react-icons/TextAlignLeft", "esm-externals:@splunk/react-icons/TextAlignCenter", "esm-externals:@splunk/react-icons/TextAlignRight", "esm-externals:@splunk/react-icons/TextAlignTop", "esm-externals:@splunk/react-icons/TextAlignVerticalCenter", "esm-externals:@splunk/react-icons/TextAlignBottom", "esm-externals:@splunk/react-icons/ArrowTurnBackLeft", "src/RichText/PureRichText/Editor/EditorPanelStyles.tsx", "src/RichText/PureRichText/Editor/editorPanelUtils.ts", "src/RichText/PureRichText/Editor/hooks/useLinkHandlers.ts", "src/RichText/PureRichText/Editor/hooks/useLineSpacing.ts", "src/RichText/PureRichText/Editor/hooks/useConfigPanelFocus.ts", "src/RichText/PureRichText/Editor/hooks/usePortalTarget.ts", "src/RichText/PureRichText/Editor/hooks/useEditorPanelSync.ts", "src/RichText/PureRichText/Editor/EditorPanel.tsx", "src/RichText/PureRichText/RichTextStyles.tsx", "src/RichText/PureRichText/utils/fontSize.ts", "src/RichText/PureRichText/renderers/ElementRenderer.tsx", "src/RichText/PureRichText/renderers/LeafRenderer.tsx", "src/RichText/PureRichText/hooks/useEditorSetup.ts", "src/RichText/PureRichText/hooks/useFakeHighlight.ts", "src/RichText/PureRichText/hooks/useContentSync.ts", "src/RichText/PureRichText/hooks/useKeyboardShortcuts.ts", "src/RichText/PureRichText/hooks/useStepFontSize.ts", "src/RichText/PureRichText/hooks/useStepLineSpacing.ts", "src/RichText/PureRichText/hooks/useFocusHandlers.ts", "src/RichText/PureRichText/hooks/useMouseHandlers.ts", "src/RichText/PureRichText/hooks/useEditModeEffect.ts", "src/RichText/PureRichText/InnerEditor.tsx", "src/RichText/PureRichText/hooks/useRichTextState.ts", "src/RichText/PureRichText/hooks/useContentSave.ts", "src/RichText/PureRichText/hooks/useDashboardKeyboardNav.ts", "src/RichText/PureRichText/PureRichText.tsx", "src/RichText/RichText.tsx"],
4
+ "sourcesContent": ["/**\n * RichText Visualization\n * Dashboard wrapper for PureRichText\n */\n\nexport * from './RichText';\nexport { default } from './RichText';\n", "\nimport * as defaultImport from \"@splunk/visualization-schemas\";\nexport * from \"@splunk/visualization-schemas\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/ui-utils/i18n\";\nexport * from \"@splunk/ui-utils/i18n\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/themes\";\nexport * from \"@splunk/themes\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-icons/RichText\";\nexport * from \"@splunk/visualization-icons/RichText\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-icons/placeholders/RichText\";\nexport * from \"@splunk/visualization-icons/placeholders/RichText\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"lodash\";\nexport * from \"lodash\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/configUtils\";\nexport * from \"@splunk/visualizations-shared/configUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import { get, range } from 'lodash';\nimport { isDynamicOption } from '@splunk/visualizations-shared/configUtils';\nimport { VizConfig } from '../interfaces/VizConfig';\nimport { EditorLayoutConfig, EditorConfig } from '../interfaces/Editor';\n\n// included for backwards compatibility\nexport { enhanceOptionsSchemaWithDynamicOptions } from '@splunk/visualization-schemas';\n\nexport interface PresetEntry {\n name: string;\n value: any;\n label: string;\n}\n\n/**\n * Helper function to enhance a Visualization Config as needed based on behaviors specified in supports block\n * this function also collapse all editor panels\n * @param vizConfig a Visualization Config\n * @returns an enhanced Visualization Config containing updated config entries based on behaviors it supports\n * and containing `open: false` for all editor panels in editorConfig\n */\nfunction enhanceConfig(vizConfig: VizConfig): VizConfig {\n const enhancedConfig: VizConfig = { ...vizConfig };\n\n enhancedConfig.editorConfig = vizConfig.editorConfig.map((config: EditorConfig): EditorConfig => {\n return { ...config, open: config.open || false };\n });\n return enhancedConfig;\n}\n\n/**\n * Helper function to uncollapse all editor panels by adding `open: true` to the editorConfig\n * Created for editor unit tests\n * @param vizConfig a Visualization Config\n * @returns a Visualization Config containing `open: true` for all editor panels in editorConfig\n */\nfunction uncollapseEditorConfig(vizConfig: VizConfig): VizConfig {\n const editorPanelUncollapsedConfig: VizConfig = { ...vizConfig };\n editorPanelUncollapsedConfig.editorConfig = vizConfig.editorConfig.map(\n (config: EditorConfig): EditorConfig => {\n return { ...config, open: true };\n }\n );\n return editorPanelUncollapsedConfig;\n}\n\n// private helpers to improve readability of getInitialPreset\n// this shouldn't be tested since this util isn't something that we expect to use outside of getInitialPreset\n\n/**\n * this checks to make sure that all values within vizContext are compatible with the given preset's context to determine the initialPreset\n * if a preset has explicitly specified a key as being undefined, the vizContext must also has that key as undefined, or else this CANNOT be the initialPreset\n * the inverse is true; if a preset has key is NOT undefined, it must also be NOT undefined in the corresponding vizContext\n * the internal config contents are irrelevant (as the user could customize them in source), just as long as the presence of `undefined`s match up\n *\n * Since the presetConfigs have explicit undefined keys to override the existing config, we need to explicitly check the undefined values\n */\nfunction hasCompatibleContexts(\n vizContext: { [configKey: string]: any },\n presetContext: { [configKey: string]: any }\n): boolean {\n const presetContextKeys = Object.keys(presetContext);\n return presetContextKeys.every(\n (contextKey): boolean =>\n (presetContext[contextKey] === undefined && vizContext[contextKey] === undefined) ||\n (presetContext[contextKey] !== undefined && vizContext[contextKey] !== undefined)\n );\n}\n\n/**\n * Checks to make sure that dynamic (non-dynamic) options in a given preset are also dynamic (non-dynamic) in the vizOptions\n */\nfunction hasCompatibleOptions(\n vizOptions: { [configKey: string]: any },\n presetOptions: { [configKey: string]: any }\n): boolean {\n const presetOptionKeys = Object.keys(presetOptions);\n return presetOptionKeys.every(\n (optionKey): boolean =>\n isDynamicOption(presetOptions[optionKey]) === isDynamicOption(vizOptions[optionKey])\n );\n}\n\n/**\n * Evaluates whether there is an initialPreset that fits the current state of vizContext + vizOptions\n * This function ignores extraneous vizOptions or vizContext keys, as they could be outside the scope of what the preset is intended to configure\n *\n * @param {Object} vizContext - the current vizContext definition\n * @param {Object} vizOptions - the current vizOptions definition\n * @param {PresetEntry[]} presets - the list of presets, one of which can be considered an initialPreset\n */\nfunction getInitialPreset(\n vizContext: { [configKey: string]: any },\n vizOptions: { [configKey: string]: any },\n presets: PresetEntry[]\n): PresetEntry | null {\n return presets.find((preset): boolean => {\n const presetContext = get(preset, ['value', 'context'], {});\n const presetOptions = get(preset, ['value', 'options'], {});\n const presetContextKeys = Object.keys(presetContext);\n const presetOptionKeys = Object.keys(presetOptions);\n\n // all presets have to explicitly specify which options to reset (i.e. need explicitly undefined keys)\n // if not, then the preset is invalid in config.ts\n if (presetContextKeys.length === 0 || presetOptionKeys.length === 0) return false;\n\n return (\n hasCompatibleContexts(vizContext, presetContext) &&\n hasCompatibleOptions(vizOptions, presetOptions)\n );\n });\n}\n\ninterface PrecisionOption {\n label: string;\n value: number;\n}\n\n/**\n * generates number precision values for a Select editor\n *\n * @param {Number} numPrecisionValues - number of integer precision values to generate\n * @returns {{ label: string; value; string }[]} array of { label, value } tuples\n */\nfunction generatePrecisionValues(numPrecisionValues: number): PrecisionOption[] {\n return range(0, numPrecisionValues + 1).map(\n (i): PrecisionOption => ({\n label: `${i} (0${i > 0 ? '.' : ''}${'0'.repeat(i)})`, // e.g. 0.000 for numPrecisionValues = 3\n value: i,\n })\n );\n}\n\nexport { enhanceConfig, getInitialPreset, generatePrecisionValues, uncollapseEditorConfig, isDynamicOption };\n\n/**\n * insert layout in layout array, return a new layout array instead of updating the original\n *\n * @param {EditorLayoutConfig[][]} layout - editor layout\n * @param {Number} index - the index to insert layout item(s)\n * @param {EditorLayoutConfig[][]} layoutItems - the item(s) to insert\n * @returns {EditorLayoutConfig[][]} new editor layout with insertion\n */\nexport const insertLayout = (\n layout: EditorLayoutConfig[][],\n index: number,\n ...layoutItems: EditorLayoutConfig[][]\n): EditorLayoutConfig[][] => [\n // copy part of the array before the specified index\n ...layout.slice(0, index),\n // inserted layout item\n ...layoutItems,\n // copy part of the array after the specified index\n ...layout.slice(index),\n];\n", "import { _ } from '@splunk/ui-utils/i18n';\nimport { EditorLayoutConfig } from '../interfaces/Editor';\nimport { ThemedDefaults } from '../interfaces/ThemedDefaults';\n\ninterface BackgroundEditorProps {\n label?: string;\n themes: ThemedDefaults;\n labelPosition?: string;\n}\n\nconst background: ({ label, themes, labelPosition }: BackgroundEditorProps) => EditorLayoutConfig[] = ({\n label,\n themes,\n labelPosition,\n}) => [\n {\n label: _(label || 'Background color'),\n option: 'backgroundColor',\n editor: 'editor.color',\n editorProps: {\n labelPosition: labelPosition || 'top',\n themes,\n },\n },\n];\n\nexport default background;\n", "import { richTextOptionsSchema as optionsSchema } from '@splunk/visualization-schemas';\nimport { _ } from '@splunk/ui-utils/i18n';\nimport { pick, variables } from '@splunk/themes';\nimport RichTextIcon from '@splunk/visualization-icons/RichText';\nimport RichTextPlaceholderIcon from '@splunk/visualization-icons/placeholders/RichText';\n\nimport { DataContract } from '../common/interfaces/DataContract';\nimport { DefaultContext } from '../common/interfaces/DefaultContext';\nimport { EditorConfig } from '../common/interfaces/Editor';\nimport { ThemedDefaults } from '../common/interfaces/ThemedDefaults';\nimport { VizBehavior } from '../common/interfaces/VizBehavior';\nimport { VizCategory } from '../common/interfaces/VizCategory';\nimport { VizConfig } from '../common/interfaces/VizConfig';\nimport { VizSize } from '../common/interfaces/VizSize';\nimport { enhanceConfig } from '../common/utils/configUtils';\nimport getBackgroundColorEditor from '../common/editorConfig/BackgroundColor';\n\nconst dataContract: DataContract = {\n requiredDataSources: [],\n optionalDataSources: [],\n initialRequestParams: {\n primary: { offset: 0, count: 10000 },\n },\n};\n\nconst size: VizSize = {\n initialWidth: 300,\n initialHeight: 200,\n};\n\nconst defaultContext: DefaultContext = {};\n\nconst themes: ThemedDefaults = {\n defaultFontColor: (props: any) =>\n pick({\n enterprise: {\n dark: variables.textColor(props),\n light: variables.textColor(props),\n },\n prisma: variables.contentColorDefault(props),\n })(props),\n defaultBackgroundColor: () => 'transparent',\n};\n\nconst editorConfig: EditorConfig[] = [\n {\n label: _('Data display'),\n open: true,\n layout: [\n [\n {\n label: _('Preview token values'),\n option: 'previewTokenValues',\n editor: 'editor.toggle',\n },\n ],\n ],\n },\n {\n label: _('Color and style'),\n open: true,\n layout: [\n [...getBackgroundColorEditor({ label: 'Background color', themes })],\n [\n {\n label: _('Border color'),\n option: 'border.color',\n editor: 'editor.color',\n editorProps: {\n labelPosition: 'top',\n },\n },\n {\n label: _('Border width (px)'),\n option: 'border.width',\n editor: 'editor.number',\n editorProps: {\n min: 0,\n max: 20,\n step: 1,\n labelPosition: 'top',\n },\n },\n ],\n [\n {\n label: '',\n option: 'richTextContent',\n editor: 'editor.text',\n editorProps: {\n multiline: false,\n style: { display: 'none' },\n },\n },\n ],\n [\n {\n label: _('Padding (px)'),\n option: 'padding',\n editor: 'editor.number',\n editorProps: {\n min: 0,\n max: 100,\n step: 1,\n labelPosition: 'top',\n },\n },\n ],\n [\n {\n label: _('Corner radius (px)'),\n option: 'border.radius',\n editor: 'editor.number',\n editorProps: {\n min: 0,\n max: 100,\n step: 1,\n labelPosition: 'top',\n },\n },\n ],\n ],\n },\n];\n\n/**\n * visualization configuration\n */\nconst config: VizConfig = {\n /**\n * unique viz key\n */\n key: 'splunk.richtext',\n /**\n * viz name\n */\n name: _('Text'),\n category: VizCategory.TEXT,\n status: 'preview',\n /**\n * viz icon\n */\n icon: RichTextIcon,\n dataContract,\n size,\n defaultContext,\n optionsSchema,\n editorConfig,\n events: {\n 'richtext.click': {\n description: 'triggered when user clicks on rich text area not formatted as a link',\n },\n 'link.open': {\n description: 'triggered when the user activates a link; payload carries the resolved url',\n // Default behavior: fires ungated by event handlers and in edit mode too.\n source: 'default',\n },\n },\n supports: [VizBehavior.DYNAMIC_OPTIONS, VizBehavior.EVENTS],\n themes,\n placeholderIcon: RichTextPlaceholderIcon,\n};\n\nexport default enhanceConfig(config);\n", "\nimport * as defaultImport from \"react\";\nexport * from \"react\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/themes/getSettingsFromThemedProps\";\nexport * from \"@splunk/themes/getSettingsFromThemedProps\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-encoding/Options\";\nexport * from \"@splunk/visualization-encoding/Options\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/SanitizeProps\";\nexport * from \"@splunk/visualizations-shared/SanitizeProps\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-context/TimezoneContext\";\nexport * from \"@splunk/visualization-context/TimezoneContext\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/moment\";\nexport * from \"@splunk/moment\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualization-context/FeatureFlagContext\";\nexport * from \"@splunk/visualization-context/FeatureFlagContext\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"styled-components\";\nexport * from \"styled-components\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/hocUtils\";\nexport * from \"@splunk/visualizations-shared/hocUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/JSONSchemaUtils\";\nexport * from \"@splunk/visualizations-shared/JSONSchemaUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/async-dynamic-options-evaluator\";\nexport * from \"@splunk/async-dynamic-options-evaluator\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/ui-utils/id\";\nexport * from \"@splunk/ui-utils/id\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"prop-types\";\nexport * from \"prop-types\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "/* eslint-disable class-methods-use-this */\nexport interface VizActionHandler {\n /**\n * put focus on the visualization\n */\n focus(): void;\n\n /**\n * compute snapshot of this visualization\n */\n snapshot(): Record<string, unknown>; // (This is for pdf export)\n}\n\nexport class DefaultVizActionHandler {\n focus(): void {\n // noop\n }\n\n snapshot(): Record<string, unknown> {\n return null; // noop\n }\n}\n", "/* eslint-disable react/no-unused-prop-types,react/prefer-stateless-function */\nimport * as T from 'prop-types';\nimport { noop } from 'lodash';\nimport { DashboardVizProps } from './interfaces/DashboardVizProps';\nimport { DefaultVizActionHandler } from './interfaces/VizActionHandler';\n\n// this is identical to the initial height and width we use in BaseVisualization in dashboard-visualizations\nexport const INITIAL_WIDTH = 250;\nexport const INITIAL_HEIGHT = 250;\n\n/**\n * A Splunk visualization\n */\nclass SplunkVisualization {\n static readonly propTypes: Record<keyof DashboardVizProps, T.Validator<any>> = {\n /**\n * display mode\n */\n mode: T.oneOf(['view', 'edit', 'export']).isRequired,\n /**\n * width in pixel or string, defaults to 100%\n */\n width: T.oneOfType([T.string, T.number]).isRequired,\n /**\n * height in pixel or string\n */\n height: T.oneOfType([T.string, T.number]).isRequired,\n /**\n * visualization context used for dynamic option evaluation\n */\n context: T.object,\n /**\n * visualization formatting options\n */\n options: T.object,\n /**\n * A callback to update formatting options\n */\n onOptionsChange: T.func,\n /**\n * datasource state which include data and request params, object key indicate the datasource type.\n */\n dataSources: T.objectOf(\n T.shape({\n /**\n * current request params\n */\n requestParams: T.object,\n /**\n * current dataset\n */\n data: T.shape({\n fields: T.array,\n columns: T.array,\n }),\n /**\n * error\n */\n error: T.shape({\n level: T.string,\n message: T.string,\n }),\n /**\n * meta data that came with the dataset\n */\n meta: T.object,\n })\n ),\n /**\n * A callback to trigger event\n */\n onEventTrigger: T.func,\n /**\n * Inform viz if there are handlers listening to events\n */\n hasEventHandlers: T.bool,\n /**\n * A callback to communicate computed props to a consumer\n */\n onComputedProps: T.func,\n /**\n * A callback to obtain visualization api\n */\n vizActionHandlerRef: T.func,\n\n loading: T.bool,\n theme: T.object,\n /**\n * A callback to request new data with updated request params\n */\n onRequestParamsChange: T.func,\n };\n\n /**\n *\n */\n public static readonly defaults: DashboardVizProps = {\n // BaseVisualization in dashboard-visualizations uses 100% for width but 250 for height\n width: '100%',\n height: INITIAL_HEIGHT,\n dataSources: {},\n onEventTrigger: (): Record<string, unknown> => ({}),\n mode: 'view',\n hasEventHandlers: false,\n options: {},\n context: {},\n onOptionsChange: (): Record<string, unknown> => ({}),\n vizActionHandlerRef: (): DefaultVizActionHandler => new DefaultVizActionHandler(),\n onComputedProps: (): Record<string, unknown> => ({}),\n loading: false,\n onRequestParamsChange: noop,\n };\n}\n\nexport default SplunkVisualization;\n", "import { FieldEntry } from '@splunk/visualizations-shared/dataSourceUtils';\nimport { validSegmentationModes } from '@splunk/visualization-schemas';\n\nexport interface JsonColumnData {\n fields: FieldEntry[] | string[];\n columns: (string | number | null)[][];\n}\n\nexport type HighlightedSourceMap = Record<string, Record<string, boolean>>;\nexport type TagsMap = Record<string, Record<string, string[]>>;\n\nexport interface Meta {\n totalCount: number;\n sid: string;\n app: string;\n highlighted?: HighlightedSourceMap;\n tags?: TagsMap;\n}\n\nexport const validSortDirs = ['asc', 'desc', 'none'] as const;\nexport type SortDirType = (typeof validSortDirs)[number];\nexport type SegmentationType = (typeof validSegmentationModes)[number];\nexport const validOutputModes = ['json_cols', 'json'] as const;\nexport type OutputModeType = (typeof validOutputModes)[number];\n\nexport interface RequestParams {\n count?: number;\n offset?: number;\n sort?: {\n [sortKey: string]: SortDirType;\n };\n segmentation?: SegmentationType;\n // eslint-disable-next-line camelcase\n output_mode?: OutputModeType;\n}\n\nexport interface DataSource {\n requestParams: Partial<RequestParams>;\n onRequestParamsChange?: (p: Record<string, unknown>) => void;\n data: JsonColumnData;\n error?: { level: string; message: string };\n meta: Partial<Meta>;\n}\n\nexport interface DataSourceMeta {\n requestParams: Partial<RequestParams>;\n meta: Partial<Meta>;\n onRequestParamsChange: (payload: RequestParams) => void;\n}\n", "import * as T from 'prop-types';\nimport { has } from 'lodash';\nimport { DataSourceMeta, SortDirType, validSortDirs } from '../interfaces/DataSource';\n\nexport interface SortParams {\n currentSortKey?: string;\n currentSortDir?: SortDirType;\n onSort?: (e: MouseEvent, { sortKey, sortDir }: { sortKey: string; sortDir: SortDirType }) => void;\n}\n\nexport const SortParamsPropTypes = T.shape({\n currentSortKey: T.string,\n currentSortDir: T.oneOf(validSortDirs),\n onSort: T.func,\n});\n\nexport const useSortingParams = ({ requestParams, onRequestParamsChange }: DataSourceMeta): SortParams => {\n let currentSortKey: string | undefined;\n let currentSortDir: SortDirType | undefined;\n\n const nextSortDirMap: Record<SortDirType, SortDirType> = {\n asc: 'desc',\n desc: 'asc',\n none: 'asc',\n };\n\n let onSort: SortParams['onSort'];\n if (typeof onRequestParamsChange === 'function') {\n if (requestParams && has(requestParams, 'sort')) {\n currentSortKey = Object.keys(requestParams.sort).shift();\n currentSortDir = requestParams.sort[currentSortKey];\n }\n\n // undid memoization since there is a dependency on requestParams, which is a deeply nested object\n onSort = (e, { sortKey, sortDir }): void => {\n if (typeof sortKey === 'string') {\n const nextSortDir = has(nextSortDirMap, sortDir) ? nextSortDirMap[sortDir] : 'none';\n onRequestParamsChange({\n ...requestParams,\n offset: 0,\n sort: { [sortKey]: nextSortDir },\n });\n } else {\n onRequestParamsChange(requestParams);\n }\n };\n }\n\n return {\n currentSortKey,\n currentSortDir,\n onSort,\n };\n};\n", "import * as T from 'prop-types';\nimport { cloneDeep, noop } from 'lodash';\nimport * as React from 'react';\nimport { DataSourceMeta, RequestParams } from '../interfaces/DataSource';\n\nexport interface OnChangeParams {\n page?: number;\n count?: number;\n}\nexport interface PaginatorParams {\n isPaging?: boolean;\n current?: number;\n totalPages?: number;\n onChange?: (event: React.MouseEvent<HTMLButtonElement>, data: OnChangeParams) => void;\n}\n\nexport const PaginatorParamsPropTypes = T.shape({\n isPaging: T.bool,\n current: T.number,\n totalPages: T.number,\n onChange: T.func,\n});\n\nexport const usePaginationParams = ({\n requestParams,\n meta,\n onRequestParamsChange,\n}: DataSourceMeta): PaginatorParams => {\n const totalCount = meta?.totalCount || 0;\n const offset = requestParams?.offset || 0;\n const count = requestParams?.count;\n const totalPages = typeof count === 'number' && count > 0 ? Math.ceil(totalCount / count) : 0;\n const current = typeof count === 'number' && count > 0 ? Math.floor(offset / count) + 1 : 0;\n const isPaging = totalPages > 1 && typeof onRequestParamsChange === 'function';\n\n const onChangeHandler = (e, { page, count: countArg }: OnChangeParams): void => {\n const newParams: RequestParams = cloneDeep(requestParams);\n\n if (typeof countArg === 'number') {\n newParams.count = countArg;\n newParams.offset = 0;\n }\n\n const pageCount = typeof newParams.count === 'number' ? newParams.count : 10;\n if (typeof page === 'number' && page > 0) {\n newParams.count = pageCount;\n newParams.offset = (page - 1) * pageCount;\n }\n\n onRequestParamsChange(newParams);\n };\n\n return {\n isPaging,\n current,\n totalPages,\n onChange: typeof onRequestParamsChange === 'function' ? onChangeHandler : noop,\n };\n};\n", "import { useRef } from 'react';\nimport { isEqual } from 'lodash';\n\n/**\n * This hook evaluates and stores the result of a passed function and only\n * re-evaluates the function when passed dependencies change.\n *\n * It is different from the internal React useMemo in the following aspects:\n * - it only stores the last evaluated result\n * - it uses a deep equality check to determine if dependencies have changed\n *\n * Inspired by apollo-client's useDeepMemo\n *\n * @param fn the function to be executed and\n * @param dependencies an array of dependencies\n */\nexport const useDeepMemo = <FnReturnType, DepType>(\n fn: () => FnReturnType,\n dependencies: DepType\n): FnReturnType => {\n const ref = useRef<{ dependencies: DepType; value: FnReturnType }>();\n if (!ref.current || !isEqual(dependencies, ref.current.dependencies)) {\n ref.current = {\n dependencies,\n value: fn(),\n };\n }\n return ref.current.value;\n};\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/Message\";\nexport * from \"@splunk/visualizations-shared/Message\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/SizeAwareWrapper\";\nexport * from \"@splunk/visualizations-shared/SizeAwareWrapper\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import * as React from 'react';\nimport { _ } from '@splunk/ui-utils/i18n';\nimport Message from '@splunk/visualizations-shared/Message';\nimport SizeAwareWrapper from '@splunk/visualizations-shared/SizeAwareWrapper';\nimport SplunkVisualization from '../SplunkVisualization';\n\n/**\n * @method isMissing\n * @param {any} v\n * @returns {boolean} true if the input value === null or undefined\n */\nexport const isMissing = (v): boolean => {\n return v === null || v === undefined;\n};\n\n/**\n * @method misskingKeys\n * @param {string[]} keys\n * @param {object} target\n * @returns {string[]} the keys of missing required props\n */\nexport const missingKeys = (keys: string[], target: Record<string, unknown>): string[] =>\n keys.filter(k => isMissing(target[k]));\n\nexport interface MissingPropsProps {\n width?: string | number;\n height?: string | number;\n missingProps: string[];\n backgroundColor?: string;\n}\n\n/**\n * @method MissingPropsMessage\n * @param {MissingPropsProps} props\n * @returns {React.ReactElement}\n */\nexport const MissingPropsMessage = (props: MissingPropsProps): React.ReactElement => {\n const {\n width = SplunkVisualization.defaults.width,\n height = SplunkVisualization.defaults.height,\n missingProps,\n backgroundColor,\n } = props;\n const cachedHandleResize = React.useCallback((w, h) => {\n setContainerWidth(w);\n setContainerHeight(h);\n }, []);\n const [containerWidth, setContainerWidth] = React.useState<number>(Number(width));\n const [containerHeight, setContainerHeight] = React.useState<number>(Number(height));\n return (\n <div style={{ width: containerWidth, height: containerHeight, background: backgroundColor }}>\n <SizeAwareWrapper width={width} height={height} onResize={cachedHandleResize} />\n <Message\n data-test=\"message\"\n width={width}\n height={height}\n message={_(`Missing property: ${missingProps.join(', ')}`)}\n level=\"error\"\n />\n </div>\n );\n};\n\nexport default MissingPropsMessage;\n", "import { DashboardVizProps } from '../interfaces/DashboardVizProps';\n\nexport type DashboardVizType = React.ComponentType<DashboardVizProps>;\n\n/**\n * @method extendStaticWrapperProps\n * @param {Object} props\n * @param {DashboardVizType} props.Wrapper\n * @param {DashboardVizType} props.Visualization\n */\nexport const extendStaticWrapperProps = ({\n Wrapper,\n Visualization,\n}: {\n [key: string]: DashboardVizType;\n}): void => {\n const extendProperties = ['propTypes', 'config'];\n extendProperties.forEach((prop: string): void => {\n if (Visualization[prop]) {\n // eslint-disable-next-line no-param-reassign\n Wrapper[prop] = Visualization[prop];\n }\n });\n};\n", "import * as React from 'react';\nimport styled from 'styled-components';\nimport { DashboardVizProps } from '../interfaces/DashboardVizProps';\nimport { ExtendedDashViz } from '../interfaces/ExtendedDashViz';\nimport { extendStaticWrapperProps } from '../utils/hocUtils';\n\n// Global provided via webpack\n// eslint-disable-next-line no-underscore-dangle\ndeclare const __VISION_VERSION__: string;\n\nconst Cover = styled.div`\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n`;\n\nconst Blocker = styled.div.attrs({\n 'data-splunk-visualization-version': __VISION_VERSION__,\n})`\n position: relative;\n width: 100%;\n height: 100%;\n`;\n\n/**\n * HOC that renders a cover layer in edit mode\n * @method withEditModeCover\n * @param {ExtendedDashViz} Visualization\n * @returns {ExtendedDashViz} Wrapper\n */\nconst withEditModeCover = (\n Visualization: ExtendedDashViz,\n disableEditModeCover?: boolean\n): ExtendedDashViz => {\n const Wrapper = (props: DashboardVizProps): React.ReactElement<DashboardVizProps> => {\n const { mode } = props;\n const showEditCover = mode === 'edit' && !disableEditModeCover;\n\n return (\n <Blocker>\n <Visualization {...props} />\n {showEditCover && <Cover data-test=\"edit-mode-cover\" />}\n </Blocker>\n );\n };\n extendStaticWrapperProps({ Wrapper, Visualization });\n return Wrapper as ExtendedDashViz;\n};\n\nexport default withEditModeCover;\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/colorUtils\";\nexport * from \"@splunk/visualizations-shared/colorUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/themes/variables\";\nexport * from \"@splunk/themes/variables\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/style\";\nexport * from \"@splunk/visualizations-shared/style\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import * as React from 'react';\nimport styled from 'styled-components';\nimport { toPx } from '@splunk/visualizations-shared/style';\nimport { isColor } from '@splunk/visualizations-shared/colorUtils';\nimport SizeAwareWrapper from '@splunk/visualizations-shared/SizeAwareWrapper';\n\n// Global provided via webpack\n// eslint-disable-next-line no-underscore-dangle\ndeclare const __VISION_VERSION__: string;\n\ninterface ItemProps {\n backgroundColor?: string;\n width?: string | number;\n}\n\nconst Item = styled.div.attrs<ItemProps>(({ width }) => ({\n style: {\n width: toPx(width),\n },\n}))<ItemProps>`\n position: relative;\n background-color: ${(props): string =>\n (isColor(props.backgroundColor) && props.backgroundColor) || props.theme.defaultBackgroundColor}};\n`;\n\ninterface FixSizeItemProps {\n backgroundColor?: string;\n height?: string | number;\n width?: string | number;\n}\n\n// Use `.attrs()` for highly dynamic styles. Ref: https://github.com/styled-components/styled-components/issues/134#issuecomment-312415291\nconst FixSizeItem = styled.div.attrs<FixSizeItemProps>(\n ({\n width,\n height,\n }): {\n style: { width?: string; height?: string };\n } => {\n // Ensure height is never negative (browsers ignore negative height)\n const validHeight = typeof height === 'number' ? Math.max(height, 1) : height;\n return {\n style: {\n ...(width && { width: toPx(width) }),\n ...(validHeight && { height: toPx(validHeight) }),\n },\n };\n }\n)<FixSizeItemProps>`\n position: relative;\n flex-direction: column;\n flex: 1;\n display: flex;\n overflow: hidden !important;\n background-color: ${(props): string =>\n (isColor(props.backgroundColor) && props.backgroundColor) || props.theme.defaultBackgroundColor}};\n`;\n\nconst ItemContent = styled.div`\n position: relative;\n min-height: 100px;\n width: 100%;\n`;\n\nconst FixSizeItemContent = styled.div`\n min-height: 0px;\n flex: 1;\n position: relative;\n box-sizing: border-box;\n overflow: hidden !important;\n`;\n\ninterface HeightAndWidthProps {\n width?: string | number;\n height?: string | number;\n backgroundColor?: string;\n}\n\nconst withFixedSizeContainer = <P extends HeightAndWidthProps>(\n Viz: React.ComponentType<P>\n): React.ComponentType<P> => {\n const FixedSizeContainer = (props: P): React.ReactElement => {\n const { width, height, backgroundColor } = props;\n\n const cachedHandleResize = React.useCallback((w, h) => {\n setContainerWidth(w);\n setContainerHeight(h);\n }, []);\n const [containerWidth, setContainerWidth] = React.useState<number>(Number(props.width));\n const [containerHeight, setContainerHeight] = React.useState<number>(Number(props.height));\n if (!height) {\n return (\n <Item data-test=\"item\" width={width} backgroundColor={backgroundColor}>\n <ItemContent>\n <Viz {...props} />\n </ItemContent>\n </Item>\n );\n }\n return (\n <FixSizeItem\n data-test=\"fix-size-item\"\n data-splunk-visualization-version={__VISION_VERSION__}\n width={width}\n height={height}\n backgroundColor={backgroundColor}\n >\n <FixSizeItemContent>\n <SizeAwareWrapper width={width} height={height} onResize={cachedHandleResize} />\n <Viz {...props} width={containerWidth} height={containerHeight} />\n </FixSizeItemContent>\n </FixSizeItem>\n );\n };\n FixedSizeContainer.displayName = 'withFixedSizeContainer';\n return FixedSizeContainer;\n};\n\nexport default withFixedSizeContainer;\n", "import * as React from 'react';\nimport styled from 'styled-components';\nimport { get } from 'lodash';\nimport { _ } from '@splunk/ui-utils/i18n';\nimport { pick } from '@splunk/themes';\nimport Message from '@splunk/visualizations-shared/Message';\nimport { DataSource } from '../interfaces/DataSource';\nimport withFixedSizeContainer from '../hocs/FixedSizeContainer';\nimport SplunkVisualization from '../SplunkVisualization';\n\n/**\n * @method shouldShowIconPlaceholder\n * @param {object} dataSources\n * @param {boolean} loading\n * @returns {boolean}\n */\nexport const shouldShowIconPlaceholder = (\n dataSources: { [name: string]: DataSource },\n loading = false\n): boolean => {\n const data = get(dataSources, 'primary.data.columns[0]', undefined);\n const noData = data === undefined;\n const fields = get(dataSources, 'primary.data.fields[0]', undefined);\n const noFields = fields === undefined;\n return loading || noData || noFields;\n};\n\nexport interface IconPlaceholderProps {\n icon?: React.ComponentType<any>;\n width?: string | number;\n height?: string | number;\n iconColor?: string;\n backgroundColor: string;\n}\n\nconst PlaceholderContainer = styled.div`\n /* The inline token color wins when supported. Older browsers discard an\n unsupported oklch value and retain this inherited fallback instead. */\n color: ${pick({\n dark: '#fafafa',\n light: '#2c2c2c',\n })};\n`;\n\n/**\n * @method IconPlaceholder\n * @param {IconPlaceholderProps} props\n * @returns {React.ReactElement}\n */\nconst IconPlaceholder = (props: IconPlaceholderProps): React.ReactElement => {\n const {\n width = SplunkVisualization.defaults.width,\n height = SplunkVisualization.defaults.height,\n icon,\n iconColor,\n backgroundColor,\n } = props;\n\n let content = (\n <Message width={width} height={height} level=\"warning\" message={_('No DataSource Connected')} />\n );\n if (icon) {\n content = React.createElement(icon, {\n style: {\n left: '50%',\n top: '50%',\n opacity: 0.15,\n position: 'absolute',\n transform: 'translate(-50%, -50%)',\n },\n width: '50%',\n height: '50%',\n 'data-test': 'icon-placeholder',\n });\n }\n\n return (\n <PlaceholderContainer\n data-test=\"icon-placeholder-container\"\n style={{ width, height, background: backgroundColor, color: iconColor }}\n >\n {content}\n </PlaceholderContainer>\n );\n};\n\nexport default withFixedSizeContainer(IconPlaceholder);\n", "import * as React from 'react';\nimport { isColor } from '@splunk/visualizations-shared/colorUtils';\nimport variables from '@splunk/themes/variables';\nimport IconPlaceholder, { shouldShowIconPlaceholder } from '../components/IconPlaceholder';\nimport { VizBehavior } from '../interfaces/VizBehavior';\nimport { DashboardVizProps } from '../interfaces/DashboardVizProps';\nimport { DataSource } from '../interfaces/DataSource';\nimport { ExtendedDashViz } from '../interfaces/ExtendedDashViz';\nimport { extendStaticWrapperProps } from '../utils/hocUtils';\nimport SplunkVisualization from '../SplunkVisualization';\n\ntype useIconPlaceholderType = (\n dataSources: { [name: string]: DataSource },\n loading: boolean,\n options: Record<string, unknown>\n) => boolean;\n\nconst withPlaceholder = (\n Visualization: ExtendedDashViz,\n useIconPlaceholder: useIconPlaceholderType = shouldShowIconPlaceholder\n): ExtendedDashViz => {\n const { config } = Visualization;\n const { themes } = config;\n\n const Wrapper = (props: DashboardVizProps): React.ReactElement<DashboardVizProps> => {\n const {\n dataSources,\n loading,\n options,\n height = SplunkVisualization.defaults.height,\n width = SplunkVisualization.defaults.width,\n } = props;\n\n const showPlaceholder = useIconPlaceholder(dataSources, loading, options);\n const icon = config.placeholderIcon ?? config.icon;\n const iconColor = variables.contentColorActive(props);\n const bgColorFromTheme = isColor(options?.backgroundColor)\n ? options?.backgroundColor\n : themes?.defaultBackgroundColor?.(props);\n\n if (config.supports.includes(VizBehavior.PLACEHOLDER) && showPlaceholder) {\n return (\n <IconPlaceholder\n data-test=\"icon-placeholder\"\n icon={icon}\n width={width}\n height={height}\n backgroundColor={bgColorFromTheme}\n iconColor={iconColor}\n />\n );\n }\n\n return <Visualization {...props} />;\n };\n extendStaticWrapperProps({ Wrapper, Visualization });\n return Wrapper as ExtendedDashViz;\n};\n\nexport default withPlaceholder;\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/numberUtils\";\nexport * from \"@splunk/visualizations-shared/numberUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import type { FieldEntry } from '@splunk/visualizations-shared/dataSourceUtils';\nimport { startsWithNumber } from '@splunk/visualizations-shared/numberUtils';\nimport type { DashboardVizProps, DataSource, VizConfig } from '../interfaces';\nimport { VizBehavior } from '../interfaces';\nimport { ChartEvent } from '../interfaces/ChartEvent';\n\nexport const convertToArrOfObjects = (columns: (string | any[])[], fields: any[]): any[] => {\n if (!columns?.[0]?.length) return [];\n\n const data = [];\n\n for (let i = 0; i < columns[0].length; i += 1) {\n const newObj = {};\n fields.forEach((field, index) => {\n const fieldName = getFieldName(field);\n if (columns[index][i] === '') {\n newObj[fieldName] = null;\n } else {\n newObj[fieldName] = columns[index][i];\n }\n });\n data.push(newObj);\n }\n\n return data;\n};\n\nconst getFieldName = (field: FieldEntry | string): string => (typeof field === 'string' ? field : field.name);\n\n// LTTB algorithm which can be used to downsample time series data while striving to maintain\n// the spikes and overall shape of the chart\n// Copied from https://github.com/sveinn-steinarsson/flot-downsample/blob/0815010016fc94b1bbc6a010afb8aad13ada6d0d/jquery.flot.downsample.js\n// Modifications include:\n// 1) Convert to modern JavaScript(use const, let, and use array.push to push to last element of array)\n// 2) Convert to camel case\n// 3) Convert to TS and also return the indices of the points that are in the downsampled result.\n// 4) Add a new parameter preferredDownsampleIndices that correspond to the indices of points\n// that should be used in case of a tie of the max area in a bucket\nconst largestTriangleThreeBuckets = (\n data: [Date | number, number][],\n threshold: number,\n preferredDownsampleIndices: Set<number>\n): {\n downsampledData: [Date | number, number][];\n downsampledIndices: number[];\n} => {\n const dataLength = data.length;\n const downsampledIndices = [];\n if (threshold >= dataLength || threshold === 0) {\n const allIndices = data.map((values, index) => index);\n return { downsampledData: data, downsampledIndices: allIndices }; // Nothing to do\n }\n\n const sampled: [Date | number, number][] = [];\n let sampledIndex = 0;\n\n // Bucket size. Leave room for start and end data points\n const every = (dataLength - 2) / (threshold - 2);\n\n let a = 0; // Initially a is the first point in the triangle\n let maxAreaPoint: [Date | number, number];\n let maxArea: number | undefined;\n let area: number | undefined;\n let nextA: number | undefined;\n\n sampled.push(data[a]); // Always add the first point\n downsampledIndices.push(0);\n\n // eslint-disable-next-line no-plusplus\n for (let i = 0; i < threshold - 2; i++) {\n // Calculate point average for next bucket (containing c)\n let avgX = 0;\n let avgY = 0;\n let avgRangeStart = Math.floor((i + 1) * every) + 1;\n let avgRangeEnd = Math.floor((i + 2) * every) + 1;\n avgRangeEnd = Math.min(avgRangeEnd, dataLength);\n\n const avgRangeLength = avgRangeEnd - avgRangeStart;\n\n // eslint-disable-next-line no-plusplus\n for (; avgRangeStart < avgRangeEnd; avgRangeStart++) {\n avgX += Number(data[avgRangeStart][0]); // * 1 enforces Number (value may be Date)\n avgY += data[avgRangeStart][1] * 1;\n }\n avgX /= avgRangeLength;\n avgY /= avgRangeLength;\n\n // Get the range for this bucket\n let rangeOffs = Math.floor((i + 0) * every) + 1;\n const rangeTo = Math.floor((i + 1) * every) + 1;\n\n // Point a\n const pointAX = Number(data[a][0]); // Enforce Number (value may be Date)\n const pointAY = data[a][1] * 1;\n\n // eslint-disable-next-line no-multi-assign\n maxArea = area = -1;\n let maxAreaIndex = rangeOffs;\n\n // eslint-disable-next-line no-plusplus\n for (; rangeOffs < rangeTo; rangeOffs++) {\n // Calculate triangle area over three buckets\n area =\n Math.abs(\n (pointAX - avgX) * (data[rangeOffs][1] - pointAY) -\n (pointAX - Number(data[rangeOffs][0])) * (avgY - pointAY)\n ) * 0.5;\n // Modification: try to downsample the least amount of points possible when there are multiple series\n // If all points in a bucket have the same area, prioritize the one with an x index\n // that also existed from another series so we don't add another point unnecessarily.\n // By default LTTB picks the leftmost point in the bucket\n if (area > maxArea || (area === maxArea && preferredDownsampleIndices.has(rangeOffs))) {\n maxArea = area;\n maxAreaPoint = data[rangeOffs];\n nextA = rangeOffs; // Next a is this b\n // Modification: save the index of the point with the most area\n maxAreaIndex = rangeOffs;\n }\n }\n\n // eslint-disable-next-line no-plusplus\n sampled[sampledIndex++] = maxAreaPoint; // Pick this point from the bucket\n downsampledIndices.push(maxAreaIndex);\n a = nextA; // This a is the next a (chosen b)\n }\n\n // eslint-disable-next-line no-plusplus\n sampled[sampledIndex++] = data[dataLength - 1]; // Always add last\n downsampledIndices.push(dataLength - 1);\n\n return { downsampledData: sampled, downsampledIndices };\n};\n\nexport type DownsampleOptions = { threshold: number } & Pick<DashboardVizProps, 'dataSources' | 'options'>;\n\ntype CoerceYColumnResult = {\n canDownsampleColumn: boolean;\n canLooselyCoerceSomeValues: boolean;\n coercedColumn: number[];\n};\n\n/**\n * Strictly coerces the entire column to numbers if it only consists of numeric strings or numbers. Also determines\n * if at least one of the values in the column can be loosely coerced to a number.\n * If the column cannot be strictly downsampled (if it contains nulls or non-numeric strings), returns an empty array and\n * returns that it cannot downsample the column.\n */\nconst strictlyCoerceYColumn = (\n column: (string | number)[] | number[],\n options: DownsampleOptions['options']\n): CoerceYColumnResult => {\n const isNullCoercionEnabled = options.nullValueDisplay === 'zero';\n // Splunk charting allows for numbers in formats such as negative hex that\n // Number() does not support and also allows loose coercion of hex numbers (but not other formats)\n // We want to identify columns which contain at least one value that can be loosely coerced\n const canLooselyCoerceSomeValues = column.some(\n value => startsWithNumber(`${value}`) || (isNullCoercionEnabled && value === null)\n );\n\n // If not all values in column can be strictly coerced to a number, we do not downsample\n const coercedColumn: number[] = [];\n const canDownsampleColumn = !column.some(value => {\n const coercedValue = Number(value);\n const coerceValueToZero = isNullCoercionEnabled && value === null;\n\n // if it can't be parsed or isn't safe, fail\n if (\n Number.isNaN(coercedValue) ||\n coercedValue <= Number.MIN_SAFE_INTEGER ||\n coercedValue >= Number.MAX_SAFE_INTEGER ||\n (typeof value !== 'string' && typeof value !== 'number' && !coerceValueToZero)\n ) {\n return true;\n }\n // save value and continue to next\n coercedColumn.push(coercedValue);\n return false;\n });\n\n return {\n canDownsampleColumn,\n canLooselyCoerceSomeValues,\n coercedColumn: canDownsampleColumn ? coercedColumn : [],\n };\n};\n\n/**\n * Tries to coerce the x-column to numbers or dates, if it is eligible for downsampling.\n * Only strictly increasing x-columns are eligible for downsampling.\n * If the column is not eligible for downsampling, returns an empty array.\n */\nconst strictlyCoerceXColumn = (column: (string | number)[], fieldType: string): Date[] | number[] => {\n if (fieldType === 'number') {\n const coercedXColumn = column.map(Number);\n if (isColumnStrictlyIncreasing(coercedXColumn, fieldType)) {\n return coercedXColumn;\n }\n } else if (fieldType === 'time') {\n const coercedXColumn = column.map(xValue => new Date(xValue));\n if (isColumnStrictlyIncreasing(coercedXColumn, fieldType)) {\n return coercedXColumn;\n }\n }\n return [];\n};\n\nexport const isDownsamplingEnabledForViz = ({ vizConfig }: { vizConfig: VizConfig }) => {\n return vizConfig.supports?.includes(VizBehavior.DOWNSAMPLING);\n};\n\nexport const calculateThresholdOnRangeSelect = ({\n firstIndex,\n lastIndex,\n dataSources,\n width,\n}: Pick<DashboardVizProps, 'dataSources'> & {\n firstIndex: number;\n lastIndex: number;\n width: number | string;\n}): number => {\n const window = lastIndex - firstIndex + 1;\n // eslint-disable-next-line no-unsafe-optional-chaining\n const ratio = Math.round(Number(dataSources?.primary?.data?.columns[0]?.length / window) * 10) / 10;\n return Math.round(ratio * Number(width));\n};\n\n/**\n * Calculates the downsampling threshold based on the range selection. If search zoom is enabled or there is no selection,\n * then returns the width of the visualization.\n *\n * Otherwise calculates the threshold based on the ratio of the window selected compared to the size of the non-downsampled\n * data sources. Returns null if the chart event's dataset does not match the passed in primary data source or if the chart is zoomed\n * in for a categorical chart.\n */\nexport const calculateDownsamplingThreshold = ({\n enableSearchZoom,\n dataSources,\n selectChartEvent,\n width,\n xField,\n}: {\n enableSearchZoom: boolean;\n dataSources: Record<string, DataSource> | null;\n selectChartEvent: ChartEvent<'chartRangeSelect'> | null;\n width: number;\n xField: string;\n}): number | null => {\n if (enableSearchZoom || !selectChartEvent) {\n return Number(width);\n }\n\n const primaryDataSource = dataSources?.primary;\n if (!primaryDataSource) {\n return null;\n }\n\n const { startXIndex, endXIndex, currentTarget } = selectChartEvent;\n\n try {\n const xFieldIndex = primaryDataSource?.data?.fields.findIndex(field => {\n const name = typeof field === 'string' ? field : field.name;\n return name === xField;\n });\n // .indexOf is not usable here: dataSet.fields is a union type (FieldEntry[] & string[]), so indexOf(xField) fails to type-check\n const downsampledXFieldIndex = currentTarget.dataSet?.fields.findIndex(field => field === xField); // NOSONAR typescript:S7753 - see note above\n\n if (xFieldIndex === -1 || downsampledXFieldIndex === -1) {\n return null;\n }\n\n const fullSeries = primaryDataSource?.data?.columns[xFieldIndex];\n const downsampledSeries = currentTarget.dataSet.seriesList[downsampledXFieldIndex];\n\n const firstIndex = fullSeries.indexOf(downsampledSeries[startXIndex]);\n const lastIndex = fullSeries.indexOf(downsampledSeries[endXIndex]);\n\n if (firstIndex >= 0 && lastIndex >= 0 && firstIndex <= lastIndex) {\n return calculateThresholdOnRangeSelect({\n firstIndex,\n lastIndex,\n dataSources,\n width,\n });\n }\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error('Error occurred while setting downsample threshold on range select event', e);\n }\n\n return null;\n};\n\nconst isColumnStrictlyIncreasing = (column: (number | Date)[], fieldType: 'number' | 'time') => {\n return column.every((value, index) => {\n if (fieldType === 'number') {\n if (Number.isNaN(value)) {\n return false;\n }\n }\n\n if (fieldType === 'time') {\n if (Number.isNaN((value as Date).getTime())) {\n return false;\n }\n }\n if (index === 0) {\n return true;\n }\n return value > column[index - 1];\n });\n};\n\n/**\n * Verifies that all of the columns that are displayed in a chart can be downsampled. Valid columns that can be\n * displayed are those that contain at least one number. We can only downsample columns that only consist of numbers.\n *\n * If all columns can be downsampled, returns the x column coerced to time/number and y columns coerced to numbers.\n * If not all columns can be downsampled, then returns empty arrays for both x and y\n */\nconst tryToCoerceAllDisplayedFields = (\n ds: DataSource,\n xField: string,\n yFields: Set<string>,\n fieldTypes: string[],\n options: DownsampleOptions['options']\n): { xColumn: Date[] | number[]; yColumns: number[][] } => {\n let xColumn: Date[] | number[] = [];\n const yColumns: number[][] = [];\n\n const canDownsample = !ds.data.fields.some((field, index) => {\n const fieldName = getFieldName(field);\n const fieldType = fieldTypes[index] ?? 'unknown';\n const column = ds.data.columns[index];\n let hasDisplayedColumnThatCantBeDownsampled = false;\n\n if (fieldName === xField) {\n xColumn = strictlyCoerceXColumn(column, fieldType);\n } else if (yFields.has(fieldName)) {\n const { coercedColumn, canLooselyCoerceSomeValues, canDownsampleColumn } = strictlyCoerceYColumn(\n ds.data.columns[index],\n options\n );\n // do not perform downsampling if a column can possibly be displayed but cannot\n // be downsampled using LTTB\n hasDisplayedColumnThatCantBeDownsampled = canLooselyCoerceSomeValues && !canDownsampleColumn;\n if (hasDisplayedColumnThatCantBeDownsampled) {\n return true;\n }\n if (canDownsampleColumn) {\n yColumns.push(coercedColumn);\n }\n }\n return false;\n });\n\n if (canDownsample) {\n return { xColumn, yColumns };\n }\n return { xColumn: [], yColumns: [] };\n};\n\nconst pickIndicesFromDataSource = (ds: DataSource, indices: Set<number>): DataSource => {\n const sortedIndices = Array.from(indices).sort((a: number, b: number) => a - b);\n const slicedColumns = [];\n ds.data.columns.forEach(column => {\n const slicedColumn = [];\n sortedIndices.forEach(index => {\n slicedColumn.push(column[index]);\n });\n slicedColumns.push(slicedColumn);\n });\n\n // update data columns with downsampled columns\n return {\n ...ds,\n data: {\n ...ds.data,\n columns: slicedColumns,\n },\n };\n};\n\nexport const downsampleDataSources = ({ dataSources, threshold, options }: DownsampleOptions) => {\n const primaryDS = dataSources?.primary;\n // only downsample time series when number of data points are over threshold\n const numPoints = primaryDS?.data?.columns[0]?.length ?? 0;\n if (Number.isNaN(threshold) || numPoints <= threshold || threshold < 2) {\n return dataSources;\n }\n\n const { xField, yFields, fieldTypes } = options;\n if (!xField || !yFields?.length || !fieldTypes?.length) {\n return dataSources;\n }\n\n const nonInternalYFields = new Set<string>(yFields.filter(yField => !yField.startsWith('_')));\n const maxPointsInDownsample = Math.min(nonInternalYFields.size * threshold, numPoints);\n\n // Do not try to downsample if there are too many downsampled pts\n // At the worst case, each series has non-overlapping downsampled pts\n // which will mean that all points will be included in the downsampled result\n // This will just lead to additional overhead due to coercing each\n // x and y field to number\n if (maxPointsInDownsample >= numPoints) {\n return dataSources;\n }\n\n const { xColumn, yColumns } = tryToCoerceAllDisplayedFields(\n primaryDS,\n xField,\n nonInternalYFields,\n fieldTypes,\n options\n );\n\n if (!yColumns.length || !xColumn.length) {\n return dataSources;\n }\n\n const downsampledDataSources = { ...dataSources };\n const downsampledIndices = new Set<number>();\n\n yColumns.forEach((yColumn, columnIndex) => {\n // perform LTTB downsampling for current series, LTTB takes an [x, y] pair\n const xyPair: [Date | number, number][] = yColumn.map((yValue, index) => {\n return [xColumn[index], yValue];\n });\n\n try {\n const { downsampledIndices: downsampledIndicesForSeries } = largestTriangleThreeBuckets(\n xyPair,\n threshold,\n downsampledIndices\n );\n downsampledIndicesForSeries.forEach(downsampleIndex => downsampledIndices.add(downsampleIndex));\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(`Error occurred while downsampling column ${columnIndex}`, e);\n }\n });\n // update data columns with downsampled columns\n downsampledDataSources.primary = pickIndicesFromDataSource(primaryDS, downsampledIndices);\n\n return downsampledDataSources;\n};\n", "import { useEffect, useRef } from 'react';\n\nexport default function usePrevious<T>(value: T): T | undefined {\n const ref = useRef<T>();\n useEffect(() => {\n ref.current = value;\n });\n return ref.current;\n}\n", "import { useMemo } from 'react';\nimport { Options as Opts } from '@splunk/visualization-encoding/Options';\nimport type { DashboardVizProps } from '../interfaces';\n\n/**\n * Hook that evaluates the DSL for subset of a viz's options needed to determine\n * its x and y fields as well as the types of all its fields.\n */\nconst useGetXAndYFields = ({\n shouldEvaluateDSL,\n options,\n context,\n dataSources,\n}: Pick<DashboardVizProps, 'dataSources' | 'options' | 'context'> & {\n shouldEvaluateDSL: boolean;\n}) => {\n const { dataSourcesWithOnlyOnePoint, dataFrameWithOnlyOnePoint } = useMemo(() => {\n if (!shouldEvaluateDSL) {\n return {\n dataSourcesWithOnlyOnePoint: null,\n dataFrameWithOnlyOnePoint: null,\n };\n }\n\n if (!dataSources?.primary?.data?.columns?.length) {\n return {\n dataSourcesWithOnlyOnePoint: null,\n dataFrameWithOnlyOnePoint: null,\n };\n }\n const { primary: primaryDS } = dataSources;\n\n const columnsWithOnlyOnePoint = primaryDS.data.columns.map(column => {\n return [column[0]];\n });\n\n const filteredDataSources = {\n primary: {\n ...primaryDS,\n data: {\n ...primaryDS.data,\n columns: columnsWithOnlyOnePoint,\n },\n },\n };\n\n return {\n dataSourcesWithOnlyOnePoint: filteredDataSources,\n dataFrameWithOnlyOnePoint: Opts.dataFrameFromDataSource(filteredDataSources),\n };\n }, [dataSources, shouldEvaluateDSL]);\n\n const xAndYFieldsWithTypes = useMemo(() => {\n try {\n if (!dataSourcesWithOnlyOnePoint || !dataFrameWithOnlyOnePoint) {\n return options;\n }\n\n if (!options?.x || (!options?.y && !options?.y2)) {\n return options;\n }\n\n const optionsToEvaluate = {\n x: options.x,\n xField: '> x | getField()',\n y: options.y,\n yFields: options.y ? '> y | getField()' : undefined,\n y2: options.y2,\n y2Fields: options.y2 ? '> y2 | getField()' : undefined,\n fieldTypes: '> primary | getType()',\n };\n\n const {\n xField = '',\n yFields = [],\n y2Fields = [],\n fieldTypes,\n } = Opts.evaluate(\n { options: optionsToEvaluate, context },\n dataSourcesWithOnlyOnePoint,\n () => {},\n dataFrameWithOnlyOnePoint\n );\n return {\n xField,\n yFields: [...yFields, ...y2Fields],\n fieldTypes,\n };\n } catch (e) /* NOSONAR typescript:S2486 - Evaluation failure falls back to empty field data */ {\n return {\n xField: undefined,\n yFields: [],\n fieldTypes: [],\n };\n }\n }, [options, context, dataSourcesWithOnlyOnePoint, dataFrameWithOnlyOnePoint]);\n\n return xAndYFieldsWithTypes;\n};\n\nexport default useGetXAndYFields;\n", "import { useRef, useMemo, useEffect, useState } from 'react';\nimport { debounce, isEqual, pick } from 'lodash';\nimport type { DashboardVizProps } from '../interfaces';\nimport type { DownsampleOptions } from '../utils/dataUtils';\nimport { downsampleDataSources } from '../utils/dataUtils';\nimport usePrevious from './usePrevious';\nimport useGetXAndYFields from './useGetXAndYFields';\n\n// Options properties which impact/require re-downsample on change.\nconst downsampleVizOptionProperties = ['nullValueDisplay'];\n\nconst useDownsampleDataSources = ({\n dataSources,\n options,\n context,\n threshold,\n isDownsamplingEnabled,\n}: Pick<DashboardVizProps, 'dataSources' | 'options' | 'context'> & {\n threshold: number;\n isDownsamplingEnabled?: boolean;\n}) => {\n const isFirstUseEffectCall = useRef(true);\n\n const xAndYFieldsWithTypes = useGetXAndYFields({\n shouldEvaluateDSL: isDownsamplingEnabled,\n options,\n context,\n dataSources,\n });\n\n // Extract viz options that impact downsampling.\n const downsampleVizOptions = useMemo(() => pick(options, downsampleVizOptionProperties), [options]);\n const downsampleDSOptions = useMemo(\n () => ({\n ...downsampleVizOptions,\n ...xAndYFieldsWithTypes,\n }),\n [xAndYFieldsWithTypes, downsampleVizOptions]\n );\n\n const previousDownsampleDSOptions = usePrevious(downsampleDSOptions);\n const previousDataSources = usePrevious(dataSources);\n const previousThreshold = usePrevious(threshold);\n\n const [downsampledDataSources, setDownsampledDataSources] = useState(() => {\n return isDownsamplingEnabled\n ? downsampleDataSources({\n dataSources,\n threshold,\n options: downsampleDSOptions,\n })\n : dataSources;\n });\n\n const debouncedDownsampleDataSources = useMemo(() => {\n return debounce(\n (downsampleOptions: DownsampleOptions) => {\n const downsampledResult = downsampleDataSources(downsampleOptions);\n setDownsampledDataSources(downsampledResult);\n },\n 100,\n { trailing: true }\n );\n }, []);\n\n useEffect(() => {\n // don't downsample again on the use effect call that happened due to the initial render\n // this is since we already downsampled as part of the useState call\n if (isFirstUseEffectCall.current) {\n isFirstUseEffectCall.current = false;\n return;\n }\n\n if (!isDownsamplingEnabled) {\n setDownsampledDataSources(dataSources);\n return;\n }\n\n if (\n isEqual(previousDownsampleDSOptions, downsampleDSOptions) &&\n previousDataSources === dataSources &&\n previousThreshold === threshold\n ) {\n return;\n }\n\n // Debounce the downsampling so we don't have to downsample and execute DSL multiple times\n // while the viz is being resized\n debouncedDownsampleDataSources({\n dataSources,\n options: downsampleDSOptions, // Dont want to re-downsample everytime the options change\n threshold,\n });\n\n // need to detect if this runs as part of the initial render\n }, [\n dataSources,\n downsampleDSOptions,\n debouncedDownsampleDataSources,\n xAndYFieldsWithTypes,\n threshold,\n isDownsamplingEnabled,\n previousDataSources,\n previousThreshold,\n previousDownsampleDSOptions,\n ]);\n\n return downsampledDataSources;\n};\n\nexport default useDownsampleDataSources;\n", "\nimport * as defaultImport from \"@splunk/visualization-context/FeatureFlags\";\nexport * from \"@splunk/visualization-context/FeatureFlags\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import * as React from 'react';\nimport FeatureFlags from '@splunk/visualization-context/FeatureFlags';\n\nexport const getFeatureFlag = (\n context: React.Context<any> | null | undefined | Record<keyof typeof FeatureFlags, boolean>,\n flagName: string\n): boolean => {\n // look for feature flag in context first\n if (context && Object.keys(context).includes(flagName)) {\n return context[flagName];\n }\n\n // fall back to defaults\n if (Object.keys(FeatureFlags).includes(flagName)) {\n return FeatureFlags[flagName];\n }\n\n // fall back to false\n return false;\n};\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/trellisUtils\";\nexport * from \"@splunk/visualizations-shared/trellisUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import { cloneDeep, omit } from 'lodash';\nimport { FieldEntry } from '@splunk/visualizations-shared/dataSourceUtils';\nimport {\n DataSplitMode,\n CHART,\n TIMECHART,\n STATS,\n UNKNOWN,\n extractDataSourceAggregationKeysChart,\n extractDataSourceAggregationKeysStats,\n extractSplitByFieldsChartFields,\n extractSplitByFieldsForStats,\n extractSplitByFieldsForUnknown,\n} from '@splunk/visualizations-shared/trellisUtils';\nimport { DataSource } from '../interfaces/DataSource';\n\nexport type SplitDataSource = { [key: string]: { [name: string]: DataSource } };\nexport interface DataSplitResult {\n splitDataSources: SplitDataSource;\n errorCode: 'UNKNOWN_DATA_SPLIT_MODE' | 'INVALID_SPLIT_BY_FIELD' | 'UNKNOWN';\n}\nexport const AGGREGATIONS = 'aggregations';\n\n/**\n * There can be certain SPL cmds that can produce dataSource without a specific field meta info (like group_by_rank, split_by_field etc),\n * to categorize it,\n * Example1:- `index = \"_internal\" | chart count`\n * Example2:- `index=_internal | chart avg(count), max(count)`\n * Example3:- `index = \"_internal\" | stats count`\n * Example4:- `index=_internal | stats avg(count), max(count)`\n */\nexport const dataSourcesSplitByAggregationsUnknown = (dataSource: {\n [name: string]: DataSource;\n}): DataSplitResult => {\n const fields = toFieldEntries(dataSource?.primary?.data?.fields);\n const columns = dataSource?.primary?.data?.columns;\n let splitDataSources = null;\n let errorCode = null;\n\n if (fields?.length) {\n splitDataSources = {};\n for (let i = 0; i < fields.length; i += 1) {\n const fieldName = fields[i].name;\n if (!fieldName?.startsWith('_')) {\n splitDataSources[fieldName] = cloneDeep(\n omit(dataSource, ['primary.data.fields', 'primary.data.columns'])\n );\n splitDataSources[fieldName].primary.data.fields = [fields[i]];\n splitDataSources[fieldName].primary.data.columns = [columns[i]];\n }\n }\n } else {\n errorCode = 'INVALID_SPLIT_BY_FIELD';\n }\n return { splitDataSources, errorCode };\n};\n\nconst toFieldEntries = (fields: FieldEntry[] | string[] = []): FieldEntry[] => {\n return fields.map(field => {\n if (typeof field === 'string') {\n return { name: field };\n }\n return field;\n });\n};\n\nexport const dataSourcesSplitByAggregationsTimechartAndChart = (dataSource: {\n [name: string]: DataSource;\n}): DataSplitResult => {\n const fields = toFieldEntries(dataSource?.primary?.data?.fields);\n const columns = dataSource?.primary?.data?.columns;\n let splitDataSources = null;\n let splitByFields = [];\n let errorCode = null;\n\n if (fields.length > 0) {\n splitByFields = extractDataSourceAggregationKeysChart(fields);\n }\n\n if (splitByFields && splitByFields.length > 0) {\n splitDataSources = {};\n splitByFields.forEach(splitByField => {\n splitDataSources[splitByField] = cloneDeep(\n omit(dataSource, ['primary.data.fields', 'primary.data.columns'])\n );\n splitDataSources[splitByField].primary.data.fields = [fields[0]];\n splitDataSources[splitByField].primary.data.columns = [columns[0]];\n fields.forEach((field: FieldEntry, idx) => {\n const fieldName = field?.name;\n if (\n fieldName !== '_time' &&\n !fieldName?.startsWith('_') &&\n field.data_source === splitByField\n ) {\n splitDataSources[splitByField].primary.data.fields.push(field);\n splitDataSources[splitByField].primary.data.columns.push(columns[idx]);\n }\n });\n });\n } else if (!splitByFields?.length && fields.length > 1) {\n // handle where data_source doesnot exist in fields\n // example1 :- index=_internal | timechart count\n // example2 :- index=_internal | timechart max(count) avg(count)\n splitDataSources = {};\n for (let i = 1; i < fields.length; i += 1) {\n const fieldName = fields[i].name;\n if (!fieldName?.startsWith('_')) {\n splitDataSources[fieldName] = cloneDeep(\n omit(dataSource, ['primary.data.fields', 'primary.data.columns'])\n );\n splitDataSources[fieldName].primary.data.fields = [fields[0], fields[i]];\n splitDataSources[fieldName].primary.data.columns = [columns[0], columns[i]];\n }\n }\n } else {\n errorCode = 'INVALID_SPLIT_BY_FIELD';\n }\n return { splitDataSources, errorCode };\n};\n\nexport const dataSourcesSplitByAggregationsStats = (dataSource: {\n [name: string]: DataSource;\n}): DataSplitResult => {\n const fields = toFieldEntries(dataSource?.primary?.data?.fields);\n const columns = dataSource?.primary?.data?.columns;\n let splitDataSources = null;\n let splitByFields = [];\n let errorCode = null;\n if (fields.length > 0) {\n splitByFields = extractDataSourceAggregationKeysStats(fields);\n }\n\n if (splitByFields && splitByFields.length > 0) {\n splitDataSources = {};\n splitByFields.forEach(splitByField => {\n splitDataSources[splitByField] = cloneDeep(\n omit(dataSource, ['primary.data.fields', 'primary.data.columns'])\n );\n splitDataSources[splitByField].primary.data.fields = [fields[0]];\n splitDataSources[splitByField].primary.data.columns = [columns[0]];\n const idx = fields.findIndex(field => field.name === splitByField);\n if (idx > 0) {\n splitDataSources[splitByField].primary.data.fields.push(fields[idx]);\n splitDataSources[splitByField].primary.data.columns.push(columns[idx]);\n }\n });\n } else {\n errorCode = 'INVALID_SPLIT_BY_FIELD';\n }\n return { splitDataSources, errorCode };\n};\n\nexport const dataSourcesSplitByModeTimechart = (\n dataSource: { [name: string]: DataSource },\n splitBy: string\n): DataSplitResult => {\n const fields = toFieldEntries(dataSource?.primary?.data?.fields);\n const columns = dataSource?.primary?.data?.columns;\n let splitDataSources = null;\n let splitByFields = [];\n let errorCode = null;\n if (fields.length > 0) {\n splitByFields = extractSplitByFieldsChartFields(fields);\n }\n if (splitByFields?.includes(splitBy)) {\n splitDataSources = {};\n const dataSourceKeys = extractDataSourceAggregationKeysChart(fields);\n const valueKeys = [];\n for (let i = 1; i < fields.length; i += 1) {\n // not including internal fields\n if (!fields[i].name?.startsWith('_')) {\n valueKeys.push(fields[i].splitby_value ? fields[i].splitby_value : fields[i].name);\n }\n }\n valueKeys.forEach(val => {\n splitDataSources[val] = cloneDeep(\n omit(dataSource, ['primary.data.fields', 'primary.data.columns'])\n );\n splitDataSources[val].primary.data.fields = [{ name: fields[0].name }];\n splitDataSources[val].primary.data.columns = [[...columns[0]]];\n dataSourceKeys.forEach(dsKey => {\n fields.forEach((field, idx) => {\n if (field.data_source === dsKey && (field.splitby_value === val || field.name === val)) {\n // only push valid fields for the current split by valueKey, instead of all fields.\n splitDataSources[val].primary.data.fields.push({\n name: dsKey,\n });\n splitDataSources[val].primary.data.columns.push([...columns[idx]]);\n }\n });\n });\n });\n } else {\n errorCode = 'INVALID_SPLIT_BY_FIELD';\n }\n return { splitDataSources, errorCode };\n};\n\nconst splitRowWise = (\n dataSource: { [name: string]: DataSource },\n columns,\n fields,\n otherSplitBy: string[],\n dataSourceKeys: string[],\n nonDataSourceAggregations: string[]\n) => {\n const splitDataSources = {};\n const valueKeys = cloneDeep(columns[0]);\n valueKeys.forEach((val, idx) => {\n splitDataSources[val] = cloneDeep(omit(dataSource, ['primary.data.fields', 'primary.data.columns']));\n splitDataSources[val].primary.data.fields = [];\n if (otherSplitBy.length) {\n splitDataSources[val].primary.data.fields = [{ name: otherSplitBy[0] }];\n }\n if (dataSourceKeys.length) {\n const columnValues = [[]];\n splitDataSources[val].primary.data.fields = [\n ...splitDataSources[val].primary.data.fields,\n ...dataSourceKeys.map(k => ({ name: k })),\n ];\n dataSourceKeys.forEach(() => {\n columnValues.push([]);\n });\n for (let i = 1; i <= Math.ceil((fields.length - 1) / dataSourceKeys.length); i += 1) {\n columnValues[0].push(fields[i].splitby_value ? fields[i].splitby_value : fields[i].name);\n dataSourceKeys.forEach((dskey, dsIndx) => {\n const mul = (fields.length - 1) / dataSourceKeys.length;\n columnValues[dsIndx + 1].push(columns[i + dsIndx * mul][idx]);\n });\n }\n splitDataSources[val].primary.data.columns = columnValues;\n } else if (nonDataSourceAggregations.length) {\n const columnValues = [];\n fields.forEach((aggregationField, fieldIdx) => {\n if (fieldIdx > 0) {\n splitDataSources[val].primary.data.fields.push(aggregationField);\n columnValues.push([columns[fieldIdx][idx]]);\n }\n });\n splitDataSources[val].primary.data.columns = columnValues;\n }\n });\n return splitDataSources;\n};\n\nconst splitColumnWise = (\n dataSource: { [name: string]: DataSource },\n columns,\n fields,\n otherSplitBy: string[],\n dataSourceKeys: string[]\n) => {\n const splitDataSources = {};\n const valueKeys = [];\n for (let i = 1; i < fields.length; i += 1) {\n valueKeys.push(fields[i].splitby_value ? fields[i].splitby_value : fields[i].name);\n }\n valueKeys.forEach(val => {\n splitDataSources[val] = cloneDeep(omit(dataSource, ['primary.data.fields', 'primary.data.columns']));\n splitDataSources[val].primary.data.fields = [\n { name: otherSplitBy[0] },\n ...dataSourceKeys.map(k => ({ name: k })),\n ];\n splitDataSources[val].primary.data.columns = [[...columns[0]]];\n dataSourceKeys.forEach(dsKey => {\n fields.forEach((field, idx) => {\n if (field.data_source === dsKey && (field.splitby_value === val || field.name === val)) {\n splitDataSources[val].primary.data.columns.push([...columns[idx]]);\n }\n });\n });\n });\n return splitDataSources;\n};\n\nexport const dataSourcesSplitByModeChart = (\n dataSource: { [name: string]: DataSource },\n splitBy: string\n): DataSplitResult => {\n const fields = toFieldEntries(dataSource?.primary?.data?.fields);\n const columns = dataSource?.primary?.data?.columns;\n let splitDataSources = null;\n let splitByFields = [];\n let errorCode = null;\n if (fields.length > 0) {\n splitByFields = extractSplitByFieldsChartFields(fields);\n }\n if (splitByFields?.includes(splitBy)) {\n const splitByFieldIdx = splitByFields.indexOf(splitBy);\n const otherSplitBy = splitByFields.filter(f => f !== splitBy);\n const dataSourceKeys = extractDataSourceAggregationKeysChart(fields);\n const nonDataSourceAggregations = [];\n if (\n !dataSourceKeys.length &&\n fields[0].groupby_rank === '0' &&\n fields.length &&\n !fields[1].groupby_rank\n ) {\n for (let i = 1; i < fields.length; i += 1) {\n nonDataSourceAggregations.push(fields[i].name);\n }\n }\n if (splitByFieldIdx === 0) {\n splitDataSources = splitRowWise(\n dataSource,\n columns,\n fields,\n otherSplitBy,\n dataSourceKeys,\n nonDataSourceAggregations\n );\n } else {\n splitDataSources = splitColumnWise(dataSource, columns, fields, otherSplitBy, dataSourceKeys);\n }\n } else {\n errorCode = 'INVALID_SPLIT_BY_FIELD';\n }\n return { splitDataSources, errorCode };\n};\n\n/**\n * This method does datasplitting for 'stats' and generic cmds('makeresults','table' etc - categoried as 'unknown' splitMode).\n * The main difference is for 'stats' cmd possible splitBy fields have 'group_by_rank' in field meta info, whereas for 'unknown' cmd it can be any fieldnames\n */\nexport const dataSourcesSplitByModeStatsorUnknown = (\n dataSource: { [name: string]: DataSource },\n splitBy: string,\n splitMode?: DataSplitMode\n): DataSplitResult => {\n const fields = toFieldEntries(dataSource?.primary?.data?.fields);\n const columns = dataSource?.primary?.data?.columns;\n let splitDataSources = null;\n let splitByFields = [];\n let errorCode = null;\n if (fields.length > 0) {\n splitByFields =\n splitMode === UNKNOWN\n ? extractSplitByFieldsForUnknown(fields)\n : extractSplitByFieldsForStats(fields);\n }\n const splitByIndex = fields.findIndex(field => field.name === splitBy);\n if (splitByFields?.includes(splitBy)) {\n const splitByColumn = dataSource?.primary?.data?.columns[splitByIndex];\n splitDataSources = {};\n splitByColumn.forEach((val, idx) => {\n if (splitDataSources[val]) {\n splitDataSources[val].push(idx);\n } else {\n splitDataSources[val] = [idx];\n }\n });\n const cloneFields = cloneDeep(fields);\n cloneFields.splice(splitByIndex, 1);\n const valueKeys = Object.keys(splitDataSources);\n valueKeys.forEach(val => {\n const valIndices = cloneDeep(splitDataSources[val]);\n splitDataSources[val] = cloneDeep(\n omit(dataSource, ['primary.data.fields', 'primary.data.columns'])\n );\n splitDataSources[val].primary.data.fields = cloneFields;\n splitDataSources[val].primary.data.columns = [];\n columns.forEach((col, idx) => {\n if (idx !== splitByIndex) {\n const newCol = valIndices.map(valIdx => col[valIdx]);\n splitDataSources[val].primary.data.columns.push(newCol);\n }\n });\n });\n } else {\n errorCode = 'INVALID_SPLIT_BY_FIELD';\n }\n return { splitDataSources, errorCode };\n};\n\nexport const getTrellisDataSourcesBySplitMode = (\n splitMode: DataSplitMode,\n dataSources: { [name: string]: DataSource },\n trellisSplitBy: string\n): DataSplitResult => {\n let result: DataSplitResult = null;\n try {\n if (splitMode === TIMECHART) {\n result =\n trellisSplitBy === AGGREGATIONS\n ? dataSourcesSplitByAggregationsTimechartAndChart(dataSources)\n : dataSourcesSplitByModeTimechart(dataSources, trellisSplitBy);\n } else if (splitMode === STATS) {\n result =\n trellisSplitBy === AGGREGATIONS\n ? dataSourcesSplitByAggregationsStats(dataSources)\n : dataSourcesSplitByModeStatsorUnknown(dataSources, trellisSplitBy, STATS);\n } else if (splitMode === CHART) {\n result =\n trellisSplitBy === AGGREGATIONS\n ? dataSourcesSplitByAggregationsTimechartAndChart(dataSources)\n : dataSourcesSplitByModeChart(dataSources, trellisSplitBy);\n } else if (splitMode === UNKNOWN) {\n result =\n trellisSplitBy === AGGREGATIONS\n ? dataSourcesSplitByAggregationsUnknown(dataSources)\n : dataSourcesSplitByModeStatsorUnknown(dataSources, trellisSplitBy, UNKNOWN);\n }\n } catch (ex) {\n // eslint-disable-next-line no-console\n console.error('getTrellisDataSourcesBySplitMode ', ex);\n result = { splitDataSources: null, errorCode: 'UNKNOWN' };\n }\n return result;\n};\n\n/**\n * sets legendDisplay to off when a visualization is in trellis mode and not set by the user\n * @param {Boolean} isTrellisOn\n * @param {DashboardVizOpts} options\n * @param {DashboardVizOpts} defaultOptions\n * @returns { {'legendDisplay', 'off'} or {} }\n */\nexport const turnOffLegendDisplayWhenTrellisIsOn = (\n isTrellisOn: boolean,\n options: Record<string, any>\n): Record<string, string> => {\n if (isTrellisOn && !options.legendDisplay) {\n return {\n legendDisplay: 'off',\n };\n }\n return {};\n};\n\ninterface MinMax {\n min: number;\n max: number;\n}\n\n// Returns the range extended to include every numeric point in the column.\n// Non-numeric strings become NaN and are ignored by the comparisons.\nconst extendMinMaxWithColumn = (column: Array<any>, range: MinMax): MinMax =>\n column.reduce((acc, point) => {\n const pointNumber = Number(point);\n if (Number.isNaN(pointNumber)) {\n return acc;\n }\n return {\n min: Math.min(pointNumber, acc.min),\n max: Math.max(pointNumber, acc.max),\n };\n }, range);\n\nconst calculateSharedMinMax = (splitData: SplitDataSource): Array<number> => {\n let range: MinMax = { min: Infinity, max: -Infinity };\n\n Object.keys(splitData).forEach(splitByKey => {\n const datasources = splitData[splitByKey];\n Object.keys(datasources).forEach(datasourceName => {\n const dataColumns = datasources[datasourceName].data.columns;\n dataColumns.forEach(column => {\n range = extendMinMaxWithColumn(column, range);\n });\n });\n });\n\n return [range.min, range.max];\n};\n\n/**\n * determines min and max to use in trellis mode\n * @param {splitData} SplitDataSource\n * @returns {Array<number | string>} [min, max]\n */\nexport const determineMinMax = (\n splitData: SplitDataSource,\n trellisSharedScale: boolean,\n yAxisMin: number | string,\n yAxisMax: number | string,\n stackMode?: string\n) => {\n if (!trellisSharedScale || stackMode === 'stacked100' || (yAxisMin !== 'auto' && yAxisMax !== 'auto'))\n return [yAxisMin, yAxisMax];\n\n const [sharedMin, sharedMax] = calculateSharedMinMax(splitData);\n\n const shouldUseSharedMax = sharedMax !== -Infinity && yAxisMax === 'auto';\n const shouldUseSharedMin = sharedMin !== Infinity && yAxisMin === 'auto';\n\n return [shouldUseSharedMin ? sharedMin : yAxisMin, shouldUseSharedMax ? sharedMax : yAxisMax];\n};\n", "\nimport * as defaultImport from \"@splunk/visualization-canvas\";\nexport * from \"@splunk/visualization-canvas\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import styled from 'styled-components';\n\nconst VizStyleWrapper = styled.div.attrs(({ dataTestKey }) => ({\n 'data-test': dataTestKey,\n 'data-testid': dataTestKey,\n}))`\n display: flex;\n justify-content: center;\n flex-direction: column;\n width: 100%;\n height: 100%;\n background-color: ${props => props.backgroundColor};\n`;\n\nVizStyleWrapper.displayName = 'VizStyleWrapper';\n\nexport default VizStyleWrapper;\n", "\nimport * as defaultImport from \"@splunk/react-icons/Triangle\";\nexport * from \"@splunk/react-icons/Triangle\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/propUtils\";\nexport * from \"@splunk/visualizations-shared/propUtils\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/visualizations-shared/simpleXMLOptions\";\nexport * from \"@splunk/visualizations-shared/simpleXMLOptions\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import { has, isArray, isUndefined } from 'lodash';\nimport React from 'react';\nimport styled from 'styled-components';\nimport variables from '@splunk/themes/variables';\nimport Triangle from '@splunk/react-icons/Triangle';\nimport { adjustOptionsToSchema } from '@splunk/visualizations-shared/propUtils';\nimport { getSimpleXMLOptionsForProps } from '@splunk/visualizations-shared/simpleXMLOptions';\nimport {\n BottomLegendFactory,\n Legend,\n SideLegendFactory,\n LeftLegendFactory,\n TopLegendFactory,\n ScaleConfig,\n shortenNumber,\n SeriesConfig,\n EventAnnotation,\n EventAnnotationRendererProps,\n} from '@splunk/visualization-canvas';\nimport type { LegendTruncation } from '@splunk/visualization-canvas';\nimport type { JsonColumnData } from './interfaces/DataSource';\n\ninterface ChartOptions {\n [key: string]: any;\n}\n\ninterface TransformAxisChartOptionsParams {\n originalOptions: Record<string, any>;\n optionsSchema: Record<string, any>;\n chart: string;\n convertToSCProps: (options: Record<string, any>) => Record<string, any>;\n preservedProps: string[];\n}\n\nexport const SHARED_AXIS_CHART_CANVAS_SPECIFIC_PROPS = [\n 'yAxisMin',\n 'yAxisMax',\n 'y2AxisMin',\n 'y2AxisMax',\n 'showXMajorGridLines',\n 'showYMajorGridLines',\n 'showY2MajorGridLines',\n 'showYMinorGridLines',\n 'showY2MinorGridLines',\n 'xAxisMajorTickVisibility',\n 'xAxisMajorTickSize',\n 'yAxisMajorTickVisibility',\n 'y2AxisMajorTickVisibility',\n 'yAxisMajorTickSize',\n 'y2AxisMajorTickSize',\n 'yAxisMinorTickVisibility',\n 'y2AxisMinorTickVisibility',\n 'yAxisMinorTickSize',\n 'y2AxisMinorTickSize',\n 'legendMode',\n 'legendTruncation',\n];\n\nexport const transformAxisChartOptions = ({\n originalOptions,\n optionsSchema,\n chart,\n convertToSCProps,\n preservedProps,\n}: TransformAxisChartOptionsParams): Record<string, any> => {\n const returnOptions = adjustOptionsToSchema(originalOptions, optionsSchema);\n const convertedOptions = convertToSCProps(returnOptions);\n const transformed = {\n ...getSimpleXMLOptionsForProps(convertedOptions),\n chart,\n };\n\n const preserved = preservedProps.reduce(\n (acc, prop) => {\n if (returnOptions[prop] !== undefined) {\n acc[prop] = returnOptions[prop];\n }\n return acc;\n },\n {} as Record<string, any>\n );\n\n // Preserve legendLabels as stringified JSON (converted in convertTo*SCProperties)\n if (convertedOptions.legendLabels !== undefined) {\n preserved.legendLabels = convertedOptions.legendLabels;\n }\n\n return { ...transformed, ...preserved };\n};\n\nexport const DEFAULT_LINE_WIDTH = 2;\n/**\n * Get formatted annotations - highcharts expects annotations in a specific format\n * @method getAnnotations\n * @param {Object} options\n * @param {Array} options.annotationX\n * @param {Array} options.annotationColor\n * @param {Array} options.annotationLabel\n * @returns {Array}\n */\nexport const getAnnotations = ({ annotationX, annotationColor, annotationLabel }) =>\n annotationX?.length\n ? annotationX.map((timestamp, i) => ({\n color: annotationColor?.[i],\n label: annotationLabel?.[i],\n time: timestamp,\n }))\n : [];\n\n/**\n * Get formatted annotations for canvas - viz-canvas timeseries expects annotations in a specific format\n * @method getAnnotationsForCanvas\n * @param {Object} options\n * @param {Array} options.annotationX\n * @param {Array} options.annotationColor\n * @param {Array} options.annotationLabel\n * @returns {Array}\n */\nexport const getAnnotationsForCanvas = ({\n annotationX,\n annotationColor,\n annotationLabel,\n}): EventAnnotation[] =>\n annotationX?.length\n ? annotationX.map((timestamp, i) => ({\n key: annotationLabel?.[i],\n time: timestamp,\n color: annotationColor?.[i],\n }))\n : [];\n\n/**\n * Styled Triangle component for event annotations with default severityColorNotice\n */\nconst StyledTriangle = styled(Triangle)<{ eventColor?: string }>`\n color: ${props => props.eventColor || variables.severityColorNotice(props)};\n`;\n\n/**\n * Custom event annotation renderer using Triangle icon from @splunk/react-icons\n * @method triangleEventAnnotationRenderer\n * @param {EventAnnotationRendererProps} props\n * @returns {ReactElement}\n */\nexport const triangleEventAnnotationRenderer: React.FC<EventAnnotationRendererProps> = ({\n event,\n dimensions,\n}) => {\n const eventWithColor = event as EventAnnotation & { color?: string };\n return React.createElement(StyledTriangle, {\n width: `${dimensions.width}px`,\n height: `${dimensions.height}px`,\n viewBox: '0 0 24 24',\n variant: 'filled',\n eventColor: eventWithColor.color,\n });\n};\n\n/**\n * Truncate the result set to given limit\n * @method truncateData\n * @param {Object} dataSet - dataSources.primary.data\n * @param {Number|String} truncationLimit - options['chart.resultTruncationLimit']\n * @returns {Object}\n */\nexport const truncateData = (dataSet, truncationLimit): Record<string, any[]> => {\n if (!dataSet) {\n return null;\n }\n\n const limit = Number.parseInt(truncationLimit, 10);\n if (!limit || limit <= 0) {\n return dataSet;\n }\n\n const truncatedData: Record<string, Array<string[] | number[]>> = {\n ...dataSet,\n };\n truncatedData.columns = truncatedData.columns.map(columnData =>\n columnData && Array.isArray(columnData) ? columnData.slice(0, limit) : columnData\n );\n return truncatedData;\n};\n\n/**\n * Helper method to update the option values into the values that SC accepts\n * @method mapToValues\n * @param {Object} options\n * @returns {Object}\n */\nexport const mapToValues = (optionValuesSCMapping: Record<string, any>) => options => {\n const convertedOptions: Record<string, any> = { ...options };\n Object.keys(optionValuesSCMapping).forEach(key => {\n if (has(options, key)) {\n const updatedValue = optionValuesSCMapping[key][options[key]];\n if (!isUndefined(updatedValue)) {\n convertedOptions[key] = updatedValue;\n }\n }\n });\n return convertedOptions;\n};\n\ninterface Y2AxisOptions extends ChartOptions {\n y2Fields?: string | string[];\n}\n\n/**\n * Helper method to process options related to y2Fields\n * @method convertY2AxisOptions\n * @param {Object} originalOptions\n * @returns {Object}\n */\nexport const convertY2AxisOptions = ({\n y2Fields,\n ...originalOptions\n}: Y2AxisOptions): Record<string, any> => {\n const convertedOptions: Record<string, any> = {\n ...originalOptions,\n };\n if (y2Fields) {\n convertedOptions['axisY2.enabled'] = true;\n convertedOptions['axisY2.fields'] = isArray(y2Fields) ? y2Fields.filter(Boolean).join(',') : y2Fields;\n }\n return convertedOptions;\n};\n\n/**\n * Helper method to format value for overlayFields\n * @method convertOverlayFields\n * @param {Object} originalOptions\n * @returns {Object}\n */\nexport const convertOverlayFields = (originalOptions: ChartOptions): ChartOptions => {\n const convertedOptions: ChartOptions = {\n ...originalOptions,\n };\n const { overlayFields } = originalOptions;\n if (overlayFields) {\n convertedOptions.overlayFields = Array.isArray(overlayFields)\n ? overlayFields\n .filter(Boolean)\n .map(field => field.trim())\n .join(',')\n : overlayFields;\n }\n return convertedOptions;\n};\n\n/**\n * checks whether data is multi series data\n * @param {array} data array\n * @return {Boolean}\n */\nexport const isMultiSeriesData = (data: string[] | string[][]): boolean =>\n Array.isArray(data) && Array.isArray(data[0]);\n/**\n * checks whether data is multi series data and returns value as array\n * @param {array} data array\n * @param {*} value to return as array\n * @return {array}\n */\nexport const toArrayForSeries = (data, value): any[] => {\n if (isMultiSeriesData(data)) {\n return Array.isArray(value) ? value : [value];\n }\n return [value];\n};\ninterface ConstructFieldsAndColumnsParams {\n x: string[];\n y: string[] | string[][];\n xField: string;\n yFields: string | string[];\n y2?: string[] | string[][];\n y2Fields?: string | string[];\n}\nexport const constructFieldsAndColumns = ({\n x = [],\n y = [],\n xField,\n yFields,\n y2,\n y2Fields,\n}: ConstructFieldsAndColumnsParams): JsonColumnData => {\n const columns = [x.map(String), ...toArrayForSeries(y, y).map(series => series.map(String))];\n const yFieldsArray = toArrayForSeries(y, yFields);\n const fields = [{ name: xField }, ...yFieldsArray.map(field => ({ name: field }))];\n // splunk-charting requires y2 to be part of columns\n // when y & y2 options are configured with different (mutually exclusive) series\n // y2 columns need to be added to columns\n if (y2Fields) {\n const y2FieldsArray = toArrayForSeries(y2, y2Fields);\n const y2AsArray = toArrayForSeries(y2, y2).map(series => series?.map(String));\n y2FieldsArray.forEach((y2Field, index) => {\n if (!yFieldsArray.includes(y2Field) && y2AsArray[index]) {\n fields.push({\n name: y2Field,\n });\n columns.push(y2AsArray[index]);\n }\n });\n }\n return {\n columns,\n fields,\n };\n};\n\nexport function constructAdditionalTooltipFieldsMap({ fields, columns, additionalTooltipFields }) {\n const map = {};\n\n additionalTooltipFields?.forEach(fieldName => {\n const index = fields.findIndex(f => f.name === fieldName);\n if (index !== -1) {\n map[fieldName] = columns[index];\n }\n });\n\n return map;\n}\n\n/**\n * Extracts additional tooltip values from columns and fields into an array of objects.\n * Each object in the array represents the values at a specific data point index.\n * This follows the same pattern used by Timeline visualization.\n *\n * @param columns - Array of column data\n * @param fields - Array of field definitions with name property\n * @param additionalTooltipFields - Array of field names to extract\n * @returns Array of objects, where each object maps field names to values at that index\n */\n// Type alias for a single tooltip field value record\ntype TooltipFieldRecord = Record<string, string | number | null>;\n\nexport function extractAdditionalTooltipValues(\n columns: (string | number | null)[][],\n fields: { name: string }[],\n additionalTooltipFields: string[]\n): TooltipFieldRecord[] {\n if (!additionalTooltipFields?.length || !columns?.length || !fields?.length) {\n return [];\n }\n\n // Create a mapping of field names to their column indices\n const fieldIndexMap = fields.reduce<Record<string, number>>((acc, field, index) => {\n acc[field.name] = index;\n return acc;\n }, {});\n\n const numRows = columns[0]?.length || 0;\n const additionalTooltipValuesArray: TooltipFieldRecord[] = [];\n\n for (let i = 0; i < numRows; i += 1) {\n const tooltipObject: TooltipFieldRecord = {};\n\n additionalTooltipFields.forEach(fieldName => {\n if (fieldName in fieldIndexMap) {\n const columnIndex = fieldIndexMap[fieldName];\n tooltipObject[fieldName] = columns[columnIndex]?.[i] ?? null;\n } else {\n tooltipObject[fieldName] = null;\n }\n });\n\n additionalTooltipValuesArray.push(tooltipObject);\n }\n\n return additionalTooltipValuesArray;\n}\n\nexport type AdditionalTooltipResult = TooltipFieldRecord[];\n\ntype AdditionalTooltipValuesCache = {\n columns: unknown;\n fields: unknown;\n additionalTooltipFields: string[] | undefined;\n result: AdditionalTooltipResult | undefined;\n};\n\nexport const areStringArraysEqual = (a: string[] | undefined, b: string[] | undefined): boolean => {\n if (a === b) return true;\n if (!a || !b) return false;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i += 1) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n};\n\nexport const createAdditionalTooltipValuesMemoizer = () => {\n let cache: AdditionalTooltipValuesCache = {\n columns: null,\n fields: null,\n additionalTooltipFields: undefined,\n result: undefined,\n };\n\n return (\n columns: (string | number | null)[][],\n fields: { name: string }[],\n additionalTooltipFields: string[] | undefined\n ): AdditionalTooltipResult | undefined => {\n if (\n cache.columns === columns &&\n cache.fields === fields &&\n areStringArraysEqual(cache.additionalTooltipFields, additionalTooltipFields)\n ) {\n return cache.result;\n }\n\n let result: AdditionalTooltipResult | undefined;\n if (additionalTooltipFields?.length && columns && fields) {\n result = extractAdditionalTooltipValues(columns, fields, additionalTooltipFields);\n }\n\n cache = {\n columns,\n fields,\n additionalTooltipFields,\n result,\n };\n\n return result;\n };\n};\n\n// Note: we are making the assumption that attaching a range.select listener means the user wants to enable search zoom\n// This is because we don't know if the time range tokens being updated by the drilldown is used by the current viz.\n// In the future we are considering using a shared context to pass this information from UDF to Viz.\ninterface OptionsProps {\n events?: string[];\n selectedItemId?: string;\n [key: string]: unknown;\n}\ninterface EventHandler {\n type: string;\n options: OptionsProps;\n}\n\nexport const shouldEnableSearchZoom = (eventHandlers: EventHandler[] = [], xField = '') => {\n const rangeSelectEventHandler = eventHandlers.find(eventHandler =>\n eventHandler.options.events?.includes('range.select')\n );\n // Check if xField is _time. This is how splunk-charting distinguishes a time chart from categorical.\n // Note: search zoom will be buggy if the x axis uses timestamp values but is not _time\n const xAxisIsTime = xField === '_time';\n\n return !!rangeSelectEventHandler && xAxisIsTime;\n};\n\nconst canvasSupportedTimeSeriesCharts = new Set(['splunk.line', 'splunk.area']);\nexport const isTimeSeriesCanvasRenderSupported = (vizConfigKey: string): boolean => {\n return canvasSupportedTimeSeriesCharts.has(vizConfigKey);\n};\n\ntype ChartData = {\n fields: (string | { name: string })[];\n columns: (string | number)[][];\n};\n\n// Filter all internal fields and columns except for _time fild\nexport const filterChartDataFromInternalFields = (chartData: ChartData): ChartData => {\n const { fields, columns } = chartData;\n\n // Determine the indexes to keep\n const keepIndexes = fields.reduce<number[]>((acc, field, index) => {\n const fieldName = typeof field === 'object' ? field?.name : field;\n if (!fieldName?.startsWith('_') || fieldName === '_time') {\n acc.push(index);\n }\n return acc;\n }, []);\n\n // Filter fields and columns\n const filteredFields = keepIndexes.map(index => fields[index]);\n const filteredColumns = keepIndexes.map(index => columns[index]);\n\n return { fields: filteredFields, columns: filteredColumns };\n};\n\nexport const isTimeField = (field): boolean => {\n return (\n (typeof field === 'object' && field?.name === '_time') ||\n (typeof field === 'string' && field === '_time')\n );\n};\n\nexport const convert2DArrayToNumbers = arr => {\n return arr.map(subArray => subArray.map(element => Number.parseFloat(element)));\n};\n\nexport const convertTimeStringToUnix = arr => {\n return arr.map(timeStr => Number.parseInt((new Date(timeStr).getTime() / 1000).toFixed(0), 10));\n};\n\n/**\n * Parses an axis value that may be 'auto', null, undefined, empty string, or a numeric value.\n * Returns undefined for non-numeric values, allowing the renderer to auto-calculate the range.\n * @param {any} val - The value to parse (string, number, null, undefined)\n * @returns {number | undefined} - Parsed number or undefined\n */\nexport const parseAxisValue = (val: any): number | undefined => {\n if (val === undefined || val === null || val === 'auto' || val === '') {\n return undefined;\n }\n const num = typeof val === 'number' ? val : Number.parseFloat(val);\n return Number.isNaN(num) ? undefined : num;\n};\n\n/**\n * Parses X-axis line visibility option from string to boolean or undefined.\n * @param {string | undefined} visibility - The visibility option ('hide', 'show', or other)\n * @returns {boolean | undefined} - false for 'hide', true for 'show', undefined otherwise\n */\nexport const parseXAxisLineVisibility = (visibility?: string): boolean | undefined => {\n if (visibility === 'hide') return false;\n if (visibility === 'show') return true;\n return undefined;\n};\n\n// Legend placement logic for canvas render, used in TimeseriesChartWrapper\nexport const getLegend = (props: {\n legendDisplay: string;\n isSeriesCompare: boolean;\n legendTruncation?: LegendTruncation;\n}): Legend | false => {\n const legendPlacement = props?.legendDisplay;\n const { isSeriesCompare, legendTruncation } = props;\n const commonLegendProps = {\n center: true,\n fontSize: 12,\n largerTiles: true,\n hideSeriesValue: !isSeriesCompare, // Show values if in seriesCompare mode\n legendTruncation,\n };\n\n // \"right\" | \"left\" | \"top\" | \"bottom\" | \"off\"\n switch (legendPlacement) {\n case 'off':\n return false;\n case 'left':\n return LeftLegendFactory({\n ...commonLegendProps,\n });\n case 'bottom':\n return BottomLegendFactory({\n wrap: true,\n ...commonLegendProps,\n });\n case 'top':\n return TopLegendFactory({\n wrap: true,\n ...commonLegendProps,\n });\n // Note: By default, use right legend\n default:\n return SideLegendFactory({\n ...commonLegendProps,\n });\n }\n};\n\nexport const getComputedAxisTitles = (\n inputAxisTitle: string,\n fields: string[],\n axisTitleVisibility: 'show' | 'collapsed'\n): string => {\n if (axisTitleVisibility === 'collapsed') {\n return '';\n }\n let fieldTitle = fields.length > 1 ? '' : fields[0]; // If more than one series (multi-series) default empty title\n if (!fieldTitle) {\n fieldTitle = '';\n }\n return inputAxisTitle?.length ? inputAxisTitle.trim() : fieldTitle;\n};\n\n/**\n * Truncates Y-axis title based on available container height and font metrics\n * @param axisTitle - The title text to potentially truncate\n * @param containerSpacing - Available height/ width in pixels depending on axis orientation\n * @param fontSize - Font size in pixels (default: 12)\n * @returns Truncated title with ellipsis if needed\n */\nexport const ellipsisAxisTitle = (axisTitle: string, containerSpacing: number, fontSize = 12): string => {\n if (!axisTitle) {\n return '';\n }\n if (Number.isNaN(containerSpacing) || containerSpacing <= 0) {\n return axisTitle;\n }\n // Calculate available height for text (leave 40% margin)\n const availableHeight = containerSpacing * 0.6;\n\n // Use a generic character width ratio that works across most fonts\n // 0.55 is a reasonable average for most fonts\n const avgCharWidth = fontSize * 0.55;\n\n // Calculate maximum characters that fit in available height\n const maxChars = Math.floor(availableHeight / avgCharWidth);\n\n // If title fits, return as-is\n if (axisTitle.length <= maxChars) {\n return axisTitle;\n }\n\n // Need to truncate - use middle ellipsis for better context\n if (maxChars <= 3) {\n return '...'; // Not enough space for meaningful text\n }\n\n // Reserve 3 characters for ellipsis\n const availableChars = maxChars - 3;\n const halfChars = Math.floor(availableChars / 2);\n\n // Create truncated title with middle ellipsis\n const start = axisTitle.slice(0, halfChars);\n const end = axisTitle.slice(-halfChars);\n\n return `${start}...${end}`;\n};\n\nexport type FieldObject = {\n name: string;\n};\n\nexport const getFieldName = (field: string | FieldObject): string => {\n const fieldName = typeof field === 'object' ? field?.name : field;\n return fieldName;\n};\n\nexport const getFieldNames = (fields: (string | FieldObject)[]): string[] => {\n return fields.map(field => getFieldName(field));\n};\n\n/**\n * Type alias for axis label visibility options\n */\nexport type AxisLabelVisibility = 'hide' | 'show' | 'auto';\n\n/**\n * Returns X scale config for viz-canvas charts\n * @param label\n * @param xAxisLabelVisibility\n * @returns\n */\nexport const getXScaleConfig = (\n label: string,\n xAxisLabelVisibility?: AxisLabelVisibility,\n xAxisLabelRotation?: -90 | -45 | 0 | 45 | 90\n): ScaleConfig => {\n const xConfig: ScaleConfig = { x: {} };\n xConfig.x.label = label;\n // Set hideLabels to true when xAxisLabelVisibility is \"hide\"\n if (xAxisLabelVisibility === 'hide') {\n xConfig.x.hideLabels = true;\n }\n // Set labelRotation if provided\n if (xAxisLabelRotation !== undefined) {\n xConfig.x.labelRotation = xAxisLabelRotation;\n }\n return xConfig;\n};\n\n/**\n * Returns Y scale config for viz-canvas charts\n * @param label\n * @param yAxisAbbreviation\n * @param yAxisScale\n * @param yAxisLabelVisibility\n * @param yAxisMin\n * @param yAxisMax\n * @returns\n */\nexport const getYScaleConfig = (\n label: string,\n yAxisAbbreviation: string,\n yAxisScale?: 'linear' | 'log',\n yAxisLabelVisibility?: AxisLabelVisibility,\n yAxisMin?: number,\n yAxisMax?: number\n): ScaleConfig => {\n const scaleType = yAxisScale ?? 'linear';\n const yConfig: ScaleConfig = { y: {} };\n yConfig.y.label = label;\n yConfig.y.type = scaleType;\n if (yAxisAbbreviation !== 'none') {\n yConfig.y.tickFmt = (v): string => shortenNumber(v, 1);\n }\n // Only set fixed width when abbreviation is ON\n // When abbreviation is OFF, width remains undefined to allow dynamic sizing in uplot-utils\n // based on actual data label lengths\n if (yAxisAbbreviation !== 'none') {\n yConfig.y.width = label && label.length > 0 ? 30 : 10;\n }\n if (yAxisLabelVisibility === 'hide') {\n yConfig.y.hideLabels = true;\n }\n if (yAxisMin !== undefined || yAxisMax !== undefined) {\n yConfig.y.range = (u, dataMin, dataMax) => {\n const min = yAxisMin ?? dataMin;\n const max = yAxisMax ?? dataMax;\n return [min, max];\n };\n }\n return yConfig;\n};\n/**\n * Returns Y2 scale config for viz-canvas charts\n * @param label\n * @param axisAbbreviation\n * @param axisScale\n * @param roundAxisLabelsToInteger\n * @param y2AxisLabelVisibility\n * @param y2AxisMin\n * @param y2AxisMax\n * @returns\n */\nexport const getY2ScaleConfig = (\n label: string,\n axisAbbreviation: string,\n axisScale?: 'linear' | 'log',\n roundAxisLabelsToInteger?: boolean,\n y2AxisLabelVisibility?: AxisLabelVisibility,\n y2AxisMin?: number,\n y2AxisMax?: number\n): ScaleConfig => {\n const y2Config: ScaleConfig = { y2: {} };\n const scaleType = axisScale ?? 'linear';\n y2Config.y2.label = label;\n y2Config.y2.side = 'right';\n // Note: showGrid is intentionally not set here so that the top-level\n // showY2MajorGridLines prop can control it (defaults to false)\n y2Config.y2.type = scaleType;\n if (axisAbbreviation !== 'none') {\n y2Config.y2.tickFmt = (v): string => shortenNumber(v, 1, roundAxisLabelsToInteger);\n // Set width for abbreviated Y2 axis\n // Y2 needs more width (50px) than Y-axis (30px) because of rotated title positioning\n // Width will be used to detect abbreviation setting in padding calculations\n y2Config.y2.width = label && label.length > 0 ? 50 : 10;\n } else if (roundAxisLabelsToInteger) {\n y2Config.y2.tickFmt = (v): string =>\n roundAxisLabelsToInteger ? Math.round(v).toString() : v.toString();\n }\n if (y2AxisLabelVisibility === 'hide') {\n y2Config.y2.hideLabels = true;\n }\n if (y2AxisMin !== undefined || y2AxisMax !== undefined) {\n y2Config.y2.range = (u, dataMin, dataMax) => {\n const min = y2AxisMin ?? dataMin;\n const max = y2AxisMax ?? dataMax;\n return [min, max];\n };\n }\n return y2Config;\n};\n\n/**\n * Add series overrides for viz-canvas charts (for eg:- line width)\n */\nconst getSeriesType = (\n isOverlay: boolean,\n isAreaChart: boolean,\n isStacked: boolean\n): SeriesConfig[string]['type'] | undefined => {\n if (isOverlay) return 'line';\n if (!isAreaChart) return undefined;\n return isStacked ? 'stacked-area' : 'area';\n};\n\nconst getY2Scale = (\n field: string,\n y2fields: string[] | undefined,\n overlayFields: string[] | undefined\n): 'y' | 'y2' => {\n const assignToY2 =\n (y2fields?.length > 0 && y2fields.includes(field)) ||\n (!y2fields?.length && overlayFields?.includes(field));\n return assignToY2 ? 'y2' : 'y';\n};\n\nexport const getSeriesOverrides = (opts: {\n yfields: string[];\n y2fields?: string[];\n lineWidth?: number;\n overlayFields?: string[];\n y2Enabled?: boolean;\n nullValueMode?: 'gaps' | 'connect' | 'zero';\n markerDisplay?: 'off' | 'filled' | 'outlined';\n lineDashStyle?: string;\n lineDashStylesByField?: Record<string, string>;\n stepPosition?: 'off' | 'before' | 'after';\n stepPositionsByField?: Record<string, 'off' | 'before' | 'after'>;\n type?: 'line' | 'area';\n stackMode?: 'auto' | 'stacked' | 'stacked100';\n showLines?: boolean;\n}): SeriesConfig => {\n const {\n yfields,\n y2fields,\n lineWidth,\n overlayFields,\n y2Enabled,\n nullValueMode,\n markerDisplay,\n lineDashStyle,\n lineDashStylesByField,\n stepPosition,\n stepPositionsByField,\n type,\n stackMode,\n showLines,\n } = opts;\n const seriesConfig: SeriesConfig = {};\n\n let spanGaps: boolean | undefined;\n if (nullValueMode === 'gaps') {\n spanGaps = false;\n } else if (nullValueMode == null) {\n spanGaps = undefined;\n } else {\n spanGaps = true;\n }\n const replaceNullsWithZero = nullValueMode === 'zero' ? true : undefined;\n\n const isAreaChart = type === 'area';\n const isStacked = isAreaChart && (stackMode === 'stacked' || stackMode === 'stacked100');\n\n // Non-overlay area fields first, then overlay fields - so overlays render on top\n const areaFields = isAreaChart ? yfields.filter(f => !overlayFields?.includes(f)) : yfields;\n const overlayFieldsInOrder = overlayFields?.filter(f => yfields.includes(f)) ?? [];\n const orderedFields = isAreaChart ? [...areaFields, ...overlayFieldsInOrder] : yfields;\n\n orderedFields.forEach(field => {\n const isOverlay = overlayFields?.includes(field) ?? false;\n const isPercent = isAreaChart && stackMode === 'stacked100' && !isOverlay;\n const shouldHideAreaOutline = isAreaChart && showLines === false && !isOverlay;\n\n seriesConfig[field] = {\n overrides: {\n width: shouldHideAreaOutline ? 0 : (lineWidth ?? DEFAULT_LINE_WIDTH),\n ...(isPercent ? ({ stacking: { mode: 'percent', group: 'A' } } as object) : {}),\n } as SeriesConfig[string]['overrides'],\n };\n\n const seriesType = getSeriesType(isOverlay, isAreaChart, isStacked);\n if (seriesType !== undefined) seriesConfig[field].type = seriesType;\n\n if (spanGaps !== undefined) seriesConfig[field].overrides.spanGaps = spanGaps;\n\n if (y2Enabled) seriesConfig[field].overrides.scale = getY2Scale(field, y2fields, overlayFields);\n\n if (markerDisplay !== undefined) seriesConfig[field].markerDisplay = markerDisplay;\n\n if (!isAreaChart || isOverlay) {\n const fieldDashStyle = lineDashStylesByField?.[field] || lineDashStyle;\n if (fieldDashStyle) seriesConfig[field].lineDashStyle = fieldDashStyle as any;\n }\n\n const hasFieldStepPosition = Object.hasOwn(stepPositionsByField || {}, field);\n const fieldStepPosition = hasFieldStepPosition ? stepPositionsByField?.[field] : stepPosition;\n if (fieldStepPosition && fieldStepPosition !== 'off') {\n (seriesConfig[field] as SeriesConfig[string] & { stepPosition?: string }).stepPosition =\n fieldStepPosition;\n }\n\n if (replaceNullsWithZero !== undefined) {\n (\n seriesConfig[field] as SeriesConfig[string] & { replaceNullsWithZero?: boolean }\n ).replaceNullsWithZero = replaceNullsWithZero;\n }\n });\n\n return seriesConfig;\n};\n\n/**\n * Finds the start and end indices in time series data for a given range.\n * @param xData - Array of time values (can be ISO strings or epoch timestamps)\n * @param startValue - Start value of the range (epoch timestamp)\n * @param endValue - End value of the range (epoch timestamp)\n * @returns Object with startXIndex (first index where time >= startValue) and endXIndex (last index where time <= endValue)\n */\nexport const findRangeIndices = (\n xData: (string | number)[],\n startValue: number,\n endValue: number\n): { startXIndex: number; endXIndex: number } => {\n let startXIndex = -1;\n let endXIndex = -1;\n\n // Convert xData to epoch timestamps if they are ISO strings\n const xDataEpoch = xData.map(val => {\n if (typeof val === 'string') {\n return new Date(val).getTime() / 1000; // Convert to epoch seconds\n }\n return val;\n });\n\n // Find the closest time value >= startValue\n for (let i = 0; i < xDataEpoch.length; i += 1) {\n if (xDataEpoch[i] >= startValue) {\n startXIndex = i;\n break;\n }\n }\n\n // If no value >= startValue found, use the last index (all values are less)\n if (startXIndex === -1 && xDataEpoch.length > 0) {\n startXIndex = xDataEpoch.length - 1;\n }\n\n // Find the closest time value <= endValue\n for (let i = xDataEpoch.length - 1; i >= 0; i -= 1) {\n if (xDataEpoch[i] <= endValue) {\n endXIndex = i;\n break;\n }\n }\n\n // If no value <= endValue found, use the first index (all values are greater)\n if (endXIndex === -1 && xDataEpoch.length > 0) {\n endXIndex = 0;\n }\n\n return { startXIndex, endXIndex };\n};\n", "import { useContext } from 'react';\nimport FeatureFlagContext from '@splunk/visualization-context/FeatureFlagContext';\nimport { LAYOUT_TYPE } from '@splunk/visualization-schemas';\n\nexport const useTrellisFeatureFlagOn = (): boolean => {\n const context = useContext(FeatureFlagContext) as Record<string, unknown>;\n return Boolean(context?.visualizations_enableTrellis);\n};\n\nexport const useTrellisEnabled = (layoutType = LAYOUT_TYPE.Off): boolean => {\n const trellisFeatureEnabled = useTrellisFeatureFlagOn();\n return trellisFeatureEnabled && layoutType === LAYOUT_TYPE.Trellis;\n};\n", "import * as React from 'react';\nimport styled from 'styled-components';\n\nexport const TRELLIS_TITLE_HEIGHT = 28;\n\nconst TrellisTitleText = styled.div`\n margin-left: 10px;\n margin-right: 10px;\n padding-top: 8px;\n text-overflow: ellipsis;\n white-space: nowrap;\n overflow: hidden;\n`;\n\nconst TrellisTitleDiv = styled.div<{\n fontColor: string;\n backgroundColor: string;\n}>`\n height: ${TRELLIS_TITLE_HEIGHT}px;\n font-size: 14px;\n font-weight: 700;\n color: ${props => props.fontColor};\n background-color: ${props => props.backgroundColor};\n box-shadow: 0 1px ${props => props.backgroundColor}; // this is added to avoid a 1px gap between title and viz divs that showed up intermittently because of pixel rounding error in chrome.\n`;\n\ninterface TrellisTitleProps {\n fontColor: string;\n backgroundColor: string;\n trellisKey: unknown;\n}\n\nconst formatTrellisKey = (value: TrellisTitleProps['trellisKey']): string => {\n if (value === null || value === undefined) {\n return '';\n }\n if (typeof value === 'string') {\n return value;\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return value.toString();\n }\n if (typeof value === 'symbol') {\n return value.toString();\n }\n try {\n return JSON.stringify(value);\n } catch {\n // JSON.stringify throws for BigInt and circular references\n return typeof value === 'bigint' ? value.toString() : '';\n }\n};\n\nexport const TrellisTitle = (props: TrellisTitleProps) => {\n const titleText = formatTrellisKey(props.trellisKey);\n return (\n <TrellisTitleDiv\n fontColor={props.fontColor}\n backgroundColor={props.backgroundColor}\n data-test=\"trellis-title\"\n title={titleText}\n >\n <TrellisTitleText>{titleText}</TrellisTitleText>\n </TrellisTitleDiv>\n );\n};\n", "import * as React from 'react';\nimport { useMemo, useRef } from 'react';\nimport { pick } from 'lodash';\nimport styled from 'styled-components';\nimport SizeAwareWrapper from '@splunk/visualizations-shared/SizeAwareWrapper';\nimport { TimeSeriesChart, RangeSelectionProvider } from '@splunk/visualization-canvas';\nimport { toDimension } from '@splunk/visualizations-shared/style';\nimport type { GenericDataSet } from '@splunk/visualization-canvas/types/types';\nimport VizStyleWrapper from './components/VizStyleWrapper';\nimport { ChartingProps } from './Charting';\nimport {\n convert2DArrayToNumbers,\n filterChartDataFromInternalFields,\n getComputedAxisTitles,\n getFieldName,\n getFieldNames,\n getLegend,\n getSeriesOverrides,\n getXScaleConfig,\n getYScaleConfig,\n getY2ScaleConfig,\n ellipsisAxisTitle,\n getAnnotationsForCanvas,\n triangleEventAnnotationRenderer,\n parseAxisValue,\n parseXAxisLineVisibility,\n findRangeIndices,\n shouldEnableSearchZoom,\n} from './chartingUtils';\nimport { useTrellisEnabled } from './hooks/useTrellisEnabled';\nimport { TrellisTitle, TRELLIS_TITLE_HEIGHT } from './components/TrellisTitle';\n\nconst TimeSeriesChartContainer = styled.div<{\n width: number | string;\n height: number | string;\n}>`\n overflow: hidden;\n ${props => toDimension(pick(props, ['width', 'height']))};\n\n canvas {\n position: absolute !important; // This is needed for canvas element export pdf/png to work correctly\n }\n`;\n\n/**\n * Adds trellis information to event payload\n * @param payload - The event payload object to modify\n * @param trellisKey - The current trellis key value (e.g., \"200\", \"404\")\n * @param trellisSplitBy - The field name being split by (e.g., \"status\")\n */\nexport const appendTrellisToPayload = (\n payload: Record<string, unknown>,\n trellisKey?: string,\n trellisSplitBy?: string\n): Record<string, unknown> => {\n const result = { ...payload };\n if (trellisSplitBy) {\n result['trellis.name'] = trellisSplitBy;\n }\n if (trellisKey) {\n result['trellis.value'] = trellisKey;\n }\n return result;\n};\n\n/**\n * Checks if the mouseover payload has changed compared to the previous payload\n * @param currentPayload - The current event payload\n * @param previousPayload - The previous event payload\n * @returns true if the payload has changed, false otherwise\n */\nexport const hasMouseoverPayloadChanged = (\n currentPayload: Record<string, unknown>,\n previousPayload: Record<string, unknown> | null\n): boolean => {\n if (!previousPayload) {\n return true;\n }\n\n // Check if data point index changed - this is the primary indicator of hovering a different point\n if (currentPayload.index !== previousPayload.index) {\n return true;\n }\n\n // Check if seriesIndex changed\n if (currentPayload.seriesIndex !== previousPayload.seriesIndex) {\n return true;\n }\n\n // Check if trellis fields changed (for trellis mode)\n if (currentPayload['trellis.name'] !== previousPayload['trellis.name']) {\n return true;\n }\n if (currentPayload['trellis.value'] !== previousPayload['trellis.value']) {\n return true;\n }\n\n return false;\n};\n\nexport const handleClick = (chartEvent, onClick, trellisKey?: string, trellisSplitBy?: string) => {\n const payload = {\n ...pick(chartEvent, 'value', 'seriesKey'),\n name: chartEvent.seriesKey,\n };\n delete payload.seriesKey;\n\n // Add row context fields in the format: row.${fieldName}.value\n if (chartEvent.rowContext) {\n Object.assign(\n payload,\n Object.keys(chartEvent.rowContext).reduce((acc, fieldName) => {\n acc[`row.${fieldName}.value`] = chartEvent.rowContext[fieldName];\n return acc;\n }, {})\n );\n }\n\n const updatedPayload = appendTrellisToPayload(payload, trellisKey, trellisSplitBy);\n\n if (onClick) {\n onClick({\n type: 'point.click',\n originalEvent: chartEvent,\n payload: updatedPayload,\n });\n }\n};\n\nexport const handleLegendClick = (chartEvent, onClick, trellisKey?: string, trellisSplitBy?: string) => {\n const payload = {\n name: chartEvent,\n };\n\n const updatedPayload = appendTrellisToPayload(payload, trellisKey, trellisSplitBy);\n\n if (onClick) {\n onClick({\n type: 'legend.click',\n originalEvent: chartEvent,\n payload: updatedPayload,\n });\n }\n};\n\nexport const handleRangeSelection = (\n rangeEvent,\n onSelect,\n chartData,\n trellisKey?: string,\n trellisSplitBy?: string\n) => {\n // Handle undefined range (clearing selection)\n if (!rangeEvent) {\n return;\n }\n\n // Find the indices in the data array that correspond to the start and end timestamps\n const xData = chartData?.columns?.[0] || [];\n const { startXIndex, endXIndex } = findRangeIndices(xData, rangeEvent.start, rangeEvent.end);\n\n const payload = {\n startXIndex,\n startXValue: rangeEvent.start,\n endXIndex,\n endXValue: rangeEvent.end,\n };\n\n const updatedPayload = appendTrellisToPayload(payload, trellisKey, trellisSplitBy);\n\n if (onSelect) {\n onSelect({\n type: 'range.selectBeforeZoom',\n originalEvent: rangeEvent,\n payload: updatedPayload,\n });\n }\n};\n\nexport const handleRangeZoom = (\n rangeEvent,\n onSelect,\n chartData,\n trellisKey?: string,\n trellisSplitBy?: string\n) => {\n // Find the indices in the data array that correspond to the start and end timestamps\n const xData = chartData?.columns?.[0] || [];\n const { startXIndex, endXIndex } = findRangeIndices(xData, rangeEvent.start, rangeEvent.end);\n\n const payload = {\n startXIndex,\n startXValue: rangeEvent.start,\n endXIndex,\n endXValue: rangeEvent.end,\n };\n\n const updatedPayload = appendTrellisToPayload(payload, trellisKey, trellisSplitBy);\n\n if (onSelect) {\n onSelect({\n type: 'range.select',\n originalEvent: rangeEvent,\n payload: updatedPayload,\n });\n }\n};\n\nexport const handleCrosshairChange = (\n chartEvent,\n onPointMouseOver,\n onPointMouseOut,\n trellisKey?: string,\n trellisSplitBy?: string,\n lastPayload = null,\n lastOriginalEvent = null\n) => {\n // Handle mouseout when chartEvent is undefined\n if (!chartEvent) {\n if (onPointMouseOut && lastPayload) {\n onPointMouseOut({\n type: 'point.mouseout',\n originalEvent: lastOriginalEvent,\n payload: lastPayload,\n });\n }\n return { payload: null, originalEvent: null };\n }\n\n // Handle mouseover\n const payload = {\n ...pick(chartEvent, 'value', 'seriesKey', 'time', 'index', 'seriesIndex'),\n name: chartEvent.seriesKey,\n };\n delete payload.seriesKey;\n\n // Add row context fields in the format: row.${fieldName}.value\n if (chartEvent.rowContext) {\n Object.assign(\n payload,\n Object.keys(chartEvent.rowContext).reduce((acc, fieldName) => {\n acc[`row.${fieldName}.value`] = chartEvent.rowContext[fieldName];\n return acc;\n }, {})\n );\n }\n\n const updatedPayload = appendTrellisToPayload(payload, trellisKey, trellisSplitBy);\n\n if (onPointMouseOver) {\n onPointMouseOver({\n type: 'point.mouseover',\n originalEvent: chartEvent,\n payload: updatedPayload,\n });\n }\n\n // Return payload and originalEvent for caller to store\n return { payload: updatedPayload, originalEvent: chartEvent };\n};\n\n/**\n * Helper function to parse array options that may be stringified JSON or already arrays\n */\nexport const parseArrayOption = (\n value: string[] | string | undefined | null\n): string[] | undefined | null => {\n if (Array.isArray(value)) {\n return value;\n }\n if (value) {\n return JSON.parse(value);\n }\n return undefined;\n};\n\nconst getAreaOpacityForCanvas = (areaOpacity: number | undefined | null): number | undefined | null =>\n // Preserve legacy visualizations behavior where area opacity is squared to match charting output.\n areaOpacity !== undefined && areaOpacity !== null ? areaOpacity ** 2 : areaOpacity;\n\nconst parseTickIntervalOption = (\n simpleXMLValue?: string | number,\n canvasValue?: number\n): number | undefined => {\n if (simpleXMLValue) return Number(simpleXMLValue);\n if (canvasValue) return Number(canvasValue);\n return undefined;\n};\n\nconst getYAxisTitles = ({\n y2Enabled,\n yFields,\n y2Fields,\n overlayFields,\n yAxisTitleText,\n yAxisTitleVisibility,\n y2AxisTitleText,\n y2AxisTitleVisibility,\n containerHeight,\n}: {\n y2Enabled: boolean;\n yFields: string[];\n y2Fields: string[];\n overlayFields: string[];\n yAxisTitleText?: string;\n yAxisTitleVisibility?: 'show' | 'collapsed';\n y2AxisTitleText?: string;\n y2AxisTitleVisibility?: 'show' | 'collapsed';\n containerHeight: number;\n}) => {\n const yFieldsForTitle = y2Enabled ? yFields.filter(field => !y2Fields.includes(field)) : yFields;\n const fieldsForY2Axis = y2Fields.length > 0 ? y2Fields : overlayFields;\n\n const yAxisTitle = ellipsisAxisTitle(\n getComputedAxisTitles(yAxisTitleText, yFieldsForTitle, yAxisTitleVisibility),\n containerHeight\n );\n const y2AxisTitle = ellipsisAxisTitle(\n getComputedAxisTitles(y2AxisTitleText, fieldsForY2Axis, y2AxisTitleVisibility),\n containerHeight\n );\n\n return { yAxisTitle, y2AxisTitle };\n};\n\nconst TimeSeriesChartWrapper = (props: ChartingProps) => {\n const {\n width,\n height,\n chartData,\n options,\n userLocale,\n annotationX,\n annotationLabel,\n annotationColor,\n legendDisplay,\n markerDisplay,\n onClick,\n onPointMouseOver,\n onPointMouseOut,\n onSelect,\n splitByLayout,\n trellisKey,\n trellisSplitBy,\n backgroundColor,\n defaultFontColor,\n additionalTooltipValues,\n // Extract axis line visibility options from props\n xAxisLineVisibility,\n yAxisLineVisibility,\n y2AxisLineVisibility,\n // Extract showYAxisWithZero directly from props for accelerated render mode\n showYAxisWithZero: showYAxisWithZeroFromProps,\n showY2AxisWithZero: showY2AxisWithZeroFromProps,\n ...otherOptions\n } = props as ChartingProps & {\n showYAxisWithZero?: boolean;\n showY2AxisWithZero?: boolean;\n xAxisLineVisibility?: string;\n yAxisLineVisibility?: string;\n y2AxisLineVisibility?: string;\n };\n const { eventHandlers, xField: xFieldFromProps } = otherOptions;\n const trellisEnabled = useTrellisEnabled(splitByLayout);\n const {\n backgroundColor: bgColorFromOptions,\n seriesColors: seriesColorsStr,\n fieldColors,\n legendLabels: legendLabelsStr,\n legendMode,\n legendTruncation,\n 'axisTitleX.text': xAxisTitleText,\n 'axisTitleY.text': yAxisTitleText,\n 'axisTitleY2.text': y2AxisTitleText,\n 'axisTitleX.visibility': xAxisTitleVisibility,\n 'axisTitleY.visibility': yAxisTitleVisibility,\n 'axisTitleY2.visibility': y2AxisTitleVisibility,\n 'axisLabelsX.majorLabelVisibility': xAxisLabelVisibility,\n 'axisLabelsX.majorLabelStyle.rotation': xAxisLabelRotation,\n 'axisLabelsX.maxLabelParts': xAxisMaxLabelParts,\n 'axisLabelsY.majorLabelVisibility': yAxisLabelVisibility,\n 'axisLabelsY.majorUnit': yAxisMajorUnitFromSimpleXML,\n 'axisLabelsY2.majorLabelVisibility': y2AxisLabelVisibility,\n 'axisLabelsY2.majorUnit': y2AxisMajorUnitFromSimpleXML,\n 'axisY.abbreviation': yAxisAbbreviation,\n 'axisY.scale': yAxisScale,\n 'axisY2.abbreviation': y2AxisAbbreviation,\n 'axisY2.fields': y2FieldsStr,\n 'axisY2.scale': y2AxisScale,\n 'axisY2.enabled': y2Enabled,\n 'axisLabelsY2.integerUnits': y2IntegerUnits,\n 'chart.overlayFields': overlayFieldsStr,\n 'chart.nullValueMode': nullValueMode,\n 'chart.showDataLabels': showDataLabels,\n 'chart.showLines': showLines,\n 'chart.stackMode': stackMode,\n lineWidth,\n lineDashStyle,\n fieldDashStyles: lineDashStylesByFieldStr,\n stepPosition,\n fieldStepPositions: stepPositionsByFieldStr,\n yAxisMin: yAxisMinRaw,\n yAxisMax: yAxisMaxRaw,\n y2AxisMin: y2AxisMinRaw,\n y2AxisMax: y2AxisMaxRaw,\n showXMajorGridLines,\n showYMajorGridLines,\n showY2MajorGridLines,\n showYMinorGridLines,\n showY2MinorGridLines,\n showLineSmoothing,\n xAxisMajorTickVisibility,\n xAxisMajorTickSize,\n yAxisMajorTickVisibility,\n y2AxisMajorTickVisibility,\n yAxisMajorTickSize,\n y2AxisMajorTickSize,\n yAxisMajorTickInterval,\n y2AxisMajorTickInterval,\n yAxisMinorTickVisibility,\n y2AxisMinorTickVisibility,\n yAxisMinorTickSize,\n y2AxisMinorTickSize,\n showYAxisWithZero: showYAxisWithZeroFromOptions,\n showY2AxisWithZero: showY2AxisWithZeroFromOptions,\n // area only props\n areaFillOpacity: areaOpacity,\n chart: chartType,\n } = options;\n\n // Map showDataLabels back to dataValuesDisplay format for canvas mode\n const dataValuesDisplay = showDataLabels === 'none' ? 'off' : showDataLabels;\n\n // Get showYAxisWithZero from top-level props first (accelerated render mode),\n // then fall back to options object (non-accelerated render mode)\n const showYAxisWithZero = showYAxisWithZeroFromProps ?? showYAxisWithZeroFromOptions;\n const showY2AxisWithZero = showY2AxisWithZeroFromProps ?? showY2AxisWithZeroFromOptions;\n\n // Convert visibility to boolean for canvas renderer\n // X-axis ticks default to true (shown) when 'auto' or 'show', false when 'hide'\n const showXMajorTicks = xAxisMajorTickVisibility !== 'hide';\n const showYMajorTicks = yAxisMajorTickVisibility === 'show';\n const showY2MajorTicks = y2AxisMajorTickVisibility === 'show';\n const showYMinorTicks = yAxisMinorTickVisibility === 'show';\n const showY2MinorTicks = y2AxisMinorTickVisibility === 'show';\n // X-axis line defaults to true (shown) for backwards compatibility\n const showXAxisLine = parseXAxisLineVisibility(xAxisLineVisibility);\n const showYAxisLine = yAxisLineVisibility === 'show';\n const showY2AxisLine = y2AxisLineVisibility === 'show';\n\n // Parse axis values - convert strings to numbers\n const yAxisMin = parseAxisValue(yAxisMinRaw);\n const yAxisMax = parseAxisValue(yAxisMaxRaw);\n const y2AxisMin = parseAxisValue(y2AxisMinRaw);\n const y2AxisMax = parseAxisValue(y2AxisMaxRaw);\n\n // Parse tick interval and size values - convert strings to numbers\n // Priority: SimpleXML props (from transformed options) > canvas-specific props\n const yAxisMajorTickIntervalNum = parseTickIntervalOption(\n yAxisMajorUnitFromSimpleXML,\n yAxisMajorTickInterval\n );\n const y2AxisMajorTickIntervalNum = parseTickIntervalOption(\n y2AxisMajorUnitFromSimpleXML,\n y2AxisMajorTickInterval\n );\n const xAxisMajorTickSizeNum = xAxisMajorTickSize == null ? undefined : Number(xAxisMajorTickSize);\n const yAxisMajorTickSizeNum = yAxisMajorTickSize == null ? undefined : Number(yAxisMajorTickSize);\n const y2AxisMajorTickSizeNum = y2AxisMajorTickSize == null ? undefined : Number(y2AxisMajorTickSize);\n const yAxisMinorTickSizeNum = yAxisMinorTickSize == null ? undefined : Number(yAxisMinorTickSize);\n const y2AxisMinorTickSizeNum = y2AxisMinorTickSize == null ? undefined : Number(y2AxisMinorTickSize);\n // Preserve legacy visualizations behavior where area opacity is squared to match charting output.\n const areaOpacityForCanvas = getAreaOpacityForCanvas(areaOpacity);\n const seriesColors = seriesColorsStr ? JSON.parse(seriesColorsStr) : undefined;\n const seriesColorsByField = fieldColors ? JSON.parse(fieldColors) : undefined;\n const lineDashStylesByField = lineDashStylesByFieldStr ? JSON.parse(lineDashStylesByFieldStr) : undefined;\n const stepPositionsByField = stepPositionsByFieldStr ? JSON.parse(stepPositionsByFieldStr) : undefined;\n const legendLabels = parseArrayOption(legendLabelsStr);\n const bgColor = backgroundColor || bgColorFromOptions;\n const [containerWidth, setContainerWidth] = React.useState(Number(props.width));\n const [containerHeight, setContainerHeight] = React.useState(Number(props.height));\n const cachedHandleResize = React.useCallback((w, h) => {\n setContainerWidth(w);\n setContainerHeight(h);\n }, []);\n const filteredChartData = filterChartDataFromInternalFields({\n fields: chartData.fields,\n columns: chartData.seriesList,\n });\n\n const xField = getFieldName(filteredChartData.fields[0]);\n const yFields = getFieldNames(\n filteredChartData.fields.length > 1 ? filteredChartData.fields.slice(1) : []\n );\n const y2Fields = useMemo(\n () => (y2FieldsStr ? y2FieldsStr.split(',').map(f => f.trim()) : []),\n [y2FieldsStr]\n );\n const overlayFields = useMemo(\n () => (overlayFieldsStr ? overlayFieldsStr.split(',').map(f => f.trim()) : []),\n [overlayFieldsStr]\n );\n\n let xAxisTitle = getComputedAxisTitles(xAxisTitleText, [xField], xAxisTitleVisibility);\n xAxisTitle = ellipsisAxisTitle(xAxisTitle, containerWidth);\n const { yAxisTitle, y2AxisTitle } = getYAxisTitles({\n y2Enabled,\n yFields,\n y2Fields,\n overlayFields,\n yAxisTitleText,\n yAxisTitleVisibility,\n y2AxisTitleText,\n y2AxisTitleVisibility,\n containerHeight,\n });\n\n const xScaleConfig = useMemo(\n () => getXScaleConfig(xAxisTitle, xAxisLabelVisibility, xAxisLabelRotation),\n [xAxisTitle, xAxisLabelVisibility, xAxisLabelRotation]\n );\n const isStacked100 = stackMode === 'stacked100';\n const yScaleConfig = useMemo(\n () => {\n const config = getYScaleConfig(\n yAxisTitle,\n yAxisAbbreviation,\n yAxisScale,\n yAxisLabelVisibility,\n yAxisMin,\n yAxisMax\n );\n // For stacked100, override tick formatter to show percentage labels (0-100%)\n // uPlot stores stacked100 values as 0-1 fractions after processPercentStacking\n if (isStacked100) {\n config.y.tickFmt = (v): string => `${Math.round(v * 100)}%`;\n config.y.range = () => [0, 1];\n }\n return config;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [yAxisTitle, yAxisAbbreviation, yAxisScale, yAxisLabelVisibility, yAxisMin, yAxisMax, isStacked100]\n );\n const y2ScaleConfig = useMemo(() => {\n if (y2Enabled) {\n return getY2ScaleConfig(\n y2AxisTitle,\n y2AxisAbbreviation,\n y2AxisScale,\n y2IntegerUnits,\n y2AxisLabelVisibility,\n y2AxisMin,\n y2AxisMax\n );\n }\n return {};\n }, [\n y2Enabled,\n y2AxisTitle,\n y2AxisAbbreviation,\n y2AxisScale,\n y2IntegerUnits,\n y2AxisLabelVisibility,\n y2AxisMin,\n y2AxisMax,\n ]);\n const uplotContainerElement = useRef(null);\n\n const seriesDataFormatted = [\n filteredChartData.columns[0],\n ...convert2DArrayToNumbers(filteredChartData.columns.slice(1)),\n ];\n chartData.fields = filteredChartData.fields;\n chartData.columns = seriesDataFormatted;\n\n // Map SimpleXML stackMode value ('default' | 'stacked' | 'stacked100') to getSeriesOverrides param\n const normalizedStackMode = stackMode === 'stacked' || stackMode === 'stacked100' ? stackMode : 'auto';\n\n // Memoize seriesOverrides to prevent unnecessary recreations\n const seriesOverrides = useMemo(\n () =>\n getSeriesOverrides({\n yfields: yFields,\n y2fields: y2Fields,\n lineWidth,\n overlayFields,\n y2Enabled,\n nullValueMode,\n markerDisplay,\n lineDashStyle,\n lineDashStylesByField,\n stepPosition,\n stepPositionsByField,\n type: chartType,\n stackMode: normalizedStackMode,\n showLines,\n }),\n [\n yFields,\n y2Fields,\n lineWidth,\n overlayFields,\n y2Enabled,\n nullValueMode,\n markerDisplay,\n lineDashStyle,\n lineDashStylesByField,\n stepPosition,\n stepPositionsByField,\n chartType,\n normalizedStackMode,\n showLines,\n ]\n );\n\n // Memoize annotations to prevent unnecessary recreations\n const chartingEventAnnotations = useMemo(\n () =>\n getAnnotationsForCanvas({\n annotationX,\n annotationColor,\n annotationLabel,\n }),\n [annotationX, annotationColor, annotationLabel]\n );\n\n // Memoize scaleConfig to prevent unnecessary recreations\n const scaleConfig = useMemo(\n () => ({ ...xScaleConfig, ...yScaleConfig, ...y2ScaleConfig }),\n [xScaleConfig, yScaleConfig, y2ScaleConfig]\n );\n\n // Memoize legend configuration\n // In seriesCompare mode, force the legend to the right side so that the legend's\n // fixed width (needed to prevent jitter when hover values appear/disappear) doesn't\n // affect layouts that would otherwise place it on the left.\n const isSeriesCompare = legendMode === 'seriesCompare';\n const legend = useMemo(\n () =>\n getLegend({\n legendDisplay: isSeriesCompare && legendDisplay !== 'off' ? 'right' : legendDisplay,\n isSeriesCompare,\n legendTruncation,\n }),\n [legendDisplay, isSeriesCompare, legendTruncation]\n );\n\n // Memoize click handlers to avoid recreating them on every render\n const handleChartClick = React.useCallback(\n event => {\n // Only invoke if onClick is defined to avoid unnecessary work\n if (onClick) {\n handleClick(event, onClick, trellisKey, trellisSplitBy);\n }\n },\n [onClick, trellisKey, trellisSplitBy]\n );\n\n const handleChartLegendClick = React.useCallback(\n event => {\n // Only invoke if onClick is defined to avoid unnecessary work\n if (onClick) {\n handleLegendClick(event, onClick, trellisKey, trellisSplitBy);\n }\n },\n [onClick, trellisKey, trellisSplitBy]\n );\n\n const handleChartRangeSelection = React.useCallback(\n range => {\n // Only invoke if onSelect is defined to avoid unnecessary work\n if (onSelect) {\n handleRangeSelection(range, onSelect, chartData, trellisKey, trellisSplitBy);\n }\n // Always allow range selection UI to appear, even if onSelect is undefined\n },\n [onSelect, chartData, trellisKey, trellisSplitBy]\n );\n\n const handleChartRangeZoom = React.useCallback(\n range => {\n // Only invoke if onSelect is defined to avoid unnecessary work\n if (onSelect) {\n handleRangeZoom(range, onSelect, chartData, trellisKey, trellisSplitBy);\n }\n },\n [onSelect, chartData, trellisKey, trellisSplitBy]\n );\n\n // Determine if search zoom should be enabled based on eventHandlers and xField\n // Use xFieldFromProps if available, otherwise fall back to computed xField from chartData\n const xFieldToUse = xFieldFromProps || xField;\n const enableSearchZoom = React.useMemo(\n () => shouldEnableSearchZoom(eventHandlers, xFieldToUse),\n [eventHandlers, xFieldToUse]\n );\n\n // Store the last payload and originalEvent to return on mouseout\n const lastPayloadRef = React.useRef<Record<string, any> | null>(null);\n const lastOriginalEventRef = React.useRef<any>(null);\n // Store the previous mouseover payload to check for changes\n const previousMouseoverPayloadRef = React.useRef<Record<string, unknown> | null>(null);\n // Store additionalTooltipValues in a ref to avoid chart remounts when it changes\n // The chart reads from this ref, so changes update the tooltip without remounting\n const additionalTooltipValuesRef = React.useRef(additionalTooltipValues);\n React.useEffect(() => {\n additionalTooltipValuesRef.current = additionalTooltipValues;\n }, [additionalTooltipValues]);\n\n const handleCrosshairMouseout = React.useCallback(() => {\n if (onPointMouseOut && lastPayloadRef.current) {\n onPointMouseOut({\n type: 'point.mouseout',\n originalEvent: lastOriginalEventRef.current,\n payload: lastPayloadRef.current,\n });\n }\n previousMouseoverPayloadRef.current = null;\n }, [onPointMouseOut]);\n\n const handleChartCrosshairChange = React.useCallback(\n event => {\n // Only invoke if onPointMouseOver or onPointMouseOut is defined to avoid unnecessary work\n if (!onPointMouseOver && !onPointMouseOut) {\n return;\n }\n\n // Handle mouseout when event is undefined\n if (!event) {\n handleCrosshairMouseout();\n return;\n }\n\n // Handle mouseover\n const payload = {\n ...pick(event, 'value', 'seriesKey', 'time', 'index', 'seriesIndex'),\n name: event.seriesKey,\n };\n delete payload.seriesKey;\n\n // Add row context fields in the format: row.${fieldName}.value\n if (event.rowContext) {\n Object.assign(\n payload,\n Object.keys(event.rowContext).reduce((acc, fieldName) => {\n acc[`row.${fieldName}.value`] = event.rowContext[fieldName];\n return acc;\n }, {})\n );\n }\n\n const updatedPayload = appendTrellisToPayload(payload, trellisKey, trellisSplitBy);\n\n // Check if the payload has actually changed to avoid emitting duplicate events\n if (!hasMouseoverPayloadChanged(updatedPayload, previousMouseoverPayloadRef.current)) {\n return;\n }\n\n // Store payload and originalEvent for mouseout\n lastPayloadRef.current = updatedPayload;\n lastOriginalEventRef.current = event;\n // Store current payload for next comparison\n previousMouseoverPayloadRef.current = { ...updatedPayload };\n\n if (onPointMouseOver) {\n onPointMouseOver({\n type: 'point.mouseover',\n originalEvent: event,\n payload: updatedPayload,\n });\n }\n },\n [onPointMouseOver, onPointMouseOut, trellisKey, trellisSplitBy, handleCrosshairMouseout]\n );\n\n // Create a key to reset RangeSelectionProvider when data changes\n const dataKey = `${chartData.columns[0]?.[0]}-${chartData.columns[0]?.[chartData.columns[0].length - 1]}-${chartData.columns[0]?.length}`;\n\n const memoizedChart = useMemo(() => {\n // Always pass zoom handler when onSelect exists, serverSideZoom controls behavior\n const computedOnRangeZoom = onSelect ? handleChartRangeZoom : undefined;\n\n return (\n <RangeSelectionProvider key={dataKey}>\n <TimeSeriesChart\n data={chartData as GenericDataSet}\n width={containerWidth}\n height={containerHeight}\n seriesColors={seriesColors}\n seriesColorsByField={seriesColorsByField}\n seriesConfig={seriesOverrides}\n legend={legend}\n legendLabels={legendLabels}\n legendTruncation={legendTruncation}\n isSeriesCompare={legendMode === 'seriesCompare'}\n maxSeriesFocus={legendMode === 'seriesCompare' ? 0 : undefined}\n scaleConfig={scaleConfig}\n timestampFormat=\"expanded\"\n onCrosshairClick={onClick ? handleChartClick : undefined}\n onCrosshairChange={\n onPointMouseOver || onPointMouseOut ? handleChartCrosshairChange : undefined\n }\n onSeriesClick={onClick ? handleChartLegendClick : undefined}\n onRangeSelection={handleChartRangeSelection}\n onRangeZoom={computedOnRangeZoom}\n serverSideZoom={enableSearchZoom}\n userLocale={userLocale}\n events={chartingEventAnnotations}\n eventsConfig={{ renderer: triangleEventAnnotationRenderer }}\n additionalTooltipValuesRef={additionalTooltipValuesRef}\n showXMajorGridLines={showXMajorGridLines}\n showYMajorGridLines={showYMajorGridLines}\n showY2MajorGridLines={showY2MajorGridLines}\n showYMinorGridLines={showYMinorGridLines}\n showY2MinorGridLines={showY2MinorGridLines}\n showLineSmoothing={showLineSmoothing}\n dataValuesDisplay={dataValuesDisplay}\n showXMajorTicks={showXMajorTicks}\n xAxisMajorTickSize={xAxisMajorTickSizeNum}\n showYMajorTicks={showYMajorTicks}\n showY2MajorTicks={showY2MajorTicks}\n yAxisMajorTickSize={yAxisMajorTickSizeNum}\n y2AxisMajorTickSize={y2AxisMajorTickSizeNum}\n yAxisMajorTickInterval={yAxisMajorTickIntervalNum}\n y2AxisMajorTickInterval={y2AxisMajorTickIntervalNum}\n showYMinorTicks={showYMinorTicks}\n showY2MinorTicks={showY2MinorTicks}\n yAxisMinorTickSize={yAxisMinorTickSizeNum}\n y2AxisMinorTickSize={y2AxisMinorTickSizeNum}\n showYAxisWithZero={showYAxisWithZero}\n showY2AxisWithZero={showY2AxisWithZero}\n showXAxisLine={showXAxisLine}\n showYAxisLine={showYAxisLine}\n showY2AxisLine={showY2AxisLine}\n xAxisMaxLabelParts={xAxisMaxLabelParts}\n areaOpacity={areaOpacityForCanvas}\n />\n </RangeSelectionProvider>\n );\n // Note: additionalTooltipValues passed via ref to avoid chart remount when switching stories.\n // The ref is updated via useEffect, so tooltip gets latest values without remounting chart.\n }, [\n onSelect,\n handleChartRangeZoom,\n dataKey,\n chartData,\n containerWidth,\n containerHeight,\n seriesColors,\n seriesColorsByField,\n seriesOverrides,\n legend,\n legendLabels,\n legendTruncation,\n scaleConfig,\n onClick,\n handleChartClick,\n onPointMouseOver,\n onPointMouseOut,\n handleChartCrosshairChange,\n handleChartLegendClick,\n handleChartRangeSelection,\n enableSearchZoom,\n userLocale,\n chartingEventAnnotations,\n showXMajorGridLines,\n showYMajorGridLines,\n showY2MajorGridLines,\n showYMinorGridLines,\n showY2MinorGridLines,\n showLineSmoothing,\n dataValuesDisplay,\n showXMajorTicks,\n xAxisMajorTickSizeNum,\n showYMajorTicks,\n showY2MajorTicks,\n yAxisMajorTickSizeNum,\n y2AxisMajorTickSizeNum,\n yAxisMajorTickIntervalNum,\n y2AxisMajorTickIntervalNum,\n showYMinorTicks,\n showY2MinorTicks,\n yAxisMinorTickSizeNum,\n y2AxisMinorTickSizeNum,\n showYAxisWithZero,\n showY2AxisWithZero,\n showXAxisLine,\n showYAxisLine,\n showY2AxisLine,\n legendMode,\n xAxisMaxLabelParts,\n areaOpacityForCanvas,\n ]);\n\n const memoizedVisualization = useMemo(() => {\n return <VizStyleWrapper backgroundColor={bgColor}>{memoizedChart}</VizStyleWrapper>;\n }, [bgColor, memoizedChart]);\n\n return (\n <>\n {trellisEnabled && (\n <TrellisTitle\n trellisKey={trellisKey}\n backgroundColor={bgColor}\n fontColor={defaultFontColor}\n />\n )}\n <TimeSeriesChartContainer\n height={trellisEnabled ? Number(height) - TRELLIS_TITLE_HEIGHT : height}\n width={width}\n ref={uplotContainerElement}\n data-test=\"timeseries-chart-wrapper\"\n >\n <SizeAwareWrapper width={width} height={height} onResize={cachedHandleResize} />\n {memoizedVisualization}\n </TimeSeriesChartContainer>\n </>\n );\n};\n\nexport default TimeSeriesChartWrapper;\n", "import * as React from 'react';\nimport { camelCase, has, get, defaultsDeep, noop } from 'lodash';\nimport getSettingsFromThemedProps from '@splunk/themes/getSettingsFromThemedProps';\nimport { Options as Opts } from '@splunk/visualization-encoding/Options';\nimport { withSanitizedProps } from '@splunk/visualizations-shared/SanitizeProps';\nimport type { TimezoneContextInterface } from '@splunk/visualization-context/TimezoneContext';\nimport TimezoneContext from '@splunk/visualization-context/TimezoneContext';\nimport moment from '@splunk/moment';\nimport FeatureFlagContext from '@splunk/visualization-context/FeatureFlagContext';\nimport { withTheme } from 'styled-components';\nimport { deepMergeWithArrayPrimitiveOverrides } from '@splunk/visualizations-shared/hocUtils';\nimport { pickFieldFromJSONSchema } from '@splunk/visualizations-shared/JSONSchemaUtils';\nimport AsyncDynamicOptionsEvaluator, {\n AsyncDynamicOptionsEvaluatorParams,\n} from '@splunk/async-dynamic-options-evaluator';\nimport { createGUID } from '@splunk/ui-utils/id';\nimport type { Frames } from '@splunk/visualization-encoding/EncodingExecutor';\nimport type { OptionsStanza } from '@splunk/visualization-encoding/AST';\nimport SplunkVisualization from './SplunkVisualization';\nimport type { DashboardVizProps, DataSource, VizConfig, VizProps } from './interfaces';\nimport { VizBehavior } from './interfaces/VizBehavior';\nimport { useSortingParams } from './hooks/useSorting';\nimport { usePaginationParams } from './hooks/usePagination';\nimport { useDeepMemo } from './hooks/useDeepMemo';\nimport MissingPropsMessage, { missingKeys } from './components/MissingPropsMessage';\nimport withEditModeCover from './hocs/withEditModeCover';\nimport withPlaceholder from './hocs/withPlaceholder';\nimport { ChartingProps } from './Charting';\nimport useDownsampleDataSources from './hooks/useDownsampleDataSources';\nimport { isDownsamplingEnabledForViz } from './utils/dataUtils';\nimport { getFeatureFlag } from '../common/utils/featureFlagUtils';\nimport { turnOffLegendDisplayWhenTrellisIsOn } from '../common/utils/trellisUtils';\nimport TimeSeriesChartWrapper from './TimeSeriesChartWrapper';\nimport { isTimeSeriesCanvasRenderSupported } from './chartingUtils';\n\n// Create the sanitized version once, outside the component to prevent remounting\nconst SanitizedTimeSeriesChartWrapper = withSanitizedProps(TimeSeriesChartWrapper);\n\ntype FeatureFlagContextValue = Record<string, boolean | undefined> | null;\n\ntype HOC = React.ComponentType<DashboardVizProps> & {\n config: VizConfig;\n};\nexport interface DashboardVizOpts {\n ReactViz: React.ComponentType<ChartingProps | VizProps>; // we will wrap this in DashboardViz (see const DashboardViz = ...)\n vizConfig: VizConfig;\n computeVizProps?: (props) => any;\n computeVizPropsBeforeEval?: (props) => any;\n computeDataFrames?: (args: {\n dataSources: { [key: string]: DataSource };\n options: Record<string, unknown>;\n }) => Partial<Frames>;\n disableEditModeCover?: boolean;\n useIconPlaceholder?: (\n dataSources: { [name: string]: DataSource },\n loading: boolean,\n options: Record<string, unknown>\n ) => boolean;\n}\n\nconst buildEventCallbackProps = (\n supportedEvents,\n evaluatedOptionsToUse,\n onEventTrigger\n): Record<string, unknown> => {\n const result = {};\n Object.keys(supportedEvents).forEach((eventName): void => {\n const { parentKeys, payloadKeys } = supportedEvents[eventName];\n const eventCallbackPropName = camelCase(`on.${eventName}`);\n\n let payload = {};\n if (Array.isArray(payloadKeys) && payloadKeys.length) {\n payloadKeys.forEach(p => {\n payload[p] = evaluatedOptionsToUse[p];\n });\n }\n\n result[eventCallbackPropName] = (ev): Record<string, unknown> => {\n if (ev?.payload) {\n payload = { ...ev.payload };\n }\n return onEventTrigger({\n originalEvent: ev,\n payload,\n type: eventName,\n });\n };\n\n if (parentKeys) {\n for (let i = parentKeys.length - 1; i >= 0; i -= 1) {\n const newObject = {};\n newObject[parentKeys[i]] = result[eventCallbackPropName];\n result[eventCallbackPropName] = newObject;\n }\n }\n });\n return result;\n};\n\n// Build the event callback props for a viz, splitting declared events by source.\n// 'default' events (e.g. RichText link.open) act as default handlers: injected\n// whenever the viz supports events, ungated by hasEventHandlers and in edit mode.\n// 'user' events (the default) only fire in view mode once handlers are bound.\nconst buildAllEventCallbackProps = (\n events: Record<string, { source?: 'default' | 'user' }>,\n evaluatedOptionsToUse,\n onEventTrigger,\n { supportsEvents, hasEventHandlers, mode }\n): Record<string, unknown> => {\n if (!supportsEvents) return {};\n const defaultEvents = {};\n const userEvents = {};\n Object.entries(events || {}).forEach(([eventKey, eventConfig]) => {\n (eventConfig.source === 'default' ? defaultEvents : userEvents)[eventKey] = eventConfig;\n });\n const userProps =\n hasEventHandlers && mode === 'view'\n ? buildEventCallbackProps(userEvents, evaluatedOptionsToUse, onEventTrigger)\n : {};\n return {\n ...userProps,\n ...buildEventCallbackProps(defaultEvents, evaluatedOptionsToUse, onEventTrigger),\n };\n};\n\n/**\n * @splunk/moment currently does not allow us to customize the timezone on a per\n * visualization basis. This ensures that if a timezone was provided via\n * TimezoneContext, @splunk/moment time formatting will use it.\n */\nconst applyContextTimezone = (localeContext: TimezoneContextInterface): void => {\n if (localeContext.serializedTimezone && !moment.getDefaultSplunkTimezone()) {\n moment.setDefaultSplunkTimezone(localeContext.serializedTimezone);\n }\n};\n\ninterface AsyncOptionsEvalArgs {\n visualizationID: string;\n props: DashboardVizProps;\n optionsToEvaluate: OptionsStanza;\n downsampledDataSources: Record<string, DataSource>;\n vizConfig: VizConfig;\n bypassCloneDeepOptionScope: boolean;\n lazyLoadingDataFrame: boolean;\n}\n\n/**\n * Builds the inputs for async (web worker) DSL evaluation without starting work during render.\n */\nconst getAsyncOptionsEvaluationParams = ({\n visualizationID,\n props,\n optionsToEvaluate,\n downsampledDataSources,\n vizConfig,\n bypassCloneDeepOptionScope,\n lazyLoadingDataFrame,\n}: AsyncOptionsEvalArgs): AsyncDynamicOptionsEvaluatorParams => {\n return {\n visualizationID,\n props,\n options: { ...optionsToEvaluate },\n dataSources: downsampledDataSources,\n theme: vizConfig.themes,\n bypassCloneDeepOptionScope,\n lazyLoadingDataFrame,\n };\n};\n\ninterface SyncOptionsEvalArgs {\n optionsToEvaluate: OptionsStanza;\n downsampledDataSources: Record<string, DataSource>;\n dataSourcesInState: Record<string, DataSource>;\n dataFramesInState: Frames | undefined;\n setDataSourcesInState: (dataSources: Record<string, DataSource>) => void;\n setDataFramesInState: (frames: Frames | undefined) => void;\n computeDataFrames?: DashboardVizOpts['computeDataFrames'];\n featureFlagContext: FeatureFlagContextValue;\n themeFunc: (themeVar: string) => unknown;\n}\n\n/**\n * Synchronously builds data frames (memoizing them in component state) and evaluates DSL\n * options against them. Extracted out of the DashboardViz render body to keep its cognitive\n * complexity down.\n */\nconst evaluateOptionsSync = ({\n optionsToEvaluate,\n downsampledDataSources,\n dataSourcesInState,\n dataFramesInState,\n setDataSourcesInState,\n setDataFramesInState,\n computeDataFrames,\n featureFlagContext,\n themeFunc,\n}: SyncOptionsEvalArgs): Record<string, unknown> => {\n let dataFrames: Frames | undefined = dataFramesInState;\n if (downsampledDataSources !== dataSourcesInState) {\n setDataSourcesInState(downsampledDataSources);\n dataFrames = Opts.dataFrameFromDataSource(\n downsampledDataSources,\n getFeatureFlag(featureFlagContext, 'visualizations_lazyLoadingDataFrame')\n );\n setDataFramesInState(dataFrames);\n }\n // Merge derived frames when provided\n let mergedFrames = dataFrames;\n if (computeDataFrames && dataFrames) {\n const derivedFrames = computeDataFrames({\n dataSources: downsampledDataSources,\n options: optionsToEvaluate.options as Record<string, unknown>,\n });\n mergedFrames = { ...dataFrames, ...derivedFrames };\n }\n return Opts.evaluate(\n optionsToEvaluate,\n downsampledDataSources,\n themeFunc,\n mergedFrames,\n getFeatureFlag(featureFlagContext, 'visualizations_bypassCloneDeepOptionScope')\n );\n};\n\n/**\n * hoc that wraps a pure react visualization in a Dashboard visualization\n * @param {DashboardVizOpts} opts\n * @returns {HOC}\n */\nconst withDashboardViz = (opts: DashboardVizOpts): HOC => {\n const {\n ReactViz,\n vizConfig,\n computeVizProps = () => {},\n computeVizPropsBeforeEval = () => {},\n computeDataFrames,\n disableEditModeCover,\n useIconPlaceholder,\n } = opts;\n\n // sanitizing props before sending them to reactviz.\n const SanitizedReactViz = withSanitizedProps(ReactViz); // Default assigned to ReactViz\n const defaultOptions = pickFieldFromJSONSchema(vizConfig.optionsSchema, 'default');\n\n const DashboardViz = (props: DashboardVizProps): React.ReactElement<DashboardVizProps> => {\n const {\n mode = 'view',\n hasEventHandlers,\n dataSources, // type of { [key: string]: DataSource }\n options = {},\n context = {},\n width,\n height,\n onComputedProps = noop,\n onEventTrigger = SplunkVisualization.defaults.onEventTrigger,\n theme,\n onRequestParamsChange = noop,\n } = props;\n const localeContext = React.useContext<TimezoneContextInterface>(TimezoneContext);\n applyContextTimezone(localeContext);\n\n const themeFunc = themeVar => vizConfig.themes[themeVar]?.(props);\n const {\n family: currentThemeFamily,\n colorScheme: currentThemeColorScheme,\n density: currentThemeDensity,\n } = getSettingsFromThemedProps({ theme });\n let evaluatedOptions: Record<string, unknown> = {}; // evaluatedOptions need to be initialized as an empty object\n const [evaluatedOptionsAsync, setEvaluatedOptionsAsync] = React.useState({}); // evaluatedOptions need to be initialized as an empty object\n const featureFlagContext = React.useContext<FeatureFlagContextValue>(FeatureFlagContext);\n\n const [visualizationID] = React.useState(`${vizConfig.name} - ${createGUID()}`);\n\n const [dataSourcesInState, setDataSourcesInState] = React.useState({});\n const [dataFramesInState, setDataFramesInState] = React.useState<Frames | undefined>();\n\n const [useAsyncEvaluatedOptions, setUseAsyncEvaluatedOptions] = React.useState(\n Boolean(getFeatureFlag(featureFlagContext, 'visualizations_useWebWorkersForDSL'))\n );\n const isDownsamplingEnabledByFeatureFlag = Boolean(\n featureFlagContext?.visualizations_enableDownsampling\n );\n const isTrellisFeatureFlagOn = Boolean(featureFlagContext?.visualizations_enableTrellis);\n const isTrellisOn =\n isTrellisFeatureFlagOn &&\n vizConfig?.supports?.includes(VizBehavior.TRELLIS) &&\n options?.splitByLayout === VizBehavior.TRELLIS;\n\n const isAcceleratedRenderFeatureFlagOn = Boolean(\n featureFlagContext?.visualizations_enableAcceleratedRender\n );\n const isAcceleratedRenderOn =\n isAcceleratedRenderFeatureFlagOn &&\n isTimeSeriesCanvasRenderSupported(vizConfig.key) &&\n options?.acceleratedRender === true;\n const bypassCloneDeepOptionScope = Boolean(\n getFeatureFlag(featureFlagContext, 'visualizations_bypassCloneDeepOptionScope')\n );\n const lazyLoadingDataFrame = Boolean(\n getFeatureFlag(featureFlagContext, 'visualizations_lazyLoadingDataFrame')\n );\n const optionsToEvaluate = React.useMemo(() => {\n const legendDisplay = turnOffLegendDisplayWhenTrellisIsOn(isTrellisOn, options);\n // computeVizPropsBeforeEval will run before DSL gets evaluated\n const computedOptions = computeVizPropsBeforeEval(options) ?? {};\n return {\n context: defaultsDeep({}, context, vizConfig.defaultContext),\n options: deepMergeWithArrayPrimitiveOverrides(\n {},\n legendDisplay,\n computedOptions,\n options,\n defaultOptions\n ),\n };\n }, [isTrellisOn, options, context]);\n\n const [threshold, setThreshold] = React.useState(Number(width));\n const onDownsamplingThresholdChange = React.useCallback((newThreshold: number) => {\n setThreshold(newThreshold);\n }, []);\n const isDownsamplingEnabled = React.useMemo(() => {\n return isDownsamplingEnabledByFeatureFlag && isDownsamplingEnabledForViz({ vizConfig });\n }, [isDownsamplingEnabledByFeatureFlag]);\n\n const downsamplingProps = React.useMemo(() => {\n if (!isDownsamplingEnabled) {\n return {};\n }\n return {\n onDownsamplingThresholdChange,\n originalDataSources: dataSources,\n };\n }, [dataSources, isDownsamplingEnabled, onDownsamplingThresholdChange]);\n const downsampledDataSources = useDownsampleDataSources({\n options: optionsToEvaluate.options,\n context: optionsToEvaluate.context,\n dataSources,\n threshold,\n isDownsamplingEnabled,\n });\n\n const asyncOptionsEvaluationParams = useDeepMemo(\n () =>\n getAsyncOptionsEvaluationParams({\n visualizationID,\n props,\n optionsToEvaluate,\n downsampledDataSources,\n vizConfig,\n bypassCloneDeepOptionScope,\n lazyLoadingDataFrame,\n }),\n [\n visualizationID,\n optionsToEvaluate,\n downsampledDataSources,\n vizConfig,\n bypassCloneDeepOptionScope,\n lazyLoadingDataFrame,\n currentThemeFamily,\n currentThemeColorScheme,\n currentThemeDensity,\n localeContext.serializedTimezone,\n ]\n );\n\n React.useEffect(() => {\n if (!useAsyncEvaluatedOptions) {\n return undefined;\n }\n\n let ownsEvaluation = true;\n try {\n AsyncDynamicOptionsEvaluator.evaluate(asyncOptionsEvaluationParams)\n .then(results => {\n if (ownsEvaluation) {\n setEvaluatedOptionsAsync(results.results as Record<string, unknown>);\n }\n })\n .catch(() => {\n if (ownsEvaluation) {\n setUseAsyncEvaluatedOptions(false);\n }\n });\n } catch {\n setUseAsyncEvaluatedOptions(false);\n }\n\n return () => {\n ownsEvaluation = false;\n AsyncDynamicOptionsEvaluator.reset(visualizationID);\n };\n }, [asyncOptionsEvaluationParams, useAsyncEvaluatedOptions, visualizationID]);\n\n evaluatedOptions = useDeepMemo(() => {\n try {\n if (useAsyncEvaluatedOptions) {\n return {};\n }\n return evaluateOptionsSync({\n optionsToEvaluate,\n downsampledDataSources,\n dataSourcesInState,\n dataFramesInState,\n setDataSourcesInState,\n setDataFramesInState,\n computeDataFrames,\n featureFlagContext,\n themeFunc,\n });\n } catch (e) {\n if (e instanceof Error) {\n // eslint-disable-next-line no-console\n console.error(`unexpected error evaluating options: ${e.message}`);\n }\n return {};\n }\n }, [\n currentThemeFamily,\n currentThemeColorScheme,\n currentThemeDensity,\n optionsToEvaluate,\n downsampledDataSources,\n localeContext.serializedTimezone,\n useAsyncEvaluatedOptions,\n ]);\n\n const evaluatedOptionsToUse = useAsyncEvaluatedOptions ? evaluatedOptionsAsync : evaluatedOptions;\n\n /**\n * PAGE_AND_SORT behavior\n *\n * Some visualizations, like table, requires metadata about the datasource,\n * like total number of results, current count, offset, and sort, for rendering\n * paginator and sorting direction. In this approach, the visualization\n * allow users to set 'paginateDataSourceKey' to select which datasource\n * should the visualization extract the metadata from. It defaults to 'primary' datasource.\n * The visualization config should set the PAGE_AND_SORT behavior to receive\n * 'requestParams', 'meta' and onRequestParams callback as props.\n *\n * In future, we could automatically detect which all datasources are being used\n * and bind those magically to pagination/sorting behavior.\n */\n let dataSourceMetadata = {};\n const OptionKey = 'paginateDataSourceKey';\n const optsKey = has(evaluatedOptionsToUse, OptionKey) && evaluatedOptionsToUse[OptionKey];\n const paginateDataSourceKey = typeof optsKey === 'string' ? optsKey : 'primary';\n\n const requestParams = get(dataSources, [paginateDataSourceKey, 'requestParams'], {});\n const meta = get(dataSources, [paginateDataSourceKey, 'meta'], {});\n const handleRequestParamsChange = (payload: Record<string, unknown>): void =>\n onRequestParamsChange(paginateDataSourceKey, payload);\n\n const sortParams = useSortingParams({\n requestParams,\n meta,\n onRequestParamsChange: handleRequestParamsChange,\n });\n\n const paginatorParams = usePaginationParams({\n requestParams,\n meta,\n onRequestParamsChange: handleRequestParamsChange,\n });\n\n dataSourceMetadata = {\n sortParams,\n paginatorParams,\n };\n\n if (\n !vizConfig.supports.includes(VizBehavior.PAGE_AND_SORT) &&\n !has(dataSources, paginateDataSourceKey)\n ) {\n dataSourceMetadata = {};\n }\n\n // trellis specific backgroundColor update for onComputedProps\n // if trellis is enabled following these three criteria - 1) trellis feature flag is enabled 2) vizConfig supports array has 'trellis' 3) option 'splitByLayout' is set to 'trellis\n // onComputedProps api should return back trellisBackgroundColor value for backgroundColor option to support coloring of sibling panels (for eg:- title/ description on UDF side)\n const clonedEvaluatedOptions: Record<string, unknown> = { ...evaluatedOptionsToUse };\n if (isTrellisOn) {\n clonedEvaluatedOptions.backgroundColor = clonedEvaluatedOptions?.trellisBackgroundColor;\n }\n // useEffect hook needs to be initialized before any early returns\n // this is in accordance with the order of hook calls being the same on each render https://reactjs.org/docs/hooks-rules.html#explanation\n React.useEffect((): void => {\n onComputedProps(clonedEvaluatedOptions);\n });\n\n // present warning message if any required props are missing\n const { requiredProps = [], supports } = vizConfig;\n const missing = missingKeys(requiredProps, evaluatedOptionsToUse);\n if (\n missing.length > 0 &&\n supports.includes(VizBehavior.PLACEHOLDER) &&\n vizConfig.key !== 'splunk.singlevalue' // For SV missing props msg is not displayed if required props majorValue is missing, instead this will be handled from the component, instead handled within component\n ) {\n return (\n <MissingPropsMessage\n data-test=\"missing-props-message\"\n width={width}\n height={height}\n missingProps={missing}\n backgroundColor={themeFunc('defaultBackgroundColor')}\n />\n );\n }\n\n // events\n const eventCallbackProps = buildAllEventCallbackProps(\n vizConfig.events,\n evaluatedOptionsToUse,\n onEventTrigger,\n {\n supportsEvents: vizConfig.supports.includes(VizBehavior.EVENTS),\n hasEventHandlers,\n mode,\n }\n );\n\n // compute pure viz props which are not from options\n const computedVizProps = computeVizProps({\n ...props,\n ...evaluatedOptionsToUse,\n // Align option transformation with the actual renderer selected below.\n // This prevents canvas-only option preservation from leaking into Highcharts mode.\n isAcceleratedRenderOn,\n ...eventCallbackProps,\n themeFunc,\n });\n\n // if were using webworkers and this is the first render we dont want to show a viz with missing data so we return null\n if (useAsyncEvaluatedOptions && Object.keys(evaluatedOptionsToUse).length === 0) {\n return null;\n }\n\n // if acceleratedRender mode is on, then use canvas viz\n const SanitizedViz = isAcceleratedRenderOn ? SanitizedTimeSeriesChartWrapper : SanitizedReactViz;\n\n return (\n <SanitizedViz\n {...SplunkVisualization.defaults}\n mode={mode}\n width={width || SplunkVisualization.defaults.width}\n height={height || SplunkVisualization.defaults.height}\n userLocale={localeContext}\n {...downsamplingProps}\n {...evaluatedOptionsToUse}\n {...computedVizProps}\n {...eventCallbackProps}\n {...dataSourceMetadata}\n />\n );\n };\n\n DashboardViz.propTypes = {\n ...SplunkVisualization.propTypes,\n ...ReactViz.propTypes,\n };\n\n DashboardViz.defaultProps = {\n ...ReactViz.defaultProps, // we still need ReactViz.defaultProps for the visualizations that still have them\n onEventTrigger: SplunkVisualization.defaults.onEventTrigger,\n };\n\n // attach viz config\n DashboardViz.config = vizConfig;\n\n return Object.assign(\n withTheme(withPlaceholder(withEditModeCover(DashboardViz, disableEditModeCover), useIconPlaceholder)),\n { config: vizConfig }\n );\n};\n\nexport default withDashboardViz;\n", "\nimport * as defaultImport from \"@splunk/dashboard-context\";\nexport * from \"@splunk/dashboard-context\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"slate\";\nexport * from \"slate\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"slate-react\";\nexport * from \"slate-react\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "/**\n * Module-level tracker for the active (focused) PureRichText instance.\n * Separate file so PureRichText.tsx and EditorPanel.tsx can import it without a cycle.\n */\n\nimport { Editor } from 'slate';\nimport { ReactEditor } from 'slate-react';\n\nlet activeRichTextId: string | null = null;\nlet activeEditableElement: HTMLDivElement | null = null;\nlet activeSlateEditor: Editor | null = null;\nconst activeRichTextListeners = new Set<() => void>();\n\nexport function registerActiveRichText(\n id: string,\n editable: HTMLDivElement | null,\n editor: Editor | null\n): void {\n activeRichTextId = id;\n activeEditableElement = editable;\n activeSlateEditor = editor;\n activeRichTextListeners.forEach(fn => fn());\n}\n\nexport function clearActiveRichText(id: string): void {\n if (activeRichTextId === id) {\n activeRichTextId = null;\n activeEditableElement = null;\n activeSlateEditor = null;\n activeRichTextListeners.forEach(fn => fn());\n }\n}\n\nexport function getActiveRichTextId(): string | null {\n return activeRichTextId;\n}\n\nexport function getActiveSlateEditor(): Editor | null {\n return activeSlateEditor;\n}\n\n/**\n * Restore focus and caret on the active Slate editor. ReactEditor.focus() restores\n * both DOM focus and the Slate selection into window.getSelection() (caret visible).\n */\nexport function focusActiveEditable(): void {\n if (activeSlateEditor) {\n try {\n ReactEditor.focus(activeSlateEditor as ReactEditor);\n } catch {\n activeEditableElement?.focus();\n }\n } else {\n activeEditableElement?.focus();\n }\n}\n\nexport function subscribeActiveRichText(callback: () => void): () => void {\n activeRichTextListeners.add(callback);\n return () => activeRichTextListeners.delete(callback);\n}\n\n// Suppress blur-deactivation while a popover (link editor, etc.) is open. It's portaled\n// to body, outside the config panel/viz-item, so handleBlur can't detect it via containment.\nlet suppressBlurDeactivation = false;\nexport function setSuppressBlurDeactivation(value: boolean): void {\n suppressBlurDeactivation = value;\n}\nexport function isSuppressBlurDeactivation(): boolean {\n return suppressBlurDeactivation;\n}\n\n// Flag to suppress blur-deactivation during mouse-drag text selection.\n// Separate from suppressBlurDeactivation so popover logic is not affected.\nlet mouseSelecting = false;\nexport function setMouseSelecting(value: boolean): void {\n mouseSelecting = value;\n}\nexport function isMouseSelecting(): boolean {\n return mouseSelecting;\n}\n\n// Set on mouseup when a press on a selected viz moved far enough to be a drag. Consumed\n// by the ensuing click so drag-to-move doesn't enter text editing. Auto-clears after one read.\nlet suppressNextEditClick = false;\nexport function setSuppressNextEditClick(value: boolean): void {\n suppressNextEditClick = value;\n}\nexport function consumeSuppressNextEditClick(): boolean {\n const v = suppressNextEditClick;\n suppressNextEditClick = false;\n return v;\n}\n", "/**\n * Types for PureRichText visualization\n * Slate.js-based rich text editor implementation\n */\n\nimport { BaseEditor, Descendant } from 'slate';\nimport { ReactEditor } from 'slate-react';\n\n// ============================================\n// Element Types\n// ============================================\n\n/** Custom element types supported by the editor */\nexport type CustomElementType = 'paragraph' | 'bulleted-list' | 'numbered-list' | 'list-item' | 'link';\n\n/** Horizontal text alignment options */\nexport type TextAlign = 'left' | 'center' | 'right' | 'justify';\n\n/** Vertical alignment options */\nexport type VerticalAlign = 'top' | 'middle' | 'bottom';\n\n/** List type options */\nexport type ListType = 'unordered' | 'ordered' | null;\n\n/** Font size preset options */\nexport type FontSizePreset = 'extraSmall' | 'small' | 'default' | 'large' | 'extraLarge' | 'custom';\n\n// ============================================\n// Slate Custom Types\n// ============================================\n\n/** Custom element with formatting properties */\nexport interface CustomElement {\n type: CustomElementType;\n align?: TextAlign;\n lineHeight?: string; // Per-paragraph line height (e.g., \"1.5\", \"2\")\n children: (CustomText | CustomElement)[];\n url?: string; // For link elements\n}\n\n/** Custom text node with marks (inline formatting) */\nexport interface CustomText {\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n color?: string;\n backgroundColor?: string;\n fontSize?: string;\n fontFamily?: string;\n tokenName?: string; // marks this text as an atomic token (resolved or raw)\n tokenOccurrence?: number; // keeps adjacent occurrences of the same token as separate Slate leaves\n isRawToken?: boolean; // true only on raw $token$ patterns (wrapRawTokensInTree path)\n isEscapedDollar?: boolean; // atomic `$$` escape: displays `$`, serializes `$$`\n}\n\n// Extend Slate's type system\ndeclare module 'slate' {\n interface CustomTypes {\n Editor: BaseEditor & ReactEditor;\n Element: CustomElement;\n Text: CustomText;\n }\n}\n\n// ============================================\n// Text Styles Interface\n// ============================================\n\n/** Complete text styles state */\nexport interface TextStyles {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikethrough: boolean;\n color: string | null;\n backgroundColor: string | null;\n fontSize: string | null;\n fontFamily: string | null;\n textAlign: TextAlign | null;\n verticalAlign?: VerticalAlign | null;\n lineHeight?: string | null;\n listType: ListType;\n}\n\n/** Default text styles */\nexport const DEFAULT_TEXT_STYLES: TextStyles = {\n bold: false,\n italic: false,\n underline: false,\n strikethrough: false,\n color: '#ffffff',\n backgroundColor: 'transparent',\n fontSize: '14px',\n fontFamily: 'Splunk Data Sans',\n textAlign: 'left',\n verticalAlign: 'top',\n lineHeight: '1.5',\n listType: null,\n};\n\n// ============================================\n// Format Commands\n// ============================================\n\n/** All supported format commands */\nexport type FormatCommand =\n | 'bold'\n | 'italic'\n | 'underline'\n | 'strikethrough'\n | 'foreColor'\n | 'backColor'\n | 'fontSize'\n | 'fontName'\n | 'fontFamily'\n | 'justifyLeft'\n | 'justifyCenter'\n | 'justifyRight'\n | 'justifyFull'\n | 'lineHeight'\n | 'insertUnorderedList'\n | 'insertOrderedList'\n | 'createLink'\n | 'unlink'\n | 'formatBlock'\n | 'verticalAlign'\n | 'undo';\n\n/** Mark types for inline formatting */\nexport type MarkType =\n | 'bold'\n | 'italic'\n | 'underline'\n | 'strikethrough'\n | 'color'\n | 'backgroundColor'\n | 'fontSize'\n | 'fontFamily';\n\n// ============================================\n// Border Configuration\n// ============================================\n\n/** Border configuration for the container */\nexport interface BorderConfig {\n color?: string;\n width?: number;\n style?: 'solid' | 'dashed' | 'dotted' | 'none';\n radius?: number;\n}\n\n// ============================================\n// Padding Configuration\n// ============================================\n\n/** Padding configuration (can be a single value or array) */\nexport type PaddingConfig = number | [number, number] | [number, number, number, number];\n\n// ============================================\n// Token Resolution Types\n// ============================================\n\nexport interface TokenMatchMetadata {\n namespace: string;\n name: string;\n filters: string[];\n match: string;\n start: number;\n end: number;\n // Filters applied server-side; the resulting primitive/array is stringified into resolvedContent.\n value: string | number | boolean | (string | number | boolean)[] | null;\n}\n\n/** Token metadata injected by the dashboard framework. Keys are option field names. */\nexport type RichTextTokenMetadata = Record<string, TokenMatchMetadata[]>;\n\n// ============================================\n// Component Props\n// ============================================\n\n/** Props for the PureRichText component */\nexport interface PureRichTextProps {\n // Dimensions\n width?: string | number;\n height?: string | number;\n\n // Content\n richTextContent?: string;\n\n // Container styling\n backgroundColor?: string;\n verticalAlign?: VerticalAlign;\n border?: BorderConfig;\n padding?: PaddingConfig;\n\n // Default text styling\n fontColor?: string;\n highlightColor?: string;\n fontFamily?: string;\n fontSize?: FontSizePreset;\n customFontSize?: number;\n lineHeight?: string | number;\n\n // Text formatting defaults\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n\n // Default text styles (aggregated from individual props)\n defaultTextStyles?: Partial<TextStyles>;\n\n // List and alignment\n listType?: ListType;\n horizontalAlignment?: TextAlign;\n\n // Link support\n link?: string;\n\n // Edit mode\n mode?: 'view' | 'edit';\n\n // Edit mode: true shows resolved token values, false (default) shows raw $token$ patterns.\n // View mode always resolves tokens regardless of this flag.\n previewTokenValues?: boolean;\n\n // Token metadata injected by the framework via tokenMetadataProp; mirrors .options with string\n // values replaced by TokenMatchMetadata arrays.\n richTextTokenMetadata?: RichTextTokenMetadata;\n\n // Callbacks\n onOptionsChange?: (options: Record<string, unknown>) => void;\n onRichtextClick?: (event: unknown) => void;\n // Injected by withDashboardViz for `link.open`; a 'default'-source event so it fires ungated by\n // hasEventHandlers and in edit mode. Absent standalone (renderer uses native fallback).\n onLinkOpen?: (event: { payload: { url: string } }) => void;\n\n // Event handlers flag\n hasEventHandlers?: boolean;\n}\n\n// ============================================\n// Constants\n// ============================================\n\n/** Initial empty Slate value */\nexport const EMPTY_SLATE_VALUE: Descendant[] = [\n {\n type: 'paragraph',\n children: [{ text: '' }],\n },\n];\n\n/** Font size preset values in pixels */\nexport const FONT_SIZE_PRESETS: Record<FontSizePreset, number> = {\n extraSmall: 10,\n small: 12,\n default: 14,\n large: 16,\n extraLarge: 20,\n custom: 14,\n};\n\n/** Preloaded system fonts available by default */\nexport const PRELOADED_FONTS = [\n 'Splunk Data Sans',\n 'Splunk Platform Sans Mono',\n 'Arial',\n 'Helvetica',\n 'Times New Roman',\n 'Comic Sans MS',\n] as const;\n\n/** Font family with fallbacks */\nexport const FONT_FAMILY_WITH_FALLBACKS: Record<string, string> = {\n 'Splunk Data Sans':\n '\"Splunk Data Sans\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif',\n 'Splunk Platform Sans Mono': '\"Splunk Platform Sans Mono\", \"Courier New\", Courier, monospace',\n Arial: 'Arial, Helvetica, sans-serif',\n Helvetica: 'Helvetica, Arial, sans-serif',\n 'Times New Roman': '\"Times New Roman\", Times, serif',\n 'Comic Sans MS': '\"Comic Sans MS\", \"Comic Sans\", cursive, sans-serif',\n};\n", "\nimport * as defaultImport from \"dompurify\";\nexport * from \"dompurify\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import { useRef } from 'react';\nimport { Descendant, Text, Element } from 'slate';\nimport type { CustomText, TokenMatchMetadata, RichTextTokenMetadata } from '../types';\n\n/** Permitted chars in a token namespace/name (framework's DEFAULT_ALLOWABLE_NAME_PATTERN):\n * alphanumeric, underscore, space, dash, period. */\nconst NAME_CHARS = String.raw` \\w.-`;\n\n/** Optional `namespace:` prefix. */\nconst NAMESPACE_PREFIX = `(?:[${NAME_CHARS}]+:)?`;\n\n/** Token name: must not start/end with a space. */\nconst NAME = String.raw`(?:(?=[\\w.-])[${NAME_CHARS}]*[\\w.-])`;\n\n/** Optional `|filter` suffixes (e.g. `|s`, `|h`, `|u`, `|v`, `|n`), stackable. */\nconst FILTERS = String.raw`(?:\\|[a-zA-Z]+)*`;\n\n/** Full token content between delimiters: `namespace:name|filter1|filter2`. */\nconst TOKEN_CONTENT = `${NAMESPACE_PREFIX}${NAME}${FILTERS}`;\n\n/** Regex that matches $namespace:token_name|filter$ patterns. */\nexport const TOKEN_PATTERN = new RegExp(String.raw`\\$(${TOKEN_CONTENT})\\$`, 'g');\n\n/** Matches an escaped dollar (`$$`, literal `$`) OR a `$token$` pattern. `$$` is tried first so it's\n * never mis-read as a token boundary. Group 1 is the raw content (undefined for `$$`), reused as the\n * `nameToValue` key so it round-trips without re-parsing. */\nexport const TOKEN_OR_ESCAPE_PATTERN = new RegExp(\n String.raw`\\$\\$|\\$(${TOKEN_CONTENT})\\$(?=\\$${TOKEN_CONTENT}\\$|\\$\\$|[^$]|$)`,\n 'g'\n);\n\n/** Stringify a resolved token value (already filter-formatted server-side) for splicing into HTML. */\nfunction toValueString(value: TokenMatchMetadata['value']): string | null {\n return value === null ? null : String(value);\n}\n\n/** Build a name -> value map and raw content from TokenMatchMetadata. `start`/`end` are RAW offsets\n * but we hold the RESOLVED string, so we walk both cursors in parallel, advancing the resolved cursor\n * by each value's length (or pattern length when unresolved). */\nexport function normalizeTokenMetadata(\n metadata: TokenMatchMetadata[] | null | undefined,\n resolvedContent: string\n): { nameToValue: Map<string, string>; rawContent: string; reconciled: boolean } {\n // Key by NAME (1:1), not value: two tokens can share a value (e.g. two\n // color inputs set to \"#2E8B57\"), which a value-keyed map would collapse.\n const nameToValue = new Map<string, string>();\n if (!metadata || metadata.length === 0) {\n return { nameToValue, rawContent: resolvedContent, reconciled: true };\n }\n\n const sorted = [...metadata].sort((a, b) => a.start - b.start);\n\n // Name->value map is offset-independent, so it is safe even if the metadata\n // is stale. Skip escaped dollars (`$$`): they are literal `$`, not tokens.\n for (const { match, value } of sorted) {\n const strValue = toValueString(value);\n if (match !== '$$' && strValue !== null && strValue !== '') {\n nameToValue.set(match.slice(1, -1), strValue);\n }\n }\n\n // Reconstruct raw content by walking both cursors in parallel. Before splicing each token back in,\n // verify its value sits at the expected position; if not, the metadata is stale, so bail out and\n // pass the content through rather than corrupting it.\n let raw = '';\n let rawCursor = 0;\n let resolvedCursor = 0;\n for (const entry of sorted) {\n const { match, value, start, end } = entry;\n const strValue = toValueString(value);\n const literalLength = start - rawCursor;\n // A token unresolved (value null) still occupies its raw pattern in resolved content.\n const expected = strValue ?? match;\n const valuePos = resolvedCursor + literalLength;\n if (literalLength < 0 || resolvedContent.slice(valuePos, valuePos + expected.length) !== expected) {\n return { nameToValue, rawContent: resolvedContent, reconciled: false };\n }\n raw += resolvedContent.slice(resolvedCursor, valuePos);\n raw += match;\n rawCursor = end;\n resolvedCursor = valuePos + expected.length;\n }\n raw += resolvedContent.slice(resolvedCursor);\n\n return { nameToValue, rawContent: raw, reconciled: true };\n}\n\n/** Split `rawContent` into literal chunks separated by token wildcards: a $token$ is a wildcard\n * boundary, `$$` is a literal `$`. Returns chunks in order plus whether any wildcard exists (adjacent\n * tokens yield an empty chunk between them). */\nfunction splitByTokenWildcards(rawContent: string): { literals: string[]; hasWildcard: boolean } {\n const re = new RegExp(TOKEN_OR_ESCAPE_PATTERN.source, 'g');\n const literals: string[] = [];\n let hasWildcard = false;\n let buf = '';\n let lastIndex = 0;\n let match = re.exec(rawContent);\n while (match !== null) {\n buf += rawContent.slice(lastIndex, match.index);\n if (match[1] === undefined) {\n // Escaped dollar ($$): a literal `$`, not a wildcard.\n buf += '$';\n } else {\n // Real token ($token$): close the current literal chunk, open a new one.\n literals.push(buf);\n buf = '';\n hasWildcard = true;\n }\n lastIndex = match.index + match[0].length;\n match = re.exec(rawContent);\n }\n buf += rawContent.slice(lastIndex);\n literals.push(buf);\n return { literals, hasWildcard };\n}\n\n/** Does `resolvedContent` match `rawContent`'s literal structure (each $token$ = wildcard)? True means\n * only a token VALUE lagged (keep frozen raw); false means literal text changed (raw is stale). Linear\n * glob walk, not a compiled regex, since adjacent tokens give catastrophic-backtracking `[\\s\\S]*[\\s\\S]*`. */\nexport function isValueOnlyChange(rawContent: string, resolvedContent: string): boolean {\n const { literals, hasWildcard } = splitByTokenWildcards(rawContent);\n // No token: the structures must be identical.\n if (!hasWildcard) return resolvedContent === literals[0];\n const prefix = literals[0];\n const suffix = literals.at(-1) ?? '';\n if (!resolvedContent.startsWith(prefix)) return false;\n if (!resolvedContent.endsWith(suffix)) return false;\n let cursor = prefix.length;\n const end = resolvedContent.length - suffix.length;\n if (cursor > end) return false;\n // Each interior literal must appear in order between prefix and suffix.\n for (let i = 1; i < literals.length - 1; i += 1) {\n const chunk = literals[i];\n const idx = resolvedContent.indexOf(chunk, cursor);\n if (idx === -1 || idx + chunk.length > end) return false;\n cursor = idx + chunk.length;\n }\n return true;\n}\n\n/** Shared recursive tree walk: applies splitLeaf to each text node. */\nfunction wrapTreeNodes(nodes: Descendant[], splitLeaf: (node: CustomText) => Descendant[]): Descendant[] {\n const processNode = (node: Descendant): Descendant[] => {\n if (Text.isText(node)) {\n return splitLeaf(node);\n }\n if (Element.isElement(node)) {\n return [{ ...node, children: node.children.flatMap(processNode) }];\n }\n return [node];\n };\n return nodes.flatMap(processNode);\n}\n\n/** Mark each `$name$` with `tokenName` and each `$$` with `isEscapedDollar`. With `nameToValue`\n * (preview) nodes display resolved values, escaped dollars show `$`; without it, raw `$name$`/`$$`.\n * `slateToHtml` re-derives the patterns from marks, so display text is never reversed by lookup. */\nexport function wrapRawTokensInTree(nodes: Descendant[], nameToValue?: Map<string, string>): Descendant[] {\n return wrapTreeNodes(nodes, node => splitTextByRawTokens(node, nameToValue));\n}\n\nfunction splitTextByRawTokens(textNode: CustomText, nameToValue?: Map<string, string>): Descendant[] {\n // Strip token flags so a plain split doesn't inherit them; set explicitly below.\n const {\n text,\n tokenName: existingTokenName,\n isEscapedDollar,\n isRawToken: existingIsRawToken,\n ...rest\n } = textNode;\n const marks = { ...rest };\n if (!text) return [textNode];\n // Already-wrapped escaped dollar: re-derive display for the current mode, unless edited away from\n // its pristine all-`$` display. Adjacent escapes merge, so count from the PRIOR mode (raw = `$$`\n // per escape, preview = `$`) before re-rendering.\n if (isEscapedDollar) {\n if (!/^\\$+$/.test(text)) return [textNode];\n const escapeCount = existingIsRawToken ? text.length / 2 : text.length;\n return [\n {\n ...textNode,\n text: displayTextForEscapedDollar(nameToValue).repeat(escapeCount),\n isRawToken: !nameToValue,\n },\n ];\n }\n // Already-wrapped token node: re-derive display text for the current mode (mode flip).\n if (existingTokenName) {\n const display = displayTextForToken(existingTokenName, nameToValue);\n return [{ ...textNode, text: display, isRawToken: !nameToValue }];\n }\n\n const re = new RegExp(TOKEN_OR_ESCAPE_PATTERN.source, 'g');\n const result: Descendant[] = [];\n let lastIndex = 0;\n let match = re.exec(text);\n while (match !== null) {\n const startIdx = match.index;\n const fullMatch = match[0];\n const name = match[1];\n if (startIdx > lastIndex) {\n result.push({ text: text.slice(lastIndex, startIdx), ...marks });\n }\n if (name === undefined) {\n // Escaped dollar: raw mode shows `$$` (editable), preview shows `$` (resolved).\n // isRawToken records the mode so a merged run of escapes serializes correctly.\n result.push({\n text: displayTextForEscapedDollar(nameToValue),\n ...marks,\n isEscapedDollar: true,\n isRawToken: !nameToValue,\n });\n } else {\n result.push({\n text: displayTextForToken(name, nameToValue),\n ...marks,\n tokenName: name,\n isRawToken: !nameToValue,\n });\n }\n lastIndex = startIdx + fullMatch.length;\n match = re.exec(text);\n }\n if (result.length === 0) return [textNode];\n if (lastIndex < text.length) {\n result.push({ text: text.slice(lastIndex), ...marks });\n }\n return result;\n}\n\n/** Displayed text for a token: resolved value in preview mode, else raw pattern. */\nfunction displayTextForToken(name: string, nameToValue?: Map<string, string>): string {\n const value = nameToValue?.get(name);\n return value !== undefined && value !== '' ? value : `$${name}$`;\n}\n\n/** Displayed text for an escaped dollar: raw `$$` (editable) in raw mode, resolved `$` in preview mode. */\nfunction displayTextForEscapedDollar(nameToValue?: Map<string, string>): string {\n return nameToValue ? '$' : '$$';\n}\n\nexport interface TokenMapResult {\n /** Map of token NAME -> resolved value (1:1, unambiguous). */\n nameToValue: Map<string, string>;\n /** The raw richTextContent (with $token$ patterns), derived from token metadata. */\n rawContent: string | null;\n}\n\nconst EMPTY_MAP = new Map<string, string>();\n\n/**\n * Derive the name -> value map and raw content from framework token metadata\n * (injected via `tokenMetadataProp`). Memoized on the metadata + resolved content.\n */\nexport function useTokenMap(\n resolvedContent: string,\n richTextTokenMetadata?: RichTextTokenMetadata | null\n): TokenMapResult {\n const contentMetadata = richTextTokenMetadata?.richTextContent ?? null;\n\n // Serialize to detect changes without creating a new Map on every render.\n const serialized = contentMetadata ? JSON.stringify(contentMetadata) : null;\n const resultRef = useRef<{\n nameToValue: Map<string, string>;\n rawContent: string;\n reconciled: boolean;\n } | null>(null);\n const prevSerializedRef = useRef<string | null>(null);\n const prevResolvedRef = useRef<string>('');\n\n if (serialized !== prevSerializedRef.current || resolvedContent !== prevResolvedRef.current) {\n prevSerializedRef.current = serialized;\n prevResolvedRef.current = resolvedContent;\n if (contentMetadata) {\n const next = normalizeTokenMetadata(contentMetadata, resolvedContent);\n // When metadata lags a just-changed token VALUE, the guard falls back to resolvedContent,\n // flashing the resolved value in edit mode. Keep the last good raw content until metadata\n // arrives -- but ONLY for value changes; a STRUCTURE change means the old raw is stale.\n const canReuseStale =\n !next.reconciled &&\n resultRef.current != null &&\n isValueOnlyChange(resultRef.current.rawContent, resolvedContent);\n resultRef.current = canReuseStale\n ? { ...next, rawContent: (resultRef.current as { rawContent: string }).rawContent }\n : next;\n } else {\n resultRef.current = null;\n }\n }\n\n const nameToValue = resultRef.current?.nameToValue ?? EMPTY_MAP;\n const rawContent = resultRef.current?.rawContent ?? null;\n\n return { nameToValue, rawContent };\n}\n", "/**\n * Slate.js utility functions for PureRichText\n */\n\nimport {\n Editor,\n Transforms,\n Element as SlateElement,\n Text,\n Node as SlateNode,\n Range,\n Descendant,\n Point,\n} from 'slate';\nimport DOMPurify from 'dompurify';\nimport {\n CustomElement,\n CustomText,\n TextAlign,\n MarkType,\n EMPTY_SLATE_VALUE,\n FONT_FAMILY_WITH_FALLBACKS,\n} from '../types';\nimport { TOKEN_PATTERN } from '../hooks/useTokenMap';\nimport { isMouseSelecting } from '../activeInstance';\n\n// Reused across htmlToSlate calls; DOMParser is stateless between parses.\nconst sharedDomParser = new DOMParser();\n\n// DOMPurify's default URI allow-list plus `file:` (else local-file hrefs are stripped), still\n// blocking javascript:/data:/vbscript:. Built from parts to keep the literal's complexity low.\nconst ALLOWED_URI_SCHEMES = ['ftps?', 'https?', 'mailto', 'tel', 'callto', 'sms', 'cid', 'xmpp', 'file'];\nconst ALLOWED_URI_REGEXP = new RegExp(\n String.raw`^(?:(?:${ALLOWED_URI_SCHEMES.join('|')}):|[^a-z]|[a-z+.-]+(?:[^a-z+.\\-:]|$))`,\n 'i'\n);\n\n// ============================================\n// Safe selection utilities\n// ============================================\n\n/**\n * Nearest in-widget scrollable ancestor of `el` (overflow auto/scroll, content taller\n * than box). Returns null at body/root so we never resolve a page-level scroller.\n */\nfunction findInWidgetScroller(el: HTMLElement | null): HTMLElement | null {\n let node = el?.parentElement ?? null;\n while (node && node !== document.body && node !== document.documentElement) {\n const { overflowY } = globalThis.getComputedStyle(node);\n if ((overflowY === 'auto' || overflowY === 'scroll') && node.scrollHeight > node.clientHeight) {\n return node;\n }\n node = node.parentElement;\n }\n return null;\n}\n\n/**\n * True when content overflows its in-widget scroll container. Gates the click-to-end-of-\n * content caret jump: harmless when everything fits, disorienting when scrollable.\n */\nexport function editorContentOverflows(editableEl: HTMLElement | null): boolean {\n return findInWidgetScroller(editableEl) !== null;\n}\n\n/**\n * Scroll the caret into view within the editor's own scroll container only. Replaces\n * slate-react's default, which walks ancestors to the page and scrolls the whole dashboard\n * on programmatic selection changes; bounding it stops the \"page jumps around\" behavior.\n */\nexport function scrollCaretWithinEditor(editor: Editor, domRange: globalThis.Range): void {\n // Mouse clicks an on-screen target, so any caret-scroll it provokes can only jump the\n // view away from the click. Never auto-scroll during a press/drag.\n if (isMouseSelecting()) return;\n // Match the default: only adjust for a collapsed caret, not drag selections.\n const { selection } = editor;\n if (selection && !Range.isCollapsed(selection)) return;\n if (typeof domRange.getBoundingClientRect !== 'function') return;\n\n const leafEl = domRange.startContainer.parentElement;\n const scroller = findInWidgetScroller(leafEl);\n if (!scroller) return;\n\n const caret = domRange.getBoundingClientRect();\n const box = scroller.getBoundingClientRect();\n if (caret.top < box.top) {\n scroller.scrollTop -= box.top - caret.top;\n } else if (caret.bottom > box.bottom) {\n scroller.scrollTop += caret.bottom - box.bottom;\n }\n}\n\n/**\n * Select the end of the document, silently catching errors from empty/invalid content.\n */\nexport function safeSelectEnd(editor: Editor): void {\n try {\n const end = Editor.end(editor, []);\n Transforms.select(editor, end);\n } catch {\n // ignore - content may be empty or paths invalid\n }\n}\n\n/**\n * Focus the framework's select-outline so Escape/Cmd+A keyboard nav keeps a target,\n * suppressing the native focus ring (a doubled border over the framework's outline).\n */\nexport function focusSelectOutline(fromEl: HTMLElement | null | undefined): void {\n const selectOutline = fromEl?.closest<HTMLElement>('[data-test=\"select-outline\"]');\n if (!selectOutline) return;\n if (!selectOutline.getAttribute('tabindex')) {\n selectOutline.setAttribute('tabindex', '-1');\n }\n selectOutline.style.outline = 'none';\n selectOutline.focus({ preventScroll: true });\n}\n\n/**\n * Deselect the editor, silently catching errors from stale selection state.\n */\nexport function safeDeselect(editor: Editor): void {\n try {\n Transforms.deselect(editor);\n } catch {\n // ignore - selection may already be null or paths stale\n }\n}\n\n// ============================================\n// Mark (inline formatting) utilities\n// ============================================\n\nexport function isMarkActive(editor: Editor, format: MarkType): boolean {\n // Editor.marks() returns pending marks or reads from the document -- the source of\n // truth for whether a mark is active, matching Slate's addMark/removeMark.\n const marks = Editor.marks(editor);\n return marks !== null && Boolean(marks[format]);\n}\n\nexport function toggleMark(editor: Editor, format: MarkType): void {\n const isActive = isMarkActive(editor, format);\n if (isActive) {\n Editor.removeMark(editor, format);\n } else {\n Editor.addMark(editor, format, true);\n }\n}\n\n// ============================================\n// Block (paragraph-level) utilities\n// ============================================\n\n// Helper: Save selection, run function, restore selection\nfunction withSelectionRestore(editor: Editor, fn: () => void): void {\n const saved = editor.selection ? structuredClone(editor.selection) : null;\n fn();\n if (saved) {\n try {\n Transforms.select(editor, saved);\n } catch {\n // Selection restoration failed\n }\n }\n}\n\nexport function getBlockAlignment(editor: Editor): TextAlign {\n const { selection } = editor;\n if (!selection) return 'left';\n\n // First, check if we're in a list item\n const [listItemMatch] = Array.from(\n Editor.nodes(editor, {\n at: Editor.unhangRange(editor, selection),\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === 'list-item',\n })\n );\n\n if (listItemMatch) {\n const [node] = listItemMatch;\n return (node as CustomElement).align || 'left';\n }\n\n // Otherwise, get the first block element's alignment\n const [match] = Array.from(\n Editor.nodes(editor, {\n at: Editor.unhangRange(editor, selection),\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n),\n })\n );\n\n if (match) {\n const [node] = match;\n return (node as CustomElement).align || 'left';\n }\n\n return 'left';\n}\n\n/**\n * Toggle alignment for current block\n * For lists, apply alignment to list items rather than the list container\n */\nexport function toggleAlignment(editor: Editor, align: TextAlign): void {\n const { selection } = editor;\n if (!selection) return;\n\n withSelectionRestore(editor, () => {\n // Alignment belongs on list-item/paragraph nodes, not list containers.\n Transforms.setNodes<SlateElement>(\n editor,\n { align },\n {\n match: n =>\n !Editor.isEditor(n) &&\n SlateElement.isElement(n) &&\n Editor.isBlock(editor, n) &&\n n.type !== 'bulleted-list' &&\n n.type !== 'numbered-list',\n }\n );\n });\n}\n\nexport function getBlockLineHeight(editor: Editor): string {\n const { selection } = editor;\n if (!selection) return '1.5';\n\n const [match] = Array.from(\n Editor.nodes(editor, {\n at: Editor.unhangRange(editor, selection),\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n),\n })\n );\n\n if (match) {\n const [node] = match;\n return (node as CustomElement).lineHeight || '1.5';\n }\n\n return '1.5';\n}\n\n/**\n * Set line height for current block(s)\n * Applies to all paragraphs that contain any part of the selection\n */\nexport function setBlockLineHeight(editor: Editor, lineHeight: string): void {\n const { selection } = editor;\n if (!selection) return;\n\n withSelectionRestore(editor, () => {\n // Use unhangRange to properly handle selections that span multiple blocks\n const at = Editor.unhangRange(editor, selection);\n\n Transforms.setNodes<SlateElement>(\n editor,\n { lineHeight },\n {\n at,\n match: n =>\n !Editor.isEditor(n) &&\n SlateElement.isElement(n) &&\n Editor.isBlock(editor, n) &&\n isLeafBlock(editor, n),\n }\n );\n });\n}\n\n/**\n * Check if currently in a list\n */\nexport function isListActive(editor: Editor, listType: 'bulleted-list' | 'numbered-list'): boolean {\n const { selection } = editor;\n if (!selection) return false;\n\n const [match] = Array.from(\n Editor.nodes(editor, {\n at: Editor.unhangRange(editor, selection),\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === listType,\n })\n );\n\n return !!match;\n}\n\nexport function toggleList(editor: Editor, listType: 'bulleted-list' | 'numbered-list'): void {\n const { selection } = editor;\n if (!selection) return;\n\n const isActive = isListActive(editor, listType);\n const isList = listType === 'bulleted-list' || listType === 'numbered-list';\n\n Transforms.unwrapNodes(editor, {\n match: n =>\n !Editor.isEditor(n) &&\n SlateElement.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n split: true,\n });\n\n let newType: string;\n if (isActive) {\n newType = 'paragraph';\n } else if (isList) {\n newType = 'list-item';\n } else {\n newType = listType;\n }\n\n Transforms.setNodes<SlateElement>(editor, {\n type: newType as CustomElement['type'],\n });\n\n if (!isActive && isList) {\n const block: CustomElement = { type: listType, children: [] };\n Transforms.wrapNodes(editor, block);\n }\n\n // Don't manually restore selection - let Slate handle it naturally\n // The saved selection path becomes invalid after unwrap/wrap operations\n}\n\nexport function getListType(editor: Editor): 'unordered' | 'ordered' | null {\n if (isListActive(editor, 'bulleted-list')) return 'unordered';\n if (isListActive(editor, 'numbered-list')) return 'ordered';\n return null;\n}\n\n// ============================================\n// Link utilities\n// ============================================\n\nexport function isLinkActive(editor: Editor): boolean {\n const [link] = Editor.nodes(editor, {\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === 'link',\n });\n return !!link;\n}\n\nexport function getSelectedText(editor: Editor): string {\n if (!editor.selection || Range.isCollapsed(editor.selection)) return '';\n return SlateNode.string({ children: Array.from(Editor.fragment(editor, editor.selection)) } as SlateNode);\n}\n\nexport function getActiveLink(editor: Editor): { url: string; text: string } | null {\n const [link] = Editor.nodes(editor, {\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === 'link',\n });\n\n if (link) {\n const [node] = link;\n const element = node as CustomElement;\n const text = SlateNode.string(element);\n return { url: element.url || '', text };\n }\n\n return null;\n}\n\n/**\n * Extract plain text from a Slate node tree. Used for screenreader content.\n */\nexport function slateToPlainText(nodes: Descendant[]): string {\n return SlateNode.string({ children: nodes } as SlateNode);\n}\n\n/**\n * Replace `$token$` patterns in a link URL with resolved values. The token pipeline only\n * rewrites text nodes, not `url` attributes, so an href stays literally `$token$`; resolve\n * it here or the browser treats `$url$` as a relative path.\n */\nexport function resolveUrlTokens(url: string, nameToValue?: Map<string, string>): string {\n if (!nameToValue || nameToValue.size === 0) return url;\n return url.replace(TOKEN_PATTERN, (match, name: string) => nameToValue.get(name) ?? match);\n}\n\n/**\n * Resolve a link URL to a browser href: resolve $token$ then normalize. Schemed values\n * are kept; a bare domain gets https:// so it doesn't open relative to the current page.\n */\nexport function resolveLinkHref(url: string, nameToValue?: Map<string, string>): string {\n return normalizeUrl(resolveUrlTokens(url, nameToValue));\n}\n\n// Schemes that execute script when opened as an href -- never render these.\nconst DANGEROUS_URL_SCHEMES = new Set(['javascript', 'data', 'vbscript']);\n\n// True when `value` parses as an openable URL. Guards against bare inputs still invalid\n// after https:// prefix (e.g. \"#2E8B57\" -> empty host) that throw in window.open.\nexport function isOpenableUrl(value: string): boolean {\n try {\n // eslint-disable-next-line no-new\n new URL(value);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function normalizeUrl(url: string): string {\n const trimmed = url.trim();\n if (!trimmed) return trimmed;\n // Leave already-schemed URLs untouched; only bare inputs need https://. Scheme charset\n // excludes dots so \"host.com:8080\" stays scheme-less and prefixed, matching browsers.\n const schemeMatch = /^([a-z][a-z0-9+-]*):/i.exec(trimmed);\n if (schemeMatch) {\n // Drop executable schemes (javascript:/data:); render time bypasses DOMPurify.\n if (DANGEROUS_URL_SCHEMES.has(schemeMatch[1].toLowerCase())) return '';\n return trimmed;\n }\n // A `$token$` resolves later to a full URL; prefixing here would mangle the result.\n if (/\\$[^$]+\\$/.test(trimmed)) {\n return trimmed;\n }\n // Fragment/query/path-relative hrefs are relative references -- leave them honest rather\n // than manufacturing a bogus absolute URL; broken-link check surfaces unopenable values.\n if (/^[#?/]/.test(trimmed)) {\n return trimmed;\n }\n return `https://${trimmed}`;\n}\n\n/**\n * Strip token-identity marks (tokenName/tokenOccurrence/isRawToken/isEscapedDollar) -- these are identity,\n * not styling, so inheriting them onto new link text would keep resolving the old token.\n * The pipeline re-derives identity from raw text.\n */\nfunction stripTokenMarks(marks: Partial<CustomText> | null): Partial<CustomText> | null {\n if (!marks) return marks;\n const styleMarks = { ...marks };\n delete styleMarks.tokenName;\n delete styleMarks.tokenOccurrence;\n delete styleMarks.isRawToken;\n delete styleMarks.isEscapedDollar;\n return styleMarks;\n}\n\n/**\n * Insert or update a link\n */\nexport function insertLink(editor: Editor, url: string, text?: string): void {\n if (isLinkActive(editor)) {\n unwrapLink(editor);\n }\n\n const { selection } = editor;\n if (!selection) return;\n\n const normalizedUrl = normalizeUrl(url);\n const isCollapsed = Range.isCollapsed(selection);\n\n // For collapsed selections, inherit current styling marks (not identity marks)\n // so the link text matches the insertion point.\n let linkChild: CustomText = { text: text || normalizedUrl };\n if (isCollapsed) {\n const marks = stripTokenMarks(Editor.marks(editor));\n if (marks) {\n linkChild = { ...linkChild, ...marks };\n }\n }\n\n const link: CustomElement = {\n type: 'link',\n url: normalizedUrl,\n children: isCollapsed ? [linkChild] : [],\n };\n\n if (isCollapsed) {\n // Capture marks before insertion so we can restore them after\n const marksBeforeInsert = stripTokenMarks(Editor.marks(editor));\n Transforms.insertNodes(editor, link);\n // Move cursor to after the link so the next typed character is outside it\n Transforms.move(editor, { unit: 'offset' });\n // Restore marks so text typed after the link inherits the same styles\n if (marksBeforeInsert) {\n Object.entries(marksBeforeInsert).forEach(([key, value]) => {\n if (value !== undefined && value !== null && key !== 'text') {\n Editor.addMark(editor, key, value);\n }\n });\n }\n } else {\n // Replace the selected text with the new link text if provided and different\n if (text) {\n Transforms.insertText(editor, text);\n // Re-select the newly inserted text\n if (!editor.selection) return;\n const { anchor } = editor.selection;\n Transforms.select(editor, {\n anchor: { path: anchor.path, offset: anchor.offset - text.length },\n focus: anchor,\n });\n // Drop token-identity marks so new text is re-tokenized from its raw content.\n Editor.removeMark(editor, 'tokenName');\n Editor.removeMark(editor, 'isRawToken');\n Editor.removeMark(editor, 'isEscapedDollar');\n }\n Transforms.wrapNodes(editor, link, { split: true });\n Transforms.collapse(editor, { edge: 'end' });\n }\n}\n\n/**\n * Remove link\n */\nexport function unwrapLink(editor: Editor): void {\n Transforms.unwrapNodes(editor, {\n match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === 'link',\n });\n}\n\n// ============================================\n// Style extraction utilities\n// ============================================\n\n// Helper: Build a mark object from a node\nfunction buildMarkObject(node: any): Partial<CustomText> {\n return {\n bold: !!node.bold,\n italic: !!node.italic,\n underline: !!node.underline,\n strikethrough: !!node.strikethrough,\n color: node.color,\n backgroundColor: node.backgroundColor,\n fontSize: node.fontSize,\n fontFamily: node.fontFamily,\n };\n}\n\n// Helper: Extract marks from text node by path traversal\nfunction extractNodeMarksByPath(editor: Editor, path: number[]): Partial<CustomText> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let current: any = editor;\n for (const index of path) {\n if (current.children && Array.isArray(current.children)) {\n current = current.children[index];\n } else {\n break;\n }\n }\n\n if (current && typeof current.text === 'string') {\n return buildMarkObject(current);\n }\n } catch {\n // Path traversal failed\n }\n return {};\n}\n\n// Helper: Extract marks using Editor.leaf\nfunction extractNodeMarksByLeaf(editor: Editor, point: Point): Partial<CustomText> {\n try {\n const [leaf] = Editor.leaf(editor, point);\n if (leaf) {\n return buildMarkObject(leaf);\n }\n } catch {\n // Editor.leaf failed\n }\n return {};\n}\n\n// Helper: Get marks from the actual text node at cursor\nfunction getNodeMarks(editor: Editor): Partial<CustomText> {\n if (!editor.selection) return {};\n\n const { path } = editor.selection.focus;\n let marks = extractNodeMarksByPath(editor, path);\n\n // Fallback to Editor.leaf if path traversal didn't work\n if (Object.keys(marks).length === 0) {\n marks = extractNodeMarksByLeaf(editor, editor.selection.focus);\n }\n\n return marks;\n}\n\n// Helper: Get pending marks for new text. hasPendingMarks is true when editor.marks is a\n// non-null object (user explicitly set/removed marks); it's null after cursor moves.\nfunction getPendingMarks(editor: Editor): { marks: Partial<CustomText>; hasPendingMarks: boolean } {\n try {\n // editor.marks pending store: null = use leaf, {} = user explicitly cleared marks\n const internalMarks = (editor as Editor & { marks: Partial<CustomText> | null }).marks;\n if (internalMarks !== null && internalMarks !== undefined) {\n return { marks: internalMarks as Partial<CustomText>, hasPendingMarks: true };\n }\n return { marks: {}, hasPendingMarks: false };\n } catch {\n return { marks: {}, hasPendingMarks: false };\n }\n}\n\n// Helper: Merge node marks with pending marks. When hasPendingMarks, boolean marks absent\n// from pendingMarks were explicitly removed and are treated as false, not inherited.\nfunction mergeMarks(\n nodeMarks: Partial<CustomText>,\n pendingMarksResult: { marks: Partial<CustomText>; hasPendingMarks: boolean }\n): Partial<CustomText> {\n const { marks: pendingMarks, hasPendingMarks } = pendingMarksResult;\n const marks: Partial<CustomText> = { ...nodeMarks };\n\n // Pending exists = full source of truth for booleans (absent key = removed).\n if (hasPendingMarks) {\n marks.bold = pendingMarks.bold ?? false;\n marks.italic = pendingMarks.italic ?? false;\n marks.underline = pendingMarks.underline ?? false;\n marks.strikethrough = pendingMarks.strikethrough ?? false;\n } else {\n // No pending marks \u2014 keep node marks for booleans (reading existing text)\n if (pendingMarks.bold !== undefined) marks.bold = pendingMarks.bold;\n if (pendingMarks.italic !== undefined) marks.italic = pendingMarks.italic;\n if (pendingMarks.underline !== undefined) marks.underline = pendingMarks.underline;\n if (pendingMarks.strikethrough !== undefined) marks.strikethrough = pendingMarks.strikethrough;\n }\n\n // Non-boolean marks always override when explicitly set\n if (pendingMarks.color !== undefined) marks.color = pendingMarks.color;\n if (pendingMarks.backgroundColor !== undefined) marks.backgroundColor = pendingMarks.backgroundColor;\n if (pendingMarks.fontSize !== undefined) marks.fontSize = pendingMarks.fontSize;\n if (pendingMarks.fontFamily !== undefined) marks.fontFamily = pendingMarks.fontFamily;\n\n return marks;\n}\n\n/** Collect unique text-level style values from non-whitespace text nodes. */\nfunction collectTextStyles(editor: Editor, selection: Range) {\n const colors = new Set<string>();\n const bgColors = new Set<string>();\n const fontSizes = new Set<string>();\n const fontFamilies = new Set<string>();\n\n for (const [node] of Editor.nodes(editor, {\n at: selection,\n match: n => Text.isText(n),\n })) {\n const textNode = node;\n if (textNode.text && textNode.text.trim().length > 0) {\n colors.add(textNode.color || '');\n bgColors.add(textNode.backgroundColor || '');\n fontSizes.add(textNode.fontSize || '');\n const normalizedFont = textNode.fontFamily\n ? normalizeFontFamilyName(textNode.fontFamily) || ''\n : '';\n fontFamilies.add(normalizedFont);\n }\n }\n\n return { colors, bgColors, fontSizes, fontFamilies };\n}\n\n/** True when every child of the element is inline (text or inline element). */\nfunction isLeafBlock(editor: Editor, node: SlateElement): boolean {\n return node.children.every(child => Text.isText(child) || editor.isInline(child));\n}\n\n/** Collect unique block-level line height values, normalized to avoid \"1.5\" vs \"1.50\". */\nfunction collectBlockLineHeights(editor: Editor, selection: Range): Set<string> {\n const lineHeights = new Set<string>();\n for (const [node] of Editor.nodes(editor, {\n at: Editor.unhangRange(editor, selection),\n match: n =>\n !Editor.isEditor(n) &&\n SlateElement.isElement(n) &&\n Editor.isBlock(editor, n) &&\n isLeafBlock(editor, n),\n })) {\n const blockNode = node as CustomElement;\n const lh = Number.parseFloat(blockNode.lineHeight || '1.5');\n lineHeights.add(Number.isNaN(lh) ? '1.5' : String(lh));\n }\n return lineHeights;\n}\n\n// Helper: Check if selection has mixed style values\nfunction checkMixedStyles(editor: Editor, selection: Range) {\n if (Range.isCollapsed(selection)) return undefined;\n\n const { colors, bgColors, fontSizes, fontFamilies } = collectTextStyles(editor, selection);\n const lineHeights = collectBlockLineHeights(editor, selection);\n\n const mixed: Record<string, boolean> = {};\n if (colors.size > 1) mixed.color = true;\n if (bgColors.size > 1) mixed.backgroundColor = true;\n if (fontSizes.size > 1) mixed.fontSize = true;\n if (fontFamilies.size > 1) mixed.fontFamily = true;\n if (lineHeights.size > 1) mixed.lineHeight = true;\n\n return Object.keys(mixed).length > 0 ? mixed : undefined;\n}\n\n// Helper: Normalize font family to base name\nfunction normalizeFontFamilyName(fontFamily: string | undefined): string | null {\n if (typeof fontFamily !== 'string') return null;\n\n // Remove quotes and normalize whitespace for comparison\n const normalizeForComparison = (font: string): string => {\n return font.replaceAll(/[\"']/g, '').trim().toLowerCase();\n };\n\n const normalizedInput = normalizeForComparison(fontFamily);\n\n // Try to match against known fallback patterns\n const matchingFont = Object.entries(FONT_FAMILY_WITH_FALLBACKS).find(([baseName, fullValue]) => {\n const normalizedFull = normalizeForComparison(fullValue);\n const normalizedBase = normalizeForComparison(baseName);\n\n // Check if input matches the full fallback string or just the base name\n return normalizedInput === normalizedFull || normalizedInput === normalizedBase;\n });\n\n return matchingFont ? matchingFont[0] : fontFamily.split(',')[0].trim().replaceAll(/[\"']/g, '');\n}\n\n/**\n * Get current text styles at cursor/selection\n */\nexport function getCurrentStyles(editor: Editor): {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikethrough: boolean;\n color: string | null;\n backgroundColor: string | null;\n fontSize: string | null;\n fontFamily: string | null;\n textAlign: TextAlign;\n lineHeight: string | null;\n listType: 'unordered' | 'ordered' | null;\n isMixed?: {\n color?: boolean;\n backgroundColor?: boolean;\n fontSize?: boolean;\n fontFamily?: boolean;\n lineHeight?: boolean;\n };\n} {\n // Get marks from text node and pending marks\n const nodeMarks = getNodeMarks(editor);\n const pendingMarksResult = getPendingMarks(editor);\n const marks = mergeMarks(nodeMarks, pendingMarksResult);\n\n // Check for mixed styles in selection\n const isMixed = editor.selection ? checkMixedStyles(editor, editor.selection) : undefined;\n\n return {\n bold: Boolean(marks.bold),\n italic: Boolean(marks.italic),\n underline: Boolean(marks.underline),\n strikethrough: Boolean(marks.strikethrough),\n color: typeof marks.color === 'string' ? normalizeColor(marks.color) : null,\n backgroundColor:\n typeof marks.backgroundColor === 'string' ? normalizeColor(marks.backgroundColor) : null,\n fontSize: typeof marks.fontSize === 'string' ? marks.fontSize : null,\n fontFamily: normalizeFontFamilyName(marks.fontFamily),\n textAlign: getBlockAlignment(editor),\n lineHeight: getBlockLineHeight(editor),\n listType: getListType(editor),\n isMixed,\n };\n}\n\n// ============================================\n// HTML conversion utilities\n// ============================================\n\n/**\n * Convert Slate value to HTML\n */\nexport function slateToHtml(value: Descendant[]): string {\n // Escape HTML special characters\n const escapeHtml = (text: string): string => {\n return text.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;');\n };\n\n // Build inline styles for text nodes\n const buildTextStyles = (node: CustomText): string[] => {\n const styles: string[] = [];\n if (node.color) styles.push(`color: ${node.color}`);\n if (node.backgroundColor && node.backgroundColor !== 'transparent') {\n styles.push(`background-color: ${node.backgroundColor}`);\n }\n if (node.fontSize) styles.push(`font-size: ${node.fontSize}`);\n if (node.fontFamily) styles.push(`font-family: ${node.fontFamily}`);\n return styles;\n };\n\n // Apply text formatting tags\n const applyTextFormatting = (text: string, node: CustomText): string => {\n let result = text;\n if (node.bold) result = `<strong>${result}</strong>`;\n if (node.italic) result = `<em>${result}</em>`;\n if (node.underline) result = `<u>${result}</u>`;\n if (node.strikethrough) result = `<s>${result}</s>`;\n return result;\n };\n\n // Serialize text node. Empty text with inline styles emits an empty styled <span> so\n // marks survive the round-trip (else Enter after a styled list item drops them on save).\n const serializeTextNode = (node: CustomText): string => {\n const styles = buildTextStyles(node);\n // Token nodes serialize to raw `$name$` (from tokenName, the authoritative identity).\n let text = node.tokenName ? `$${node.tokenName}$` : node.text;\n // Pristine escaped-dollar re-emits `$$` per escape. Count by mode (raw shows `$$` each,\n // preview `$` each); if edited (not all `$`), fall through to literal text.\n if (node.isEscapedDollar && /^\\$+$/.test(node.text)) {\n const escapeCount = node.isRawToken ? node.text.length / 2 : node.text.length;\n text = '$$'.repeat(escapeCount);\n }\n if (!text) {\n return styles.length > 0 ? `<span style=\"${styles.join('; ')}\"></span>` : '';\n }\n\n text = escapeHtml(text);\n text = applyTextFormatting(text, node);\n\n if (styles.length > 0) {\n text = `<span style=\"${styles.join('; ')}\">${text}</span>`;\n }\n\n return text;\n };\n\n // Build block-level style attribute\n const buildBlockStyleAttr = (element: CustomElement): string => {\n const styles: string[] = [];\n if (element.align) styles.push(`text-align: ${element.align}`);\n if (element.lineHeight) styles.push(`line-height: ${element.lineHeight}`);\n return styles.length > 0 ? ` style=\"${styles.join('; ')}\"` : '';\n };\n\n // Serialize element node\n const serializeElement = (\n element: CustomElement & { children: Descendant[] },\n children: string\n ): string => {\n const styleAttr = buildBlockStyleAttr(element);\n\n switch (element.type) {\n case 'paragraph':\n // Empty paragraph -> canonical `<p>\\n</p>` (not `<br>`) so content round-trips\n // byte-identically and empty lines stay length-0 on the way back in.\n return `<p${styleAttr}>${children || '\\n'}</p>`;\n case 'bulleted-list':\n return `<ul${styleAttr}>${children}</ul>`;\n case 'numbered-list':\n return `<ol${styleAttr}>${children}</ol>`;\n case 'list-item':\n return `<li${styleAttr}>${children}</li>`;\n case 'link':\n return `<a href=\"${normalizeUrl(element.url || '') || '#'}\"${styleAttr}>${children}</a>`;\n default:\n return `<p${styleAttr}>${children}</p>`;\n }\n };\n\n const serializeNode = (node: Descendant): string => {\n if (Text.isText(node)) {\n return serializeTextNode(node);\n }\n\n const element = node as CustomElement & { children: Descendant[] };\n const children = element.children.map(serializeNode).join('');\n return serializeElement(element, children);\n };\n\n return value.map(serializeNode).join('');\n}\n\n/**\n * Convert HTML to Slate value\n *\n * Note: This is a simplified parser. Complex HTML from other approaches may not\n * render exactly the same due to Slate's block/inline model differences.\n */\nexport function htmlToSlate(html: string): Descendant[] {\n if (!html || html.trim() === '') {\n return EMPTY_SLATE_VALUE;\n }\n\n // Preserve literal angle brackets by escaping non-tag bracket sequences. Null-byte\n // placeholder sentinel can't appear in HTML, so it never collides with user text (unlike\n // the old \"__RT_ALLOWED_TAG_N__\"). Regex built at runtime for the no-control-regex lint.\n const NULL = '\\x00'; // eslint-disable-line no-control-regex\n const restorePlaceholderRe = new RegExp(String.raw`${NULL}RT(\\d+)${NULL}`, 'g');\n const escapeUnsafeAngleBrackets = (input: string): string => {\n const placeholders: string[] = [];\n const allowedTagRegex = /<\\/?(?:p|br|strong|b|em|i|u|s|strike|span|a|ul|ol|li|div|font)\\b[^>]*>/gi;\n\n const withPlaceholders = input.replace(allowedTagRegex, match => {\n const index = placeholders.push(match) - 1;\n return `${NULL}RT${index}${NULL}`;\n });\n\n const escaped = withPlaceholders.replaceAll('<', '&lt;').replaceAll('>', '&gt;');\n\n return escaped.replace(restorePlaceholderRe, (_, index: string) => {\n const parsedIndex = Number.parseInt(index, 10);\n return placeholders[parsedIndex] || '';\n });\n };\n\n // Type alias for deserialization result\n type DeserializeResult = Descendant | Descendant[] | null;\n\n const normalizedHtml = escapeUnsafeAngleBrackets(html);\n\n // Sanitize HTML first - include font tag\n const sanitized = DOMPurify.sanitize(normalizedHtml, {\n ALLOWED_TAGS: [\n 'p',\n 'br',\n 'strong',\n 'b',\n 'em',\n 'i',\n 'u',\n 's',\n 'strike',\n 'span',\n 'a',\n 'ul',\n 'ol',\n 'li',\n 'div',\n 'font',\n ],\n ALLOWED_ATTR: ['style', 'href', 'color', 'face', 'size'],\n ALLOWED_URI_REGEXP,\n });\n\n const doc = sharedDomParser.parseFromString(`<body>${sanitized}</body>`, 'text/html');\n\n // Helper to apply marks to all text children\n const applyMarksToChildren = (children: Descendant[], marks: Partial<CustomText>): Descendant[] => {\n return children.map(child => {\n if (Text.isText(child)) {\n return { ...child, ...marks };\n }\n return child;\n });\n };\n\n // Extract block-level styles from element\n const extractBlockStyles = (style: string) => {\n const alignMatch = /text-align:\\s*(left|center|right|justify)/i.exec(style);\n const align = alignMatch ? (alignMatch[1] as TextAlign) : undefined;\n const lineHeightMatch = /line-height:\\s*([^;]+)/i.exec(style);\n const lineHeight = lineHeightMatch ? lineHeightMatch[1].trim() : undefined;\n return { align, lineHeight };\n };\n\n // Extract inline styles from span element\n const extractSpanMarks = (style: string): Partial<CustomText> => {\n const marks: Partial<CustomText> = {};\n const colorMatch = /(?:^|;)\\s*color:\\s*([^;]+)/i.exec(style);\n const bgMatch = /background-color:\\s*([^;]+)/i.exec(style);\n const fontSizeMatch = /font-size:\\s*([^;]+)/i.exec(style);\n const fontFamilyMatch = /font-family:\\s*([^;]+)/i.exec(style);\n const fontWeightMatch = /font-weight:\\s*([^;]+)/i.exec(style);\n const fontStyleMatch = /font-style:\\s*([^;]+)/i.exec(style);\n const textDecorationMatch = /text-decoration:\\s*([^;]+)/i.exec(style);\n\n if (colorMatch) marks.color = colorMatch[1].trim();\n if (bgMatch) marks.backgroundColor = bgMatch[1].trim();\n if (fontSizeMatch) marks.fontSize = fontSizeMatch[1].trim();\n if (fontFamilyMatch) marks.fontFamily = fontFamilyMatch[1].trim().replaceAll(/[\"']/g, '');\n if (fontWeightMatch?.[1].trim() === 'bold') marks.bold = true;\n if (fontStyleMatch?.[1].trim() === 'italic') marks.italic = true;\n\n if (textDecorationMatch) {\n const decoration = textDecorationMatch[1].trim().toLowerCase();\n if (decoration.includes('underline')) marks.underline = true;\n if (decoration.includes('line-through')) marks.strikethrough = true;\n }\n\n return marks;\n };\n\n // Extract marks from font element\n const extractFontMarks = (element: HTMLElement): Partial<CustomText> => {\n const marks: Partial<CustomText> = {};\n const fontColor = element.getAttribute('color');\n const fontFace = element.getAttribute('face');\n if (fontColor) marks.color = fontColor;\n if (fontFace) marks.fontFamily = fontFace;\n return marks;\n };\n\n // Process children of an element\n const processChildren = (\n element: HTMLElement,\n deserializeFn: (node: ChildNode) => DeserializeResult\n ): Descendant[] => {\n let children: Descendant[] = [];\n element.childNodes.forEach(child => {\n const result = deserializeFn(child);\n if (result) {\n if (Array.isArray(result)) {\n children.push(...result);\n } else {\n children.push(result);\n }\n }\n });\n\n // Ensure we have at least one child for block elements\n if (children.length === 0) {\n children = [{ text: '' }];\n }\n\n return children;\n };\n\n // Collapse an \"empty line\" block to a length-0 text node. `<p><br></p>` and `<p>\\n</p>`\n // deserialize to a newline-only node whose literal `\\n` renders a phantom line and desyncs\n // token offsets; strip to `{ text: '' }`, preserving marks and non-newline content.\n const collapseEmptyLineChildren = (children: Descendant[]): Descendant[] => {\n if (children.length !== 1) return children;\n const [only] = children;\n if (Text.isText(only) && /^[\\n\\r]+$/.test(only.text)) {\n return [{ ...only, text: '' }];\n }\n return children;\n };\n\n // Handle different HTML tags\n const handleTag = (\n tagName: string,\n element: HTMLElement,\n children: Descendant[],\n blockStyles: { align?: TextAlign; lineHeight?: string }\n ): DeserializeResult => {\n const { align, lineHeight } = blockStyles;\n\n switch (tagName) {\n case 'body':\n case 'div':\n return children;\n\n case 'p':\n return {\n type: 'paragraph',\n align,\n lineHeight,\n children: collapseEmptyLineChildren(children),\n } as CustomElement;\n\n case 'ul':\n return { type: 'bulleted-list', align, lineHeight, children } as CustomElement;\n\n case 'ol':\n return { type: 'numbered-list', align, lineHeight, children } as CustomElement;\n\n case 'li':\n return {\n type: 'list-item',\n align,\n lineHeight,\n children: collapseEmptyLineChildren(children),\n } as CustomElement;\n\n case 'a':\n return {\n type: 'link',\n url: normalizeUrl(element.getAttribute('href') || ''),\n children,\n } as CustomElement;\n\n case 'strong':\n case 'b':\n return applyMarksToChildren(children, { bold: true });\n\n case 'em':\n case 'i':\n return applyMarksToChildren(children, { italic: true });\n\n case 'u':\n return applyMarksToChildren(children, { underline: true });\n\n case 's':\n case 'strike':\n return applyMarksToChildren(children, { strikethrough: true });\n\n case 'font':\n return applyMarksToChildren(children, extractFontMarks(element));\n\n case 'span': {\n const style = element.getAttribute('style') || '';\n return applyMarksToChildren(children, extractSpanMarks(style));\n }\n\n case 'br':\n return { text: '\\n' };\n\n default:\n return children;\n }\n };\n\n const deserialize = (el: ChildNode): DeserializeResult => {\n // Use global Node constants (not Slate's Node)\n if (el.nodeType === globalThis.Node.TEXT_NODE) {\n const text = el.textContent || '';\n if (!text) return null;\n return { text };\n }\n\n if (el.nodeType !== globalThis.Node.ELEMENT_NODE) {\n return null;\n }\n\n const element = el as HTMLElement;\n const tagName = element.tagName.toLowerCase();\n const style = element.getAttribute('style') || '';\n\n const children = processChildren(element, deserialize);\n const blockStyles = extractBlockStyles(style);\n\n return handleTag(tagName, element, children, blockStyles);\n };\n\n const result = deserialize(doc.body);\n if (!result) return EMPTY_SLATE_VALUE;\n\n const nodes = Array.isArray(result) ? result : [result];\n\n // Normalize: group consecutive text nodes into paragraphs\n const normalized: Descendant[] = [];\n let currentTextNodes: CustomText[] = [];\n\n const flushTextNodes = (): void => {\n if (currentTextNodes.length > 0) {\n normalized.push({ type: 'paragraph', children: currentTextNodes });\n currentTextNodes = [];\n }\n };\n\n for (const node of nodes) {\n if (Text.isText(node)) {\n currentTextNodes.push(node);\n } else {\n flushTextNodes();\n normalized.push(node);\n }\n }\n flushTextNodes();\n\n return normalized.length > 0 ? normalized : EMPTY_SLATE_VALUE;\n}\n\n/**\n * Normalize color to hex format\n */\nexport function normalizeColor(color: string | null | undefined): string | null {\n if (!color || color === 'transparent') return null;\n\n // Already hex\n if (color.startsWith('#')) {\n return color.toLowerCase();\n }\n\n // RGB/RGBA\n const rgbMatch = /rgba?\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/i.exec(color);\n if (rgbMatch) {\n const r = Number.parseInt(rgbMatch[1], 10);\n const g = Number.parseInt(rgbMatch[2], 10);\n const b = Number.parseInt(rgbMatch[3], 10);\n return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`.toLowerCase();\n }\n\n return color;\n}\n\n/**\n * Parse padding value to array format [top, right, bottom, left]\n */\nexport function parsePadding(\n padding: number | [number, number] | [number, number, number, number] | undefined\n): [number, number, number, number] {\n if (padding === undefined) {\n return [8, 8, 8, 8];\n }\n\n if (typeof padding === 'number') {\n return [padding, padding, padding, padding];\n }\n\n if (padding.length === 2) {\n return [padding[0], padding[1], padding[0], padding[1]];\n }\n\n return padding;\n}\n", "/**\n * Accessibility utilities for PureRichText.\n */\n\nimport type { FormatCommand } from '../types';\n\n/**\n * Generate a screenreader announcement for a format command.\n */\nexport function generateFormatAnnouncement(command: FormatCommand, value?: string): string {\n switch (command) {\n case 'bold':\n return 'Bold toggled';\n case 'italic':\n return 'Italic toggled';\n case 'underline':\n return 'Underline toggled';\n case 'strikethrough':\n return 'Strikethrough toggled';\n case 'fontSize':\n return `Font size changed to ${value}`;\n case 'fontName':\n case 'fontFamily':\n return `Font changed to ${value}`;\n case 'foreColor':\n return 'Font color changed';\n case 'backColor':\n return 'Highlight color changed';\n case 'justifyLeft':\n return 'Aligned left';\n case 'justifyCenter':\n return 'Aligned center';\n case 'justifyRight':\n return 'Aligned right';\n case 'justifyFull':\n return 'Aligned justify';\n case 'lineHeight':\n return 'Line spacing changed';\n case 'insertOrderedList':\n return 'Numbered list toggled';\n case 'insertUnorderedList':\n return 'Bulleted list toggled';\n case 'createLink':\n return 'Link inserted';\n case 'unlink':\n return 'Link removed';\n default:\n return 'Format applied';\n }\n}\n", "/**\n * PureRichText Context. activeTextStyles resolves active > user defaults > system defaults;\n * updates on cursor move or edit, and Reset restores user defaults.\n */\n\nimport React, { createContext, useContext, useCallback, useState, useRef, useMemo, useEffect } from 'react';\nimport { Editor, Range, Transforms, Element as SlateElement, Text } from 'slate';\nimport { TextStyles, DEFAULT_TEXT_STYLES, FormatCommand } from './types';\nimport {\n toggleMark,\n toggleAlignment,\n setBlockLineHeight,\n toggleList,\n getCurrentStyles,\n insertLink,\n unwrapLink,\n isLinkActive,\n getActiveLink,\n getSelectedText,\n} from './utils/slateUtils';\nimport { generateFormatAnnouncement } from './utils/a11yUtils';\n\ntype EditorWithMarks = Editor & { marks: Record<string, unknown> | null };\ntype LinkInfo = { url: string; text: string };\ntype BooleanMarkFormat = 'bold' | 'italic' | 'underline' | 'strikethrough';\ntype BoolMarkOverride = Partial<Record<BooleanMarkFormat, boolean>>;\n\nexport type ActiveTextStyles = TextStyles & {\n // Caret/selection inside a link. In active styles (not per-render) so the panel\n // re-renders when only the selection moves.\n isLink?: boolean;\n isMixed?: {\n color?: boolean;\n backgroundColor?: boolean;\n fontSize?: boolean;\n fontFamily?: boolean;\n lineHeight?: boolean;\n };\n};\n\nexport interface PureRichTextContextValue {\n // Active text styles (source of truth for editor panel)\n activeTextStyles: ActiveTextStyles;\n\n // User default styles (for reset)\n userDefaultStyles: TextStyles;\n\n // Slate editor instance\n editor: Editor | null;\n setEditor: (editor: Editor) => void;\n\n // Update active styles from cursor; pass isContentChange=true on text change to clear mark overrides.\n updateActiveStyles: (isContentChange?: boolean) => void;\n\n // Save current selection before focus leaves the editable\n saveSelection: () => void;\n\n // Format application\n applyFormat: (command: FormatCommand, value?: string) => void;\n resetToDefault: () => void;\n stepFontSize: (delta: number) => void;\n registerStepFontSize: (fn: (delta: number) => void) => void;\n stepLineSpacing: (delta: number) => void;\n registerStepLineSpacing: (fn: (delta: number) => void) => void;\n /** Register callback invoked after each applyFormat with the post-format selection. */\n registerOnFormatApplied: (fn: (selection: Editor['selection']) => void) => void;\n /** Register callback for screenreader announcements on format changes. */\n registerAnnouncement: (fn: (message: string) => void) => void;\n\n // Link helpers\n openLinkPopover: () => void;\n registerOpenLinkPopover: (fn: () => void) => void;\n isInLink: () => boolean;\n getLinkInfo: () => LinkInfo | null;\n createOrUpdateLink: (url: string, text?: string) => void;\n removeLink: () => void;\n}\n\n/**\n * Shallow-equal two ActiveTextStyles (incl. nested `isMixed`) so drag-select over\n * identically-styled text skips the no-op state update and context re-render.\n */\nfunction activeStylesEqual(a: ActiveTextStyles, b: ActiveTextStyles): boolean {\n const keys = [\n 'bold',\n 'italic',\n 'underline',\n 'strikethrough',\n 'color',\n 'backgroundColor',\n 'fontSize',\n 'fontFamily',\n 'textAlign',\n 'verticalAlign',\n 'lineHeight',\n 'listType',\n 'isLink',\n ] as const;\n for (const key of keys) {\n if (a[key] !== b[key]) return false;\n }\n const aMixed = a.isMixed;\n const bMixed = b.isMixed;\n if (aMixed === bMixed) return true;\n if (!aMixed || !bMixed) return false;\n const mixedKeys = ['color', 'backgroundColor', 'fontSize', 'fontFamily', 'lineHeight'] as const;\n return mixedKeys.every(key => aMixed[key] === bMixed[key]);\n}\n\nconst PureRichTextContext = createContext<PureRichTextContextValue | null>(null);\n\nexport function usePureRichText(): PureRichTextContextValue {\n const context = useContext(PureRichTextContext);\n if (!context) {\n throw new Error('usePureRichText must be used within a PureRichTextProvider');\n }\n return context;\n}\n\nexport function usePureRichTextOptional(): PureRichTextContextValue | null {\n return useContext(PureRichTextContext);\n}\n\ninterface PureRichTextProviderProps {\n children: React.ReactNode;\n defaultColor?: string;\n defaultBackgroundColor?: string;\n defaultFontFamily?: string;\n defaultFontSize?: string;\n defaultBold?: boolean;\n defaultItalic?: boolean;\n defaultUnderline?: boolean;\n defaultStrikethrough?: boolean;\n}\n\nexport function PureRichTextProvider({\n children,\n defaultColor,\n defaultBackgroundColor,\n defaultFontFamily,\n defaultFontSize,\n defaultBold,\n defaultItalic,\n defaultUnderline,\n defaultStrikethrough,\n}: Readonly<PureRichTextProviderProps>): JSX.Element {\n // User default styles - memoize based on props\n const userDefaultStyles: TextStyles = useMemo(\n () => ({\n ...DEFAULT_TEXT_STYLES,\n color: defaultColor || DEFAULT_TEXT_STYLES.color,\n backgroundColor: defaultBackgroundColor || DEFAULT_TEXT_STYLES.backgroundColor,\n fontFamily: defaultFontFamily || DEFAULT_TEXT_STYLES.fontFamily,\n fontSize: defaultFontSize || DEFAULT_TEXT_STYLES.fontSize,\n bold: defaultBold ?? DEFAULT_TEXT_STYLES.bold,\n italic: defaultItalic ?? DEFAULT_TEXT_STYLES.italic,\n underline: defaultUnderline ?? DEFAULT_TEXT_STYLES.underline,\n strikethrough: defaultStrikethrough ?? DEFAULT_TEXT_STYLES.strikethrough,\n }),\n [\n defaultColor,\n defaultBackgroundColor,\n defaultFontFamily,\n defaultFontSize,\n defaultBold,\n defaultItalic,\n defaultUnderline,\n defaultStrikethrough,\n ]\n );\n\n // Active text styles - starts with user defaults, updates from cursor/changes\n const [activeTextStyles, setActiveTextStyles] = useState<ActiveTextStyles>(userDefaultStyles);\n\n // Update activeTextStyles when userDefaultStyles changes (on mount or prop change)\n useEffect(() => {\n setActiveTextStyles(userDefaultStyles);\n }, [userDefaultStyles]);\n\n // Editor instance\n const editorRef = useRef<Editor | null>(null);\n\n // Saved selection, restored before applying formats when toolbar controls steal focus.\n const savedSelectionRef = useRef<Editor['selection']>(null);\n\n // Explicit boolean-mark overrides: focus restoration after a toggle nulls editor.marks, so\n // updateActiveStyles would read the unchanged leaf and revert the panel. Cleared on content change.\n const boolMarkOverrideRef = useRef<BoolMarkOverride | null>(null);\n\n const setEditor = useCallback((editor: Editor) => {\n editorRef.current = editor;\n }, []);\n\n // Save the current selection explicitly \u2014 called from handleBlur before Slate clears it\n const saveSelection = useCallback(() => {\n const editor = editorRef.current;\n if (editor?.selection) {\n savedSelectionRef.current = editor.selection;\n }\n }, []);\n\n // Resolve a boolean mark: explicit override > slate value > user default (empty editor).\n const resolveBooleanMark = useCallback(\n (\n format: BooleanMarkFormat,\n slateValue: boolean,\n hasAnyLeafContent: boolean,\n hasPendingMarks: boolean\n ): boolean => {\n // Use the applyFormat override so focus-restoration set_selection can't revert the toggle.\n if (boolMarkOverrideRef.current !== null && format in boolMarkOverrideRef.current) {\n return Boolean(boolMarkOverrideRef.current[format]);\n }\n // If there's actual content OR pending marks exist (user has made a toggle), trust slate\n if (hasAnyLeafContent || hasPendingMarks) return slateValue;\n // Empty editor with no pending marks \u2014 use user default as the \"will type\" preview\n return userDefaultStyles[format] ?? false;\n },\n [userDefaultStyles]\n );\n\n // Update active styles from Slate at cursor; isContentChange=true on a real text op\n // clears the boolean mark override once content is committed.\n const updateActiveStyles = useCallback(\n (isContentChange?: boolean) => {\n const editor = editorRef.current;\n if (!editor?.selection) {\n return;\n }\n\n // Get current styles from Slate at cursor\n const slateStyles = getCurrentStyles(editor);\n\n // editor.marks: null after cursor moves (no pending marks), else an object after add/removeMark.\n const editorWithMarks: EditorWithMarks = editor;\n const internalPendingMarks = editorWithMarks.marks;\n const hasPendingMarks = internalPendingMarks !== null && internalPendingMarks !== undefined;\n const hasAnyLeafContent = editor.children.some(\n n => SlateElement.isElement(n) && n.children.some(c => Text.isText(c) && c.text !== '')\n );\n\n // Clear the override when content actually changes (user typed, paste, etc.)\n if (isContentChange) {\n boolMarkOverrideRef.current = null;\n }\n\n const newActiveStyles: ActiveTextStyles = {\n bold: resolveBooleanMark('bold', slateStyles.bold, hasAnyLeafContent, hasPendingMarks),\n italic: resolveBooleanMark('italic', slateStyles.italic, hasAnyLeafContent, hasPendingMarks),\n underline: resolveBooleanMark(\n 'underline',\n slateStyles.underline,\n hasAnyLeafContent,\n hasPendingMarks\n ),\n strikethrough: resolveBooleanMark(\n 'strikethrough',\n slateStyles.strikethrough,\n hasAnyLeafContent,\n hasPendingMarks\n ),\n color: slateStyles.color || userDefaultStyles.color,\n backgroundColor:\n slateStyles.backgroundColor ??\n (hasAnyLeafContent || hasPendingMarks ? null : userDefaultStyles.backgroundColor),\n fontSize: slateStyles.fontSize || userDefaultStyles.fontSize,\n fontFamily: slateStyles.fontFamily || userDefaultStyles.fontFamily,\n textAlign: slateStyles.textAlign || userDefaultStyles.textAlign,\n verticalAlign: userDefaultStyles.verticalAlign,\n lineHeight: slateStyles.lineHeight || userDefaultStyles.lineHeight,\n listType: slateStyles.listType ?? userDefaultStyles.listType,\n isLink: isLinkActive(editor),\n };\n\n if (slateStyles.isMixed && Object.keys(slateStyles.isMixed).length > 0) {\n newActiveStyles.isMixed = slateStyles.isMixed;\n }\n\n // Bail on unchanged styles so React skips the re-render (avoids per-frame drag-select renders).\n setActiveTextStyles(prev => (activeStylesEqual(prev, newActiveStyles) ? prev : newActiveStyles));\n },\n [userDefaultStyles, resolveBooleanMark]\n );\n\n // Toggle a boolean mark and record an override so the panel reflects it before focus restoration reverts it.\n const toggleBooleanMark = useCallback((editor: Editor, format: BooleanMarkFormat): void => {\n toggleMark(editor, format);\n if (editor.selection && Range.isCollapsed(editor.selection)) {\n const editorWithMarks: EditorWithMarks = editor;\n const internalMarks = editorWithMarks.marks;\n const newValue = internalMarks === null ? false : Boolean(internalMarks[format]);\n boolMarkOverrideRef.current = {\n ...boolMarkOverrideRef.current,\n [format]: newValue,\n };\n }\n }, []);\n\n // Map a justify/alignment command to the Slate alignment value and apply it.\n const applyAlignmentCommand = useCallback((editor: Editor, command: FormatCommand): void => {\n const alignMap: Partial<Record<FormatCommand, 'left' | 'center' | 'right' | 'justify'>> = {\n justifyLeft: 'left',\n justifyCenter: 'center',\n justifyRight: 'right',\n justifyFull: 'justify',\n };\n const align = alignMap[command];\n if (align) toggleAlignment(editor, align);\n }, []);\n\n // Dispatch a format command to the appropriate Slate operation.\n const dispatchFormatCommand = useCallback(\n (editor: Editor, command: FormatCommand, value?: string): void => {\n const boolFormats = ['bold', 'italic', 'underline', 'strikethrough'];\n if (boolFormats.includes(command)) {\n // cast is required: FormatCommand is wider than BooleanMarkFormat; the boolFormats guard narrows at runtime but not in the type system\n toggleBooleanMark(editor, command as BooleanMarkFormat); // NOSONAR typescript:S4325 - see note above\n } else if (command === 'foreColor' && value) {\n Editor.addMark(editor, 'color', value);\n } else if (command === 'backColor' && value) {\n Editor.addMark(editor, 'backgroundColor', value);\n } else if (command === 'fontSize' && value) {\n Editor.addMark(editor, 'fontSize', value);\n } else if ((command === 'fontName' || command === 'fontFamily') && value) {\n Editor.addMark(editor, 'fontFamily', value);\n } else if (['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull'].includes(command)) {\n applyAlignmentCommand(editor, command);\n } else if (command === 'lineHeight' && value) {\n setBlockLineHeight(editor, value);\n } else if (command === 'insertUnorderedList') {\n toggleList(editor, 'bulleted-list');\n } else if (command === 'insertOrderedList') {\n toggleList(editor, 'numbered-list');\n }\n },\n [toggleBooleanMark, applyAlignmentCommand]\n );\n\n // Apply format command\n const applyFormat = useCallback(\n (command: FormatCommand, value?: string) => {\n const editor = editorRef.current;\n if (!editor) return;\n\n // Toolbar focus theft nulls editor.selection: restore last known selection. Preserve pending\n // marks since Transforms.select resets editor.marks, which would make the next toggle read stale.\n if (!editor.selection && savedSelectionRef.current) {\n const pendingMarks = editor.marks;\n Transforms.select(editor, savedSelectionRef.current);\n if (pendingMarks) {\n editor.marks = pendingMarks;\n }\n }\n\n if (!editor.selection) return;\n\n try {\n dispatchFormatCommand(editor, command, value);\n // Refresh saved selection so subsequent formats use the post-format range:\n // add/removeMark can split/merge nodes, and onDOMSelectionChange may deselect while\n // focus is on the panel (next applyFormat falls back to savedSelection).\n if (editor.selection) {\n savedSelectionRef.current = editor.selection;\n onFormatAppliedRef.current?.(editor.selection);\n }\n updateActiveStyles();\n onAnnouncementRef.current?.(generateFormatAnnouncement(command, value));\n } catch (error) /* NOSONAR typescript:S2486 - a failed format operation is intentionally a no-op; the error carries no actionable info for the user */ {\n // Silently catch errors\n }\n },\n [updateActiveStyles, dispatchFormatCommand]\n );\n\n // Mark style helpers: apply or reset style/boolean marks to editor\n const applyDefaultMarks = useCallback(\n (editor: Editor): void => {\n Editor.addMark(editor, 'color', userDefaultStyles.color);\n Editor.addMark(editor, 'backgroundColor', userDefaultStyles.backgroundColor);\n Editor.addMark(editor, 'fontSize', userDefaultStyles.fontSize);\n Editor.addMark(editor, 'fontFamily', userDefaultStyles.fontFamily);\n if (userDefaultStyles.bold) Editor.addMark(editor, 'bold', true);\n if (userDefaultStyles.italic) Editor.addMark(editor, 'italic', true);\n if (userDefaultStyles.underline) Editor.addMark(editor, 'underline', true);\n if (userDefaultStyles.strikethrough) Editor.addMark(editor, 'strikethrough', true);\n },\n [userDefaultStyles]\n );\n\n const resetCollapsedCursorMarks = useCallback(\n (editor: Editor): void => {\n Editor.removeMark(editor, 'color');\n Editor.removeMark(editor, 'backgroundColor');\n Editor.removeMark(editor, 'fontSize');\n Editor.removeMark(editor, 'fontFamily');\n applyDefaultMarks(editor);\n },\n [applyDefaultMarks]\n );\n\n // Reset to user defaults\n const resetToDefault = useCallback(() => {\n const editor = editorRef.current;\n if (!editor) return;\n\n // Restore saved selection if focus left the editable (e.g. clicking reset button)\n if (!editor.selection && savedSelectionRef.current) {\n Transforms.select(editor, savedSelectionRef.current);\n }\n\n if (!editor.selection) return;\n\n try {\n const hasSelection = !Range.isCollapsed(editor.selection);\n\n if (isLinkActive(editor)) {\n unwrapLink(editor);\n }\n\n // Remove all boolean marks first\n Editor.removeMark(editor, 'bold');\n Editor.removeMark(editor, 'italic');\n Editor.removeMark(editor, 'underline');\n Editor.removeMark(editor, 'strikethrough');\n\n if (hasSelection) {\n // For a range selection: restore all style marks and block properties\n applyDefaultMarks(editor);\n Transforms.setNodes(\n editor,\n { align: userDefaultStyles.textAlign, lineHeight: userDefaultStyles.lineHeight },\n { match: n => !Editor.isEditor(n) && SlateElement.isElement(n) }\n );\n } else {\n // For a collapsed cursor: remove all marks then apply defaults as pending marks\n resetCollapsedCursorMarks(editor);\n }\n\n setActiveTextStyles(userDefaultStyles);\n updateActiveStyles();\n } catch (error) /* NOSONAR typescript:S2486 - a failed reset is intentionally a no-op; the error carries no actionable info for the user */ {\n // Silently catch errors\n }\n }, [userDefaultStyles, applyDefaultMarks, resetCollapsedCursorMarks, updateActiveStyles]);\n\n // Link helpers\n const isInLink = useCallback(() => {\n const editor = editorRef.current;\n return editor ? isLinkActive(editor) : false;\n }, []);\n\n const getLinkInfo = useCallback((): LinkInfo | null => {\n const editor = editorRef.current;\n if (!editor) return null;\n // If cursor is inside an existing link, return its info\n const activeLink = getActiveLink(editor);\n if (activeLink) return activeLink;\n // Otherwise return selected text so the popover can prefill the link text field\n const selectedText = getSelectedText(editor);\n if (selectedText) return { url: '', text: selectedText };\n return null;\n }, []);\n\n const createOrUpdateLink = useCallback(\n (url: string, text?: string) => {\n const editor = editorRef.current;\n if (!editor) return;\n\n try {\n // Restore saved selection if focus left the editable; try/catch as savedSelectionRef\n // may be stale (e.g. after content reset via undo).\n if (!editor.selection && savedSelectionRef.current) {\n try {\n Transforms.select(editor, savedSelectionRef.current);\n } catch {\n // Stale selection \u2014 fall back to selecting the full document\n savedSelectionRef.current = null;\n Transforms.select(editor, {\n anchor: Editor.start(editor, []),\n focus: Editor.end(editor, []),\n });\n }\n }\n\n if (isLinkActive(editor)) {\n unwrapLink(editor);\n }\n insertLink(editor, url, text);\n updateActiveStyles();\n } catch (error) /* NOSONAR typescript:S2486 - a failed link operation is intentionally a no-op; the error carries no actionable info for the user */ {\n // Silently catch errors\n }\n },\n [updateActiveStyles]\n );\n\n const removeLink = useCallback(() => {\n const editor = editorRef.current;\n if (!editor) return;\n\n try {\n // Restore saved selection if focus left the editable (e.g. Cmd+K then to Remove button);\n // without a selection unwrapLink matches nothing and silently no-ops.\n if (!editor.selection && savedSelectionRef.current) {\n try {\n Transforms.select(editor, savedSelectionRef.current);\n } catch {\n return;\n }\n }\n if (!editor.selection) return;\n unwrapLink(editor);\n updateActiveStyles();\n } catch (error) /* NOSONAR typescript:S2486 - a failed unlink is intentionally a no-op; the error carries no actionable info for the user */ {\n // Silently catch errors\n }\n }, [updateActiveStyles]);\n\n // Ref-based so EditorPanel registers the popover opener and InnerEditor calls it via Cmd+K (no prop drilling).\n const openLinkPopoverRef = useRef<() => void>(() => {});\n const openLinkPopover = useCallback(() => {\n openLinkPopoverRef.current();\n }, []);\n const registerOpenLinkPopover = useCallback((fn: () => void) => {\n openLinkPopoverRef.current = fn;\n }, []);\n\n // Ref-based so EditorPanel calls stepFontSize (in InnerEditor) for per-node font size step in mixed selections.\n const stepFontSizeRef = useRef<(delta: number) => void>(() => {});\n const stepFontSize = useCallback((delta: number) => {\n stepFontSizeRef.current(delta);\n }, []);\n const registerStepFontSize = useCallback((fn: (delta: number) => void) => {\n stepFontSizeRef.current = fn;\n }, []);\n\n // Same pattern for line spacing: per-block increment/decrement in mixed selections.\n const stepLineSpacingRef = useRef<(delta: number) => void>(() => {});\n const stepLineSpacing = useCallback((delta: number) => {\n stepLineSpacingRef.current(delta);\n }, []);\n const registerStepLineSpacing = useCallback((fn: (delta: number) => void) => {\n stepLineSpacingRef.current = fn;\n }, []);\n\n // Invoked after each applyFormat with the post-format selection; PureRichText uses it to keep\n // preEditSelection current so Escape-from-panel restores the right caret.\n const onFormatAppliedRef = useRef<((selection: Editor['selection']) => void) | null>(null);\n const registerOnFormatApplied = useCallback((fn: (selection: Editor['selection']) => void) => {\n onFormatAppliedRef.current = fn;\n }, []);\n\n // Screenreader announcement callback, registered by InnerEditor.\n const onAnnouncementRef = useRef<((message: string) => void) | null>(null);\n const registerAnnouncement = useCallback((fn: (message: string) => void) => {\n onAnnouncementRef.current = fn;\n }, []);\n\n const contextValue: PureRichTextContextValue = useMemo(\n () => ({\n activeTextStyles,\n userDefaultStyles,\n editor: editorRef.current,\n setEditor,\n updateActiveStyles,\n saveSelection,\n applyFormat,\n resetToDefault,\n stepFontSize,\n registerStepFontSize,\n stepLineSpacing,\n registerStepLineSpacing,\n registerOnFormatApplied,\n registerAnnouncement,\n openLinkPopover,\n registerOpenLinkPopover,\n isInLink,\n getLinkInfo,\n createOrUpdateLink,\n removeLink,\n }),\n [\n activeTextStyles,\n userDefaultStyles,\n setEditor,\n updateActiveStyles,\n saveSelection,\n applyFormat,\n resetToDefault,\n stepFontSize,\n registerStepFontSize,\n stepLineSpacing,\n registerStepLineSpacing,\n registerOnFormatApplied,\n registerAnnouncement,\n openLinkPopover,\n registerOpenLinkPopover,\n isInLink,\n getLinkInfo,\n createOrUpdateLink,\n removeLink,\n ]\n );\n\n return <PureRichTextContext.Provider value={contextValue}>{children}</PureRichTextContext.Provider>;\n}\n", "\nimport * as defaultImport from \"@splunk/react-ui/ScreenReaderContent\";\nexport * from \"@splunk/react-ui/ScreenReaderContent\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "/**\n * FormatButton Component\n *\n * A styled button for formatting actions in the rich text editor toolbar.\n */\n\nimport React from 'react';\nimport styled from 'styled-components';\nimport { variables } from '@splunk/themes';\nimport ScreenReaderContent from '@splunk/react-ui/ScreenReaderContent';\n\nconst StyledButton = styled.button<{ $isActive?: boolean }>`\n min-width: 24px;\n height: 24px;\n width: 24px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n border: 1px solid transparent;\n background: ${props => (props.$isActive ? variables.interactiveColorOverlaySelected : 'transparent')};\n cursor: pointer;\n transition: all 0.2s ease;\n\n svg {\n fill: ${props => (props.$isActive ? variables.contentColorActive : variables.contentColorMuted)};\n width: 16px;\n height: 16px;\n transition: fill 0.2s ease;\n }\n\n &:hover {\n background: ${variables.interactiveColorOverlaySelected};\n\n svg {\n fill: ${variables.contentColorActive};\n }\n }\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n`;\n\nexport interface FormatButtonProps {\n /** Icon to display in the button */\n icon: React.ReactNode;\n /** Whether the format is currently active */\n isActive?: boolean;\n /** Click handler */\n onClick: () => void;\n /** Tooltip title */\n title: string;\n /** Accessible label for screen readers */\n ariaLabel?: string;\n /** Whether the button is disabled */\n disabled?: boolean;\n}\n\nexport const FormatButton: React.FC<FormatButtonProps> = ({\n icon,\n isActive = false,\n onClick,\n title,\n ariaLabel,\n disabled = false,\n}) => {\n const handleMouseDown = (e: React.MouseEvent): void => {\n // Prevent the button click from causing the contentEditable to lose focus\n // This preserves the selection/cursor position\n e.preventDefault();\n };\n\n return (\n <StyledButton\n $isActive={isActive}\n onClick={onClick}\n onMouseDown={handleMouseDown}\n title={title}\n type=\"button\"\n disabled={disabled}\n >\n {icon}\n {ariaLabel && <ScreenReaderContent>{ariaLabel}</ScreenReaderContent>}\n </StyledButton>\n );\n};\n\nexport default FormatButton;\n", "\nimport * as defaultImport from \"@splunk/react-ui/ControlGroup\";\nexport * from \"@splunk/react-ui/ControlGroup\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Select\";\nexport * from \"@splunk/react-ui/Select\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "/**\n * FontSelector Component\n *\n * A font family selector with support for preloaded system fonts.\n * MVP version - web fonts support will be added in future releases.\n */\n\nimport React, { useCallback } from 'react';\nimport styled from 'styled-components';\nimport ControlGroup from '@splunk/react-ui/ControlGroup';\nimport Select from '@splunk/react-ui/Select';\nimport { PRELOADED_FONTS } from '../types';\n\n// ============================================\n// Styled Components - minimal\n// ============================================\n\nconst FontSelectorContainer = styled.div`\n display: flex;\n align-items: center;\n gap: 4px;\n width: 100%;\n`;\n\nconst SelectWrapper = styled.div`\n flex: 1;\n width: 100%;\n min-width: 0;\n\n /* Target Select component wrapper */\n & > div {\n width: 100%;\n }\n\n /* Target the actual select button */\n button {\n width: 100%;\n }\n`;\n\n// ============================================\n// Component Props\n// ============================================\n\ninterface FontSelectorProps {\n value: string;\n onChange: (fontFamily: string) => void;\n onBeforeChange?: () => void;\n}\n\n// ============================================\n// Component\n// ============================================\n\nexport const FontSelector: React.FC<FontSelectorProps> = ({ value, onChange, onBeforeChange }) => {\n const handleFontChange = useCallback(\n (_e: React.SyntheticEvent, { value: val }: { value: string }) => {\n onChange(val);\n },\n [onChange]\n );\n\n // Save selection when user clicks to open the dropdown (before focus is lost)\n const handleMouseDown = useCallback(() => {\n if (onBeforeChange) {\n onBeforeChange();\n }\n }, [onBeforeChange]);\n\n // Empty value indicates mixed fonts in selection - show placeholder\n const isMixed = !value;\n const displayValue = isMixed ? '' : value;\n const placeholder = isMixed ? 'Mixed fonts' : undefined;\n\n return (\n <ControlGroup label=\"Font family\" labelPosition=\"top\">\n <FontSelectorContainer onMouseDownCapture={handleMouseDown}>\n <SelectWrapper>\n <Select\n value={displayValue}\n onChange={handleFontChange}\n placeholder={placeholder}\n style={{ width: '100%' }}\n >\n {PRELOADED_FONTS.map(font => (\n <Select.Option key={font} label={font} value={font} />\n ))}\n </Select>\n </SelectWrapper>\n </FontSelectorContainer>\n </ControlGroup>\n );\n};\n\nexport default FontSelector;\n", "\nimport * as defaultImport from \"react-dom\";\nexport * from \"react-dom\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Button\";\nexport * from \"@splunk/react-ui/Button\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/RadioBar\";\nexport * from \"@splunk/react-ui/RadioBar\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Color\";\nexport * from \"@splunk/react-ui/Color\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Text\";\nexport * from \"@splunk/react-ui/Text\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Number\";\nexport * from \"@splunk/react-ui/Number\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-ui/Popover\";\nexport * from \"@splunk/react-ui/Popover\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/Chain\";\nexport * from \"@splunk/react-icons/Chain\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/List\";\nexport * from \"@splunk/react-icons/List\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/ListNumbered\";\nexport * from \"@splunk/react-icons/ListNumbered\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextBBold\";\nexport * from \"@splunk/react-icons/TextBBold\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextIItalic\";\nexport * from \"@splunk/react-icons/TextIItalic\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextUUnderline\";\nexport * from \"@splunk/react-icons/TextUUnderline\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextSStrikethrough\";\nexport * from \"@splunk/react-icons/TextSStrikethrough\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextAlignLeft\";\nexport * from \"@splunk/react-icons/TextAlignLeft\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextAlignCenter\";\nexport * from \"@splunk/react-icons/TextAlignCenter\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextAlignRight\";\nexport * from \"@splunk/react-icons/TextAlignRight\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextAlignTop\";\nexport * from \"@splunk/react-icons/TextAlignTop\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextAlignVerticalCenter\";\nexport * from \"@splunk/react-icons/TextAlignVerticalCenter\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/TextAlignBottom\";\nexport * from \"@splunk/react-icons/TextAlignBottom\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "\nimport * as defaultImport from \"@splunk/react-icons/ArrowTurnBackLeft\";\nexport * from \"@splunk/react-icons/ArrowTurnBackLeft\";\nexport default ('default' in defaultImport ? defaultImport.default : defaultImport);\n", "import styled from 'styled-components';\nimport { variables } from '@splunk/themes';\nimport Button from '@splunk/react-ui/Button';\n\nexport const EditorContainer = styled.div`\n display: flex;\n flex-direction: column;\n width: 100%;\n max-width: 100%;\n overflow-x: hidden;\n gap: 8px;\n`;\n\nexport const Row = styled.div`\n display: flex;\n gap: 4px;\n align-items: center;\n width: 100%;\n`;\n\nexport const ColorRow = styled.div`\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 4px;\n width: 100%;\n\n /* Ensure grid children stay within bounds */\n & > * {\n min-width: 0;\n }\n\n /* Make Color component fill its container properly */\n & [data-test='color'] {\n width: 100%;\n max-width: 100%;\n\n /* Inner flex container */\n & > div {\n width: 100%;\n max-width: 100%;\n display: flex;\n\n /* Text input wrapper - fill remaining space after swatch */\n & > div:last-child {\n flex: 1 1 auto;\n min-width: 0;\n max-width: calc(100% - 40px);\n\n /* The actual input inside */\n & input {\n width: 100%;\n }\n }\n }\n }\n`;\n\nexport const ButtonRow = styled.div`\n display: flex;\n gap: 4px;\n align-items: center;\n flex-wrap: wrap;\n width: 100%;\n justify-content: space-between;\n`;\n\nexport const LineSpacingWrapper = styled.div`\n position: relative;\n width: 100%;\n\n /* Make the Number component fill the width */\n & > div {\n width: 100%;\n }\n\n /* Style the % to appear right after the number */\n & > span {\n position: absolute;\n left: 42px; /* Position right after typical 3-digit number */\n top: 50%;\n transform: translateY(-50%);\n pointer-events: none;\n color: ${variables.contentColorDefault};\n font-size: 14px;\n }\n`;\n\n// Wrapper for Color component when selection has mixed values.\n// Makes the hex input text invisible (replaced by \"Mixed\" label) while\n// keeping the swatch and input fully interactive and focusable.\nexport const MixedLabel = styled.div`\n position: absolute;\n left: 40px;\n top: 50%;\n transform: translateY(-50%);\n pointer-events: none;\n color: ${variables.contentColorDefault};\n font-size: 14px;\n`;\n\nexport const MixedColorWrapper = styled.div<{ $isMixed?: boolean }>`\n position: relative;\n\n ${props =>\n props.$isMixed &&\n `\n & [data-test=\"color\"] input {\n color: transparent;\n caret-color: transparent;\n }\n & [data-test=\"color\"] input:focus {\n color: inherit;\n caret-color: auto;\n }\n `}\n\n &:focus-within ${MixedLabel} {\n display: none;\n }\n`;\n\n// Styled button to match Figma design - square with rounded corners\nexport const FormatToggleButton = styled(Button)<{ $isActive?: boolean }>`\n && {\n min-width: 32px;\n height: 32px;\n padding: 0;\n border-radius: 8px;\n background: ${props => (props.$isActive ? variables.interactiveColorOverlaySelected : 'transparent')};\n border: 1px solid ${props => (props.$isActive ? variables.borderColor : 'transparent')};\n\n &:hover {\n background: ${variables.interactiveColorOverlayHover};\n }\n\n &:focus-visible {\n box-shadow: 0 0 0 2px ${variables.focusColor};\n }\n\n svg {\n width: 16px;\n height: 16px;\n fill: ${props => (props.$isActive ? variables.contentColorActive : variables.contentColorMuted)};\n }\n }\n`;\n\nexport const AlignmentSection = styled.div`\n display: flex;\n gap: 12px;\n width: 100%;\n`;\n\nexport const HorizontalAlignmentRadioBar = styled.div`\n flex: 4;\n min-width: 0;\n\n /* Make RadioBar fill width and buttons expand equally */\n & > div {\n width: 100%;\n\n & > label {\n flex: 1;\n }\n }\n`;\n\nexport const VerticalAlignmentRadioBar = styled.div`\n flex: 3;\n min-width: 0;\n\n /* Make RadioBar fill width and buttons expand equally */\n & > div {\n width: 100%;\n\n & > label {\n flex: 1;\n }\n }\n`;\n\nexport const LinkPopoverContent = styled.div`\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-width: 280px;\n`;\n", "// Portal target for PureRichText - portals into config panel or sidebar\nexport const getEditorPanelTarget = (): Element | null => {\n // First try config panel (from dynamic-editors richtext editor)\n const configPanelTarget = document.querySelector('[data-test=\"editor-richTextContent\"]');\n if (configPanelTarget) {\n return configPanelTarget;\n }\n // Fallback to sidebar target\n return document.querySelector('[data-test=\"editor-purerichtext\"]');\n};\n\nexport const FONT_SIZE_OPTIONS = [\n { label: 'Extra small', value: '10' },\n { label: 'Small', value: '12' },\n { label: 'Default', value: '14' },\n { label: 'Large', value: '16' },\n { label: 'Extra large', value: '20' },\n] as const;\n\nexport const getFontSizePreset = (fontSize: number): string => {\n const preset = FONT_SIZE_OPTIONS.find(p => p.value === String(fontSize));\n return preset ? preset.value : 'custom';\n};\n", "import { useCallback, useEffect, useState, useRef } from 'react';\nimport {\n focusActiveEditable,\n setSuppressBlurDeactivation,\n isSuppressBlurDeactivation,\n} from '../../activeInstance';\n\ninterface UseLinkHandlersParams {\n isInLink: (() => boolean) | undefined;\n getLinkInfo: (() => { text: string; url: string } | null) | undefined;\n createOrUpdateLink: ((url: string, text?: string) => void) | undefined;\n removeLink: (() => void) | undefined;\n}\n\n// Hook for link popover state and handlers\nexport function useLinkHandlers(handlers: UseLinkHandlersParams) {\n const { isInLink, getLinkInfo, createOrUpdateLink, removeLink } = handlers;\n const [linkPopoverOpen, setLinkPopoverOpen] = useState(false);\n const [linkText, setLinkText] = useState('');\n const [linkUrl, setLinkUrl] = useState('');\n const linkButtonRef = useRef<HTMLButtonElement>(null);\n const linkPopoverRef = useRef<HTMLDivElement>(null);\n const linkIsActive = isInLink?.() || false;\n\n const handleLinkButtonClick = useCallback(() => {\n const linkInfo = getLinkInfo?.();\n if (linkInfo) {\n setLinkText(linkInfo.text);\n setLinkUrl(linkInfo.url);\n } else {\n setLinkText('');\n setLinkUrl('');\n }\n setSuppressBlurDeactivation(true);\n setLinkPopoverOpen(true);\n }, [getLinkInfo]);\n\n const resetLinkState = useCallback(() => {\n setSuppressBlurDeactivation(false);\n setLinkPopoverOpen(false);\n setLinkText('');\n setLinkUrl('');\n }, []);\n\n const handleLinkPopoverClose = useCallback(() => {\n resetLinkState();\n setTimeout(() => {\n focusActiveEditable();\n }, 0);\n }, [resetLinkState]);\n\n const handleLinkSave = useCallback(() => {\n if (linkUrl && createOrUpdateLink) {\n createOrUpdateLink(linkUrl, linkText || undefined);\n }\n resetLinkState();\n setTimeout(() => {\n linkButtonRef.current?.focus();\n }, 0);\n }, [linkUrl, linkText, createOrUpdateLink, resetLinkState]);\n\n const handleLinkRemove = useCallback(() => {\n if (removeLink) {\n removeLink();\n }\n resetLinkState();\n setTimeout(() => {\n linkButtonRef.current?.focus();\n }, 0);\n }, [removeLink, resetLinkState]);\n\n const handleLinkKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n // Enter submits only from text inputs; on buttons let native activation fire\n // their own onClick, else Enter on Remove would run Save.\n if (e.key === 'Enter' && (e.target as HTMLElement)?.tagName === 'INPUT') {\n e.preventDefault();\n handleLinkSave();\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n e.nativeEvent.stopImmediatePropagation();\n resetLinkState();\n // Return focus to the link button in the config panel\n setTimeout(() => {\n linkButtonRef.current?.focus();\n }, 0);\n }\n },\n [handleLinkSave, resetLinkState]\n );\n\n // Auto-focus the first input when the link popover opens\n useEffect(() => {\n if (!linkPopoverOpen) return undefined;\n // The Popover renders asynchronously (portaled), so wait a frame\n const timer = setTimeout(() => {\n linkPopoverRef.current?.querySelector<HTMLInputElement>('input')?.focus();\n }, 50);\n return () => clearTimeout(timer);\n }, [linkPopoverOpen]);\n\n // Reset the global suppress flag on unmount while the popover is open, else it\n // stays true and later editor blur events are skipped.\n useEffect(\n () => () => {\n if (isSuppressBlurDeactivation()) {\n setSuppressBlurDeactivation(false);\n }\n },\n []\n );\n\n return {\n linkIsActive,\n linkPopoverOpen,\n linkPopoverRef,\n linkText,\n linkUrl,\n linkButtonRef,\n setLinkText,\n setLinkUrl,\n handleLinkButtonClick,\n handleLinkPopoverClose,\n handleLinkSave,\n handleLinkRemove,\n handleLinkKeyDown,\n };\n}\n", "import { useCallback, useEffect, useRef, useState } from 'react';\nimport { FormatCommand } from '../../types';\n\n// Hook for line spacing state and handlers\nexport function useLineSpacing(\n lineHeight: string,\n displayLineHeight: string | undefined,\n isLineHeightMixed: boolean,\n applyFormat: ((command: FormatCommand, value?: string) => void) | undefined,\n handleFormat: (command: FormatCommand, value?: string) => void,\n stepLineSpacing?: (delta: number) => void\n) {\n const [lineSpacingPercent, setLineSpacingPercent] = useState<number>(() => {\n const num = Number.parseFloat(lineHeight);\n return Number.isNaN(num) ? 100 : Math.round(num * 100);\n });\n\n // Tracks whether the user has typed a value (overrides Mixed display)\n const dirtyRef = useRef(false);\n const [isDirty, setIsDirty] = useState(false);\n\n // Sync line spacing from displayStyles or prop\n useEffect(() => {\n if (isLineHeightMixed && !dirtyRef.current) return;\n\n const lh = displayLineHeight || lineHeight;\n const num = Number.parseFloat(String(lh));\n if (!Number.isNaN(num)) {\n setLineSpacingPercent(Math.round(num * 100));\n }\n dirtyRef.current = false;\n setIsDirty(false);\n }, [displayLineHeight, lineHeight, isLineHeightMixed]);\n\n const handleLineSpacingChange = useCallback(\n (_e: unknown, data: { value?: number; reason?: 'input' | 'stepButton' }) => {\n const { value, reason } = data;\n if (value !== undefined && value !== null) {\n setLineSpacingPercent(value);\n if (reason === 'input') {\n dirtyRef.current = true;\n setIsDirty(true);\n }\n if (reason === 'stepButton' && applyFormat) {\n // When mixed, use stepLineSpacing to step each block independently\n if (isLineHeightMixed && stepLineSpacing) {\n const target = (_e as React.MouseEvent)?.currentTarget;\n const testId =\n (target as HTMLElement)?.getAttribute?.('data-test') ||\n (target as HTMLElement)?.getAttribute?.('data-testid') ||\n '';\n const isDecrement = testId === 'decrement' || testId.includes('down');\n stepLineSpacing(isDecrement ? -1 : 1);\n return;\n }\n const newLineHeight = Math.max(1, value / 100).toFixed(2);\n handleFormat('lineHeight', newLineHeight);\n }\n }\n },\n [applyFormat, handleFormat, isLineHeightMixed, stepLineSpacing]\n );\n\n const handleLineSpacingBlur = useCallback(() => {\n if (!dirtyRef.current && isLineHeightMixed) return;\n dirtyRef.current = false;\n setIsDirty(false);\n const multiplier = Math.max(1, lineSpacingPercent / 100);\n handleFormat('lineHeight', String(multiplier));\n }, [lineSpacingPercent, handleFormat, isLineHeightMixed]);\n\n // When mixed and not dirty, show undefined (placeholder \"Mixed\").\n // When dirty (user typed a value), show the typed value.\n const showMixed = isLineHeightMixed && !isDirty;\n\n return {\n lineSpacingPercent,\n showMixed,\n handleLineSpacingChange,\n handleLineSpacingBlur,\n };\n}\n", "import { useEffect } from 'react';\n\ninterface ConfigPanelFocusArgs {\n isEditMode: boolean;\n isActive: boolean;\n editorContainerRef: React.RefObject<HTMLDivElement>;\n wasMouseRef: React.MutableRefObject<boolean>;\n}\n\n/**\n * Config-panel focus behavior: tracks whether the last interaction was mouse vs keyboard\n * (so format actions only refocus the editable after a click), and traps Tab focus within\n * the panel so tabindex=\"-1\" step buttons stay reachable.\n */\nexport function useConfigPanelFocus({\n isEditMode,\n isActive,\n editorContainerRef,\n wasMouseRef,\n}: ConfigPanelFocusArgs): void {\n // Track mouse vs keyboard so refocus-on-format only fires after a click.\n useEffect(() => {\n if (!isEditMode || !isActive) return undefined;\n\n const handleMouseDown = (e: MouseEvent): void => {\n const container = editorContainerRef.current;\n if (!container) return;\n const target = e.target as HTMLElement;\n if (!container.contains(target)) return;\n // eslint-disable-next-line no-param-reassign\n wasMouseRef.current = true;\n const tag = target.tagName;\n if (tag !== 'INPUT' && tag !== 'TEXTAREA') {\n e.preventDefault();\n }\n };\n\n const handleKeyDown = (e: KeyboardEvent): void => {\n const container = editorContainerRef.current;\n if (!container) return;\n const target = e.target as HTMLElement;\n if (container.contains(target)) {\n // eslint-disable-next-line no-param-reassign\n wasMouseRef.current = false;\n }\n };\n\n document.addEventListener('mousedown', handleMouseDown, true);\n document.addEventListener('keydown', handleKeyDown, true);\n return () => {\n document.removeEventListener('mousedown', handleMouseDown, true);\n document.removeEventListener('keydown', handleKeyDown, true);\n };\n }, [isEditMode, isActive, editorContainerRef, wasMouseRef]);\n\n // Manual Tab focus management + focus ring for tabindex=\"-1\" step buttons.\n useEffect(() => {\n if (!isEditMode || !isActive) return undefined;\n\n const FOCUS_RING_ATTR = 'data-trap-focused';\n let lastFocused: HTMLElement | null = null;\n\n const applyFocusRing = (el: HTMLElement): void => {\n removeFocusRing();\n if (el.getAttribute('tabindex') === '-1') {\n el.setAttribute(FOCUS_RING_ATTR, 'true');\n // eslint-disable-next-line no-param-reassign\n el.style.outline = '2px solid #3b82f6';\n // eslint-disable-next-line no-param-reassign\n el.style.outlineOffset = '-2px';\n // eslint-disable-next-line no-param-reassign\n el.style.position = 'relative';\n // eslint-disable-next-line no-param-reassign\n el.style.zIndex = '1';\n lastFocused = el;\n }\n };\n\n const removeFocusRing = (): void => {\n if (lastFocused?.hasAttribute(FOCUS_RING_ATTR)) {\n lastFocused.removeAttribute(FOCUS_RING_ATTR);\n lastFocused.style.outline = '';\n lastFocused.style.outlineOffset = '';\n lastFocused.style.position = '';\n lastFocused.style.zIndex = '';\n lastFocused = null;\n }\n };\n\n const handleBlurCleanup = (): void => {\n removeFocusRing();\n };\n\n const getFocusableElements = (panel: HTMLElement): HTMLElement[] => {\n const selector =\n 'button:not([disabled]):not([aria-disabled=\"true\"]), ' +\n 'input:not([disabled]), ' +\n 'select:not([disabled]), ' +\n 'textarea:not([disabled]), ' +\n 'a[href]:not([disabled])';\n return Array.from(panel.querySelectorAll<HTMLElement>(selector)).filter(\n el => el.offsetParent !== null && el.offsetWidth > 0 && el.offsetHeight > 0\n );\n };\n\n // Move focus to the next/previous focusable element. At the boundary, defer to native\n // Tab (no preventDefault) so focus can reach adjacent sidebar sections.\n const moveFocus = (e: KeyboardEvent, focusable: HTMLElement[], currentIndex: number): void => {\n const backward = e.shiftKey;\n const atBoundary = backward ? currentIndex <= 0 : currentIndex >= focusable.length - 1;\n if (atBoundary) {\n removeFocusRing();\n return;\n }\n e.preventDefault();\n const nextEl = focusable[backward ? currentIndex - 1 : currentIndex + 1];\n nextEl.focus();\n applyFocusRing(nextEl);\n };\n\n const handleConfigPanelKeyDown = (e: KeyboardEvent): void => {\n const target = e.target as HTMLElement;\n\n // Escape is handled by PureRichText's document keydown handler which\n // sets isTextEditing=true before focusing. Only clean up the focus ring here.\n if (e.key === 'Escape') {\n removeFocusRing();\n return;\n }\n\n // Tab/Shift+Tab: move focus manually so tabindex=\"-1\" step buttons are reachable;\n // at the boundaries defer to native Tab to reach adjacent sidebar sections (no wrapping).\n const configPanel = editorContainerRef.current;\n if (!configPanel?.contains(target) || e.key !== 'Tab') return;\n\n const focusable = getFocusableElements(configPanel);\n if (focusable.length === 0) return;\n\n const currentIndex = focusable.indexOf(target);\n if (currentIndex === -1) {\n removeFocusRing();\n return;\n }\n moveFocus(e, focusable, currentIndex);\n };\n\n document.addEventListener('keydown', handleConfigPanelKeyDown, true);\n document.addEventListener('focusout', handleBlurCleanup, true);\n return () => {\n document.removeEventListener('keydown', handleConfigPanelKeyDown, true);\n document.removeEventListener('focusout', handleBlurCleanup, true);\n removeFocusRing();\n };\n }, [isEditMode, isActive, editorContainerRef]);\n}\n", "import { useEffect, useReducer, useRef } from 'react';\nimport { getEditorPanelTarget } from '../editorPanelUtils';\n\n/**\n * Polls for the toolbar's portal target (data-test=\"editor-purerichtext\") while in edit mode,\n * since it mounts/unmounts outside React's render cycle.\n */\nexport function usePortalTarget(isEditMode: boolean): {\n portalTargetRef: React.RefObject<HTMLElement>;\n portalReady: boolean;\n} {\n const portalTargetRef = useRef<HTMLElement | null>(null);\n // renderTick increments each time the portal target is found/cleared, triggering a re-render\n const [renderTick, forceUpdate] = useReducer((n: number) => n + 1, 0);\n const portalReady = renderTick >= 0 && portalTargetRef.current !== null;\n\n useEffect(() => {\n if (!isEditMode) {\n portalTargetRef.current = null;\n forceUpdate();\n return undefined;\n }\n\n const findTarget = (): void => {\n const target = getEditorPanelTarget();\n if (target && target !== portalTargetRef.current) {\n portalTargetRef.current = target as HTMLElement;\n forceUpdate();\n }\n };\n\n findTarget();\n const interval = setInterval(findTarget, 100);\n\n return (): void => {\n clearInterval(interval);\n portalTargetRef.current = null;\n };\n }, [isEditMode]);\n\n return { portalTargetRef, portalReady };\n}\n", "import { useEffect } from 'react';\nimport { TextAlign, VerticalAlign } from '../../types';\nimport { getFontSizePreset } from '../editorPanelUtils';\n\ninterface EditorPanelSyncArgs {\n textAlign: TextAlign | undefined;\n setAlign: (align: TextAlign) => void;\n verticalAlignProp: VerticalAlign;\n setVerticalAlign: (align: VerticalAlign) => void;\n activeFontSize: string | number | undefined;\n fontSizeDirtyRef: React.MutableRefObject<boolean>;\n setCurrentFontSize: (n: number) => void;\n setFontSizePreset: (s: string) => void;\n}\n\n/** Syncs alignment, vertical alignment, and font size state from selection/prop changes. */\nexport function useEditorPanelSync({\n textAlign,\n setAlign,\n verticalAlignProp,\n setVerticalAlign,\n activeFontSize,\n fontSizeDirtyRef,\n setCurrentFontSize,\n setFontSizePreset,\n}: EditorPanelSyncArgs): void {\n useEffect(() => {\n if (textAlign) {\n setAlign(textAlign);\n }\n }, [textAlign, setAlign]);\n\n useEffect(() => {\n setVerticalAlign(verticalAlignProp);\n }, [verticalAlignProp, setVerticalAlign]);\n\n useEffect(() => {\n // eslint-disable-next-line no-param-reassign\n fontSizeDirtyRef.current = false;\n if (activeFontSize) {\n const size = Number.parseInt(String(activeFontSize), 10) || 14;\n setCurrentFontSize(size);\n setFontSizePreset(getFontSizePreset(size));\n }\n }, [activeFontSize, fontSizeDirtyRef, setCurrentFontSize, setFontSizePreset]);\n}\n", "/**\n * Editor panel toolbar for the Slate.js editor; portals to data-test=\"editor-purerichtext\".\n */\n\nimport React, { useCallback, useEffect, useState, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport Button from '@splunk/react-ui/Button';\nimport RadioBar from '@splunk/react-ui/RadioBar';\nimport Color, { defaultPalette } from '@splunk/react-ui/Color';\nimport Text from '@splunk/react-ui/Text';\nimport NumberInput, { NumberChangeHandler } from '@splunk/react-ui/Number';\nimport Select from '@splunk/react-ui/Select';\nimport ControlGroup from '@splunk/react-ui/ControlGroup';\nimport Popover from '@splunk/react-ui/Popover';\nimport Chain from '@splunk/react-icons/Chain';\nimport List from '@splunk/react-icons/List';\nimport ListNumbered from '@splunk/react-icons/ListNumbered';\nimport TextBBold from '@splunk/react-icons/TextBBold';\nimport TextIItalic from '@splunk/react-icons/TextIItalic';\nimport TextUUnderline from '@splunk/react-icons/TextUUnderline';\nimport TextSStrikethrough from '@splunk/react-icons/TextSStrikethrough';\nimport TextAlignLeft from '@splunk/react-icons/TextAlignLeft';\nimport TextAlignCenter from '@splunk/react-icons/TextAlignCenter';\nimport TextAlignRight from '@splunk/react-icons/TextAlignRight';\nimport TextAlignTop from '@splunk/react-icons/TextAlignTop';\nimport TextAlignVerticalCenter from '@splunk/react-icons/TextAlignVerticalCenter';\nimport TextAlignBottom from '@splunk/react-icons/TextAlignBottom';\nimport ArrowTurnBackLeft from '@splunk/react-icons/ArrowTurnBackLeft';\nimport ScreenReaderContent from '@splunk/react-ui/ScreenReaderContent';\nimport { usePureRichTextOptional, ActiveTextStyles } from '../PureRichTextContext';\nimport { focusActiveEditable } from '../activeInstance';\nimport { DEFAULT_TEXT_STYLES, FormatCommand, VerticalAlign, TextAlign } from '../types';\nimport { FontSelector } from './FontSelector';\nimport {\n EditorContainer,\n Row,\n ColorRow,\n ButtonRow,\n LineSpacingWrapper,\n MixedColorWrapper,\n MixedLabel,\n FormatToggleButton,\n AlignmentSection,\n HorizontalAlignmentRadioBar,\n VerticalAlignmentRadioBar,\n LinkPopoverContent,\n} from './EditorPanelStyles';\nimport { FONT_SIZE_OPTIONS, getFontSizePreset } from './editorPanelUtils';\nimport { useLinkHandlers } from './hooks/useLinkHandlers';\nimport { useLineSpacing } from './hooks/useLineSpacing';\nimport { useConfigPanelFocus } from './hooks/useConfigPanelFocus';\nimport { usePortalTarget } from './hooks/usePortalTarget';\nimport { useEditorPanelSync } from './hooks/useEditorPanelSync';\n\n// TextAlignJustified is not available in the installed @splunk/react-icons version.\n// Inline SVG matching the Splunk icon style (24x24 viewBox, 1.5 stroke, currentColor).\nconst TextAlignJustified: React.FC = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M3 6h18M3 10h18M3 14h18M3 18h18\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n);\n\nconst preventDefaultMouseDown = (e: React.MouseEvent): void => e.preventDefault();\n\ninterface FontSizeStepCtx {\n stepFontSize?: (delta: number) => void;\n setCurrentFontSize: (n: number) => void;\n setFontSizePreset: (s: string) => void;\n handleFormat: (command: FormatCommand, value?: string) => void;\n fontSizeDirtyRef: React.MutableRefObject<boolean>;\n wasMouseRef: React.MutableRefObject<boolean>;\n}\n\n// Font-size step buttons. Without stepFontSize (no fake-highlight support), apply the raw\n// value; with it, derive the sign from the button's data-test and preserve the highlight.\nfunction handleFontSizeStep(\n e: Parameters<NumberChangeHandler>[0],\n val: number | undefined,\n ctx: FontSizeStepCtx\n): void {\n if (!ctx.stepFontSize) {\n if (val != null) {\n ctx.setCurrentFontSize(val);\n ctx.setFontSizePreset(getFontSizePreset(val));\n ctx.handleFormat('fontSize', `${val}px`);\n }\n return;\n }\n const target = (e as React.MouseEvent)?.currentTarget as HTMLElement;\n const testId = target?.getAttribute?.('data-test') || target?.getAttribute?.('data-testid') || '';\n const isDecrement = testId === 'decrement' || testId.includes('down');\n ctx.stepFontSize(isDecrement ? -2 : 2);\n if (ctx.wasMouseRef.current) {\n setTimeout(() => focusActiveEditable(), 0);\n }\n}\n\nfunction handleFontSizeChange(\n e: Parameters<NumberChangeHandler>[0],\n val: number | undefined,\n reason: 'input' | 'stepButton',\n ctx: FontSizeStepCtx\n): void {\n if (reason === 'stepButton') {\n handleFontSizeStep(e, val, ctx);\n return;\n }\n if (val != null) {\n ctx.fontSizeDirtyRef.current = true;\n ctx.setCurrentFontSize(val);\n ctx.setFontSizePreset(getFontSizePreset(val));\n }\n}\n\nconst focusMixedSwatch = (selector: string): void => {\n setTimeout(() => {\n document.querySelector<HTMLButtonElement>(selector)?.focus();\n }, 50);\n};\n\n// A mixed color/highlight swatch shows no color; clicking it should still focus the underlying\n// swatch button rather than no-op.\nfunction handleMixedSwatchClick(isMixed: boolean): void {\n if (isMixed) focusMixedSwatch('[data-test=\"textbox-swatch\"]');\n}\n\nconst ALIGN_COMMANDS: Record<TextAlign, FormatCommand> = {\n left: 'justifyLeft',\n center: 'justifyCenter',\n right: 'justifyRight',\n justify: 'justifyFull',\n};\n\nfunction handleAlignmentChange(\n newAlign: TextAlign,\n setAlign: (align: TextAlign) => void,\n handleFormat: (command: FormatCommand, value?: string) => void\n): void {\n setAlign(newAlign);\n handleFormat(ALIGN_COMMANDS[newAlign]);\n}\n\ninterface FontSizePresetCtx {\n setCurrentFontSize: (n: number) => void;\n setFontSizePreset: (s: string) => void;\n handleFormat: (command: FormatCommand, value?: string) => void;\n}\n\nfunction handleFontSizePresetChange(val: string | undefined, ctx: FontSizePresetCtx): void {\n const preset = FONT_SIZE_OPTIONS.find(p => p.value === val);\n if (!preset) {\n ctx.setFontSizePreset('custom');\n return;\n }\n ctx.setCurrentFontSize(Number.parseInt(preset.value, 10));\n ctx.setFontSizePreset(preset.value);\n ctx.handleFormat('fontSize', `${preset.value}px`);\n}\n\n// Capture ArrowUp/Down so the step is correctly signed: Number's stepButton\n// onChange has currentTarget=input, so the guess below reads 'increment' for both.\nfunction handleFontSizeArrowCapture(e: React.KeyboardEvent, stepFontSize: (delta: number) => void): void {\n if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return;\n e.preventDefault();\n e.stopPropagation();\n stepFontSize(e.key === 'ArrowUp' ? 2 : -2);\n}\n\ninterface FontSizeInputCtx {\n currentFontSize: number;\n fontSizeDirtyRef: React.MutableRefObject<boolean>;\n handleFormat: (command: FormatCommand, value?: string) => void;\n}\n\n// ArrowUp/ArrowDown are handled in onKeyDownCapture above.\nfunction handleFontSizeInputKeyDown(e: React.KeyboardEvent, ctx: FontSizeInputCtx): void {\n if (e.key !== 'Enter' || !ctx.currentFontSize) return;\n e.preventDefault();\n e.stopPropagation();\n ctx.fontSizeDirtyRef.current = false;\n ctx.handleFormat('fontSize', `${ctx.currentFontSize}px`);\n}\n\nfunction handleFontSizeInputBlur(ctx: FontSizeInputCtx): void {\n if (ctx.fontSizeDirtyRef.current && ctx.currentFontSize) {\n ctx.handleFormat('fontSize', `${ctx.currentFontSize}px`);\n }\n ctx.fontSizeDirtyRef.current = false;\n}\n\ninterface LineSpacingKeyDownCtx {\n isLineHeightMixed: boolean;\n stepLineSpacing?: (delta: number) => void;\n handleLineSpacingBlur: () => void;\n}\n\nfunction handleLineSpacingKeyDown(e: React.KeyboardEvent, ctx: LineSpacingKeyDownCtx): void {\n if (e.key === 'Enter') {\n ctx.handleLineSpacingBlur();\n }\n if (!ctx.isLineHeightMixed || !ctx.stepLineSpacing) return;\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n ctx.stepLineSpacing(1);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n ctx.stepLineSpacing(-1);\n }\n}\n\ninterface MixedDisplayStyles {\n isColorMixed: boolean;\n isHighlightMixed: boolean;\n isFontSizeMixed: boolean;\n isFontFamilyMixed: boolean;\n displayTextColor: string;\n displayHighlightColor: string;\n displayFontFamily: string;\n}\n\n// Mixed-selection display values: a mixed style shows blank/placeholder rather than any\n// one block's value.\nfunction computeMixedDisplayStyles(\n activeTextStyles: ActiveTextStyles,\n fontColor: string\n): MixedDisplayStyles {\n const isMixedStyles = activeTextStyles.isMixed || {};\n const isColorMixed = isMixedStyles.color === true;\n const isHighlightMixed = isMixedStyles.backgroundColor === true;\n const isFontSizeMixed = isMixedStyles.fontSize === true;\n const isFontFamilyMixed = isMixedStyles.fontFamily === true;\n return {\n isColorMixed,\n isHighlightMixed,\n isFontSizeMixed,\n isFontFamilyMixed,\n displayTextColor: isColorMixed ? '' : activeTextStyles.color || fontColor,\n displayHighlightColor: isHighlightMixed ? '' : (activeTextStyles.backgroundColor ?? 'transparent'),\n displayFontFamily: isFontFamilyMixed ? '' : activeTextStyles.fontFamily || 'Splunk Data Sans',\n };\n}\n\nfunction handleResetToDefault(\n resetToDefault: (() => void) | undefined,\n wasMouseRef: React.MutableRefObject<boolean>\n): void {\n resetToDefault?.();\n if (wasMouseRef.current) {\n setTimeout(() => focusActiveEditable(), 0);\n }\n}\n\nexport interface EditorPanelProps {\n isEditMode: boolean;\n isActive?: boolean;\n fontColor?: string;\n fontSize?: number;\n lineHeight?: string;\n verticalAlign?: VerticalAlign;\n onVerticalAlignChange?: (align: VerticalAlign) => void;\n}\n\nexport const EditorPanel: React.FC<EditorPanelProps> = ({\n isEditMode,\n isActive = false,\n fontColor = '#ffffff',\n fontSize: fontSizeProp = 14,\n lineHeight = '1.5',\n verticalAlign: verticalAlignProp = 'top',\n onVerticalAlignChange,\n}) => {\n const { portalTargetRef, portalReady } = usePortalTarget(isEditMode);\n\n const contextValue = usePureRichTextOptional();\n const activeTextStyles: ActiveTextStyles = contextValue?.activeTextStyles || DEFAULT_TEXT_STYLES;\n const applyFormat = contextValue?.applyFormat;\n const resetToDefault = contextValue?.resetToDefault;\n const stepFontSize = contextValue?.stepFontSize;\n const stepLineSpacing = contextValue?.stepLineSpacing;\n const isInLink = contextValue?.isInLink;\n const getLinkInfo = contextValue?.getLinkInfo;\n const createOrUpdateLink = contextValue?.createOrUpdateLink;\n const removeLink = contextValue?.removeLink;\n const registerOpenLinkPopover = contextValue?.registerOpenLinkPopover;\n\n const [align, setAlign] = useState<TextAlign>('left');\n const [verticalAlign, setVerticalAlign] = useState<VerticalAlign>(verticalAlignProp);\n const [currentFontSize, setCurrentFontSize] = useState<number>(fontSizeProp);\n const [fontSizePreset, setFontSizePreset] = useState<string>(() => getFontSizePreset(fontSizeProp));\n const fontSizeDirtyRef = useRef(false);\n\n // From activeTextStyles (recomputed per selection change) so the icon updates\n // when the caret enters a link even if surrounding formatting is identical.\n const linkIsActive = activeTextStyles.isLink ?? false;\n\n const {\n linkPopoverOpen,\n linkPopoverRef,\n linkText,\n linkUrl,\n linkButtonRef,\n setLinkText,\n setLinkUrl,\n handleLinkButtonClick,\n handleLinkPopoverClose,\n handleLinkSave,\n handleLinkRemove,\n handleLinkKeyDown,\n } = useLinkHandlers({\n isInLink,\n getLinkInfo,\n createOrUpdateLink,\n removeLink,\n });\n\n useEffect(() => {\n registerOpenLinkPopover?.(handleLinkButtonClick);\n }, [registerOpenLinkPopover, handleLinkButtonClick]);\n\n const wasMouseRef = useRef(false);\n\n const handleFormat = useCallback(\n (command: FormatCommand, value?: string) => {\n if (!applyFormat) return;\n applyFormat(command, value);\n if (wasMouseRef.current) {\n setTimeout(() => {\n focusActiveEditable();\n }, 0);\n }\n },\n [applyFormat]\n );\n\n const isLineHeightMixed = activeTextStyles.isMixed?.lineHeight === true;\n\n const {\n lineSpacingPercent,\n showMixed: showLineSpacingMixed,\n handleLineSpacingChange,\n handleLineSpacingBlur,\n } = useLineSpacing(\n lineHeight,\n activeTextStyles.lineHeight,\n isLineHeightMixed,\n applyFormat,\n handleFormat,\n stepLineSpacing\n );\n\n const handleFontFamilyChange = useCallback(\n (fontFamily: string) => handleFormat('fontName', fontFamily),\n [handleFormat]\n );\n\n const onFontSizeChange = useCallback<NumberChangeHandler>(\n (e, { value: val, reason }) => {\n handleFontSizeChange(e, val, reason, {\n stepFontSize,\n setCurrentFontSize,\n setFontSizePreset,\n handleFormat,\n fontSizeDirtyRef,\n wasMouseRef,\n });\n },\n [stepFontSize, handleFormat]\n );\n\n useEditorPanelSync({\n textAlign: activeTextStyles.textAlign,\n setAlign,\n verticalAlignProp,\n setVerticalAlign,\n activeFontSize: activeTextStyles.fontSize,\n fontSizeDirtyRef,\n setCurrentFontSize,\n setFontSizePreset,\n });\n\n const handleVerticalAlignChange = useCallback(\n (newAlign: VerticalAlign) => {\n setVerticalAlign(newAlign);\n onVerticalAlignChange?.(newAlign);\n },\n [onVerticalAlignChange]\n );\n\n const {\n isColorMixed,\n isHighlightMixed,\n isFontSizeMixed,\n displayTextColor,\n displayHighlightColor,\n displayFontFamily,\n } = computeMixedDisplayStyles(activeTextStyles, fontColor);\n\n const editorContainerRef = useRef<HTMLDivElement>(null);\n\n useConfigPanelFocus({ isEditMode, isActive, editorContainerRef, wasMouseRef });\n\n if (!isEditMode) return null;\n\n const editor = (\n <EditorContainer ref={editorContainerRef} data-test=\"editor-purerichtext-content\">\n <FontSelector value={displayFontFamily} onChange={handleFontFamilyChange} />\n <ControlGroup label=\"Font size\" labelPosition=\"top\">\n <Row style={{ gap: '12px' }}>\n <Select\n value={isFontSizeMixed ? undefined : fontSizePreset}\n placeholder={isFontSizeMixed ? 'Mixed' : undefined}\n onChange={(_e, { value: val }): void => {\n handleFontSizePresetChange(val as string | undefined, {\n setCurrentFontSize,\n setFontSizePreset,\n handleFormat,\n });\n }}\n style={{ flex: 1, minWidth: 100 }}\n >\n {FONT_SIZE_OPTIONS.map(({ label, value }) => (\n <Select.Option key={value} label={label} value={value} />\n ))}\n <Select.Option label=\"Custom\" value=\"custom\" />\n </Select>\n <div\n style={{ width: '80px', flexShrink: 0 }}\n // Capture ArrowUp/Down so the step is correctly signed: Number's stepButton\n // onChange has currentTarget=input, so the guess below reads 'increment' for both.\n onKeyDownCapture={\n stepFontSize\n ? (e: React.KeyboardEvent): void =>\n handleFontSizeArrowCapture(e, stepFontSize)\n : undefined\n }\n >\n <NumberInput\n aria-label=\"Font size in pixels\"\n value={isFontSizeMixed ? (undefined as unknown as number) : currentFontSize}\n onFocus={(): void => {\n fontSizeDirtyRef.current = false;\n }}\n onChange={onFontSizeChange}\n onKeyDown={(e: React.KeyboardEvent): void => {\n handleFontSizeInputKeyDown(e, {\n currentFontSize,\n fontSizeDirtyRef,\n handleFormat,\n });\n }}\n onBlur={(): void => {\n handleFontSizeInputBlur({ currentFontSize, fontSizeDirtyRef, handleFormat });\n }}\n min={8}\n max={200}\n step={1}\n inline\n />\n </div>\n </Row>\n </ControlGroup>\n\n <ColorRow>\n <ControlGroup label=\"Font color\" labelPosition=\"top\">\n <MixedColorWrapper\n $isMixed={isColorMixed}\n onClick={(): void => handleMixedSwatchClick(isColorMixed)}\n >\n <Color\n value={displayTextColor}\n onChange={(data): void => handleFormat('foreColor', data.value || '')}\n style={{ width: '100%' }}\n />\n {isColorMixed && <MixedLabel>Mixed</MixedLabel>}\n </MixedColorWrapper>\n </ControlGroup>\n <ControlGroup label=\"Highlight color\" labelPosition=\"top\">\n <MixedColorWrapper\n $isMixed={isHighlightMixed}\n onClick={(): void => handleMixedSwatchClick(isHighlightMixed)}\n >\n <Color\n value={displayHighlightColor}\n onChange={(data): void => handleFormat('backColor', data.value || 'transparent')}\n palette={\n isHighlightMixed\n ? [...defaultPalette, 'transparent']\n : ['transparent', ...defaultPalette]\n }\n style={{ width: '100%' }}\n />\n {isHighlightMixed && <MixedLabel>Mixed</MixedLabel>}\n </MixedColorWrapper>\n </ControlGroup>\n </ColorRow>\n\n <ButtonRow>\n {[\n { isActive: activeTextStyles.bold, command: 'bold', icon: <TextBBold />, label: 'Bold' },\n {\n isActive: activeTextStyles.italic,\n command: 'italic',\n icon: <TextIItalic />,\n label: 'Italic',\n },\n {\n isActive: activeTextStyles.underline,\n command: 'underline',\n icon: <TextUUnderline />,\n label: 'Underline',\n },\n {\n isActive: activeTextStyles.strikethrough,\n command: 'strikethrough',\n icon: <TextSStrikethrough />,\n label: 'Strikethrough',\n },\n ].map(({ isActive: active, command, icon, label }) => (\n <FormatToggleButton\n key={command}\n $isActive={active}\n appearance=\"secondary\"\n onMouseDown={preventDefaultMouseDown}\n // cast is required: the array literal widens `command` to `string`, which is not assignable to FormatCommand\n onClick={(): void => handleFormat(command as FormatCommand)} // NOSONAR typescript:S4325 - see note above\n icon={icon}\n aria-label={label}\n />\n ))}\n <FormatToggleButton\n ref={linkButtonRef}\n $isActive={linkIsActive}\n appearance=\"secondary\"\n onMouseDown={preventDefaultMouseDown}\n onClick={handleLinkButtonClick}\n icon={<Chain />}\n aria-label=\"Link\"\n />\n <FormatToggleButton\n $isActive={activeTextStyles.listType === 'unordered'}\n appearance=\"secondary\"\n onMouseDown={preventDefaultMouseDown}\n onClick={(): void => handleFormat('insertUnorderedList')}\n icon={<List />}\n aria-label=\"Bulleted list\"\n />\n <FormatToggleButton\n $isActive={activeTextStyles.listType === 'ordered'}\n appearance=\"secondary\"\n onMouseDown={preventDefaultMouseDown}\n onClick={(): void => handleFormat('insertOrderedList')}\n icon={<ListNumbered />}\n aria-label=\"Numbered list\"\n />\n <FormatToggleButton\n $isActive={false}\n appearance=\"secondary\"\n onMouseDown={preventDefaultMouseDown}\n onClick={(): void => handleResetToDefault(resetToDefault, wasMouseRef)}\n icon={<ArrowTurnBackLeft />}\n aria-label=\"Reset to default\"\n />\n </ButtonRow>\n\n {/* Link Popover */}\n <Popover\n open={linkPopoverOpen}\n anchor={linkButtonRef.current}\n onRequestClose={handleLinkPopoverClose}\n >\n <LinkPopoverContent\n ref={linkPopoverRef}\n onKeyDown={handleLinkKeyDown}\n data-test=\"link-popover-content\"\n >\n <ControlGroup label=\"Text\" labelPosition=\"top\">\n <Text\n value={linkText}\n onChange={(_e, { value: v }): void => setLinkText(v)}\n placeholder=\"Link text\"\n />\n </ControlGroup>\n <ControlGroup label=\"URL\" labelPosition=\"top\">\n <Text\n value={linkUrl}\n onChange={(_e, { value: v }): void => setLinkUrl(v)}\n placeholder=\"https://...\"\n />\n </ControlGroup>\n <Row>\n <Button appearance=\"primary\" onClick={handleLinkSave} label=\"Save\" />\n {linkIsActive && <Button onClick={handleLinkRemove} label=\"Remove\" />}\n <Button onClick={handleLinkPopoverClose} label=\"Cancel\" />\n </Row>\n </LinkPopoverContent>\n </Popover>\n\n <ControlGroup label=\"Alignment\" labelPosition=\"top\">\n <AlignmentSection>\n <HorizontalAlignmentRadioBar>\n <RadioBar\n value={align}\n onChange={(_e, { value: val }): void => {\n handleAlignmentChange(val as TextAlign, setAlign, handleFormat);\n }}\n >\n <RadioBar.Option\n value=\"left\"\n startAdornment={\n <>\n <TextAlignLeft />\n <ScreenReaderContent>Align left</ScreenReaderContent>\n </>\n }\n />\n <RadioBar.Option\n value=\"center\"\n startAdornment={\n <>\n <TextAlignCenter />\n <ScreenReaderContent>Align center</ScreenReaderContent>\n </>\n }\n />\n <RadioBar.Option\n value=\"right\"\n startAdornment={\n <>\n <TextAlignRight />\n <ScreenReaderContent>Align right</ScreenReaderContent>\n </>\n }\n />\n <RadioBar.Option\n value=\"justify\"\n startAdornment={\n <>\n <TextAlignJustified />\n <ScreenReaderContent>Justify</ScreenReaderContent>\n </>\n }\n />\n </RadioBar>\n </HorizontalAlignmentRadioBar>\n <VerticalAlignmentRadioBar>\n <RadioBar\n value={verticalAlign}\n onChange={(_e, { value: val }): void => {\n handleVerticalAlignChange(val as VerticalAlign);\n }}\n >\n <RadioBar.Option\n value=\"top\"\n startAdornment={\n <>\n <TextAlignTop />\n <ScreenReaderContent>Align top</ScreenReaderContent>\n </>\n }\n />\n <RadioBar.Option\n value=\"middle\"\n startAdornment={\n <>\n <TextAlignVerticalCenter />\n <ScreenReaderContent>Align middle</ScreenReaderContent>\n </>\n }\n />\n <RadioBar.Option\n value=\"bottom\"\n startAdornment={\n <>\n <TextAlignBottom />\n <ScreenReaderContent>Align bottom</ScreenReaderContent>\n </>\n }\n />\n </RadioBar>\n </VerticalAlignmentRadioBar>\n </AlignmentSection>\n </ControlGroup>\n <ControlGroup label=\"Line spacing\" labelPosition=\"top\">\n <div role=\"none\">\n <LineSpacingWrapper>\n <NumberInput\n aria-label=\"Line spacing percentage\"\n value={showLineSpacingMixed ? ('' as unknown as number) : lineSpacingPercent}\n onChange={handleLineSpacingChange}\n onBlur={handleLineSpacingBlur}\n onKeyDown={(e: React.KeyboardEvent): void => {\n handleLineSpacingKeyDown(e, {\n isLineHeightMixed,\n stepLineSpacing,\n handleLineSpacingBlur,\n });\n }}\n min={100}\n max={300}\n step={10}\n roundTo={0}\n />\n {showLineSpacingMixed ? <span aria-hidden=\"true\">Mixed</span> : <span>%</span>}\n </LineSpacingWrapper>\n </div>\n </ControlGroup>\n </EditorContainer>\n );\n\n if (portalReady && isActive) {\n return createPortal(editor, portalTargetRef.current as HTMLElement);\n }\n\n return null;\n};\n\nexport default EditorPanel;\n", "import styled, { css } from 'styled-components';\nimport { mixins, variables } from '@splunk/themes';\nimport Button from '@splunk/react-ui/Button';\nimport { VerticalAlign } from './types';\n\n/** flex `justify-content` value for a vertical alignment (top/middle/bottom). */\nfunction justifyForVerticalAlign(align?: VerticalAlign): string {\n switch (align) {\n case 'bottom':\n return 'flex-end';\n case 'middle':\n return 'center';\n case 'top':\n default:\n return 'flex-start';\n }\n}\n\nexport const PureRichTextContainer = styled.div<{\n $backgroundColor?: string;\n $verticalAlign?: VerticalAlign;\n $borderColor?: string;\n $borderWidth?: number;\n $borderStyle?: string;\n $borderRadius?: number;\n $padding: [number, number, number, number];\n $isTextEditing?: boolean;\n $isEditMode?: boolean;\n $hasEventHandlers?: boolean;\n}>`\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: ${props => {\n switch (props.$verticalAlign) {\n case 'top':\n return 'flex-start';\n case 'bottom':\n return 'flex-end';\n case 'middle':\n default:\n return 'center';\n }\n }};\n background-color: ${props => props.$backgroundColor || 'transparent'};\n border: ${props =>\n props.$borderWidth && props.$borderColor\n ? `${props.$borderWidth}px ${props.$borderStyle || 'solid'} ${props.$borderColor}`\n : 'none'};\n border-radius: ${props => (props.$borderRadius ? `${props.$borderRadius}px` : '0')};\n padding: ${props =>\n `${props.$padding[0]}px ${props.$padding[1]}px ${props.$padding[2]}px ${props.$padding[3]}px`};\n box-sizing: border-box;\n overflow: hidden;\n position: relative;\n /* Show an inset ring when actively editing text so the user can click the border to deactivate */\n ${props => props.$isTextEditing && `box-shadow: inset 0 0 0 2px ${variables.focusColor};`}\n /* When event handlers are bound (view mode), show pointer cursor to signal clickability */\n ${props =>\n props.$hasEventHandlers &&\n !props.$isTextEditing &&\n css`\n cursor: pointer;\n `}\n /* Edit-mode only: hovering a selected block's edges/padding shows grab (PowerPoint-style).\n EditorWrapper re-asserts its own cursor over the text content. */\n ${props =>\n props.$isEditMode &&\n !props.$isTextEditing &&\n css`\n [data-selected='true'] & {\n cursor: grab;\n }\n `}\n`;\n\n/** Skip-link drilldown button (shown when a richtext.click handler is bound) so SR/keyboard users can\n * reach the click action. Mirrors the Markdown viz pattern. */\nexport const DrilldownButton = styled(Button)`\n ${mixins.skipLink()}\n /* Override the secondary Button's transparent default so the skip-link is visible when focused. */\n &:not([disabled], [aria-disabled='true']) {\n background-color: ${variables.backgroundColorSection};\n }\n`;\n\nexport const EditorWrapper = styled.div<{\n $isEditMode: boolean;\n $isTextEditing: boolean;\n $hasEventHandlers?: boolean;\n $lineHeight?: string;\n $verticalAlign?: VerticalAlign;\n}>`\n width: 100%;\n /* Fill the container's content box so a click anywhere over the text region enters editing, not\n just the top. Vertical alignment moves here from the container to keep text top/middle/bottom. */\n flex: 1 1 auto;\n min-height: 0;\n max-height: 100%;\n display: flex;\n flex-direction: column;\n overflow: auto;\n /* Cursor over text: editing -> text; view mode w/ interaction -> pointer; view mode plain -> text;\n edit mode not editing -> default (grab layered below when selected). */\n cursor: ${props => {\n if (props.$isTextEditing) return 'text';\n if (props.$hasEventHandlers && !props.$isEditMode) return 'pointer';\n if (!props.$isEditMode) return 'text';\n return 'default';\n }};\n\n /* Selected in edit mode (not editing): grab cursor over the whole block including text, so it\n doesn't flip to default crossing from padding into text. View mode keeps text/pointer. */\n ${props =>\n props.$isEditMode &&\n !props.$isTextEditing &&\n css`\n [data-selected='true'] & {\n cursor: grab;\n }\n `}\n\n /* Styling for the Slate editor */\n [data-slate-editor] {\n outline: none;\n /* Fill the stretched wrapper so a click anywhere enters editing, but keep the editable as the\n vertical-align flex column: the stretched wrapper has no free space to align short content. */\n min-height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: ${props => justifyForVerticalAlign(props.$verticalAlign)};\n }\n\n /* Underline styling - match text color */\n u {\n text-decoration-color: currentColor;\n }\n\n /* Link styling */\n a {\n cursor: pointer;\n text-decoration: underline;\n color: ${variables.contentColorLink};\n\n &:hover {\n opacity: 0.8;\n }\n }\n\n /* List styling */\n ul,\n ol {\n margin: 0;\n padding-left: 24px;\n }\n\n /* Nested numbered list sub-numbering: 1 -> a -> i -> A -> I */\n ol ol {\n list-style-type: lower-alpha;\n }\n ol ol ol {\n list-style-type: lower-roman;\n }\n ol ol ol ol {\n list-style-type: upper-alpha;\n }\n ol ol ol ol ol {\n list-style-type: upper-roman;\n }\n\n li {\n margin: 4px 0;\n }\n\n /* Paragraph spacing */\n p {\n margin: 0 0 8px 0;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n`;\n\n/** Visually hidden live region for screenreader announcements. */\nexport const LiveRegion = styled.div`\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n`;\n", "import { FONT_SIZE_PRESETS, FontSizePreset } from '../types';\n\n/**\n * Get font size in pixels based on preset or custom value\n */\nexport const getFontSizeInPx = (fontSize?: FontSizePreset, customFontSize?: number): number => {\n if (fontSize === 'custom' && customFontSize) {\n return customFontSize;\n }\n return FONT_SIZE_PRESETS[fontSize || 'default'];\n};\n", "import * as React from 'react';\nimport { useSplunkTheme } from '@splunk/themes';\nimport { useState, useCallback, useEffect, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { RenderElementProps } from 'slate-react';\nimport { CustomText } from '../types';\nimport { resolveLinkHref, isOpenableUrl } from '../utils/slateUtils';\n\n// A resolved href is \"broken\" when it can't be opened as a navigation target. Path/protocol-\n// relative (/..., //...) stay openable; everything else must parse as a URL. Catches malformed\n// absolute urls and fragment/query-only values (e.g. a resolved \"#2E8B57\" color token).\nfunction isBrokenHref(href: string): boolean {\n if (!href) return false;\n if (href.startsWith('/')) return false;\n return !isOpenableUrl(href);\n}\n\n// True when the framework's link.open handler will surface the broken href itself (its\n// InvalidUrlModal): it only accepts whitespace-free http(s):// urls (e.g. \"https://#2E8B57\").\n// Bare fragments it drops silently, so we surface our own note. Only relevant when bound.\nfunction frameworkFlagsHref(href: string, onLinkOpen?: (url: string) => void): boolean {\n if (!onLinkOpen) return false;\n return !/\\s/.test(href) && /^https?:\\/\\//i.test(href);\n}\n\n// True when the framework's link.open will accept the href, mirroring its isValidUrl gate\n// (whitespace-free http(s):// or root-relative /path). Other schemes (file:, mailto:, tel:)\n// it drops silently, so we open those natively instead.\nfunction frameworkHandlesHref(href: string): boolean {\n if (/\\s/.test(href)) return false;\n return /^https?:\\/\\//i.test(href) || /^\\/(?!\\/)/.test(href);\n}\n\n// Prefer modern userAgentData.platform; fall back to deprecated navigator.platform.\nconst platformString =\n (typeof navigator !== 'undefined' &&\n ((navigator as Navigator & { userAgentData?: { platform?: string } }).userAgentData?.platform ||\n navigator.platform)) ||\n '';\nconst isMacPlatform = /Mac|iP(hone|ad|od)/.test(platformString);\n\ntype PortalPos = { top: number; left: number } | null;\n\nconst OVERLAY_STYLE: React.CSSProperties = {\n position: 'fixed',\n transform: 'translateY(-100%) translateY(-6px)',\n zIndex: 2147483647,\n maxWidth: 320,\n padding: '4px 8px',\n borderRadius: 4,\n background: '#3c444d',\n color: '#fff',\n fontSize: 12,\n lineHeight: 1.4,\n overflowWrap: 'anywhere',\n pointerEvents: 'none',\n boxShadow: '0 2px 8px rgba(0,0,0,0.4)',\n};\n\nconst styleBlock = { display: 'block' };\nconst styleBlockOpacity = { display: 'block', opacity: 0.75 };\n\n// Edit-mode hover tooltip showing the URL + follow hint, portaled to body so it doesn't\n// disturb Slate's DOM. Returns null unless shown, keeping the branch out of LinkElement.\nconst LinkFollowTooltip: React.FC<{ show: boolean; pos: PortalPos; href: string }> = ({\n show,\n pos,\n href,\n}) => {\n const { fontFamily } = useSplunkTheme();\n if (!show || !pos || typeof document === 'undefined') return null;\n return createPortal(\n <span contentEditable={false} style={{ ...OVERLAY_STYLE, top: pos.top, left: pos.left, fontFamily }}>\n <span style={styleBlock}>{href}</span>\n <span style={styleBlockOpacity}>{isMacPlatform ? '\u2318' : 'Ctrl'}+click to open</span>\n </span>,\n document.body\n );\n};\n\n// Standalone \"can't open\" note for a broken link, portaled to body. Returns null unless shown.\nconst BrokenLinkNote: React.FC<{ pos: PortalPos; href: string }> = ({ pos, href }) => {\n const { fontFamily } = useSplunkTheme();\n if (!pos || typeof document === 'undefined') return null;\n return createPortal(\n <span\n role=\"alert\"\n contentEditable={false}\n style={{ ...OVERLAY_STYLE, top: pos.top, left: pos.left, fontFamily }}\n >\n <span style={styleBlock}>This link can&apos;t be opened.</span>\n <span style={styleBlockOpacity}>{href}</span>\n </span>,\n document.body\n );\n};\n\ninterface LinkHandlerCtx {\n isEditMode: boolean;\n showBrokenNote: boolean;\n routeToFramework: boolean;\n activateLink: (el: HTMLAnchorElement) => void;\n hideTooltip: () => void;\n clearBrokenNote: () => void;\n}\n\n// A plain mousedown on the focusable <a> steals focus off the editable, blurring the viz.\n// Prevent it (not on modifier-click); Slate still sets the caret.\nfunction handleAnchorMouseDown(e: React.MouseEvent, ctx: LinkHandlerCtx): void {\n if (ctx.isEditMode && !e.metaKey && !e.ctrlKey) e.preventDefault();\n}\n\nfunction handleAnchorMouseLeave(ctx: LinkHandlerCtx): void {\n if (ctx.isEditMode) ctx.hideTooltip();\n ctx.clearBrokenNote();\n}\n\nfunction handleAnchorClick(e: React.MouseEvent<HTMLAnchorElement>, ctx: LinkHandlerCtx): void {\n if (ctx.isEditMode) {\n e.preventDefault();\n // Cmd/Ctrl+click follows the link; plain click just places the caret.\n if (e.metaKey || e.ctrlKey) {\n e.stopPropagation();\n ctx.activateLink(e.currentTarget);\n }\n return;\n }\n // View mode: stop link clicks bubbling to the container's richtext.click (matches Markdown\n // viz). Broken/routed hrefs need preventDefault; a framework-flagged or native (file:/mailto:,\n // unbound) href falls through to the anchor's own navigation.\n e.stopPropagation();\n if (ctx.showBrokenNote || ctx.routeToFramework) {\n e.preventDefault();\n ctx.activateLink(e.currentTarget);\n }\n}\n\nfunction handleAnchorKeyDown(e: React.KeyboardEvent<HTMLAnchorElement>, ctx: LinkHandlerCtx): void {\n if (!ctx.isEditMode && e.key === 'Enter') {\n // Suppress native Enter so it doesn't also fire onClick and open twice.\n e.preventDefault();\n e.stopPropagation();\n ctx.activateLink(e.currentTarget);\n }\n}\n\n/**\n * Renders an inline link. In edit mode plain click edits text, Cmd/Ctrl+click follows; a hover\n * tooltip (portaled to body so it doesn't disturb Slate's DOM) shows the URL and follow hint.\n */\nconst LinkElement: React.FC<\n RenderElementProps & {\n isEditMode: boolean;\n url: string;\n nameToValue?: Map<string, string>;\n onLinkOpen?: (url: string) => void;\n }\n> = ({ attributes, children, isEditMode, url, nameToValue, onLinkOpen }) => {\n const normalizedHref = resolveLinkHref(url, nameToValue);\n const broken = isBrokenHref(normalizedHref);\n // Surface our own note for a broken href the framework's modal wouldn't flag (a bare\n // \"#2E8B57\" it drops silently, vs a valid-looking \"https://#2E8B57\" it handles).\n const showBrokenNote = broken && !frameworkFlagsHref(normalizedHref, onLinkOpen);\n // Route through link.open (its URL protection) only when bound AND it handles the href;\n // other schemes (file:, mailto:, tel:) go via the native anchor, as the Markdown viz does.\n const routeToFramework = !!onLinkOpen && frameworkHandlesHref(normalizedHref);\n const [tooltipPos, setTooltipPos] = useState<{ top: number; left: number } | null>(null);\n // Standalone (no framework handler): show a brief \"can't open\" note on a broken link,\n // since there's no dashboard modal to surface it.\n const [brokenPos, setBrokenPos] = useState<{ top: number; left: number } | null>(null);\n const dismissTimer = useRef<ReturnType<typeof setTimeout>>();\n const flagBroken = useCallback((el: HTMLAnchorElement) => {\n const rect = el.getBoundingClientRect();\n setBrokenPos({ top: rect.top, left: rect.left });\n }, []);\n // Auto-dismiss the \"can't open\" note so it can't linger (mouse-leave and re-click\n // also clear it, handled at the call sites).\n useEffect(() => {\n if (!brokenPos) return undefined;\n dismissTimer.current = setTimeout(() => setBrokenPos(null), 2500);\n return () => clearTimeout(dismissTimer.current);\n }, [brokenPos]);\n\n // Read the rect from the hovered anchor directly instead of our own ref -- a composed ref\n // would fight Slate's ref on this inline element and churn its DOM<->node weakmap.\n const showTooltip = useCallback((ev: React.MouseEvent<HTMLAnchorElement>) => {\n const rect = ev.currentTarget.getBoundingClientRect();\n setTooltipPos({ top: rect.top, left: rect.left });\n }, []);\n const hideTooltip = useCallback(() => setTooltipPos(null), []);\n\n // Broken href the framework wouldn't flag: show our own note; else open (routed through\n // link.open when bound, native otherwise). Shared by Cmd-click, view click, and Enter.\n const activateLink = useCallback(\n (el: HTMLAnchorElement) => {\n if (showBrokenNote) {\n flagBroken(el);\n return;\n }\n openHref(normalizedHref, onLinkOpen);\n },\n [showBrokenNote, flagBroken, normalizedHref, onLinkOpen]\n );\n\n const clearBrokenNote = useCallback(() => setBrokenPos(null), []);\n const ctx: LinkHandlerCtx = {\n isEditMode,\n showBrokenNote,\n routeToFramework,\n activateLink,\n hideTooltip,\n clearBrokenNote,\n };\n\n return (\n <a\n href={normalizedHref}\n style={{ display: 'inline' }}\n {...attributes}\n // Let link.open own navigation when it routes the href; else keep native new-tab\n // via target/rel (standalone AND file:/mailto: the framework drops). A broken href\n // gets no target so the browser can't try to open it -- onClick shows the note.\n target={isEditMode || routeToFramework || broken ? undefined : '_blank'}\n rel={isEditMode || routeToFramework ? undefined : 'noopener noreferrer'}\n tabIndex={isEditMode ? undefined : 0}\n onMouseDown={(e): void => handleAnchorMouseDown(e, ctx)}\n onMouseEnter={isEditMode ? showTooltip : undefined}\n onMouseLeave={(): void => handleAnchorMouseLeave(ctx)}\n onClick={(e): void => handleAnchorClick(e, ctx)}\n onKeyDown={(e): void => handleAnchorKeyDown(e, ctx)}\n >\n {children}\n <LinkFollowTooltip show={isEditMode} pos={tooltipPos} href={normalizedHref} />\n <BrokenLinkNote pos={brokenPos} href={normalizedHref} />\n </a>\n );\n};\n\n/**\n * Open a resolved link href. Route through the bound `link.open` event for its URL protection;\n * otherwise (standalone/pure viz) open directly.\n */\nfunction openHref(href: string, onLinkOpen?: (url: string) => void): void {\n if (!href) return;\n // Only route through the framework when it will open the href; it drops non-http(s)/relative\n // schemes (file:, mailto:, tel:), so open those natively, as the Markdown viz does.\n if (onLinkOpen && frameworkHandlesHref(href)) {\n onLinkOpen(href);\n return;\n }\n try {\n window.open(href, '_blank', 'noopener,noreferrer');\n } catch {\n // window.open throws a SyntaxError on an unopenable URL; swallow it.\n }\n}\n\n/** Create an edit-mode-aware component that renders Slate elements (paragraphs, lists, links). */\nexport const createElementRenderer = (\n isEditMode: boolean,\n defaultLineHeight: string,\n nameToValue?: Map<string, string>,\n onLinkOpen?: (url: string) => void\n): React.FC<RenderElementProps> => {\n return function ElementRenderer({ attributes, children, element }): JSX.Element {\n const customElement = element;\n // Base style for alignment\n const baseStyle: React.CSSProperties = {\n textAlign: customElement.align,\n };\n // Style with line height for block elements\n const blockStyle: React.CSSProperties = {\n ...baseStyle,\n lineHeight: customElement.lineHeight || defaultLineHeight,\n };\n\n switch (customElement.type) {\n case 'bulleted-list': {\n return <ul {...attributes}>{children}</ul>;\n }\n case 'numbered-list': {\n return <ol {...attributes}>{children}</ol>;\n }\n case 'list-item': {\n const listItemStyle: React.CSSProperties = { ...blockStyle };\n // Set color and fontSize on <li> so the ::marker (bullet/number) inherits them\n const firstLeaf = customElement.children[0] as CustomText | undefined;\n if (firstLeaf?.color) {\n listItemStyle.color = firstLeaf.color;\n }\n if (firstLeaf?.fontSize) {\n listItemStyle.fontSize = firstLeaf.fontSize;\n }\n // Use inside positioning when aligned or when font is large\n // enough that the marker would overflow the fixed padding gutter\n const fontSize = Number.parseInt(String(firstLeaf?.fontSize || '0'), 10);\n if (customElement.align === 'center' || customElement.align === 'right' || fontSize > 24) {\n listItemStyle.listStylePosition = 'inside';\n }\n return (\n <li style={listItemStyle} {...attributes}>\n {children}\n </li>\n );\n }\n case 'link': {\n return (\n <LinkElement\n attributes={attributes}\n element={element}\n isEditMode={isEditMode}\n url={customElement.url || ''}\n nameToValue={nameToValue}\n onLinkOpen={onLinkOpen}\n >\n {children}\n </LinkElement>\n );\n }\n case 'paragraph':\n default:\n return (\n <p style={blockStyle} {...attributes}>\n {children}\n </p>\n );\n }\n };\n};\n", "import * as React from 'react';\nimport { RenderLeafProps } from 'slate-react';\nimport { CustomText, FONT_FAMILY_WITH_FALLBACKS } from '../types';\n\nexport const Leaf: React.FC<RenderLeafProps> = ({ attributes, children, leaf }) => {\n const customLeaf = leaf as CustomText & { fakeHighlight?: boolean };\n const style: React.CSSProperties = {};\n\n if (customLeaf.fakeHighlight) {\n style.backgroundColor = 'rgba(0, 120, 215, 0.35)';\n } else if (customLeaf.backgroundColor && customLeaf.backgroundColor !== 'transparent') {\n style.backgroundColor = customLeaf.backgroundColor;\n }\n if (customLeaf.color) {\n style.color = customLeaf.color;\n }\n if (customLeaf.fontSize) {\n style.fontSize = customLeaf.fontSize;\n }\n if (customLeaf.fontFamily) {\n style.fontFamily = FONT_FAMILY_WITH_FALLBACKS[customLeaf.fontFamily] || customLeaf.fontFamily;\n }\n\n let content: React.ReactNode = children;\n\n if (customLeaf.bold) {\n content = <strong>{content}</strong>;\n }\n if (customLeaf.italic) {\n content = <em>{content}</em>;\n }\n if (customLeaf.underline) {\n content = <u>{content}</u>;\n }\n if (customLeaf.strikethrough) {\n content = <s>{content}</s>;\n }\n\n // data-token-name is rendered only for raw $token$ patterns (isRawToken=true),\n // not for resolved token values in preview mode. Both paths set tokenName for\n // atomicity (moveCursorPastAtomicIfNeeded / expandSelectionToAtomic).\n // The inner span avoids affecting the data-slate-leaf span's inline layout metrics.\n if (customLeaf.tokenName) {\n return (\n <span {...attributes} style={style}>\n <span data-token-name={customLeaf.isRawToken ? customLeaf.tokenName : undefined}>\n {content}\n </span>\n </span>\n );\n }\n\n return (\n <span {...attributes} style={style}>\n {content}\n </span>\n );\n};\n", "/**\n * useEditorSetup - Creates the Slate editor: inline links, markdown autoformat,\n * empty list-item Enter, and stale selection recovery on onChange.\n */\n\nimport { useMemo, useRef, useEffect } from 'react';\nimport {\n createEditor,\n Editor,\n Transforms,\n Text,\n Element,\n Range,\n Node as SlateNode,\n Point,\n Path,\n} from 'slate';\nimport { withReact } from 'slate-react';\nimport { isLinkActive, toggleList } from '../utils/slateUtils';\nimport { CustomElement, CustomText } from '../types';\n\n/**\n * Point just after a link, staying within its block. Null when the only point after\n * lives in the NEXT block (link is block-last, no trailing text): selecting it jumps the caret down.\n */\nfunction pointAfterLinkInBlock(e: Editor, linkPath: Path): Point | null {\n const blockEntry = Editor.above(e, {\n at: linkPath,\n match: n => !Editor.isEditor(n) && Element.isElement(n) && Editor.isBlock(e, n),\n });\n const after = Editor.after(e, linkPath);\n if (after && blockEntry && Path.isDescendant(after.path, blockEntry[1])) {\n return after;\n }\n return null;\n}\n\n/**\n * Mirror of pointAfterLinkInBlock: point just before a link, staying within its block.\n * Null when the only point before lives in the PREVIOUS block (link is block-first, no leading text).\n */\nfunction pointBeforeLinkInBlock(e: Editor, linkPath: Path): Point | null {\n const blockEntry = Editor.above(e, {\n at: linkPath,\n match: n => !Editor.isEditor(n) && Element.isElement(n) && Editor.isBlock(e, n),\n });\n const before = Editor.before(e, linkPath);\n if (before && blockEntry && Path.isDescendant(before.path, blockEntry[1])) {\n return before;\n }\n return null;\n}\n\n/** If the cursor is at the start of a link, move it before the link so inserted text lands outside it. */\nfunction exitLinkStartBeforeInsert(e: Editor): void {\n const { selection } = e;\n if (!selection || !Range.isCollapsed(selection)) return;\n const above = Editor.above(e, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'link',\n });\n if (!above) return;\n const [, linkPath] = above;\n if (!Editor.isStart(e, selection.anchor, linkPath)) return;\n let before = pointBeforeLinkInBlock(e, linkPath);\n // With an adjacent link before this one, `before` lands in that link's text; selecting it\n // would extend it. Treat like \"no leading text\" so we insert a plain separator.\n if (before) {\n const prevLink = Editor.above(e, {\n at: before,\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'link',\n });\n if (prevLink) before = null;\n }\n if (!before) {\n // No leading text node (link is block-first or adjacent to another link). Add an empty\n // one WITHOUT selecting it (see exitLinkBeforeInsert), then select it.\n Transforms.insertNodes(e, { text: '' }, { at: linkPath });\n before = pointBeforeLinkInBlock(e, Path.next(linkPath));\n }\n if (before) {\n Transforms.select(e, before);\n }\n}\n\n/** If the cursor is at the end of a link, move it past the link before inserting. */\nfunction exitLinkBeforeInsert(e: Editor): void {\n const { selection } = e;\n if (!selection || !Range.isCollapsed(selection)) return;\n const above = Editor.above(e, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'link',\n });\n if (!above) return;\n const [, linkPath] = above;\n // At the start edge, exit to the front of the link instead of the back.\n if (Editor.isStart(e, selection.anchor, linkPath)) {\n exitLinkStartBeforeInsert(e);\n return;\n }\n if (!Editor.isEnd(e, selection.anchor, linkPath)) return;\n let after = pointAfterLinkInBlock(e, linkPath);\n if (!after) {\n // Link is block-last (no trailing text). Add an empty one WITHOUT selecting it: selecting\n // a fresh node trips slate-react's toDOMPoint on an unrendered leaf. Then select the resolvable point.\n const trailingPath = Path.next(linkPath);\n Transforms.insertNodes(e, { text: '' }, { at: trailingPath });\n after = pointAfterLinkInBlock(e, linkPath);\n }\n if (after) {\n Transforms.select(e, after);\n }\n}\n\n/** Check if a list item node is empty (single empty text child). */\nfunction isEmptyListItem(node: Element): boolean {\n return node.children.length === 1 && Text.isText(node.children[0]) && node.children[0].text === '';\n}\n\n/** Returns true if the editor contains a single empty paragraph. */\nexport function isEditorEmpty(e: Editor): boolean {\n return (\n e.children.length === 1 &&\n Element.isElement(e.children[0]) &&\n isEmptyListItem(e.children[0] as Element)\n );\n}\n\n/** Apply defaultTextStyle marks so the first typed character inherits them. */\nexport function applyInitialMarks(\n e: Editor,\n style: {\n color?: string;\n backgroundColor?: string;\n fontSize?: string;\n fontFamily?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n }\n): void {\n if (style.color) Editor.addMark(e, 'color', style.color);\n if (style.backgroundColor) Editor.addMark(e, 'backgroundColor', style.backgroundColor);\n if (style.fontSize) Editor.addMark(e, 'fontSize', style.fontSize);\n if (style.fontFamily) Editor.addMark(e, 'fontFamily', style.fontFamily);\n if (style.bold) Editor.addMark(e, 'bold', true);\n if (style.italic) Editor.addMark(e, 'italic', true);\n if (style.underline) Editor.addMark(e, 'underline', true);\n if (style.strikethrough) Editor.addMark(e, 'strikethrough', true);\n}\n\ninterface DefaultTextStyleRef {\n current: {\n color?: string;\n backgroundColor?: string;\n fontSize?: string;\n fontFamily?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n };\n}\n\n/** Build a fallback marks object from default text style. */\nfunction buildFallbackMarks(s: DefaultTextStyleRef['current']): Record<string, unknown> {\n const fallback: Record<string, unknown> = {};\n if (s.color) fallback.color = s.color;\n if (s.backgroundColor) fallback.backgroundColor = s.backgroundColor;\n if (s.fontSize) fallback.fontSize = s.fontSize;\n if (s.fontFamily) fallback.fontFamily = s.fontFamily;\n if (s.bold) fallback.bold = true;\n if (s.italic) fallback.italic = true;\n if (s.underline) fallback.underline = true;\n if (s.strikethrough) fallback.strikethrough = true;\n return fallback;\n}\n\n/** Handle markdown autoformat: space after a trigger prefix at line start. */\nfunction handleAutoformat(e: Editor, defaultTextStyleRef: DefaultTextStyleRef): boolean {\n if (!e.selection || !Range.isCollapsed(e.selection)) return false;\n const { anchor } = e.selection;\n const block = Editor.above(e, {\n match: n => Element.isElement(n) && Editor.isBlock(e, n),\n });\n if (!block) return false;\n\n const [blockNode, blockPath] = block;\n\n const start = Editor.start(e, blockPath);\n const beforeText = Editor.string(e, { anchor, focus: start }).trim();\n\n let listType: 'bulleted-list' | 'numbered-list' | null = null;\n if (beforeText === '*' || beforeText === '-' || beforeText === '\\u2022') {\n listType = 'bulleted-list';\n } else if (/^\\d+\\.$/.test(beforeText)) {\n listType = 'numbered-list';\n }\n if (!listType) return false;\n\n // Inside a list item, only autoformat when the whole content is the trigger text (e.g. \"* \"\n // to switch list type); prevents \"2.\" mid-sentence being read as a trigger.\n if (Element.isElement(blockNode) && blockNode.type === 'list-item') {\n const fullText = Editor.string(e, blockPath).trim();\n if (fullText !== beforeText) return false;\n\n // If already in the same list type, skip autoformat to avoid toggling it off.\n const [parentList] = Editor.nodes(e, {\n at: blockPath,\n match: n =>\n !Editor.isEditor(n) &&\n Element.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n });\n if (parentList && (parentList[0] as CustomElement).type === listType) return false;\n }\n\n let marks = Editor.marks(e);\n const hasStyleMarks = marks && Object.keys(marks).some(k => k !== 'text');\n if (!hasStyleMarks) {\n marks = buildFallbackMarks(defaultTextStyleRef.current);\n }\n Transforms.select(e, { anchor, focus: start });\n Transforms.delete(e);\n toggleList(e, listType);\n if (marks) {\n Object.entries(marks).forEach(([key, val]) => {\n if (key !== 'text') {\n e.addMark(key, val);\n }\n });\n }\n return true;\n}\n\n/** Full range of the token text node at a point, or null if not in a token. */\nfunction getTokenRangeAtPoint(e: Editor, point: Point): Range | null {\n const [node, path] = Editor.node(e, point);\n if (!Text.isText(node)) return null;\n const custom = node as CustomText;\n if (!custom.tokenName && !custom.isEscapedDollar) return null;\n return {\n anchor: { path, offset: 0 },\n focus: { path, offset: custom.text.length },\n };\n}\n\n/** Full range of the link element at a point, or null if not in a link. */\nfunction getLinkRangeAtPoint(e: Editor, point: Point): Range | null {\n const linkEntry = Editor.above(e, {\n at: point,\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'link',\n });\n if (!linkEntry) return null;\n const [, linkPath] = linkEntry;\n return Editor.range(e, linkPath);\n}\n\n/** Range of the atomic node (token or link) at a point, or null. */\nfunction getAtomicRangeAtPoint(e: Editor, point: Point): Range | null {\n return getTokenRangeAtPoint(e, point) || getLinkRangeAtPoint(e, point);\n}\n\n/**\n * Delete the atomic node covered by `range`. For a link, remove the whole <a> (deleting only its\n * text leaves an empty inline that later merges neighbours and crashes toDOMPoint); tokens just range-delete.\n */\nfunction deleteAtomicRange(e: Editor, point: Point, range: Range): void {\n const linkEntry = Editor.above(e, {\n at: point,\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'link',\n });\n if (linkEntry) {\n const [, linkPath] = linkEntry;\n // Move caret to a surviving sibling BEFORE removing the <a>: removing it unmounts the\n // caret's DOM node, and a caret still inside blurs the editable (swallowing the next Cmd+K).\n const before = Editor.before(e, Editor.start(e, linkPath));\n const after = Editor.after(e, Editor.end(e, linkPath));\n if (before) Transforms.select(e, before);\n else if (after) Transforms.select(e, after);\n Transforms.removeNodes(e, { at: linkPath });\n return;\n }\n Transforms.delete(e, { at: range });\n}\n\n/**\n * True when the point is strictly interior to an atomic node (token or link), not at an edge.\n * Edge positions are valid caret positions for editing beside the node.\n */\nfunction isStrictlyInsideAtomic(e: Editor, point: Point): boolean {\n // Check token / escaped-dollar first (text-level mark)\n const [node] = Editor.node(e, point);\n const custom = node as CustomText;\n if (Text.isText(node) && (custom.tokenName || custom.isEscapedDollar)) {\n return point.offset > 0 && point.offset < node.text.length;\n }\n // Check link (element-level)\n const linkEntry = Editor.above(e, {\n at: point,\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'link',\n });\n if (!linkEntry) return false;\n const [, linkPath] = linkEntry;\n const linkRange = Editor.range(e, linkPath);\n const atStart = Point.equals(point, linkRange.anchor);\n const atEnd = Point.equals(point, linkRange.focus);\n return !atStart && !atEnd;\n}\n\n/**\n * Point just AFTER the atomic node at a point: end of the text node for tokens, past the\n * <a> for links so inserted text lands outside the link.\n */\nfunction getPointAfterAtomic(e: Editor, point: Point): Point | null {\n // Check link first (element-level)\n const linkEntry = Editor.above(e, {\n at: point,\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'link',\n });\n if (linkEntry) {\n const [, linkPath] = linkEntry;\n return pointAfterLinkInBlock(e, linkPath);\n }\n // Token: end of the text node\n const tokenRange = getTokenRangeAtPoint(e, point);\n if (tokenRange) return tokenRange.focus;\n return null;\n}\n\n/**\n * For an expanded-selection endpoint strictly inside an atomic node, pick which atomic edge to\n * snap to and which endpoint (anchor/focus) to move. Null if no adjustment needed.\n */\nfunction getAtomicExpansion(\n atomicRange: Range,\n isAnchorEndpoint: boolean,\n isBackward: boolean\n): { adjustAnchor: boolean; target: Point } | null {\n // Move only the examined (interior) endpoint, never the fixed drag origin (would collapse on\n // crossing). Snap OUTWARD to the atomic edge at its left end (anchor if forward, focus if backward), else its end.\n const isLeftEnd = isAnchorEndpoint ? !isBackward : isBackward;\n const target = isLeftEnd ? atomicRange.anchor : atomicRange.focus;\n return { adjustAnchor: isAnchorEndpoint, target };\n}\n\n/**\n * Snap one endpoint of a selection to an atomic node boundary.\n * Returns the updated anchor/focus and whether a change was made.\n */\nfunction snapEndpointToAtomic(\n e: Editor,\n point: Point,\n isAnchorEndpoint: boolean,\n anchor: Point,\n focus: Point,\n isBackward: boolean\n): { anchor: Point; focus: Point; changed: boolean } | null {\n const atomicRange = getAtomicRangeAtPoint(e, point);\n if (!atomicRange) return null;\n const exp = getAtomicExpansion(atomicRange, isAnchorEndpoint, isBackward);\n if (!exp) return null;\n const current = exp.adjustAnchor ? anchor : focus;\n if (Point.compare(current, exp.target) === 0) return null;\n return {\n anchor: exp.adjustAnchor ? exp.target : anchor,\n focus: exp.adjustAnchor ? focus : exp.target,\n changed: true,\n };\n}\n\n/**\n * If a selection endpoint is strictly inside an atomic node (token or link), expand to cover\n * the full node. Edge positions are valid caret positions for editing beside the node.\n */\nfunction expandSelectionToAtomic(e: Editor): void {\n const { selection } = e;\n if (!selection) return;\n\n let { anchor, focus } = selection;\n let changed = false;\n\n if (isStrictlyInsideAtomic(e, anchor)) {\n const anchorRange = getAtomicRangeAtPoint(e, anchor);\n if (!anchorRange) return;\n if (Range.isCollapsed(selection)) {\n Transforms.select(e, anchorRange);\n return;\n }\n const result = snapEndpointToAtomic(e, anchor, true, anchor, focus, Range.isBackward(selection));\n if (result) {\n ({ anchor, focus, changed } = result);\n }\n }\n\n if (isStrictlyInsideAtomic(e, focus)) {\n const focusRange = getAtomicRangeAtPoint(e, focus);\n if (!focusRange) return;\n const result = snapEndpointToAtomic(e, focus, false, anchor, focus, Range.isBackward(selection));\n if (result) {\n ({ anchor, focus, changed } = result);\n }\n }\n\n if (changed) {\n Transforms.select(e, { anchor, focus });\n }\n}\n\n/**\n * At/inside a token, strip the tokenName mark so inserted text isn't tagged as part of it.\n * Mutates selection directly (not Transforms.select) to avoid firing onChange mid-insertText, which would reset e.marks.\n */\nfunction moveCursorPastAtomicIfNeeded(e: Editor): void {\n if (!e.selection || !Range.isCollapsed(e.selection)) return;\n const { anchor } = e.selection;\n const [node] = Editor.node(e, anchor);\n if (Text.isText(node) && (node.tokenName || node.isEscapedDollar)) {\n if (anchor.offset > 0 && anchor.offset < node.text.length) {\n const endPoint: Point = { path: anchor.path, offset: node.text.length };\n // eslint-disable-next-line no-param-reassign\n e.selection = { anchor: endPoint, focus: endPoint };\n }\n const currentMarks = Editor.marks(e) ?? {};\n // Strip atomic flags so inserted text is not tagged as part of the token/escape.\n const marksWithoutToken = { ...(currentMarks as Record<string, unknown>) };\n delete marksWithoutToken.tokenName;\n delete marksWithoutToken.tokenOccurrence;\n delete marksWithoutToken.isEscapedDollar;\n // eslint-disable-next-line no-param-reassign\n e.marks = marksWithoutToken;\n return;\n }\n if (!isStrictlyInsideAtomic(e, anchor)) return;\n const afterAtomic = getPointAfterAtomic(e, anchor);\n if (afterAtomic) {\n Transforms.select(e, afterAtomic);\n }\n}\n\n/** If the caret is in an empty top-level list item, exit the list to a paragraph. */\nfunction tryExitEmptyListItem(e: Editor): boolean {\n const { selection } = e;\n if (!selection || !Range.isCollapsed(selection)) return false;\n const above = Editor.above(e, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n if (!above) return false;\n const [itemNode] = above;\n if (!Element.isElement(itemNode) || !isEmptyListItem(itemNode)) return false;\n Transforms.unwrapNodes(e, {\n match: n =>\n !Editor.isEditor(n) &&\n Element.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n split: true,\n });\n Transforms.setNodes(e, { type: 'paragraph' });\n return true;\n}\n\n/** The path of the block element containing a point, or null. */\nfunction blockPathAt(ed: Editor, point: Point): number[] | null {\n const above = Editor.above(ed, {\n at: point,\n match: n => !Editor.isEditor(n) && Element.isElement(n) && Editor.isBlock(ed, n),\n });\n return above ? above[1] : null;\n}\n\n/** True when two points sit in the same block element. */\nfunction inSameBlock(ed: Editor, a: Point, b: Point): boolean {\n const pa = blockPathAt(ed, a);\n const pb = blockPathAt(ed, b);\n return pa !== null && pb !== null && Path.equals(pa, pb);\n}\n\n/**\n * Atomic range immediately before `point`, or null. Slate keeps an empty spacer text node between\n * adjacent inlines, so step over an empty in-block text node to reach the real preceding atomic.\n */\nfunction atomicRangeBefore(ed: Editor, point: Point): { range: Range; at: Point } | null {\n const before = Editor.before(ed, point);\n if (!before || !inSameBlock(ed, point, before)) return null;\n const direct = getAtomicRangeAtPoint(ed, before);\n if (direct) return { range: direct, at: before };\n const [node] = Editor.node(ed, before.path);\n if (Text.isText(node) && node.text === '') {\n const prior = Editor.before(ed, before);\n if (prior && inSameBlock(ed, point, prior)) {\n const priorRange = getAtomicRangeAtPoint(ed, prior);\n if (priorRange) return { range: priorRange, at: prior };\n }\n }\n return null;\n}\n\n/** Mirror of atomicRangeBefore for forward-delete. */\nfunction atomicRangeAfter(ed: Editor, point: Point): { range: Range; at: Point } | null {\n const after = Editor.after(ed, point);\n if (!after || !inSameBlock(ed, point, after)) return null;\n const direct = getAtomicRangeAtPoint(ed, after);\n if (direct) return { range: direct, at: after };\n const [node] = Editor.node(ed, after.path);\n if (Text.isText(node) && node.text === '') {\n const next = Editor.after(ed, after);\n if (next && inSameBlock(ed, point, next)) {\n const nextRange = getAtomicRangeAtPoint(ed, next);\n if (nextRange) return { range: nextRange, at: next };\n }\n }\n return null;\n}\n\n/**\n * Backspace: delete an atomic node near the cursor (strictly inside, at end edge, or right after).\n * Returns true if a deletion was performed.\n */\nfunction tryDeleteAtomicBackward(ed: Editor, anchor: Point): boolean {\n if (isStrictlyInsideAtomic(ed, anchor)) {\n const range = getAtomicRangeAtPoint(ed, anchor);\n if (range) deleteAtomicRange(ed, anchor, range);\n return true;\n }\n const currentRange = getAtomicRangeAtPoint(ed, anchor);\n if (currentRange && Point.equals(anchor, currentRange.focus)) {\n deleteAtomicRange(ed, anchor, currentRange);\n return true;\n }\n // At an atomic's START edge (e.g. between adjacent links), fall through to remove the atomic\n // BEFORE the caret; bailing here would let Slate eat one char of the previous link.\n if (currentRange && !Point.equals(anchor, currentRange.anchor)) return false;\n // Only eat a preceding atomic in the SAME block; else Backspace at line start must merge\n // with the previous block (Slate's default), not delete across the boundary.\n const prev = atomicRangeBefore(ed, anchor);\n if (!prev) return false;\n deleteAtomicRange(ed, prev.at, prev.range);\n return true;\n}\n\n/** Unwrap a list item at the start of a line back to a paragraph, or un-indent if nested. */\nfunction tryUnwrapListItem(ed: Editor, anchor: Point): boolean {\n const [listItemMatch] = Editor.nodes(ed, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n if (!listItemMatch) return false;\n const [, listItemPath] = listItemMatch;\n if (!Editor.isStart(ed, anchor, listItemPath)) return false;\n\n const listAncestors = Array.from(\n Editor.nodes(ed, {\n at: listItemPath,\n match: n =>\n !Editor.isEditor(n) &&\n Element.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n })\n );\n\n if (listAncestors.length > 1) {\n Transforms.liftNodes(ed, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n return true;\n }\n\n Transforms.unwrapNodes(ed, {\n match: n =>\n !Editor.isEditor(n) &&\n Element.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n split: true,\n });\n Transforms.setNodes(ed, { type: 'paragraph' });\n return true;\n}\n\n/**\n * Forward-delete: delete an atomic node near the cursor (strictly inside, at start edge, or right before).\n * Returns true if a deletion was performed.\n */\nfunction tryDeleteAtomicForward(ed: Editor, anchor: Point): boolean {\n if (isStrictlyInsideAtomic(ed, anchor)) {\n const range = getAtomicRangeAtPoint(ed, anchor);\n if (range) deleteAtomicRange(ed, anchor, range);\n return true;\n }\n const fwdRange = getAtomicRangeAtPoint(ed, anchor);\n if (fwdRange && Point.equals(anchor, fwdRange.anchor)) {\n deleteAtomicRange(ed, anchor, fwdRange);\n return true;\n }\n // At an atomic's END edge (e.g. between adjacent links), fall through to remove the atomic\n // AFTER the caret; bailing here would let Slate eat one char of the next link.\n if (fwdRange && !Point.equals(anchor, fwdRange.focus)) return false;\n // Only eat a following atomic in the SAME block; else forward-delete at line end must merge\n // with the next block (Slate's default), not delete across the boundary.\n const next = atomicRangeAfter(ed, anchor);\n if (!next) return false;\n deleteAtomicRange(ed, next.at, next.range);\n return true;\n}\n\n/** Recover from stale selection paths after tree-restructuring operations. */\nfunction recoverStaleSelection(e: Editor): void {\n if (!e.selection) return;\n try {\n SlateNode.get(e, e.selection.anchor.path);\n SlateNode.get(e, e.selection.focus.path);\n return;\n } catch {\n // fall through to recovery\n }\n try {\n e.selection = { anchor: Editor.end(e, []), focus: Editor.end(e, []) };\n } catch {\n e.selection = null;\n }\n}\n\n/** Expand selection to atomic node bounds while preserving editor.marks. */\nfunction expandAtomicPreservingMarks(e: Editor): void {\n if (!e.selection) return;\n const savedMarks = e.marks;\n expandSelectionToAtomic(e);\n if (savedMarks) {\n e.marks = savedMarks;\n }\n}\n\n/**\n * Strip token marks from a range before replacement. When typing over an expanded selection,\n * Slate's insertText delete+insert runs withoutNormalizing, so the emptied node keeps its\n * tokenName/isEscapedDollar marks and the typed text inherits the old token's identity.\n */\nfunction stripAtomicMarksInRange(e: Editor, range: Range): void {\n Transforms.unsetNodes(e, ['tokenName', 'tokenOccurrence', 'isEscapedDollar', 'isRawToken'], {\n at: range,\n match: n => Text.isText(n) && (Boolean(n.tokenName) || Boolean(n.isEscapedDollar)),\n });\n}\n\n/** Install custom insertText / insertBreak overrides on the editor. */\nfunction installInsertOverrides(\n e: Editor,\n defaultTextStyleRef: DefaultTextStyleRef,\n onBeforeBreak: () => void\n): void {\n const { insertText, insertBreak } = e;\n\n e.insertText = text => {\n if (text && isLinkActive(e)) {\n // Expanded selection touching a link (auto-selected atomic): delete first so normalizeNode\n // removes the emptied <a> and text lands plain. Collapsed selections fall through below.\n if (e.selection && !Range.isCollapsed(e.selection)) {\n Transforms.delete(e);\n }\n exitLinkBeforeInsert(e);\n }\n if (text === ' ' && handleAutoformat(e, defaultTextStyleRef)) {\n return;\n }\n if (e.selection && !Range.isCollapsed(e.selection)) {\n stripAtomicMarksInRange(e, e.selection);\n }\n moveCursorPastAtomicIfNeeded(e);\n insertText(text);\n };\n\n e.insertBreak = () => {\n moveCursorPastAtomicIfNeeded(e);\n if (tryExitEmptyListItem(e)) return;\n onBeforeBreak();\n insertBreak();\n };\n}\n\n/**\n * Route plain-text insertion through editor.insertText instead of slate-react's native fast path,\n * which calls toDOMPoint while the DOM<->node map may be stale (crashing \"Cannot resolve a DOM node\").\n * Returning true makes slate-react skip its native path. IME input uses a different inputType, left untouched.\n */\nexport function handleTextInsert(e: Editor, event: InputEvent): boolean {\n if (event.inputType !== 'insertText' || typeof event.data !== 'string' || event.data === '') {\n return false;\n }\n if (!e.selection) return false;\n event.preventDefault();\n e.insertText(event.data);\n return true;\n}\n\n/** Install custom deleteBackward / deleteForward overrides on the editor. */\nfunction installDeleteOverrides(e: Editor): void {\n const { deleteBackward, deleteForward } = e;\n\n e.deleteBackward = unit => {\n const { selection } = e;\n if (selection && Range.isCollapsed(selection)) {\n if (tryDeleteAtomicBackward(e, selection.anchor)) return;\n if (tryUnwrapListItem(e, selection.anchor)) return;\n }\n deleteBackward(unit);\n };\n\n e.deleteForward = unit => {\n const { selection } = e;\n if (selection && Range.isCollapsed(selection)) {\n if (tryDeleteAtomicForward(e, selection.anchor)) return;\n }\n deleteForward(unit);\n };\n}\n\ninterface TokenRun {\n start: number;\n end: number;\n first: CustomText;\n}\n\nfunction getTokenRun(children: Element['children'], start: number): TokenRun | null {\n const first = children[start];\n if (!Text.isText(first) || !first.tokenName) return null;\n\n let end = start + 1;\n while (end < children.length) {\n const child = children[end];\n if (!Text.isText(child) || child.tokenName !== first.tokenName) break;\n end += 1;\n }\n return { start, end, first };\n}\n\n/** Apply at most one correction so Slate can continue normalizing incrementally. */\nfunction normalizeTokenRun(e: Editor, children: Element['children'], path: Path, run: TokenRun): boolean {\n const { start, end, first } = run;\n if (end - start === 1) {\n if (first.tokenOccurrence === undefined) return false;\n Transforms.unsetNodes(e, 'tokenOccurrence', { at: path.concat(start) });\n return true;\n }\n\n for (let index = start; index < end; index += 1) {\n const child = children[index] as CustomText;\n const occurrence = index - start;\n if (child.tokenOccurrence !== occurrence) {\n Transforms.setNodes(e, { tokenOccurrence: occurrence }, { at: path.concat(index) });\n return true;\n }\n }\n return false;\n}\n\n/**\n * Give adjacent occurrences of the same token distinct internal marks before Slate's default\n * normalizer can merge their text leaves. Kept here (instead of the token conversion pass) so\n * converting a freshly pasted token follows the unchanged, immediate repaint path.\n */\nfunction normalizeAdjacentTokenOccurrences(e: Editor, node: Element, path: Path): boolean {\n let start = 0;\n while (start < node.children.length) {\n const run = getTokenRun(node.children, start);\n if (run) {\n if (normalizeTokenRun(e, node.children, path, run)) return true;\n start = run.end;\n } else {\n start += 1;\n }\n }\n return false;\n}\n\n/**\n * normalizeNode rule stripping token identity from empty text nodes. Enter at a token's end splits\n * its leaf into an empty node that inherits `tokenName`, which would serialize a phantom `$token$`.\n */\nfunction installNormalizeOverride(e: Editor): void {\n const { normalizeNode } = e;\n e.normalizeNode = entry => {\n const [node, path] = entry;\n if (Element.isElement(node) && normalizeAdjacentTokenOccurrences(e, node, path)) {\n return;\n }\n if (Text.isText(node) && node.text === '' && (node.tokenName || node.isEscapedDollar)) {\n Transforms.unsetNodes(e, ['tokenName', 'tokenOccurrence', 'isEscapedDollar', 'isRawToken'], {\n at: path,\n });\n return;\n }\n // A link whose text was fully deleted leaves an empty <a> that serializes to a contentless\n // anchor; remove it so the link disappears entirely.\n if (Element.isElement(node) && node.type === 'link' && SlateNode.string(node) === '') {\n Transforms.removeNodes(e, { at: path });\n return;\n }\n normalizeNode(entry);\n };\n}\n\n/** Install custom onChange override on the editor. */\nfunction installOnChangeOverride(\n e: Editor,\n getSavedMarks: () => ReturnType<typeof Editor.marks>,\n clearSavedMarks: () => void\n): void {\n const { onChange } = e;\n e.onChange = () => {\n recoverStaleSelection(e);\n // Restore marks saved before insertBreak so updateActiveStyles (via onChange render) reads them.\n const saved = getSavedMarks();\n if (saved) {\n e.marks = saved;\n clearSavedMarks();\n }\n onChange();\n // Expand selection to atomic boundaries; preserve editor.marks since Transforms.select\n // resets them, which would break mark toggles (bold, italic, etc.).\n expandAtomicPreservingMarks(e);\n };\n}\n\nexport function useEditorSetup(defaultTextStyleRef: DefaultTextStyleRef): Editor {\n const editor = useMemo(() => {\n const e = withReact(createEditor());\n\n const { isInline } = e;\n e.isInline = element => (element.type === 'link' ? true : isInline(element));\n\n // Marks saved before insertBreak for onChange to restore: insertBreak's set_selection ops\n // clear editor.marks to null, so updateActiveStyles would read stale leaf marks instead.\n let savedMarksForOnChange: ReturnType<typeof Editor.marks> = null;\n\n installInsertOverrides(e, defaultTextStyleRef, () => {\n savedMarksForOnChange = Editor.marks(e);\n });\n installDeleteOverrides(e);\n installNormalizeOverride(e);\n installOnChangeOverride(\n e,\n () => savedMarksForOnChange,\n () => {\n savedMarksForOnChange = null;\n }\n );\n\n return e;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return editor;\n}\n\nexport function useInitialMarks(\n editor: Editor,\n isEditMode: boolean,\n defaultTextStyle: DefaultTextStyleRef['current']\n): void {\n const hasInitializedMarksRef = useRef(false);\n useEffect(() => {\n if (hasInitializedMarksRef.current) return;\n if (isEditMode && isEditorEmpty(editor)) {\n applyInitialMarks(editor, defaultTextStyle);\n hasInitializedMarksRef.current = true;\n }\n // Only run on mount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isEditMode, editor]);\n}\n", "import { useState, useCallback, useRef } from 'react';\nimport { Editor, Text, Range, Point, Path, Node as SlateNode } from 'slate';\n\nexport type AbsRange = { absStart: number; absEnd: number };\n\n/** Compute the absolute character offset of a Point by walking all text nodes. */\nexport function pointToAbsOffset(editor: Editor, point: Point): number {\n let offset = 0;\n for (const [textNode, path] of Editor.nodes<Text>(editor, {\n at: [],\n match: n => Text.isText(n),\n })) {\n if (Path.equals(path, point.path)) return offset + point.offset;\n offset += textNode.text.length;\n }\n return offset;\n}\n\n/** Convert a Slate Range to absolute character offsets. */\nfunction rangeToAbsOffsets(editor: Editor, range: Range): AbsRange {\n const [start, end] = Range.edges(range);\n return {\n absStart: pointToAbsOffset(editor, start),\n absEnd: pointToAbsOffset(editor, end),\n };\n}\n\n/** isStart=true biases boundary offsets to the next node rather than the preceding one. */\nexport function absOffsetToPoint(editor: Editor, absOffset: number, isStart = false): Point | null {\n let seen = 0;\n for (const [textNode, path] of Editor.nodes<Text>(editor, {\n at: [],\n match: n => Text.isText(n),\n })) {\n const len = textNode.text.length;\n if (isStart ? seen + len > absOffset : seen + len >= absOffset) {\n return { path, offset: absOffset - seen };\n }\n seen += len;\n }\n return null;\n}\n\nexport interface FakeHighlightResult {\n fakeHighlightAbs: AbsRange | null;\n fakeHighlightAbsRef: React.MutableRefObject<AbsRange | null>;\n updateFakeHighlight: (range: Range | null) => void;\n updateFakeHighlightAbs: (abs: AbsRange | null) => void;\n decorate: ([node, path]: [SlateNode, Path]) => Range[];\n}\n\nexport function useFakeHighlight(editor: Editor): FakeHighlightResult {\n const [fakeHighlightAbs, setFakeHighlightAbs] = useState<AbsRange | null>(null);\n const fakeHighlightAbsRef = useRef<AbsRange | null>(null);\n\n const updateFakeHighlight = useCallback(\n (range: Range | null) => {\n if (!range) {\n fakeHighlightAbsRef.current = null;\n setFakeHighlightAbs(null);\n return;\n }\n const abs = rangeToAbsOffsets(editor, range);\n fakeHighlightAbsRef.current = abs;\n setFakeHighlightAbs(abs);\n },\n [editor]\n );\n\n const updateFakeHighlightAbs = useCallback((abs: AbsRange | null) => {\n fakeHighlightAbsRef.current = abs;\n setFakeHighlightAbs(abs);\n }, []);\n\n const decorate = useCallback(\n ([node, path]: [SlateNode, Path]): Range[] => {\n // Use the ref so synchronous tree replacements see the latest offsets\n // without waiting for a state update (avoids a highlight-misalign flash).\n const abs = fakeHighlightAbsRef.current;\n if (!abs || !Text.isText(node)) return [];\n const { absStart, absEnd } = abs;\n let nodeAbsStart = 0;\n for (const [n, p] of Editor.nodes<Text>(editor, {\n at: [],\n match: nd => Text.isText(nd),\n })) {\n if (Path.equals(p, path)) break;\n nodeAbsStart += n.text.length;\n }\n const nodeAbsEnd = nodeAbsStart + node.text.length;\n const overlapStart = Math.max(absStart, nodeAbsStart);\n const overlapEnd = Math.min(absEnd, nodeAbsEnd);\n if (overlapStart >= overlapEnd) return [];\n return [\n {\n anchor: { path, offset: overlapStart - nodeAbsStart },\n focus: { path, offset: overlapEnd - nodeAbsStart },\n fakeHighlight: true,\n } as Range & { fakeHighlight: boolean },\n ];\n },\n // fakeHighlightAbs (state) triggers re-evaluation; fakeHighlightAbsRef provides the current value.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [fakeHighlightAbs, editor]\n );\n\n return {\n fakeHighlightAbs,\n fakeHighlightAbsRef,\n updateFakeHighlight,\n updateFakeHighlightAbs,\n decorate,\n };\n}\n", "/**\n * useContentSync - Manages editor value state, external content syncing,\n * and the onChange handler with history tracking.\n */\n\nimport { useState, useCallback, useRef, useEffect } from 'react';\nimport { Descendant, Editor, Transforms, Range, Node as SlateNode, Text, Point } from 'slate';\nimport { slateToHtml, htmlToSlate } from '../utils/slateUtils';\nimport { pointToAbsOffset } from './useFakeHighlight';\nimport type { AbsRange } from './useFakeHighlight';\nimport { TOKEN_PATTERN } from './useTokenMap';\n\n/** Clamp a Point so its path and offset are valid within the current tree. */\nfunction clampPoint(editor: Editor, point: Point): Point {\n try {\n const node = SlateNode.get(editor, point.path);\n if (Text.isText(node)) {\n return { path: point.path, offset: Math.min(point.offset, node.text.length) };\n }\n } catch {\n // Path doesn't exist in the new tree\n }\n // Fall back to the end of the document\n return Editor.end(editor, []);\n}\n\n/** Clamp a Selection so both anchor and focus are valid within the current tree. */\nfunction clampSelection(editor: Editor, selection: Range): Range {\n return {\n anchor: clampPoint(editor, selection.anchor),\n focus: clampPoint(editor, selection.focus),\n };\n}\n\n/** Safely restore a selection, falling back to end-of-document if the path is invalid. */\nfunction safeRestoreSelection(editor: Editor, selection: Range | null): void {\n try {\n if (selection) {\n Transforms.select(editor, clampSelection(editor, selection));\n } else {\n Transforms.select(editor, Editor.end(editor, []));\n }\n } catch {\n try {\n Transforms.select(editor, Editor.end(editor, []));\n } catch {\n // ignore - editor may be empty\n }\n }\n}\n\n/**\n * Restore selection by direct mutation so the tree swap and fake-highlight update batch\n * into one render (Transforms.select fires onChange, flashing stale highlight offsets).\n */\nfunction directRestoreSelection(editor: Editor, selection: Range | null): void {\n try {\n if (selection) {\n // eslint-disable-next-line no-param-reassign\n editor.selection = clampSelection(editor, selection);\n } else {\n const end = Editor.end(editor, []);\n // eslint-disable-next-line no-param-reassign\n editor.selection = { anchor: end, focus: end };\n }\n } catch {\n try {\n const end = Editor.end(editor, []);\n // eslint-disable-next-line no-param-reassign\n editor.selection = { anchor: end, focus: end };\n } catch {\n // ignore - editor may be empty\n }\n }\n}\n\ntype HistoryEntry = {\n html: string;\n /** Selection after this edit was applied. */\n selection: Editor['selection'];\n /** Selection before this edit was applied (used to restore cursor on undo). */\n preSelection: Editor['selection'];\n};\n\ninterface ContentSyncArgs {\n editor: Editor;\n initialValue: Descendant[];\n richTextContent: string;\n onContentChange: (html: string, immediate?: boolean) => void;\n updateActiveStyles: (isContentChange?: boolean) => void;\n updateFakeHighlightAbs: (abs: AbsRange | null) => void;\n fakeHighlightAbsRef: React.MutableRefObject<AbsRange | null>;\n hasFocusRef: React.MutableRefObject<boolean>;\n /** Authoritative editing ref, true before DOM focus. Used (not hasFocusRef) for the\n * tree-reset guard so a stale prop update can't reset the tree before focus lands. */\n isTextEditingRef: React.MutableRefObject<boolean>;\n lastSelectionRef: React.MutableRefObject<Editor['selection']>;\n /** Set by useContentSave; checked to detect round-trips and skip tree resets. */\n recentSavesRef?: React.MutableRefObject<Set<string>>;\n /** When true, accept the next external content change even if the editor has focus (e.g. Cmd+Z undo). */\n forceNextSyncRef?: React.MutableRefObject<boolean>;\n /** Optional post-processing step (e.g. re-apply token marks) after a forced tree reset. */\n transformTreeRef?: React.MutableRefObject<((tree: Descendant[]) => Descendant[]) | null>;\n /** Whether an initialValue identity change by itself should replace the editor tree.\n * Resolved-token mode needs this; raw token editing does not. */\n syncInitialValueChanges?: boolean;\n /** When set, requested via queueMicrotask after each content change to auto-resolve\n * newly typed $token$ patterns. The request may be coalesced during a paste burst. */\n autoResolveTokensRef?: React.MutableRefObject<((includeValueChanges?: boolean) => void) | null>;\n}\n\ninterface ContentSyncResult {\n value: Descendant[];\n handleChange: (newValue: Descendant[]) => void;\n lastEmittedHtmlRef: React.MutableRefObject<string>;\n}\n\n/** Consume the forceSync flag if set, returning its value. */\nfunction consumeForceSync(ref?: React.MutableRefObject<boolean>): boolean {\n const value = ref?.current ?? false;\n if (value && ref) {\n // eslint-disable-next-line no-param-reassign\n ref.current = false;\n }\n return value;\n}\n\n/** Skip the tree reset when the content is a known round-trip or the user is actively editing. */\nfunction shouldSkipSync(\n forceSync: boolean,\n richTextContent: string,\n recentSavesRef: React.MutableRefObject<Set<string>> | undefined,\n isTextEditingRef: React.MutableRefObject<boolean>,\n hasFocusRef: React.MutableRefObject<boolean>\n): boolean {\n if (forceSync) return false;\n if (recentSavesRef?.current.has(richTextContent)) return true;\n // Require focus, not just isTextEditing: editing richTextContent from the config\n // panel (editable blurred) is an external change that must still apply.\n if (isTextEditingRef.current && hasFocusRef.current) return true;\n return false;\n}\n\n/** True when neither external content nor a relevant initial-value change needs applying. */\nfunction shouldSkipUnchangedContent(\n explicitForceSync: boolean,\n contentMatchesLastEdit: boolean,\n initialValueChanged: boolean,\n syncInitialValueChanges: boolean\n): boolean {\n return !explicitForceSync && contentMatchesLastEdit && (!initialValueChanged || !syncInitialValueChanges);\n}\n\n/** Preserve the newest emitted value when an older save acknowledgement is ignored. */\nfunction recordSkippedExternalContent(\n isRecentSave: boolean,\n richTextContent: string,\n lastEmittedHtmlRef: React.MutableRefObject<string>\n): void {\n if (!isRecentSave) {\n // eslint-disable-next-line no-param-reassign\n lastEmittedHtmlRef.current = richTextContent;\n }\n}\n\n/** Select the cursor location associated with an incoming history entry. */\nfunction getSavedSelection(\n history: HistoryEntry[],\n incomingIdx: number,\n lastSelection: Editor['selection']\n): Editor['selection'] {\n if (incomingIdx === -1) return lastSelection;\n return history[incomingIdx + 1]?.preSelection || history[incomingIdx].selection || lastSelection;\n}\n\n/** Build a fresh tree for forced syncs; otherwise retain the memoized initial value. */\nfunction getTreeToApply(\n forceSync: boolean,\n richTextContent: string,\n initialValue: Descendant[],\n transformTree: ((tree: Descendant[]) => Descendant[]) | null | undefined\n): Descendant[] {\n if (!forceSync || !richTextContent) return initialValue;\n const parsed = htmlToSlate(richTextContent);\n return transformTree ? transformTree(parsed) : parsed;\n}\n\n/** Snap a point to the token boundary if it lands mid-token. */\nfunction snapToTokenEdge(editor: Editor, point: Point, isStart: boolean): Point {\n try {\n const [node] = Editor.node(editor, point);\n if (Text.isText(node) && (node as { tokenName?: string }).tokenName) {\n return { path: point.path, offset: isStart ? 0 : node.text.length };\n }\n } catch {\n // ignore invalid paths\n }\n return point;\n}\n\ninterface RestoreSelectionArgs {\n editor: Editor;\n savedSelection: Range | null;\n forceSync: boolean;\n isExternalContentChange: boolean;\n fakeHighlightAbsRef: React.MutableRefObject<AbsRange | null>;\n hasFocusRef: React.MutableRefObject<boolean>;\n updateFakeHighlightAbs: (abs: AbsRange | null) => void;\n}\n\n/** Restore selection and recompute fake-highlight abs offsets after a tree swap. */\nfunction restoreSelectionAndHighlight({\n editor,\n savedSelection,\n forceSync,\n isExternalContentChange,\n fakeHighlightAbsRef,\n hasFocusRef,\n updateFakeHighlightAbs,\n}: RestoreSelectionArgs): void {\n if (isExternalContentChange || forceSync) {\n // forceSync uses direct mutation so onChange doesn't fire before the\n // fake-highlight update below, keeping both in one React render.\n if (forceSync) {\n directRestoreSelection(editor, savedSelection);\n } else {\n safeRestoreSelection(editor, savedSelection);\n }\n }\n\n // Recompute fake-highlight abs offsets for the new tree from the restored selection when\n // a highlight was active and unfocused; otherwise clear (focus means real selection wins).\n if (fakeHighlightAbsRef.current !== null && !hasFocusRef.current && editor.selection) {\n let [start, end] = Range.isBackward(editor.selection)\n ? [editor.selection.focus, editor.selection.anchor]\n : [editor.selection.anchor, editor.selection.focus];\n\n // Snap mid-token endpoints to the boundary so the highlight covers the full token\n // (lengths change when toggling raw \"$mytoken$\" vs the resolved value).\n start = snapToTokenEdge(editor, start, true);\n end = snapToTokenEdge(editor, end, false);\n\n updateFakeHighlightAbs({\n absStart: pointToAbsOffset(editor, start),\n absEnd: pointToAbsOffset(editor, end),\n });\n } else {\n updateFakeHighlightAbs(null);\n }\n}\n\n/** Find the most recent history entry matching the given HTML. */\nfunction findHistoryIndex(history: HistoryEntry[], html: string): number {\n for (let i = history.length - 1; i >= 0; i -= 1) {\n if (history[i].html === html) return i;\n }\n return -1;\n}\n\n/** True when every operation is a selection change or plain text edit (i.e. typing). */\nfunction isTypingOnly(editor: Editor): boolean {\n return editor.operations.every(\n op => op.type === 'set_selection' || op.type === 'insert_text' || op.type === 'remove_text'\n );\n}\n\ninterface EmitContentArgs {\n editor: Editor;\n html: string;\n prevSelection: Editor['selection'];\n lastEmittedHtmlRef: React.MutableRefObject<string>;\n emittedHistoryRef: React.MutableRefObject<HistoryEntry[]>;\n historyPosRef: React.MutableRefObject<number>;\n onContentChange: (html: string, immediate?: boolean) => void;\n autoResolveTokensRef?: React.MutableRefObject<((includeValueChanges?: boolean) => void) | null>;\n}\n\n/** Record a content change in history and notify the parent (with auto-resolve). */\nfunction emitContentChange({\n editor,\n html,\n prevSelection,\n lastEmittedHtmlRef,\n emittedHistoryRef,\n historyPosRef,\n onContentChange,\n autoResolveTokensRef,\n}: EmitContentArgs): void {\n const typing = isTypingOnly(editor);\n // A complete $token$ with auto-resolve active saves immediately so the dashboard returns\n // the tokenMap without the 300ms idle wait -- first token resolves as fast as later ones.\n const hasBareToken =\n typing &&\n autoResolveTokensRef?.current != null &&\n new RegExp(TOKEN_PATTERN.source, TOKEN_PATTERN.flags).test(html);\n\n const pos = historyPosRef.current;\n // eslint-disable-next-line no-param-reassign\n lastEmittedHtmlRef.current = html;\n // eslint-disable-next-line no-param-reassign\n emittedHistoryRef.current = [\n ...emittedHistoryRef.current.slice(0, pos + 1),\n { html, selection: editor.selection, preSelection: prevSelection },\n ];\n // eslint-disable-next-line no-param-reassign\n historyPosRef.current = emittedHistoryRef.current.length - 1;\n onContentChange(html, hasBareToken || !typing);\n\n if (autoResolveTokensRef?.current) {\n // Dashboard token metadata can update between the paste and this microtask.\n // Read the ref when the task runs so the first paste uses the latest token map.\n queueMicrotask(() => autoResolveTokensRef.current?.());\n }\n}\n\n/** Cancel any pending coalesced selection-style recompute frame. */\nfunction cancelPendingStyleUpdate(styleUpdateRafRef: React.MutableRefObject<number | null>): void {\n if (styleUpdateRafRef.current !== null) {\n cancelAnimationFrame(styleUpdateRafRef.current);\n // eslint-disable-next-line no-param-reassign\n styleUpdateRafRef.current = null;\n }\n}\n\n/** Recompute styles synchronously for a content edit so the toolbar updates now,\n * superseding any pending selection-only frame. */\nfunction recomputeStylesForContentChange(\n styleUpdateRafRef: React.MutableRefObject<number | null>,\n updateActiveStyles: (isContentChange?: boolean) => void\n): void {\n cancelPendingStyleUpdate(styleUpdateRafRef);\n updateActiveStyles(true);\n}\n\n/** Schedule a style recompute for a selection-only change, coalesced to one per frame\n * (these fire continuously during a drag-select). */\nfunction scheduleStylesForSelectionChange(\n editor: Editor,\n styleUpdateRafRef: React.MutableRefObject<number | null>,\n updateActiveStyles: (isContentChange?: boolean) => void\n): void {\n if (styleUpdateRafRef.current !== null) return;\n // eslint-disable-next-line no-param-reassign\n styleUpdateRafRef.current = requestAnimationFrame(() => {\n // eslint-disable-next-line no-param-reassign\n styleUpdateRafRef.current = null;\n if (editor.selection) {\n updateActiveStyles(false);\n }\n });\n}\n\nexport function useContentSync({\n editor,\n initialValue,\n richTextContent,\n onContentChange,\n updateActiveStyles,\n updateFakeHighlightAbs,\n fakeHighlightAbsRef,\n hasFocusRef,\n isTextEditingRef,\n lastSelectionRef,\n recentSavesRef,\n forceNextSyncRef,\n transformTreeRef,\n syncInitialValueChanges = true,\n autoResolveTokensRef,\n}: ContentSyncArgs): ContentSyncResult {\n const [value, setValue] = useState<Descendant[]>(initialValue);\n const lastEmittedHtmlRef = useRef<string>(richTextContent);\n // rAF handle for coalescing selection-only style recomputes.\n const styleUpdateRafRef = useRef<number | null>(null);\n const emittedHistoryRef = useRef<HistoryEntry[]>([\n { html: richTextContent, selection: null, preSelection: null },\n ]);\n const historyPosRef = useRef<number>(0);\n const lastInitialValueRef = useRef<Descendant[]>(initialValue);\n\n // Sync external content changes (dashboard undo/redo), and re-sync when initialValue\n // changes without richTextContent (e.g. token marks added after mount).\n useEffect(() => {\n const initialValueChanged = initialValue !== lastInitialValueRef.current;\n lastInitialValueRef.current = initialValue;\n\n // Consume forceSync before the early-return: a toggle can be forceSync=true even when\n // richTextContent equals lastEmittedHtmlRef (e.g. \"$price$\" round-trips to same HTML).\n const explicitForceSync = consumeForceSync(forceNextSyncRef);\n\n const contentMatchesLastEdit = richTextContent === lastEmittedHtmlRef.current;\n if (\n shouldSkipUnchangedContent(\n explicitForceSync,\n contentMatchesLastEdit,\n initialValueChanged,\n syncInitialValueChanges\n )\n ) {\n return;\n }\n\n const history = emittedHistoryRef.current;\n const incomingIdx = findHistoryIndex(history, richTextContent);\n const isRecentSave = recentSavesRef?.current.has(richTextContent) ?? false;\n\n // If richTextContent matches last emitted, only initialValue changed; preserve pending\n // marks so in-progress format toggles (bold on collapsed cursor) aren't lost.\n const isExternalContentChange = richTextContent !== lastEmittedHtmlRef.current;\n\n // A value matching an EARLIER history point is an undo/redo revert (dashboard or\n // toolbar), which never sets forceNextSyncRef. Undo/redo must win, so treat it like\n // forceSync: bypass the typing guard and stale initialValue (parse fresh instead).\n // An older in-flight save can match an earlier history entry while the user has already\n // typed ahead. It is an acknowledgement, not undo, and must never replace the live tree.\n const isHistoryRevert = isExternalContentChange && incomingIdx !== -1 && !isRecentSave;\n const forceSync = explicitForceSync || isHistoryRevert;\n\n if (shouldSkipSync(forceSync, richTextContent, recentSavesRef, isTextEditingRef, hasFocusRef)) {\n recordSkippedExternalContent(isRecentSave, richTextContent, lastEmittedHtmlRef);\n return;\n }\n\n const pendingMarks = isExternalContentChange ? null : editor.marks;\n\n lastEmittedHtmlRef.current = richTextContent;\n if (incomingIdx !== -1) {\n historyPosRef.current = incomingIdx;\n }\n\n // On undo, restore the cursor to where it was BEFORE the undone edit.\n const savedSelection = getSavedSelection(history, incomingIdx, lastSelectionRef.current);\n\n // On forceSync, initialValue may be stale (parent memo skips while isTextEditing),\n // so parse HTML directly and re-apply token marks.\n const treeToApply = getTreeToApply(\n forceSync,\n richTextContent,\n initialValue,\n transformTreeRef?.current\n );\n setValue(treeToApply);\n // eslint-disable-next-line no-param-reassign\n editor.children = treeToApply;\n // eslint-disable-next-line no-param-reassign\n editor.selection = null;\n\n // Restore selection only when content actually changed (undo/redo, forceSync); skip on\n // an isTextEditing-toggle initialValue change to avoid a stale expanded selection.\n restoreSelectionAndHighlight({\n editor,\n savedSelection,\n forceSync,\n isExternalContentChange,\n fakeHighlightAbsRef,\n hasFocusRef,\n updateFakeHighlightAbs,\n });\n\n if (pendingMarks) {\n // eslint-disable-next-line no-param-reassign\n editor.marks = pendingMarks;\n }\n\n // onChange repaints the readOnly Editable (direct mutation leaves view-mode tokens stale).\n // Skip when focused, else selection-sync crashes on a DOM missing the just-set tree.\n if (!hasFocusRef.current) {\n editor.onChange();\n }\n }, [\n initialValue,\n richTextContent,\n editor,\n lastSelectionRef,\n hasFocusRef,\n syncInitialValueChanges,\n fakeHighlightAbsRef,\n forceNextSyncRef,\n isTextEditingRef,\n recentSavesRef,\n transformTreeRef,\n updateFakeHighlightAbs,\n ]);\n\n // Cancel any pending selection-style recompute frame on unmount.\n useEffect(() => {\n return () => cancelPendingStyleUpdate(styleUpdateRafRef);\n }, []);\n\n const handleChange = useCallback(\n (newValue: Descendant[]) => {\n setValue(newValue);\n\n const prevSelection = lastSelectionRef.current;\n if (editor.selection) {\n // eslint-disable-next-line no-param-reassign\n lastSelectionRef.current = editor.selection;\n }\n\n const isContentChange = editor.operations.some(op => op.type !== 'set_selection');\n\n if (isContentChange) {\n const html = slateToHtml(newValue);\n if (html !== lastEmittedHtmlRef.current) {\n emitContentChange({\n editor,\n html,\n prevSelection,\n lastEmittedHtmlRef,\n emittedHistoryRef,\n historyPosRef,\n onContentChange,\n autoResolveTokensRef,\n });\n }\n }\n\n if (hasFocusRef.current || editor.selection) {\n if (isContentChange) {\n recomputeStylesForContentChange(styleUpdateRafRef, updateActiveStyles);\n } else {\n scheduleStylesForSelectionChange(editor, styleUpdateRafRef, updateActiveStyles);\n }\n }\n\n if (\n isContentChange &&\n fakeHighlightAbsRef.current &&\n hasFocusRef.current &&\n editor.selection &&\n Range.isCollapsed(editor.selection)\n ) {\n updateFakeHighlightAbs(null);\n }\n },\n [\n editor,\n onContentChange,\n updateActiveStyles,\n updateFakeHighlightAbs,\n fakeHighlightAbsRef,\n hasFocusRef,\n lastSelectionRef,\n autoResolveTokensRef,\n ]\n );\n\n return { value, handleChange, lastEmittedHtmlRef };\n}\n", "/**\n * useKeyboardShortcuts - Handles keyboard shortcuts, Enter/Tab in lists,\n * and select-all within the Slate editor.\n */\n\nimport { useCallback } from 'react';\nimport { Editor, Transforms, Element, Text } from 'slate';\nimport { CustomElement, FormatCommand } from '../types';\n\ninterface KeyboardShortcutsArgs {\n editor: Editor;\n applyFormat: (command: FormatCommand, value?: string) => void;\n resetToDefault: () => void;\n openLinkPopover: () => void;\n stepFontSize: (delta: number) => void;\n}\n\n/** Handle Enter key: lift empty nested list items to parent. */\nfunction handleEnterKey(editor: Editor, event: React.KeyboardEvent): void {\n if (!editor.selection) return;\n\n const [listItemMatch] = Editor.nodes(editor, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n if (!listItemMatch) return;\n\n const [listItemNode, listItemPath] = listItemMatch;\n const isEmpty =\n Element.isElement(listItemNode) &&\n listItemNode.children.length === 1 &&\n Text.isText(listItemNode.children[0]) &&\n listItemNode.children[0].text === '';\n if (!isEmpty) return;\n\n const [parentList] = Editor.nodes(editor, {\n at: listItemPath,\n match: n =>\n !Editor.isEditor(n) &&\n Element.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n });\n if (!parentList) return;\n\n const [, parentListPath] = parentList;\n const [grandparentListItem] = Editor.nodes(editor, {\n at: parentListPath,\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n if (!grandparentListItem) return;\n\n event.preventDefault();\n Transforms.liftNodes(editor, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n}\n\n/** Handle Tab key: indent list item by wrapping in a nested list. */\nfunction handleTabKey(editor: Editor, event: React.KeyboardEvent): void {\n if (!editor.selection) return;\n\n const [match] = Editor.nodes(editor, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n if (!match) return;\n\n event.preventDefault();\n const [, listItemPath] = match;\n\n const [parentList] = Editor.nodes(editor, {\n at: listItemPath,\n match: n =>\n !Editor.isEditor(n) &&\n Element.isElement(n) &&\n (n.type === 'bulleted-list' || n.type === 'numbered-list'),\n });\n if (!parentList) return;\n\n const [parentListNode] = parentList;\n const parentListElement = parentListNode as CustomElement;\n const listType: 'bulleted-list' | 'numbered-list' =\n parentListElement.type === 'numbered-list' ? 'numbered-list' : 'bulleted-list';\n Transforms.wrapNodes(\n editor,\n { type: listType, children: [] },\n {\n at: listItemPath,\n }\n );\n}\n\n/** Cycle text alignment: left -> center -> right -> justify -> left */\nfunction cycleAlignment(editor: Editor, applyFormat: (cmd: FormatCommand) => void): void {\n const cycle: Record<string, FormatCommand> = {\n left: 'justifyCenter',\n center: 'justifyRight',\n right: 'justifyFull',\n justify: 'justifyLeft',\n };\n\n const [listItemMatch] = Editor.nodes(editor, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && n.type === 'list-item',\n });\n const [blockMatch] = Editor.nodes(editor, {\n match: n => !Editor.isEditor(n) && Element.isElement(n) && Editor.isBlock(editor, n),\n });\n\n const node = listItemMatch?.[0] || blockMatch?.[0];\n const current = (node as { align?: string })?.align || 'left';\n applyFormat(cycle[current] || 'justifyCenter');\n}\n\nexport function useKeyboardShortcuts({\n editor,\n applyFormat,\n resetToDefault,\n openLinkPopover,\n stepFontSize,\n}: KeyboardShortcutsArgs): {\n handleKeyDown: (event: React.KeyboardEvent) => void;\n} {\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n const mod = event.metaKey || event.ctrlKey;\n\n if (event.key === 'a' && mod) {\n event.preventDefault();\n Transforms.select(editor, {\n anchor: Editor.start(editor, []),\n focus: Editor.end(editor, []),\n });\n return;\n }\n\n // Cmd+key (no Shift)\n if (mod && !event.shiftKey) {\n const cmdHandled = handleModShortcut(event, applyFormat, openLinkPopover, resetToDefault);\n if (cmdHandled) return;\n }\n\n // Cmd+Shift+key\n if (mod && event.shiftKey) {\n const shiftHandled = handleModShiftShortcut(event, editor, applyFormat, stepFontSize);\n if (shiftHandled) return;\n }\n\n if (event.key === 'Enter') {\n handleEnterKey(editor, event);\n return;\n }\n if (event.key === 'Tab' && !event.shiftKey) {\n handleTabKey(editor, event);\n // If handleTabKey didn't preventDefault (cursor not in a list),\n // insert a tab character so Tab never leaves the editor.\n if (!event.defaultPrevented) {\n event.preventDefault();\n editor.insertText('\\t');\n }\n }\n },\n [editor, applyFormat, resetToDefault, openLinkPopover, stepFontSize]\n );\n\n return { handleKeyDown };\n}\n\n/** Cmd+key shortcuts (without Shift). Returns true if handled. */\nfunction handleModShortcut(\n event: React.KeyboardEvent,\n applyFormat: (cmd: FormatCommand) => void,\n openLinkPopover: () => void,\n resetToDefault: () => void\n): boolean {\n switch (event.key) {\n case 'b':\n event.preventDefault();\n applyFormat('bold');\n return true;\n case 'i':\n event.preventDefault();\n applyFormat('italic');\n return true;\n case 'u':\n event.preventDefault();\n applyFormat('underline');\n return true;\n case 'k':\n event.preventDefault();\n openLinkPopover();\n return true;\n default:\n break;\n }\n if (event.key === '\\\\' || event.code === 'Backslash') {\n event.preventDefault();\n resetToDefault();\n return true;\n }\n return false;\n}\n\n/** Cmd+Shift+key shortcuts. Returns true if handled. */\nfunction handleModShiftShortcut(\n event: React.KeyboardEvent,\n editor: Editor,\n applyFormat: (cmd: FormatCommand) => void,\n stepFontSize: (delta: number) => void\n): boolean {\n const key = event.key.toLowerCase();\n if (key === 'x') {\n event.preventDefault();\n applyFormat('strikethrough');\n return true;\n }\n if (event.key === ',' || event.key === '<') {\n event.preventDefault();\n stepFontSize(-2);\n return true;\n }\n if (event.key === '.' || event.key === '>') {\n event.preventDefault();\n stepFontSize(2);\n return true;\n }\n if (key === 'l') {\n event.preventDefault();\n cycleAlignment(editor, applyFormat);\n return true;\n }\n // Cmd+Shift+7 -> numbered list (event.key is '&' on Mac with Shift+7)\n if (event.key === '&' || event.key === '7') {\n event.preventDefault();\n applyFormat('insertOrderedList');\n return true;\n }\n // Cmd+Shift+8 -> bulleted list (event.key is '*' on Mac with Shift+8)\n if (event.key === '*' || event.key === '8') {\n event.preventDefault();\n applyFormat('insertUnorderedList');\n return true;\n }\n return false;\n}\n", "/**\n * useStepFontSize - Step font size by delta px, clamped to [8, 96].\n * Mixed-size selections step each text node independently.\n */\n\nimport { useCallback, useEffect } from 'react';\nimport { Editor, Transforms, Text, Range, Point } from 'slate';\nimport { pointToAbsOffset, absOffsetToPoint } from './useFakeHighlight';\nimport type { AbsRange } from './useFakeHighlight';\n\nconst MIN_FONT_SIZE = 8;\nconst MAX_FONT_SIZE = 96;\n\nfunction clampFontSize(size: number): number {\n return Math.min(MAX_FONT_SIZE, Math.max(MIN_FONT_SIZE, size));\n}\n\n/** Restore editor.selection from abs highlight or last known selection. */\nfunction restoreSelection(\n editor: Editor,\n fakeHighlightAbsRef: React.MutableRefObject<AbsRange | null>,\n lastSelectionRef: React.MutableRefObject<Editor['selection']>\n): void {\n if (!editor.selection && fakeHighlightAbsRef.current) {\n const s = absOffsetToPoint(editor, fakeHighlightAbsRef.current.absStart, true);\n const e = absOffsetToPoint(editor, fakeHighlightAbsRef.current.absEnd);\n // eslint-disable-next-line no-param-reassign\n if (s && e) editor.selection = { anchor: s, focus: e };\n }\n if (!editor.selection && lastSelectionRef.current) {\n // eslint-disable-next-line no-param-reassign\n editor.selection = lastSelectionRef.current;\n }\n}\n\n/** Step font size for a collapsed cursor (no range selection). */\nfunction stepCollapsed(editor: Editor, delta: number, updateActiveStyles: () => void): void {\n const marks = Editor.marks(editor);\n const current = marks?.fontSize ? Number.parseInt(String(marks.fontSize), 10) : 14;\n Editor.addMark(editor, 'fontSize', `${clampFontSize(current + delta)}px`);\n updateActiveStyles();\n}\n\n/** Collect per-node font sizes and ranges for a range selection. */\nfunction collectTextEntries(editor: Editor): { size: number; start: Point; end: Point }[] {\n if (!editor.selection) return [];\n const [selStart, selEnd] = Range.edges(editor.selection);\n const entries: { size: number; start: Point; end: Point }[] = [];\n for (const [node, path] of Editor.nodes<Text>(editor, {\n at: editor.selection,\n match: n => Text.isText(n),\n })) {\n const fontSize = (node as unknown as Record<string, unknown>).fontSize as string | undefined;\n const cur = fontSize ? Number.parseInt(fontSize, 10) : 14;\n const nodeStart = Editor.start(editor, path);\n const nodeEnd = Editor.end(editor, path);\n const start = Point.compare(nodeStart, selStart) >= 0 ? nodeStart : selStart;\n const end = Point.compare(nodeEnd, selEnd) <= 0 ? nodeEnd : selEnd;\n entries.push({ size: cur, start, end });\n }\n return entries;\n}\n\n/** Apply font size delta to each text entry in reverse order. */\nfunction applyFontSizeEntries(\n editor: Editor,\n entries: { size: number; start: Point; end: Point }[],\n delta: number\n): void {\n for (let i = entries.length - 1; i >= 0; i -= 1) {\n const { size, start, end } = entries[i];\n Transforms.setNodes(editor, { fontSize: `${clampFontSize(size + delta)}px` } as Partial<Text>, {\n at: { anchor: start, focus: end },\n match: n => Text.isText(n),\n split: true,\n });\n }\n}\n\ninterface StepFontSizeArgs {\n editor: Editor;\n fakeHighlightAbsRef: React.MutableRefObject<AbsRange | null>;\n lastSelectionRef: React.MutableRefObject<Editor['selection']>;\n updateFakeHighlightAbs: (abs: AbsRange | null) => void;\n updateActiveStyles: () => void;\n registerStepFontSize: (fn: (delta: number) => void) => void;\n}\n\nexport function useStepFontSize({\n editor,\n fakeHighlightAbsRef,\n lastSelectionRef,\n updateFakeHighlightAbs,\n updateActiveStyles,\n registerStepFontSize,\n}: StepFontSizeArgs): (delta: number) => void {\n const stepFontSize = useCallback(\n (delta: number) => {\n restoreSelection(editor, fakeHighlightAbsRef, lastSelectionRef);\n if (!editor.selection) return;\n\n if (Range.isCollapsed(editor.selection)) {\n stepCollapsed(editor, delta, updateActiveStyles);\n return;\n }\n\n const absStart = fakeHighlightAbsRef.current\n ? fakeHighlightAbsRef.current.absStart\n : pointToAbsOffset(editor, Range.edges(editor.selection)[0]);\n const absEnd = fakeHighlightAbsRef.current\n ? fakeHighlightAbsRef.current.absEnd\n : pointToAbsOffset(editor, Range.edges(editor.selection)[1]);\n\n const entries = collectTextEntries(editor);\n applyFontSizeEntries(editor, entries, delta);\n\n updateFakeHighlightAbs({ absStart, absEnd });\n const newStart = absOffsetToPoint(editor, absStart, true);\n const newEnd = absOffsetToPoint(editor, absEnd);\n if (newStart && newEnd) {\n // eslint-disable-next-line no-param-reassign\n editor.selection = { anchor: newStart, focus: newEnd };\n updateActiveStyles();\n }\n globalThis.getSelection()?.removeAllRanges();\n },\n [editor, fakeHighlightAbsRef, lastSelectionRef, updateFakeHighlightAbs, updateActiveStyles]\n );\n\n useEffect(() => {\n registerStepFontSize(stepFontSize);\n }, [registerStepFontSize, stepFontSize]);\n\n return stepFontSize;\n}\n", "/**\n * useStepLineSpacing - Step line spacing by delta (0.10 = 10%), clamped to [1.00, 3.00].\n * Mixed-height blocks step independently (same pattern as useStepFontSize).\n */\n\nimport { useCallback, useEffect } from 'react';\nimport { Editor, Transforms, Range, Element as SlateElement, Text } from 'slate';\nimport { pointToAbsOffset, absOffsetToPoint } from './useFakeHighlight';\nimport type { AbsRange } from './useFakeHighlight';\n\nconst MIN_LINE_HEIGHT = 1;\nconst MAX_LINE_HEIGHT = 3;\nconst LINE_HEIGHT_STEP = 0.1;\n\nfunction clampLineHeight(value: number): number {\n return Math.min(MAX_LINE_HEIGHT, Math.max(MIN_LINE_HEIGHT, value));\n}\n\n/** True when every child of the element is inline (text or inline element). */\nfunction isLeafBlock(editor: Editor, node: SlateElement): boolean {\n return node.children.every(child => Text.isText(child) || editor.isInline(child));\n}\n\n/** Round to 2 decimal places to avoid floating-point drift. */\nfunction roundLineHeight(value: number): string {\n return clampLineHeight(value).toFixed(2);\n}\n\ninterface StepLineSpacingArgs {\n editor: Editor;\n fakeHighlightAbsRef: React.MutableRefObject<AbsRange | null>;\n lastSelectionRef: React.MutableRefObject<Editor['selection']>;\n updateFakeHighlightAbs: (abs: AbsRange | null) => void;\n updateActiveStyles: () => void;\n registerStepLineSpacing: (fn: (delta: number) => void) => void;\n}\n\nexport function useStepLineSpacing({\n editor,\n fakeHighlightAbsRef,\n lastSelectionRef,\n updateFakeHighlightAbs,\n updateActiveStyles,\n registerStepLineSpacing,\n}: StepLineSpacingArgs): (delta: number) => void {\n const stepLineSpacing = useCallback(\n (delta: number) => {\n // Restore selection from fake highlight or last known selection\n if (!editor.selection && fakeHighlightAbsRef.current) {\n const s = absOffsetToPoint(editor, fakeHighlightAbsRef.current.absStart, true);\n const e = absOffsetToPoint(editor, fakeHighlightAbsRef.current.absEnd);\n if (s && e) {\n // eslint-disable-next-line no-param-reassign\n editor.selection = { anchor: s, focus: e };\n }\n }\n if (!editor.selection && lastSelectionRef.current) {\n // eslint-disable-next-line no-param-reassign\n editor.selection = lastSelectionRef.current;\n }\n if (!editor.selection) return;\n\n const at = Range.isCollapsed(editor.selection)\n ? editor.selection\n : Editor.unhangRange(editor, editor.selection);\n\n // Save abs offsets before modifying the tree\n const absStart = fakeHighlightAbsRef.current\n ? fakeHighlightAbsRef.current.absStart\n : pointToAbsOffset(editor, Range.edges(editor.selection)[0]);\n const absEnd = fakeHighlightAbsRef.current\n ? fakeHighlightAbsRef.current.absEnd\n : pointToAbsOffset(editor, Range.edges(editor.selection)[1]);\n\n // Collect leaf blocks (blocks whose children are all inline) and step each independently\n const blocks = Array.from(\n Editor.nodes(editor, {\n at,\n match: n =>\n !Editor.isEditor(n) &&\n SlateElement.isElement(n) &&\n Editor.isBlock(editor, n) &&\n isLeafBlock(editor, n),\n })\n );\n\n const step = delta > 0 ? LINE_HEIGHT_STEP : -LINE_HEIGHT_STEP;\n for (let i = blocks.length - 1; i >= 0; i -= 1) {\n const [node, path] = blocks[i];\n const current = Number.parseFloat(\n (node as SlateElement & { lineHeight?: string }).lineHeight || '1.5'\n );\n Transforms.setNodes(\n editor,\n { lineHeight: roundLineHeight(current + step) } as Partial<SlateElement>,\n { at: path }\n );\n }\n\n // Preserve fake highlight\n updateFakeHighlightAbs({ absStart, absEnd });\n const newStart = absOffsetToPoint(editor, absStart, true);\n const newEnd = absOffsetToPoint(editor, absEnd);\n if (newStart && newEnd) {\n // eslint-disable-next-line no-param-reassign\n editor.selection = { anchor: newStart, focus: newEnd };\n updateActiveStyles();\n }\n globalThis.getSelection()?.removeAllRanges();\n },\n [editor, fakeHighlightAbsRef, lastSelectionRef, updateFakeHighlightAbs, updateActiveStyles]\n );\n\n useEffect(() => {\n registerStepLineSpacing(stepLineSpacing);\n }, [registerStepLineSpacing, stepLineSpacing]);\n\n return stepLineSpacing;\n}\n", "/**\n * useFocusHandlers - Focus/blur for the Slate editor: focus gating when not\n * editing, blur deactivation with configPanel detection, fake highlight on blur.\n */\n\nimport { useCallback } from 'react';\nimport { Editor, Range } from 'slate';\nimport { isSuppressBlurDeactivation, isMouseSelecting } from '../activeInstance';\nimport { safeDeselect } from '../utils/slateUtils';\n\ninterface FocusHandlersArgs {\n editor: Editor;\n editableRef: React.RefObject<HTMLDivElement | null>;\n hasFocusRef: React.MutableRefObject<boolean>;\n isTextEditingRef: React.MutableRefObject<boolean>;\n wasTextEditingRef: React.MutableRefObject<boolean>;\n /** Fallback selection ref -- continuously updated in handleChange. */\n lastSelectionRef: React.MutableRefObject<Editor['selection']>;\n /** When true, the fake highlight was explicitly dismissed and must not\n * reappear until the user makes a fresh expanded selection. */\n highlightDismissedRef: React.MutableRefObject<boolean>;\n saveSelection: () => void;\n onEnterSkipLinkFlow?: (selection: Range | null) => void;\n /** Save selection for Escape-from-panel without deactivating text editing. */\n onSavePreEditSelection?: (selection: Range | null) => void;\n updateFakeHighlight: (sel: Range | null) => void;\n updateFakeHighlightAbs: (abs: null) => void;\n onFocusGained?: (editable: HTMLDivElement | null, editor: Editor | null) => void;\n onFocusLost?: () => void;\n onDeactivateTextEditing?: () => void;\n}\n\ninterface FocusHandlersResult {\n handleFocus: () => void;\n handleBlur: (e: React.FocusEvent) => void;\n}\n\n/** Find the editor config panel element in the DOM. */\nfunction findConfigPanel(): Element | null {\n return (\n document\n .querySelector('[data-test=\"editor-richTextContent\"]')\n ?.closest('[class*=\"StyledInsetWrapper\"]') ||\n document.querySelector('[data-test=\"editor-richTextContent\"]') ||\n document.querySelector('[data-test=\"editor-purerichtext\"]') ||\n document.querySelector('[data-test=\"sidebar-content\"]') ||\n null\n );\n}\n\n/** Check if blur target is within a known panel UI element. */\nfunction isFocusInPanelUI(relatedTarget: HTMLElement | null, configPanel: Element | null): boolean {\n if (!relatedTarget) return false;\n const isSkipLink = relatedTarget.closest('[data-test=\"skip-link-config\"]') != null;\n const isPopover = relatedTarget.closest('[data-test=\"popover\"], [data-test-popover-id]') != null;\n const isMenu = relatedTarget.closest('[data-test=\"menu\"]') != null;\n const isSidebar = relatedTarget.closest('[data-test=\"sidebar-content\"]') != null;\n const isCollapsiblePanel = relatedTarget.closest('[data-test=\"collapsible-panel\"]') != null;\n const isVizConfigPanel = relatedTarget.closest('[data-test=\"viz-config-panel\"]') != null;\n const isFlyoutPane = relatedTarget.closest('[data-test=\"flyout-pane\"]') != null;\n return (\n Boolean(configPanel?.contains(relatedTarget)) ||\n isSkipLink ||\n isPopover ||\n isMenu ||\n isSidebar ||\n isCollapsiblePanel ||\n isVizConfigPanel ||\n isFlyoutPane\n );\n}\n\nexport function useFocusHandlers({\n editor,\n editableRef,\n hasFocusRef,\n isTextEditingRef,\n wasTextEditingRef,\n lastSelectionRef,\n highlightDismissedRef,\n saveSelection,\n onSavePreEditSelection,\n updateFakeHighlight,\n updateFakeHighlightAbs,\n onFocusGained,\n onFocusLost,\n onDeactivateTextEditing,\n}: FocusHandlersArgs): FocusHandlersResult {\n const handleFocus = useCallback(() => {\n if (wasTextEditingRef.current) {\n // Returning from config panel: clear the highlight now for non-Escape paths\n // (click back, Tab). The Escape rAF sets its own selection after, so this is harmless.\n updateFakeHighlightAbs(null);\n // eslint-disable-next-line no-param-reassign\n wasTextEditingRef.current = false;\n }\n if (!isTextEditingRef.current) {\n editableRef.current?.blur();\n safeDeselect(editor);\n globalThis.getSelection()?.removeAllRanges();\n return;\n }\n // eslint-disable-next-line no-param-reassign\n hasFocusRef.current = true;\n onFocusGained?.(editableRef.current, editor);\n }, [onFocusGained, editor, editableRef, hasFocusRef, wasTextEditingRef, updateFakeHighlightAbs]);\n\n const handleBlur = useCallback(\n (e: React.FocusEvent) => {\n saveSelection();\n // eslint-disable-next-line no-param-reassign\n hasFocusRef.current = false;\n\n // Current editor selection, falling back to lastSelectionRef (updated in handleChange).\n const sel = editor.selection\n ? { anchor: { ...editor.selection.anchor }, focus: { ...editor.selection.focus } }\n : lastSelectionRef.current;\n\n // Show fake highlight only if still editing, selection is expanded, and not\n // explicitly dismissed (Escape / arrow key).\n const canShowFakeHighlight =\n isTextEditingRef.current && !highlightDismissedRef.current && sel && !Range.isCollapsed(sel);\n\n if (isSuppressBlurDeactivation()) {\n if (canShowFakeHighlight) {\n updateFakeHighlight(sel);\n }\n return;\n }\n\n if (isMouseSelecting()) {\n onFocusLost?.();\n return;\n }\n\n const relatedTarget = e.relatedTarget instanceof HTMLElement ? e.relatedTarget : null;\n const configPanel = findConfigPanel();\n const focusStaysInPanel = isFocusInPanelUI(relatedTarget, configPanel);\n\n if (focusStaysInPanel) {\n // Save selection for Escape-from-panel via savePreEditSelection (not\n // enterSkipLinkFlow) so isTextEditing stays true: Editable non-readOnly, caret visible.\n onSavePreEditSelection?.(sel);\n if (canShowFakeHighlight) {\n updateFakeHighlight(sel);\n }\n globalThis.getSelection()?.removeAllRanges();\n }\n\n if (!focusStaysInPanel) {\n updateFakeHighlight(null);\n // eslint-disable-next-line no-param-reassign\n wasTextEditingRef.current = false;\n // eslint-disable-next-line no-param-reassign\n lastSelectionRef.current = null;\n safeDeselect(editor);\n globalThis.getSelection()?.removeAllRanges();\n onDeactivateTextEditing?.();\n }\n\n onFocusLost?.();\n },\n [\n saveSelection,\n hasFocusRef,\n editor,\n lastSelectionRef,\n isTextEditingRef,\n highlightDismissedRef,\n onFocusLost,\n updateFakeHighlight,\n onSavePreEditSelection,\n wasTextEditingRef,\n onDeactivateTextEditing,\n ]\n );\n\n return { handleFocus, handleBlur };\n}\n", "/** useMouseHandlers - Slate mouse handlers: mousedown (edit activation, drag-to-select\n * stopPropagation), empty-space click (caret placement), and drag prevention. */\n\nimport { useCallback } from 'react';\nimport { Editor, Range, Transforms } from 'slate';\nimport { ReactEditor } from 'slate-react';\nimport { setMouseSelecting, isMouseSelecting, setSuppressNextEditClick } from '../activeInstance';\nimport { safeSelectEnd, editorContentOverflows } from '../utils/slateUtils';\n\n// Distance (px) a pointer must travel before a press is treated as a viz drag\n// rather than a click. Matches the dashboard canvas move threshold.\nconst MOVE_THRESHOLD = 4;\n\n// Place the Slate caret at a viewport point for click-to-edit. `target` is a\n// fallback when the point can't be resolved (e.g. the inline <a>); `editableEl`\n// gates the end-of-content fallback to non-scrollable content so the view can't jump.\nfunction placeCaretAtPoint(\n editor: Editor,\n clientX: number,\n clientY: number,\n target?: Node | null,\n editableEl?: HTMLElement | null\n): void {\n try {\n let domRange: globalThis.Range | null = null;\n // Local interface avoids lib.dom's deprecated caretRangeFromPoint signature; both APIs\n // are needed for cross-browser caret resolution (Firefox lacks caretRangeFromPoint).\n interface CaretDocument {\n caretRangeFromPoint?: (x: number, y: number) => globalThis.Range | null;\n caretPositionFromPoint?: (x: number, y: number) => { offsetNode: Node; offset: number } | null;\n }\n const doc = document as unknown as CaretDocument;\n if (typeof doc.caretRangeFromPoint === 'function') {\n domRange = doc.caretRangeFromPoint(clientX, clientY);\n } else if (typeof doc.caretPositionFromPoint === 'function') {\n const pos = doc.caretPositionFromPoint(clientX, clientY);\n if (pos) {\n const r = document.createRange();\n r.setStart(pos.offsetNode, pos.offset);\n r.collapse(true);\n domRange = r;\n }\n }\n if (domRange) {\n const sel = globalThis.getSelection();\n sel?.removeAllRanges();\n sel?.addRange(domRange);\n const point = ReactEditor.toSlatePoint(editor, [domRange.startContainer, domRange.startOffset], {\n exactMatch: false,\n suppressThrow: true,\n });\n if (point) {\n Transforms.select(editor, point);\n return;\n }\n }\n // Caret landed on a node toSlatePoint can't map (e.g. the inline <a>). Resolve the clicked\n // element to a path and place the caret at its start, not at doc end (which scrolls away).\n if (target) {\n const node = ReactEditor.toSlateNode(editor, target);\n const path = ReactEditor.findPath(editor, node);\n Transforms.select(editor, Editor.start(editor, path));\n return;\n }\n } catch {\n // fall through to end-of-content\n }\n // Last resort: jump to content end, but only when not scrollable -- else the jump scrolls the box\n // away from the click. When scrollable, leave the selection at the closest resolvable position.\n if (!editorContentOverflows(editableEl ?? null)) {\n safeSelectEnd(editor);\n }\n}\n\ninterface MouseHandlersArgs {\n editor: Editor;\n editableRef: React.RefObject<HTMLDivElement | null>;\n containerRef: React.RefObject<HTMLDivElement | null>;\n isEditMode: boolean;\n isTextEditing: boolean;\n onActivateTextEditing?: () => void;\n clearFakeHighlight: () => void;\n}\n\ninterface MouseHandlersResult {\n handleMouseDown: (e: React.MouseEvent) => void;\n handleEmptySpaceClick: (e: React.MouseEvent) => void;\n handleDragStart: (e: React.DragEvent) => void;\n}\n\nexport function useMouseHandlers({\n editor,\n editableRef,\n containerRef,\n isEditMode,\n isTextEditing,\n onActivateTextEditing,\n clearFakeHighlight,\n}: MouseHandlersArgs): MouseHandlersResult {\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n if (isEditMode && !isTextEditing) {\n const isVizSelected = containerRef.current?.closest('[data-selected=\"true\"]') != null;\n if (isVizSelected) {\n // Once selected, a press on the text content must only enter editing, never move\n // the block, so stop it reaching the canvas's drag-to-move listener.\n e.stopPropagation();\n }\n // Don't enter editing on mousedown: let the press bubble so the canvas can move the viz\n // on drag; only a click (pointer stays put) enters editing on mouseup and places caret.\n // Reset stale suppression from a prior move with no trailing click.\n setSuppressNextEditClick(false);\n const startX = e.clientX;\n const startY = e.clientY;\n const onMouseUp = (ev: MouseEvent): void => {\n document.removeEventListener('mouseup', onMouseUp, true);\n const moved =\n Math.abs(ev.clientX - startX) > MOVE_THRESHOLD ||\n Math.abs(ev.clientY - startY) > MOVE_THRESHOLD;\n if (moved) {\n // A drag, not a click: never enter editing (unselected the canvas moved the viz;\n // selected it does nothing). Suppress the trailing click so it can't activate.\n setSuppressNextEditClick(true);\n return;\n }\n onActivateTextEditing?.();\n setMouseSelecting(true);\n requestAnimationFrame(() => {\n setMouseSelecting(false);\n });\n const clickTarget = ev.target as Node | null;\n setTimeout(() => {\n editableRef.current?.focus({ preventScroll: true });\n placeCaretAtPoint(editor, startX, startY, clickTarget, editableRef.current);\n }, 0);\n };\n document.addEventListener('mouseup', onMouseUp, true);\n return;\n }\n\n if (isTextEditing) {\n clearFakeHighlight();\n e.stopPropagation();\n\n // Set before collapsing so scrollCaretWithinEditor sees the flag on the collapse's\n // render and skips the jump-inducing scroll.\n setMouseSelecting(true);\n if (editor.selection && !Range.isCollapsed(editor.selection)) {\n Transforms.collapse(editor, { edge: 'focus' });\n globalThis.getSelection()?.removeAllRanges();\n }\n const onMouseUp = (ev: MouseEvent): void => {\n document.removeEventListener('mouseup', onMouseUp, true);\n ev.stopPropagation();\n requestAnimationFrame(() => {\n setMouseSelecting(false);\n });\n };\n document.addEventListener('mouseup', onMouseUp, true);\n }\n },\n [\n editor,\n isEditMode,\n isTextEditing,\n onActivateTextEditing,\n editableRef,\n containerRef,\n clearFakeHighlight,\n ]\n );\n\n const handleEmptySpaceClick = useCallback(\n (e: React.MouseEvent) => {\n if (!isTextEditing || !editableRef.current) return;\n if (isMouseSelecting()) return;\n const target = e.target as HTMLElement;\n if (target.closest('[data-slate-node]')) return;\n editableRef.current.focus({ preventScroll: true });\n // Click in the non-text padding: placeCaretAtPoint resolves the nearest point first, only\n // falling back to end-of-doc when content isn't scrollable (else the view would jump away).\n placeCaretAtPoint(editor, e.clientX, e.clientY, null, editableRef.current);\n },\n [isTextEditing, editor, editableRef]\n );\n\n const handleDragStart = useCallback(\n (e: React.DragEvent) => {\n // Prevent native drag so dragging across selected text doesn't start a DnD (doesn't affect\n // text selection). In edit mode also stopPropagation so the press can't reach canvas move.\n e.preventDefault();\n if (isEditMode) {\n e.stopPropagation();\n }\n },\n [isEditMode]\n );\n\n return { handleMouseDown, handleEmptySpaceClick, handleDragStart };\n}\n", "/**\n * useEditModeEffect - Handles transitions out of edit mode.\n *\n * When leaving edit mode: deselects and blurs.\n * Text editing is NOT auto-activated on edit mode entry; the user must\n * explicitly press Enter.\n */\n\nimport { useRef, useEffect } from 'react';\nimport { Editor } from 'slate';\nimport { safeDeselect } from '../utils/slateUtils';\n\nexport function useEditModeEffect(\n editor: Editor,\n editableRef: React.RefObject<HTMLDivElement | null>,\n isEditMode: boolean\n): void {\n const prevIsEditModeRef = useRef(isEditMode);\n\n useEffect(() => {\n const wasEditMode = prevIsEditModeRef.current;\n prevIsEditModeRef.current = isEditMode;\n\n if (wasEditMode && !isEditMode) {\n safeDeselect(editor);\n editableRef.current?.blur();\n }\n }, [isEditMode, editor, editableRef]);\n}\n", "/**\n * InnerEditor - Slate editor wrapper: setup, content sync, keyboard, focus/blur,\n * mouse, fake highlight, font stepping, and edit mode transitions.\n */\n\nimport * as React from 'react';\nimport { useCallback, useMemo, useRef, useEffect } from 'react';\nimport { Descendant, Editor, Transforms } from 'slate';\nimport { Slate, Editable, RenderElementProps, RenderLeafProps } from 'slate-react';\nimport { usePureRichText } from './PureRichTextContext';\nimport { createElementRenderer } from './renderers/ElementRenderer';\nimport { Leaf } from './renderers/LeafRenderer';\nimport { FONT_FAMILY_WITH_FALLBACKS } from './types';\nimport { useEditorSetup, useInitialMarks, handleTextInsert } from './hooks/useEditorSetup';\nimport { useFakeHighlight } from './hooks/useFakeHighlight';\nimport { useContentSync } from './hooks/useContentSync';\nimport { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';\nimport { useStepFontSize } from './hooks/useStepFontSize';\nimport { useStepLineSpacing } from './hooks/useStepLineSpacing';\nimport { useFocusHandlers } from './hooks/useFocusHandlers';\nimport { useMouseHandlers } from './hooks/useMouseHandlers';\nimport { useEditModeEffect } from './hooks/useEditModeEffect';\nimport { focusSelectOutline, scrollCaretWithinEditor } from './utils/slateUtils';\nimport type { RichTextStateResult } from './hooks/useRichTextState';\n\nexport interface InnerEditorProps {\n initialValue: Descendant[];\n richTextContent: string;\n isEditMode: boolean;\n isTextEditing: boolean;\n containerRef: React.RefObject<HTMLDivElement | null>;\n defaultTextStyle: {\n color?: string;\n backgroundColor?: string;\n fontSize?: string;\n fontFamily?: string;\n lineHeight?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n };\n onContentChange: (html: string, immediate?: boolean) => void;\n onFocusGained?: (editable: HTMLDivElement | null, editor: Editor | null) => void;\n onFocusLost?: () => void;\n /** Consolidated text-editing lifecycle from useRichTextState. */\n richTextState?: Partial<RichTextStateResult>;\n onEditorReady?: (editor: Editor) => void;\n updateActiveStylesRef?: React.MutableRefObject<(() => void) | null>;\n clearFakeHighlightRef?: React.MutableRefObject<(() => void) | null>;\n /** Set by useContentSave; checked to detect round-trips and skip tree resets. */\n recentSavesRef?: React.MutableRefObject<Set<string>>;\n /** When true, forces the next external content sync even if the editor has focus. */\n forceNextSyncRef?: React.MutableRefObject<boolean>;\n /** Post-processing applied after a forced tree reset (e.g. re-apply token marks). */\n transformTreeRef?: React.MutableRefObject<\n ((tree: import('slate').Descendant[]) => import('slate').Descendant[]) | null\n >;\n /** Whether a new initialValue reference should re-sync otherwise unchanged content. */\n syncInitialValueChanges?: boolean;\n /** Called after editor changes to auto-resolve newly typed or pasted $token$ patterns. */\n autoResolveTokensRef?: React.MutableRefObject<((includeValueChanges?: boolean) => void) | null>;\n /** Marks the start of a paste so token resolution can wait for the paste burst to settle. */\n onPasteStart?: () => void;\n /** Callback for screenreader announcements on format changes. */\n onAnnouncement?: (message: string) => void;\n /** Token name -> resolved value, used to resolve $token$ in link URLs. */\n nameToValue?: Map<string, string>;\n /** Cancel pending typing batch (no save). On Cmd+Z, avoids an intermediate\n * save consuming forceNextSyncRef before the dashboard undo prop arrives. */\n onCancelPendingChanges?: () => void;\n /** When bound (dashboard), open links through the framework's link.open\n * event so its URL protection applies. Unset for the standalone viz. */\n onLinkOpen?: (url: string) => void;\n}\n\nexport const InnerEditor: React.FC<InnerEditorProps> = ({\n initialValue,\n richTextContent,\n isEditMode,\n isTextEditing,\n containerRef,\n defaultTextStyle,\n onContentChange,\n onFocusGained,\n onFocusLost,\n richTextState: richTextStateProp,\n onEditorReady,\n updateActiveStylesRef,\n clearFakeHighlightRef,\n recentSavesRef,\n forceNextSyncRef: forceNextSyncRefProp,\n transformTreeRef,\n syncInitialValueChanges,\n autoResolveTokensRef,\n onPasteStart,\n onAnnouncement,\n onCancelPendingChanges,\n nameToValue,\n onLinkOpen,\n}) => {\n const {\n setEditor,\n updateActiveStyles,\n saveSelection,\n applyFormat,\n resetToDefault,\n openLinkPopover,\n registerStepFontSize,\n registerStepLineSpacing,\n registerOnFormatApplied,\n registerAnnouncement,\n } = usePureRichText();\n\n // Extract richTextState callbacks; fallback refs for tests without the full object.\n const fallbackIsTextEditingRef = useRef(false);\n fallbackIsTextEditingRef.current = isTextEditing;\n const isTextEditingRef = richTextStateProp?.isTextEditingRef || fallbackIsTextEditingRef;\n const fallbackWasTextEditingRef = useRef(false);\n const wasTextEditingRef = richTextStateProp?.wasTextEditingRef || fallbackWasTextEditingRef;\n const onActivateTextEditing = richTextStateProp?.activateTextEditing;\n const onDeactivateTextEditing = richTextStateProp?.deactivateTextEditing;\n const onEnterSkipLinkFlow = richTextStateProp?.enterSkipLinkFlow;\n const onSavePreEditSelection = richTextStateProp?.savePreEditSelection;\n\n // Keep defaultTextStyle accessible to the editor's insertText override via ref\n const defaultTextStyleRef = useRef(defaultTextStyle);\n defaultTextStyleRef.current = defaultTextStyle;\n\n // Create editor instance with inline element support\n const editor = useEditorSetup(defaultTextStyleRef);\n\n // Set editor in context and notify parent\n useEffect(() => {\n setEditor(editor);\n onEditorReady?.(editor);\n }, [editor, setEditor, onEditorReady]);\n\n // Expose updateActiveStyles to parent via ref\n useEffect(() => {\n if (updateActiveStylesRef) {\n // eslint-disable-next-line no-param-reassign\n updateActiveStylesRef.current = updateActiveStyles;\n }\n }, [updateActiveStyles, updateActiveStylesRef]);\n\n // Keep preEditSelection current on applyFormat, else Escape-from-panel after a\n // format change uses the stale Shift+Tab selection and the caret jumps.\n useEffect(() => {\n if (onSavePreEditSelection) {\n registerOnFormatApplied(onSavePreEditSelection);\n }\n }, [registerOnFormatApplied, onSavePreEditSelection]);\n\n // Register announcement callback so format changes hit the aria-live region.\n useEffect(() => {\n if (onAnnouncement) {\n registerAnnouncement(onAnnouncement);\n }\n }, [registerAnnouncement, onAnnouncement]);\n\n // Initialize marks for empty editor (only once on mount)\n useInitialMarks(editor, isEditMode, defaultTextStyle);\n\n // Ref to the editable DOM element\n const editableRef = useRef<HTMLDivElement | null>(null);\n\n // Last known selection -- used by stepFontSize when editor.selection is null\n const lastSelectionRef = useRef<Editor['selection']>(null);\n\n // Handle edit mode transitions (deselect/blur on leave)\n useEditModeEffect(editor, editableRef, isEditMode);\n\n // Track if editor has focus\n const hasFocusRef = useRef(false);\n // Bypasses useContentSync's hasFocusRef guard for in-editor undo/redo. Prefer the\n // parent-provided ref so the parent can also force syncs (e.g. toggling token resolution).\n const localForceNextSyncRef = useRef(false);\n const forceNextSyncRef = forceNextSyncRefProp ?? localForceNextSyncRef;\n\n // Fake highlight system\n const { fakeHighlightAbsRef, updateFakeHighlight, updateFakeHighlightAbs, decorate } =\n useFakeHighlight(editor);\n\n // When true, the fake highlight was explicitly dismissed (Escape, arrow key)\n // and must not reappear until the user makes a fresh expanded selection.\n const highlightDismissedRef = useRef(false);\n\n // Expose clearFakeHighlight to parent. Clears only the visual highlight and\n // lastSelectionRef; permanent dismiss (highlightDismissedRef, selection) is caller's job.\n useEffect(() => {\n if (clearFakeHighlightRef) {\n // eslint-disable-next-line no-param-reassign\n clearFakeHighlightRef.current = () => {\n updateFakeHighlightAbs(null);\n lastSelectionRef.current = null;\n };\n }\n }, [clearFakeHighlightRef, updateFakeHighlightAbs]);\n\n // Content sync and onChange handler\n const { value, handleChange } = useContentSync({\n editor,\n initialValue,\n richTextContent,\n onContentChange,\n updateActiveStyles,\n updateFakeHighlightAbs,\n fakeHighlightAbsRef,\n hasFocusRef,\n isTextEditingRef,\n lastSelectionRef,\n recentSavesRef,\n forceNextSyncRef,\n transformTreeRef,\n syncInitialValueChanges,\n autoResolveTokensRef,\n });\n\n // Step font size (registers itself via registerStepFontSize)\n const stepFontSize = useStepFontSize({\n editor,\n fakeHighlightAbsRef,\n lastSelectionRef,\n updateFakeHighlightAbs,\n updateActiveStyles,\n registerStepFontSize,\n });\n\n // Step line spacing (registers itself via registerStepLineSpacing)\n useStepLineSpacing({\n editor,\n fakeHighlightAbsRef,\n lastSelectionRef,\n updateFakeHighlightAbs,\n updateActiveStyles,\n registerStepLineSpacing,\n });\n\n // Keyboard shortcuts\n const { handleKeyDown: handleKeyboardShortcuts } = useKeyboardShortcuts({\n editor,\n applyFormat,\n resetToDefault,\n openLinkPopover,\n stepFontSize,\n });\n\n // Focus and blur handlers\n const { handleFocus, handleBlur } = useFocusHandlers({\n editor,\n editableRef,\n hasFocusRef,\n isTextEditingRef,\n wasTextEditingRef,\n lastSelectionRef,\n highlightDismissedRef,\n saveSelection,\n onEnterSkipLinkFlow,\n onSavePreEditSelection,\n updateFakeHighlight,\n updateFakeHighlightAbs,\n onFocusGained,\n onFocusLost,\n onDeactivateTextEditing,\n });\n\n // Mouse event handlers\n const {\n handleMouseDown: baseHandleMouseDown,\n handleEmptySpaceClick,\n handleDragStart,\n } = useMouseHandlers({\n editor,\n editableRef,\n containerRef,\n isEditMode,\n isTextEditing,\n onActivateTextEditing,\n clearFakeHighlight: () => updateFakeHighlightAbs(null),\n });\n\n // Reset highlight-dismissed so Shift+Tab after a fresh mouse selection shows the highlight.\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n highlightDismissedRef.current = false;\n baseHandleMouseDown(e);\n },\n [baseHandleMouseDown]\n );\n\n // Wrap handleKeyDown: Escape exits text editing, Tab exits editing.\n // Returns true when Slate should skip its own processing for this key.\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent): boolean | void => {\n if (!isTextEditingRef.current) {\n return undefined;\n }\n if (event.key === 'Escape') {\n event.preventDefault();\n highlightDismissedRef.current = true;\n // prettier-ignore\n try {\n Transforms.deselect(editor);\n } catch (e) { // NOSONAR typescript:S2486 - Ignore if editor is empty\n }\n globalThis.getSelection()?.removeAllRanges();\n onDeactivateTextEditing?.();\n editableRef.current?.blur();\n focusSelectOutline(editableRef.current);\n return undefined;\n }\n if (event.key === 'Tab' && event.shiftKey) {\n // Shift+Tab: allow fake highlight this blur cycle, save selection for\n // Escape-from-panel, then let the doc capture handler focus the skip link.\n // isTextEditing stays true: guards the parent's initialValue memo (no tree\n // reset) and keeps Editable non-readOnly (caret visible via fake highlight).\n highlightDismissedRef.current = false;\n onSavePreEditSelection?.(editor.selection);\n if (wasTextEditingRef) {\n // eslint-disable-next-line no-param-reassign\n wasTextEditingRef.current = true;\n }\n return undefined;\n }\n // Cmd+Z/Cmd+Shift+Z: delegate undo/redo to the dashboard. Cancel (not flush)\n // the pending typing batch so no intermediate save consumes forceNextSyncRef\n // early. Set forceNextSyncRef so useContentSync accepts the reverted prop despite\n // focus; return true so Slate skips its own undo handler (which would swallow it).\n const mod = event.metaKey || event.ctrlKey;\n if (mod && event.key.toLowerCase() === 'z') {\n onCancelPendingChanges?.();\n forceNextSyncRef.current = true;\n return true;\n }\n handleKeyboardShortcuts(event);\n return undefined;\n },\n [\n isTextEditingRef,\n handleKeyboardShortcuts,\n onDeactivateTextEditing,\n editor,\n onSavePreEditSelection,\n wasTextEditingRef,\n onCancelPendingChanges,\n forceNextSyncRef,\n ]\n );\n\n // Render element callback\n const ElementRenderer = useMemo(\n () =>\n createElementRenderer(isEditMode, defaultTextStyle.lineHeight || '1.5', nameToValue, onLinkOpen),\n [isEditMode, defaultTextStyle.lineHeight, nameToValue, onLinkOpen]\n );\n const renderElement = useCallback(\n (props: RenderElementProps) => <ElementRenderer {...props} />,\n [ElementRenderer]\n );\n\n // Render leaf callback\n const renderLeaf = useCallback((props: RenderLeafProps) => <Leaf {...props} />, []);\n\n // Route plain-text inserts through Slate to skip slate-react's Chromium native fast\n // path, which crashes toDOMPoint when the DOM<->node map is out of sync (near links).\n const handleDOMBeforeInput = useCallback(\n (event: InputEvent): void | boolean => handleTextInsert(editor, event) || undefined,\n [editor]\n );\n\n // Default styling for the editable area\n const editableStyle: React.CSSProperties = {\n color: defaultTextStyle.color || '#ffffff',\n fontSize: defaultTextStyle.fontSize || '14px',\n fontFamily:\n FONT_FAMILY_WITH_FALLBACKS[defaultTextStyle.fontFamily] ||\n defaultTextStyle.fontFamily ||\n FONT_FAMILY_WITH_FALLBACKS['Splunk Data Sans'],\n lineHeight: defaultTextStyle.lineHeight || '1.5',\n // Text I-beam only while editing; otherwise inherit from wrapper so read-only\n // viewers don't get a text cursor (pointer when an interaction is bound).\n cursor: isTextEditing ? 'text' : 'inherit',\n };\n const editorContainerStyle: React.CSSProperties = {\n // Keep the Slate editor's percentage min-height resolvable while actively editing so\n // vertical alignment has the same full-height layout used in read-only mode.\n minHeight: '100%',\n ...(isTextEditing ? {} : { caretColor: 'transparent', outline: 'none' }),\n };\n\n return (\n <div\n role=\"none\"\n suppressContentEditableWarning\n onMouseDown={handleMouseDown}\n onClick={handleEmptySpaceClick}\n // Here too (not just Editable): in view mode Editable is readOnly so slate-react\n // skips onDragStart; catch the bubbling event to stop selection drag-and-drop.\n onDragStart={handleDragStart}\n style={editorContainerStyle}\n >\n <Slate editor={editor} initialValue={value} onChange={handleChange}>\n <Editable\n readOnly={!isTextEditing}\n tabIndex={isTextEditing ? 0 : -1}\n aria-label=\"Rich text editor\"\n decorate={decorate}\n renderElement={renderElement}\n renderLeaf={renderLeaf}\n onDOMBeforeInput={handleDOMBeforeInput}\n // Keep caret-into-view scrolling in the widget's own container;\n // slate-react's default jumps the whole dashboard on programmatic selects.\n scrollSelectionIntoView={scrollCaretWithinEditor}\n style={editableStyle}\n ref={editableRef}\n onKeyDown={handleKeyDown}\n onPaste={onPasteStart}\n onDragStart={handleDragStart}\n onFocus={handleFocus}\n onBlur={handleBlur}\n placeholder={isTextEditing ? 'Enter text...' : ''}\n spellCheck={false}\n draggable={false}\n />\n </Slate>\n </div>\n );\n};\n", "/**\n * useRichTextState - Centralized state management for RichText editing lifecycle.\n *\n * Replaces scattered isTextEditing / isTextEditingRef / wasTextEditingRef / activateTextEditing\n * with a single hook that co-locates state, refs, and transition functions.\n *\n * Stores preEditSelection so Escape-from-config-panel can restore the caret reliably.\n */\n\nimport { useState, useCallback, useRef } from 'react';\nimport { flushSync } from 'react-dom';\nimport { Range } from 'slate';\n\nexport interface RichTextStateResult {\n /** Whether the user is actively editing text (caret visible). */\n isTextEditing: boolean;\n /** Imperative ref always in sync with isTextEditing (for event handlers that read mid-render). */\n isTextEditingRef: React.MutableRefObject<boolean>;\n /** Whether the user was text-editing before entering the skip-link/config-panel flow.\n * Exposed as a ref so document-level event listeners (stale closures) read the latest value. */\n wasTextEditingRef: React.MutableRefObject<boolean>;\n /** Activate text editing (Enter-to-edit, click-to-edit). */\n activateTextEditing: () => void;\n /** Deactivate text editing (Escape, blur, etc.). Clears preEditSelection. */\n deactivateTextEditing: () => void;\n /** Transition from text-editing to skip-link/config-panel flow.\n * Stores the current selection so it can be restored on Escape-from-panel.\n * Sets wasTextEditing = true and isTextEditing = false. */\n enterSkipLinkFlow: (selection: Range | null) => void;\n /** Re-enter text editing from config panel (Escape-from-panel).\n * Sets isTextEditing = true. preEditSelection is preserved for the caller to read. */\n returnFromConfigPanel: () => void;\n /** Save the pre-edit selection without changing isTextEditing or wasTextEditing.\n * Used when focus moves to the panel via mouse click (caret should stay visible). */\n savePreEditSelection: (selection: Range | null) => void;\n /** Read the selection that was saved when entering the skip-link flow. */\n getPreEditSelection: () => Range | null;\n /** Reset wasTextEditing to false (after skip-link Enter handler consumes it). */\n clearWasTextEditing: () => void;\n}\n\nexport function useRichTextState(): RichTextStateResult {\n const [isTextEditing, setIsTextEditing] = useState(false);\n const isTextEditingRef = useRef(false);\n // Keep ref in sync on every render\n isTextEditingRef.current = isTextEditing;\n\n const wasTextEditingRef = useRef(false);\n const preEditSelectionRef = useRef<Range | null>(null);\n\n const activateTextEditing = useCallback(() => {\n setIsTextEditing(true);\n isTextEditingRef.current = true;\n }, []);\n\n const deactivateTextEditing = useCallback(() => {\n setIsTextEditing(false);\n isTextEditingRef.current = false;\n // Only clear the saved selection if we are NOT in the skip-link/config-panel\n // flow. During that flow enterSkipLinkFlow() stores the selection so\n // Escape-from-panel can restore it; a subsequent blur-triggered deactivate\n // must not wipe it.\n if (!wasTextEditingRef.current) {\n preEditSelectionRef.current = null;\n }\n }, []);\n\n const enterSkipLinkFlow = useCallback((selection: Range | null) => {\n preEditSelectionRef.current = selection\n ? { anchor: { ...selection.anchor }, focus: { ...selection.focus } }\n : null;\n wasTextEditingRef.current = true;\n setIsTextEditing(false);\n isTextEditingRef.current = false;\n }, []);\n\n const returnFromConfigPanel = useCallback(() => {\n // preEditSelection is intentionally preserved so the caller can read it\n // after this transition to restore the caret position.\n // flushSync forces React to commit the state update synchronously so\n // that <Editable readOnly={false}> is in the DOM before the caller\n // focuses and restores the selection. Without this, React 18 batches\n // the update and the editor may still be readOnly when focus() runs,\n // causing Slate-React's onDOMSelectionChange to deselect.\n isTextEditingRef.current = true;\n flushSync(() => {\n setIsTextEditing(true);\n });\n }, []);\n\n const savePreEditSelection = useCallback((selection: Range | null) => {\n preEditSelectionRef.current = selection\n ? { anchor: { ...selection.anchor }, focus: { ...selection.focus } }\n : null;\n }, []);\n\n const getPreEditSelection = useCallback((): Range | null => {\n return preEditSelectionRef.current;\n }, []);\n\n const clearWasTextEditing = useCallback(() => {\n wasTextEditingRef.current = false;\n }, []);\n\n return {\n isTextEditing,\n isTextEditingRef,\n wasTextEditingRef,\n activateTextEditing,\n deactivateTextEditing,\n enterSkipLinkFlow,\n returnFromConfigPanel,\n savePreEditSelection,\n getPreEditSelection,\n clearWasTextEditing,\n };\n}\n", "/**\n * useContentSave - Synchronous content save with smart typing batches.\n *\n * Replaces useDebouncedSave. Key differences:\n * - Format and structural changes (Enter, Delete, bold, alignment) save immediately\n * - Typing batches with a short idle timer so undo reverts a chunk, not one char\n * - Token restoration before every save\n * - recentSavesRef (Set) for round-trip detection in useContentSync\n */\n\nimport { useCallback, useRef, useEffect } from 'react';\n\ninterface ContentSaveArgs {\n richTextContent: string;\n onOptionsChange?: (options: Record<string, unknown>) => void;\n restoreTokensInHtml: (html: string) => string;\n}\n\ninterface ContentSaveResult {\n /** Called by useContentSync on every content change. immediate=true skips batching. */\n handleContentChange: (html: string, immediate?: boolean) => void;\n /** Flush any pending batched typing content (blur, unmount). */\n flushPendingChanges: () => void;\n /**\n * Cancel any pending batched typing without saving. Used when the caller\n * has already taken responsibility for saving the latest content (e.g. a\n * token-display toggle that needs to save with a previous restore function).\n */\n cancelPendingChanges: () => void;\n /** Tracks recently saved HTML values for round-trip detection. */\n recentSavesRef: React.MutableRefObject<Set<string>>;\n}\n\n/** Idle timeout for typing batches (ms). Balances undo granularity with responsiveness. */\nconst TYPING_IDLE_MS = 300;\n\nexport function useContentSave({\n richTextContent,\n onOptionsChange,\n restoreTokensInHtml,\n}: ContentSaveArgs): ContentSaveResult {\n const idleTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingHtmlRef = useRef<string | null>(null);\n // Track all in-flight save values so round-trips are detected even when\n // multiple saves overlap (e.g. rapid typing produces batch N and N+1 before\n // round-trip N arrives). Values are removed as round-trips are consumed.\n const recentSavesRef = useRef<Set<string>>(new Set());\n\n // Keep current values in refs so `save` has a stable identity.\n // Without this, `save` would depend on richTextContent/onOptionsChange/\n // restoreTokensInHtml, causing flushPendingChanges to change identity on\n // every save round-trip, which re-runs the cleanup effect in PureRichText\n // and clears the active instance (panel disappears).\n const richTextContentRef = useRef(richTextContent);\n richTextContentRef.current = richTextContent;\n const onOptionsChangeRef = useRef(onOptionsChange);\n onOptionsChangeRef.current = onOptionsChange;\n const restoreTokensInHtmlRef = useRef(restoreTokensInHtml);\n restoreTokensInHtmlRef.current = restoreTokensInHtml;\n\n // Cancel pending batch when richTextContent changes externally (undo/redo).\n // Skip cancellation for our own save round-trips so that characters typed\n // between a batch send and its round-trip are not silently dropped.\n useEffect(() => {\n if (recentSavesRef.current.has(richTextContent)) {\n // Round-trip from our own save -- consume it and keep in-flight batches.\n recentSavesRef.current.delete(richTextContent);\n return;\n }\n // External change (undo/redo) -- cancel pending batch and clear all tracked saves.\n recentSavesRef.current.clear();\n if (idleTimerRef.current) {\n clearTimeout(idleTimerRef.current);\n idleTimerRef.current = null;\n }\n pendingHtmlRef.current = null;\n }, [richTextContent]);\n\n // Core save: restore tokens and dispatch to dashboard.\n // Stable identity -- reads props from refs.\n const save = useCallback((html: string): void => {\n if (!onOptionsChangeRef.current) return;\n const htmlWithTokens = restoreTokensInHtmlRef.current(html);\n if (htmlWithTokens === richTextContentRef.current) return;\n recentSavesRef.current.add(htmlWithTokens);\n onOptionsChangeRef.current({ richTextContent: htmlWithTokens });\n }, []);\n\n // Handle content change from the editor.\n // immediate=true for structural/format ops; false (default) for typing.\n const handleContentChange = useCallback(\n (html: string, immediate?: boolean): void => {\n if (immediate) {\n // Clear any pending typing batch -- the structural change supersedes it\n if (idleTimerRef.current) {\n clearTimeout(idleTimerRef.current);\n idleTimerRef.current = null;\n }\n pendingHtmlRef.current = null;\n save(html);\n return;\n }\n // Typing: batch with idle timer\n pendingHtmlRef.current = html;\n if (idleTimerRef.current) {\n clearTimeout(idleTimerRef.current);\n }\n idleTimerRef.current = setTimeout(() => {\n if (pendingHtmlRef.current !== null) {\n save(pendingHtmlRef.current);\n pendingHtmlRef.current = null;\n }\n }, TYPING_IDLE_MS);\n },\n [save]\n );\n\n // Flush pending typing content immediately (blur, unmount)\n const flushPendingChanges = useCallback((): void => {\n if (idleTimerRef.current) {\n clearTimeout(idleTimerRef.current);\n idleTimerRef.current = null;\n }\n if (pendingHtmlRef.current) {\n save(pendingHtmlRef.current);\n pendingHtmlRef.current = null;\n }\n }, [save]);\n\n // Cancel pending typing without saving. The caller is responsible for\n // having already saved (or intentionally discarding) the latest content.\n const cancelPendingChanges = useCallback((): void => {\n if (idleTimerRef.current) {\n clearTimeout(idleTimerRef.current);\n idleTimerRef.current = null;\n }\n pendingHtmlRef.current = null;\n }, []);\n\n return { handleContentChange, flushPendingChanges, cancelPendingChanges, recentSavesRef };\n}\n", "/**\n * Document-level keyboard nav for PureRichText: Tab/Shift+Tab skip-links, Escape from sidebar,\n * Enter-to-edit, skip-link activation, focus-out deselection. See kb reference sections D and E.\n */\n\nimport { useEffect, useRef } from 'react';\nimport { Editor, Transforms } from 'slate';\nimport { ReactEditor } from 'slate-react';\nimport { registerActiveRichText } from '../activeInstance';\nimport { safeDeselect, safeSelectEnd } from '../utils/slateUtils';\n\ninterface DashboardKeyboardNavArgs {\n isEditMode: boolean;\n containerRef: React.RefObject<HTMLDivElement | null>;\n instanceId: string;\n slateEditorRef: React.MutableRefObject<Editor | null>;\n isTextEditingRef: React.MutableRefObject<boolean>;\n wasTextEditingRef: React.MutableRefObject<boolean>;\n clearFakeHighlightRef: React.MutableRefObject<(() => void) | null>;\n updateActiveStylesFnRef: React.MutableRefObject<(() => void) | null>;\n activateTextEditing: () => void;\n richTextState: {\n deactivateTextEditing: () => void;\n getPreEditSelection: () => Editor['selection'];\n returnFromConfigPanel: () => void;\n clearWasTextEditing: () => void;\n };\n dashboardCoreApi: {\n updateSelectedItems: (items?: unknown[]) => void;\n } | null;\n}\n\ninterface SkipLinkAndFocusOutArgs {\n isEditMode: boolean;\n containerRef: React.RefObject<HTMLDivElement | null>;\n slateEditorRef: React.MutableRefObject<Editor | null>;\n isTextEditingRef: React.MutableRefObject<boolean>;\n wasTextEditingRef: React.MutableRefObject<boolean>;\n clearFakeHighlightRef: React.MutableRefObject<(() => void) | null>;\n deactivateTextEditing: () => void;\n dashboardCoreApi: DashboardKeyboardNavArgs['dashboardCoreApi'];\n}\n\n/**\n * Listener 1: skip-link Tab/Shift+Tab (hide/show/focus), Escape-to-deselect, and focusout\n * deselection when focus leaves the viz (unless to sidebar/panel/popover).\n */\nfunction useSkipLinkAndFocusOut({\n isEditMode,\n containerRef,\n slateEditorRef,\n isTextEditingRef,\n wasTextEditingRef,\n clearFakeHighlightRef,\n deactivateTextEditing,\n dashboardCoreApi,\n}: SkipLinkAndFocusOutArgs): void {\n useEffect(() => {\n if (!isEditMode) return undefined;\n\n const vizItem = containerRef.current?.closest<HTMLElement>('[data-test=\"viz-item\"]');\n if (!vizItem) return undefined;\n\n const handleEscapeOnSkipLink = (configLink: HTMLElement | null): void => {\n if (configLink) configLink.setAttribute('tabindex', '-1');\n clearFakeHighlightRef.current?.();\n // Clear selection so a subsequent Shift+Tab can't re-create the fake highlight.\n const ed = slateEditorRef.current;\n if (ed) {\n safeDeselect(ed);\n }\n // Fully exit editing so the Editable becomes readOnly and initialValue re-gates.\n deactivateTextEditing();\n // eslint-disable-next-line no-param-reassign\n wasTextEditingRef.current = false;\n if (dashboardCoreApi) {\n dashboardCoreApi.updateSelectedItems([]);\n }\n };\n\n // After Shift+Tab OFF the skip link (focus on viz-item), the next Shift+Tab should\n // let focus leave the viz rather than re-show the skip link.\n let skipLinkJustHidden = false;\n\n const handleShiftTab = (\n e: KeyboardEvent,\n target: HTMLElement,\n configLink: HTMLElement | null\n ): void => {\n // If on the skip link, hide it and let focus leave backward.\n if (target.closest('[data-test=\"skip-link-config\"]')) {\n if (configLink) configLink.setAttribute('tabindex', '-1');\n skipLinkJustHidden = true;\n return;\n }\n // If we just hid the skip link, don't re-show it -- let focus\n // leave the viz naturally.\n if (skipLinkJustHidden) {\n skipLinkJustHidden = false;\n return;\n }\n // Shift+Tab from anywhere else in the viz: focus the skip link.\n if (configLink) {\n e.preventDefault();\n configLink.setAttribute('tabindex', '0');\n configLink.focus();\n }\n };\n\n const handleForwardTab = (configLink: HTMLElement | null): void => {\n if (configLink) configLink.setAttribute('tabindex', '-1');\n const actionMenuLink = vizItem.querySelector<HTMLElement>('[data-test=\"skip-link-action-menu\"]');\n if (actionMenuLink) actionMenuLink.setAttribute('tabindex', '-1');\n };\n\n const handleKeyDown = (e: KeyboardEvent): void => {\n const target = e.target as HTMLElement;\n if (!vizItem.contains(target)) return;\n const configLink = vizItem.querySelector<HTMLElement>('[data-test=\"skip-link-config\"]');\n\n if (e.key === 'Escape' && target.closest('[data-test=\"skip-link-config\"]')) {\n e.preventDefault();\n handleEscapeOnSkipLink(configLink);\n return;\n }\n\n // Escape #2: viz focused but not editing -- release focus and deselect. Blur first\n // so the outline can't re-fire onFocusCapture and re-select (thrashing the config\n // panel/toolbar); preventDefault suppresses the dashboard's own cancel handler.\n if (e.key === 'Escape' && !isTextEditingRef.current) {\n const isSelected = containerRef.current?.closest('[data-selected=\"true\"]') != null;\n if (isSelected) {\n e.preventDefault();\n (document.activeElement as HTMLElement | null)?.blur();\n if (dashboardCoreApi) {\n dashboardCoreApi.updateSelectedItems([]);\n }\n return;\n }\n }\n\n if (e.key !== 'Tab') return;\n\n if (e.shiftKey) {\n handleShiftTab(e, target, configLink);\n } else {\n handleForwardTab(configLink);\n }\n };\n\n const handleFocusOut = (e: FocusEvent): void => {\n const relatedTarget = e.relatedTarget as HTMLElement | null;\n if (!relatedTarget) return;\n if (vizItem.contains(relatedTarget)) return;\n // Don't deselect if focus moved to the sidebar or a popover (color picker, select,\n // link editor, etc. are portaled to the body).\n if (\n relatedTarget.closest('[data-test=\"sidebar-content\"]') ||\n relatedTarget.id === 'configuration-back-button' ||\n relatedTarget.closest('#configuration-back-button') ||\n relatedTarget.closest('[data-test=\"popover\"]') ||\n relatedTarget.closest('[data-test-popover-id]') ||\n relatedTarget.closest('[data-test=\"menu\"]') ||\n relatedTarget.closest('[role=\"dialog\"]') ||\n relatedTarget.closest('[data-layer]') ||\n relatedTarget.closest('[data-test=\"flyout-pane\"]') ||\n relatedTarget.closest('[data-test=\"collapsible-panel\"]') ||\n relatedTarget.closest('[data-test=\"viz-config-panel\"]')\n ) {\n return;\n }\n // Don't deselect if focus moved to a resize handle or block outline\n if (relatedTarget.closest('[data-test=\"handle\"]')) return;\n // Focus left the viz -- deselect\n if (dashboardCoreApi) {\n dashboardCoreApi.updateSelectedItems([]);\n }\n // Re-hide config link for next interaction\n const configLink = vizItem.querySelector<HTMLElement>('[data-test=\"skip-link-config\"]');\n if (configLink) configLink.setAttribute('tabindex', '-1');\n };\n\n document.addEventListener('keydown', handleKeyDown, true);\n vizItem.addEventListener('focusout', handleFocusOut);\n return () => {\n document.removeEventListener('keydown', handleKeyDown, true);\n vizItem.removeEventListener('focusout', handleFocusOut);\n };\n }, [isEditMode, dashboardCoreApi]); // eslint-disable-line react-hooks/exhaustive-deps\n}\n\n/**\n * Listener 2: sidebar Escape (restore selection, return to editor), Enter/Space skip-link\n * activation (select-all, focus config), Enter-to-edit on viz-item, click to block <a> nav.\n */\nfunction useSidebarAndEditActivation({\n isEditMode,\n containerRef,\n instanceId,\n slateEditorRef,\n isTextEditingRef,\n wasTextEditingRef,\n clearFakeHighlightRef,\n updateActiveStylesFnRef,\n activateTextEditing,\n richTextState,\n}: Omit<DashboardKeyboardNavArgs, 'dashboardCoreApi'>): void {\n const activateTextEditingRef = useRef(activateTextEditing);\n activateTextEditingRef.current = activateTextEditing;\n\n useEffect(() => {\n if (!isEditMode) return undefined;\n\n const getOurVizItem = (): HTMLElement | null =>\n containerRef.current?.closest<HTMLElement>('[data-test=\"viz-item\"]') ?? null;\n\n const isTargetInSidebar = (target: HTMLElement, vizItem: HTMLElement | null): boolean =>\n !vizItem?.contains(target) &&\n // The link popover (Cmd+K) owns its own Escape (useLinkHandlers); excluded here so\n // this capture handler doesn't intercept it, forcing a second Escape to close.\n !target.closest('[data-test=\"link-popover-content\"]') &&\n Boolean(\n target.closest('[data-test=\"sidebar-content\"]') ||\n target.closest('[data-test=\"header\"]') ||\n target.id === 'configuration-back-button' ||\n target.closest('#configuration-back-button') ||\n target.closest('[data-test=\"popover\"]') ||\n target.closest('[data-test-popover-id]')\n );\n\n const handleEscapeFromSidebar = (e: KeyboardEvent): void => {\n const isSelected = containerRef.current?.closest('[data-selected=\"true\"]') != null;\n if (!isSelected) return;\n e.preventDefault();\n e.stopImmediatePropagation();\n registerActiveRichText(instanceId, null, slateEditorRef.current);\n // Prefer the editor's current selection over preEditSelection, which may be stale\n // if format ops restructured the tree (e.g. addMark splits text nodes).\n const selToRestore = slateEditorRef.current?.selection || richTextState.getPreEditSelection();\n // returnFromConfigPanel flushSyncs isTextEditing=true so <Editable readOnly={false}>\n // is in the DOM before we focus and restore the selection.\n richTextState.returnFromConfigPanel();\n requestAnimationFrame(() => {\n const editable = containerRef.current?.querySelector<HTMLElement>('[data-slate-editor]');\n editable?.focus();\n const ed = slateEditorRef.current;\n if (ed && selToRestore) {\n try {\n Transforms.select(ed, selToRestore);\n // Sync the DOM selection now so Slate-React's throttled\n // onDOMSelectionChange reads it, not the stale focus()-default (start).\n const domRange = ReactEditor.toDOMRange(ed, selToRestore);\n const domSel = globalThis.getSelection();\n domSel?.removeAllRanges();\n domSel?.addRange(domRange);\n } catch {\n safeSelectEnd(ed);\n }\n } else if (ed) {\n safeSelectEnd(ed);\n }\n clearFakeHighlightRef.current?.();\n richTextState.clearWasTextEditing();\n });\n };\n\n const handleSkipLinkActivate = (e: KeyboardEvent): void => {\n e.preventDefault();\n e.stopImmediatePropagation();\n registerActiveRichText(instanceId, null, slateEditorRef.current);\n if (!wasTextEditingRef.current) {\n const slateEditor = slateEditorRef.current;\n if (slateEditor) {\n try {\n Transforms.select(slateEditor, {\n anchor: Editor.start(slateEditor, []),\n focus: Editor.end(slateEditor, []),\n });\n } catch {\n // Ignore if editor is empty\n }\n }\n updateActiveStylesFnRef.current?.();\n }\n richTextState.clearWasTextEditing();\n const configBtn = document.getElementById('configuration-back-button');\n if (configBtn) {\n configBtn.focus();\n }\n };\n\n const handleKeyDown = (e: KeyboardEvent): void => {\n const target = e.target as HTMLElement;\n const ourVizItem = getOurVizItem();\n\n if (e.key === 'Escape' && isTargetInSidebar(target, ourVizItem)) {\n handleEscapeFromSidebar(e);\n return;\n }\n\n if (!ourVizItem?.contains(target)) return;\n\n if ((e.key === 'Enter' || e.key === ' ') && target.closest('[data-test=\"skip-link-config\"]')) {\n handleSkipLinkActivate(e);\n return;\n }\n\n if (e.key === 'Enter' && !isTextEditingRef.current) {\n const isVizSelected = containerRef.current?.closest('[data-selected=\"true\"]') != null;\n if (!isVizSelected) return;\n e.preventDefault();\n e.stopImmediatePropagation();\n activateTextEditingRef.current();\n }\n };\n\n // Also intercept click on skip link to prevent <a> navigation\n const handleClick = (e: Event): void => {\n const link = (e.target as HTMLElement)?.closest('[data-test=\"skip-link-config\"]');\n if (!link) return;\n const ourVizItem = getOurVizItem();\n if (!ourVizItem?.contains(link)) return;\n e.preventDefault();\n e.stopImmediatePropagation();\n const configBtn = document.getElementById('configuration-back-button');\n if (configBtn) {\n configBtn.focus();\n }\n };\n\n document.addEventListener('keydown', handleKeyDown, true);\n document.addEventListener('click', handleClick, true);\n return () => {\n document.removeEventListener('keydown', handleKeyDown, true);\n document.removeEventListener('click', handleClick, true);\n };\n }, [isEditMode]); // eslint-disable-line react-hooks/exhaustive-deps\n}\n\nexport function useDashboardKeyboardNav(args: DashboardKeyboardNavArgs): void {\n useSkipLinkAndFocusOut({\n isEditMode: args.isEditMode,\n containerRef: args.containerRef,\n slateEditorRef: args.slateEditorRef,\n isTextEditingRef: args.isTextEditingRef,\n wasTextEditingRef: args.wasTextEditingRef,\n clearFakeHighlightRef: args.clearFakeHighlightRef,\n deactivateTextEditing: args.richTextState.deactivateTextEditing,\n dashboardCoreApi: args.dashboardCoreApi,\n });\n\n useSidebarAndEditActivation(args);\n}\n", "/** PureRichText - Slate.js based rich text editor visualization with full formatting support. */\n\nimport * as React from 'react';\nimport { useCallback, useMemo, useState, useRef, useEffect, useId, useSyncExternalStore } from 'react';\n\nimport { useSplunkTheme } from '@splunk/themes';\n// eslint-disable-next-line import/no-extraneous-dependencies\nimport { DashboardCoreApiContext } from '@splunk/dashboard-context';\nimport { Descendant, Editor, Text, Transforms } from 'slate';\nimport { noop } from 'lodash';\nimport {\n registerActiveRichText,\n clearActiveRichText,\n getActiveRichTextId,\n getActiveSlateEditor,\n subscribeActiveRichText,\n isMouseSelecting,\n consumeSuppressNextEditClick,\n} from './activeInstance';\nimport { PureRichTextProvider } from './PureRichTextContext';\nimport { EditorPanel } from './Editor';\nimport { EMPTY_SLATE_VALUE, VerticalAlign, PureRichTextProps, TextStyles, FontSizePreset } from './types';\nimport {\n focusSelectOutline,\n htmlToSlate,\n parsePadding,\n safeSelectEnd,\n slateToHtml,\n slateToPlainText,\n} from './utils/slateUtils';\nimport { PureRichTextContainer, DrilldownButton, EditorWrapper, LiveRegion } from './RichTextStyles';\nimport { getFontSizeInPx } from './utils/fontSize';\nimport { InnerEditor } from './InnerEditor';\nimport { useRichTextState } from './hooks/useRichTextState';\nimport { useTokenMap, wrapRawTokensInTree, TOKEN_OR_ESCAPE_PATTERN } from './hooks/useTokenMap';\nimport { absOffsetToPoint, pointToAbsOffset } from './hooks/useFakeHighlight';\nimport { useContentSave } from './hooks/useContentSave';\nimport { useDashboardKeyboardNav } from './hooks/useDashboardKeyboardNav';\n\nfunction useIsActiveRichText(id: string): boolean {\n return useSyncExternalStore(\n callback => subscribeActiveRichText(callback),\n () => getActiveRichTextId() === id\n );\n}\n\n/** slateToHtml already emits raw $token$ patterns, so no restore is needed. */\nconst identityRestore = (html: string): string => html;\n\n// Max pointer travel (px) between mousedown and click before it counts as a drag-to-reposition tail, not a click.\nconst CONTAINER_MOVE_THRESHOLD = 4;\n\n/** Exported for unit testing. */\nexport function resolveTokenDisplay(args: {\n isEditMode: boolean;\n previewTokenValues: boolean;\n resolvedContent: string;\n rawContent: string | null;\n}): {\n editorSourceContent: string;\n showResolvedTokens: boolean;\n} {\n const { isEditMode, previewTokenValues, resolvedContent, rawContent } = args;\n const showResolvedTokens = !isEditMode || previewTokenValues;\n // Always drive editor from raw `$token$` content (token identity by position); preview only changes display.\n const editorSourceContent = rawContent ?? resolvedContent;\n return { editorSourceContent, showResolvedTokens };\n}\n\n/** Resolve the effective font size from defaultTextStyles or individual props. */\nfunction resolveFontSize(\n defaultTextStyles: Partial<TextStyles> | undefined,\n fontSize: FontSizePreset,\n customFontSize: number\n): { effectiveFontSize: FontSizePreset; effectiveCustomFontSize: number } {\n if (defaultTextStyles?.fontSize) {\n const dtsFs = defaultTextStyles.fontSize;\n if (typeof dtsFs === 'string' && dtsFs.endsWith('px')) {\n return { effectiveFontSize: 'custom', effectiveCustomFontSize: Number.parseInt(dtsFs, 10) };\n }\n }\n return { effectiveFontSize: fontSize, effectiveCustomFontSize: customFontSize };\n}\n\ninterface TokenToggleArgs {\n editor: Editor | null;\n richTextContent: string;\n recentSavesRef: React.MutableRefObject<Set<string>>;\n cancelPendingChanges: () => void;\n forceNextSyncRef: React.MutableRefObject<boolean>;\n}\n\ninterface TokenToggleResult {\n /** HTML to save to the dashboard, or null if the content is already current. */\n pendingSave: string | null;\n /** Editor source to use for this render instead of editorSourceContent. */\n editorSourceOverride: string | null;\n}\n\n/**\n * On showResolvedTokens flip: force re-sync and carry current raw HTML as override (unsaved typing survives).\n * slateToHtml is mode-independent, so emitted HTML matches regardless of display. Caller saves via useEffect.\n */\nfunction handleTokenToggle(args: TokenToggleArgs): TokenToggleResult {\n const { editor, richTextContent, recentSavesRef, cancelPendingChanges, forceNextSyncRef } = args;\n // eslint-disable-next-line no-param-reassign\n forceNextSyncRef.current = true;\n if (!editor) return { pendingSave: null, editorSourceOverride: null };\n const currentRawHtml = slateToHtml(editor.children);\n if (currentRawHtml !== richTextContent) {\n recentSavesRef.current.add(currentRawHtml);\n }\n cancelPendingChanges();\n return {\n pendingSave: currentRawHtml === richTextContent ? null : currentRawHtml,\n editorSourceOverride: currentRawHtml,\n };\n}\n\ntype BareTokenInfo = { absStart: number; rawLen: number; resolvedLen: number };\n\nconst TOKEN_PASTE_SETTLE_MS = 300;\n\ninterface TokenResolutionScheduler {\n beginPasteBurst: () => void;\n flushPendingResolution: () => void;\n requestResolutionRef: React.MutableRefObject<((includeValueChanges?: boolean) => void) | null>;\n}\n\n/**\n * Coalesce token resolution while Slate is processing a paste burst. Resolving replaces the full\n * editor tree, so doing it between rapid paste operations can invalidate Slate's DOM selection.\n * Ordinary typing still resolves through useContentSync's existing microtask.\n */\nfunction useTokenResolutionScheduler(\n resolverRef: React.MutableRefObject<((includeValueChanges?: boolean) => void) | null>,\n enabled: boolean\n): TokenResolutionScheduler {\n const pasteBurstRef = useRef(false);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hasPendingRequestRef = useRef(false);\n const includeValueChangesRef = useRef(false);\n const enabledRef = useRef(enabled);\n enabledRef.current = enabled;\n\n const clearTimer = useCallback(() => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n }, []);\n\n const cancelPendingResolution = useCallback(() => {\n clearTimer();\n pasteBurstRef.current = false;\n hasPendingRequestRef.current = false;\n includeValueChangesRef.current = false;\n }, [clearTimer]);\n\n const flushPendingResolution = useCallback(() => {\n const shouldResolve = enabledRef.current && hasPendingRequestRef.current;\n const includeValueChanges = includeValueChangesRef.current;\n clearTimer();\n pasteBurstRef.current = false;\n hasPendingRequestRef.current = false;\n includeValueChangesRef.current = false;\n if (shouldResolve) {\n resolverRef.current?.(includeValueChanges);\n }\n }, [clearTimer, resolverRef]);\n\n const restartPasteTimer = useCallback(() => {\n clearTimer();\n timerRef.current = setTimeout(flushPendingResolution, TOKEN_PASTE_SETTLE_MS);\n }, [clearTimer, flushPendingResolution]);\n\n const beginPasteBurst = useCallback(() => {\n if (!enabledRef.current) return;\n pasteBurstRef.current = true;\n restartPasteTimer();\n }, [restartPasteTimer]);\n\n const requestResolutionRef = useRef<((includeValueChanges?: boolean) => void) | null>(null);\n requestResolutionRef.current = enabled\n ? (includeValueChanges = false) => {\n if (!pasteBurstRef.current) {\n resolverRef.current?.(includeValueChanges);\n return;\n }\n hasPendingRequestRef.current = true;\n includeValueChangesRef.current ||= includeValueChanges;\n restartPasteTimer();\n }\n : null;\n\n useEffect(() => {\n if (!enabled) {\n cancelPendingResolution();\n }\n }, [cancelPendingResolution, enabled]);\n\n useEffect(() => cancelPendingResolution, [cancelPendingResolution]);\n\n return {\n beginPasteBurst,\n flushPendingResolution,\n requestResolutionRef,\n };\n}\n\nfunction resolvePoint(\n editor: Editor,\n absOffset: number,\n isStart = false\n): ReturnType<typeof absOffsetToPoint> {\n const point = absOffsetToPoint(editor, absOffset, isStart);\n if (point) return point;\n try {\n return Editor.end(editor, []);\n } catch {\n return null;\n }\n}\n\nfunction moveCaretPastTokenIfNeeded(editor: Editor): void {\n if (!editor.selection || !Editor.isEditor(editor)) return;\n const { anchor, focus } = editor.selection;\n const isCollapsed = anchor.offset === focus.offset && anchor.path.join(',') === focus.path.join(',');\n if (!isCollapsed) return;\n try {\n const [node] = Editor.node(editor, anchor);\n const custom = node as { tokenName?: string; isEscapedDollar?: boolean };\n if (!Text.isText(node) || !(custom.tokenName || custom.isEscapedDollar)) return;\n // Snap to end of token node first (in case cursor landed mid-token)\n const endPoint = { path: anchor.path, offset: node.text.length };\n // Move cursor AFTER the token node so next insertText makes a new sibling instead of extending the token.\n // Constrain to same block: Editor.after can cross paragraphs, causing a spurious newline jump.\n const blockPath = anchor.path.slice(0, -1);\n const afterToken = Editor.after(editor, endPoint);\n const staysInBlock =\n afterToken &&\n afterToken.path.length > blockPath.length &&\n afterToken.path.slice(0, blockPath.length).join(',') === blockPath.join(',');\n // eslint-disable-next-line no-param-reassign\n editor.selection = {\n anchor: staysInBlock ? afterToken : endPoint,\n focus: staysInBlock ? afterToken : endPoint,\n };\n } catch {\n // Ignore stale-path errors and keep current selection\n }\n}\n\n/**\n * Adjust an absolute offset by the length delta of each bare token preceding the cursor.\n * A token resolving shorter (e.g. $token$ -> *) leaves fewer chars, so the raw offset overshoots.\n */\nfunction adjustAbsOffsetForResolution(absOffset: number, tokenResolvedLengths: BareTokenInfo[]): number {\n let adjustment = 0;\n for (const { absStart, rawLen, resolvedLen } of tokenResolvedLengths) {\n // Token fully precedes the cursor (cursor is after the raw token end)\n if (absOffset > absStart + rawLen - 1) {\n adjustment += resolvedLen - rawLen;\n } else if (absOffset > absStart) {\n // Cursor is inside the token -- snap to its resolved end\n adjustment += resolvedLen - rawLen;\n break;\n }\n }\n return absOffset + adjustment;\n}\n\n/** Displayed text a token node should show for the current mode: resolved value if any, else raw. */\nfunction displayForToken(tokenName: string, nameToValue: Map<string, string>): string {\n const value = nameToValue.get(tokenName);\n return value !== undefined && value !== '' ? value : `$${tokenName}$`;\n}\n\n/**\n * Text node flagged for re-wrap: bare `$token$`/`$$` in untagged text, or a wrapped node still `isRawToken`.\n * Staleness uses `isRawToken` not text comparison, else a token typed into looks stale and gets wrongly reset.\n */\ntype TokenTextNode = Text & { tokenName?: string; isEscapedDollar?: boolean; isRawToken?: boolean };\n\n/** Bare token deltas found in a single unwrapped text node (scans raw $token$/$$ patterns). */\nfunction bareTokensInPlainText(\n text: string,\n baseOffset: number,\n nameToValue: Map<string, string>\n): BareTokenInfo[] {\n const result: BareTokenInfo[] = [];\n const re = new RegExp(TOKEN_OR_ESCAPE_PATTERN.source, 'g');\n let m = re.exec(text);\n while (m !== null) {\n const rawPattern = m[0];\n const tokenName = m[1];\n // `$$` collapses to a single `$`; a token resolves to its value.\n const resolvedValue = tokenName === undefined ? '$' : (nameToValue.get(tokenName) ?? rawPattern);\n result.push({\n absStart: baseOffset + m.index,\n rawLen: rawPattern.length,\n resolvedLen: resolvedValue.length,\n });\n m = re.exec(text);\n }\n return result;\n}\n\n/** Bare token deltas contributed by a single text node at the given running offset. */\nfunction bareTokensInNode(\n node: TokenTextNode,\n runningOffset: number,\n nameToValue: Map<string, string>,\n includeValueChanges: boolean\n): BareTokenInfo[] {\n const { text } = node;\n // Wrapped token: resolve if still raw, or (on external value change) if display is stale. Stale check gated\n // on includeValueChanges so a token being typed into (text differs from resolved) isn't reset mid-edit.\n if (node.tokenName) {\n const target = displayForToken(node.tokenName, nameToValue);\n if (!node.isRawToken && !(includeValueChanges && text !== target)) return [];\n return [{ absStart: runningOffset, rawLen: text.length, resolvedLen: target.length }];\n }\n // Wrapped escaped dollar (preview mode only): a raw-flagged node resolves `$$`->`$` per escape.\n // Adjacent escapes merge into one node, so half the `$` count resolves.\n if (node.isEscapedDollar) {\n if (!node.isRawToken || !/^\\$+$/.test(text)) return [];\n return [{ absStart: runningOffset, rawLen: text.length, resolvedLen: text.length / 2 }];\n }\n return bareTokensInPlainText(text, runningOffset, nameToValue);\n}\n\nfunction collectBareTokens(\n editor: Editor,\n nameToValue: Map<string, string>,\n includeValueChanges: boolean\n): BareTokenInfo[] {\n const result: BareTokenInfo[] = [];\n let runningOffset = 0;\n for (const [textNode] of Editor.nodes<Text>(editor, { at: [], match: n => Text.isText(n) })) {\n result.push(...bareTokensInNode(textNode, runningOffset, nameToValue, includeValueChanges));\n runningOffset += textNode.text.length;\n }\n return result;\n}\n\ninterface AutoResolveArgs {\n slateEditorRef: React.MutableRefObject<Editor | null>;\n nameToValue: Map<string, string>;\n}\n\n/** Build the auto-resolve callback for showResolvedTokens=true, or null when off. Exported for unit testing only. */\nexport function buildAutoResolveCallback(\n args: AutoResolveArgs\n): ((includeValueChanges?: boolean) => void) | null {\n const { slateEditorRef, nameToValue } = args;\n\n // includeValueChanges: set on external nameToValue change (not keystroke) to re-wrap resolved-but-stale nodes.\n return (includeValueChanges = false) => {\n const editor = slateEditorRef.current;\n if (!editor) return;\n\n // Collect bare tokens BEFORE the tree is replaced so cursor offsets can be adjusted.\n const bareTokenInfo = collectBareTokens(editor, nameToValue, includeValueChanges);\n if (bareTokenInfo.length === 0) return;\n\n const rawAnchorAbs = editor.selection ? pointToAbsOffset(editor, editor.selection.anchor) : null;\n const rawFocusAbs = editor.selection ? pointToAbsOffset(editor, editor.selection.focus) : null;\n\n // Re-wrap in place so bare tokens show resolved values, avoiding a slateToHtml -> htmlToSlate round-trip.\n const newTree = wrapRawTokensInTree(editor.children, nameToValue);\n\n const anchorAbs =\n rawAnchorAbs === null ? null : adjustAbsOffsetForResolution(rawAnchorAbs, bareTokenInfo);\n const focusAbs =\n rawFocusAbs === null ? null : adjustAbsOffsetForResolution(rawFocusAbs, bareTokenInfo);\n\n // eslint-disable-next-line no-param-reassign\n editor.children = newTree;\n\n if (anchorAbs !== null && focusAbs !== null) {\n const collapsed = anchorAbs === focusAbs;\n const anchor = resolvePoint(editor, anchorAbs, !collapsed);\n const focus = resolvePoint(editor, focusAbs, false);\n // eslint-disable-next-line no-param-reassign\n editor.selection = anchor && focus ? { anchor, focus } : null;\n } else {\n // eslint-disable-next-line no-param-reassign\n editor.selection = null;\n }\n\n moveCaretPastTokenIfNeeded(editor);\n\n const selectionAfterResolve = editor.selection;\n editor.onChange();\n\n // Tree swap clears the native DOM selection; Transforms.select fires a set_selection op so\n // slate-react re-syncs the caret into the DOM and the user can keep typing.\n if (selectionAfterResolve) {\n try {\n Transforms.select(editor, selectionAfterResolve);\n } catch {\n // ignore stale-path errors\n }\n }\n };\n}\n\nconst PureRichText = React.forwardRef<HTMLDivElement, PureRichTextProps>((props, ref) => {\n // Get theme for default colors\n const theme = useSplunkTheme();\n const themeTextColor = theme.contentColorDefault;\n\n const {\n richTextContent = '',\n fontColor,\n highlightColor,\n fontFamily = 'Splunk Data Sans',\n fontSize = 'default',\n customFontSize = 14,\n backgroundColor = 'transparent',\n verticalAlign = 'top',\n lineHeight = '1.5',\n border,\n padding,\n mode = 'view',\n onOptionsChange,\n onRichtextClick = noop,\n onLinkOpen,\n hasEventHandlers = false,\n bold = false,\n italic = false,\n underline = false,\n strikethrough = false,\n defaultTextStyles,\n previewTokenValues = false,\n richTextTokenMetadata: richTextTokenMetadataProp,\n } = props;\n\n // Apply defaultTextStyles overrides on top of individual props\n const effectiveFontColorFromStyles = defaultTextStyles?.color || fontColor;\n const effectiveHighlightColor = defaultTextStyles?.backgroundColor || highlightColor;\n const effectiveFontFamily = defaultTextStyles?.fontFamily || fontFamily;\n const effectiveBold = defaultTextStyles?.bold ?? bold;\n const effectiveItalic = defaultTextStyles?.italic ?? italic;\n const effectiveUnderline = defaultTextStyles?.underline ?? underline;\n const effectiveStrikethrough = defaultTextStyles?.strikethrough ?? strikethrough;\n\n const { effectiveFontSize, effectiveCustomFontSize } = resolveFontSize(\n defaultTextStyles,\n fontSize,\n customFontSize\n );\n\n // Adapt framework onLinkOpen ({ payload: { url } }) to (url) => void; undefined lets the renderer open natively.\n const handleLinkOpen = useMemo(\n () => (onLinkOpen ? (url: string): void => onLinkOpen({ payload: { url } }) : undefined),\n [onLinkOpen]\n );\n\n // Use theme color as default if fontColor not provided\n const effectiveFontColor = effectiveFontColorFromStyles || themeTextColor;\n\n const isEditMode = mode === 'edit';\n const containerRef = useRef<HTMLDivElement>(null);\n // Viewport point of the last container mousedown, to tell a click from a drag-to-reposition\n // (whose trailing click must not activate editing / scroll the editor to the bottom).\n const containerMouseDownRef = useRef<{ x: number; y: number } | null>(null);\n const slateEditorRef = useRef<Editor | null>(null);\n // Whether the Slate editable holds DOM focus. Text-editing can persist with focus in the config panel;\n // that isn't \"editor owns content\", so external richTextContent edits must still apply.\n const editorHasFocusRef = useRef(false);\n const updateActiveStylesFnRef = useRef<(() => void) | null>(null);\n const clearFakeHighlightRef = useRef<(() => void) | null>(null);\n const forceNextSyncRef = useRef(false);\n const transformTreeRef = useRef<((tree: Descendant[]) => Descendant[]) | null>(null);\n // Callback ref that sets both the forwarded ref and our internal containerRef\n const setContainerRef = useCallback(\n (node: HTMLDivElement | null) => {\n containerRef.current = node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n // eslint-disable-next-line no-param-reassign\n ref.current = node;\n }\n },\n [ref]\n );\n const [currentVerticalAlign, setCurrentVerticalAlign] = useState<VerticalAlign>(verticalAlign);\n // Centralized text-editing lifecycle state.\n const richTextState = useRichTextState();\n const { isTextEditing, isTextEditingRef, wasTextEditingRef } = richTextState;\n const [currentLineHeight, setCurrentLineHeight] = useState<string>(String(lineHeight));\n const [announcement, setAnnouncement] = useState('');\n // Clear-then-set so repeated identical announcements still trigger the live region.\n const handleAnnouncement = useCallback((msg: string) => {\n setAnnouncement('');\n requestAnimationFrame(() => setAnnouncement(msg));\n }, []);\n\n // Stable ID for this instance \u2014 used to track which richtext owns the editor panel\n const instanceId = useId();\n const isActive = useIsActiveRichText(instanceId);\n\n // Entering edit mode: register active so the panel shows. Leaving: deactivate to hide panel and reset editing.\n useEffect(() => {\n if (isEditMode) {\n registerActiveRichText(instanceId, null, slateEditorRef.current);\n } else {\n clearActiveRichText(instanceId);\n richTextState.deactivateTextEditing();\n }\n }, [isEditMode, instanceId]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Register active when selected so the panel shows. Do NOT steal focus -- the framework manages\n // focus on select-outline so Cmd+A (select all vizs) works.\n useEffect(() => {\n if (!isEditMode || isTextEditing) return undefined;\n\n const checkAndRegister = (): void => {\n const isSelected = containerRef.current?.closest('[data-selected=\"true\"]') != null;\n if (isSelected) {\n registerActiveRichText(instanceId, null, slateEditorRef.current);\n }\n };\n\n const selectedAncestor = containerRef.current?.closest('[data-selected]');\n let observer: MutationObserver | null = null;\n if (selectedAncestor) {\n observer = new MutationObserver(checkAndRegister);\n observer.observe(selectedAncestor, {\n attributes: true,\n attributeFilter: ['data-selected'],\n });\n }\n\n checkAndRegister();\n\n return () => {\n observer?.disconnect();\n };\n }, [instanceId, isEditMode, isTextEditing]);\n\n // Deactivate text editing on external deselect (e.g. config panel calls updateSelectedItems([])); else\n // isTextEditing and data-no-drag persist, making the next click drag instead of select.\n useEffect(() => {\n if (!isEditMode || !isTextEditing) return undefined;\n\n const selectedAncestor = containerRef.current?.closest<HTMLElement>('[data-selected]');\n if (!selectedAncestor) return undefined;\n\n const observer = new MutationObserver(() => {\n const isSelected = selectedAncestor.dataset.selected === 'true';\n if (!isSelected) {\n richTextState.deactivateTextEditing();\n }\n });\n observer.observe(selectedAncestor, {\n attributes: true,\n attributeFilter: ['data-selected'],\n });\n\n return () => {\n observer.disconnect();\n };\n }, [isEditMode, isTextEditing, richTextState]);\n\n // Dashboard API for programmatic deselection.\n const dashboardCoreApi = React.useContext(DashboardCoreApiContext) as {\n updateSelectedItems: (items?: unknown[]) => void;\n } | null;\n\n // Sync verticalAlign and lineHeight props to local state\n useEffect(() => {\n setCurrentVerticalAlign(verticalAlign);\n setCurrentLineHeight(String(lineHeight));\n }, [verticalAlign, lineHeight]);\n\n // Compute font size\n const fontSizeInPx = getFontSizeInPx(effectiveFontSize, effectiveCustomFontSize);\n\n // Parse border config\n const borderConfig = border || {};\n const borderColor = borderConfig.color;\n const borderWidth = borderConfig.width;\n const borderStyle = borderConfig.style || 'solid';\n const borderRadius = borderConfig.radius || 0;\n\n // Parse padding\n const paddingValues = parsePadding(padding);\n\n // Name->value map + raw ($token$) content from framework-injected metadata.\n const { nameToValue, rawContent } = useTokenMap(richTextContent, richTextTokenMetadataProp);\n\n // `showResolvedTokens` selects the display mode; editor source is always raw.\n const { editorSourceContent, showResolvedTokens } = resolveTokenDisplay({\n isEditMode,\n previewTokenValues,\n resolvedContent: richTextContent,\n rawContent,\n });\n\n // Content save: immediate for structural/format ops, batched for typing.\n // slateToHtml already emits raw $token$ patterns, so no restore step is needed.\n const { handleContentChange, flushPendingChanges, cancelPendingChanges, recentSavesRef } = useContentSave(\n {\n richTextContent: editorSourceContent,\n onOptionsChange,\n restoreTokensInHtml: identityRestore,\n }\n );\n\n // On showResolvedTokens flip, force re-sync even with focus. Set during render (not useEffect) so the flag\n // is true when InnerEditor's useContentSync effect runs in the same commit (child effects fire first).\n const prevShowResolvedRef = useRef(showResolvedTokens);\n // HTML from handleTokenToggle to save; written during render, dispatched in the useEffect below (never mid-render).\n const pendingToggleSaveRef = useRef<string | null>(null);\n // Local to this render -- only survives to effectiveEditorSourceContent below.\n let editorSourceOverride: string | null = null;\n if (prevShowResolvedRef.current !== showResolvedTokens) {\n prevShowResolvedRef.current = showResolvedTokens;\n const result = handleTokenToggle({\n editor: slateEditorRef.current,\n richTextContent,\n recentSavesRef,\n cancelPendingChanges,\n forceNextSyncRef,\n });\n pendingToggleSaveRef.current = result.pendingSave;\n editorSourceOverride = result.editorSourceOverride;\n }\n\n // Dispatch the save handleTokenToggle prepared; useEffect keeps it out of render (required in concurrent mode).\n useEffect(() => {\n const html = pendingToggleSaveRef.current;\n pendingToggleSaveRef.current = null;\n if (html !== null) {\n onOptionsChange?.({ richTextContent: html });\n }\n }, [showResolvedTokens]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Raw edit mode must leave `$token$` patterns as ordinary Slate text. Wrapping them creates\n // atomic token leaves, which can move the caret or replace text while the user is typing.\n transformTreeRef.current = (tree: Descendant[]) =>\n showResolvedTokens ? wrapRawTokensInTree(tree, nameToValue) : tree;\n\n // Keep the resolver current without re-subscribing consumers when token metadata changes.\n const tokenResolverRef = useRef<((includeValueChanges?: boolean) => void) | null>(null);\n tokenResolverRef.current = showResolvedTokens\n ? buildAutoResolveCallback({ slateEditorRef, nameToValue })\n : null;\n const {\n beginPasteBurst,\n flushPendingResolution,\n requestResolutionRef: autoResolveTokensRef,\n } = useTokenResolutionScheduler(tokenResolverRef, showResolvedTokens);\n\n // Re-run auto-resolve when dashboard token metadata OR the reconstructed raw content changes.\n // Dynamic-dashboard edits can reuse the same token map while returning newly pasted token content,\n // so watching nameToValue alone leaves the first paste raw until another edit or a preview toggle.\n const prevNameToValueRef = useRef(nameToValue);\n const prevEditorSourceContentRef = useRef(editorSourceContent);\n useEffect(() => {\n const prev = prevNameToValueRef.current;\n const tokenMapChanged = nameToValue !== prev;\n const sourceContentChanged = editorSourceContent !== prevEditorSourceContentRef.current;\n prevNameToValueRef.current = nameToValue;\n prevEditorSourceContentRef.current = editorSourceContent;\n if ((tokenMapChanged || sourceContentChanged) && autoResolveTokensRef.current) {\n // Only a token-map change may refresh already-resolved nodes. A content-only round-trip\n // resolves bare pasted tokens without resetting a resolved token the user is editing.\n autoResolveTokensRef.current(tokenMapChanged);\n }\n }, [autoResolveTokensRef, editorSourceContent, nameToValue]);\n\n const effectiveEditorSourceContent = editorSourceOverride ?? editorSourceContent;\n // Token-value changes do not affect raw editor text. Keeping this dependency null in raw mode\n // avoids rebuilding initialValue whenever the framework refreshes token metadata.\n const initialValueTokenMap = showResolvedTokens ? nameToValue : null;\n\n // Parse HTML and wrap $token$ as atomic nodes only when resolved values are displayed.\n const initialValueRef = useRef<Descendant[]>(EMPTY_SLATE_VALUE);\n // Display mode of the last computed tree; lets a toggle force a recompute though source HTML is unchanged.\n const initialValueModeRef = useRef(showResolvedTokens);\n const initialValue = useMemo(() => {\n const modeChanged = initialValueModeRef.current !== showResolvedTokens;\n initialValueModeRef.current = showResolvedTokens;\n // Editor tree is authoritative while editing; also skip recompute for save round-trips. Toggle always recomputes.\n if (\n !modeChanged &&\n (recentSavesRef.current.has(effectiveEditorSourceContent) ||\n (isTextEditingRef.current && editorHasFocusRef.current))\n ) {\n return initialValueRef.current;\n }\n if (!effectiveEditorSourceContent) {\n initialValueRef.current = EMPTY_SLATE_VALUE;\n return EMPTY_SLATE_VALUE;\n }\n const tree = htmlToSlate(effectiveEditorSourceContent);\n const result = initialValueTokenMap ? wrapRawTokensInTree(tree, initialValueTokenMap) : tree;\n initialValueRef.current = result;\n return result;\n }, [effectiveEditorSourceContent, initialValueTokenMap, showResolvedTokens]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Handle focus gained: register this instance as active (displacing any other).\n const handleFocusGained = useCallback(\n (editable: HTMLDivElement | null, slateEditor: Editor | null) => {\n editorHasFocusRef.current = true;\n registerActiveRichText(instanceId, editable, slateEditor);\n },\n [instanceId]\n );\n\n // Focus lost: do NOT clear active (only changes when another instance gains focus), so panel inputs\n // (color pickers, number fields) don't disrupt active state when they temporarily steal DOM focus.\n const handleFocusLost = useCallback(() => {\n editorHasFocusRef.current = false;\n flushPendingResolution();\n flushPendingChanges();\n }, [flushPendingChanges, flushPendingResolution]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n flushPendingChanges();\n clearActiveRichText(instanceId);\n };\n }, [flushPendingChanges, instanceId]);\n\n // Handle vertical alignment change\n const handleVerticalAlignChange = useCallback(\n (align: VerticalAlign) => {\n setCurrentVerticalAlign(align);\n onOptionsChange?.({ verticalAlign: align });\n },\n [onOptionsChange]\n );\n\n // Default text style object\n const defaultTextStyle = useMemo(\n () => ({\n color: effectiveFontColor,\n backgroundColor: effectiveHighlightColor,\n fontSize: `${fontSizeInPx}px`,\n fontFamily: effectiveFontFamily,\n lineHeight: currentLineHeight,\n bold: effectiveBold,\n italic: effectiveItalic,\n underline: effectiveUnderline,\n strikethrough: effectiveStrikethrough,\n }),\n [\n effectiveFontColor,\n effectiveHighlightColor,\n fontSizeInPx,\n effectiveFontFamily,\n currentLineHeight,\n effectiveBold,\n effectiveItalic,\n effectiveUnderline,\n effectiveStrikethrough,\n ]\n );\n\n const activateTextEditing = useCallback(() => {\n richTextState.activateTextEditing();\n requestAnimationFrame(() => {\n const editable = containerRef.current?.querySelector<HTMLElement>('[data-slate-editor]');\n editable?.focus({ preventScroll: true });\n if (slateEditorRef.current && !slateEditorRef.current.selection) {\n safeSelectEnd(slateEditorRef.current);\n }\n });\n }, [richTextState]);\n\n // Dashboard keyboard navigation: skip-links, Escape-from-sidebar, Enter-to-edit, focusout\n useDashboardKeyboardNav({\n isEditMode,\n containerRef,\n instanceId,\n slateEditorRef,\n isTextEditingRef,\n wasTextEditingRef,\n clearFakeHighlightRef,\n updateActiveStylesFnRef,\n activateTextEditing,\n richTextState,\n dashboardCoreApi,\n });\n\n // Grid canvas has a capture-phase mousedown (captureSelectionState) that preventDefaults on non-interactive\n // targets; Slate's readOnly Editable isn't contentEditable, so it blocks focus/selection/click-to-place-caret.\n // Check live DOM (data-selected, isTextEditingRef) not React state, to avoid stale closures after external deselect.\n useEffect(() => {\n if (!isEditMode) return undefined;\n\n const guard = (e: MouseEvent): void => {\n const target = e.target as HTMLElement;\n if (!containerRef.current?.contains(target)) return;\n const isVizSelected = containerRef.current.closest('[data-selected=\"true\"]') != null;\n if (!isVizSelected) return;\n if (!isTextEditingRef.current) {\n e.preventDefault = () => {};\n return;\n }\n const isOnSlateContent = target.closest('[data-slate-node]') != null;\n if (isOnSlateContent) {\n e.preventDefault = () => {};\n }\n };\n document.addEventListener('mousedown', guard, true);\n return () => document.removeEventListener('mousedown', guard, true);\n }, [isEditMode]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Edit mode, not yet editing: a bubbling click enters editing unless it was really a\n // drag-to-reposition, a suppressed post-drag click, a press already handled by\n // useMouseHandlers, the viz isn't selected, or the click landed on the edge/padding.\n const maybeActivateEditing = useCallback(\n (e: React.MouseEvent): void => {\n if (!containerRef.current) return;\n const down = containerMouseDownRef.current;\n containerMouseDownRef.current = null;\n if (\n down &&\n (Math.abs(e.clientX - down.x) > CONTAINER_MOVE_THRESHOLD ||\n Math.abs(e.clientY - down.y) > CONTAINER_MOVE_THRESHOLD)\n ) {\n return;\n }\n if (consumeSuppressNextEditClick()) return;\n if (isMouseSelecting()) return;\n const isVizSelected = containerRef.current.closest('[data-selected=\"true\"]') != null;\n if (!isVizSelected) return;\n const wrapper = containerRef.current.querySelector('[data-richtext-editor-wrapper]');\n if (wrapper && !wrapper.contains(e.target as Node)) return;\n registerActiveRichText(instanceId, null, slateEditorRef.current);\n activateTextEditing();\n },\n [activateTextEditing, instanceId]\n );\n\n // While editing, a click outside the editable either exits editing (edge/padding, keeping the\n // viz selected so Delete works, mirroring Escape) or keeps editing with the caret at end.\n const handleEditingOutsideClick = useCallback(\n (e: React.MouseEvent): void => {\n if (!containerRef.current) return;\n const editable = containerRef.current.querySelector<HTMLElement>('[data-slate-editor]');\n if (!editable || editable.contains(e.target as Node)) return;\n\n const wrapper = containerRef.current.querySelector('[data-richtext-editor-wrapper]');\n if (wrapper && !wrapper.contains(e.target as Node)) {\n const editorToDeselect = slateEditorRef.current;\n if (editorToDeselect) {\n try {\n Transforms.deselect(editorToDeselect);\n } catch {\n // editor may be empty\n }\n }\n globalThis.getSelection()?.removeAllRanges();\n richTextState.deactivateTextEditing();\n editable.blur();\n focusSelectOutline(containerRef.current);\n return;\n }\n\n editable.focus({ preventScroll: true });\n const slateEditor = getActiveSlateEditor();\n if (slateEditor) {\n safeSelectEnd(slateEditor);\n }\n },\n [richTextState]\n );\n\n const handleContainerClick = useCallback(\n (e: React.MouseEvent) => {\n if (hasEventHandlers && !isEditMode) {\n onRichtextClick(e);\n }\n if (isEditMode && !isTextEditing && containerRef.current) {\n maybeActivateEditing(e);\n return;\n }\n if (!isTextEditing || !containerRef.current || isMouseSelecting()) return;\n handleEditingOutsideClick(e);\n },\n [\n hasEventHandlers,\n isEditMode,\n isTextEditing,\n onRichtextClick,\n maybeActivateEditing,\n handleEditingOutsideClick,\n ]\n );\n\n return (\n <PureRichTextProvider\n defaultColor={effectiveFontColor}\n defaultBackgroundColor={effectiveHighlightColor || 'transparent'}\n defaultFontFamily={effectiveFontFamily}\n defaultFontSize={`${fontSizeInPx}px`}\n defaultBold={effectiveBold}\n defaultItalic={effectiveItalic}\n defaultUnderline={effectiveUnderline}\n defaultStrikethrough={effectiveStrikethrough}\n >\n <PureRichTextContainer\n ref={setContainerRef}\n $backgroundColor={backgroundColor}\n $verticalAlign={currentVerticalAlign}\n $borderColor={borderColor}\n $borderWidth={borderWidth}\n $borderStyle={borderStyle}\n $borderRadius={borderRadius}\n $padding={paddingValues}\n $isTextEditing={isTextEditing}\n $isEditMode={isEditMode}\n $hasEventHandlers={hasEventHandlers && !isEditMode}\n data-no-drag={isTextEditing ? 'true' : undefined}\n data-text-editor={isTextEditing ? 'true' : undefined}\n data-test=\"purerichtext-container\"\n role={isEditMode ? undefined : 'region'}\n aria-label={isEditMode ? undefined : slateToPlainText(initialValue) || 'Empty rich text'}\n onMouseDownCapture={(e: React.MouseEvent) => {\n containerMouseDownRef.current = { x: e.clientX, y: e.clientY };\n }}\n onClick={handleContainerClick}\n >\n {hasEventHandlers && !isEditMode && (\n <DrilldownButton\n onClick={(e: React.MouseEvent) => {\n e.stopPropagation();\n onRichtextClick(e);\n }}\n appearance=\"secondary\"\n data-test=\"richtext-drilldown\"\n >\n Drilldown\n </DrilldownButton>\n )}\n <EditorWrapper\n $isEditMode={isEditMode}\n $isTextEditing={isTextEditing}\n $hasEventHandlers={hasEventHandlers}\n $lineHeight={currentLineHeight}\n $verticalAlign={currentVerticalAlign}\n data-richtext-editor-wrapper\n onMouseDown={(e: React.MouseEvent) => {\n // A scrollbar press targets the wrapper itself; stop it so the canvas doesn't read the\n // scrollbar drag as a viz move. Runs in every mode (bug also occurs when unfocused).\n if (e.target === e.currentTarget) {\n e.stopPropagation();\n }\n }}\n >\n <InnerEditor\n initialValue={initialValue}\n richTextContent={effectiveEditorSourceContent}\n isEditMode={isEditMode}\n isTextEditing={isTextEditing}\n containerRef={containerRef}\n defaultTextStyle={defaultTextStyle}\n onContentChange={handleContentChange}\n onFocusGained={handleFocusGained}\n onFocusLost={handleFocusLost}\n onCancelPendingChanges={cancelPendingChanges}\n richTextState={richTextState}\n onEditorReady={ed => {\n slateEditorRef.current = ed;\n }}\n updateActiveStylesRef={updateActiveStylesFnRef}\n clearFakeHighlightRef={clearFakeHighlightRef}\n recentSavesRef={recentSavesRef}\n forceNextSyncRef={forceNextSyncRef}\n transformTreeRef={transformTreeRef}\n syncInitialValueChanges={showResolvedTokens}\n autoResolveTokensRef={autoResolveTokensRef}\n onPasteStart={beginPasteBurst}\n onAnnouncement={handleAnnouncement}\n nameToValue={nameToValue}\n onLinkOpen={handleLinkOpen}\n />\n </EditorWrapper>\n <LiveRegion aria-live=\"polite\" aria-atomic=\"true\">\n {announcement}\n </LiveRegion>\n </PureRichTextContainer>\n\n {/* Editor Panel - portals into editor sidebar only when this instance is focused */}\n <EditorPanel\n isEditMode={isEditMode}\n isActive={isActive}\n fontColor={effectiveFontColor}\n fontSize={fontSizeInPx}\n lineHeight={currentLineHeight}\n verticalAlign={currentVerticalAlign}\n onVerticalAlignChange={handleVerticalAlignChange}\n />\n </PureRichTextProvider>\n );\n});\n\nPureRichText.displayName = 'PureRichText';\n\n// Export the pure component and utility functions\nexport { Leaf } from './renderers/LeafRenderer';\nexport { createElementRenderer } from './renderers/ElementRenderer';\nexport { getFontSizeInPx };\nexport { InnerEditor } from './InnerEditor';\nexport type { InnerEditorProps } from './InnerEditor';\nexport type { PureRichTextProps };\n// Export as both PureRichText and PureRichTextPure for compatibility with stories\nexport { PureRichText as PureRichTextPure };\nexport default PureRichText;\n", "import { richTextOptionsSchema as optionsSchema } from '@splunk/visualization-schemas';\nimport vizConfig from './config';\nimport withDashboardViz from '../common/withDashboardViz';\nimport PureRichText, { PureRichTextProps } from './PureRichText/PureRichText';\nimport { FontSizePreset, RichTextTokenMetadata } from './PureRichText/types';\n\nconst validOptions = Object.keys(optionsSchema);\n\ntype ComputeVizPropsFn = (props: {\n options: Record<string, any>;\n dataSources: any;\n mode?: 'view' | 'edit';\n onRichtextClick?: (...args: any) => void;\n onOptionsChange?: (options: Record<string, unknown>) => void;\n richTextContent?: string;\n hasEventHandlers?: boolean;\n richTextTokenMetadata?: RichTextTokenMetadata;\n [key: string]: any;\n}) => Partial<PureRichTextProps>;\n\n// Pick valid options from the raw options map.\nfunction pickValidOptions(options: Record<string, any>): Record<string, any> {\n const picked: Record<string, any> = {};\n validOptions.forEach(key => {\n if (options[key] !== undefined) {\n picked[key] = options[key];\n }\n });\n return picked;\n}\n\n// Build the border config from options, supporting both nested and flat shapes.\nfunction buildBorderConfig(\n pickedOptions: Record<string, any>,\n options: Record<string, any>\n): Record<string, any> | undefined {\n if (pickedOptions.border) return pickedOptions.border;\n if (options.borderColor || options.borderWidth) {\n return {\n color: options.borderColor,\n width: options.borderWidth,\n style: options.borderStyle || 'solid',\n radius: options.borderRadius || 0,\n };\n }\n return undefined;\n}\n\n// Build defaultTextStyles from options, supporting both nested object and individual props.\nfunction buildDefaultTextStyles(\n pickedOptions: Record<string, any>,\n options: Record<string, any>\n): Record<string, any> {\n if (options.defaultTextStyles && typeof options.defaultTextStyles === 'object') {\n return { ...options.defaultTextStyles };\n }\n const styles: Record<string, any> = {};\n if (pickedOptions.fontColor) styles.color = pickedOptions.fontColor;\n if (pickedOptions.highlightColor) styles.backgroundColor = pickedOptions.highlightColor;\n if (pickedOptions.fontFamily) styles.fontFamily = pickedOptions.fontFamily;\n if (pickedOptions.fontSize || pickedOptions.customFontSize) {\n const fontSize = pickedOptions.fontSize || 'default';\n const customFontSize = pickedOptions.customFontSize || 14;\n styles.fontSize = fontSize === 'custom' ? `${customFontSize}px` : undefined;\n }\n if (pickedOptions.bold) styles.bold = true;\n if (pickedOptions.italic) styles.italic = true;\n if (pickedOptions.underline) styles.underline = true;\n if (pickedOptions.strikethrough) styles.strikethrough = true;\n return styles;\n}\n\n// Resolve fontSize and customFontSize \u2014 handles the case where fontSize is a px string.\nfunction resolveFontSize(\n defaultTextStyles: Record<string, any>,\n pickedOptions: Record<string, any>\n): { fontSize: FontSizePreset | undefined; customFontSize: number | undefined } {\n let fontSize: FontSizePreset | undefined = defaultTextStyles.fontSize || pickedOptions.fontSize;\n let customFontSize: number | undefined = defaultTextStyles.customFontSize || pickedOptions.customFontSize;\n if (typeof fontSize === 'string' && fontSize.endsWith('px')) {\n customFontSize = Number.parseInt(fontSize, 10);\n fontSize = 'custom';\n }\n return { fontSize, customFontSize };\n}\n\nexport const computeVizProps: ComputeVizPropsFn = ({\n options,\n mode,\n onRichtextClick,\n onOptionsChange,\n richTextContent: richTextContentProp,\n hasEventHandlers = false,\n richTextTokenMetadata,\n}) => {\n const pickedOptions = pickValidOptions(options);\n const border = buildBorderConfig(pickedOptions, options);\n const defaultTextStyles = buildDefaultTextStyles(pickedOptions, options);\n\n const fontColor = defaultTextStyles.color || pickedOptions.fontColor;\n const highlightColor =\n defaultTextStyles.highlightColor || defaultTextStyles.backgroundColor || pickedOptions.highlightColor;\n const fontFamily = defaultTextStyles.fontFamily || pickedOptions.fontFamily;\n const { fontSize, customFontSize } = resolveFontSize(defaultTextStyles, pickedOptions);\n\n const bold = defaultTextStyles.bold ?? pickedOptions.bold ?? false;\n const italic = defaultTextStyles.italic ?? pickedOptions.italic ?? false;\n const underline = defaultTextStyles.underline ?? pickedOptions.underline ?? false;\n const strikethrough = defaultTextStyles.strikethrough ?? pickedOptions.strikethrough ?? false;\n\n return {\n richTextContent: richTextContentProp || '',\n fontColor,\n highlightColor,\n fontFamily,\n fontSize,\n customFontSize,\n backgroundColor: pickedOptions.backgroundColor || 'transparent',\n verticalAlign: pickedOptions.verticalAlign,\n lineHeight: pickedOptions.lineHeight,\n border,\n padding: pickedOptions.padding,\n mode,\n onRichtextClick,\n onOptionsChange,\n defaultTextStyles,\n bold,\n italic,\n underline,\n strikethrough,\n hasEventHandlers,\n previewTokenValues: pickedOptions.previewTokenValues ?? false,\n richTextTokenMetadata,\n };\n};\n\nconst RichText = withDashboardViz({\n ReactViz: PureRichText as any,\n computeVizProps,\n vizConfig,\n disableEditModeCover: true,\n});\n\n// Tells the framework to inject token resolution metadata (TokenMatchMetadata shape)\n// into the `richTextTokenMetadata` prop.\n(RichText as any).tokenMetadataProp = 'richTextTokenMetadata';\n\nexport const { themes } = vizConfig;\nexport const config = vizConfig;\nexport default RichText;\n"],
5
+ "mappings": "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",
6
+ "names": ["RichText_exports", "config", "RichText_default", "themes", "defaultImport", "defaultImport", "defaultImport", "RichText_exports", "RichText_default", "defaultImport", "RichText_exports", "RichText_default", "defaultImport", "defaultImport", "config", "themes", "optionsSchema", "RichText_default", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "config", "themes", "_a", "defaultImport", "_a", "_a", "_a", "Opts", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "_a", "getFieldName", "_a", "_a", "_a", "getFieldName", "config", "range", "Opts", "computeVizProps", "_a", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "_a", "_a", "SlateElement", "SlateNode", "_", "result", "_a", "SlateElement", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "defaultImport", "_a", "_a", "size", "_a", "range", "_a", "SlateNode", "e", "range", "SlateNode", "e", "_a", "size", "_a", "isLeafBlock", "_a", "SlateElement", "_a", "_a", "_a", "_a", "_a", "_b", "e", "handleClick", "_a", "e", "optionsSchema", "resolveFontSize", "_a", "themes", "config", "RichText_default"]
7
7
  }