@djangocfg/ui-tools 2.1.417 → 2.1.419

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 (335) hide show
  1. package/dist/audio-player/index.cjs +1 -2
  2. package/dist/audio-player/index.cjs.map +1 -1
  3. package/dist/audio-player/index.d.cts +3 -11
  4. package/dist/audio-player/index.d.ts +3 -11
  5. package/dist/audio-player/index.mjs +1 -2
  6. package/dist/audio-player/index.mjs.map +1 -1
  7. package/dist/file-icon/index.cjs +3 -3
  8. package/dist/file-icon/index.cjs.map +1 -1
  9. package/dist/file-icon/index.mjs +3 -3
  10. package/dist/file-icon/index.mjs.map +1 -1
  11. package/dist/tree/index.cjs +0 -3
  12. package/dist/tree/index.cjs.map +1 -1
  13. package/dist/tree/index.mjs +0 -3
  14. package/dist/tree/index.mjs.map +1 -1
  15. package/package.json +117 -36
  16. package/src/common/FloatingToolbar/actions/CopyAction.tsx +31 -0
  17. package/src/{components → common}/FloatingToolbar/actions/DownloadAction.tsx +15 -10
  18. package/src/common/FloatingToolbar/actions/ExpandAction.tsx +33 -0
  19. package/src/common/FloatingToolbar/actions/FullscreenAction.tsx +38 -0
  20. package/src/{components → common}/FloatingToolbar/index.tsx +39 -0
  21. package/src/lib/http.ts +64 -0
  22. package/src/tools/chat/index.ts +1 -1
  23. package/src/tools/chat/launcher/ChatFAB.tsx +66 -74
  24. package/src/tools/chat/launcher/header/ChatHeaderActionButton.tsx +2 -3
  25. package/src/tools/chat/lazy.tsx +1 -1
  26. package/src/tools/chat/messages/MessageBubble.tsx +1 -1
  27. package/src/tools/chat/messages/blocks/builtin.tsx +1 -1
  28. package/src/tools/chat/messages/blocks/renderers/CodeBlock.tsx +2 -2
  29. package/src/tools/chat/messages/blocks/renderers/JsonBlock.tsx +12 -1
  30. package/src/tools/data/DataGrid/lazy.tsx +1 -1
  31. package/src/tools/data/DataTable/lazy.tsx +1 -1
  32. package/src/tools/data/JsonTree/JsonViewer.tsx +720 -0
  33. package/src/tools/data/JsonTree/README.md +126 -73
  34. package/src/tools/data/JsonTree/index.tsx +3 -95
  35. package/src/tools/data/JsonTree/lazy.tsx +10 -50
  36. package/src/tools/data/JsonTree/types.ts +82 -63
  37. package/src/tools/data/Kanban/lazy.tsx +1 -1
  38. package/src/tools/data/Listbox/lazy.tsx +1 -1
  39. package/src/tools/data/Masonry/lazy.tsx +1 -1
  40. package/src/tools/data/Timeline/lazy.tsx +1 -1
  41. package/src/tools/data/Tree/components/TreeRow.tsx +0 -11
  42. package/src/tools/data/Tree/lazy.tsx +1 -1
  43. package/src/tools/dev/Map/lazy.tsx +1 -1
  44. package/src/tools/dev/Mermaid/Mermaid.client.tsx +2 -2
  45. package/src/tools/dev/Mermaid/lazy.tsx +1 -1
  46. package/src/tools/dev/api/ApiRefTable/ApiRefTable.tsx +65 -0
  47. package/src/tools/dev/api/ApiRefTable/README.md +31 -0
  48. package/src/tools/dev/api/ApiRefTable/components/Row.tsx +96 -0
  49. package/src/tools/dev/api/ApiRefTable/components/TypeDisplay.tsx +44 -0
  50. package/src/tools/dev/api/ApiRefTable/index.ts +6 -0
  51. package/src/tools/dev/api/ApiRefTable/lazy.tsx +21 -0
  52. package/src/tools/dev/api/ApiRefTable/types.ts +82 -0
  53. package/src/tools/dev/api/ApiRefTable/utils.ts +42 -0
  54. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/ApiIntroSection.tsx +1 -1
  55. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/CodeSamples/index.tsx +1 -1
  56. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Header/index.tsx +1 -1
  57. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Responses/ResponseBody.tsx +7 -21
  58. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/RequestPanel.tsx +1 -1
  59. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/PrettyView.tsx +13 -19
  60. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/types.ts +1 -1
  61. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/lazy.tsx +1 -1
  62. package/src/tools/dev/api/RequestViewer/README.md +33 -0
  63. package/src/tools/dev/api/RequestViewer/RequestViewer.tsx +121 -0
  64. package/src/tools/dev/api/RequestViewer/components/BodyTab.tsx +44 -0
  65. package/src/tools/dev/api/RequestViewer/components/EmptyState.tsx +13 -0
  66. package/src/tools/dev/api/RequestViewer/components/HeadersTab.tsx +78 -0
  67. package/src/tools/dev/api/RequestViewer/components/TimingTab.tsx +113 -0
  68. package/src/tools/dev/api/RequestViewer/components/utils.ts +31 -0
  69. package/src/tools/dev/api/RequestViewer/index.ts +16 -0
  70. package/src/tools/dev/api/RequestViewer/lazy.tsx +30 -0
  71. package/src/tools/dev/api/RequestViewer/types.ts +81 -0
  72. package/src/tools/dev/code/DiffViewer/DiffViewer.tsx +144 -0
  73. package/src/tools/dev/code/DiffViewer/README.md +33 -0
  74. package/src/tools/dev/code/DiffViewer/components/CopyButton.tsx +49 -0
  75. package/src/tools/dev/code/DiffViewer/components/DiffLineContent.tsx +48 -0
  76. package/src/tools/dev/code/DiffViewer/components/SplitView.tsx +220 -0
  77. package/src/tools/dev/code/DiffViewer/components/UnifiedView.tsx +154 -0
  78. package/src/tools/dev/code/DiffViewer/hooks/useDiff.ts +47 -0
  79. package/src/tools/dev/code/DiffViewer/hooks/useHighlighter.ts +54 -0
  80. package/src/tools/dev/code/DiffViewer/index.ts +22 -0
  81. package/src/tools/dev/code/DiffViewer/lazy.tsx +22 -0
  82. package/src/tools/dev/code/DiffViewer/types.ts +109 -0
  83. package/src/tools/dev/code/DiffViewer/utils/computeDiff.ts +159 -0
  84. package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/CollapseToggle.tsx +1 -1
  85. package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/MarkdownMessage.tsx +1 -1
  86. package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/components.tsx +2 -2
  87. package/src/tools/dev/{PrettyCode → code/PrettyCode}/PrettyCode.client.tsx +2 -2
  88. package/src/tools/dev/{PrettyCode → code/PrettyCode}/lazy.tsx +1 -1
  89. package/src/tools/dev/ops/EnvTable/EnvTable.tsx +228 -0
  90. package/src/tools/dev/ops/EnvTable/README.md +29 -0
  91. package/src/tools/dev/ops/EnvTable/hooks/useEnvMask.ts +121 -0
  92. package/src/tools/dev/ops/EnvTable/index.ts +12 -0
  93. package/src/tools/dev/ops/EnvTable/lazy.tsx +21 -0
  94. package/src/tools/dev/ops/EnvTable/types.ts +76 -0
  95. package/src/tools/dev/ops/LogViewer/LogViewer.tsx +194 -0
  96. package/src/tools/dev/ops/LogViewer/README.md +30 -0
  97. package/src/tools/dev/ops/LogViewer/components/LogRow.tsx +151 -0
  98. package/src/tools/dev/ops/LogViewer/components/Toolbar.tsx +199 -0
  99. package/src/tools/dev/ops/LogViewer/hooks/useAutoScroll.ts +68 -0
  100. package/src/tools/dev/ops/LogViewer/hooks/useLogFilter.ts +58 -0
  101. package/src/tools/dev/ops/LogViewer/index.ts +18 -0
  102. package/src/tools/dev/ops/LogViewer/lazy.tsx +25 -0
  103. package/src/tools/dev/ops/LogViewer/types.ts +142 -0
  104. package/src/tools/dev/ops/LogViewer/utils/ansi.ts +231 -0
  105. package/src/tools/forms/CodeEditor/components/Editor.tsx +19 -0
  106. package/src/tools/forms/CodeEditor/hooks/useEditorTheme.ts +13 -73
  107. package/src/tools/forms/CodeEditor/lazy.tsx +1 -1
  108. package/src/tools/forms/CodeEditor/types/index.ts +7 -0
  109. package/src/tools/forms/FileUpload/lazy.tsx +1 -1
  110. package/src/tools/forms/JsonEditor/JsonEditor.tsx +115 -0
  111. package/src/tools/forms/JsonEditor/index.ts +1 -0
  112. package/src/tools/forms/JsonEditor/lazy.tsx +24 -0
  113. package/src/tools/forms/JsonForm/index.ts +1 -1
  114. package/src/tools/forms/JsonForm/lazy.tsx +1 -1
  115. package/src/tools/forms/MarkdownEditor/MarkdownEditor.tsx +40 -0
  116. package/src/tools/forms/MarkdownEditor/lazy.tsx +1 -1
  117. package/src/tools/forms/MarkdownEditor/styles.css +174 -21
  118. package/src/tools/forms/NotionEditor/CustomKeymap.ts +48 -0
  119. package/src/tools/forms/NotionEditor/LinkDialog.tsx +133 -0
  120. package/src/tools/forms/NotionEditor/NotionEditor.tsx +304 -0
  121. package/src/tools/forms/NotionEditor/README.md +237 -0
  122. package/src/tools/forms/NotionEditor/SlashExtension.ts +32 -0
  123. package/src/tools/forms/NotionEditor/SlashList.tsx +136 -0
  124. package/src/tools/forms/NotionEditor/TaskItemView.tsx +41 -0
  125. package/src/tools/forms/NotionEditor/createSlashSuggestion.ts +121 -0
  126. package/src/tools/forms/NotionEditor/extensions.ts +105 -0
  127. package/src/tools/forms/NotionEditor/index.ts +1 -0
  128. package/src/tools/forms/NotionEditor/lazy.tsx +44 -0
  129. package/src/tools/forms/NotionEditor/slashItems.ts +159 -0
  130. package/src/tools/forms/NotionEditor/styles.css +478 -0
  131. package/src/tools/forms/NotionEditor/types.ts +28 -0
  132. package/src/tools/index.ts +153 -13
  133. package/src/tools/input/Combobox/lazy.tsx +1 -1
  134. package/src/tools/input/CronScheduler/components/CronPreview.README.md +28 -0
  135. package/src/tools/input/CronScheduler/components/CronPreview.tsx +136 -0
  136. package/src/tools/input/CronScheduler/components/index.ts +3 -0
  137. package/src/tools/input/CronScheduler/index.tsx +5 -1
  138. package/src/tools/input/CronScheduler/lazy.tsx +5 -1
  139. package/src/tools/input/CronScheduler/utils/cron-next-runs.ts +122 -0
  140. package/src/tools/input/CronScheduler/utils/index.ts +1 -0
  141. package/src/tools/input/Scroller/lazy.tsx +1 -1
  142. package/src/tools/input/Sortable/lazy.tsx +1 -1
  143. package/src/tools/input/SpeechRecognition/lazy.tsx +1 -1
  144. package/src/tools/input/SpeechRecognition/widgets/VoiceComposerSlot.tsx +41 -36
  145. package/src/tools/media/AudioPlayer/PlayerShell.tsx +3 -11
  146. package/src/tools/media/AudioPlayer/types.ts +4 -11
  147. package/src/tools/media/ImageViewer/components/ImageToolbar.tsx +58 -47
  148. package/src/tools/media/ImageViewer/components/ImageViewer.tsx +35 -19
  149. package/src/tools/media/ImageViewer/lazy.tsx +1 -1
  150. package/src/tools/media/ImageViewer/types.ts +4 -0
  151. package/src/tools/media/LottiePlayer/lazy.tsx +1 -1
  152. package/src/tools/media/VideoPlayer/VideoPlayer.tsx +47 -1
  153. package/src/tools/media/VideoPlayer/parts/fullscreen.tsx +21 -4
  154. package/src/tools/media/VideoPlayer/parts/pip.tsx +21 -4
  155. package/src/tools/media/VideoPlayer/parts/play-button.tsx +21 -4
  156. package/src/tools/media/VideoPlayer/parts/playback-rate.tsx +19 -3
  157. package/src/tools/media/VideoPlayer/parts/volume.tsx +237 -18
  158. package/src/tools/media/VideoPlayer/styles/video-player.css +87 -7
  159. package/src/tools/media/VideoPlayer/types.ts +4 -0
  160. package/src/tools/overlay/ResponsiveDialog/lazy.tsx +1 -1
  161. package/src/tools/overlay/ScrollSpy/lazy.tsx +1 -1
  162. package/src/tools/overlay/SelectionToolbar/lazy.tsx +1 -1
  163. package/src/tools/overlay/Tour/lazy.tsx +1 -1
  164. package/src/tools/visual/Marquee/lazy.tsx +1 -1
  165. package/src/tools/visual/QRCode/lazy.tsx +1 -1
  166. package/src/tools/visual/charts/ActivityGraph/ActivityGraph.tsx +195 -0
  167. package/src/tools/visual/charts/ActivityGraph/README.md +28 -0
  168. package/src/tools/visual/charts/ActivityGraph/index.ts +8 -0
  169. package/src/tools/visual/charts/ActivityGraph/lazy.tsx +21 -0
  170. package/src/tools/visual/charts/ActivityGraph/types.ts +59 -0
  171. package/src/tools/visual/charts/ActivityGraph/utils.ts +88 -0
  172. package/src/tools/visual/charts/CommitGraph/CommitGraph.tsx +80 -0
  173. package/src/tools/visual/charts/CommitGraph/README.md +28 -0
  174. package/src/tools/visual/charts/CommitGraph/components/CommitDetail.tsx +107 -0
  175. package/src/tools/visual/charts/CommitGraph/components/CommitRow.tsx +122 -0
  176. package/src/tools/visual/charts/CommitGraph/components/Rails.tsx +171 -0
  177. package/src/tools/visual/charts/CommitGraph/hooks/useGraphLayout.ts +169 -0
  178. package/src/tools/visual/charts/CommitGraph/hooks/useLaneColors.ts +45 -0
  179. package/src/tools/visual/charts/CommitGraph/index.ts +14 -0
  180. package/src/tools/visual/charts/CommitGraph/lazy.tsx +25 -0
  181. package/src/tools/visual/charts/CommitGraph/types.ts +85 -0
  182. package/src/tools/visual/charts/CommitGraph/utils.ts +53 -0
  183. package/src/tools/visual/{Gauge → charts/Gauge}/lazy.tsx +1 -1
  184. package/src/tools/visual/charts/Sparkline/README.md +29 -0
  185. package/src/tools/visual/charts/Sparkline/Sparkline.tsx +217 -0
  186. package/src/tools/visual/charts/Sparkline/index.ts +9 -0
  187. package/src/tools/visual/charts/Sparkline/lazy.tsx +26 -0
  188. package/src/tools/visual/charts/Sparkline/types.ts +58 -0
  189. package/src/tools/visual/design/ColorPalette/ColorPalette.tsx +129 -0
  190. package/src/tools/visual/design/ColorPalette/README.md +34 -0
  191. package/src/tools/visual/design/ColorPalette/components/Swatch.tsx +102 -0
  192. package/src/tools/visual/design/ColorPalette/hooks/useCopyToClipboard.ts +41 -0
  193. package/src/tools/visual/design/ColorPalette/index.ts +12 -0
  194. package/src/tools/visual/design/ColorPalette/lazy.tsx +21 -0
  195. package/src/tools/visual/design/ColorPalette/types.ts +63 -0
  196. package/src/tools/visual/design/ColorPalette/utils.ts +83 -0
  197. package/src/tools/visual/{ColorPicker → design/ColorPicker}/lazy.tsx +1 -1
  198. package/src/tools/visual/{FileIcon → design/FileIcon}/treeAdapter.tsx +1 -1
  199. package/src/tools/visual/{Fps → indicators/Fps}/lazy.tsx +1 -1
  200. package/src/tools/visual/{Rating → indicators/Rating}/lazy.tsx +1 -1
  201. package/src/tools/visual/indicators/StatusIndicator/README.md +28 -0
  202. package/src/tools/visual/indicators/StatusIndicator/StatusIndicator.tsx +83 -0
  203. package/src/tools/visual/indicators/StatusIndicator/index.ts +14 -0
  204. package/src/tools/visual/indicators/StatusIndicator/lazy.tsx +21 -0
  205. package/src/tools/visual/indicators/StatusIndicator/types.ts +133 -0
  206. package/src/components/FloatingToolbar/actions/CopyAction.tsx +0 -22
  207. package/src/components/FloatingToolbar/actions/ExpandAction.tsx +0 -25
  208. package/src/components/FloatingToolbar/actions/FullscreenAction.tsx +0 -30
  209. package/src/tools/data/JsonTree/components/JsonContent.tsx +0 -197
  210. package/src/tools/data/JsonTree/hooks/useJsonExpand.ts +0 -50
  211. /package/src/{components → common}/FloatingToolbar/FloatingToolbar.css +0 -0
  212. /package/src/{components → common}/FloatingToolbar/actions/index.ts +0 -0
  213. /package/src/{components → common}/FloatingToolbar/hooks/useElementCorner.ts +0 -0
  214. /package/src/{components → common}/FloatingToolbar/hooks/useScrollIsolation.ts +0 -0
  215. /package/src/{components → common}/index.ts +0 -0
  216. /package/src/{components → common}/lazy-wrapper.tsx +0 -0
  217. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/README.md +0 -0
  218. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/DocsView.tsx +0 -0
  219. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/CodeSamples/LanguageTabs.tsx +0 -0
  220. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/CodeSamples/useCodeSnippet.ts +0 -0
  221. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Header/MetaActions.tsx +0 -0
  222. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Header/MethodBadge.tsx +0 -0
  223. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Header/PathDisplay.tsx +0 -0
  224. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Parameters/ParamGroup.tsx +0 -0
  225. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Parameters/ParamRow.tsx +0 -0
  226. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Parameters/index.tsx +0 -0
  227. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/RequestBody/index.tsx +0 -0
  228. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Responses/ResponseRow.tsx +0 -0
  229. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Responses/StatusTag.tsx +0 -0
  230. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Responses/index.tsx +0 -0
  231. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/SchemaFields/FieldRow.tsx +0 -0
  232. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/SchemaFields/buildTree.ts +0 -0
  233. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/SchemaFields/index.tsx +0 -0
  234. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/SchemaFields/types.ts +0 -0
  235. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Section/SectionHeader.tsx +0 -0
  236. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Section/defaults.ts +0 -0
  237. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Section/index.tsx +0 -0
  238. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/context.tsx +0 -0
  239. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/hooks/useSectionHash.ts +0 -0
  240. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/index.tsx +0 -0
  241. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/store/index.ts +0 -0
  242. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/store/selectors.ts +0 -0
  243. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/types.ts +0 -0
  244. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/SchemaCopyMenu.tsx +0 -0
  245. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/BrandHeader.tsx +0 -0
  246. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/CategoryBlock.tsx +0 -0
  247. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/EndpointRow.tsx +0 -0
  248. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/SchemaSection.tsx +0 -0
  249. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/SearchInput.tsx +0 -0
  250. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/SidebarBody.tsx +0 -0
  251. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/Toolbar.tsx +0 -0
  252. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/buildVM.ts +0 -0
  253. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/index.tsx +0 -0
  254. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/types.ts +0 -0
  255. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/useDebouncedValue.ts +0 -0
  256. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/SlideInPlayground.tsx +0 -0
  257. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/TryItSheet.tsx +0 -0
  258. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/anchor.ts +0 -0
  259. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/grouping.ts +0 -0
  260. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/index.tsx +0 -0
  261. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/sidebarLabel.ts +0 -0
  262. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/index.ts +0 -0
  263. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/BodyFormEditor.tsx +0 -0
  264. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/EndpointDraftSync.tsx +0 -0
  265. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/EndpointResetButton.tsx +0 -0
  266. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/PreviewView.tsx +0 -0
  267. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/RawView.tsx +0 -0
  268. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/StatusBar.tsx +0 -0
  269. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/ViewTabs.tsx +0 -0
  270. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/detectContent.ts +0 -0
  271. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/index.tsx +0 -0
  272. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/useResponseView.ts +0 -0
  273. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/SendButton.tsx +0 -0
  274. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ui.tsx +0 -0
  275. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/constants.ts +0 -0
  276. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/context/PlaygroundContext.tsx +0 -0
  277. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/index.ts +0 -0
  278. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/useDocsUrlSync.ts +0 -0
  279. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/useEndpointDraft.ts +0 -0
  280. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/useMobile.ts +0 -0
  281. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/useOpenApiSchema.ts +0 -0
  282. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/index.tsx +0 -0
  283. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/types.ts +0 -0
  284. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/apiKeyManager.ts +0 -0
  285. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/codeSamples.ts +0 -0
  286. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/formatters.ts +0 -0
  287. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/index.ts +0 -0
  288. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/operationToHar.ts +0 -0
  289. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/sampler.ts +0 -0
  290. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/schemaExport.ts +0 -0
  291. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/scrollParent.ts +0 -0
  292. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/url.ts +0 -0
  293. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/versionManager.ts +0 -0
  294. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/ActionRow.tsx +0 -0
  295. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/ChatMessageRow.tsx +0 -0
  296. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/CodeBlock.tsx +0 -0
  297. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/README.md +0 -0
  298. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/index.ts +0 -0
  299. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/linkRules.ts +0 -0
  300. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/plainText.ts +0 -0
  301. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/sanitize.ts +0 -0
  302. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/types.ts +0 -0
  303. /package/src/tools/dev/{PrettyCode → code/PrettyCode}/README.md +0 -0
  304. /package/src/tools/dev/{PrettyCode → code/PrettyCode}/index.tsx +0 -0
  305. /package/src/tools/dev/{PrettyCode → code/PrettyCode}/registerPrismLanguages.ts +0 -0
  306. /package/src/tools/visual/{Gauge → charts/Gauge}/Gauge.tsx +0 -0
  307. /package/src/tools/visual/{Gauge → charts/Gauge}/index.ts +0 -0
  308. /package/src/tools/visual/{Gauge → charts/Gauge}/types.ts +0 -0
  309. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/ColorPicker.tsx +0 -0
  310. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/context/ColorPickerContext.tsx +0 -0
  311. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/context/ColorPickerStore.tsx +0 -0
  312. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/context/index.ts +0 -0
  313. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/index.ts +0 -0
  314. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/lib/color-utils.ts +0 -0
  315. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerAlphaSlider.tsx +0 -0
  316. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerArea.tsx +0 -0
  317. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerEyeDropper.tsx +0 -0
  318. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerFormatSelect.tsx +0 -0
  319. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerHueSlider.tsx +0 -0
  320. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerInput.tsx +0 -0
  321. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerSwatch.tsx +0 -0
  322. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/index.ts +0 -0
  323. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/types.ts +0 -0
  324. /package/src/tools/visual/{FileIcon → design/FileIcon}/FileIcon.tsx +0 -0
  325. /package/src/tools/visual/{FileIcon → design/FileIcon}/get-file-icon.ts +0 -0
  326. /package/src/tools/visual/{FileIcon → design/FileIcon}/icons/icon-data.ts +0 -0
  327. /package/src/tools/visual/{FileIcon → design/FileIcon}/index.ts +0 -0
  328. /package/src/tools/visual/{FileIcon → design/FileIcon}/loader.ts +0 -0
  329. /package/src/tools/visual/{FileIcon → design/FileIcon}/specialFolders.ts +0 -0
  330. /package/src/tools/visual/{Fps → indicators/Fps}/Fps.tsx +0 -0
  331. /package/src/tools/visual/{Fps → indicators/Fps}/index.ts +0 -0
  332. /package/src/tools/visual/{Fps → indicators/Fps}/types.ts +0 -0
  333. /package/src/tools/visual/{Rating → indicators/Rating}/Rating.tsx +0 -0
  334. /package/src/tools/visual/{Rating → indicators/Rating}/index.ts +0 -0
  335. /package/src/tools/visual/{Rating → indicators/Rating}/types.ts +0 -0
