@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 CHANGED
@@ -186,6 +186,19 @@ var themes = {
186
186
  defaultBackgroundColor: () => "transparent"
187
187
  };
188
188
  var editorConfig = [
189
+ {
190
+ label: (0, i18n_exports._)("Data display"),
191
+ open: true,
192
+ layout: [
193
+ [
194
+ {
195
+ label: (0, i18n_exports._)("Preview token values"),
196
+ option: "previewTokenValues",
197
+ editor: "editor.toggle"
198
+ }
199
+ ]
200
+ ]
201
+ },
189
202
  {
190
203
  label: (0, i18n_exports._)("Color and style"),
191
204
  open: true,
@@ -261,7 +274,7 @@ var config = {
261
274
  * viz name
262
275
  */
263
276
  name: (0, i18n_exports._)("Text"),
264
- category: "Comparisons" /* COMPARISONS */,
277
+ category: "Text" /* TEXT */,
265
278
  status: "preview",
266
279
  /**
267
280
  * viz icon
@@ -275,6 +288,11 @@ var config = {
275
288
  events: {
276
289
  "richtext.click": {
277
290
  description: "triggered when user clicks on rich text area not formatted as a link"
291
+ },
292
+ "link.open": {
293
+ description: "triggered when the user activates a link; payload carries the resolved url",
294
+ // Default behavior: fires ungated by event handlers and in edit mode too.
295
+ source: "default"
278
296
  }
279
297
  },
280
298
  supports: ["dynamic-options" /* DYNAMIC_OPTIONS */, "events" /* EVENTS */],
@@ -537,7 +555,10 @@ var useSortingParams = ({ requestParams, onRequestParamsChange }) => {
537
555
  onSort = (e, { sortKey, sortDir }) => {
538
556
  if (typeof sortKey === "string") {
539
557
  const nextSortDir = (0, lodash_exports.has)(nextSortDirMap, sortDir) ? nextSortDirMap[sortDir] : "none";
540
- onRequestParamsChange(__spreadValues(__spreadValues({}, requestParams), { offset: 0, sort: { [sortKey]: nextSortDir } }));
558
+ onRequestParamsChange(__spreadProps(__spreadValues({}, requestParams), {
559
+ offset: 0,
560
+ sort: { [sortKey]: nextSortDir }
561
+ }));
541
562
  } else {
542
563
  onRequestParamsChange(requestParams);
543
564
  }
@@ -672,7 +693,7 @@ var Cover = styled_components_default.div`
672
693
  bottom: 0;
673
694
  `;
674
695
  var Blocker = styled_components_default.div.attrs({
675
- "data-splunk-visualization-version": "28.7.0 - d7b18cab6"
696
+ "data-splunk-visualization-version": "28.9.0 - 96b03188d"
676
697
  })`
677
698
  position: relative;
678
699
  width: 100%;
@@ -771,7 +792,7 @@ var withFixedSizeContainer = (Viz) => {
771
792
  FixSizeItem,
772
793
  {
773
794
  "data-test": "fix-size-item",
774
- "data-splunk-visualization-version": "28.7.0 - d7b18cab6",
795
+ "data-splunk-visualization-version": "28.9.0 - 96b03188d",
775
796
  width,
776
797
  height,
777
798
  backgroundColor
@@ -792,6 +813,14 @@ var shouldShowIconPlaceholder = (dataSources, loading = false) => {
792
813
  const noFields = fields === void 0;
793
814
  return loading || noData || noFields;
794
815
  };
816
+ var PlaceholderContainer = styled_components_default.div`
817
+ /* The inline token color wins when supported. Older browsers discard an
818
+ unsupported oklch value and retain this inherited fallback instead. */
819
+ color: ${(0, themes_exports.pick)({
820
+ dark: "#fafafa",
821
+ light: "#2c2c2c"
822
+ })};
823
+ `;
795
824
  var IconPlaceholder = (props) => {
796
825
  const {
797
826
  width = SplunkVisualization_default.defaults.width,
@@ -806,7 +835,6 @@ var IconPlaceholder = (props) => {
806
835
  style: {
807
836
  left: "50%",
808
837
  top: "50%",
809
- color: iconColor,
810
838
  opacity: 0.15,
811
839
  position: "absolute",
812
840
  transform: "translate(-50%, -50%)"
@@ -816,7 +844,14 @@ var IconPlaceholder = (props) => {
816
844
  "data-test": "icon-placeholder"
817
845
  });
818
846
  }
819
- return /* @__PURE__ */ react_exports.createElement("div", { style: { width, height, background: backgroundColor } }, content);
847
+ return /* @__PURE__ */ react_exports.createElement(
848
+ PlaceholderContainer,
849
+ {
850
+ "data-test": "icon-placeholder-container",
851
+ style: { width, height, background: backgroundColor, color: iconColor }
852
+ },
853
+ content
854
+ );
820
855
  };
821
856
  var IconPlaceholder_default = FixedSizeContainer_default(IconPlaceholder);
822
857
 
@@ -825,7 +860,7 @@ var withPlaceholder = (Visualization, useIconPlaceholder = shouldShowIconPlaceho
825
860
  const { config: config3 } = Visualization;
826
861
  const { themes: themes3 } = config3;
827
862
  const Wrapper = (props) => {
828
- var _a, _b;
863
+ var _a2, _b;
829
864
  const {
830
865
  dataSources,
831
866
  loading,
@@ -834,7 +869,7 @@ var withPlaceholder = (Visualization, useIconPlaceholder = shouldShowIconPlaceho
834
869
  width = SplunkVisualization_default.defaults.width
835
870
  } = props;
836
871
  const showPlaceholder = useIconPlaceholder(dataSources, loading, options);
837
- const icon = (_a = config3.placeholderIcon) != null ? _a : config3.icon;
872
+ const icon = (_a2 = config3.placeholderIcon) != null ? _a2 : config3.icon;
838
873
  const iconColor = variables_default.contentColorActive(props);
839
874
  const bgColorFromTheme = (0, colorUtils_exports.isColor)(options == null ? void 0 : options.backgroundColor) ? options == null ? void 0 : options.backgroundColor : (_b = themes3 == null ? void 0 : themes3.defaultBackgroundColor) == null ? void 0 : _b.call(themes3, props);
840
875
  if (config3.supports.includes("placeholder" /* PLACEHOLDER */) && showPlaceholder) {
@@ -890,7 +925,7 @@ var largestTriangleThreeBuckets = (data, threshold, preferredDownsampleIndices)
890
925
  let avgY = 0;
891
926
  let avgRangeStart = Math.floor((i + 1) * every) + 1;
892
927
  let avgRangeEnd = Math.floor((i + 2) * every) + 1;
893
- avgRangeEnd = avgRangeEnd < dataLength ? avgRangeEnd : dataLength;
928
+ avgRangeEnd = Math.min(avgRangeEnd, dataLength);
894
929
  const avgRangeLength = avgRangeEnd - avgRangeStart;
895
930
  for (; avgRangeStart < avgRangeEnd; avgRangeStart++) {
896
931
  avgX += Number(data[avgRangeStart][0]);
@@ -925,9 +960,9 @@ var largestTriangleThreeBuckets = (data, threshold, preferredDownsampleIndices)
925
960
  };
926
961
  var strictlyCoerceYColumn = (column, options) => {
927
962
  const isNullCoercionEnabled = options.nullValueDisplay === "zero";
928
- const canLooselyCoerceSomeValues = column.findIndex(
963
+ const canLooselyCoerceSomeValues = column.some(
929
964
  (value) => (0, numberUtils_exports.startsWithNumber)(`${value}`) || isNullCoercionEnabled && value === null
930
- ) >= 0;
965
+ );
931
966
  const coercedColumn = [];
932
967
  const canDownsampleColumn = !column.some((value) => {
933
968
  const coercedValue = Number(value);
@@ -946,7 +981,7 @@ var strictlyCoerceYColumn = (column, options) => {
946
981
  };
947
982
  var strictlyCoerceXColumn = (column, fieldType) => {
948
983
  if (fieldType === "number") {
949
- const coercedXColumn = column.map((xValue) => Number(xValue));
984
+ const coercedXColumn = column.map(Number);
950
985
  if (isColumnStrictlyIncreasing(coercedXColumn, fieldType)) {
951
986
  return coercedXColumn;
952
987
  }
@@ -959,8 +994,8 @@ var strictlyCoerceXColumn = (column, fieldType) => {
959
994
  return [];
960
995
  };
961
996
  var isDownsamplingEnabledForViz = ({ vizConfig }) => {
962
- var _a;
963
- return (_a = vizConfig.supports) == null ? void 0 : _a.includes("downsampling" /* DOWNSAMPLING */);
997
+ var _a2;
998
+ return (_a2 = vizConfig.supports) == null ? void 0 : _a2.includes("downsampling" /* DOWNSAMPLING */);
964
999
  };
965
1000
  var isColumnStrictlyIncreasing = (column, fieldType) => {
966
1001
  return column.every((value, index) => {
@@ -984,9 +1019,9 @@ var tryToCoerceAllDisplayedFields = (ds, xField, yFields, fieldTypes, options) =
984
1019
  let xColumn = [];
985
1020
  const yColumns = [];
986
1021
  const canDownsample = !ds.data.fields.some((field, index) => {
987
- var _a;
1022
+ var _a2;
988
1023
  const fieldName = getFieldName(field);
989
- const fieldType = (_a = fieldTypes[index]) != null ? _a : "unknown";
1024
+ const fieldType = (_a2 = fieldTypes[index]) != null ? _a2 : "unknown";
990
1025
  const column = ds.data.columns[index];
991
1026
  let hasDisplayedColumnThatCantBeDownsampled = false;
992
1027
  if (fieldName === xField) {
@@ -1028,9 +1063,9 @@ var pickIndicesFromDataSource = (ds, indices) => {
1028
1063
  });
1029
1064
  };
1030
1065
  var downsampleDataSources = ({ dataSources, threshold, options }) => {
1031
- var _a, _b, _c;
1066
+ var _a2, _b, _c;
1032
1067
  const primaryDS = dataSources == null ? void 0 : dataSources.primary;
1033
- const numPoints = (_c = (_b = (_a = primaryDS == null ? void 0 : primaryDS.data) == null ? void 0 : _a.columns[0]) == null ? void 0 : _b.length) != null ? _c : 0;
1068
+ const numPoints = (_c = (_b = (_a2 = primaryDS == null ? void 0 : primaryDS.data) == null ? void 0 : _a2.columns[0]) == null ? void 0 : _b.length) != null ? _c : 0;
1034
1069
  if (Number.isNaN(threshold) || numPoints <= threshold || threshold < 2) {
1035
1070
  return dataSources;
1036
1071
  }
@@ -1091,14 +1126,14 @@ var useGetXAndYFields = ({
1091
1126
  dataSources
1092
1127
  }) => {
1093
1128
  const { dataSourcesWithOnlyOnePoint, dataFrameWithOnlyOnePoint } = (0, react_exports.useMemo)(() => {
1094
- var _a, _b, _c;
1129
+ var _a2, _b, _c;
1095
1130
  if (!shouldEvaluateDSL) {
1096
1131
  return {
1097
1132
  dataSourcesWithOnlyOnePoint: null,
1098
1133
  dataFrameWithOnlyOnePoint: null
1099
1134
  };
1100
1135
  }
1101
- if (!((_c = (_b = (_a = dataSources == null ? void 0 : dataSources.primary) == null ? void 0 : _a.data) == null ? void 0 : _b.columns) == null ? void 0 : _c.length)) {
1136
+ if (!((_c = (_b = (_a2 = dataSources == null ? void 0 : dataSources.primary) == null ? void 0 : _a2.data) == null ? void 0 : _b.columns) == null ? void 0 : _c.length)) {
1102
1137
  return {
1103
1138
  dataSourcesWithOnlyOnePoint: null,
1104
1139
  dataFrameWithOnlyOnePoint: null
@@ -1251,10 +1286,10 @@ var FeatureFlags_default = "default" in defaultImport27 ? defaultImport27.defaul
1251
1286
 
1252
1287
  // src/common/utils/featureFlagUtils.ts
1253
1288
  var getFeatureFlag = (context, flagName) => {
1254
- if (context && Object.keys(context).find((key) => key === flagName)) {
1289
+ if (context && Object.keys(context).includes(flagName)) {
1255
1290
  return context[flagName];
1256
1291
  }
1257
- if (Object.keys(FeatureFlags_default).find((key) => key === flagName)) {
1292
+ if (Object.keys(FeatureFlags_default).includes(flagName)) {
1258
1293
  return FeatureFlags_default[flagName];
1259
1294
  }
1260
1295
  return false;
@@ -1360,16 +1395,16 @@ var triangleEventAnnotationRenderer = ({
1360
1395
  var shouldEnableSearchZoom = (eventHandlers = [], xField = "") => {
1361
1396
  const rangeSelectEventHandler = eventHandlers.find(
1362
1397
  (eventHandler) => {
1363
- var _a;
1364
- return (_a = eventHandler.options.events) == null ? void 0 : _a.includes("range.select");
1398
+ var _a2;
1399
+ return (_a2 = eventHandler.options.events) == null ? void 0 : _a2.includes("range.select");
1365
1400
  }
1366
1401
  );
1367
1402
  const xAxisIsTime = xField === "_time";
1368
1403
  return !!rangeSelectEventHandler && xAxisIsTime;
1369
1404
  };
1370
- var canvasSupportedTimeSeriesCharts = ["splunk.line", "splunk.area"];
1405
+ var canvasSupportedTimeSeriesCharts = /* @__PURE__ */ new Set(["splunk.line", "splunk.area"]);
1371
1406
  var isTimeSeriesCanvasRenderSupported = (vizConfigKey) => {
1372
- return canvasSupportedTimeSeriesCharts.includes(vizConfigKey);
1407
+ return canvasSupportedTimeSeriesCharts.has(vizConfigKey);
1373
1408
  };
1374
1409
  var filterChartDataFromInternalFields = (chartData) => {
1375
1410
  const { fields, columns } = chartData;
@@ -1385,7 +1420,7 @@ var filterChartDataFromInternalFields = (chartData) => {
1385
1420
  return { fields: filteredFields, columns: filteredColumns };
1386
1421
  };
1387
1422
  var convert2DArrayToNumbers = (arr) => {
1388
- return arr.map((subArray) => subArray.map((element) => parseFloat(element)));
1423
+ return arr.map((subArray) => subArray.map((element) => Number.parseFloat(element)));
1389
1424
  };
1390
1425
  var parseAxisValue = (val) => {
1391
1426
  if (val === void 0 || val === null || val === "auto" || val === "") {
@@ -1423,6 +1458,7 @@ var getLegend = (props) => {
1423
1458
  return (0, visualization_canvas_exports.TopLegendFactory)(__spreadValues({
1424
1459
  wrap: true
1425
1460
  }, commonLegendProps));
1461
+ // Note: By default, use right legend
1426
1462
  default:
1427
1463
  return (0, visualization_canvas_exports.SideLegendFactory)(__spreadValues({}, commonLegendProps));
1428
1464
  }
@@ -1534,7 +1570,7 @@ var getY2Scale = (field, y2fields, overlayFields) => {
1534
1570
  return assignToY2 ? "y2" : "y";
1535
1571
  };
1536
1572
  var getSeriesOverrides = (opts) => {
1537
- var _a;
1573
+ var _a2;
1538
1574
  const {
1539
1575
  yfields,
1540
1576
  y2fields,
@@ -1555,20 +1591,20 @@ var getSeriesOverrides = (opts) => {
1555
1591
  let spanGaps;
1556
1592
  if (nullValueMode === "gaps") {
1557
1593
  spanGaps = false;
1558
- } else if (nullValueMode != null) {
1559
- spanGaps = true;
1560
- } else {
1594
+ } else if (nullValueMode == null) {
1561
1595
  spanGaps = void 0;
1596
+ } else {
1597
+ spanGaps = true;
1562
1598
  }
1563
1599
  const replaceNullsWithZero = nullValueMode === "zero" ? true : void 0;
1564
1600
  const isAreaChart = type === "area";
1565
1601
  const isStacked = isAreaChart && (stackMode === "stacked" || stackMode === "stacked100");
1566
1602
  const areaFields = isAreaChart ? yfields.filter((f) => !(overlayFields == null ? void 0 : overlayFields.includes(f))) : yfields;
1567
- const overlayFieldsInOrder = (_a = overlayFields == null ? void 0 : overlayFields.filter((f) => yfields.includes(f))) != null ? _a : [];
1603
+ const overlayFieldsInOrder = (_a2 = overlayFields == null ? void 0 : overlayFields.filter((f) => yfields.includes(f))) != null ? _a2 : [];
1568
1604
  const orderedFields = isAreaChart ? [...areaFields, ...overlayFieldsInOrder] : yfields;
1569
1605
  orderedFields.forEach((field) => {
1570
- var _a2;
1571
- const isOverlay = (_a2 = overlayFields == null ? void 0 : overlayFields.includes(field)) != null ? _a2 : false;
1606
+ var _a3;
1607
+ const isOverlay = (_a3 = overlayFields == null ? void 0 : overlayFields.includes(field)) != null ? _a3 : false;
1572
1608
  const isPercent = isAreaChart && stackMode === "stacked100" && !isOverlay;
1573
1609
  const shouldHideAreaOutline = isAreaChart && showLines === false && !isOverlay;
1574
1610
  seriesConfig[field] = {
@@ -1761,11 +1797,11 @@ var handleLegendClick = (chartEvent, onClick, trellisKey, trellisSplitBy) => {
1761
1797
  }
1762
1798
  };
1763
1799
  var handleRangeSelection = (rangeEvent, onSelect, chartData, trellisKey, trellisSplitBy) => {
1764
- var _a;
1800
+ var _a2;
1765
1801
  if (!rangeEvent) {
1766
1802
  return;
1767
1803
  }
1768
- const xData = ((_a = chartData == null ? void 0 : chartData.columns) == null ? void 0 : _a[0]) || [];
1804
+ const xData = ((_a2 = chartData == null ? void 0 : chartData.columns) == null ? void 0 : _a2[0]) || [];
1769
1805
  const { startXIndex, endXIndex } = findRangeIndices(xData, rangeEvent.start, rangeEvent.end);
1770
1806
  const payload = {
1771
1807
  startXIndex,
@@ -1783,8 +1819,8 @@ var handleRangeSelection = (rangeEvent, onSelect, chartData, trellisKey, trellis
1783
1819
  }
1784
1820
  };
1785
1821
  var handleRangeZoom = (rangeEvent, onSelect, chartData, trellisKey, trellisSplitBy) => {
1786
- var _a;
1787
- const xData = ((_a = chartData == null ? void 0 : chartData.columns) == null ? void 0 : _a[0]) || [];
1822
+ var _a2;
1823
+ const xData = ((_a2 = chartData == null ? void 0 : chartData.columns) == null ? void 0 : _a2[0]) || [];
1788
1824
  const { startXIndex, endXIndex } = findRangeIndices(xData, rangeEvent.start, rangeEvent.end);
1789
1825
  const payload = {
1790
1826
  startXIndex,
@@ -1844,7 +1880,7 @@ var getYAxisTitles = ({
1844
1880
  };
1845
1881
  var TimeSeriesChartWrapper = (props) => {
1846
1882
  var _b, _c, _d;
1847
- const _a = props, {
1883
+ const _a2 = props, {
1848
1884
  width,
1849
1885
  height,
1850
1886
  chartData,
@@ -1870,7 +1906,7 @@ var TimeSeriesChartWrapper = (props) => {
1870
1906
  y2AxisLineVisibility,
1871
1907
  showYAxisWithZero: showYAxisWithZeroFromProps,
1872
1908
  showY2AxisWithZero: showY2AxisWithZeroFromProps
1873
- } = _a, otherOptions = __objRest(_a, [
1909
+ } = _a2, otherOptions = __objRest(_a2, [
1874
1910
  "width",
1875
1911
  "height",
1876
1912
  "chartData",
@@ -1989,11 +2025,11 @@ var TimeSeriesChartWrapper = (props) => {
1989
2025
  y2AxisMajorUnitFromSimpleXML,
1990
2026
  y2AxisMajorTickInterval
1991
2027
  );
1992
- const xAxisMajorTickSizeNum = xAxisMajorTickSize != null ? Number(xAxisMajorTickSize) : void 0;
1993
- const yAxisMajorTickSizeNum = yAxisMajorTickSize != null ? Number(yAxisMajorTickSize) : void 0;
1994
- const y2AxisMajorTickSizeNum = y2AxisMajorTickSize != null ? Number(y2AxisMajorTickSize) : void 0;
1995
- const yAxisMinorTickSizeNum = yAxisMinorTickSize != null ? Number(yAxisMinorTickSize) : void 0;
1996
- const y2AxisMinorTickSizeNum = y2AxisMinorTickSize != null ? Number(y2AxisMinorTickSize) : void 0;
2028
+ const xAxisMajorTickSizeNum = xAxisMajorTickSize == null ? void 0 : Number(xAxisMajorTickSize);
2029
+ const yAxisMajorTickSizeNum = yAxisMajorTickSize == null ? void 0 : Number(yAxisMajorTickSize);
2030
+ const y2AxisMajorTickSizeNum = y2AxisMajorTickSize == null ? void 0 : Number(y2AxisMajorTickSize);
2031
+ const yAxisMinorTickSizeNum = yAxisMinorTickSize == null ? void 0 : Number(yAxisMinorTickSize);
2032
+ const y2AxisMinorTickSizeNum = y2AxisMinorTickSize == null ? void 0 : Number(y2AxisMinorTickSize);
1997
2033
  const areaOpacityForCanvas = getAreaOpacityForCanvas(areaOpacity);
1998
2034
  const seriesColors = seriesColorsStr ? JSON.parse(seriesColorsStr) : void 0;
1999
2035
  const seriesColorsByField = fieldColors ? JSON.parse(fieldColors) : void 0;
@@ -2405,6 +2441,76 @@ var buildEventCallbackProps = (supportedEvents, evaluatedOptionsToUse, onEventTr
2405
2441
  });
2406
2442
  return result;
2407
2443
  };
2444
+ var buildAllEventCallbackProps = (events, evaluatedOptionsToUse, onEventTrigger, { supportsEvents, hasEventHandlers, mode }) => {
2445
+ if (!supportsEvents) return {};
2446
+ const defaultEvents = {};
2447
+ const userEvents = {};
2448
+ Object.entries(events || {}).forEach(([eventKey, eventConfig]) => {
2449
+ (eventConfig.source === "default" ? defaultEvents : userEvents)[eventKey] = eventConfig;
2450
+ });
2451
+ const userProps = hasEventHandlers && mode === "view" ? buildEventCallbackProps(userEvents, evaluatedOptionsToUse, onEventTrigger) : {};
2452
+ return __spreadValues(__spreadValues({}, userProps), buildEventCallbackProps(defaultEvents, evaluatedOptionsToUse, onEventTrigger));
2453
+ };
2454
+ var applyContextTimezone = (localeContext) => {
2455
+ if (localeContext.serializedTimezone && !moment_default.getDefaultSplunkTimezone()) {
2456
+ moment_default.setDefaultSplunkTimezone(localeContext.serializedTimezone);
2457
+ }
2458
+ };
2459
+ var getAsyncOptionsEvaluationParams = ({
2460
+ visualizationID,
2461
+ props,
2462
+ optionsToEvaluate,
2463
+ downsampledDataSources,
2464
+ vizConfig,
2465
+ bypassCloneDeepOptionScope,
2466
+ lazyLoadingDataFrame
2467
+ }) => {
2468
+ return {
2469
+ visualizationID,
2470
+ props,
2471
+ options: __spreadValues({}, optionsToEvaluate),
2472
+ dataSources: downsampledDataSources,
2473
+ theme: vizConfig.themes,
2474
+ bypassCloneDeepOptionScope,
2475
+ lazyLoadingDataFrame
2476
+ };
2477
+ };
2478
+ var evaluateOptionsSync = ({
2479
+ optionsToEvaluate,
2480
+ downsampledDataSources,
2481
+ dataSourcesInState,
2482
+ dataFramesInState,
2483
+ setDataSourcesInState,
2484
+ setDataFramesInState,
2485
+ computeDataFrames,
2486
+ featureFlagContext,
2487
+ themeFunc
2488
+ }) => {
2489
+ let dataFrames = dataFramesInState;
2490
+ if (downsampledDataSources !== dataSourcesInState) {
2491
+ setDataSourcesInState(downsampledDataSources);
2492
+ dataFrames = Options_exports.Options.dataFrameFromDataSource(
2493
+ downsampledDataSources,
2494
+ getFeatureFlag(featureFlagContext, "visualizations_lazyLoadingDataFrame")
2495
+ );
2496
+ setDataFramesInState(dataFrames);
2497
+ }
2498
+ let mergedFrames = dataFrames;
2499
+ if (computeDataFrames && dataFrames) {
2500
+ const derivedFrames = computeDataFrames({
2501
+ dataSources: downsampledDataSources,
2502
+ options: optionsToEvaluate.options
2503
+ });
2504
+ mergedFrames = __spreadValues(__spreadValues({}, dataFrames), derivedFrames);
2505
+ }
2506
+ return Options_exports.Options.evaluate(
2507
+ optionsToEvaluate,
2508
+ downsampledDataSources,
2509
+ themeFunc,
2510
+ mergedFrames,
2511
+ getFeatureFlag(featureFlagContext, "visualizations_bypassCloneDeepOptionScope")
2512
+ );
2513
+ };
2408
2514
  var withDashboardViz = (opts) => {
2409
2515
  const {
2410
2516
  ReactViz,
@@ -2420,7 +2526,7 @@ var withDashboardViz = (opts) => {
2420
2526
  const SanitizedReactViz = (0, SanitizeProps_exports.withSanitizedProps)(ReactViz);
2421
2527
  const defaultOptions = (0, JSONSchemaUtils_exports.pickFieldFromJSONSchema)(vizConfig.optionsSchema, "default");
2422
2528
  const DashboardViz = (props) => {
2423
- var _a;
2529
+ var _a2;
2424
2530
  const {
2425
2531
  mode = "view",
2426
2532
  hasEventHandlers,
@@ -2436,14 +2542,10 @@ var withDashboardViz = (opts) => {
2436
2542
  onRequestParamsChange = lodash_exports.noop
2437
2543
  } = props;
2438
2544
  const localeContext = react_exports.useContext(TimezoneContext_default);
2439
- if (localeContext.serializedTimezone) {
2440
- if (!moment_default.getDefaultSplunkTimezone()) {
2441
- moment_default.setDefaultSplunkTimezone(localeContext.serializedTimezone);
2442
- }
2443
- }
2545
+ applyContextTimezone(localeContext);
2444
2546
  const themeFunc = (themeVar) => {
2445
- var _a2, _b;
2446
- return (_b = (_a2 = vizConfig.themes)[themeVar]) == null ? void 0 : _b.call(_a2, props);
2547
+ var _a3, _b;
2548
+ return (_b = (_a3 = vizConfig.themes)[themeVar]) == null ? void 0 : _b.call(_a3, props);
2447
2549
  };
2448
2550
  const {
2449
2551
  family: currentThemeFamily,
@@ -2463,16 +2565,21 @@ var withDashboardViz = (opts) => {
2463
2565
  featureFlagContext == null ? void 0 : featureFlagContext.visualizations_enableDownsampling
2464
2566
  );
2465
2567
  const isTrellisFeatureFlagOn = Boolean(featureFlagContext == null ? void 0 : featureFlagContext.visualizations_enableTrellis);
2466
- const isTrellisOn = isTrellisFeatureFlagOn && ((_a = vizConfig == null ? void 0 : vizConfig.supports) == null ? void 0 : _a.includes("trellis" /* TRELLIS */)) && (options == null ? void 0 : options.splitByLayout) === "trellis" /* TRELLIS */;
2568
+ const isTrellisOn = isTrellisFeatureFlagOn && ((_a2 = vizConfig == null ? void 0 : vizConfig.supports) == null ? void 0 : _a2.includes("trellis" /* TRELLIS */)) && (options == null ? void 0 : options.splitByLayout) === "trellis" /* TRELLIS */;
2467
2569
  const isAcceleratedRenderFeatureFlagOn = Boolean(
2468
2570
  featureFlagContext == null ? void 0 : featureFlagContext.visualizations_enableAcceleratedRender
2469
2571
  );
2470
2572
  const isAcceleratedRenderOn = isAcceleratedRenderFeatureFlagOn && isTimeSeriesCanvasRenderSupported(vizConfig.key) && (options == null ? void 0 : options.acceleratedRender) === true;
2471
- const isMounted = react_exports.useRef(true);
2573
+ const bypassCloneDeepOptionScope = Boolean(
2574
+ getFeatureFlag(featureFlagContext, "visualizations_bypassCloneDeepOptionScope")
2575
+ );
2576
+ const lazyLoadingDataFrame = Boolean(
2577
+ getFeatureFlag(featureFlagContext, "visualizations_lazyLoadingDataFrame")
2578
+ );
2472
2579
  const optionsToEvaluate = react_exports.useMemo(() => {
2473
- var _a2;
2580
+ var _a3;
2474
2581
  const legendDisplay = turnOffLegendDisplayWhenTrellisIsOn(isTrellisOn, options);
2475
- const computedOptions = (_a2 = computeVizPropsBeforeEval(options)) != null ? _a2 : {};
2582
+ const computedOptions = (_a3 = computeVizPropsBeforeEval(options)) != null ? _a3 : {};
2476
2583
  return {
2477
2584
  context: (0, lodash_exports.defaultsDeep)({}, context, vizConfig.defaultContext),
2478
2585
  options: (0, hocUtils_exports.deepMergeWithArrayPrimitiveOverrides)(
@@ -2507,63 +2614,74 @@ var withDashboardViz = (opts) => {
2507
2614
  threshold,
2508
2615
  isDownsamplingEnabled
2509
2616
  });
2510
- evaluatedOptions = useDeepMemo(() => {
2617
+ const asyncOptionsEvaluationParams = useDeepMemo(
2618
+ () => getAsyncOptionsEvaluationParams({
2619
+ visualizationID,
2620
+ props,
2621
+ optionsToEvaluate,
2622
+ downsampledDataSources,
2623
+ vizConfig,
2624
+ bypassCloneDeepOptionScope,
2625
+ lazyLoadingDataFrame
2626
+ }),
2627
+ [
2628
+ visualizationID,
2629
+ optionsToEvaluate,
2630
+ downsampledDataSources,
2631
+ vizConfig,
2632
+ bypassCloneDeepOptionScope,
2633
+ lazyLoadingDataFrame,
2634
+ currentThemeFamily,
2635
+ currentThemeColorScheme,
2636
+ currentThemeDensity,
2637
+ localeContext.serializedTimezone
2638
+ ]
2639
+ );
2640
+ react_exports.useEffect(() => {
2641
+ if (!useAsyncEvaluatedOptions) {
2642
+ return void 0;
2643
+ }
2644
+ let ownsEvaluation = true;
2511
2645
  try {
2512
- if (useAsyncEvaluatedOptions) {
2513
- const asyncDynamicOptionsEvaluatorParams = {
2514
- visualizationID,
2515
- props,
2516
- options: optionsToEvaluate,
2517
- dataSources: downsampledDataSources,
2518
- theme: vizConfig.themes,
2519
- bypassCloneDeepOptionScope: Boolean(
2520
- getFeatureFlag(featureFlagContext, "visualizations_bypassCloneDeepOptionScope")
2521
- ),
2522
- lazyLoadingDataFrame: Boolean(
2523
- getFeatureFlag(featureFlagContext, "visualizations_lazyLoadingDataFrame")
2524
- )
2525
- };
2526
- async_dynamic_options_evaluator_default.evaluate(asyncDynamicOptionsEvaluatorParams).then((results) => {
2646
+ async_dynamic_options_evaluator_default.evaluate(asyncOptionsEvaluationParams).then((results) => {
2647
+ if (ownsEvaluation) {
2527
2648
  setEvaluatedOptionsAsync(results.results);
2528
- }).catch(() => {
2529
- if (isMounted.current) {
2530
- setUseAsyncEvaluatedOptions(false);
2531
- }
2532
- });
2533
- } else {
2534
- let dataFrames = dataFramesInState;
2535
- if (downsampledDataSources !== dataSourcesInState) {
2536
- setDataSourcesInState(downsampledDataSources);
2537
- dataFrames = Options_exports.Options.dataFrameFromDataSource(
2538
- downsampledDataSources,
2539
- getFeatureFlag(featureFlagContext, "visualizations_lazyLoadingDataFrame")
2540
- );
2541
- setDataFramesInState(dataFrames);
2542
2649
  }
2543
- let mergedFrames = dataFrames;
2544
- if (computeDataFrames && dataFrames) {
2545
- const derivedFrames = computeDataFrames({
2546
- dataSources: downsampledDataSources,
2547
- options: optionsToEvaluate.options
2548
- });
2549
- mergedFrames = __spreadValues(__spreadValues({}, dataFrames), derivedFrames);
2650
+ }).catch(() => {
2651
+ if (ownsEvaluation) {
2652
+ setUseAsyncEvaluatedOptions(false);
2550
2653
  }
2551
- const result = Options_exports.Options.evaluate(
2552
- optionsToEvaluate,
2553
- downsampledDataSources,
2554
- themeFunc,
2555
- mergedFrames,
2556
- getFeatureFlag(featureFlagContext, "visualizations_bypassCloneDeepOptionScope")
2557
- );
2558
- return result;
2654
+ });
2655
+ } catch (e) {
2656
+ setUseAsyncEvaluatedOptions(false);
2657
+ }
2658
+ return () => {
2659
+ ownsEvaluation = false;
2660
+ async_dynamic_options_evaluator_default.reset(visualizationID);
2661
+ };
2662
+ }, [asyncOptionsEvaluationParams, useAsyncEvaluatedOptions, visualizationID]);
2663
+ evaluatedOptions = useDeepMemo(() => {
2664
+ try {
2665
+ if (useAsyncEvaluatedOptions) {
2666
+ return {};
2559
2667
  }
2668
+ return evaluateOptionsSync({
2669
+ optionsToEvaluate,
2670
+ downsampledDataSources,
2671
+ dataSourcesInState,
2672
+ dataFramesInState,
2673
+ setDataSourcesInState,
2674
+ setDataFramesInState,
2675
+ computeDataFrames,
2676
+ featureFlagContext,
2677
+ themeFunc
2678
+ });
2560
2679
  } catch (e) {
2561
2680
  if (e instanceof Error) {
2562
2681
  console.error(`unexpected error evaluating options: ${e.message}`);
2563
2682
  }
2564
2683
  return {};
2565
2684
  }
2566
- return {};
2567
2685
  }, [
2568
2686
  currentThemeFamily,
2569
2687
  currentThemeColorScheme,
@@ -2573,7 +2691,7 @@ var withDashboardViz = (opts) => {
2573
2691
  localeContext.serializedTimezone,
2574
2692
  useAsyncEvaluatedOptions
2575
2693
  ]);
2576
- const evaluatedOptionsToUse = !useAsyncEvaluatedOptions ? evaluatedOptions : evaluatedOptionsAsync;
2694
+ const evaluatedOptionsToUse = useAsyncEvaluatedOptions ? evaluatedOptionsAsync : evaluatedOptions;
2577
2695
  let dataSourceMetadata = {};
2578
2696
  const OptionKey = "paginateDataSourceKey";
2579
2697
  const optsKey = (0, lodash_exports.has)(evaluatedOptionsToUse, OptionKey) && evaluatedOptionsToUse[OptionKey];
@@ -2595,7 +2713,7 @@ var withDashboardViz = (opts) => {
2595
2713
  sortParams,
2596
2714
  paginatorParams
2597
2715
  };
2598
- if (vizConfig.supports.indexOf("page-and-sort" /* PAGE_AND_SORT */) === -1 && !(0, lodash_exports.has)(dataSources, paginateDataSourceKey)) {
2716
+ if (!vizConfig.supports.includes("page-and-sort" /* PAGE_AND_SORT */) && !(0, lodash_exports.has)(dataSources, paginateDataSourceKey)) {
2599
2717
  dataSourceMetadata = {};
2600
2718
  }
2601
2719
  const clonedEvaluatedOptions = __spreadValues({}, evaluatedOptionsToUse);
@@ -2605,14 +2723,6 @@ var withDashboardViz = (opts) => {
2605
2723
  react_exports.useEffect(() => {
2606
2724
  onComputedProps(clonedEvaluatedOptions);
2607
2725
  });
2608
- react_exports.useEffect(() => {
2609
- return () => {
2610
- if (useAsyncEvaluatedOptions) {
2611
- isMounted.current = false;
2612
- async_dynamic_options_evaluator_default.reset(visualizationID);
2613
- }
2614
- };
2615
- }, []);
2616
2726
  const { requiredProps = [], supports } = vizConfig;
2617
2727
  const missing = missingKeys(requiredProps, evaluatedOptionsToUse);
2618
2728
  if (missing.length > 0 && supports.includes("placeholder" /* PLACEHOLDER */) && vizConfig.key !== "splunk.singlevalue") {
@@ -2627,7 +2737,16 @@ var withDashboardViz = (opts) => {
2627
2737
  }
2628
2738
  );
2629
2739
  }
2630
- const eventCallbackProps = hasEventHandlers && mode === "view" && vizConfig.supports.includes("events" /* EVENTS */) ? buildEventCallbackProps(vizConfig.events, evaluatedOptionsToUse, onEventTrigger) : {};
2740
+ const eventCallbackProps = buildAllEventCallbackProps(
2741
+ vizConfig.events,
2742
+ evaluatedOptionsToUse,
2743
+ onEventTrigger,
2744
+ {
2745
+ supportsEvents: vizConfig.supports.includes("events" /* EVENTS */),
2746
+ hasEventHandlers,
2747
+ mode
2748
+ }
2749
+ );
2631
2750
  const computedVizProps = computeVizProps2(__spreadProps(__spreadValues(__spreadProps(__spreadValues(__spreadValues({}, props), evaluatedOptionsToUse), {
2632
2751
  // Align option transformation with the actual renderer selected below.
2633
2752
  // This prevents canvas-only option preservation from leaking into Highcharts mode.
@@ -2655,8 +2774,9 @@ var withDashboardViz = (opts) => {
2655
2774
  onEventTrigger: SplunkVisualization_default.defaults.onEventTrigger
2656
2775
  });
2657
2776
  DashboardViz.config = vizConfig;
2658
- return (0, styled_components_exports.withTheme)(
2659
- withPlaceholder_default(withEditModeCover_default(DashboardViz, disableEditModeCover), useIconPlaceholder)
2777
+ return Object.assign(
2778
+ (0, styled_components_exports.withTheme)(withPlaceholder_default(withEditModeCover_default(DashboardViz, disableEditModeCover), useIconPlaceholder)),
2779
+ { config: vizConfig }
2660
2780
  );
2661
2781
  };
2662
2782
  var withDashboardViz_default = withDashboardViz;
@@ -2670,14 +2790,23 @@ var defaultImport33 = __toESM(require("@splunk/dashboard-context"));
2670
2790
  __reExport(dashboard_context_exports, require("@splunk/dashboard-context"));
2671
2791
  var dashboard_context_default = "default" in defaultImport33 ? defaultImport33.default : defaultImport33;
2672
2792
 
2793
+ // esm-externals:slate
2794
+ var slate_exports = {};
2795
+ __export(slate_exports, {
2796
+ default: () => slate_default
2797
+ });
2798
+ var defaultImport34 = __toESM(require("slate"));
2799
+ __reExport(slate_exports, require("slate"));
2800
+ var slate_default = "default" in defaultImport34 ? defaultImport34.default : defaultImport34;
2801
+
2673
2802
  // esm-externals:slate-react
2674
2803
  var slate_react_exports = {};
2675
2804
  __export(slate_react_exports, {
2676
2805
  default: () => slate_react_default
2677
2806
  });
2678
- var defaultImport34 = __toESM(require("slate-react"));
2807
+ var defaultImport35 = __toESM(require("slate-react"));
2679
2808
  __reExport(slate_react_exports, require("slate-react"));
2680
- var slate_react_default = "default" in defaultImport34 ? defaultImport34.default : defaultImport34;
2809
+ var slate_react_default = "default" in defaultImport35 ? defaultImport35.default : defaultImport35;
2681
2810
 
2682
2811
  // src/RichText/PureRichText/activeInstance.ts
2683
2812
  var activeRichTextId = null;
@@ -2733,15 +2862,15 @@ function setMouseSelecting(value) {
2733
2862
  function isMouseSelecting() {
2734
2863
  return mouseSelecting;
2735
2864
  }
2736
-
2737
- // esm-externals:slate
2738
- var slate_exports = {};
2739
- __export(slate_exports, {
2740
- default: () => slate_default
2741
- });
2742
- var defaultImport35 = __toESM(require("slate"));
2743
- __reExport(slate_exports, require("slate"));
2744
- var slate_default = "default" in defaultImport35 ? defaultImport35.default : defaultImport35;
2865
+ var suppressNextEditClick = false;
2866
+ function setSuppressNextEditClick(value) {
2867
+ suppressNextEditClick = value;
2868
+ }
2869
+ function consumeSuppressNextEditClick() {
2870
+ const v = suppressNextEditClick;
2871
+ suppressNextEditClick = false;
2872
+ return v;
2873
+ }
2745
2874
 
2746
2875
  // src/RichText/PureRichText/types.ts
2747
2876
  var DEFAULT_TEXT_STYLES = {
@@ -2798,7 +2927,241 @@ var defaultImport36 = __toESM(require("dompurify"));
2798
2927
  __reExport(dompurify_exports, require("dompurify"));
2799
2928
  var dompurify_default = "default" in defaultImport36 ? defaultImport36.default : defaultImport36;
2800
2929
 
2930
+ // src/RichText/PureRichText/hooks/useTokenMap.ts
2931
+ var NAME_CHARS = String.raw` \w.-`;
2932
+ var NAMESPACE_PREFIX = `(?:[${NAME_CHARS}]+:)?`;
2933
+ var NAME = String.raw`(?:(?=[\w.-])[${NAME_CHARS}]*[\w.-])`;
2934
+ var FILTERS = String.raw`(?:\|[a-zA-Z]+)*`;
2935
+ var TOKEN_CONTENT = `${NAMESPACE_PREFIX}${NAME}${FILTERS}`;
2936
+ var TOKEN_PATTERN = new RegExp(String.raw`\$(${TOKEN_CONTENT})\$`, "g");
2937
+ var TOKEN_OR_ESCAPE_PATTERN = new RegExp(
2938
+ String.raw`\$\$|\$(${TOKEN_CONTENT})\$(?=\$${TOKEN_CONTENT}\$|\$\$|[^$]|$)`,
2939
+ "g"
2940
+ );
2941
+ function toValueString(value) {
2942
+ return value === null ? null : String(value);
2943
+ }
2944
+ function normalizeTokenMetadata(metadata, resolvedContent) {
2945
+ const nameToValue = /* @__PURE__ */ new Map();
2946
+ if (!metadata || metadata.length === 0) {
2947
+ return { nameToValue, rawContent: resolvedContent, reconciled: true };
2948
+ }
2949
+ const sorted = [...metadata].sort((a, b) => a.start - b.start);
2950
+ for (const { match, value } of sorted) {
2951
+ const strValue = toValueString(value);
2952
+ if (match !== "$$" && strValue !== null && strValue !== "") {
2953
+ nameToValue.set(match.slice(1, -1), strValue);
2954
+ }
2955
+ }
2956
+ let raw = "";
2957
+ let rawCursor = 0;
2958
+ let resolvedCursor = 0;
2959
+ for (const entry of sorted) {
2960
+ const { match, value, start, end } = entry;
2961
+ const strValue = toValueString(value);
2962
+ const literalLength = start - rawCursor;
2963
+ const expected = strValue != null ? strValue : match;
2964
+ const valuePos = resolvedCursor + literalLength;
2965
+ if (literalLength < 0 || resolvedContent.slice(valuePos, valuePos + expected.length) !== expected) {
2966
+ return { nameToValue, rawContent: resolvedContent, reconciled: false };
2967
+ }
2968
+ raw += resolvedContent.slice(resolvedCursor, valuePos);
2969
+ raw += match;
2970
+ rawCursor = end;
2971
+ resolvedCursor = valuePos + expected.length;
2972
+ }
2973
+ raw += resolvedContent.slice(resolvedCursor);
2974
+ return { nameToValue, rawContent: raw, reconciled: true };
2975
+ }
2976
+ function splitByTokenWildcards(rawContent) {
2977
+ const re = new RegExp(TOKEN_OR_ESCAPE_PATTERN.source, "g");
2978
+ const literals = [];
2979
+ let hasWildcard = false;
2980
+ let buf = "";
2981
+ let lastIndex = 0;
2982
+ let match = re.exec(rawContent);
2983
+ while (match !== null) {
2984
+ buf += rawContent.slice(lastIndex, match.index);
2985
+ if (match[1] === void 0) {
2986
+ buf += "$";
2987
+ } else {
2988
+ literals.push(buf);
2989
+ buf = "";
2990
+ hasWildcard = true;
2991
+ }
2992
+ lastIndex = match.index + match[0].length;
2993
+ match = re.exec(rawContent);
2994
+ }
2995
+ buf += rawContent.slice(lastIndex);
2996
+ literals.push(buf);
2997
+ return { literals, hasWildcard };
2998
+ }
2999
+ function isValueOnlyChange(rawContent, resolvedContent) {
3000
+ var _a2;
3001
+ const { literals, hasWildcard } = splitByTokenWildcards(rawContent);
3002
+ if (!hasWildcard) return resolvedContent === literals[0];
3003
+ const prefix = literals[0];
3004
+ const suffix = (_a2 = literals.at(-1)) != null ? _a2 : "";
3005
+ if (!resolvedContent.startsWith(prefix)) return false;
3006
+ if (!resolvedContent.endsWith(suffix)) return false;
3007
+ let cursor = prefix.length;
3008
+ const end = resolvedContent.length - suffix.length;
3009
+ if (cursor > end) return false;
3010
+ for (let i = 1; i < literals.length - 1; i += 1) {
3011
+ const chunk = literals[i];
3012
+ const idx = resolvedContent.indexOf(chunk, cursor);
3013
+ if (idx === -1 || idx + chunk.length > end) return false;
3014
+ cursor = idx + chunk.length;
3015
+ }
3016
+ return true;
3017
+ }
3018
+ function wrapTreeNodes(nodes, splitLeaf) {
3019
+ const processNode = (node) => {
3020
+ if (slate_exports.Text.isText(node)) {
3021
+ return splitLeaf(node);
3022
+ }
3023
+ if (slate_exports.Element.isElement(node)) {
3024
+ return [__spreadProps(__spreadValues({}, node), { children: node.children.flatMap(processNode) })];
3025
+ }
3026
+ return [node];
3027
+ };
3028
+ return nodes.flatMap(processNode);
3029
+ }
3030
+ function wrapRawTokensInTree(nodes, nameToValue) {
3031
+ return wrapTreeNodes(nodes, (node) => splitTextByRawTokens(node, nameToValue));
3032
+ }
3033
+ function splitTextByRawTokens(textNode, nameToValue) {
3034
+ const _a2 = textNode, {
3035
+ text,
3036
+ tokenName: existingTokenName,
3037
+ isEscapedDollar,
3038
+ isRawToken: existingIsRawToken
3039
+ } = _a2, rest = __objRest(_a2, [
3040
+ "text",
3041
+ "tokenName",
3042
+ "isEscapedDollar",
3043
+ "isRawToken"
3044
+ ]);
3045
+ const marks = __spreadValues({}, rest);
3046
+ if (!text) return [textNode];
3047
+ if (isEscapedDollar) {
3048
+ if (!/^\$+$/.test(text)) return [textNode];
3049
+ const escapeCount = existingIsRawToken ? text.length / 2 : text.length;
3050
+ return [
3051
+ __spreadProps(__spreadValues({}, textNode), {
3052
+ text: displayTextForEscapedDollar(nameToValue).repeat(escapeCount),
3053
+ isRawToken: !nameToValue
3054
+ })
3055
+ ];
3056
+ }
3057
+ if (existingTokenName) {
3058
+ const display = displayTextForToken(existingTokenName, nameToValue);
3059
+ return [__spreadProps(__spreadValues({}, textNode), { text: display, isRawToken: !nameToValue })];
3060
+ }
3061
+ const re = new RegExp(TOKEN_OR_ESCAPE_PATTERN.source, "g");
3062
+ const result = [];
3063
+ let lastIndex = 0;
3064
+ let match = re.exec(text);
3065
+ while (match !== null) {
3066
+ const startIdx = match.index;
3067
+ const fullMatch = match[0];
3068
+ const name = match[1];
3069
+ if (startIdx > lastIndex) {
3070
+ result.push(__spreadValues({ text: text.slice(lastIndex, startIdx) }, marks));
3071
+ }
3072
+ if (name === void 0) {
3073
+ result.push(__spreadProps(__spreadValues({
3074
+ text: displayTextForEscapedDollar(nameToValue)
3075
+ }, marks), {
3076
+ isEscapedDollar: true,
3077
+ isRawToken: !nameToValue
3078
+ }));
3079
+ } else {
3080
+ result.push(__spreadProps(__spreadValues({
3081
+ text: displayTextForToken(name, nameToValue)
3082
+ }, marks), {
3083
+ tokenName: name,
3084
+ isRawToken: !nameToValue
3085
+ }));
3086
+ }
3087
+ lastIndex = startIdx + fullMatch.length;
3088
+ match = re.exec(text);
3089
+ }
3090
+ if (result.length === 0) return [textNode];
3091
+ if (lastIndex < text.length) {
3092
+ result.push(__spreadValues({ text: text.slice(lastIndex) }, marks));
3093
+ }
3094
+ return result;
3095
+ }
3096
+ function displayTextForToken(name, nameToValue) {
3097
+ const value = nameToValue == null ? void 0 : nameToValue.get(name);
3098
+ return value !== void 0 && value !== "" ? value : `$${name}$`;
3099
+ }
3100
+ function displayTextForEscapedDollar(nameToValue) {
3101
+ return nameToValue ? "$" : "$$";
3102
+ }
3103
+ var EMPTY_MAP = /* @__PURE__ */ new Map();
3104
+ function useTokenMap(resolvedContent, richTextTokenMetadata) {
3105
+ var _a2, _b, _c, _d, _e;
3106
+ const contentMetadata = (_a2 = richTextTokenMetadata == null ? void 0 : richTextTokenMetadata.richTextContent) != null ? _a2 : null;
3107
+ const serialized = contentMetadata ? JSON.stringify(contentMetadata) : null;
3108
+ const resultRef = (0, react_exports.useRef)(null);
3109
+ const prevSerializedRef = (0, react_exports.useRef)(null);
3110
+ const prevResolvedRef = (0, react_exports.useRef)("");
3111
+ if (serialized !== prevSerializedRef.current || resolvedContent !== prevResolvedRef.current) {
3112
+ prevSerializedRef.current = serialized;
3113
+ prevResolvedRef.current = resolvedContent;
3114
+ if (contentMetadata) {
3115
+ const next = normalizeTokenMetadata(contentMetadata, resolvedContent);
3116
+ const canReuseStale = !next.reconciled && resultRef.current != null && isValueOnlyChange(resultRef.current.rawContent, resolvedContent);
3117
+ resultRef.current = canReuseStale ? __spreadProps(__spreadValues({}, next), { rawContent: resultRef.current.rawContent }) : next;
3118
+ } else {
3119
+ resultRef.current = null;
3120
+ }
3121
+ }
3122
+ const nameToValue = (_c = (_b = resultRef.current) == null ? void 0 : _b.nameToValue) != null ? _c : EMPTY_MAP;
3123
+ const rawContent = (_e = (_d = resultRef.current) == null ? void 0 : _d.rawContent) != null ? _e : null;
3124
+ return { nameToValue, rawContent };
3125
+ }
3126
+
2801
3127
  // src/RichText/PureRichText/utils/slateUtils.ts
3128
+ var sharedDomParser = new DOMParser();
3129
+ var ALLOWED_URI_SCHEMES = ["ftps?", "https?", "mailto", "tel", "callto", "sms", "cid", "xmpp", "file"];
3130
+ var ALLOWED_URI_REGEXP = new RegExp(
3131
+ String.raw`^(?:(?:${ALLOWED_URI_SCHEMES.join("|")}):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))`,
3132
+ "i"
3133
+ );
3134
+ function findInWidgetScroller(el) {
3135
+ var _a2;
3136
+ let node = (_a2 = el == null ? void 0 : el.parentElement) != null ? _a2 : null;
3137
+ while (node && node !== document.body && node !== document.documentElement) {
3138
+ const { overflowY } = globalThis.getComputedStyle(node);
3139
+ if ((overflowY === "auto" || overflowY === "scroll") && node.scrollHeight > node.clientHeight) {
3140
+ return node;
3141
+ }
3142
+ node = node.parentElement;
3143
+ }
3144
+ return null;
3145
+ }
3146
+ function editorContentOverflows(editableEl) {
3147
+ return findInWidgetScroller(editableEl) !== null;
3148
+ }
3149
+ function scrollCaretWithinEditor(editor, domRange) {
3150
+ if (isMouseSelecting()) return;
3151
+ const { selection } = editor;
3152
+ if (selection && !slate_exports.Range.isCollapsed(selection)) return;
3153
+ if (typeof domRange.getBoundingClientRect !== "function") return;
3154
+ const leafEl = domRange.startContainer.parentElement;
3155
+ const scroller = findInWidgetScroller(leafEl);
3156
+ if (!scroller) return;
3157
+ const caret = domRange.getBoundingClientRect();
3158
+ const box = scroller.getBoundingClientRect();
3159
+ if (caret.top < box.top) {
3160
+ scroller.scrollTop -= box.top - caret.top;
3161
+ } else if (caret.bottom > box.bottom) {
3162
+ scroller.scrollTop += caret.bottom - box.bottom;
3163
+ }
3164
+ }
2802
3165
  function safeSelectEnd(editor) {
2803
3166
  try {
2804
3167
  const end = slate_exports.Editor.end(editor, []);
@@ -2806,6 +3169,15 @@ function safeSelectEnd(editor) {
2806
3169
  } catch (e) {
2807
3170
  }
2808
3171
  }
3172
+ function focusSelectOutline(fromEl) {
3173
+ const selectOutline = fromEl == null ? void 0 : fromEl.closest('[data-test="select-outline"]');
3174
+ if (!selectOutline) return;
3175
+ if (!selectOutline.getAttribute("tabindex")) {
3176
+ selectOutline.setAttribute("tabindex", "-1");
3177
+ }
3178
+ selectOutline.style.outline = "none";
3179
+ selectOutline.focus({ preventScroll: true });
3180
+ }
2809
3181
  function safeDeselect(editor) {
2810
3182
  try {
2811
3183
  slate_exports.Transforms.deselect(editor);
@@ -2968,14 +3340,50 @@ function getActiveLink(editor) {
2968
3340
  function slateToPlainText(nodes) {
2969
3341
  return slate_exports.Node.string({ children: nodes });
2970
3342
  }
3343
+ function resolveUrlTokens(url, nameToValue) {
3344
+ if (!nameToValue || nameToValue.size === 0) return url;
3345
+ return url.replace(TOKEN_PATTERN, (match, name) => {
3346
+ var _a2;
3347
+ return (_a2 = nameToValue.get(name)) != null ? _a2 : match;
3348
+ });
3349
+ }
3350
+ function resolveLinkHref(url, nameToValue) {
3351
+ return normalizeUrl(resolveUrlTokens(url, nameToValue));
3352
+ }
3353
+ var DANGEROUS_URL_SCHEMES = /* @__PURE__ */ new Set(["javascript", "data", "vbscript"]);
3354
+ function isOpenableUrl(value) {
3355
+ try {
3356
+ new URL(value);
3357
+ return true;
3358
+ } catch (e) {
3359
+ return false;
3360
+ }
3361
+ }
2971
3362
  function normalizeUrl(url) {
2972
3363
  const trimmed = url.trim();
2973
3364
  if (!trimmed) return trimmed;
2974
- if (/^https?:\/\//i.test(trimmed) || /^mailto:/i.test(trimmed) || /^tel:/i.test(trimmed)) {
3365
+ const schemeMatch = /^([a-z][a-z0-9+-]*):/i.exec(trimmed);
3366
+ if (schemeMatch) {
3367
+ if (DANGEROUS_URL_SCHEMES.has(schemeMatch[1].toLowerCase())) return "";
3368
+ return trimmed;
3369
+ }
3370
+ if (/\$[^$]+\$/.test(trimmed)) {
3371
+ return trimmed;
3372
+ }
3373
+ if (/^[#?/]/.test(trimmed)) {
2975
3374
  return trimmed;
2976
3375
  }
2977
3376
  return `https://${trimmed}`;
2978
3377
  }
3378
+ function stripTokenMarks(marks) {
3379
+ if (!marks) return marks;
3380
+ const styleMarks = __spreadValues({}, marks);
3381
+ delete styleMarks.tokenName;
3382
+ delete styleMarks.tokenOccurrence;
3383
+ delete styleMarks.isRawToken;
3384
+ delete styleMarks.isEscapedDollar;
3385
+ return styleMarks;
3386
+ }
2979
3387
  function insertLink(editor, url, text) {
2980
3388
  if (isLinkActive(editor)) {
2981
3389
  unwrapLink(editor);
@@ -2986,7 +3394,7 @@ function insertLink(editor, url, text) {
2986
3394
  const isCollapsed = slate_exports.Range.isCollapsed(selection);
2987
3395
  let linkChild = { text: text || normalizedUrl };
2988
3396
  if (isCollapsed) {
2989
- const marks = slate_exports.Editor.marks(editor);
3397
+ const marks = stripTokenMarks(slate_exports.Editor.marks(editor));
2990
3398
  if (marks) {
2991
3399
  linkChild = __spreadValues(__spreadValues({}, linkChild), marks);
2992
3400
  }
@@ -2997,7 +3405,7 @@ function insertLink(editor, url, text) {
2997
3405
  children: isCollapsed ? [linkChild] : []
2998
3406
  };
2999
3407
  if (isCollapsed) {
3000
- const marksBeforeInsert = slate_exports.Editor.marks(editor);
3408
+ const marksBeforeInsert = stripTokenMarks(slate_exports.Editor.marks(editor));
3001
3409
  slate_exports.Transforms.insertNodes(editor, link);
3002
3410
  slate_exports.Transforms.move(editor, { unit: "offset" });
3003
3411
  if (marksBeforeInsert) {
@@ -3016,6 +3424,9 @@ function insertLink(editor, url, text) {
3016
3424
  anchor: { path: anchor.path, offset: anchor.offset - text.length },
3017
3425
  focus: anchor
3018
3426
  });
3427
+ slate_exports.Editor.removeMark(editor, "tokenName");
3428
+ slate_exports.Editor.removeMark(editor, "isRawToken");
3429
+ slate_exports.Editor.removeMark(editor, "isEscapedDollar");
3019
3430
  }
3020
3431
  slate_exports.Transforms.wrapNodes(editor, link, { split: true });
3021
3432
  slate_exports.Transforms.collapse(editor, { edge: "end" });
@@ -3086,11 +3497,11 @@ function getPendingMarks(editor) {
3086
3497
  }
3087
3498
  }
3088
3499
  function mergeMarks(nodeMarks, pendingMarksResult) {
3089
- var _a, _b, _c, _d;
3500
+ var _a2, _b, _c, _d;
3090
3501
  const { marks: pendingMarks, hasPendingMarks } = pendingMarksResult;
3091
3502
  const marks = __spreadValues({}, nodeMarks);
3092
3503
  if (hasPendingMarks) {
3093
- marks.bold = (_a = pendingMarks.bold) != null ? _a : false;
3504
+ marks.bold = (_a2 = pendingMarks.bold) != null ? _a2 : false;
3094
3505
  marks.italic = (_b = pendingMarks.italic) != null ? _b : false;
3095
3506
  marks.underline = (_c = pendingMarks.underline) != null ? _c : false;
3096
3507
  marks.strikethrough = (_d = pendingMarks.strikethrough) != null ? _d : false;
@@ -3210,7 +3621,11 @@ function slateToHtml(value) {
3210
3621
  };
3211
3622
  const serializeTextNode = (node) => {
3212
3623
  const styles = buildTextStyles(node);
3213
- let { text } = node;
3624
+ let text = node.tokenName ? `$${node.tokenName}$` : node.text;
3625
+ if (node.isEscapedDollar && /^\$+$/.test(node.text)) {
3626
+ const escapeCount = node.isRawToken ? node.text.length / 2 : node.text.length;
3627
+ text = "$$".repeat(escapeCount);
3628
+ }
3214
3629
  if (!text) {
3215
3630
  return styles.length > 0 ? `<span style="${styles.join("; ")}"></span>` : "";
3216
3631
  }
@@ -3231,7 +3646,7 @@ function slateToHtml(value) {
3231
3646
  const styleAttr = buildBlockStyleAttr(element);
3232
3647
  switch (element.type) {
3233
3648
  case "paragraph":
3234
- return `<p${styleAttr}>${children || "<br>"}</p>`;
3649
+ return `<p${styleAttr}>${children || "\n"}</p>`;
3235
3650
  case "bulleted-list":
3236
3651
  return `<ul${styleAttr}>${children}</ul>`;
3237
3652
  case "numbered-list":
@@ -3258,7 +3673,23 @@ function htmlToSlate(html) {
3258
3673
  if (!html || html.trim() === "") {
3259
3674
  return EMPTY_SLATE_VALUE;
3260
3675
  }
3261
- const sanitized = dompurify_default.sanitize(html, {
3676
+ const NULL = "\0";
3677
+ const restorePlaceholderRe = new RegExp(String.raw`${NULL}RT(\d+)${NULL}`, "g");
3678
+ const escapeUnsafeAngleBrackets = (input) => {
3679
+ const placeholders = [];
3680
+ const allowedTagRegex = /<\/?(?:p|br|strong|b|em|i|u|s|strike|span|a|ul|ol|li|div|font)\b[^>]*>/gi;
3681
+ const withPlaceholders = input.replace(allowedTagRegex, (match) => {
3682
+ const index = placeholders.push(match) - 1;
3683
+ return `${NULL}RT${index}${NULL}`;
3684
+ });
3685
+ const escaped = withPlaceholders.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
3686
+ return escaped.replace(restorePlaceholderRe, (_5, index) => {
3687
+ const parsedIndex = Number.parseInt(index, 10);
3688
+ return placeholders[parsedIndex] || "";
3689
+ });
3690
+ };
3691
+ const normalizedHtml = escapeUnsafeAngleBrackets(html);
3692
+ const sanitized = dompurify_default.sanitize(normalizedHtml, {
3262
3693
  ALLOWED_TAGS: [
3263
3694
  "p",
3264
3695
  "br",
@@ -3277,10 +3708,10 @@ function htmlToSlate(html) {
3277
3708
  "div",
3278
3709
  "font"
3279
3710
  ],
3280
- ALLOWED_ATTR: ["style", "href", "color", "face", "size"]
3711
+ ALLOWED_ATTR: ["style", "href", "color", "face", "size"],
3712
+ ALLOWED_URI_REGEXP
3281
3713
  });
3282
- const parser = new DOMParser();
3283
- const doc = parser.parseFromString(`<body>${sanitized}</body>`, "text/html");
3714
+ const doc = sharedDomParser.parseFromString(`<body>${sanitized}</body>`, "text/html");
3284
3715
  const applyMarksToChildren = (children, marks) => {
3285
3716
  return children.map((child) => {
3286
3717
  if (slate_exports.Text.isText(child)) {
@@ -3343,6 +3774,14 @@ function htmlToSlate(html) {
3343
3774
  }
3344
3775
  return children;
3345
3776
  };
3777
+ const collapseEmptyLineChildren = (children) => {
3778
+ if (children.length !== 1) return children;
3779
+ const [only] = children;
3780
+ if (slate_exports.Text.isText(only) && /^[\n\r]+$/.test(only.text)) {
3781
+ return [__spreadProps(__spreadValues({}, only), { text: "" })];
3782
+ }
3783
+ return children;
3784
+ };
3346
3785
  const handleTag = (tagName, element, children, blockStyles) => {
3347
3786
  const { align, lineHeight } = blockStyles;
3348
3787
  switch (tagName) {
@@ -3350,13 +3789,23 @@ function htmlToSlate(html) {
3350
3789
  case "div":
3351
3790
  return children;
3352
3791
  case "p":
3353
- return { type: "paragraph", align, lineHeight, children };
3792
+ return {
3793
+ type: "paragraph",
3794
+ align,
3795
+ lineHeight,
3796
+ children: collapseEmptyLineChildren(children)
3797
+ };
3354
3798
  case "ul":
3355
3799
  return { type: "bulleted-list", align, lineHeight, children };
3356
3800
  case "ol":
3357
3801
  return { type: "numbered-list", align, lineHeight, children };
3358
3802
  case "li":
3359
- return { type: "list-item", align, lineHeight, children };
3803
+ return {
3804
+ type: "list-item",
3805
+ align,
3806
+ lineHeight,
3807
+ children: collapseEmptyLineChildren(children)
3808
+ };
3360
3809
  case "a":
3361
3810
  return {
3362
3811
  type: "link",
@@ -3495,6 +3944,32 @@ function generateFormatAnnouncement(command, value) {
3495
3944
  }
3496
3945
 
3497
3946
  // src/RichText/PureRichText/PureRichTextContext.tsx
3947
+ function activeStylesEqual(a, b) {
3948
+ const keys = [
3949
+ "bold",
3950
+ "italic",
3951
+ "underline",
3952
+ "strikethrough",
3953
+ "color",
3954
+ "backgroundColor",
3955
+ "fontSize",
3956
+ "fontFamily",
3957
+ "textAlign",
3958
+ "verticalAlign",
3959
+ "lineHeight",
3960
+ "listType",
3961
+ "isLink"
3962
+ ];
3963
+ for (const key of keys) {
3964
+ if (a[key] !== b[key]) return false;
3965
+ }
3966
+ const aMixed = a.isMixed;
3967
+ const bMixed = b.isMixed;
3968
+ if (aMixed === bMixed) return true;
3969
+ if (!aMixed || !bMixed) return false;
3970
+ const mixedKeys = ["color", "backgroundColor", "fontSize", "fontFamily", "lineHeight"];
3971
+ return mixedKeys.every((key) => aMixed[key] === bMixed[key]);
3972
+ }
3498
3973
  var PureRichTextContext = (0, react_exports.createContext)(null);
3499
3974
  function usePureRichText() {
3500
3975
  const context = (0, react_exports.useContext)(PureRichTextContext);
@@ -3557,18 +4032,18 @@ function PureRichTextProvider({
3557
4032
  }, []);
3558
4033
  const resolveBooleanMark = (0, react_exports.useCallback)(
3559
4034
  (format, slateValue, hasAnyLeafContent, hasPendingMarks) => {
3560
- var _a;
4035
+ var _a2;
3561
4036
  if (boolMarkOverrideRef.current !== null && format in boolMarkOverrideRef.current) {
3562
4037
  return Boolean(boolMarkOverrideRef.current[format]);
3563
4038
  }
3564
4039
  if (hasAnyLeafContent || hasPendingMarks) return slateValue;
3565
- return (_a = userDefaultStyles[format]) != null ? _a : false;
4040
+ return (_a2 = userDefaultStyles[format]) != null ? _a2 : false;
3566
4041
  },
3567
4042
  [userDefaultStyles]
3568
4043
  );
3569
4044
  const updateActiveStyles = (0, react_exports.useCallback)(
3570
4045
  (isContentChange) => {
3571
- var _a, _b;
4046
+ var _a2, _b;
3572
4047
  const editor = editorRef.current;
3573
4048
  if (!(editor == null ? void 0 : editor.selection)) {
3574
4049
  return;
@@ -3599,29 +4074,29 @@ function PureRichTextProvider({
3599
4074
  hasPendingMarks
3600
4075
  ),
3601
4076
  color: slateStyles.color || userDefaultStyles.color,
3602
- backgroundColor: (_a = slateStyles.backgroundColor) != null ? _a : hasAnyLeafContent || hasPendingMarks ? null : userDefaultStyles.backgroundColor,
4077
+ backgroundColor: (_a2 = slateStyles.backgroundColor) != null ? _a2 : hasAnyLeafContent || hasPendingMarks ? null : userDefaultStyles.backgroundColor,
3603
4078
  fontSize: slateStyles.fontSize || userDefaultStyles.fontSize,
3604
4079
  fontFamily: slateStyles.fontFamily || userDefaultStyles.fontFamily,
3605
4080
  textAlign: slateStyles.textAlign || userDefaultStyles.textAlign,
3606
4081
  verticalAlign: userDefaultStyles.verticalAlign,
3607
4082
  lineHeight: slateStyles.lineHeight || userDefaultStyles.lineHeight,
3608
- listType: (_b = slateStyles.listType) != null ? _b : userDefaultStyles.listType
4083
+ listType: (_b = slateStyles.listType) != null ? _b : userDefaultStyles.listType,
4084
+ isLink: isLinkActive(editor)
3609
4085
  };
3610
4086
  if (slateStyles.isMixed && Object.keys(slateStyles.isMixed).length > 0) {
3611
4087
  newActiveStyles.isMixed = slateStyles.isMixed;
3612
4088
  }
3613
- setActiveTextStyles(newActiveStyles);
4089
+ setActiveTextStyles((prev) => activeStylesEqual(prev, newActiveStyles) ? prev : newActiveStyles);
3614
4090
  },
3615
4091
  [userDefaultStyles, resolveBooleanMark]
3616
4092
  );
3617
4093
  const toggleBooleanMark = (0, react_exports.useCallback)((editor, format) => {
3618
- var _a;
3619
4094
  toggleMark(editor, format);
3620
4095
  if (editor.selection && slate_exports.Range.isCollapsed(editor.selection)) {
3621
4096
  const editorWithMarks = editor;
3622
4097
  const internalMarks = editorWithMarks.marks;
3623
- const newValue = internalMarks !== null ? Boolean(internalMarks[format]) : false;
3624
- boolMarkOverrideRef.current = __spreadProps(__spreadValues({}, (_a = boolMarkOverrideRef.current) != null ? _a : {}), {
4098
+ const newValue = internalMarks === null ? false : Boolean(internalMarks[format]);
4099
+ boolMarkOverrideRef.current = __spreadProps(__spreadValues({}, boolMarkOverrideRef.current), {
3625
4100
  [format]: newValue
3626
4101
  });
3627
4102
  }
@@ -3663,7 +4138,7 @@ function PureRichTextProvider({
3663
4138
  );
3664
4139
  const applyFormat = (0, react_exports.useCallback)(
3665
4140
  (command, value) => {
3666
- var _a, _b;
4141
+ var _a2, _b;
3667
4142
  const editor = editorRef.current;
3668
4143
  if (!editor) return;
3669
4144
  if (!editor.selection && savedSelectionRef.current) {
@@ -3678,7 +4153,7 @@ function PureRichTextProvider({
3678
4153
  dispatchFormatCommand(editor, command, value);
3679
4154
  if (editor.selection) {
3680
4155
  savedSelectionRef.current = editor.selection;
3681
- (_a = onFormatAppliedRef.current) == null ? void 0 : _a.call(onFormatAppliedRef, editor.selection);
4156
+ (_a2 = onFormatAppliedRef.current) == null ? void 0 : _a2.call(onFormatAppliedRef, editor.selection);
3682
4157
  }
3683
4158
  updateActiveStyles();
3684
4159
  (_b = onAnnouncementRef.current) == null ? void 0 : _b.call(onAnnouncementRef, generateFormatAnnouncement(command, value));
@@ -3784,6 +4259,14 @@ function PureRichTextProvider({
3784
4259
  const editor = editorRef.current;
3785
4260
  if (!editor) return;
3786
4261
  try {
4262
+ if (!editor.selection && savedSelectionRef.current) {
4263
+ try {
4264
+ slate_exports.Transforms.select(editor, savedSelectionRef.current);
4265
+ } catch (e) {
4266
+ return;
4267
+ }
4268
+ }
4269
+ if (!editor.selection) return;
3787
4270
  unwrapLink(editor);
3788
4271
  updateActiveStyles();
3789
4272
  } catch (error) {
@@ -4398,8 +4881,8 @@ function useLinkHandlers(handlers) {
4398
4881
  }
4399
4882
  resetLinkState();
4400
4883
  setTimeout(() => {
4401
- var _a;
4402
- (_a = linkButtonRef.current) == null ? void 0 : _a.focus();
4884
+ var _a2;
4885
+ (_a2 = linkButtonRef.current) == null ? void 0 : _a2.focus();
4403
4886
  }, 0);
4404
4887
  }, [linkUrl, linkText, createOrUpdateLink, resetLinkState]);
4405
4888
  const handleLinkRemove = (0, react_exports.useCallback)(() => {
@@ -4408,13 +4891,14 @@ function useLinkHandlers(handlers) {
4408
4891
  }
4409
4892
  resetLinkState();
4410
4893
  setTimeout(() => {
4411
- var _a;
4412
- (_a = linkButtonRef.current) == null ? void 0 : _a.focus();
4894
+ var _a2;
4895
+ (_a2 = linkButtonRef.current) == null ? void 0 : _a2.focus();
4413
4896
  }, 0);
4414
4897
  }, [removeLink, resetLinkState]);
4415
4898
  const handleLinkKeyDown = (0, react_exports.useCallback)(
4416
4899
  (e) => {
4417
- if (e.key === "Enter") {
4900
+ var _a2;
4901
+ if (e.key === "Enter" && ((_a2 = e.target) == null ? void 0 : _a2.tagName) === "INPUT") {
4418
4902
  e.preventDefault();
4419
4903
  handleLinkSave();
4420
4904
  }
@@ -4424,8 +4908,8 @@ function useLinkHandlers(handlers) {
4424
4908
  e.nativeEvent.stopImmediatePropagation();
4425
4909
  resetLinkState();
4426
4910
  setTimeout(() => {
4427
- var _a;
4428
- (_a = linkButtonRef.current) == null ? void 0 : _a.focus();
4911
+ var _a3;
4912
+ (_a3 = linkButtonRef.current) == null ? void 0 : _a3.focus();
4429
4913
  }, 0);
4430
4914
  }
4431
4915
  },
@@ -4434,8 +4918,8 @@ function useLinkHandlers(handlers) {
4434
4918
  (0, react_exports.useEffect)(() => {
4435
4919
  if (!linkPopoverOpen) return void 0;
4436
4920
  const timer = setTimeout(() => {
4437
- var _a, _b;
4438
- (_b = (_a = linkPopoverRef.current) == null ? void 0 : _a.querySelector("input")) == null ? void 0 : _b.focus();
4921
+ var _a2, _b;
4922
+ (_b = (_a2 = linkPopoverRef.current) == null ? void 0 : _a2.querySelector("input")) == null ? void 0 : _b.focus();
4439
4923
  }, 50);
4440
4924
  return () => clearTimeout(timer);
4441
4925
  }, [linkPopoverOpen]);
@@ -4484,7 +4968,7 @@ function useLineSpacing(lineHeight, displayLineHeight, isLineHeightMixed, applyF
4484
4968
  }, [displayLineHeight, lineHeight, isLineHeightMixed]);
4485
4969
  const handleLineSpacingChange = (0, react_exports.useCallback)(
4486
4970
  (_e, data) => {
4487
- var _a, _b;
4971
+ var _a2, _b;
4488
4972
  const { value, reason } = data;
4489
4973
  if (value !== void 0 && value !== null) {
4490
4974
  setLineSpacingPercent(value);
@@ -4495,7 +4979,7 @@ function useLineSpacing(lineHeight, displayLineHeight, isLineHeightMixed, applyF
4495
4979
  if (reason === "stepButton" && applyFormat) {
4496
4980
  if (isLineHeightMixed && stepLineSpacing) {
4497
4981
  const target = _e == null ? void 0 : _e.currentTarget;
4498
- const testId = ((_a = target == null ? void 0 : target.getAttribute) == null ? void 0 : _a.call(target, "data-test")) || ((_b = target == null ? void 0 : target.getAttribute) == null ? void 0 : _b.call(target, "data-testid")) || "";
4982
+ const testId = ((_a2 = target == null ? void 0 : target.getAttribute) == null ? void 0 : _a2.call(target, "data-test")) || ((_b = target == null ? void 0 : target.getAttribute) == null ? void 0 : _b.call(target, "data-testid")) || "";
4499
4983
  const isDecrement = testId === "decrement" || testId.includes("down");
4500
4984
  stepLineSpacing(isDecrement ? -1 : 1);
4501
4985
  return;
@@ -4523,158 +5007,13 @@ function useLineSpacing(lineHeight, displayLineHeight, isLineHeightMixed, applyF
4523
5007
  };
4524
5008
  }
4525
5009
 
4526
- // src/RichText/PureRichText/Editor/EditorPanel.tsx
4527
- var TextAlignJustified = () => /* @__PURE__ */ react_default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ react_default.createElement(
4528
- "path",
4529
- {
4530
- d: "M3 6h18M3 10h18M3 14h18M3 18h18",
4531
- stroke: "currentColor",
4532
- strokeWidth: "1.5",
4533
- strokeLinecap: "round"
4534
- }
4535
- ));
4536
- var preventDefaultMouseDown = (e) => e.preventDefault();
4537
- var focusMixedSwatch = (selector) => {
4538
- setTimeout(() => {
4539
- var _a;
4540
- (_a = document.querySelector(selector)) == null ? void 0 : _a.focus();
4541
- }, 50);
4542
- };
4543
- var EditorPanel = ({
5010
+ // src/RichText/PureRichText/Editor/hooks/useConfigPanelFocus.ts
5011
+ function useConfigPanelFocus({
4544
5012
  isEditMode,
4545
- isActive = false,
4546
- fontColor = "#ffffff",
4547
- fontSize: fontSizeProp = 14,
4548
- lineHeight = "1.5",
4549
- verticalAlign: verticalAlignProp = "top",
4550
- onVerticalAlignChange
4551
- }) => {
4552
- var _a, _b;
4553
- const portalTargetRef = (0, react_exports.useRef)(null);
4554
- const [renderTick, forceUpdate] = react_default.useReducer((n) => n + 1, 0);
4555
- const portalReady = renderTick >= 0 && portalTargetRef.current !== null;
4556
- const contextValue = usePureRichTextOptional();
4557
- const activeTextStyles = (contextValue == null ? void 0 : contextValue.activeTextStyles) || DEFAULT_TEXT_STYLES;
4558
- const applyFormat = contextValue == null ? void 0 : contextValue.applyFormat;
4559
- const resetToDefault = contextValue == null ? void 0 : contextValue.resetToDefault;
4560
- const stepFontSize = contextValue == null ? void 0 : contextValue.stepFontSize;
4561
- const stepLineSpacing = contextValue == null ? void 0 : contextValue.stepLineSpacing;
4562
- const isInLink = contextValue == null ? void 0 : contextValue.isInLink;
4563
- const getLinkInfo = contextValue == null ? void 0 : contextValue.getLinkInfo;
4564
- const createOrUpdateLink = contextValue == null ? void 0 : contextValue.createOrUpdateLink;
4565
- const removeLink = contextValue == null ? void 0 : contextValue.removeLink;
4566
- const registerOpenLinkPopover = contextValue == null ? void 0 : contextValue.registerOpenLinkPopover;
4567
- const [align, setAlign] = (0, react_exports.useState)("left");
4568
- const [verticalAlign, setVerticalAlign] = (0, react_exports.useState)(verticalAlignProp);
4569
- const [currentFontSize, setCurrentFontSize] = (0, react_exports.useState)(fontSizeProp);
4570
- const [fontSizePreset, setFontSizePreset] = (0, react_exports.useState)(() => getFontSizePreset(fontSizeProp));
4571
- const fontSizeDirtyRef = (0, react_exports.useRef)(false);
4572
- const {
4573
- linkIsActive,
4574
- linkPopoverOpen,
4575
- linkPopoverRef,
4576
- linkText,
4577
- linkUrl,
4578
- linkButtonRef,
4579
- setLinkText,
4580
- setLinkUrl,
4581
- handleLinkButtonClick,
4582
- handleLinkPopoverClose,
4583
- handleLinkSave,
4584
- handleLinkRemove,
4585
- handleLinkKeyDown
4586
- } = useLinkHandlers({
4587
- isInLink,
4588
- getLinkInfo,
4589
- createOrUpdateLink,
4590
- removeLink
4591
- });
4592
- (0, react_exports.useEffect)(() => {
4593
- registerOpenLinkPopover == null ? void 0 : registerOpenLinkPopover(handleLinkButtonClick);
4594
- }, [registerOpenLinkPopover, handleLinkButtonClick]);
4595
- const wasMouseRef = (0, react_exports.useRef)(false);
4596
- const handleFormat = (0, react_exports.useCallback)(
4597
- (command, value) => {
4598
- if (!applyFormat) return;
4599
- applyFormat(command, value);
4600
- if (wasMouseRef.current) {
4601
- setTimeout(() => {
4602
- focusActiveEditable();
4603
- }, 0);
4604
- }
4605
- },
4606
- [applyFormat]
4607
- );
4608
- const isLineHeightMixed = ((_a = activeTextStyles.isMixed) == null ? void 0 : _a.lineHeight) === true;
4609
- const {
4610
- lineSpacingPercent,
4611
- showMixed: showLineSpacingMixed,
4612
- handleLineSpacingChange,
4613
- handleLineSpacingBlur
4614
- } = useLineSpacing(
4615
- lineHeight,
4616
- activeTextStyles.lineHeight,
4617
- isLineHeightMixed,
4618
- applyFormat,
4619
- handleFormat,
4620
- stepLineSpacing
4621
- );
4622
- const handleFontFamilyChange = (0, react_exports.useCallback)(
4623
- (fontFamily) => handleFormat("fontName", fontFamily),
4624
- [handleFormat]
4625
- );
4626
- (0, react_exports.useEffect)(() => {
4627
- if (!isEditMode) {
4628
- portalTargetRef.current = null;
4629
- forceUpdate();
4630
- return void 0;
4631
- }
4632
- const findTarget = () => {
4633
- const target = getEditorPanelTarget();
4634
- if (target && target !== portalTargetRef.current) {
4635
- portalTargetRef.current = target;
4636
- forceUpdate();
4637
- }
4638
- };
4639
- findTarget();
4640
- const interval = setInterval(findTarget, 100);
4641
- return () => {
4642
- clearInterval(interval);
4643
- portalTargetRef.current = null;
4644
- };
4645
- }, [isEditMode]);
4646
- (0, react_exports.useEffect)(() => {
4647
- if (activeTextStyles.textAlign) {
4648
- setAlign(activeTextStyles.textAlign);
4649
- }
4650
- }, [activeTextStyles.textAlign]);
4651
- (0, react_exports.useEffect)(() => {
4652
- setVerticalAlign(verticalAlignProp);
4653
- }, [verticalAlignProp]);
4654
- (0, react_exports.useEffect)(() => {
4655
- fontSizeDirtyRef.current = false;
4656
- if (activeTextStyles.fontSize) {
4657
- const size2 = Number.parseInt(String(activeTextStyles.fontSize), 10) || 14;
4658
- setCurrentFontSize(size2);
4659
- setFontSizePreset(getFontSizePreset(size2));
4660
- }
4661
- }, [activeTextStyles.fontSize]);
4662
- const handleVerticalAlignChange = (0, react_exports.useCallback)(
4663
- (newAlign) => {
4664
- setVerticalAlign(newAlign);
4665
- onVerticalAlignChange == null ? void 0 : onVerticalAlignChange(newAlign);
4666
- },
4667
- [onVerticalAlignChange]
4668
- );
4669
- const isMixedStyles = activeTextStyles.isMixed || {};
4670
- const isColorMixed = isMixedStyles.color === true;
4671
- const isHighlightMixed = isMixedStyles.backgroundColor === true;
4672
- const isFontSizeMixed = isMixedStyles.fontSize === true;
4673
- const isFontFamilyMixed = isMixedStyles.fontFamily === true;
4674
- const displayTextColor = isColorMixed ? "" : activeTextStyles.color || fontColor;
4675
- const displayHighlightColor = isHighlightMixed ? "" : (_b = activeTextStyles.backgroundColor) != null ? _b : "transparent";
4676
- const displayFontFamily = isFontFamilyMixed ? "" : activeTextStyles.fontFamily || "Splunk Data Sans";
4677
- const editorContainerRef = (0, react_exports.useRef)(null);
5013
+ isActive,
5014
+ editorContainerRef,
5015
+ wasMouseRef
5016
+ }) {
4678
5017
  (0, react_exports.useEffect)(() => {
4679
5018
  if (!isEditMode || !isActive) return void 0;
4680
5019
  const handleMouseDown = (e) => {
@@ -4702,7 +5041,7 @@ var EditorPanel = ({
4702
5041
  document.removeEventListener("mousedown", handleMouseDown, true);
4703
5042
  document.removeEventListener("keydown", handleKeyDown, true);
4704
5043
  };
4705
- }, [isEditMode, isActive]);
5044
+ }, [isEditMode, isActive, editorContainerRef, wasMouseRef]);
4706
5045
  (0, react_exports.useEffect)(() => {
4707
5046
  if (!isEditMode || !isActive) return void 0;
4708
5047
  const FOCUS_RING_ATTR = "data-trap-focused";
@@ -4731,23 +5070,32 @@ var EditorPanel = ({
4731
5070
  const handleBlurCleanup = () => {
4732
5071
  removeFocusRing();
4733
5072
  };
4734
- const getConfigPanel = () => editorContainerRef.current;
4735
5073
  const getFocusableElements = (panel) => {
4736
5074
  const selector = 'button:not([disabled]):not([aria-disabled="true"]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href]:not([disabled])';
4737
5075
  return Array.from(panel.querySelectorAll(selector)).filter(
4738
5076
  (el) => el.offsetParent !== null && el.offsetWidth > 0 && el.offsetHeight > 0
4739
5077
  );
4740
5078
  };
5079
+ const moveFocus = (e, focusable, currentIndex) => {
5080
+ const backward = e.shiftKey;
5081
+ const atBoundary = backward ? currentIndex <= 0 : currentIndex >= focusable.length - 1;
5082
+ if (atBoundary) {
5083
+ removeFocusRing();
5084
+ return;
5085
+ }
5086
+ e.preventDefault();
5087
+ const nextEl = focusable[backward ? currentIndex - 1 : currentIndex + 1];
5088
+ nextEl.focus();
5089
+ applyFocusRing(nextEl);
5090
+ };
4741
5091
  const handleConfigPanelKeyDown = (e) => {
4742
5092
  const target = e.target;
4743
5093
  if (e.key === "Escape") {
4744
5094
  removeFocusRing();
4745
5095
  return;
4746
5096
  }
4747
- const configPanel = getConfigPanel();
4748
- if (!configPanel) return;
4749
- if (!configPanel.contains(target)) return;
4750
- if (e.key !== "Tab") return;
5097
+ const configPanel = editorContainerRef.current;
5098
+ if (!(configPanel == null ? void 0 : configPanel.contains(target)) || e.key !== "Tab") return;
4751
5099
  const focusable = getFocusableElements(configPanel);
4752
5100
  if (focusable.length === 0) return;
4753
5101
  const currentIndex = focusable.indexOf(target);
@@ -4755,25 +5103,7 @@ var EditorPanel = ({
4755
5103
  removeFocusRing();
4756
5104
  return;
4757
5105
  }
4758
- if (e.shiftKey) {
4759
- if (currentIndex <= 0) {
4760
- removeFocusRing();
4761
- return;
4762
- }
4763
- e.preventDefault();
4764
- const nextEl = focusable[currentIndex - 1];
4765
- nextEl.focus();
4766
- applyFocusRing(nextEl);
4767
- } else {
4768
- if (currentIndex >= focusable.length - 1) {
4769
- removeFocusRing();
4770
- return;
4771
- }
4772
- e.preventDefault();
4773
- const nextEl = focusable[currentIndex + 1];
4774
- nextEl.focus();
4775
- applyFocusRing(nextEl);
4776
- }
5106
+ moveFocus(e, focusable, currentIndex);
4777
5107
  };
4778
5108
  document.addEventListener("keydown", handleConfigPanelKeyDown, true);
4779
5109
  document.addEventListener("focusout", handleBlurCleanup, true);
@@ -4782,7 +5112,311 @@ var EditorPanel = ({
4782
5112
  document.removeEventListener("focusout", handleBlurCleanup, true);
4783
5113
  removeFocusRing();
4784
5114
  };
4785
- }, [isEditMode, isActive]);
5115
+ }, [isEditMode, isActive, editorContainerRef]);
5116
+ }
5117
+
5118
+ // src/RichText/PureRichText/Editor/hooks/usePortalTarget.ts
5119
+ function usePortalTarget(isEditMode) {
5120
+ const portalTargetRef = (0, react_exports.useRef)(null);
5121
+ const [renderTick, forceUpdate] = (0, react_exports.useReducer)((n) => n + 1, 0);
5122
+ const portalReady = renderTick >= 0 && portalTargetRef.current !== null;
5123
+ (0, react_exports.useEffect)(() => {
5124
+ if (!isEditMode) {
5125
+ portalTargetRef.current = null;
5126
+ forceUpdate();
5127
+ return void 0;
5128
+ }
5129
+ const findTarget = () => {
5130
+ const target = getEditorPanelTarget();
5131
+ if (target && target !== portalTargetRef.current) {
5132
+ portalTargetRef.current = target;
5133
+ forceUpdate();
5134
+ }
5135
+ };
5136
+ findTarget();
5137
+ const interval = setInterval(findTarget, 100);
5138
+ return () => {
5139
+ clearInterval(interval);
5140
+ portalTargetRef.current = null;
5141
+ };
5142
+ }, [isEditMode]);
5143
+ return { portalTargetRef, portalReady };
5144
+ }
5145
+
5146
+ // src/RichText/PureRichText/Editor/hooks/useEditorPanelSync.ts
5147
+ function useEditorPanelSync({
5148
+ textAlign,
5149
+ setAlign,
5150
+ verticalAlignProp,
5151
+ setVerticalAlign,
5152
+ activeFontSize,
5153
+ fontSizeDirtyRef,
5154
+ setCurrentFontSize,
5155
+ setFontSizePreset
5156
+ }) {
5157
+ (0, react_exports.useEffect)(() => {
5158
+ if (textAlign) {
5159
+ setAlign(textAlign);
5160
+ }
5161
+ }, [textAlign, setAlign]);
5162
+ (0, react_exports.useEffect)(() => {
5163
+ setVerticalAlign(verticalAlignProp);
5164
+ }, [verticalAlignProp, setVerticalAlign]);
5165
+ (0, react_exports.useEffect)(() => {
5166
+ fontSizeDirtyRef.current = false;
5167
+ if (activeFontSize) {
5168
+ const size2 = Number.parseInt(String(activeFontSize), 10) || 14;
5169
+ setCurrentFontSize(size2);
5170
+ setFontSizePreset(getFontSizePreset(size2));
5171
+ }
5172
+ }, [activeFontSize, fontSizeDirtyRef, setCurrentFontSize, setFontSizePreset]);
5173
+ }
5174
+
5175
+ // src/RichText/PureRichText/Editor/EditorPanel.tsx
5176
+ var TextAlignJustified = () => /* @__PURE__ */ react_default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ react_default.createElement(
5177
+ "path",
5178
+ {
5179
+ d: "M3 6h18M3 10h18M3 14h18M3 18h18",
5180
+ stroke: "currentColor",
5181
+ strokeWidth: "1.5",
5182
+ strokeLinecap: "round"
5183
+ }
5184
+ ));
5185
+ var preventDefaultMouseDown = (e) => e.preventDefault();
5186
+ function handleFontSizeStep(e, val, ctx) {
5187
+ var _a2, _b;
5188
+ if (!ctx.stepFontSize) {
5189
+ if (val != null) {
5190
+ ctx.setCurrentFontSize(val);
5191
+ ctx.setFontSizePreset(getFontSizePreset(val));
5192
+ ctx.handleFormat("fontSize", `${val}px`);
5193
+ }
5194
+ return;
5195
+ }
5196
+ const target = e == null ? void 0 : e.currentTarget;
5197
+ const testId = ((_a2 = target == null ? void 0 : target.getAttribute) == null ? void 0 : _a2.call(target, "data-test")) || ((_b = target == null ? void 0 : target.getAttribute) == null ? void 0 : _b.call(target, "data-testid")) || "";
5198
+ const isDecrement = testId === "decrement" || testId.includes("down");
5199
+ ctx.stepFontSize(isDecrement ? -2 : 2);
5200
+ if (ctx.wasMouseRef.current) {
5201
+ setTimeout(() => focusActiveEditable(), 0);
5202
+ }
5203
+ }
5204
+ function handleFontSizeChange(e, val, reason, ctx) {
5205
+ if (reason === "stepButton") {
5206
+ handleFontSizeStep(e, val, ctx);
5207
+ return;
5208
+ }
5209
+ if (val != null) {
5210
+ ctx.fontSizeDirtyRef.current = true;
5211
+ ctx.setCurrentFontSize(val);
5212
+ ctx.setFontSizePreset(getFontSizePreset(val));
5213
+ }
5214
+ }
5215
+ var focusMixedSwatch = (selector) => {
5216
+ setTimeout(() => {
5217
+ var _a2;
5218
+ (_a2 = document.querySelector(selector)) == null ? void 0 : _a2.focus();
5219
+ }, 50);
5220
+ };
5221
+ function handleMixedSwatchClick(isMixed) {
5222
+ if (isMixed) focusMixedSwatch('[data-test="textbox-swatch"]');
5223
+ }
5224
+ var ALIGN_COMMANDS = {
5225
+ left: "justifyLeft",
5226
+ center: "justifyCenter",
5227
+ right: "justifyRight",
5228
+ justify: "justifyFull"
5229
+ };
5230
+ function handleAlignmentChange(newAlign, setAlign, handleFormat) {
5231
+ setAlign(newAlign);
5232
+ handleFormat(ALIGN_COMMANDS[newAlign]);
5233
+ }
5234
+ function handleFontSizePresetChange(val, ctx) {
5235
+ const preset = FONT_SIZE_OPTIONS.find((p) => p.value === val);
5236
+ if (!preset) {
5237
+ ctx.setFontSizePreset("custom");
5238
+ return;
5239
+ }
5240
+ ctx.setCurrentFontSize(Number.parseInt(preset.value, 10));
5241
+ ctx.setFontSizePreset(preset.value);
5242
+ ctx.handleFormat("fontSize", `${preset.value}px`);
5243
+ }
5244
+ function handleFontSizeArrowCapture(e, stepFontSize) {
5245
+ if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return;
5246
+ e.preventDefault();
5247
+ e.stopPropagation();
5248
+ stepFontSize(e.key === "ArrowUp" ? 2 : -2);
5249
+ }
5250
+ function handleFontSizeInputKeyDown(e, ctx) {
5251
+ if (e.key !== "Enter" || !ctx.currentFontSize) return;
5252
+ e.preventDefault();
5253
+ e.stopPropagation();
5254
+ ctx.fontSizeDirtyRef.current = false;
5255
+ ctx.handleFormat("fontSize", `${ctx.currentFontSize}px`);
5256
+ }
5257
+ function handleFontSizeInputBlur(ctx) {
5258
+ if (ctx.fontSizeDirtyRef.current && ctx.currentFontSize) {
5259
+ ctx.handleFormat("fontSize", `${ctx.currentFontSize}px`);
5260
+ }
5261
+ ctx.fontSizeDirtyRef.current = false;
5262
+ }
5263
+ function handleLineSpacingKeyDown(e, ctx) {
5264
+ if (e.key === "Enter") {
5265
+ ctx.handleLineSpacingBlur();
5266
+ }
5267
+ if (!ctx.isLineHeightMixed || !ctx.stepLineSpacing) return;
5268
+ if (e.key === "ArrowUp") {
5269
+ e.preventDefault();
5270
+ ctx.stepLineSpacing(1);
5271
+ } else if (e.key === "ArrowDown") {
5272
+ e.preventDefault();
5273
+ ctx.stepLineSpacing(-1);
5274
+ }
5275
+ }
5276
+ function computeMixedDisplayStyles(activeTextStyles, fontColor) {
5277
+ var _a2;
5278
+ const isMixedStyles = activeTextStyles.isMixed || {};
5279
+ const isColorMixed = isMixedStyles.color === true;
5280
+ const isHighlightMixed = isMixedStyles.backgroundColor === true;
5281
+ const isFontSizeMixed = isMixedStyles.fontSize === true;
5282
+ const isFontFamilyMixed = isMixedStyles.fontFamily === true;
5283
+ return {
5284
+ isColorMixed,
5285
+ isHighlightMixed,
5286
+ isFontSizeMixed,
5287
+ isFontFamilyMixed,
5288
+ displayTextColor: isColorMixed ? "" : activeTextStyles.color || fontColor,
5289
+ displayHighlightColor: isHighlightMixed ? "" : (_a2 = activeTextStyles.backgroundColor) != null ? _a2 : "transparent",
5290
+ displayFontFamily: isFontFamilyMixed ? "" : activeTextStyles.fontFamily || "Splunk Data Sans"
5291
+ };
5292
+ }
5293
+ function handleResetToDefault(resetToDefault, wasMouseRef) {
5294
+ resetToDefault == null ? void 0 : resetToDefault();
5295
+ if (wasMouseRef.current) {
5296
+ setTimeout(() => focusActiveEditable(), 0);
5297
+ }
5298
+ }
5299
+ var EditorPanel = ({
5300
+ isEditMode,
5301
+ isActive = false,
5302
+ fontColor = "#ffffff",
5303
+ fontSize: fontSizeProp = 14,
5304
+ lineHeight = "1.5",
5305
+ verticalAlign: verticalAlignProp = "top",
5306
+ onVerticalAlignChange
5307
+ }) => {
5308
+ var _a2, _b;
5309
+ const { portalTargetRef, portalReady } = usePortalTarget(isEditMode);
5310
+ const contextValue = usePureRichTextOptional();
5311
+ const activeTextStyles = (contextValue == null ? void 0 : contextValue.activeTextStyles) || DEFAULT_TEXT_STYLES;
5312
+ const applyFormat = contextValue == null ? void 0 : contextValue.applyFormat;
5313
+ const resetToDefault = contextValue == null ? void 0 : contextValue.resetToDefault;
5314
+ const stepFontSize = contextValue == null ? void 0 : contextValue.stepFontSize;
5315
+ const stepLineSpacing = contextValue == null ? void 0 : contextValue.stepLineSpacing;
5316
+ const isInLink = contextValue == null ? void 0 : contextValue.isInLink;
5317
+ const getLinkInfo = contextValue == null ? void 0 : contextValue.getLinkInfo;
5318
+ const createOrUpdateLink = contextValue == null ? void 0 : contextValue.createOrUpdateLink;
5319
+ const removeLink = contextValue == null ? void 0 : contextValue.removeLink;
5320
+ const registerOpenLinkPopover = contextValue == null ? void 0 : contextValue.registerOpenLinkPopover;
5321
+ const [align, setAlign] = (0, react_exports.useState)("left");
5322
+ const [verticalAlign, setVerticalAlign] = (0, react_exports.useState)(verticalAlignProp);
5323
+ const [currentFontSize, setCurrentFontSize] = (0, react_exports.useState)(fontSizeProp);
5324
+ const [fontSizePreset, setFontSizePreset] = (0, react_exports.useState)(() => getFontSizePreset(fontSizeProp));
5325
+ const fontSizeDirtyRef = (0, react_exports.useRef)(false);
5326
+ const linkIsActive = (_a2 = activeTextStyles.isLink) != null ? _a2 : false;
5327
+ const {
5328
+ linkPopoverOpen,
5329
+ linkPopoverRef,
5330
+ linkText,
5331
+ linkUrl,
5332
+ linkButtonRef,
5333
+ setLinkText,
5334
+ setLinkUrl,
5335
+ handleLinkButtonClick,
5336
+ handleLinkPopoverClose,
5337
+ handleLinkSave,
5338
+ handleLinkRemove,
5339
+ handleLinkKeyDown
5340
+ } = useLinkHandlers({
5341
+ isInLink,
5342
+ getLinkInfo,
5343
+ createOrUpdateLink,
5344
+ removeLink
5345
+ });
5346
+ (0, react_exports.useEffect)(() => {
5347
+ registerOpenLinkPopover == null ? void 0 : registerOpenLinkPopover(handleLinkButtonClick);
5348
+ }, [registerOpenLinkPopover, handleLinkButtonClick]);
5349
+ const wasMouseRef = (0, react_exports.useRef)(false);
5350
+ const handleFormat = (0, react_exports.useCallback)(
5351
+ (command, value) => {
5352
+ if (!applyFormat) return;
5353
+ applyFormat(command, value);
5354
+ if (wasMouseRef.current) {
5355
+ setTimeout(() => {
5356
+ focusActiveEditable();
5357
+ }, 0);
5358
+ }
5359
+ },
5360
+ [applyFormat]
5361
+ );
5362
+ const isLineHeightMixed = ((_b = activeTextStyles.isMixed) == null ? void 0 : _b.lineHeight) === true;
5363
+ const {
5364
+ lineSpacingPercent,
5365
+ showMixed: showLineSpacingMixed,
5366
+ handleLineSpacingChange,
5367
+ handleLineSpacingBlur
5368
+ } = useLineSpacing(
5369
+ lineHeight,
5370
+ activeTextStyles.lineHeight,
5371
+ isLineHeightMixed,
5372
+ applyFormat,
5373
+ handleFormat,
5374
+ stepLineSpacing
5375
+ );
5376
+ const handleFontFamilyChange = (0, react_exports.useCallback)(
5377
+ (fontFamily) => handleFormat("fontName", fontFamily),
5378
+ [handleFormat]
5379
+ );
5380
+ const onFontSizeChange = (0, react_exports.useCallback)(
5381
+ (e, { value: val, reason }) => {
5382
+ handleFontSizeChange(e, val, reason, {
5383
+ stepFontSize,
5384
+ setCurrentFontSize,
5385
+ setFontSizePreset,
5386
+ handleFormat,
5387
+ fontSizeDirtyRef,
5388
+ wasMouseRef
5389
+ });
5390
+ },
5391
+ [stepFontSize, handleFormat]
5392
+ );
5393
+ useEditorPanelSync({
5394
+ textAlign: activeTextStyles.textAlign,
5395
+ setAlign,
5396
+ verticalAlignProp,
5397
+ setVerticalAlign,
5398
+ activeFontSize: activeTextStyles.fontSize,
5399
+ fontSizeDirtyRef,
5400
+ setCurrentFontSize,
5401
+ setFontSizePreset
5402
+ });
5403
+ const handleVerticalAlignChange = (0, react_exports.useCallback)(
5404
+ (newAlign) => {
5405
+ setVerticalAlign(newAlign);
5406
+ onVerticalAlignChange == null ? void 0 : onVerticalAlignChange(newAlign);
5407
+ },
5408
+ [onVerticalAlignChange]
5409
+ );
5410
+ const {
5411
+ isColorMixed,
5412
+ isHighlightMixed,
5413
+ isFontSizeMixed,
5414
+ displayTextColor,
5415
+ displayHighlightColor,
5416
+ displayFontFamily
5417
+ } = computeMixedDisplayStyles(activeTextStyles, fontColor);
5418
+ const editorContainerRef = (0, react_exports.useRef)(null);
5419
+ useConfigPanelFocus({ isEditMode, isActive, editorContainerRef, wasMouseRef });
4786
5420
  if (!isEditMode) return null;
4787
5421
  const editor = /* @__PURE__ */ react_default.createElement(EditorContainer, { ref: editorContainerRef, "data-test": "editor-purerichtext-content" }, /* @__PURE__ */ react_default.createElement(FontSelector, { value: displayFontFamily, onChange: handleFontFamilyChange }), /* @__PURE__ */ react_default.createElement(ControlGroup_default, { label: "Font size", labelPosition: "top" }, /* @__PURE__ */ react_default.createElement(Row, { style: { gap: "12px" } }, /* @__PURE__ */ react_default.createElement(
4788
5422
  Select_default,
@@ -4790,90 +5424,52 @@ var EditorPanel = ({
4790
5424
  value: isFontSizeMixed ? void 0 : fontSizePreset,
4791
5425
  placeholder: isFontSizeMixed ? "Mixed" : void 0,
4792
5426
  onChange: (_e, { value: val }) => {
4793
- const preset = FONT_SIZE_OPTIONS.find((p) => p.value === val);
4794
- if (preset) {
4795
- setCurrentFontSize(Number.parseInt(preset.value, 10));
4796
- setFontSizePreset(val);
4797
- handleFormat("fontSize", `${preset.value}px`);
4798
- } else {
4799
- setFontSizePreset("custom");
4800
- }
5427
+ handleFontSizePresetChange(val, {
5428
+ setCurrentFontSize,
5429
+ setFontSizePreset,
5430
+ handleFormat
5431
+ });
4801
5432
  },
4802
5433
  style: { flex: 1, minWidth: 100 }
4803
5434
  },
4804
5435
  FONT_SIZE_OPTIONS.map(({ label, value }) => /* @__PURE__ */ react_default.createElement(Select_default.Option, { key: value, label, value })),
4805
5436
  /* @__PURE__ */ react_default.createElement(Select_default.Option, { label: "Custom", value: "custom" })
4806
- ), /* @__PURE__ */ react_default.createElement("div", { style: { width: "80px", flexShrink: 0 } }, /* @__PURE__ */ react_default.createElement(
4807
- Number_default,
5437
+ ), /* @__PURE__ */ react_default.createElement(
5438
+ "div",
4808
5439
  {
4809
- "aria-label": "Font size in pixels",
4810
- value: isFontSizeMixed ? void 0 : currentFontSize,
4811
- onFocus: () => {
4812
- fontSizeDirtyRef.current = false;
4813
- },
4814
- onChange: (_e, { value: val, reason }) => {
4815
- var _a2, _b2;
4816
- if (reason === "stepButton") {
4817
- if (!stepFontSize) {
4818
- if (val != null) {
4819
- setCurrentFontSize(val);
4820
- setFontSizePreset(getFontSizePreset(val));
4821
- handleFormat("fontSize", `${val}px`);
4822
- }
4823
- return;
4824
- }
4825
- const target = _e == null ? void 0 : _e.currentTarget;
4826
- const testId = ((_a2 = target == null ? void 0 : target.getAttribute) == null ? void 0 : _a2.call(target, "data-test")) || ((_b2 = target == null ? void 0 : target.getAttribute) == null ? void 0 : _b2.call(target, "data-testid")) || "";
4827
- const isDecrement = testId === "decrement" || testId.includes("down");
4828
- stepFontSize(isDecrement ? -2 : 2);
4829
- if (wasMouseRef.current) {
4830
- setTimeout(() => {
4831
- focusActiveEditable();
4832
- }, 0);
4833
- }
4834
- return;
4835
- }
4836
- if (val != null) {
4837
- fontSizeDirtyRef.current = true;
4838
- setCurrentFontSize(val);
4839
- setFontSizePreset(getFontSizePreset(val));
4840
- }
4841
- },
4842
- onKeyDown: (e) => {
4843
- if (e.key === "Enter" && currentFontSize) {
4844
- e.preventDefault();
4845
- e.stopPropagation();
5440
+ style: { width: "80px", flexShrink: 0 },
5441
+ onKeyDownCapture: stepFontSize ? (e) => handleFontSizeArrowCapture(e, stepFontSize) : void 0
5442
+ },
5443
+ /* @__PURE__ */ react_default.createElement(
5444
+ Number_default,
5445
+ {
5446
+ "aria-label": "Font size in pixels",
5447
+ value: isFontSizeMixed ? void 0 : currentFontSize,
5448
+ onFocus: () => {
4846
5449
  fontSizeDirtyRef.current = false;
4847
- handleFormat("fontSize", `${currentFontSize}px`);
4848
- }
4849
- if (isFontSizeMixed) {
4850
- if (e.key === "ArrowUp") {
4851
- e.preventDefault();
4852
- stepFontSize == null ? void 0 : stepFontSize(2);
4853
- } else if (e.key === "ArrowDown") {
4854
- e.preventDefault();
4855
- stepFontSize == null ? void 0 : stepFontSize(-2);
4856
- }
4857
- }
4858
- },
4859
- onBlur: () => {
4860
- if (fontSizeDirtyRef.current && currentFontSize) {
4861
- handleFormat("fontSize", `${currentFontSize}px`);
4862
- }
4863
- fontSizeDirtyRef.current = false;
4864
- },
4865
- min: 8,
4866
- max: 200,
4867
- step: 1,
4868
- inline: true
4869
- }
4870
- )))), /* @__PURE__ */ react_default.createElement(ColorRow, null, /* @__PURE__ */ react_default.createElement(ControlGroup_default, { label: "Font color", labelPosition: "top" }, /* @__PURE__ */ react_default.createElement(
5450
+ },
5451
+ onChange: onFontSizeChange,
5452
+ onKeyDown: (e) => {
5453
+ handleFontSizeInputKeyDown(e, {
5454
+ currentFontSize,
5455
+ fontSizeDirtyRef,
5456
+ handleFormat
5457
+ });
5458
+ },
5459
+ onBlur: () => {
5460
+ handleFontSizeInputBlur({ currentFontSize, fontSizeDirtyRef, handleFormat });
5461
+ },
5462
+ min: 8,
5463
+ max: 200,
5464
+ step: 1,
5465
+ inline: true
5466
+ }
5467
+ )
5468
+ ))), /* @__PURE__ */ react_default.createElement(ColorRow, null, /* @__PURE__ */ react_default.createElement(ControlGroup_default, { label: "Font color", labelPosition: "top" }, /* @__PURE__ */ react_default.createElement(
4871
5469
  MixedColorWrapper,
4872
5470
  {
4873
5471
  $isMixed: isColorMixed,
4874
- onClick: () => {
4875
- if (isColorMixed) focusMixedSwatch('[data-test="textbox-swatch"]');
4876
- }
5472
+ onClick: () => handleMixedSwatchClick(isColorMixed)
4877
5473
  },
4878
5474
  /* @__PURE__ */ react_default.createElement(
4879
5475
  Color_default,
@@ -4888,9 +5484,7 @@ var EditorPanel = ({
4888
5484
  MixedColorWrapper,
4889
5485
  {
4890
5486
  $isMixed: isHighlightMixed,
4891
- onClick: () => {
4892
- if (isHighlightMixed) focusMixedSwatch('[data-test="textbox-swatch"]');
4893
- }
5487
+ onClick: () => handleMixedSwatchClick(isHighlightMixed)
4894
5488
  },
4895
5489
  /* @__PURE__ */ react_default.createElement(
4896
5490
  Color_default,
@@ -4970,14 +5564,7 @@ var EditorPanel = ({
4970
5564
  $isActive: false,
4971
5565
  appearance: "secondary",
4972
5566
  onMouseDown: preventDefaultMouseDown,
4973
- onClick: () => {
4974
- resetToDefault == null ? void 0 : resetToDefault();
4975
- if (wasMouseRef.current) {
4976
- setTimeout(() => {
4977
- focusActiveEditable();
4978
- }, 0);
4979
- }
4980
- },
5567
+ onClick: () => handleResetToDefault(resetToDefault, wasMouseRef),
4981
5568
  icon: /* @__PURE__ */ react_default.createElement(ArrowTurnBackLeft_default, null),
4982
5569
  "aria-label": "Reset to default"
4983
5570
  }
@@ -4988,32 +5575,37 @@ var EditorPanel = ({
4988
5575
  anchor: linkButtonRef.current,
4989
5576
  onRequestClose: handleLinkPopoverClose
4990
5577
  },
4991
- /* @__PURE__ */ react_default.createElement(LinkPopoverContent, { ref: linkPopoverRef, onKeyDown: handleLinkKeyDown }, /* @__PURE__ */ react_default.createElement(ControlGroup_default, { label: "Text", labelPosition: "top" }, /* @__PURE__ */ react_default.createElement(
4992
- Text_default,
4993
- {
4994
- value: linkText,
4995
- onChange: (_e, { value: v }) => setLinkText(v),
4996
- placeholder: "Link text"
4997
- }
4998
- )), /* @__PURE__ */ react_default.createElement(ControlGroup_default, { label: "URL", labelPosition: "top" }, /* @__PURE__ */ react_default.createElement(
4999
- Text_default,
5578
+ /* @__PURE__ */ react_default.createElement(
5579
+ LinkPopoverContent,
5000
5580
  {
5001
- value: linkUrl,
5002
- onChange: (_e, { value: v }) => setLinkUrl(v),
5003
- placeholder: "https://..."
5004
- }
5005
- )), /* @__PURE__ */ react_default.createElement(Row, null, /* @__PURE__ */ react_default.createElement(Button_default, { appearance: "primary", onClick: handleLinkSave, label: "Save" }), linkIsActive && /* @__PURE__ */ react_default.createElement(Button_default, { onClick: handleLinkRemove, label: "Remove" }), /* @__PURE__ */ react_default.createElement(Button_default, { onClick: handleLinkPopoverClose, label: "Cancel" })))
5581
+ ref: linkPopoverRef,
5582
+ onKeyDown: handleLinkKeyDown,
5583
+ "data-test": "link-popover-content"
5584
+ },
5585
+ /* @__PURE__ */ react_default.createElement(ControlGroup_default, { label: "Text", labelPosition: "top" }, /* @__PURE__ */ react_default.createElement(
5586
+ Text_default,
5587
+ {
5588
+ value: linkText,
5589
+ onChange: (_e, { value: v }) => setLinkText(v),
5590
+ placeholder: "Link text"
5591
+ }
5592
+ )),
5593
+ /* @__PURE__ */ react_default.createElement(ControlGroup_default, { label: "URL", labelPosition: "top" }, /* @__PURE__ */ react_default.createElement(
5594
+ Text_default,
5595
+ {
5596
+ value: linkUrl,
5597
+ onChange: (_e, { value: v }) => setLinkUrl(v),
5598
+ placeholder: "https://..."
5599
+ }
5600
+ )),
5601
+ /* @__PURE__ */ react_default.createElement(Row, null, /* @__PURE__ */ react_default.createElement(Button_default, { appearance: "primary", onClick: handleLinkSave, label: "Save" }), linkIsActive && /* @__PURE__ */ react_default.createElement(Button_default, { onClick: handleLinkRemove, label: "Remove" }), /* @__PURE__ */ react_default.createElement(Button_default, { onClick: handleLinkPopoverClose, label: "Cancel" }))
5602
+ )
5006
5603
  ), /* @__PURE__ */ react_default.createElement(ControlGroup_default, { label: "Alignment", labelPosition: "top" }, /* @__PURE__ */ react_default.createElement(AlignmentSection, null, /* @__PURE__ */ react_default.createElement(HorizontalAlignmentRadioBar, null, /* @__PURE__ */ react_default.createElement(
5007
5604
  RadioBar_default,
5008
5605
  {
5009
5606
  value: align,
5010
5607
  onChange: (_e, { value: val }) => {
5011
- const newAlign = val;
5012
- setAlign(newAlign);
5013
- if (newAlign === "left") handleFormat("justifyLeft");
5014
- else if (newAlign === "center") handleFormat("justifyCenter");
5015
- else if (newAlign === "right") handleFormat("justifyRight");
5016
- else if (newAlign === "justify") handleFormat("justifyFull");
5608
+ handleAlignmentChange(val, setAlign, handleFormat);
5017
5609
  }
5018
5610
  },
5019
5611
  /* @__PURE__ */ react_default.createElement(
@@ -5081,18 +5673,11 @@ var EditorPanel = ({
5081
5673
  onChange: handleLineSpacingChange,
5082
5674
  onBlur: handleLineSpacingBlur,
5083
5675
  onKeyDown: (e) => {
5084
- if (e.key === "Enter") {
5085
- handleLineSpacingBlur();
5086
- }
5087
- if (isLineHeightMixed && stepLineSpacing) {
5088
- if (e.key === "ArrowUp") {
5089
- e.preventDefault();
5090
- stepLineSpacing(1);
5091
- } else if (e.key === "ArrowDown") {
5092
- e.preventDefault();
5093
- stepLineSpacing(-1);
5094
- }
5095
- }
5676
+ handleLineSpacingKeyDown(e, {
5677
+ isLineHeightMixed,
5678
+ stepLineSpacing,
5679
+ handleLineSpacingBlur
5680
+ });
5096
5681
  },
5097
5682
  min: 100,
5098
5683
  max: 300,
@@ -5107,6 +5692,17 @@ var EditorPanel = ({
5107
5692
  };
5108
5693
 
5109
5694
  // src/RichText/PureRichText/RichTextStyles.tsx
5695
+ function justifyForVerticalAlign(align) {
5696
+ switch (align) {
5697
+ case "bottom":
5698
+ return "flex-end";
5699
+ case "middle":
5700
+ return "center";
5701
+ case "top":
5702
+ default:
5703
+ return "flex-start";
5704
+ }
5705
+ }
5110
5706
  var PureRichTextContainer = styled_components_default.div`
5111
5707
  width: 100%;
5112
5708
  height: 100%;
@@ -5136,27 +5732,57 @@ var PureRichTextContainer = styled_components_default.div`
5136
5732
  ${(props) => props.$hasEventHandlers && !props.$isTextEditing && styled_components_exports.css`
5137
5733
  cursor: pointer;
5138
5734
  `}
5735
+ /* Edit-mode only: hovering a selected block's edges/padding shows grab (PowerPoint-style).
5736
+ EditorWrapper re-asserts its own cursor over the text content. */
5737
+ ${(props) => props.$isEditMode && !props.$isTextEditing && styled_components_exports.css`
5738
+ [data-selected='true'] & {
5739
+ cursor: grab;
5740
+ }
5741
+ `}
5139
5742
  `;
5140
5743
  var DrilldownButton = styled_components_default(Button_default)`
5141
5744
  ${themes_exports.mixins.skipLink()}
5142
- /**
5143
- * Override the secondary Button's transparent default so the skip-link is visible when focused.
5144
- */
5745
+ /* Override the secondary Button's transparent default so the skip-link is visible when focused. */
5145
5746
  &:not([disabled], [aria-disabled='true']) {
5146
5747
  background-color: ${themes_exports.variables.backgroundColorSection};
5147
5748
  }
5148
5749
  `;
5149
5750
  var EditorWrapper = styled_components_default.div`
5150
5751
  width: 100%;
5752
+ /* Fill the container's content box so a click anywhere over the text region enters editing, not
5753
+ just the top. Vertical alignment moves here from the container to keep text top/middle/bottom. */
5754
+ flex: 1 1 auto;
5151
5755
  min-height: 0;
5152
5756
  max-height: 100%;
5757
+ display: flex;
5758
+ flex-direction: column;
5153
5759
  overflow: auto;
5154
- cursor: ${(props) => props.$isTextEditing ? "text" : "default"};
5760
+ /* Cursor over text: editing -> text; view mode w/ interaction -> pointer; view mode plain -> text;
5761
+ edit mode not editing -> default (grab layered below when selected). */
5762
+ cursor: ${(props) => {
5763
+ if (props.$isTextEditing) return "text";
5764
+ if (props.$hasEventHandlers && !props.$isEditMode) return "pointer";
5765
+ if (!props.$isEditMode) return "text";
5766
+ return "default";
5767
+ }};
5768
+
5769
+ /* Selected in edit mode (not editing): grab cursor over the whole block including text, so it
5770
+ doesn't flip to default crossing from padding into text. View mode keeps text/pointer. */
5771
+ ${(props) => props.$isEditMode && !props.$isTextEditing && styled_components_exports.css`
5772
+ [data-selected='true'] & {
5773
+ cursor: grab;
5774
+ }
5775
+ `}
5155
5776
 
5156
5777
  /* Styling for the Slate editor */
5157
5778
  [data-slate-editor] {
5158
5779
  outline: none;
5780
+ /* Fill the stretched wrapper so a click anywhere enters editing, but keep the editable as the
5781
+ vertical-align flex column: the stretched wrapper has no free space to align short content. */
5159
5782
  min-height: 100%;
5783
+ display: flex;
5784
+ flex-direction: column;
5785
+ justify-content: ${(props) => justifyForVerticalAlign(props.$verticalAlign)};
5160
5786
  }
5161
5787
 
5162
5788
  /* Underline styling - match text color */
@@ -5221,8 +5847,179 @@ var LiveRegion = styled_components_default.div`
5221
5847
  border: 0;
5222
5848
  `;
5223
5849
 
5850
+ // src/RichText/PureRichText/utils/fontSize.ts
5851
+ var getFontSizeInPx = (fontSize, customFontSize) => {
5852
+ if (fontSize === "custom" && customFontSize) {
5853
+ return customFontSize;
5854
+ }
5855
+ return FONT_SIZE_PRESETS[fontSize || "default"];
5856
+ };
5857
+
5224
5858
  // src/RichText/PureRichText/renderers/ElementRenderer.tsx
5225
- var createElementRenderer = (isEditMode, defaultLineHeight) => {
5859
+ function isBrokenHref(href) {
5860
+ if (!href) return false;
5861
+ if (href.startsWith("/")) return false;
5862
+ return !isOpenableUrl(href);
5863
+ }
5864
+ function frameworkFlagsHref(href, onLinkOpen) {
5865
+ if (!onLinkOpen) return false;
5866
+ return !/\s/.test(href) && /^https?:\/\//i.test(href);
5867
+ }
5868
+ function frameworkHandlesHref(href) {
5869
+ if (/\s/.test(href)) return false;
5870
+ return /^https?:\/\//i.test(href) || /^\/(?!\/)/.test(href);
5871
+ }
5872
+ var _a;
5873
+ var platformString = typeof navigator !== "undefined" && (((_a = navigator.userAgentData) == null ? void 0 : _a.platform) || navigator.platform) || "";
5874
+ var isMacPlatform = /Mac|iP(hone|ad|od)/.test(platformString);
5875
+ var OVERLAY_STYLE = {
5876
+ position: "fixed",
5877
+ transform: "translateY(-100%) translateY(-6px)",
5878
+ zIndex: 2147483647,
5879
+ maxWidth: 320,
5880
+ padding: "4px 8px",
5881
+ borderRadius: 4,
5882
+ background: "#3c444d",
5883
+ color: "#fff",
5884
+ fontSize: 12,
5885
+ lineHeight: 1.4,
5886
+ overflowWrap: "anywhere",
5887
+ pointerEvents: "none",
5888
+ boxShadow: "0 2px 8px rgba(0,0,0,0.4)"
5889
+ };
5890
+ var styleBlock = { display: "block" };
5891
+ var styleBlockOpacity = { display: "block", opacity: 0.75 };
5892
+ var LinkFollowTooltip = ({
5893
+ show,
5894
+ pos,
5895
+ href
5896
+ }) => {
5897
+ const { fontFamily } = (0, themes_exports.useSplunkTheme)();
5898
+ if (!show || !pos || typeof document === "undefined") return null;
5899
+ return (0, react_dom_exports.createPortal)(
5900
+ /* @__PURE__ */ react_exports.createElement("span", { contentEditable: false, style: __spreadProps(__spreadValues({}, OVERLAY_STYLE), { top: pos.top, left: pos.left, fontFamily }) }, /* @__PURE__ */ react_exports.createElement("span", { style: styleBlock }, href), /* @__PURE__ */ react_exports.createElement("span", { style: styleBlockOpacity }, isMacPlatform ? "\u2318" : "Ctrl", "+click to open")),
5901
+ document.body
5902
+ );
5903
+ };
5904
+ var BrokenLinkNote = ({ pos, href }) => {
5905
+ const { fontFamily } = (0, themes_exports.useSplunkTheme)();
5906
+ if (!pos || typeof document === "undefined") return null;
5907
+ return (0, react_dom_exports.createPortal)(
5908
+ /* @__PURE__ */ react_exports.createElement(
5909
+ "span",
5910
+ {
5911
+ role: "alert",
5912
+ contentEditable: false,
5913
+ style: __spreadProps(__spreadValues({}, OVERLAY_STYLE), { top: pos.top, left: pos.left, fontFamily })
5914
+ },
5915
+ /* @__PURE__ */ react_exports.createElement("span", { style: styleBlock }, "This link can't be opened."),
5916
+ /* @__PURE__ */ react_exports.createElement("span", { style: styleBlockOpacity }, href)
5917
+ ),
5918
+ document.body
5919
+ );
5920
+ };
5921
+ function handleAnchorMouseDown(e, ctx) {
5922
+ if (ctx.isEditMode && !e.metaKey && !e.ctrlKey) e.preventDefault();
5923
+ }
5924
+ function handleAnchorMouseLeave(ctx) {
5925
+ if (ctx.isEditMode) ctx.hideTooltip();
5926
+ ctx.clearBrokenNote();
5927
+ }
5928
+ function handleAnchorClick(e, ctx) {
5929
+ if (ctx.isEditMode) {
5930
+ e.preventDefault();
5931
+ if (e.metaKey || e.ctrlKey) {
5932
+ e.stopPropagation();
5933
+ ctx.activateLink(e.currentTarget);
5934
+ }
5935
+ return;
5936
+ }
5937
+ e.stopPropagation();
5938
+ if (ctx.showBrokenNote || ctx.routeToFramework) {
5939
+ e.preventDefault();
5940
+ ctx.activateLink(e.currentTarget);
5941
+ }
5942
+ }
5943
+ function handleAnchorKeyDown(e, ctx) {
5944
+ if (!ctx.isEditMode && e.key === "Enter") {
5945
+ e.preventDefault();
5946
+ e.stopPropagation();
5947
+ ctx.activateLink(e.currentTarget);
5948
+ }
5949
+ }
5950
+ var LinkElement = ({ attributes, children, isEditMode, url, nameToValue, onLinkOpen }) => {
5951
+ const normalizedHref = resolveLinkHref(url, nameToValue);
5952
+ const broken = isBrokenHref(normalizedHref);
5953
+ const showBrokenNote = broken && !frameworkFlagsHref(normalizedHref, onLinkOpen);
5954
+ const routeToFramework = !!onLinkOpen && frameworkHandlesHref(normalizedHref);
5955
+ const [tooltipPos, setTooltipPos] = (0, react_exports.useState)(null);
5956
+ const [brokenPos, setBrokenPos] = (0, react_exports.useState)(null);
5957
+ const dismissTimer = (0, react_exports.useRef)();
5958
+ const flagBroken = (0, react_exports.useCallback)((el) => {
5959
+ const rect = el.getBoundingClientRect();
5960
+ setBrokenPos({ top: rect.top, left: rect.left });
5961
+ }, []);
5962
+ (0, react_exports.useEffect)(() => {
5963
+ if (!brokenPos) return void 0;
5964
+ dismissTimer.current = setTimeout(() => setBrokenPos(null), 2500);
5965
+ return () => clearTimeout(dismissTimer.current);
5966
+ }, [brokenPos]);
5967
+ const showTooltip = (0, react_exports.useCallback)((ev) => {
5968
+ const rect = ev.currentTarget.getBoundingClientRect();
5969
+ setTooltipPos({ top: rect.top, left: rect.left });
5970
+ }, []);
5971
+ const hideTooltip = (0, react_exports.useCallback)(() => setTooltipPos(null), []);
5972
+ const activateLink = (0, react_exports.useCallback)(
5973
+ (el) => {
5974
+ if (showBrokenNote) {
5975
+ flagBroken(el);
5976
+ return;
5977
+ }
5978
+ openHref(normalizedHref, onLinkOpen);
5979
+ },
5980
+ [showBrokenNote, flagBroken, normalizedHref, onLinkOpen]
5981
+ );
5982
+ const clearBrokenNote = (0, react_exports.useCallback)(() => setBrokenPos(null), []);
5983
+ const ctx = {
5984
+ isEditMode,
5985
+ showBrokenNote,
5986
+ routeToFramework,
5987
+ activateLink,
5988
+ hideTooltip,
5989
+ clearBrokenNote
5990
+ };
5991
+ return /* @__PURE__ */ react_exports.createElement(
5992
+ "a",
5993
+ __spreadProps(__spreadValues({
5994
+ href: normalizedHref,
5995
+ style: { display: "inline" }
5996
+ }, attributes), {
5997
+ target: isEditMode || routeToFramework || broken ? void 0 : "_blank",
5998
+ rel: isEditMode || routeToFramework ? void 0 : "noopener noreferrer",
5999
+ tabIndex: isEditMode ? void 0 : 0,
6000
+ onMouseDown: (e) => handleAnchorMouseDown(e, ctx),
6001
+ onMouseEnter: isEditMode ? showTooltip : void 0,
6002
+ onMouseLeave: () => handleAnchorMouseLeave(ctx),
6003
+ onClick: (e) => handleAnchorClick(e, ctx),
6004
+ onKeyDown: (e) => handleAnchorKeyDown(e, ctx)
6005
+ }),
6006
+ children,
6007
+ /* @__PURE__ */ react_exports.createElement(LinkFollowTooltip, { show: isEditMode, pos: tooltipPos, href: normalizedHref }),
6008
+ /* @__PURE__ */ react_exports.createElement(BrokenLinkNote, { pos: brokenPos, href: normalizedHref })
6009
+ );
6010
+ };
6011
+ function openHref(href, onLinkOpen) {
6012
+ if (!href) return;
6013
+ if (onLinkOpen && frameworkHandlesHref(href)) {
6014
+ onLinkOpen(href);
6015
+ return;
6016
+ }
6017
+ try {
6018
+ window.open(href, "_blank", "noopener,noreferrer");
6019
+ } catch (e) {
6020
+ }
6021
+ }
6022
+ var createElementRenderer = (isEditMode, defaultLineHeight, nameToValue, onLinkOpen) => {
5226
6023
  return function ElementRenderer({ attributes, children, element }) {
5227
6024
  const customElement = element;
5228
6025
  const baseStyle = {
@@ -5247,36 +6044,23 @@ var createElementRenderer = (isEditMode, defaultLineHeight) => {
5247
6044
  if (firstLeaf == null ? void 0 : firstLeaf.fontSize) {
5248
6045
  listItemStyle.fontSize = firstLeaf.fontSize;
5249
6046
  }
5250
- const fontSize = parseInt(String((firstLeaf == null ? void 0 : firstLeaf.fontSize) || "0"), 10);
6047
+ const fontSize = Number.parseInt(String((firstLeaf == null ? void 0 : firstLeaf.fontSize) || "0"), 10);
5251
6048
  if (customElement.align === "center" || customElement.align === "right" || fontSize > 24) {
5252
6049
  listItemStyle.listStylePosition = "inside";
5253
6050
  }
5254
6051
  return /* @__PURE__ */ react_exports.createElement("li", __spreadValues({ style: listItemStyle }, attributes), children);
5255
6052
  }
5256
6053
  case "link": {
5257
- const normalizedHref = normalizeUrl(customElement.url || "");
5258
6054
  return /* @__PURE__ */ react_exports.createElement(
5259
- "a",
5260
- __spreadProps(__spreadValues({
5261
- href: normalizedHref,
5262
- style: { display: "inline" }
5263
- }, attributes), {
5264
- target: isEditMode ? void 0 : "_blank",
5265
- rel: isEditMode ? void 0 : "noopener noreferrer",
5266
- tabIndex: isEditMode ? void 0 : 0,
5267
- onClick: (e) => {
5268
- if (isEditMode) {
5269
- e.preventDefault();
5270
- return;
5271
- }
5272
- e.stopPropagation();
5273
- },
5274
- onKeyDown: (e) => {
5275
- if (!isEditMode && e.key === "Enter") {
5276
- window.open(normalizedHref, "_blank", "noopener,noreferrer");
5277
- }
5278
- }
5279
- }),
6055
+ LinkElement,
6056
+ {
6057
+ attributes,
6058
+ element,
6059
+ isEditMode,
6060
+ url: customElement.url || "",
6061
+ nameToValue,
6062
+ onLinkOpen
6063
+ },
5280
6064
  children
5281
6065
  );
5282
6066
  }
@@ -5318,18 +6102,60 @@ var Leaf = ({ attributes, children, leaf }) => {
5318
6102
  if (customLeaf.strikethrough) {
5319
6103
  content = /* @__PURE__ */ react_exports.createElement("s", null, content);
5320
6104
  }
5321
- return /* @__PURE__ */ react_exports.createElement("span", __spreadProps(__spreadValues({}, attributes), { style }), content);
5322
- };
5323
-
5324
- // src/RichText/PureRichText/utils/fontSize.ts
5325
- var getFontSizeInPx = (fontSize, customFontSize) => {
5326
- if (fontSize === "custom" && customFontSize) {
5327
- return customFontSize;
6105
+ if (customLeaf.tokenName) {
6106
+ return /* @__PURE__ */ react_exports.createElement("span", __spreadProps(__spreadValues({}, attributes), { style }), /* @__PURE__ */ react_exports.createElement("span", { "data-token-name": customLeaf.isRawToken ? customLeaf.tokenName : void 0 }, content));
5328
6107
  }
5329
- return FONT_SIZE_PRESETS[fontSize || "default"];
6108
+ return /* @__PURE__ */ react_exports.createElement("span", __spreadProps(__spreadValues({}, attributes), { style }), content);
5330
6109
  };
5331
6110
 
5332
6111
  // src/RichText/PureRichText/hooks/useEditorSetup.ts
6112
+ function pointAfterLinkInBlock(e, linkPath) {
6113
+ const blockEntry = slate_exports.Editor.above(e, {
6114
+ at: linkPath,
6115
+ match: (n) => !slate_exports.Editor.isEditor(n) && slate_exports.Element.isElement(n) && slate_exports.Editor.isBlock(e, n)
6116
+ });
6117
+ const after = slate_exports.Editor.after(e, linkPath);
6118
+ if (after && blockEntry && slate_exports.Path.isDescendant(after.path, blockEntry[1])) {
6119
+ return after;
6120
+ }
6121
+ return null;
6122
+ }
6123
+ function pointBeforeLinkInBlock(e, linkPath) {
6124
+ const blockEntry = slate_exports.Editor.above(e, {
6125
+ at: linkPath,
6126
+ match: (n) => !slate_exports.Editor.isEditor(n) && slate_exports.Element.isElement(n) && slate_exports.Editor.isBlock(e, n)
6127
+ });
6128
+ const before = slate_exports.Editor.before(e, linkPath);
6129
+ if (before && blockEntry && slate_exports.Path.isDescendant(before.path, blockEntry[1])) {
6130
+ return before;
6131
+ }
6132
+ return null;
6133
+ }
6134
+ function exitLinkStartBeforeInsert(e) {
6135
+ const { selection } = e;
6136
+ if (!selection || !slate_exports.Range.isCollapsed(selection)) return;
6137
+ const above = slate_exports.Editor.above(e, {
6138
+ match: (n) => !slate_exports.Editor.isEditor(n) && slate_exports.Element.isElement(n) && n.type === "link"
6139
+ });
6140
+ if (!above) return;
6141
+ const [, linkPath] = above;
6142
+ if (!slate_exports.Editor.isStart(e, selection.anchor, linkPath)) return;
6143
+ let before = pointBeforeLinkInBlock(e, linkPath);
6144
+ if (before) {
6145
+ const prevLink = slate_exports.Editor.above(e, {
6146
+ at: before,
6147
+ match: (n) => !slate_exports.Editor.isEditor(n) && slate_exports.Element.isElement(n) && n.type === "link"
6148
+ });
6149
+ if (prevLink) before = null;
6150
+ }
6151
+ if (!before) {
6152
+ slate_exports.Transforms.insertNodes(e, { text: "" }, { at: linkPath });
6153
+ before = pointBeforeLinkInBlock(e, slate_exports.Path.next(linkPath));
6154
+ }
6155
+ if (before) {
6156
+ slate_exports.Transforms.select(e, before);
6157
+ }
6158
+ }
5333
6159
  function exitLinkBeforeInsert(e) {
5334
6160
  const { selection } = e;
5335
6161
  if (!selection || !slate_exports.Range.isCollapsed(selection)) return;
@@ -5338,8 +6164,17 @@ function exitLinkBeforeInsert(e) {
5338
6164
  });
5339
6165
  if (!above) return;
5340
6166
  const [, linkPath] = above;
6167
+ if (slate_exports.Editor.isStart(e, selection.anchor, linkPath)) {
6168
+ exitLinkStartBeforeInsert(e);
6169
+ return;
6170
+ }
5341
6171
  if (!slate_exports.Editor.isEnd(e, selection.anchor, linkPath)) return;
5342
- const after = slate_exports.Editor.after(e, linkPath);
6172
+ let after = pointAfterLinkInBlock(e, linkPath);
6173
+ if (!after) {
6174
+ const trailingPath = slate_exports.Path.next(linkPath);
6175
+ slate_exports.Transforms.insertNodes(e, { text: "" }, { at: trailingPath });
6176
+ after = pointAfterLinkInBlock(e, linkPath);
6177
+ }
5343
6178
  if (after) {
5344
6179
  slate_exports.Transforms.select(e, after);
5345
6180
  }
@@ -5419,7 +6254,7 @@ function getTokenRangeAtPoint(e, point) {
5419
6254
  const [node, path] = slate_exports.Editor.node(e, point);
5420
6255
  if (!slate_exports.Text.isText(node)) return null;
5421
6256
  const custom = node;
5422
- if (!custom.tokenName) return null;
6257
+ if (!custom.tokenName && !custom.isEscapedDollar) return null;
5423
6258
  return {
5424
6259
  anchor: { path, offset: 0 },
5425
6260
  focus: { path, offset: custom.text.length }
@@ -5437,9 +6272,26 @@ function getLinkRangeAtPoint(e, point) {
5437
6272
  function getAtomicRangeAtPoint(e, point) {
5438
6273
  return getTokenRangeAtPoint(e, point) || getLinkRangeAtPoint(e, point);
5439
6274
  }
6275
+ function deleteAtomicRange(e, point, range2) {
6276
+ const linkEntry = slate_exports.Editor.above(e, {
6277
+ at: point,
6278
+ match: (n) => !slate_exports.Editor.isEditor(n) && slate_exports.Element.isElement(n) && n.type === "link"
6279
+ });
6280
+ if (linkEntry) {
6281
+ const [, linkPath] = linkEntry;
6282
+ const before = slate_exports.Editor.before(e, slate_exports.Editor.start(e, linkPath));
6283
+ const after = slate_exports.Editor.after(e, slate_exports.Editor.end(e, linkPath));
6284
+ if (before) slate_exports.Transforms.select(e, before);
6285
+ else if (after) slate_exports.Transforms.select(e, after);
6286
+ slate_exports.Transforms.removeNodes(e, { at: linkPath });
6287
+ return;
6288
+ }
6289
+ slate_exports.Transforms.delete(e, { at: range2 });
6290
+ }
5440
6291
  function isStrictlyInsideAtomic(e, point) {
5441
6292
  const [node] = slate_exports.Editor.node(e, point);
5442
- if (slate_exports.Text.isText(node) && node.tokenName) {
6293
+ const custom = node;
6294
+ if (slate_exports.Text.isText(node) && (custom.tokenName || custom.isEscapedDollar)) {
5443
6295
  return point.offset > 0 && point.offset < node.text.length;
5444
6296
  }
5445
6297
  const linkEntry = slate_exports.Editor.above(e, {
@@ -5460,16 +6312,16 @@ function getPointAfterAtomic(e, point) {
5460
6312
  });
5461
6313
  if (linkEntry) {
5462
6314
  const [, linkPath] = linkEntry;
5463
- return slate_exports.Editor.after(e, linkPath) || null;
6315
+ return pointAfterLinkInBlock(e, linkPath);
5464
6316
  }
5465
6317
  const tokenRange = getTokenRangeAtPoint(e, point);
5466
6318
  if (tokenRange) return tokenRange.focus;
5467
6319
  return null;
5468
6320
  }
5469
6321
  function getAtomicExpansion(atomicRange, isAnchorEndpoint, isBackward) {
5470
- const adjustAnchor = isAnchorEndpoint ? !isBackward : isBackward;
5471
- const target = adjustAnchor ? atomicRange.anchor : atomicRange.focus;
5472
- return { adjustAnchor, target };
6322
+ const isLeftEnd = isAnchorEndpoint ? !isBackward : isBackward;
6323
+ const target = isLeftEnd ? atomicRange.anchor : atomicRange.focus;
6324
+ return { adjustAnchor: isAnchorEndpoint, target };
5473
6325
  }
5474
6326
  function snapEndpointToAtomic(e, point, isAnchorEndpoint, anchor, focus, isBackward) {
5475
6327
  const atomicRange = getAtomicRangeAtPoint(e, point);
@@ -5514,11 +6366,27 @@ function expandSelectionToAtomic(e) {
5514
6366
  }
5515
6367
  }
5516
6368
  function moveCursorPastAtomicIfNeeded(e) {
6369
+ var _a2;
5517
6370
  if (!e.selection || !slate_exports.Range.isCollapsed(e.selection)) return;
5518
- if (!isStrictlyInsideAtomic(e, e.selection.anchor)) return;
5519
- const after = getPointAfterAtomic(e, e.selection.anchor);
5520
- if (after) {
5521
- slate_exports.Transforms.select(e, after);
6371
+ const { anchor } = e.selection;
6372
+ const [node] = slate_exports.Editor.node(e, anchor);
6373
+ if (slate_exports.Text.isText(node) && (node.tokenName || node.isEscapedDollar)) {
6374
+ if (anchor.offset > 0 && anchor.offset < node.text.length) {
6375
+ const endPoint = { path: anchor.path, offset: node.text.length };
6376
+ e.selection = { anchor: endPoint, focus: endPoint };
6377
+ }
6378
+ const currentMarks = (_a2 = slate_exports.Editor.marks(e)) != null ? _a2 : {};
6379
+ const marksWithoutToken = __spreadValues({}, currentMarks);
6380
+ delete marksWithoutToken.tokenName;
6381
+ delete marksWithoutToken.tokenOccurrence;
6382
+ delete marksWithoutToken.isEscapedDollar;
6383
+ e.marks = marksWithoutToken;
6384
+ return;
6385
+ }
6386
+ if (!isStrictlyInsideAtomic(e, anchor)) return;
6387
+ const afterAtomic = getPointAfterAtomic(e, anchor);
6388
+ if (afterAtomic) {
6389
+ slate_exports.Transforms.select(e, afterAtomic);
5522
6390
  }
5523
6391
  }
5524
6392
  function tryExitEmptyListItem(e) {
@@ -5537,22 +6405,63 @@ function tryExitEmptyListItem(e) {
5537
6405
  slate_exports.Transforms.setNodes(e, { type: "paragraph" });
5538
6406
  return true;
5539
6407
  }
6408
+ function blockPathAt(ed, point) {
6409
+ const above = slate_exports.Editor.above(ed, {
6410
+ at: point,
6411
+ match: (n) => !slate_exports.Editor.isEditor(n) && slate_exports.Element.isElement(n) && slate_exports.Editor.isBlock(ed, n)
6412
+ });
6413
+ return above ? above[1] : null;
6414
+ }
6415
+ function inSameBlock(ed, a, b) {
6416
+ const pa = blockPathAt(ed, a);
6417
+ const pb = blockPathAt(ed, b);
6418
+ return pa !== null && pb !== null && slate_exports.Path.equals(pa, pb);
6419
+ }
6420
+ function atomicRangeBefore(ed, point) {
6421
+ const before = slate_exports.Editor.before(ed, point);
6422
+ if (!before || !inSameBlock(ed, point, before)) return null;
6423
+ const direct = getAtomicRangeAtPoint(ed, before);
6424
+ if (direct) return { range: direct, at: before };
6425
+ const [node] = slate_exports.Editor.node(ed, before.path);
6426
+ if (slate_exports.Text.isText(node) && node.text === "") {
6427
+ const prior = slate_exports.Editor.before(ed, before);
6428
+ if (prior && inSameBlock(ed, point, prior)) {
6429
+ const priorRange = getAtomicRangeAtPoint(ed, prior);
6430
+ if (priorRange) return { range: priorRange, at: prior };
6431
+ }
6432
+ }
6433
+ return null;
6434
+ }
6435
+ function atomicRangeAfter(ed, point) {
6436
+ const after = slate_exports.Editor.after(ed, point);
6437
+ if (!after || !inSameBlock(ed, point, after)) return null;
6438
+ const direct = getAtomicRangeAtPoint(ed, after);
6439
+ if (direct) return { range: direct, at: after };
6440
+ const [node] = slate_exports.Editor.node(ed, after.path);
6441
+ if (slate_exports.Text.isText(node) && node.text === "") {
6442
+ const next = slate_exports.Editor.after(ed, after);
6443
+ if (next && inSameBlock(ed, point, next)) {
6444
+ const nextRange = getAtomicRangeAtPoint(ed, next);
6445
+ if (nextRange) return { range: nextRange, at: next };
6446
+ }
6447
+ }
6448
+ return null;
6449
+ }
5540
6450
  function tryDeleteAtomicBackward(ed, anchor) {
5541
6451
  if (isStrictlyInsideAtomic(ed, anchor)) {
5542
6452
  const range2 = getAtomicRangeAtPoint(ed, anchor);
5543
- if (range2) slate_exports.Transforms.delete(ed, { at: range2 });
6453
+ if (range2) deleteAtomicRange(ed, anchor, range2);
5544
6454
  return true;
5545
6455
  }
5546
6456
  const currentRange = getAtomicRangeAtPoint(ed, anchor);
5547
6457
  if (currentRange && slate_exports.Point.equals(anchor, currentRange.focus)) {
5548
- slate_exports.Transforms.delete(ed, { at: currentRange });
6458
+ deleteAtomicRange(ed, anchor, currentRange);
5549
6459
  return true;
5550
6460
  }
5551
- if (currentRange) return false;
5552
- const before = slate_exports.Editor.before(ed, anchor);
5553
- const prevRange = before ? getAtomicRangeAtPoint(ed, before) : null;
5554
- if (!prevRange) return false;
5555
- slate_exports.Transforms.delete(ed, { at: prevRange });
6461
+ if (currentRange && !slate_exports.Point.equals(anchor, currentRange.anchor)) return false;
6462
+ const prev = atomicRangeBefore(ed, anchor);
6463
+ if (!prev) return false;
6464
+ deleteAtomicRange(ed, prev.at, prev.range);
5556
6465
  return true;
5557
6466
  }
5558
6467
  function tryUnwrapListItem(ed, anchor) {
@@ -5584,19 +6493,18 @@ function tryUnwrapListItem(ed, anchor) {
5584
6493
  function tryDeleteAtomicForward(ed, anchor) {
5585
6494
  if (isStrictlyInsideAtomic(ed, anchor)) {
5586
6495
  const range2 = getAtomicRangeAtPoint(ed, anchor);
5587
- if (range2) slate_exports.Transforms.delete(ed, { at: range2 });
6496
+ if (range2) deleteAtomicRange(ed, anchor, range2);
5588
6497
  return true;
5589
6498
  }
5590
6499
  const fwdRange = getAtomicRangeAtPoint(ed, anchor);
5591
6500
  if (fwdRange && slate_exports.Point.equals(anchor, fwdRange.anchor)) {
5592
- slate_exports.Transforms.delete(ed, { at: fwdRange });
6501
+ deleteAtomicRange(ed, anchor, fwdRange);
5593
6502
  return true;
5594
6503
  }
5595
- if (fwdRange) return false;
5596
- const after = slate_exports.Editor.after(ed, anchor);
5597
- const nextRange = after ? getAtomicRangeAtPoint(ed, after) : null;
5598
- if (!nextRange) return false;
5599
- slate_exports.Transforms.delete(ed, { at: nextRange });
6504
+ if (fwdRange && !slate_exports.Point.equals(anchor, fwdRange.focus)) return false;
6505
+ const next = atomicRangeAfter(ed, anchor);
6506
+ if (!next) return false;
6507
+ deleteAtomicRange(ed, next.at, next.range);
5600
6508
  return true;
5601
6509
  }
5602
6510
  function recoverStaleSelection(e) {
@@ -5621,15 +6529,27 @@ function expandAtomicPreservingMarks(e) {
5621
6529
  e.marks = savedMarks;
5622
6530
  }
5623
6531
  }
6532
+ function stripAtomicMarksInRange(e, range2) {
6533
+ slate_exports.Transforms.unsetNodes(e, ["tokenName", "tokenOccurrence", "isEscapedDollar", "isRawToken"], {
6534
+ at: range2,
6535
+ match: (n) => slate_exports.Text.isText(n) && (Boolean(n.tokenName) || Boolean(n.isEscapedDollar))
6536
+ });
6537
+ }
5624
6538
  function installInsertOverrides(e, defaultTextStyleRef, onBeforeBreak) {
5625
6539
  const { insertText, insertBreak } = e;
5626
6540
  e.insertText = (text) => {
5627
6541
  if (text && isLinkActive(e)) {
6542
+ if (e.selection && !slate_exports.Range.isCollapsed(e.selection)) {
6543
+ slate_exports.Transforms.delete(e);
6544
+ }
5628
6545
  exitLinkBeforeInsert(e);
5629
6546
  }
5630
6547
  if (text === " " && handleAutoformat(e, defaultTextStyleRef)) {
5631
6548
  return;
5632
6549
  }
6550
+ if (e.selection && !slate_exports.Range.isCollapsed(e.selection)) {
6551
+ stripAtomicMarksInRange(e, e.selection);
6552
+ }
5633
6553
  moveCursorPastAtomicIfNeeded(e);
5634
6554
  insertText(text);
5635
6555
  };
@@ -5640,6 +6560,15 @@ function installInsertOverrides(e, defaultTextStyleRef, onBeforeBreak) {
5640
6560
  insertBreak();
5641
6561
  };
5642
6562
  }
6563
+ function handleTextInsert(e, event) {
6564
+ if (event.inputType !== "insertText" || typeof event.data !== "string" || event.data === "") {
6565
+ return false;
6566
+ }
6567
+ if (!e.selection) return false;
6568
+ event.preventDefault();
6569
+ e.insertText(event.data);
6570
+ return true;
6571
+ }
5643
6572
  function installDeleteOverrides(e) {
5644
6573
  const { deleteBackward, deleteForward } = e;
5645
6574
  e.deleteBackward = (unit) => {
@@ -5658,6 +6587,67 @@ function installDeleteOverrides(e) {
5658
6587
  deleteForward(unit);
5659
6588
  };
5660
6589
  }
6590
+ function getTokenRun(children, start) {
6591
+ const first = children[start];
6592
+ if (!slate_exports.Text.isText(first) || !first.tokenName) return null;
6593
+ let end = start + 1;
6594
+ while (end < children.length) {
6595
+ const child = children[end];
6596
+ if (!slate_exports.Text.isText(child) || child.tokenName !== first.tokenName) break;
6597
+ end += 1;
6598
+ }
6599
+ return { start, end, first };
6600
+ }
6601
+ function normalizeTokenRun(e, children, path, run) {
6602
+ const { start, end, first } = run;
6603
+ if (end - start === 1) {
6604
+ if (first.tokenOccurrence === void 0) return false;
6605
+ slate_exports.Transforms.unsetNodes(e, "tokenOccurrence", { at: path.concat(start) });
6606
+ return true;
6607
+ }
6608
+ for (let index = start; index < end; index += 1) {
6609
+ const child = children[index];
6610
+ const occurrence = index - start;
6611
+ if (child.tokenOccurrence !== occurrence) {
6612
+ slate_exports.Transforms.setNodes(e, { tokenOccurrence: occurrence }, { at: path.concat(index) });
6613
+ return true;
6614
+ }
6615
+ }
6616
+ return false;
6617
+ }
6618
+ function normalizeAdjacentTokenOccurrences(e, node, path) {
6619
+ let start = 0;
6620
+ while (start < node.children.length) {
6621
+ const run = getTokenRun(node.children, start);
6622
+ if (run) {
6623
+ if (normalizeTokenRun(e, node.children, path, run)) return true;
6624
+ start = run.end;
6625
+ } else {
6626
+ start += 1;
6627
+ }
6628
+ }
6629
+ return false;
6630
+ }
6631
+ function installNormalizeOverride(e) {
6632
+ const { normalizeNode } = e;
6633
+ e.normalizeNode = (entry) => {
6634
+ const [node, path] = entry;
6635
+ if (slate_exports.Element.isElement(node) && normalizeAdjacentTokenOccurrences(e, node, path)) {
6636
+ return;
6637
+ }
6638
+ if (slate_exports.Text.isText(node) && node.text === "" && (node.tokenName || node.isEscapedDollar)) {
6639
+ slate_exports.Transforms.unsetNodes(e, ["tokenName", "tokenOccurrence", "isEscapedDollar", "isRawToken"], {
6640
+ at: path
6641
+ });
6642
+ return;
6643
+ }
6644
+ if (slate_exports.Element.isElement(node) && node.type === "link" && slate_exports.Node.string(node) === "") {
6645
+ slate_exports.Transforms.removeNodes(e, { at: path });
6646
+ return;
6647
+ }
6648
+ normalizeNode(entry);
6649
+ };
6650
+ }
5661
6651
  function installOnChangeOverride(e, getSavedMarks, clearSavedMarks) {
5662
6652
  const { onChange } = e;
5663
6653
  e.onChange = () => {
@@ -5681,6 +6671,7 @@ function useEditorSetup(defaultTextStyleRef) {
5681
6671
  savedMarksForOnChange = slate_exports.Editor.marks(e);
5682
6672
  });
5683
6673
  installDeleteOverrides(e);
6674
+ installNormalizeOverride(e);
5684
6675
  installOnChangeOverride(
5685
6676
  e,
5686
6677
  () => savedMarksForOnChange,
@@ -5704,24 +6695,6 @@ function useInitialMarks(editor, isEditMode, defaultTextStyle) {
5704
6695
  }
5705
6696
 
5706
6697
  // src/RichText/PureRichText/hooks/useFakeHighlight.ts
5707
- function pointAbsOffset(editor, point) {
5708
- let abs = 0;
5709
- for (const [textNode, path] of slate_exports.Editor.nodes(editor, {
5710
- at: [],
5711
- match: (n) => slate_exports.Text.isText(n)
5712
- })) {
5713
- if (slate_exports.Path.equals(path, point.path)) return abs + point.offset;
5714
- abs += textNode.text.length;
5715
- }
5716
- return abs;
5717
- }
5718
- function rangeToAbsOffsets(editor, range2) {
5719
- const [start, end] = slate_exports.Range.edges(range2);
5720
- return {
5721
- absStart: pointAbsOffset(editor, start),
5722
- absEnd: pointAbsOffset(editor, end)
5723
- };
5724
- }
5725
6698
  function pointToAbsOffset(editor, point) {
5726
6699
  let offset = 0;
5727
6700
  for (const [textNode, path] of slate_exports.Editor.nodes(editor, {
@@ -5733,6 +6706,13 @@ function pointToAbsOffset(editor, point) {
5733
6706
  }
5734
6707
  return offset;
5735
6708
  }
6709
+ function rangeToAbsOffsets(editor, range2) {
6710
+ const [start, end] = slate_exports.Range.edges(range2);
6711
+ return {
6712
+ absStart: pointToAbsOffset(editor, start),
6713
+ absEnd: pointToAbsOffset(editor, end)
6714
+ };
6715
+ }
5736
6716
  function absOffsetToPoint(editor, absOffset, isStart = false) {
5737
6717
  let seen = 0;
5738
6718
  for (const [textNode, path] of slate_exports.Editor.nodes(editor, {
@@ -5769,8 +6749,9 @@ function useFakeHighlight(editor) {
5769
6749
  }, []);
5770
6750
  const decorate = (0, react_exports.useCallback)(
5771
6751
  ([node, path]) => {
5772
- if (!fakeHighlightAbs || !slate_exports.Text.isText(node)) return [];
5773
- const { absStart, absEnd } = fakeHighlightAbs;
6752
+ const abs = fakeHighlightAbsRef.current;
6753
+ if (!abs || !slate_exports.Text.isText(node)) return [];
6754
+ const { absStart, absEnd } = abs;
5774
6755
  let nodeAbsStart = 0;
5775
6756
  for (const [n, p] of slate_exports.Editor.nodes(editor, {
5776
6757
  at: [],
@@ -5791,6 +6772,8 @@ function useFakeHighlight(editor) {
5791
6772
  }
5792
6773
  ];
5793
6774
  },
6775
+ // fakeHighlightAbs (state) triggers re-evaluation; fakeHighlightAbsRef provides the current value.
6776
+ // eslint-disable-next-line react-hooks/exhaustive-deps
5794
6777
  [fakeHighlightAbs, editor]
5795
6778
  );
5796
6779
  return {
@@ -5833,26 +6816,149 @@ function safeRestoreSelection(editor, selection) {
5833
6816
  }
5834
6817
  }
5835
6818
  }
6819
+ function directRestoreSelection(editor, selection) {
6820
+ try {
6821
+ if (selection) {
6822
+ editor.selection = clampSelection(editor, selection);
6823
+ } else {
6824
+ const end = slate_exports.Editor.end(editor, []);
6825
+ editor.selection = { anchor: end, focus: end };
6826
+ }
6827
+ } catch (e) {
6828
+ try {
6829
+ const end = slate_exports.Editor.end(editor, []);
6830
+ editor.selection = { anchor: end, focus: end };
6831
+ } catch (e2) {
6832
+ }
6833
+ }
6834
+ }
5836
6835
  function consumeForceSync(ref) {
5837
- var _a;
5838
- const value = (_a = ref == null ? void 0 : ref.current) != null ? _a : false;
6836
+ var _a2;
6837
+ const value = (_a2 = ref == null ? void 0 : ref.current) != null ? _a2 : false;
5839
6838
  if (value && ref) {
5840
6839
  ref.current = false;
5841
6840
  }
5842
6841
  return value;
5843
6842
  }
5844
- function shouldSkipSync(forceSync, richTextContent, lastEmittedHtml, recentSavesRef, hasFocusRef) {
6843
+ function shouldSkipSync(forceSync, richTextContent, recentSavesRef, isTextEditingRef, hasFocusRef) {
5845
6844
  if (forceSync) return false;
5846
6845
  if (recentSavesRef == null ? void 0 : recentSavesRef.current.has(richTextContent)) return true;
5847
- if (hasFocusRef.current) return true;
6846
+ if (isTextEditingRef.current && hasFocusRef.current) return true;
5848
6847
  return false;
5849
6848
  }
6849
+ function shouldSkipUnchangedContent(explicitForceSync, contentMatchesLastEdit, initialValueChanged, syncInitialValueChanges) {
6850
+ return !explicitForceSync && contentMatchesLastEdit && (!initialValueChanged || !syncInitialValueChanges);
6851
+ }
6852
+ function recordSkippedExternalContent(isRecentSave, richTextContent, lastEmittedHtmlRef) {
6853
+ if (!isRecentSave) {
6854
+ lastEmittedHtmlRef.current = richTextContent;
6855
+ }
6856
+ }
6857
+ function getSavedSelection(history, incomingIdx, lastSelection) {
6858
+ var _a2;
6859
+ if (incomingIdx === -1) return lastSelection;
6860
+ return ((_a2 = history[incomingIdx + 1]) == null ? void 0 : _a2.preSelection) || history[incomingIdx].selection || lastSelection;
6861
+ }
6862
+ function getTreeToApply(forceSync, richTextContent, initialValue, transformTree) {
6863
+ if (!forceSync || !richTextContent) return initialValue;
6864
+ const parsed = htmlToSlate(richTextContent);
6865
+ return transformTree ? transformTree(parsed) : parsed;
6866
+ }
6867
+ function snapToTokenEdge(editor, point, isStart) {
6868
+ try {
6869
+ const [node] = slate_exports.Editor.node(editor, point);
6870
+ if (slate_exports.Text.isText(node) && node.tokenName) {
6871
+ return { path: point.path, offset: isStart ? 0 : node.text.length };
6872
+ }
6873
+ } catch (e) {
6874
+ }
6875
+ return point;
6876
+ }
6877
+ function restoreSelectionAndHighlight({
6878
+ editor,
6879
+ savedSelection,
6880
+ forceSync,
6881
+ isExternalContentChange,
6882
+ fakeHighlightAbsRef,
6883
+ hasFocusRef,
6884
+ updateFakeHighlightAbs
6885
+ }) {
6886
+ if (isExternalContentChange || forceSync) {
6887
+ if (forceSync) {
6888
+ directRestoreSelection(editor, savedSelection);
6889
+ } else {
6890
+ safeRestoreSelection(editor, savedSelection);
6891
+ }
6892
+ }
6893
+ if (fakeHighlightAbsRef.current !== null && !hasFocusRef.current && editor.selection) {
6894
+ let [start, end] = slate_exports.Range.isBackward(editor.selection) ? [editor.selection.focus, editor.selection.anchor] : [editor.selection.anchor, editor.selection.focus];
6895
+ start = snapToTokenEdge(editor, start, true);
6896
+ end = snapToTokenEdge(editor, end, false);
6897
+ updateFakeHighlightAbs({
6898
+ absStart: pointToAbsOffset(editor, start),
6899
+ absEnd: pointToAbsOffset(editor, end)
6900
+ });
6901
+ } else {
6902
+ updateFakeHighlightAbs(null);
6903
+ }
6904
+ }
5850
6905
  function findHistoryIndex(history, html) {
5851
6906
  for (let i = history.length - 1; i >= 0; i -= 1) {
5852
6907
  if (history[i].html === html) return i;
5853
6908
  }
5854
6909
  return -1;
5855
6910
  }
6911
+ function isTypingOnly(editor) {
6912
+ return editor.operations.every(
6913
+ (op) => op.type === "set_selection" || op.type === "insert_text" || op.type === "remove_text"
6914
+ );
6915
+ }
6916
+ function emitContentChange({
6917
+ editor,
6918
+ html,
6919
+ prevSelection,
6920
+ lastEmittedHtmlRef,
6921
+ emittedHistoryRef,
6922
+ historyPosRef,
6923
+ onContentChange,
6924
+ autoResolveTokensRef
6925
+ }) {
6926
+ const typing = isTypingOnly(editor);
6927
+ const hasBareToken = typing && (autoResolveTokensRef == null ? void 0 : autoResolveTokensRef.current) != null && new RegExp(TOKEN_PATTERN.source, TOKEN_PATTERN.flags).test(html);
6928
+ const pos = historyPosRef.current;
6929
+ lastEmittedHtmlRef.current = html;
6930
+ emittedHistoryRef.current = [
6931
+ ...emittedHistoryRef.current.slice(0, pos + 1),
6932
+ { html, selection: editor.selection, preSelection: prevSelection }
6933
+ ];
6934
+ historyPosRef.current = emittedHistoryRef.current.length - 1;
6935
+ onContentChange(html, hasBareToken || !typing);
6936
+ if (autoResolveTokensRef == null ? void 0 : autoResolveTokensRef.current) {
6937
+ queueMicrotask(() => {
6938
+ var _a2;
6939
+ return (_a2 = autoResolveTokensRef.current) == null ? void 0 : _a2.call(autoResolveTokensRef);
6940
+ });
6941
+ }
6942
+ }
6943
+ function cancelPendingStyleUpdate(styleUpdateRafRef) {
6944
+ if (styleUpdateRafRef.current !== null) {
6945
+ cancelAnimationFrame(styleUpdateRafRef.current);
6946
+ styleUpdateRafRef.current = null;
6947
+ }
6948
+ }
6949
+ function recomputeStylesForContentChange(styleUpdateRafRef, updateActiveStyles) {
6950
+ cancelPendingStyleUpdate(styleUpdateRafRef);
6951
+ updateActiveStyles(true);
6952
+ }
6953
+ function scheduleStylesForSelectionChange(editor, styleUpdateRafRef, updateActiveStyles) {
6954
+ if (styleUpdateRafRef.current !== null) return;
6955
+ styleUpdateRafRef.current = requestAnimationFrame(() => {
6956
+ styleUpdateRafRef.current = null;
6957
+ if (editor.selection) {
6958
+ updateActiveStyles(false);
6959
+ }
6960
+ });
6961
+ }
5856
6962
  function useContentSync({
5857
6963
  editor,
5858
6964
  initialValue,
@@ -5862,53 +6968,93 @@ function useContentSync({
5862
6968
  updateFakeHighlightAbs,
5863
6969
  fakeHighlightAbsRef,
5864
6970
  hasFocusRef,
6971
+ isTextEditingRef,
5865
6972
  lastSelectionRef,
5866
6973
  recentSavesRef,
5867
- forceNextSyncRef
6974
+ forceNextSyncRef,
6975
+ transformTreeRef,
6976
+ syncInitialValueChanges = true,
6977
+ autoResolveTokensRef
5868
6978
  }) {
5869
6979
  const [value, setValue] = (0, react_exports.useState)(initialValue);
5870
6980
  const lastEmittedHtmlRef = (0, react_exports.useRef)(richTextContent);
6981
+ const styleUpdateRafRef = (0, react_exports.useRef)(null);
5871
6982
  const emittedHistoryRef = (0, react_exports.useRef)([
5872
6983
  { html: richTextContent, selection: null, preSelection: null }
5873
6984
  ]);
5874
6985
  const historyPosRef = (0, react_exports.useRef)(0);
5875
6986
  const lastInitialValueRef = (0, react_exports.useRef)(initialValue);
5876
6987
  (0, react_exports.useEffect)(() => {
6988
+ var _a2;
5877
6989
  const initialValueChanged = initialValue !== lastInitialValueRef.current;
5878
6990
  lastInitialValueRef.current = initialValue;
5879
- if (!initialValueChanged && richTextContent === lastEmittedHtmlRef.current) return;
5880
- const forceSync = consumeForceSync(forceNextSyncRef);
5881
- if (shouldSkipSync(
5882
- forceSync,
5883
- richTextContent,
5884
- lastEmittedHtmlRef.current,
5885
- recentSavesRef,
5886
- hasFocusRef
6991
+ const explicitForceSync = consumeForceSync(forceNextSyncRef);
6992
+ const contentMatchesLastEdit = richTextContent === lastEmittedHtmlRef.current;
6993
+ if (shouldSkipUnchangedContent(
6994
+ explicitForceSync,
6995
+ contentMatchesLastEdit,
6996
+ initialValueChanged,
6997
+ syncInitialValueChanges
5887
6998
  )) {
5888
- lastEmittedHtmlRef.current = richTextContent;
5889
6999
  return;
5890
7000
  }
5891
7001
  const history = emittedHistoryRef.current;
5892
7002
  const incomingIdx = findHistoryIndex(history, richTextContent);
7003
+ const isRecentSave = (_a2 = recentSavesRef == null ? void 0 : recentSavesRef.current.has(richTextContent)) != null ? _a2 : false;
5893
7004
  const isExternalContentChange = richTextContent !== lastEmittedHtmlRef.current;
7005
+ const isHistoryRevert = isExternalContentChange && incomingIdx !== -1 && !isRecentSave;
7006
+ const forceSync = explicitForceSync || isHistoryRevert;
7007
+ if (shouldSkipSync(forceSync, richTextContent, recentSavesRef, isTextEditingRef, hasFocusRef)) {
7008
+ recordSkippedExternalContent(isRecentSave, richTextContent, lastEmittedHtmlRef);
7009
+ return;
7010
+ }
5894
7011
  const pendingMarks = isExternalContentChange ? null : editor.marks;
5895
7012
  lastEmittedHtmlRef.current = richTextContent;
5896
7013
  if (incomingIdx !== -1) {
5897
7014
  historyPosRef.current = incomingIdx;
5898
7015
  }
5899
- const undoneEntry = incomingIdx !== -1 ? history[incomingIdx + 1] : null;
5900
- const savedSelection = (undoneEntry == null ? void 0 : undoneEntry.preSelection) || (incomingIdx !== -1 ? history[incomingIdx].selection : null) || lastSelectionRef.current;
5901
- const treeToApply = forceSync && richTextContent ? htmlToSlate(richTextContent) : initialValue;
7016
+ const savedSelection = getSavedSelection(history, incomingIdx, lastSelectionRef.current);
7017
+ const treeToApply = getTreeToApply(
7018
+ forceSync,
7019
+ richTextContent,
7020
+ initialValue,
7021
+ transformTreeRef == null ? void 0 : transformTreeRef.current
7022
+ );
5902
7023
  setValue(treeToApply);
5903
7024
  editor.children = treeToApply;
5904
7025
  editor.selection = null;
5905
- if (isExternalContentChange || forceSync) {
5906
- safeRestoreSelection(editor, savedSelection);
5907
- }
7026
+ restoreSelectionAndHighlight({
7027
+ editor,
7028
+ savedSelection,
7029
+ forceSync,
7030
+ isExternalContentChange,
7031
+ fakeHighlightAbsRef,
7032
+ hasFocusRef,
7033
+ updateFakeHighlightAbs
7034
+ });
5908
7035
  if (pendingMarks) {
5909
7036
  editor.marks = pendingMarks;
5910
7037
  }
5911
- }, [initialValue, richTextContent, editor, lastSelectionRef]);
7038
+ if (!hasFocusRef.current) {
7039
+ editor.onChange();
7040
+ }
7041
+ }, [
7042
+ initialValue,
7043
+ richTextContent,
7044
+ editor,
7045
+ lastSelectionRef,
7046
+ hasFocusRef,
7047
+ syncInitialValueChanges,
7048
+ fakeHighlightAbsRef,
7049
+ forceNextSyncRef,
7050
+ isTextEditingRef,
7051
+ recentSavesRef,
7052
+ transformTreeRef,
7053
+ updateFakeHighlightAbs
7054
+ ]);
7055
+ (0, react_exports.useEffect)(() => {
7056
+ return () => cancelPendingStyleUpdate(styleUpdateRafRef);
7057
+ }, []);
5912
7058
  const handleChange = (0, react_exports.useCallback)(
5913
7059
  (newValue) => {
5914
7060
  setValue(newValue);
@@ -5920,27 +7066,28 @@ function useContentSync({
5920
7066
  if (isContentChange) {
5921
7067
  const html = slateToHtml(newValue);
5922
7068
  if (html !== lastEmittedHtmlRef.current) {
5923
- const isTypingOnly = editor.operations.every(
5924
- (op) => op.type === "set_selection" || op.type === "insert_text" || op.type === "remove_text"
5925
- );
5926
- const pos = historyPosRef.current;
5927
- lastEmittedHtmlRef.current = html;
5928
- emittedHistoryRef.current = [
5929
- ...emittedHistoryRef.current.slice(0, pos + 1),
5930
- { html, selection: editor.selection, preSelection: prevSelection }
5931
- ];
5932
- historyPosRef.current = emittedHistoryRef.current.length - 1;
5933
- onContentChange(html, !isTypingOnly);
7069
+ emitContentChange({
7070
+ editor,
7071
+ html,
7072
+ prevSelection,
7073
+ lastEmittedHtmlRef,
7074
+ emittedHistoryRef,
7075
+ historyPosRef,
7076
+ onContentChange,
7077
+ autoResolveTokensRef
7078
+ });
5934
7079
  }
5935
7080
  }
5936
7081
  if (hasFocusRef.current || editor.selection) {
5937
- updateActiveStyles(isContentChange);
5938
- }
5939
- if (isContentChange && fakeHighlightAbsRef.current && hasFocusRef.current && editor.selection) {
5940
- if (slate_exports.Range.isCollapsed(editor.selection)) {
5941
- updateFakeHighlightAbs(null);
7082
+ if (isContentChange) {
7083
+ recomputeStylesForContentChange(styleUpdateRafRef, updateActiveStyles);
7084
+ } else {
7085
+ scheduleStylesForSelectionChange(editor, styleUpdateRafRef, updateActiveStyles);
5942
7086
  }
5943
7087
  }
7088
+ if (isContentChange && fakeHighlightAbsRef.current && hasFocusRef.current && editor.selection && slate_exports.Range.isCollapsed(editor.selection)) {
7089
+ updateFakeHighlightAbs(null);
7090
+ }
5944
7091
  },
5945
7092
  [
5946
7093
  editor,
@@ -5949,10 +7096,11 @@ function useContentSync({
5949
7096
  updateFakeHighlightAbs,
5950
7097
  fakeHighlightAbsRef,
5951
7098
  hasFocusRef,
5952
- lastSelectionRef
7099
+ lastSelectionRef,
7100
+ autoResolveTokensRef
5953
7101
  ]
5954
7102
  );
5955
- return { value, handleChange };
7103
+ return { value, handleChange, lastEmittedHtmlRef };
5956
7104
  }
5957
7105
 
5958
7106
  // src/RichText/PureRichText/hooks/useKeyboardShortcuts.ts
@@ -5997,9 +7145,13 @@ function handleTabKey(editor, event) {
5997
7145
  const [parentListNode] = parentList;
5998
7146
  const parentListElement = parentListNode;
5999
7147
  const listType = parentListElement.type === "numbered-list" ? "numbered-list" : "bulleted-list";
6000
- slate_exports.Transforms.wrapNodes(editor, { type: listType, children: [] }, {
6001
- at: listItemPath
6002
- });
7148
+ slate_exports.Transforms.wrapNodes(
7149
+ editor,
7150
+ { type: listType, children: [] },
7151
+ {
7152
+ at: listItemPath
7153
+ }
7154
+ );
6003
7155
  }
6004
7156
  function cycleAlignment(editor, applyFormat) {
6005
7157
  const cycle = {
@@ -6141,7 +7293,7 @@ function restoreSelection(editor, fakeHighlightAbsRef, lastSelectionRef) {
6141
7293
  }
6142
7294
  function stepCollapsed(editor, delta, updateActiveStyles) {
6143
7295
  const marks = slate_exports.Editor.marks(editor);
6144
- const current = (marks == null ? void 0 : marks.fontSize) ? parseInt(String(marks.fontSize), 10) : 14;
7296
+ const current = (marks == null ? void 0 : marks.fontSize) ? Number.parseInt(String(marks.fontSize), 10) : 14;
6145
7297
  slate_exports.Editor.addMark(editor, "fontSize", `${clampFontSize(current + delta)}px`);
6146
7298
  updateActiveStyles();
6147
7299
  }
@@ -6154,7 +7306,7 @@ function collectTextEntries(editor) {
6154
7306
  match: (n) => slate_exports.Text.isText(n)
6155
7307
  })) {
6156
7308
  const fontSize = node.fontSize;
6157
- const cur = fontSize ? parseInt(fontSize, 10) : 14;
7309
+ const cur = fontSize ? Number.parseInt(fontSize, 10) : 14;
6158
7310
  const nodeStart = slate_exports.Editor.start(editor, path);
6159
7311
  const nodeEnd = slate_exports.Editor.end(editor, path);
6160
7312
  const start = slate_exports.Point.compare(nodeStart, selStart) >= 0 ? nodeStart : selStart;
@@ -6183,7 +7335,7 @@ function useStepFontSize({
6183
7335
  }) {
6184
7336
  const stepFontSize = (0, react_exports.useCallback)(
6185
7337
  (delta) => {
6186
- var _a;
7338
+ var _a2;
6187
7339
  restoreSelection(editor, fakeHighlightAbsRef, lastSelectionRef);
6188
7340
  if (!editor.selection) return;
6189
7341
  if (slate_exports.Range.isCollapsed(editor.selection)) {
@@ -6201,7 +7353,7 @@ function useStepFontSize({
6201
7353
  editor.selection = { anchor: newStart, focus: newEnd };
6202
7354
  updateActiveStyles();
6203
7355
  }
6204
- (_a = window.getSelection()) == null ? void 0 : _a.removeAllRanges();
7356
+ (_a2 = globalThis.getSelection()) == null ? void 0 : _a2.removeAllRanges();
6205
7357
  },
6206
7358
  [editor, fakeHighlightAbsRef, lastSelectionRef, updateFakeHighlightAbs, updateActiveStyles]
6207
7359
  );
@@ -6234,7 +7386,7 @@ function useStepLineSpacing({
6234
7386
  }) {
6235
7387
  const stepLineSpacing = (0, react_exports.useCallback)(
6236
7388
  (delta) => {
6237
- var _a;
7389
+ var _a2;
6238
7390
  if (!editor.selection && fakeHighlightAbsRef.current) {
6239
7391
  const s = absOffsetToPoint(editor, fakeHighlightAbsRef.current.absStart, true);
6240
7392
  const e = absOffsetToPoint(editor, fakeHighlightAbsRef.current.absEnd);
@@ -6274,7 +7426,7 @@ function useStepLineSpacing({
6274
7426
  editor.selection = { anchor: newStart, focus: newEnd };
6275
7427
  updateActiveStyles();
6276
7428
  }
6277
- (_a = window.getSelection()) == null ? void 0 : _a.removeAllRanges();
7429
+ (_a2 = globalThis.getSelection()) == null ? void 0 : _a2.removeAllRanges();
6278
7430
  },
6279
7431
  [editor, fakeHighlightAbsRef, lastSelectionRef, updateFakeHighlightAbs, updateActiveStyles]
6280
7432
  );
@@ -6286,8 +7438,8 @@ function useStepLineSpacing({
6286
7438
 
6287
7439
  // src/RichText/PureRichText/hooks/useFocusHandlers.ts
6288
7440
  function findConfigPanel() {
6289
- var _a;
6290
- return ((_a = document.querySelector('[data-test="editor-richTextContent"]')) == null ? void 0 : _a.closest('[class*="StyledInsetWrapper"]')) || document.querySelector('[data-test="editor-richTextContent"]') || document.querySelector('[data-test="editor-purerichtext"]') || document.querySelector('[data-test="sidebar-content"]') || null;
7441
+ var _a2;
7442
+ return ((_a2 = document.querySelector('[data-test="editor-richTextContent"]')) == null ? void 0 : _a2.closest('[class*="StyledInsetWrapper"]')) || document.querySelector('[data-test="editor-richTextContent"]') || document.querySelector('[data-test="editor-purerichtext"]') || document.querySelector('[data-test="sidebar-content"]') || null;
6291
7443
  }
6292
7444
  function isFocusInPanelUI(relatedTarget, configPanel) {
6293
7445
  if (!relatedTarget) return false;
@@ -6317,15 +7469,15 @@ function useFocusHandlers({
6317
7469
  onDeactivateTextEditing
6318
7470
  }) {
6319
7471
  const handleFocus = (0, react_exports.useCallback)(() => {
6320
- var _a, _b;
7472
+ var _a2, _b;
6321
7473
  if (wasTextEditingRef.current) {
6322
7474
  updateFakeHighlightAbs(null);
6323
7475
  wasTextEditingRef.current = false;
6324
7476
  }
6325
7477
  if (!isTextEditingRef.current) {
6326
- (_a = editableRef.current) == null ? void 0 : _a.blur();
7478
+ (_a2 = editableRef.current) == null ? void 0 : _a2.blur();
6327
7479
  safeDeselect(editor);
6328
- (_b = window.getSelection()) == null ? void 0 : _b.removeAllRanges();
7480
+ (_b = globalThis.getSelection()) == null ? void 0 : _b.removeAllRanges();
6329
7481
  return;
6330
7482
  }
6331
7483
  hasFocusRef.current = true;
@@ -6333,7 +7485,7 @@ function useFocusHandlers({
6333
7485
  }, [onFocusGained, editor, editableRef, hasFocusRef, wasTextEditingRef, updateFakeHighlightAbs]);
6334
7486
  const handleBlur = (0, react_exports.useCallback)(
6335
7487
  (e) => {
6336
- var _a, _b;
7488
+ var _a2, _b;
6337
7489
  saveSelection();
6338
7490
  hasFocusRef.current = false;
6339
7491
  const sel = editor.selection ? { anchor: __spreadValues({}, editor.selection.anchor), focus: __spreadValues({}, editor.selection.focus) } : lastSelectionRef.current;
@@ -6356,14 +7508,14 @@ function useFocusHandlers({
6356
7508
  if (canShowFakeHighlight) {
6357
7509
  updateFakeHighlight(sel);
6358
7510
  }
6359
- (_a = window.getSelection()) == null ? void 0 : _a.removeAllRanges();
7511
+ (_a2 = globalThis.getSelection()) == null ? void 0 : _a2.removeAllRanges();
6360
7512
  }
6361
7513
  if (!focusStaysInPanel) {
6362
7514
  updateFakeHighlight(null);
6363
7515
  wasTextEditingRef.current = false;
6364
7516
  lastSelectionRef.current = null;
6365
7517
  safeDeselect(editor);
6366
- (_b = window.getSelection()) == null ? void 0 : _b.removeAllRanges();
7518
+ (_b = globalThis.getSelection()) == null ? void 0 : _b.removeAllRanges();
6367
7519
  onDeactivateTextEditing == null ? void 0 : onDeactivateTextEditing();
6368
7520
  }
6369
7521
  onFocusLost == null ? void 0 : onFocusLost();
@@ -6386,9 +7538,51 @@ function useFocusHandlers({
6386
7538
  }
6387
7539
 
6388
7540
  // src/RichText/PureRichText/hooks/useMouseHandlers.ts
7541
+ var MOVE_THRESHOLD = 4;
7542
+ function placeCaretAtPoint(editor, clientX, clientY, target, editableEl) {
7543
+ try {
7544
+ let domRange = null;
7545
+ const doc = document;
7546
+ if (typeof doc.caretRangeFromPoint === "function") {
7547
+ domRange = doc.caretRangeFromPoint(clientX, clientY);
7548
+ } else if (typeof doc.caretPositionFromPoint === "function") {
7549
+ const pos = doc.caretPositionFromPoint(clientX, clientY);
7550
+ if (pos) {
7551
+ const r = document.createRange();
7552
+ r.setStart(pos.offsetNode, pos.offset);
7553
+ r.collapse(true);
7554
+ domRange = r;
7555
+ }
7556
+ }
7557
+ if (domRange) {
7558
+ const sel = globalThis.getSelection();
7559
+ sel == null ? void 0 : sel.removeAllRanges();
7560
+ sel == null ? void 0 : sel.addRange(domRange);
7561
+ const point = slate_react_exports.ReactEditor.toSlatePoint(editor, [domRange.startContainer, domRange.startOffset], {
7562
+ exactMatch: false,
7563
+ suppressThrow: true
7564
+ });
7565
+ if (point) {
7566
+ slate_exports.Transforms.select(editor, point);
7567
+ return;
7568
+ }
7569
+ }
7570
+ if (target) {
7571
+ const node = slate_react_exports.ReactEditor.toSlateNode(editor, target);
7572
+ const path = slate_react_exports.ReactEditor.findPath(editor, node);
7573
+ slate_exports.Transforms.select(editor, slate_exports.Editor.start(editor, path));
7574
+ return;
7575
+ }
7576
+ } catch (e) {
7577
+ }
7578
+ if (!editorContentOverflows(editableEl != null ? editableEl : null)) {
7579
+ safeSelectEnd(editor);
7580
+ }
7581
+ }
6389
7582
  function useMouseHandlers({
6390
7583
  editor,
6391
7584
  editableRef,
7585
+ containerRef,
6392
7586
  isEditMode,
6393
7587
  isTextEditing,
6394
7588
  onActivateTextEditing,
@@ -6396,31 +7590,45 @@ function useMouseHandlers({
6396
7590
  }) {
6397
7591
  const handleMouseDown = (0, react_exports.useCallback)(
6398
7592
  (e) => {
6399
- var _a;
7593
+ var _a2, _b;
6400
7594
  if (isEditMode && !isTextEditing) {
6401
- onActivateTextEditing == null ? void 0 : onActivateTextEditing();
6402
- setMouseSelecting(true);
6403
- const onMouseUp = () => {
7595
+ const isVizSelected = ((_a2 = containerRef.current) == null ? void 0 : _a2.closest('[data-selected="true"]')) != null;
7596
+ if (isVizSelected) {
7597
+ e.stopPropagation();
7598
+ }
7599
+ setSuppressNextEditClick(false);
7600
+ const startX = e.clientX;
7601
+ const startY = e.clientY;
7602
+ const onMouseUp = (ev) => {
6404
7603
  document.removeEventListener("mouseup", onMouseUp, true);
7604
+ const moved = Math.abs(ev.clientX - startX) > MOVE_THRESHOLD || Math.abs(ev.clientY - startY) > MOVE_THRESHOLD;
7605
+ if (moved) {
7606
+ setSuppressNextEditClick(true);
7607
+ return;
7608
+ }
7609
+ onActivateTextEditing == null ? void 0 : onActivateTextEditing();
7610
+ setMouseSelecting(true);
6405
7611
  requestAnimationFrame(() => {
6406
7612
  setMouseSelecting(false);
6407
7613
  });
7614
+ const clickTarget = ev.target;
7615
+ setTimeout(() => {
7616
+ var _a3;
7617
+ (_a3 = editableRef.current) == null ? void 0 : _a3.focus({ preventScroll: true });
7618
+ placeCaretAtPoint(editor, startX, startY, clickTarget, editableRef.current);
7619
+ }, 0);
6408
7620
  };
6409
7621
  document.addEventListener("mouseup", onMouseUp, true);
6410
- setTimeout(() => {
6411
- var _a2;
6412
- (_a2 = editableRef.current) == null ? void 0 : _a2.focus({ preventScroll: true });
6413
- }, 0);
6414
7622
  return;
6415
7623
  }
6416
7624
  if (isTextEditing) {
6417
7625
  clearFakeHighlight();
6418
7626
  e.stopPropagation();
7627
+ setMouseSelecting(true);
6419
7628
  if (editor.selection && !slate_exports.Range.isCollapsed(editor.selection)) {
6420
7629
  slate_exports.Transforms.collapse(editor, { edge: "focus" });
6421
- (_a = window.getSelection()) == null ? void 0 : _a.removeAllRanges();
7630
+ (_b = globalThis.getSelection()) == null ? void 0 : _b.removeAllRanges();
6422
7631
  }
6423
- setMouseSelecting(true);
6424
7632
  const onMouseUp = (ev) => {
6425
7633
  document.removeEventListener("mouseup", onMouseUp, true);
6426
7634
  ev.stopPropagation();
@@ -6431,7 +7639,15 @@ function useMouseHandlers({
6431
7639
  document.addEventListener("mouseup", onMouseUp, true);
6432
7640
  }
6433
7641
  },
6434
- [isEditMode, isTextEditing, onActivateTextEditing, editableRef, clearFakeHighlight]
7642
+ [
7643
+ editor,
7644
+ isEditMode,
7645
+ isTextEditing,
7646
+ onActivateTextEditing,
7647
+ editableRef,
7648
+ containerRef,
7649
+ clearFakeHighlight
7650
+ ]
6435
7651
  );
6436
7652
  const handleEmptySpaceClick = (0, react_exports.useCallback)(
6437
7653
  (e) => {
@@ -6440,14 +7656,14 @@ function useMouseHandlers({
6440
7656
  const target = e.target;
6441
7657
  if (target.closest("[data-slate-node]")) return;
6442
7658
  editableRef.current.focus({ preventScroll: true });
6443
- safeSelectEnd(editor);
7659
+ placeCaretAtPoint(editor, e.clientX, e.clientY, null, editableRef.current);
6444
7660
  },
6445
7661
  [isTextEditing, editor, editableRef]
6446
7662
  );
6447
7663
  const handleDragStart = (0, react_exports.useCallback)(
6448
7664
  (e) => {
7665
+ e.preventDefault();
6449
7666
  if (isEditMode) {
6450
- e.preventDefault();
6451
7667
  e.stopPropagation();
6452
7668
  }
6453
7669
  },
@@ -6460,12 +7676,12 @@ function useMouseHandlers({
6460
7676
  function useEditModeEffect(editor, editableRef, isEditMode) {
6461
7677
  const prevIsEditModeRef = (0, react_exports.useRef)(isEditMode);
6462
7678
  (0, react_exports.useEffect)(() => {
6463
- var _a;
7679
+ var _a2;
6464
7680
  const wasEditMode = prevIsEditModeRef.current;
6465
7681
  prevIsEditModeRef.current = isEditMode;
6466
7682
  if (wasEditMode && !isEditMode) {
6467
7683
  safeDeselect(editor);
6468
- (_a = editableRef.current) == null ? void 0 : _a.blur();
7684
+ (_a2 = editableRef.current) == null ? void 0 : _a2.blur();
6469
7685
  }
6470
7686
  }, [isEditMode, editor, editableRef]);
6471
7687
  }
@@ -6486,7 +7702,15 @@ var InnerEditor = ({
6486
7702
  updateActiveStylesRef,
6487
7703
  clearFakeHighlightRef,
6488
7704
  recentSavesRef,
6489
- onAnnouncement
7705
+ forceNextSyncRef: forceNextSyncRefProp,
7706
+ transformTreeRef,
7707
+ syncInitialValueChanges,
7708
+ autoResolveTokensRef,
7709
+ onPasteStart,
7710
+ onAnnouncement,
7711
+ onCancelPendingChanges,
7712
+ nameToValue,
7713
+ onLinkOpen
6490
7714
  }) => {
6491
7715
  const {
6492
7716
  setEditor,
@@ -6536,7 +7760,8 @@ var InnerEditor = ({
6536
7760
  const lastSelectionRef = (0, react_exports.useRef)(null);
6537
7761
  useEditModeEffect(editor, editableRef, isEditMode);
6538
7762
  const hasFocusRef = (0, react_exports.useRef)(false);
6539
- const forceNextSyncRef = (0, react_exports.useRef)(false);
7763
+ const localForceNextSyncRef = (0, react_exports.useRef)(false);
7764
+ const forceNextSyncRef = forceNextSyncRefProp != null ? forceNextSyncRefProp : localForceNextSyncRef;
6540
7765
  const { fakeHighlightAbsRef, updateFakeHighlight, updateFakeHighlightAbs, decorate } = useFakeHighlight(editor);
6541
7766
  const highlightDismissedRef = (0, react_exports.useRef)(false);
6542
7767
  (0, react_exports.useEffect)(() => {
@@ -6556,9 +7781,13 @@ var InnerEditor = ({
6556
7781
  updateFakeHighlightAbs,
6557
7782
  fakeHighlightAbsRef,
6558
7783
  hasFocusRef,
7784
+ isTextEditingRef,
6559
7785
  lastSelectionRef,
6560
7786
  recentSavesRef,
6561
- forceNextSyncRef
7787
+ forceNextSyncRef,
7788
+ transformTreeRef,
7789
+ syncInitialValueChanges,
7790
+ autoResolveTokensRef
6562
7791
  });
6563
7792
  const stepFontSize = useStepFontSize({
6564
7793
  editor,
@@ -6622,7 +7851,7 @@ var InnerEditor = ({
6622
7851
  );
6623
7852
  const handleKeyDown = (0, react_exports.useCallback)(
6624
7853
  (event) => {
6625
- var _a, _b, _c;
7854
+ var _a2, _b;
6626
7855
  if (!isTextEditingRef.current) {
6627
7856
  return void 0;
6628
7857
  }
@@ -6633,18 +7862,10 @@ var InnerEditor = ({
6633
7862
  slate_exports.Transforms.deselect(editor);
6634
7863
  } catch (e) {
6635
7864
  }
6636
- (_a = window.getSelection()) == null ? void 0 : _a.removeAllRanges();
7865
+ (_a2 = globalThis.getSelection()) == null ? void 0 : _a2.removeAllRanges();
6637
7866
  onDeactivateTextEditing == null ? void 0 : onDeactivateTextEditing();
6638
7867
  (_b = editableRef.current) == null ? void 0 : _b.blur();
6639
- const selectOutline = (_c = editableRef.current) == null ? void 0 : _c.closest(
6640
- '[data-test="select-outline"]'
6641
- );
6642
- if (selectOutline) {
6643
- if (!selectOutline.getAttribute("tabindex")) {
6644
- selectOutline.setAttribute("tabindex", "-1");
6645
- }
6646
- selectOutline.focus({ preventScroll: true });
6647
- }
7868
+ focusSelectOutline(editableRef.current);
6648
7869
  return void 0;
6649
7870
  }
6650
7871
  if (event.key === "Tab" && event.shiftKey) {
@@ -6657,7 +7878,7 @@ var InnerEditor = ({
6657
7878
  }
6658
7879
  const mod = event.metaKey || event.ctrlKey;
6659
7880
  if (mod && event.key.toLowerCase() === "z") {
6660
- onFocusLost == null ? void 0 : onFocusLost();
7881
+ onCancelPendingChanges == null ? void 0 : onCancelPendingChanges();
6661
7882
  forceNextSyncRef.current = true;
6662
7883
  return true;
6663
7884
  }
@@ -6665,30 +7886,43 @@ var InnerEditor = ({
6665
7886
  return void 0;
6666
7887
  },
6667
7888
  [
6668
- editor,
6669
- editableRef,
7889
+ isTextEditingRef,
6670
7890
  handleKeyboardShortcuts,
6671
7891
  onDeactivateTextEditing,
6672
- onFocusLost,
7892
+ editor,
6673
7893
  onSavePreEditSelection,
6674
- wasTextEditingRef
7894
+ wasTextEditingRef,
7895
+ onCancelPendingChanges,
7896
+ forceNextSyncRef
6675
7897
  ]
6676
7898
  );
6677
7899
  const ElementRenderer = (0, react_exports.useMemo)(
6678
- () => createElementRenderer(isEditMode, defaultTextStyle.lineHeight || "1.5"),
6679
- [isEditMode, defaultTextStyle.lineHeight]
7900
+ () => createElementRenderer(isEditMode, defaultTextStyle.lineHeight || "1.5", nameToValue, onLinkOpen),
7901
+ [isEditMode, defaultTextStyle.lineHeight, nameToValue, onLinkOpen]
6680
7902
  );
6681
7903
  const renderElement = (0, react_exports.useCallback)(
6682
7904
  (props) => /* @__PURE__ */ react_exports.createElement(ElementRenderer, __spreadValues({}, props)),
6683
7905
  [ElementRenderer]
6684
7906
  );
6685
7907
  const renderLeaf = (0, react_exports.useCallback)((props) => /* @__PURE__ */ react_exports.createElement(Leaf, __spreadValues({}, props)), []);
7908
+ const handleDOMBeforeInput = (0, react_exports.useCallback)(
7909
+ (event) => handleTextInsert(editor, event) || void 0,
7910
+ [editor]
7911
+ );
6686
7912
  const editableStyle = {
6687
7913
  color: defaultTextStyle.color || "#ffffff",
6688
7914
  fontSize: defaultTextStyle.fontSize || "14px",
6689
7915
  fontFamily: FONT_FAMILY_WITH_FALLBACKS[defaultTextStyle.fontFamily] || defaultTextStyle.fontFamily || FONT_FAMILY_WITH_FALLBACKS["Splunk Data Sans"],
6690
- lineHeight: defaultTextStyle.lineHeight || "1.5"
7916
+ lineHeight: defaultTextStyle.lineHeight || "1.5",
7917
+ // Text I-beam only while editing; otherwise inherit from wrapper so read-only
7918
+ // viewers don't get a text cursor (pointer when an interaction is bound).
7919
+ cursor: isTextEditing ? "text" : "inherit"
6691
7920
  };
7921
+ const editorContainerStyle = __spreadValues({
7922
+ // Keep the Slate editor's percentage min-height resolvable while actively editing so
7923
+ // vertical alignment has the same full-height layout used in read-only mode.
7924
+ minHeight: "100%"
7925
+ }, isTextEditing ? {} : { caretColor: "transparent", outline: "none" });
6692
7926
  return /* @__PURE__ */ react_exports.createElement(
6693
7927
  "div",
6694
7928
  {
@@ -6696,7 +7930,8 @@ var InnerEditor = ({
6696
7930
  suppressContentEditableWarning: true,
6697
7931
  onMouseDown: handleMouseDown,
6698
7932
  onClick: handleEmptySpaceClick,
6699
- style: isTextEditing ? void 0 : { minHeight: "100%", caretColor: "transparent", outline: "none" }
7933
+ onDragStart: handleDragStart,
7934
+ style: editorContainerStyle
6700
7935
  },
6701
7936
  /* @__PURE__ */ react_exports.createElement(slate_react_exports.Slate, { editor, initialValue: value, onChange: handleChange }, /* @__PURE__ */ react_exports.createElement(
6702
7937
  slate_react_exports.Editable,
@@ -6707,9 +7942,12 @@ var InnerEditor = ({
6707
7942
  decorate,
6708
7943
  renderElement,
6709
7944
  renderLeaf,
7945
+ onDOMBeforeInput: handleDOMBeforeInput,
7946
+ scrollSelectionIntoView: scrollCaretWithinEditor,
6710
7947
  style: editableStyle,
6711
7948
  ref: editableRef,
6712
7949
  onKeyDown: handleKeyDown,
7950
+ onPaste: onPasteStart,
6713
7951
  onDragStart: handleDragStart,
6714
7952
  onFocus: handleFocus,
6715
7953
  onBlur: handleBlur,
@@ -6774,132 +8012,6 @@ function useRichTextState() {
6774
8012
  };
6775
8013
  }
6776
8014
 
6777
- // src/RichText/PureRichText/hooks/useTokenMap.ts
6778
- var TOKEN_PATTERN = /\$([a-zA-Z_]\w*)\$/g;
6779
- function getVizIdFromDom(containerRef) {
6780
- var _a, _b, _c;
6781
- const vizItem = (_a = containerRef.current) == null ? void 0 : _a.closest('[data-test="viz-item"]');
6782
- return (_c = (_b = vizItem == null ? void 0 : vizItem.dataset) == null ? void 0 : _b.id) != null ? _c : null;
6783
- }
6784
- function getRawContent(api, containerRef) {
6785
- var _a, _b, _c;
6786
- if (!(api == null ? void 0 : api.getDefinition)) return null;
6787
- const vizId = getVizIdFromDom(containerRef);
6788
- if (!vizId) return null;
6789
- try {
6790
- const def = api.getDefinition();
6791
- const rawContent = (_c = (_b = (_a = def == null ? void 0 : def.visualizations) == null ? void 0 : _a[vizId]) == null ? void 0 : _b.options) == null ? void 0 : _c.richTextContent;
6792
- return typeof rawContent === "string" ? rawContent : null;
6793
- } catch (e) {
6794
- return null;
6795
- }
6796
- }
6797
- function buildTokenMap(rawContent, resolvedContent) {
6798
- const map = /* @__PURE__ */ new Map();
6799
- const tokens = [];
6800
- let match;
6801
- const re = new RegExp(TOKEN_PATTERN.source, "g");
6802
- match = re.exec(rawContent);
6803
- while (match !== null) {
6804
- tokens.push(match[1]);
6805
- match = re.exec(rawContent);
6806
- }
6807
- if (tokens.length === 0) return map;
6808
- const escapedParts = rawContent.split(TOKEN_PATTERN);
6809
- let pattern = "";
6810
- for (let i = 0; i < escapedParts.length; i += 1) {
6811
- if (i % 2 === 0) {
6812
- pattern += escapedParts[i].replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6813
- } else {
6814
- pattern += "([\\s\\S]*?)";
6815
- }
6816
- }
6817
- const fullMatch = new RegExp(`^${pattern}$`).exec(resolvedContent);
6818
- if (!fullMatch) return map;
6819
- for (let i = 0; i < tokens.length; i += 1) {
6820
- const resolved = fullMatch[i + 1];
6821
- if (resolved !== void 0) {
6822
- map.set(resolved, `$${tokens[i]}$`);
6823
- }
6824
- }
6825
- return map;
6826
- }
6827
- function restoreTokens(html, tokenMap) {
6828
- if (tokenMap.size === 0) return html;
6829
- let result = html;
6830
- const entries = [...tokenMap.entries()].filter(([resolved]) => resolved !== "").sort((a, b) => b[0].length - a[0].length);
6831
- for (const [resolved, tokenPattern] of entries) {
6832
- result = result.split(resolved).join(tokenPattern);
6833
- }
6834
- return result;
6835
- }
6836
- function wrapTokensInTree(nodes, tokenMap) {
6837
- if (tokenMap.size === 0) return nodes;
6838
- const resolvedToName = /* @__PURE__ */ new Map();
6839
- for (const [resolved, pattern] of tokenMap) {
6840
- if (resolved === "") return nodes;
6841
- const name = pattern.slice(1, -1);
6842
- resolvedToName.set(resolved, name);
6843
- }
6844
- const processNode = (node) => {
6845
- if (slate_exports.Text.isText(node)) {
6846
- return splitTextByTokens(node, resolvedToName);
6847
- }
6848
- if (slate_exports.Element.isElement(node)) {
6849
- const el = node;
6850
- return [__spreadProps(__spreadValues({}, el), { children: el.children.flatMap(processNode) })];
6851
- }
6852
- return [node];
6853
- };
6854
- return nodes.flatMap(processNode);
6855
- }
6856
- function splitTextByTokens(textNode, resolvedToName) {
6857
- const _a = textNode, { text } = _a, marks = __objRest(_a, ["text"]);
6858
- if (!text) return [textNode];
6859
- const entries = [...resolvedToName.entries()].sort((a, b) => b[0].length - a[0].length);
6860
- let earliestIdx = -1;
6861
- let matchedResolved = "";
6862
- let matchedName = "";
6863
- for (const [resolved, name] of entries) {
6864
- const idx = text.indexOf(resolved);
6865
- if (idx !== -1 && (earliestIdx === -1 || idx < earliestIdx)) {
6866
- earliestIdx = idx;
6867
- matchedResolved = resolved;
6868
- matchedName = name;
6869
- }
6870
- }
6871
- if (earliestIdx === -1) return [textNode];
6872
- const result = [];
6873
- if (earliestIdx > 0) {
6874
- result.push(__spreadValues({ text: text.slice(0, earliestIdx) }, marks));
6875
- }
6876
- result.push(__spreadProps(__spreadValues({ text: matchedResolved }, marks), { tokenName: matchedName }));
6877
- const after = text.slice(earliestIdx + matchedResolved.length);
6878
- if (after) {
6879
- const afterNode = __spreadValues({ text: after }, marks);
6880
- result.push(...splitTextByTokens(afterNode, resolvedToName));
6881
- }
6882
- return result;
6883
- }
6884
- var EMPTY_MAP = /* @__PURE__ */ new Map();
6885
- function useTokenMap(dashboardCoreApi, containerRef, resolvedContent) {
6886
- const [tokenMap, setTokenMap] = (0, react_exports.useState)(EMPTY_MAP);
6887
- (0, react_exports.useEffect)(() => {
6888
- const raw = getRawContent(dashboardCoreApi, containerRef);
6889
- if (!raw) {
6890
- setTokenMap((prev) => prev.size === 0 ? prev : EMPTY_MAP);
6891
- return;
6892
- }
6893
- const map = buildTokenMap(raw, resolvedContent);
6894
- setTokenMap(map);
6895
- }, [dashboardCoreApi, resolvedContent, containerRef]);
6896
- const restoreTokensInHtml = (0, react_exports.useMemo)(() => {
6897
- if (tokenMap.size === 0) return (html) => html;
6898
- return (html) => restoreTokens(html, tokenMap);
6899
- }, [tokenMap]);
6900
- return { restoreTokensInHtml, tokenMap };
6901
- }
6902
-
6903
8015
  // src/RichText/PureRichText/hooks/useContentSave.ts
6904
8016
  var TYPING_IDLE_MS = 300;
6905
8017
  function useContentSave({
@@ -6969,7 +8081,14 @@ function useContentSave({
6969
8081
  pendingHtmlRef.current = null;
6970
8082
  }
6971
8083
  }, [save]);
6972
- return { handleContentChange, flushPendingChanges, recentSavesRef };
8084
+ const cancelPendingChanges = (0, react_exports.useCallback)(() => {
8085
+ if (idleTimerRef.current) {
8086
+ clearTimeout(idleTimerRef.current);
8087
+ idleTimerRef.current = null;
8088
+ }
8089
+ pendingHtmlRef.current = null;
8090
+ }, []);
8091
+ return { handleContentChange, flushPendingChanges, cancelPendingChanges, recentSavesRef };
6973
8092
  }
6974
8093
 
6975
8094
  // src/RichText/PureRichText/hooks/useDashboardKeyboardNav.ts
@@ -6977,20 +8096,21 @@ function useSkipLinkAndFocusOut({
6977
8096
  isEditMode,
6978
8097
  containerRef,
6979
8098
  slateEditorRef,
8099
+ isTextEditingRef,
6980
8100
  wasTextEditingRef,
6981
8101
  clearFakeHighlightRef,
6982
8102
  deactivateTextEditing,
6983
8103
  dashboardCoreApi
6984
8104
  }) {
6985
8105
  (0, react_exports.useEffect)(() => {
6986
- var _a;
8106
+ var _a2;
6987
8107
  if (!isEditMode) return void 0;
6988
- const vizItem = (_a = containerRef.current) == null ? void 0 : _a.closest('[data-test="viz-item"]');
8108
+ const vizItem = (_a2 = containerRef.current) == null ? void 0 : _a2.closest('[data-test="viz-item"]');
6989
8109
  if (!vizItem) return void 0;
6990
8110
  const handleEscapeOnSkipLink = (configLink) => {
6991
- var _a2;
8111
+ var _a3;
6992
8112
  if (configLink) configLink.setAttribute("tabindex", "-1");
6993
- (_a2 = clearFakeHighlightRef.current) == null ? void 0 : _a2.call(clearFakeHighlightRef);
8113
+ (_a3 = clearFakeHighlightRef.current) == null ? void 0 : _a3.call(clearFakeHighlightRef);
6994
8114
  const ed = slateEditorRef.current;
6995
8115
  if (ed) {
6996
8116
  safeDeselect(ed);
@@ -7024,14 +8144,26 @@ function useSkipLinkAndFocusOut({
7024
8144
  if (actionMenuLink) actionMenuLink.setAttribute("tabindex", "-1");
7025
8145
  };
7026
8146
  const handleKeyDown = (e) => {
7027
- if (!vizItem.contains(e.target)) return;
8147
+ var _a3, _b;
7028
8148
  const target = e.target;
8149
+ if (!vizItem.contains(target)) return;
7029
8150
  const configLink = vizItem.querySelector('[data-test="skip-link-config"]');
7030
8151
  if (e.key === "Escape" && target.closest('[data-test="skip-link-config"]')) {
7031
8152
  e.preventDefault();
7032
8153
  handleEscapeOnSkipLink(configLink);
7033
8154
  return;
7034
8155
  }
8156
+ if (e.key === "Escape" && !isTextEditingRef.current) {
8157
+ const isSelected = ((_a3 = containerRef.current) == null ? void 0 : _a3.closest('[data-selected="true"]')) != null;
8158
+ if (isSelected) {
8159
+ e.preventDefault();
8160
+ (_b = document.activeElement) == null ? void 0 : _b.blur();
8161
+ if (dashboardCoreApi) {
8162
+ dashboardCoreApi.updateSelectedItems([]);
8163
+ }
8164
+ return;
8165
+ }
8166
+ }
7035
8167
  if (e.key !== "Tab") return;
7036
8168
  if (e.shiftKey) {
7037
8169
  handleShiftTab(e, target, configLink);
@@ -7078,15 +8210,17 @@ function useSidebarAndEditActivation({
7078
8210
  (0, react_exports.useEffect)(() => {
7079
8211
  if (!isEditMode) return void 0;
7080
8212
  const getOurVizItem = () => {
7081
- var _a, _b;
7082
- return (_b = (_a = containerRef.current) == null ? void 0 : _a.closest('[data-test="viz-item"]')) != null ? _b : null;
8213
+ var _a2, _b;
8214
+ return (_b = (_a2 = containerRef.current) == null ? void 0 : _a2.closest('[data-test="viz-item"]')) != null ? _b : null;
7083
8215
  };
7084
- const isTargetInSidebar = (target, vizItem) => !(vizItem == null ? void 0 : vizItem.contains(target)) && Boolean(
8216
+ const isTargetInSidebar = (target, vizItem) => !(vizItem == null ? void 0 : vizItem.contains(target)) && // The link popover (Cmd+K) owns its own Escape (useLinkHandlers); excluded here so
8217
+ // this capture handler doesn't intercept it, forcing a second Escape to close.
8218
+ !target.closest('[data-test="link-popover-content"]') && Boolean(
7085
8219
  target.closest('[data-test="sidebar-content"]') || target.closest('[data-test="header"]') || target.id === "configuration-back-button" || target.closest("#configuration-back-button") || target.closest('[data-test="popover"]') || target.closest("[data-test-popover-id]")
7086
8220
  );
7087
8221
  const handleEscapeFromSidebar = (e) => {
7088
- var _a, _b;
7089
- const isSelected = ((_a = containerRef.current) == null ? void 0 : _a.closest('[data-selected="true"]')) != null;
8222
+ var _a2, _b;
8223
+ const isSelected = ((_a2 = containerRef.current) == null ? void 0 : _a2.closest('[data-selected="true"]')) != null;
7090
8224
  if (!isSelected) return;
7091
8225
  e.preventDefault();
7092
8226
  e.stopImmediatePropagation();
@@ -7094,15 +8228,15 @@ function useSidebarAndEditActivation({
7094
8228
  const selToRestore = ((_b = slateEditorRef.current) == null ? void 0 : _b.selection) || richTextState.getPreEditSelection();
7095
8229
  richTextState.returnFromConfigPanel();
7096
8230
  requestAnimationFrame(() => {
7097
- var _a2, _b2;
7098
- const editable = (_a2 = containerRef.current) == null ? void 0 : _a2.querySelector("[data-slate-editor]");
8231
+ var _a3, _b2;
8232
+ const editable = (_a3 = containerRef.current) == null ? void 0 : _a3.querySelector("[data-slate-editor]");
7099
8233
  editable == null ? void 0 : editable.focus();
7100
8234
  const ed = slateEditorRef.current;
7101
8235
  if (ed && selToRestore) {
7102
8236
  try {
7103
8237
  slate_exports.Transforms.select(ed, selToRestore);
7104
8238
  const domRange = slate_react_exports.ReactEditor.toDOMRange(ed, selToRestore);
7105
- const domSel = window.getSelection();
8239
+ const domSel = globalThis.getSelection();
7106
8240
  domSel == null ? void 0 : domSel.removeAllRanges();
7107
8241
  domSel == null ? void 0 : domSel.addRange(domRange);
7108
8242
  } catch (e2) {
@@ -7116,7 +8250,7 @@ function useSidebarAndEditActivation({
7116
8250
  });
7117
8251
  };
7118
8252
  const handleSkipLinkActivate = (e) => {
7119
- var _a;
8253
+ var _a2;
7120
8254
  e.preventDefault();
7121
8255
  e.stopImmediatePropagation();
7122
8256
  registerActiveRichText(instanceId, null, slateEditorRef.current);
@@ -7131,7 +8265,7 @@ function useSidebarAndEditActivation({
7131
8265
  } catch (e2) {
7132
8266
  }
7133
8267
  }
7134
- (_a = updateActiveStylesFnRef.current) == null ? void 0 : _a.call(updateActiveStylesFnRef);
8268
+ (_a2 = updateActiveStylesFnRef.current) == null ? void 0 : _a2.call(updateActiveStylesFnRef);
7135
8269
  }
7136
8270
  richTextState.clearWasTextEditing();
7137
8271
  const configBtn = document.getElementById("configuration-back-button");
@@ -7140,7 +8274,7 @@ function useSidebarAndEditActivation({
7140
8274
  }
7141
8275
  };
7142
8276
  const handleKeyDown = (e) => {
7143
- var _a;
8277
+ var _a2;
7144
8278
  const target = e.target;
7145
8279
  const ourVizItem = getOurVizItem();
7146
8280
  if (e.key === "Escape" && isTargetInSidebar(target, ourVizItem)) {
@@ -7153,7 +8287,7 @@ function useSidebarAndEditActivation({
7153
8287
  return;
7154
8288
  }
7155
8289
  if (e.key === "Enter" && !isTextEditingRef.current) {
7156
- const isVizSelected = ((_a = containerRef.current) == null ? void 0 : _a.closest('[data-selected="true"]')) != null;
8290
+ const isVizSelected = ((_a2 = containerRef.current) == null ? void 0 : _a2.closest('[data-selected="true"]')) != null;
7157
8291
  if (!isVizSelected) return;
7158
8292
  e.preventDefault();
7159
8293
  e.stopImmediatePropagation();
@@ -7161,8 +8295,8 @@ function useSidebarAndEditActivation({
7161
8295
  }
7162
8296
  };
7163
8297
  const handleClick2 = (e) => {
7164
- var _a;
7165
- const link = (_a = e.target) == null ? void 0 : _a.closest('[data-test="skip-link-config"]');
8298
+ var _a2;
8299
+ const link = (_a2 = e.target) == null ? void 0 : _a2.closest('[data-test="skip-link-config"]');
7166
8300
  if (!link) return;
7167
8301
  const ourVizItem = getOurVizItem();
7168
8302
  if (!(ourVizItem == null ? void 0 : ourVizItem.contains(link))) return;
@@ -7186,6 +8320,7 @@ function useDashboardKeyboardNav(args) {
7186
8320
  isEditMode: args.isEditMode,
7187
8321
  containerRef: args.containerRef,
7188
8322
  slateEditorRef: args.slateEditorRef,
8323
+ isTextEditingRef: args.isTextEditingRef,
7189
8324
  wasTextEditingRef: args.wasTextEditingRef,
7190
8325
  clearFakeHighlightRef: args.clearFakeHighlightRef,
7191
8326
  deactivateTextEditing: args.richTextState.deactivateTextEditing,
@@ -7201,8 +8336,220 @@ function useIsActiveRichText(id) {
7201
8336
  () => getActiveRichTextId() === id
7202
8337
  );
7203
8338
  }
8339
+ var identityRestore = (html) => html;
8340
+ var CONTAINER_MOVE_THRESHOLD = 4;
8341
+ function resolveTokenDisplay(args) {
8342
+ const { isEditMode, previewTokenValues, resolvedContent, rawContent } = args;
8343
+ const showResolvedTokens = !isEditMode || previewTokenValues;
8344
+ const editorSourceContent = rawContent != null ? rawContent : resolvedContent;
8345
+ return { editorSourceContent, showResolvedTokens };
8346
+ }
8347
+ function resolveFontSize(defaultTextStyles, fontSize, customFontSize) {
8348
+ if (defaultTextStyles == null ? void 0 : defaultTextStyles.fontSize) {
8349
+ const dtsFs = defaultTextStyles.fontSize;
8350
+ if (typeof dtsFs === "string" && dtsFs.endsWith("px")) {
8351
+ return { effectiveFontSize: "custom", effectiveCustomFontSize: Number.parseInt(dtsFs, 10) };
8352
+ }
8353
+ }
8354
+ return { effectiveFontSize: fontSize, effectiveCustomFontSize: customFontSize };
8355
+ }
8356
+ function handleTokenToggle(args) {
8357
+ const { editor, richTextContent, recentSavesRef, cancelPendingChanges, forceNextSyncRef } = args;
8358
+ forceNextSyncRef.current = true;
8359
+ if (!editor) return { pendingSave: null, editorSourceOverride: null };
8360
+ const currentRawHtml = slateToHtml(editor.children);
8361
+ if (currentRawHtml !== richTextContent) {
8362
+ recentSavesRef.current.add(currentRawHtml);
8363
+ }
8364
+ cancelPendingChanges();
8365
+ return {
8366
+ pendingSave: currentRawHtml === richTextContent ? null : currentRawHtml,
8367
+ editorSourceOverride: currentRawHtml
8368
+ };
8369
+ }
8370
+ var TOKEN_PASTE_SETTLE_MS = 300;
8371
+ function useTokenResolutionScheduler(resolverRef, enabled) {
8372
+ const pasteBurstRef = (0, react_exports.useRef)(false);
8373
+ const timerRef = (0, react_exports.useRef)(null);
8374
+ const hasPendingRequestRef = (0, react_exports.useRef)(false);
8375
+ const includeValueChangesRef = (0, react_exports.useRef)(false);
8376
+ const enabledRef = (0, react_exports.useRef)(enabled);
8377
+ enabledRef.current = enabled;
8378
+ const clearTimer = (0, react_exports.useCallback)(() => {
8379
+ if (timerRef.current !== null) {
8380
+ clearTimeout(timerRef.current);
8381
+ timerRef.current = null;
8382
+ }
8383
+ }, []);
8384
+ const cancelPendingResolution = (0, react_exports.useCallback)(() => {
8385
+ clearTimer();
8386
+ pasteBurstRef.current = false;
8387
+ hasPendingRequestRef.current = false;
8388
+ includeValueChangesRef.current = false;
8389
+ }, [clearTimer]);
8390
+ const flushPendingResolution = (0, react_exports.useCallback)(() => {
8391
+ var _a2;
8392
+ const shouldResolve = enabledRef.current && hasPendingRequestRef.current;
8393
+ const includeValueChanges = includeValueChangesRef.current;
8394
+ clearTimer();
8395
+ pasteBurstRef.current = false;
8396
+ hasPendingRequestRef.current = false;
8397
+ includeValueChangesRef.current = false;
8398
+ if (shouldResolve) {
8399
+ (_a2 = resolverRef.current) == null ? void 0 : _a2.call(resolverRef, includeValueChanges);
8400
+ }
8401
+ }, [clearTimer, resolverRef]);
8402
+ const restartPasteTimer = (0, react_exports.useCallback)(() => {
8403
+ clearTimer();
8404
+ timerRef.current = setTimeout(flushPendingResolution, TOKEN_PASTE_SETTLE_MS);
8405
+ }, [clearTimer, flushPendingResolution]);
8406
+ const beginPasteBurst = (0, react_exports.useCallback)(() => {
8407
+ if (!enabledRef.current) return;
8408
+ pasteBurstRef.current = true;
8409
+ restartPasteTimer();
8410
+ }, [restartPasteTimer]);
8411
+ const requestResolutionRef = (0, react_exports.useRef)(null);
8412
+ requestResolutionRef.current = enabled ? (includeValueChanges = false) => {
8413
+ var _a2;
8414
+ if (!pasteBurstRef.current) {
8415
+ (_a2 = resolverRef.current) == null ? void 0 : _a2.call(resolverRef, includeValueChanges);
8416
+ return;
8417
+ }
8418
+ hasPendingRequestRef.current = true;
8419
+ includeValueChangesRef.current || (includeValueChangesRef.current = includeValueChanges);
8420
+ restartPasteTimer();
8421
+ } : null;
8422
+ (0, react_exports.useEffect)(() => {
8423
+ if (!enabled) {
8424
+ cancelPendingResolution();
8425
+ }
8426
+ }, [cancelPendingResolution, enabled]);
8427
+ (0, react_exports.useEffect)(() => cancelPendingResolution, [cancelPendingResolution]);
8428
+ return {
8429
+ beginPasteBurst,
8430
+ flushPendingResolution,
8431
+ requestResolutionRef
8432
+ };
8433
+ }
8434
+ function resolvePoint(editor, absOffset, isStart = false) {
8435
+ const point = absOffsetToPoint(editor, absOffset, isStart);
8436
+ if (point) return point;
8437
+ try {
8438
+ return slate_exports.Editor.end(editor, []);
8439
+ } catch (e) {
8440
+ return null;
8441
+ }
8442
+ }
8443
+ function moveCaretPastTokenIfNeeded(editor) {
8444
+ if (!editor.selection || !slate_exports.Editor.isEditor(editor)) return;
8445
+ const { anchor, focus } = editor.selection;
8446
+ const isCollapsed = anchor.offset === focus.offset && anchor.path.join(",") === focus.path.join(",");
8447
+ if (!isCollapsed) return;
8448
+ try {
8449
+ const [node] = slate_exports.Editor.node(editor, anchor);
8450
+ const custom = node;
8451
+ if (!slate_exports.Text.isText(node) || !(custom.tokenName || custom.isEscapedDollar)) return;
8452
+ const endPoint = { path: anchor.path, offset: node.text.length };
8453
+ const blockPath = anchor.path.slice(0, -1);
8454
+ const afterToken = slate_exports.Editor.after(editor, endPoint);
8455
+ const staysInBlock = afterToken && afterToken.path.length > blockPath.length && afterToken.path.slice(0, blockPath.length).join(",") === blockPath.join(",");
8456
+ editor.selection = {
8457
+ anchor: staysInBlock ? afterToken : endPoint,
8458
+ focus: staysInBlock ? afterToken : endPoint
8459
+ };
8460
+ } catch (e) {
8461
+ }
8462
+ }
8463
+ function adjustAbsOffsetForResolution(absOffset, tokenResolvedLengths) {
8464
+ let adjustment = 0;
8465
+ for (const { absStart, rawLen, resolvedLen } of tokenResolvedLengths) {
8466
+ if (absOffset > absStart + rawLen - 1) {
8467
+ adjustment += resolvedLen - rawLen;
8468
+ } else if (absOffset > absStart) {
8469
+ adjustment += resolvedLen - rawLen;
8470
+ break;
8471
+ }
8472
+ }
8473
+ return absOffset + adjustment;
8474
+ }
8475
+ function displayForToken(tokenName, nameToValue) {
8476
+ const value = nameToValue.get(tokenName);
8477
+ return value !== void 0 && value !== "" ? value : `$${tokenName}$`;
8478
+ }
8479
+ function bareTokensInPlainText(text, baseOffset, nameToValue) {
8480
+ var _a2;
8481
+ const result = [];
8482
+ const re = new RegExp(TOKEN_OR_ESCAPE_PATTERN.source, "g");
8483
+ let m = re.exec(text);
8484
+ while (m !== null) {
8485
+ const rawPattern = m[0];
8486
+ const tokenName = m[1];
8487
+ const resolvedValue = tokenName === void 0 ? "$" : (_a2 = nameToValue.get(tokenName)) != null ? _a2 : rawPattern;
8488
+ result.push({
8489
+ absStart: baseOffset + m.index,
8490
+ rawLen: rawPattern.length,
8491
+ resolvedLen: resolvedValue.length
8492
+ });
8493
+ m = re.exec(text);
8494
+ }
8495
+ return result;
8496
+ }
8497
+ function bareTokensInNode(node, runningOffset, nameToValue, includeValueChanges) {
8498
+ const { text } = node;
8499
+ if (node.tokenName) {
8500
+ const target = displayForToken(node.tokenName, nameToValue);
8501
+ if (!node.isRawToken && !(includeValueChanges && text !== target)) return [];
8502
+ return [{ absStart: runningOffset, rawLen: text.length, resolvedLen: target.length }];
8503
+ }
8504
+ if (node.isEscapedDollar) {
8505
+ if (!node.isRawToken || !/^\$+$/.test(text)) return [];
8506
+ return [{ absStart: runningOffset, rawLen: text.length, resolvedLen: text.length / 2 }];
8507
+ }
8508
+ return bareTokensInPlainText(text, runningOffset, nameToValue);
8509
+ }
8510
+ function collectBareTokens(editor, nameToValue, includeValueChanges) {
8511
+ const result = [];
8512
+ let runningOffset = 0;
8513
+ for (const [textNode] of slate_exports.Editor.nodes(editor, { at: [], match: (n) => slate_exports.Text.isText(n) })) {
8514
+ result.push(...bareTokensInNode(textNode, runningOffset, nameToValue, includeValueChanges));
8515
+ runningOffset += textNode.text.length;
8516
+ }
8517
+ return result;
8518
+ }
8519
+ function buildAutoResolveCallback(args) {
8520
+ const { slateEditorRef, nameToValue } = args;
8521
+ return (includeValueChanges = false) => {
8522
+ const editor = slateEditorRef.current;
8523
+ if (!editor) return;
8524
+ const bareTokenInfo = collectBareTokens(editor, nameToValue, includeValueChanges);
8525
+ if (bareTokenInfo.length === 0) return;
8526
+ const rawAnchorAbs = editor.selection ? pointToAbsOffset(editor, editor.selection.anchor) : null;
8527
+ const rawFocusAbs = editor.selection ? pointToAbsOffset(editor, editor.selection.focus) : null;
8528
+ const newTree = wrapRawTokensInTree(editor.children, nameToValue);
8529
+ const anchorAbs = rawAnchorAbs === null ? null : adjustAbsOffsetForResolution(rawAnchorAbs, bareTokenInfo);
8530
+ const focusAbs = rawFocusAbs === null ? null : adjustAbsOffsetForResolution(rawFocusAbs, bareTokenInfo);
8531
+ editor.children = newTree;
8532
+ if (anchorAbs !== null && focusAbs !== null) {
8533
+ const collapsed = anchorAbs === focusAbs;
8534
+ const anchor = resolvePoint(editor, anchorAbs, !collapsed);
8535
+ const focus = resolvePoint(editor, focusAbs, false);
8536
+ editor.selection = anchor && focus ? { anchor, focus } : null;
8537
+ } else {
8538
+ editor.selection = null;
8539
+ }
8540
+ moveCaretPastTokenIfNeeded(editor);
8541
+ const selectionAfterResolve = editor.selection;
8542
+ editor.onChange();
8543
+ if (selectionAfterResolve) {
8544
+ try {
8545
+ slate_exports.Transforms.select(editor, selectionAfterResolve);
8546
+ } catch (e) {
8547
+ }
8548
+ }
8549
+ };
8550
+ }
7204
8551
  var PureRichText = react_exports.forwardRef((props, ref) => {
7205
- var _a, _b, _c, _d;
8552
+ var _a2, _b, _c, _d;
7206
8553
  const theme = (0, themes_exports.useSplunkTheme)();
7207
8554
  const themeTextColor = theme.contentColorDefault;
7208
8555
  const {
@@ -7220,35 +8567,42 @@ var PureRichText = react_exports.forwardRef((props, ref) => {
7220
8567
  mode = "view",
7221
8568
  onOptionsChange,
7222
8569
  onRichtextClick = lodash_exports.noop,
8570
+ onLinkOpen,
7223
8571
  hasEventHandlers = false,
7224
8572
  bold = false,
7225
8573
  italic = false,
7226
8574
  underline = false,
7227
8575
  strikethrough = false,
7228
- defaultTextStyles
8576
+ defaultTextStyles,
8577
+ previewTokenValues = false,
8578
+ richTextTokenMetadata: richTextTokenMetadataProp
7229
8579
  } = props;
7230
8580
  const effectiveFontColorFromStyles = (defaultTextStyles == null ? void 0 : defaultTextStyles.color) || fontColor;
7231
8581
  const effectiveHighlightColor = (defaultTextStyles == null ? void 0 : defaultTextStyles.backgroundColor) || highlightColor;
7232
8582
  const effectiveFontFamily = (defaultTextStyles == null ? void 0 : defaultTextStyles.fontFamily) || fontFamily;
7233
- const effectiveBold = (_a = defaultTextStyles == null ? void 0 : defaultTextStyles.bold) != null ? _a : bold;
8583
+ const effectiveBold = (_a2 = defaultTextStyles == null ? void 0 : defaultTextStyles.bold) != null ? _a2 : bold;
7234
8584
  const effectiveItalic = (_b = defaultTextStyles == null ? void 0 : defaultTextStyles.italic) != null ? _b : italic;
7235
8585
  const effectiveUnderline = (_c = defaultTextStyles == null ? void 0 : defaultTextStyles.underline) != null ? _c : underline;
7236
8586
  const effectiveStrikethrough = (_d = defaultTextStyles == null ? void 0 : defaultTextStyles.strikethrough) != null ? _d : strikethrough;
7237
- let effectiveFontSize = fontSize;
7238
- let effectiveCustomFontSize = customFontSize;
7239
- if (defaultTextStyles == null ? void 0 : defaultTextStyles.fontSize) {
7240
- const dtsFs = defaultTextStyles.fontSize;
7241
- if (typeof dtsFs === "string" && dtsFs.endsWith("px")) {
7242
- effectiveCustomFontSize = parseInt(dtsFs, 10);
7243
- effectiveFontSize = "custom";
7244
- }
7245
- }
8587
+ const { effectiveFontSize, effectiveCustomFontSize } = resolveFontSize(
8588
+ defaultTextStyles,
8589
+ fontSize,
8590
+ customFontSize
8591
+ );
8592
+ const handleLinkOpen = (0, react_exports.useMemo)(
8593
+ () => onLinkOpen ? (url) => onLinkOpen({ payload: { url } }) : void 0,
8594
+ [onLinkOpen]
8595
+ );
7246
8596
  const effectiveFontColor = effectiveFontColorFromStyles || themeTextColor;
7247
8597
  const isEditMode = mode === "edit";
7248
8598
  const containerRef = (0, react_exports.useRef)(null);
8599
+ const containerMouseDownRef = (0, react_exports.useRef)(null);
7249
8600
  const slateEditorRef = (0, react_exports.useRef)(null);
8601
+ const editorHasFocusRef = (0, react_exports.useRef)(false);
7250
8602
  const updateActiveStylesFnRef = (0, react_exports.useRef)(null);
7251
8603
  const clearFakeHighlightRef = (0, react_exports.useRef)(null);
8604
+ const forceNextSyncRef = (0, react_exports.useRef)(false);
8605
+ const transformTreeRef = (0, react_exports.useRef)(null);
7252
8606
  const setContainerRef = (0, react_exports.useCallback)(
7253
8607
  (node) => {
7254
8608
  containerRef.current = node;
@@ -7280,16 +8634,16 @@ var PureRichText = react_exports.forwardRef((props, ref) => {
7280
8634
  }
7281
8635
  }, [isEditMode, instanceId]);
7282
8636
  (0, react_exports.useEffect)(() => {
7283
- var _a2;
8637
+ var _a3;
7284
8638
  if (!isEditMode || isTextEditing) return void 0;
7285
8639
  const checkAndRegister = () => {
7286
- var _a3;
7287
- const isSelected = ((_a3 = containerRef.current) == null ? void 0 : _a3.closest('[data-selected="true"]')) != null;
8640
+ var _a4;
8641
+ const isSelected = ((_a4 = containerRef.current) == null ? void 0 : _a4.closest('[data-selected="true"]')) != null;
7288
8642
  if (isSelected) {
7289
8643
  registerActiveRichText(instanceId, null, slateEditorRef.current);
7290
8644
  }
7291
8645
  };
7292
- const selectedAncestor = (_a2 = containerRef.current) == null ? void 0 : _a2.closest("[data-selected]");
8646
+ const selectedAncestor = (_a3 = containerRef.current) == null ? void 0 : _a3.closest("[data-selected]");
7293
8647
  let observer = null;
7294
8648
  if (selectedAncestor) {
7295
8649
  observer = new MutationObserver(checkAndRegister);
@@ -7304,12 +8658,12 @@ var PureRichText = react_exports.forwardRef((props, ref) => {
7304
8658
  };
7305
8659
  }, [instanceId, isEditMode, isTextEditing]);
7306
8660
  (0, react_exports.useEffect)(() => {
7307
- var _a2;
8661
+ var _a3;
7308
8662
  if (!isEditMode || !isTextEditing) return void 0;
7309
- const selectedAncestor = (_a2 = containerRef.current) == null ? void 0 : _a2.closest("[data-selected]");
8663
+ const selectedAncestor = (_a3 = containerRef.current) == null ? void 0 : _a3.closest("[data-selected]");
7310
8664
  if (!selectedAncestor) return void 0;
7311
8665
  const observer = new MutationObserver(() => {
7312
- const isSelected = selectedAncestor.getAttribute("data-selected") === "true";
8666
+ const isSelected = selectedAncestor.dataset.selected === "true";
7313
8667
  if (!isSelected) {
7314
8668
  richTextState.deactivateTextEditing();
7315
8669
  }
@@ -7334,35 +8688,93 @@ var PureRichText = react_exports.forwardRef((props, ref) => {
7334
8688
  const borderStyle = borderConfig.style || "solid";
7335
8689
  const borderRadius = borderConfig.radius || 0;
7336
8690
  const paddingValues = parsePadding(padding);
7337
- const { restoreTokensInHtml, tokenMap } = useTokenMap(dashboardCoreApi, containerRef, richTextContent);
7338
- const { handleContentChange, flushPendingChanges, recentSavesRef } = useContentSave({
7339
- richTextContent,
7340
- onOptionsChange,
7341
- restoreTokensInHtml
8691
+ const { nameToValue, rawContent } = useTokenMap(richTextContent, richTextTokenMetadataProp);
8692
+ const { editorSourceContent, showResolvedTokens } = resolveTokenDisplay({
8693
+ isEditMode,
8694
+ previewTokenValues,
8695
+ resolvedContent: richTextContent,
8696
+ rawContent
7342
8697
  });
8698
+ const { handleContentChange, flushPendingChanges, cancelPendingChanges, recentSavesRef } = useContentSave(
8699
+ {
8700
+ richTextContent: editorSourceContent,
8701
+ onOptionsChange,
8702
+ restoreTokensInHtml: identityRestore
8703
+ }
8704
+ );
8705
+ const prevShowResolvedRef = (0, react_exports.useRef)(showResolvedTokens);
8706
+ const pendingToggleSaveRef = (0, react_exports.useRef)(null);
8707
+ let editorSourceOverride = null;
8708
+ if (prevShowResolvedRef.current !== showResolvedTokens) {
8709
+ prevShowResolvedRef.current = showResolvedTokens;
8710
+ const result = handleTokenToggle({
8711
+ editor: slateEditorRef.current,
8712
+ richTextContent,
8713
+ recentSavesRef,
8714
+ cancelPendingChanges,
8715
+ forceNextSyncRef
8716
+ });
8717
+ pendingToggleSaveRef.current = result.pendingSave;
8718
+ editorSourceOverride = result.editorSourceOverride;
8719
+ }
8720
+ (0, react_exports.useEffect)(() => {
8721
+ const html = pendingToggleSaveRef.current;
8722
+ pendingToggleSaveRef.current = null;
8723
+ if (html !== null) {
8724
+ onOptionsChange == null ? void 0 : onOptionsChange({ richTextContent: html });
8725
+ }
8726
+ }, [showResolvedTokens]);
8727
+ transformTreeRef.current = (tree) => showResolvedTokens ? wrapRawTokensInTree(tree, nameToValue) : tree;
8728
+ const tokenResolverRef = (0, react_exports.useRef)(null);
8729
+ tokenResolverRef.current = showResolvedTokens ? buildAutoResolveCallback({ slateEditorRef, nameToValue }) : null;
8730
+ const {
8731
+ beginPasteBurst,
8732
+ flushPendingResolution,
8733
+ requestResolutionRef: autoResolveTokensRef
8734
+ } = useTokenResolutionScheduler(tokenResolverRef, showResolvedTokens);
8735
+ const prevNameToValueRef = (0, react_exports.useRef)(nameToValue);
8736
+ const prevEditorSourceContentRef = (0, react_exports.useRef)(editorSourceContent);
8737
+ (0, react_exports.useEffect)(() => {
8738
+ const prev = prevNameToValueRef.current;
8739
+ const tokenMapChanged = nameToValue !== prev;
8740
+ const sourceContentChanged = editorSourceContent !== prevEditorSourceContentRef.current;
8741
+ prevNameToValueRef.current = nameToValue;
8742
+ prevEditorSourceContentRef.current = editorSourceContent;
8743
+ if ((tokenMapChanged || sourceContentChanged) && autoResolveTokensRef.current) {
8744
+ autoResolveTokensRef.current(tokenMapChanged);
8745
+ }
8746
+ }, [autoResolveTokensRef, editorSourceContent, nameToValue]);
8747
+ const effectiveEditorSourceContent = editorSourceOverride != null ? editorSourceOverride : editorSourceContent;
8748
+ const initialValueTokenMap = showResolvedTokens ? nameToValue : null;
7343
8749
  const initialValueRef = (0, react_exports.useRef)(EMPTY_SLATE_VALUE);
8750
+ const initialValueModeRef = (0, react_exports.useRef)(showResolvedTokens);
7344
8751
  const initialValue = (0, react_exports.useMemo)(() => {
7345
- if (recentSavesRef.current.has(richTextContent) || isTextEditingRef.current) {
8752
+ const modeChanged = initialValueModeRef.current !== showResolvedTokens;
8753
+ initialValueModeRef.current = showResolvedTokens;
8754
+ if (!modeChanged && (recentSavesRef.current.has(effectiveEditorSourceContent) || isTextEditingRef.current && editorHasFocusRef.current)) {
7346
8755
  return initialValueRef.current;
7347
8756
  }
7348
- if (!richTextContent) {
8757
+ if (!effectiveEditorSourceContent) {
7349
8758
  initialValueRef.current = EMPTY_SLATE_VALUE;
7350
8759
  return EMPTY_SLATE_VALUE;
7351
8760
  }
7352
- const tree = htmlToSlate(richTextContent);
7353
- const result = wrapTokensInTree(tree, tokenMap);
8761
+ const tree = htmlToSlate(effectiveEditorSourceContent);
8762
+ const result = initialValueTokenMap ? wrapRawTokensInTree(tree, initialValueTokenMap) : tree;
7354
8763
  initialValueRef.current = result;
7355
8764
  return result;
7356
- }, [richTextContent, tokenMap]);
8765
+ }, [effectiveEditorSourceContent, initialValueTokenMap, showResolvedTokens]);
7357
8766
  const handleFocusGained = (0, react_exports.useCallback)(
7358
8767
  (editable, slateEditor) => {
8768
+ editorHasFocusRef.current = true;
7359
8769
  registerActiveRichText(instanceId, editable, slateEditor);
7360
8770
  },
7361
8771
  [instanceId]
7362
8772
  );
7363
8773
  const handleFocusLost = (0, react_exports.useCallback)(() => {
8774
+ editorHasFocusRef.current = false;
8775
+ flushPendingResolution();
7364
8776
  flushPendingChanges();
7365
- }, [flushPendingChanges]);
8777
+ }, [flushPendingChanges, flushPendingResolution]);
7366
8778
  (0, react_exports.useEffect)(() => {
7367
8779
  return () => {
7368
8780
  flushPendingChanges();
@@ -7403,8 +8815,8 @@ var PureRichText = react_exports.forwardRef((props, ref) => {
7403
8815
  const activateTextEditing = (0, react_exports.useCallback)(() => {
7404
8816
  richTextState.activateTextEditing();
7405
8817
  requestAnimationFrame(() => {
7406
- var _a2;
7407
- const editable = (_a2 = containerRef.current) == null ? void 0 : _a2.querySelector("[data-slate-editor]");
8818
+ var _a3;
8819
+ const editable = (_a3 = containerRef.current) == null ? void 0 : _a3.querySelector("[data-slate-editor]");
7408
8820
  editable == null ? void 0 : editable.focus({ preventScroll: true });
7409
8821
  if (slateEditorRef.current && !slateEditorRef.current.selection) {
7410
8822
  safeSelectEnd(slateEditorRef.current);
@@ -7427,9 +8839,9 @@ var PureRichText = react_exports.forwardRef((props, ref) => {
7427
8839
  (0, react_exports.useEffect)(() => {
7428
8840
  if (!isEditMode) return void 0;
7429
8841
  const guard = (e) => {
7430
- var _a2;
8842
+ var _a3;
7431
8843
  const target = e.target;
7432
- if (!((_a2 = containerRef.current) == null ? void 0 : _a2.contains(target))) return;
8844
+ if (!((_a3 = containerRef.current) == null ? void 0 : _a3.contains(target))) return;
7433
8845
  const isVizSelected = containerRef.current.closest('[data-selected="true"]') != null;
7434
8846
  if (!isVizSelected) return;
7435
8847
  if (!isTextEditingRef.current) {
@@ -7446,28 +8858,74 @@ var PureRichText = react_exports.forwardRef((props, ref) => {
7446
8858
  document.addEventListener("mousedown", guard, true);
7447
8859
  return () => document.removeEventListener("mousedown", guard, true);
7448
8860
  }, [isEditMode]);
7449
- const handleContainerClick = (0, react_exports.useCallback)(
8861
+ const maybeActivateEditing = (0, react_exports.useCallback)(
7450
8862
  (e) => {
7451
- if (hasEventHandlers && !isEditMode) {
7452
- onRichtextClick(e);
7453
- }
7454
- if (isEditMode && !isTextEditing && containerRef.current) {
7455
- const isVizSelected = containerRef.current.closest('[data-selected="true"]') != null;
7456
- if (!isVizSelected) return;
7457
- registerActiveRichText(instanceId, null, slateEditorRef.current);
7458
- activateTextEditing();
8863
+ if (!containerRef.current) return;
8864
+ const down = containerMouseDownRef.current;
8865
+ containerMouseDownRef.current = null;
8866
+ if (down && (Math.abs(e.clientX - down.x) > CONTAINER_MOVE_THRESHOLD || Math.abs(e.clientY - down.y) > CONTAINER_MOVE_THRESHOLD)) {
7459
8867
  return;
7460
8868
  }
7461
- if (!isTextEditing || !containerRef.current || isMouseSelecting()) return;
8869
+ if (consumeSuppressNextEditClick()) return;
8870
+ if (isMouseSelecting()) return;
8871
+ const isVizSelected = containerRef.current.closest('[data-selected="true"]') != null;
8872
+ if (!isVizSelected) return;
8873
+ const wrapper = containerRef.current.querySelector("[data-richtext-editor-wrapper]");
8874
+ if (wrapper && !wrapper.contains(e.target)) return;
8875
+ registerActiveRichText(instanceId, null, slateEditorRef.current);
8876
+ activateTextEditing();
8877
+ },
8878
+ [activateTextEditing, instanceId]
8879
+ );
8880
+ const handleEditingOutsideClick = (0, react_exports.useCallback)(
8881
+ (e) => {
8882
+ var _a3;
8883
+ if (!containerRef.current) return;
7462
8884
  const editable = containerRef.current.querySelector("[data-slate-editor]");
7463
8885
  if (!editable || editable.contains(e.target)) return;
8886
+ const wrapper = containerRef.current.querySelector("[data-richtext-editor-wrapper]");
8887
+ if (wrapper && !wrapper.contains(e.target)) {
8888
+ const editorToDeselect = slateEditorRef.current;
8889
+ if (editorToDeselect) {
8890
+ try {
8891
+ slate_exports.Transforms.deselect(editorToDeselect);
8892
+ } catch (e2) {
8893
+ }
8894
+ }
8895
+ (_a3 = globalThis.getSelection()) == null ? void 0 : _a3.removeAllRanges();
8896
+ richTextState.deactivateTextEditing();
8897
+ editable.blur();
8898
+ focusSelectOutline(containerRef.current);
8899
+ return;
8900
+ }
7464
8901
  editable.focus({ preventScroll: true });
7465
8902
  const slateEditor = getActiveSlateEditor();
7466
8903
  if (slateEditor) {
7467
8904
  safeSelectEnd(slateEditor);
7468
8905
  }
7469
8906
  },
7470
- [hasEventHandlers, isEditMode, isTextEditing, onRichtextClick]
8907
+ [richTextState]
8908
+ );
8909
+ const handleContainerClick = (0, react_exports.useCallback)(
8910
+ (e) => {
8911
+ if (hasEventHandlers && !isEditMode) {
8912
+ onRichtextClick(e);
8913
+ }
8914
+ if (isEditMode && !isTextEditing && containerRef.current) {
8915
+ maybeActivateEditing(e);
8916
+ return;
8917
+ }
8918
+ if (!isTextEditing || !containerRef.current || isMouseSelecting()) return;
8919
+ handleEditingOutsideClick(e);
8920
+ },
8921
+ [
8922
+ hasEventHandlers,
8923
+ isEditMode,
8924
+ isTextEditing,
8925
+ onRichtextClick,
8926
+ maybeActivateEditing,
8927
+ handleEditingOutsideClick
8928
+ ]
7471
8929
  );
7472
8930
  return /* @__PURE__ */ react_exports.createElement(
7473
8931
  PureRichTextProvider,
@@ -7493,12 +8951,16 @@ var PureRichText = react_exports.forwardRef((props, ref) => {
7493
8951
  $borderRadius: borderRadius,
7494
8952
  $padding: paddingValues,
7495
8953
  $isTextEditing: isTextEditing,
8954
+ $isEditMode: isEditMode,
7496
8955
  $hasEventHandlers: hasEventHandlers && !isEditMode,
7497
8956
  "data-no-drag": isTextEditing ? "true" : void 0,
7498
8957
  "data-text-editor": isTextEditing ? "true" : void 0,
7499
8958
  "data-test": "purerichtext-container",
7500
- role: !isEditMode ? "region" : void 0,
7501
- "aria-label": !isEditMode ? slateToPlainText(initialValue) || "Empty rich text" : void 0,
8959
+ role: isEditMode ? void 0 : "region",
8960
+ "aria-label": isEditMode ? void 0 : slateToPlainText(initialValue) || "Empty rich text",
8961
+ onMouseDownCapture: (e) => {
8962
+ containerMouseDownRef.current = { x: e.clientX, y: e.clientY };
8963
+ },
7502
8964
  onClick: handleContainerClick
7503
8965
  },
7504
8966
  hasEventHandlers && !isEditMode && /* @__PURE__ */ react_exports.createElement(
@@ -7518,19 +8980,21 @@ var PureRichText = react_exports.forwardRef((props, ref) => {
7518
8980
  {
7519
8981
  $isEditMode: isEditMode,
7520
8982
  $isTextEditing: isTextEditing,
8983
+ $hasEventHandlers: hasEventHandlers,
7521
8984
  $lineHeight: currentLineHeight,
8985
+ $verticalAlign: currentVerticalAlign,
7522
8986
  "data-richtext-editor-wrapper": true,
7523
- onMouseDown: isTextEditing ? (e) => {
8987
+ onMouseDown: (e) => {
7524
8988
  if (e.target === e.currentTarget) {
7525
8989
  e.stopPropagation();
7526
8990
  }
7527
- } : void 0
8991
+ }
7528
8992
  },
7529
8993
  /* @__PURE__ */ react_exports.createElement(
7530
8994
  InnerEditor,
7531
8995
  {
7532
8996
  initialValue,
7533
- richTextContent,
8997
+ richTextContent: effectiveEditorSourceContent,
7534
8998
  isEditMode,
7535
8999
  isTextEditing,
7536
9000
  containerRef,
@@ -7538,6 +9002,7 @@ var PureRichText = react_exports.forwardRef((props, ref) => {
7538
9002
  onContentChange: handleContentChange,
7539
9003
  onFocusGained: handleFocusGained,
7540
9004
  onFocusLost: handleFocusLost,
9005
+ onCancelPendingChanges: cancelPendingChanges,
7541
9006
  richTextState,
7542
9007
  onEditorReady: (ed) => {
7543
9008
  slateEditorRef.current = ed;
@@ -7545,7 +9010,14 @@ var PureRichText = react_exports.forwardRef((props, ref) => {
7545
9010
  updateActiveStylesRef: updateActiveStylesFnRef,
7546
9011
  clearFakeHighlightRef,
7547
9012
  recentSavesRef,
7548
- onAnnouncement: handleAnnouncement
9013
+ forceNextSyncRef,
9014
+ transformTreeRef,
9015
+ syncInitialValueChanges: showResolvedTokens,
9016
+ autoResolveTokensRef,
9017
+ onPasteStart: beginPasteBurst,
9018
+ onAnnouncement: handleAnnouncement,
9019
+ nameToValue,
9020
+ onLinkOpen: handleLinkOpen
7549
9021
  }
7550
9022
  )
7551
9023
  ),
@@ -7610,11 +9082,11 @@ function buildDefaultTextStyles(pickedOptions, options) {
7610
9082
  if (pickedOptions.strikethrough) styles.strikethrough = true;
7611
9083
  return styles;
7612
9084
  }
7613
- function resolveFontSize(defaultTextStyles, pickedOptions) {
9085
+ function resolveFontSize2(defaultTextStyles, pickedOptions) {
7614
9086
  let fontSize = defaultTextStyles.fontSize || pickedOptions.fontSize;
7615
9087
  let customFontSize = defaultTextStyles.customFontSize || pickedOptions.customFontSize;
7616
9088
  if (typeof fontSize === "string" && fontSize.endsWith("px")) {
7617
- customFontSize = parseInt(fontSize, 10);
9089
+ customFontSize = Number.parseInt(fontSize, 10);
7618
9090
  fontSize = "custom";
7619
9091
  }
7620
9092
  return { fontSize, customFontSize };
@@ -7625,17 +9097,18 @@ var computeVizProps = ({
7625
9097
  onRichtextClick,
7626
9098
  onOptionsChange,
7627
9099
  richTextContent: richTextContentProp,
7628
- hasEventHandlers = false
9100
+ hasEventHandlers = false,
9101
+ richTextTokenMetadata
7629
9102
  }) => {
7630
- var _a, _b, _c, _d, _e, _f, _g, _h;
9103
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
7631
9104
  const pickedOptions = pickValidOptions(options);
7632
9105
  const border = buildBorderConfig(pickedOptions, options);
7633
9106
  const defaultTextStyles = buildDefaultTextStyles(pickedOptions, options);
7634
9107
  const fontColor = defaultTextStyles.color || pickedOptions.fontColor;
7635
9108
  const highlightColor = defaultTextStyles.highlightColor || defaultTextStyles.backgroundColor || pickedOptions.highlightColor;
7636
9109
  const fontFamily = defaultTextStyles.fontFamily || pickedOptions.fontFamily;
7637
- const { fontSize, customFontSize } = resolveFontSize(defaultTextStyles, pickedOptions);
7638
- const bold = (_b = (_a = defaultTextStyles.bold) != null ? _a : pickedOptions.bold) != null ? _b : false;
9110
+ const { fontSize, customFontSize } = resolveFontSize2(defaultTextStyles, pickedOptions);
9111
+ const bold = (_b = (_a2 = defaultTextStyles.bold) != null ? _a2 : pickedOptions.bold) != null ? _b : false;
7639
9112
  const italic = (_d = (_c = defaultTextStyles.italic) != null ? _c : pickedOptions.italic) != null ? _d : false;
7640
9113
  const underline = (_f = (_e = defaultTextStyles.underline) != null ? _e : pickedOptions.underline) != null ? _f : false;
7641
9114
  const strikethrough = (_h = (_g = defaultTextStyles.strikethrough) != null ? _g : pickedOptions.strikethrough) != null ? _h : false;
@@ -7659,7 +9132,9 @@ var computeVizProps = ({
7659
9132
  italic,
7660
9133
  underline,
7661
9134
  strikethrough,
7662
- hasEventHandlers
9135
+ hasEventHandlers,
9136
+ previewTokenValues: (_i = pickedOptions.previewTokenValues) != null ? _i : false,
9137
+ richTextTokenMetadata
7663
9138
  };
7664
9139
  };
7665
9140
  var RichText = withDashboardViz_default({
@@ -7668,6 +9143,7 @@ var RichText = withDashboardViz_default({
7668
9143
  vizConfig: config_default,
7669
9144
  disableEditModeCover: true
7670
9145
  });
9146
+ RichText.tokenMetadataProp = "richTextTokenMetadata";
7671
9147
  var { themes: themes2 } = config_default;
7672
9148
  var config2 = config_default;
7673
9149
  var RichText_default3 = RichText;