@@ -2,49 +2,88 @@
2
2
  outline: none;
3
3
  }
4
4
 
5
- /* Inherit semantic foreground so the editor renders correctly in both
6
- light + dark themes (and under any active preset). Without this the
7
- browser falls back to UA black on a token-driven background. */
5
+ /* ─────────────────────────────────────────────────────────────────────
6
+ * Typography Notion-inspired: comfy line-height, generous heading
7
+ * scale, restrained spacing. Calibrated so the chat composer (compact,
8
+ * single-paragraph) and the document-preview editor (long-form, with
9
+ * many headings) both feel right without a variant prop.
10
+ *
11
+ * Inherit semantic foreground so the editor renders correctly in both
12
+ * light + dark themes (and under any active preset).
13
+ * ───────────────────────────────────────────────────────────────────── */
8
14
  .markdown-editor .tiptap,
9
15
  .markdown-editor .ProseMirror {
10
16
  color: var(--color-foreground, var(--foreground));
17
+ font-family:
18
+ -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto,
19
+ "Helvetica Neue", Arial, sans-serif;
20
+ font-size: 15px;
21
+ line-height: 1.6;
22
+ -webkit-font-smoothing: antialiased;
23
+ -moz-osx-font-smoothing: grayscale;
24
+ text-rendering: optimizeLegibility;
11
25
  }
12
26
 
13
27
  .markdown-editor .tiptap a,
14
28
  .markdown-editor .ProseMirror a {
15
29
  color: var(--color-primary, var(--primary));
16
30
  text-decoration: underline;
31
+ text-underline-offset: 2px;
32
+ text-decoration-thickness: 1px;
17
33
  }
18
34
 
35
+ .markdown-editor .tiptap a:hover,
36
+ .markdown-editor .ProseMirror a:hover {
37
+ text-decoration-thickness: 2px;
38
+ }
39
+
40
+ /* Headings — Notion scale. Top-padding > bottom so a heading sits
41
+ * visually grouped with the paragraph below it. */
19
42
  .markdown-editor .tiptap h1 {
20
- font-size: 1.5em;
43
+ font-size: 1.875em;
21
44
  font-weight: 700;
22
- margin: 0.5em 0 0.25em;
23
- line-height: 1.3;
45
+ line-height: 1.25;
46
+ margin: 1em 0 0.25em;
47
+ letter-spacing: -0.015em;
24
48
  }
25
49
 
26
50
  .markdown-editor .tiptap h2 {
27
- font-size: 1.25em;
51
+ font-size: 1.5em;
28
52
  font-weight: 600;
29
- margin: 0.5em 0 0.25em;
30
53
  line-height: 1.3;
54
+ margin: 0.9em 0 0.25em;
55
+ letter-spacing: -0.01em;
31
56
  }
32
57
 
33
58
  .markdown-editor .tiptap h3 {
59
+ font-size: 1.25em;
60
+ font-weight: 600;
61
+ line-height: 1.35;
62
+ margin: 0.8em 0 0.2em;
63
+ }
64
+
65
+ .markdown-editor .tiptap h4 {
34
66
  font-size: 1.1em;
35
67
  font-weight: 600;
36
- margin: 0.4em 0 0.2em;
37
- line-height: 1.3;
68
+ line-height: 1.4;
69
+ margin: 0.7em 0 0.2em;
70
+ }
71
+
72
+ /* First heading at the very top of the document has no leading air —
73
+ * Notion convention. */
74
+ .markdown-editor .tiptap > :is(h1, h2, h3, h4):first-child {
75
+ margin-top: 0;
38
76
  }
39
77
 
40
78
  .markdown-editor .tiptap p {
41
79
  margin: 0.25em 0;
42
80
  }
43
81
 
82
+ /* Lists — Notion uses tighter row spacing than browser default. */
44
83
  .markdown-editor .tiptap ul,
45
84
  .markdown-editor .tiptap ol {
46
85
  padding-left: 1.5em;
47
- margin: 0.25em 0;
86
+ margin: 0.35em 0;
48
87
  }
49
88
 
50
89
  .markdown-editor .tiptap ul {
@@ -56,29 +95,138 @@
56
95
  }
57
96
 
58
97
  .markdown-editor .tiptap li {
59
- margin: 0.1em 0;
98
+ margin: 0.15em 0;
99
+ }
100
+
101
+ .markdown-editor .tiptap li > p {
102
+ margin: 0;
103
+ }
104
+
105
+ /* Nested lists get a subtler marker. */
106
+ .markdown-editor .tiptap ul ul {
107
+ list-style: circle;
108
+ }
109
+ .markdown-editor .tiptap ul ul ul {
110
+ list-style: square;
111
+ }
112
+
113
+ /* Task list (GFM `- [ ] item`). StarterKit ships TaskList extension. */
114
+ .markdown-editor .tiptap ul[data-type="taskList"] {
115
+ list-style: none;
116
+ padding-left: 0.25em;
117
+ }
118
+
119
+ .markdown-editor .tiptap ul[data-type="taskList"] li {
120
+ display: flex;
121
+ align-items: flex-start;
122
+ gap: 0.5em;
123
+ }
124
+
125
+ .markdown-editor .tiptap ul[data-type="taskList"] li > label {
126
+ flex-shrink: 0;
127
+ margin-top: 0.3em;
128
+ user-select: none;
129
+ }
130
+
131
+ .markdown-editor .tiptap ul[data-type="taskList"] li > div {
132
+ flex: 1;
133
+ min-width: 0;
134
+ }
135
+
136
+ .markdown-editor .tiptap ul[data-type="taskList"] li[data-checked="true"] > div {
137
+ opacity: 0.55;
138
+ text-decoration: line-through;
60
139
  }
61
140
 
141
+ /* Blockquote — Notion uses a chunky left bar without italic. */
62
142
  .markdown-editor .tiptap blockquote {
63
143
  border-left: 3px solid var(--color-border, var(--border));
64
- padding-left: 1em;
65
- margin: 0.5em 0;
66
- opacity: 0.8;
144
+ padding: 0.2em 0 0.2em 1em;
145
+ margin: 0.6em 0;
146
+ color: color-mix(in oklab, var(--color-foreground, var(--foreground)) 80%, transparent);
147
+ }
148
+
149
+ .markdown-editor .tiptap blockquote > :first-child {
150
+ margin-top: 0;
151
+ }
152
+ .markdown-editor .tiptap blockquote > :last-child {
153
+ margin-bottom: 0;
67
154
  }
68
155
 
156
+ /* Divider — full-width thin rule with breathing room. */
69
157
  .markdown-editor .tiptap hr {
70
158
  border: none;
71
159
  border-top: 1px solid var(--color-border, var(--border));
72
- margin: 0.75em 0;
160
+ margin: 1.5em 0;
73
161
  }
74
162
 
163
+ /* Inline code — monospace pill, restrained tint. */
75
164
  .markdown-editor .tiptap code {
165
+ background: color-mix(in oklab, var(--color-muted, var(--muted)) 70%, transparent);
166
+ color: var(--color-foreground, var(--foreground));
167
+ padding: 0.15em 0.35em;
168
+ border-radius: 4px;
169
+ font-size: 0.875em;
170
+ font-family:
171
+ "SF Mono", ui-monospace, "JetBrains Mono", "Fira Code", Menlo, Consolas,
172
+ monospace;
173
+ border: 1px solid color-mix(in oklab, var(--color-border, var(--border)) 60%, transparent);
174
+ }
175
+
176
+ /* Code block — darker surface so it stands apart from inline code. */
177
+ .markdown-editor .tiptap pre {
76
178
  background: var(--color-muted, var(--muted));
77
- color: var(--color-muted-foreground, var(--muted-foreground));
78
- padding: 0.15em 0.3em;
79
- border-radius: 0.25em;
80
- font-size: 0.9em;
81
- font-family: monospace;
179
+ color: var(--color-foreground, var(--foreground));
180
+ padding: 0.9em 1em;
181
+ border-radius: 6px;
182
+ margin: 0.75em 0;
183
+ font-family:
184
+ "SF Mono", ui-monospace, "JetBrains Mono", "Fira Code", Menlo, Consolas,
185
+ monospace;
186
+ font-size: 0.875em;
187
+ line-height: 1.55;
188
+ overflow-x: auto;
189
+ border: 1px solid color-mix(in oklab, var(--color-border, var(--border)) 50%, transparent);
190
+ }
191
+
192
+ .markdown-editor .tiptap pre code {
193
+ background: transparent;
194
+ border: none;
195
+ padding: 0;
196
+ border-radius: 0;
197
+ font-size: inherit;
198
+ color: inherit;
199
+ }
200
+
201
+ /* Tables — borderless, subtle row separators (Notion-flavour). */
202
+ .markdown-editor .tiptap table {
203
+ border-collapse: collapse;
204
+ width: 100%;
205
+ margin: 0.75em 0;
206
+ font-size: 0.95em;
207
+ table-layout: fixed;
208
+ }
209
+
210
+ .markdown-editor .tiptap th,
211
+ .markdown-editor .tiptap td {
212
+ border: 1px solid var(--color-border, var(--border));
213
+ padding: 0.45em 0.75em;
214
+ vertical-align: top;
215
+ text-align: left;
216
+ min-width: 4ch;
217
+ }
218
+
219
+ .markdown-editor .tiptap th {
220
+ background: color-mix(in oklab, var(--color-muted, var(--muted)) 60%, transparent);
221
+ font-weight: 600;
222
+ }
223
+
224
+ /* Images — rounded, never overflow. */
225
+ .markdown-editor .tiptap img {
226
+ max-width: 100%;
227
+ height: auto;
228
+ border-radius: 6px;
229
+ margin: 0.5em 0;
82
230
  }
83
231
 
84
232
  .markdown-editor .tiptap strong {
@@ -93,6 +241,11 @@
93
241
  text-decoration: line-through;
94
242
  }
95
243
 
244
+ /* Selection highlight — semantic ring colour, not browser-blue. */
245
+ .markdown-editor .tiptap ::selection {
246
+ background: color-mix(in oklab, var(--color-primary, var(--primary)) 25%, transparent);
247
+ }
248
+
96
249
  .markdown-editor .tiptap p.is-editor-empty:first-child::before {
97
250
  content: attr(data-placeholder);
98
251
  float: left;
@@ -0,0 +1,48 @@
1
+ import { Extension } from '@tiptap/core';
2
+ import { TextSelection } from '@tiptap/pm/state';
3
+
4
+ /**
5
+ * Notion-style smart Cmd/Ctrl+A:
6
+ * 1st press → select the current text block
7
+ * 2nd press → select the whole document
8
+ *
9
+ * Default editor behaviour selects everything on first press, which is
10
+ * jarring in long documents where the user almost always wants "select
11
+ * paragraph" first. Ported from Novel (`extensions/custom-keymap.ts`).
12
+ */
13
+ export const CustomKeymap = Extension.create({
14
+ name: 'notion-custom-keymap',
15
+
16
+ addKeyboardShortcuts() {
17
+ return {
18
+ 'Mod-a': ({ editor }) => {
19
+ const { selection, doc } = editor.state;
20
+ const { $from, $to, from, to } = selection;
21
+
22
+ // Resolve the boundaries of the current text block. `start`/`end`
23
+ // on $from/$to give the inclusive content range of the parent
24
+ // textblock (a paragraph, heading, code block, list item body).
25
+ const blockStart = $from.start();
26
+ const blockEnd = $to.end();
27
+
28
+ const isWholeBlockSelected = from === blockStart && to === blockEnd;
29
+ // If the block is already fully selected → escalate to whole doc.
30
+ if (isWholeBlockSelected) {
31
+ editor
32
+ .chain()
33
+ .setTextSelection({ from: 0, to: doc.content.size })
34
+ .run();
35
+ return true;
36
+ }
37
+
38
+ editor
39
+ .chain()
40
+ .setTextSelection(
41
+ TextSelection.create(editor.state.doc, blockStart, blockEnd),
42
+ )
43
+ .run();
44
+ return true;
45
+ },
46
+ };
47
+ },
48
+ });
@@ -0,0 +1,133 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * Cmd/Ctrl+K link prompt. Modeless dialog with a single URL input and
5
+ * Save/Remove/Cancel actions. Mounted as a side-channel above the editor
6
+ * so it survives selection collapse — without this, focusing the input
7
+ * would unset the selection and TipTap couldn't apply the mark.
8
+ *
9
+ * We snapshot `from`/`to` of the selection on open and re-apply it
10
+ * before running the link command. ProseMirror tolerates this because
11
+ * the dialog is rendered in a portal (Radix's `DialogPortal`) and the
12
+ * editor's view does not lose its `state` — only its DOM focus.
13
+ */
14
+
15
+ import { useEffect, useRef, useState } from 'react';
16
+ import {
17
+ Button,
18
+ Dialog,
19
+ DialogContent,
20
+ DialogFooter,
21
+ DialogHeader,
22
+ DialogTitle,
23
+ Input,
24
+ } from '@djangocfg/ui-core';
25
+ import type { Editor } from '@tiptap/react';
26
+
27
+ /** Reject `javascript:`, `data:`, `vbscript:` schemes. Plain anchors,
28
+ * http(s), mailto, tel, and relative paths pass. Same allow-list TipTap
29
+ * uses internally when `validate` is omitted, made explicit here. */
30
+ function isSafeHref(value: string): boolean {
31
+ const trimmed = value.trim();
32
+ const colon = trimmed.indexOf(':');
33
+ if (colon === -1) return true; // relative or hash link
34
+ const scheme = trimmed.slice(0, colon).toLowerCase();
35
+ return ['http', 'https', 'mailto', 'tel', 'sms', 'ftp'].includes(scheme);
36
+ }
37
+
38
+ interface LinkDialogProps {
39
+ editor: Editor;
40
+ open: boolean;
41
+ onOpenChange: (open: boolean) => void;
42
+ }
43
+
44
+ export function LinkDialog({ editor, open, onOpenChange }: LinkDialogProps) {
45
+ const [href, setHref] = useState('');
46
+ const inputRef = useRef<HTMLInputElement | null>(null);
47
+ // Remember the selection range when the dialog opened — focusing the
48
+ // input collapses selection in the editor; we re-apply the snapshot
49
+ // before running the link command.
50
+ const rangeRef = useRef<{ from: number; to: number } | null>(null);
51
+
52
+ useEffect(() => {
53
+ if (!open) return;
54
+ const { from, to } = editor.state.selection;
55
+ rangeRef.current = { from, to };
56
+ const existing = editor.getAttributes('link').href as string | undefined;
57
+ setHref(existing ?? '');
58
+ // Focus is handled by Radix's `onOpenAutoFocus` below — that fires
59
+ // after the dialog DOM is in the document and avoids racing the
60
+ // built-in focus trap.
61
+ }, [open, editor]);
62
+
63
+ const applyLink = (value: string) => {
64
+ const range = rangeRef.current;
65
+ if (range) {
66
+ editor.chain().focus().setTextSelection(range).run();
67
+ }
68
+ const trimmed = value.trim();
69
+ if (!trimmed) {
70
+ editor.chain().focus().unsetLink().run();
71
+ } else if (isSafeHref(trimmed)) {
72
+ editor.chain().focus().extendMarkRange('link').setLink({ href: trimmed }).run();
73
+ }
74
+ onOpenChange(false);
75
+ };
76
+
77
+ const removeLink = () => {
78
+ const range = rangeRef.current;
79
+ if (range) {
80
+ editor.chain().focus().setTextSelection(range).run();
81
+ }
82
+ editor.chain().focus().unsetLink().run();
83
+ onOpenChange(false);
84
+ };
85
+
86
+ return (
87
+ <Dialog open={open} onOpenChange={onOpenChange}>
88
+ <DialogContent
89
+ className="sm:max-w-md"
90
+ // Override Radix's default auto-focus (first focusable). We want
91
+ // the URL input focused + selected — combining `preventDefault`
92
+ // here with a direct `focus()` call sequences cleanly with the
93
+ // dialog mount; the earlier queueMicrotask version raced Radix.
94
+ onOpenAutoFocus={(e) => {
95
+ e.preventDefault();
96
+ inputRef.current?.focus();
97
+ inputRef.current?.select();
98
+ }}
99
+ >
100
+ <DialogHeader>
101
+ <DialogTitle>Link</DialogTitle>
102
+ </DialogHeader>
103
+ <form
104
+ onSubmit={(e) => {
105
+ e.preventDefault();
106
+ applyLink(href);
107
+ }}
108
+ >
109
+ <Input
110
+ ref={inputRef}
111
+ type="url"
112
+ placeholder="https://example.com"
113
+ value={href}
114
+ onChange={(e) => setHref(e.target.value)}
115
+ autoComplete="off"
116
+ spellCheck={false}
117
+ />
118
+ <DialogFooter className="mt-4 gap-2 sm:gap-2">
119
+ {editor.isActive('link') ? (
120
+ <Button type="button" variant="outline" onClick={removeLink}>
121
+ Remove
122
+ </Button>
123
+ ) : null}
124
+ <Button type="button" variant="ghost" onClick={() => onOpenChange(false)}>
125
+ Cancel
126
+ </Button>
127
+ <Button type="submit">Save</Button>
128
+ </DialogFooter>
129
+ </form>
130
+ </DialogContent>
131
+ </Dialog>
132
+ );
133
+ }