@djangocfg/ui-tools 2.1.418 → 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 (304) hide show
  1. package/dist/file-icon/index.cjs +3 -3
  2. package/dist/file-icon/index.cjs.map +1 -1
  3. package/dist/file-icon/index.mjs +3 -3
  4. package/dist/file-icon/index.mjs.map +1 -1
  5. package/package.json +93 -28
  6. package/src/common/FloatingToolbar/actions/CopyAction.tsx +31 -0
  7. package/src/{components → common}/FloatingToolbar/actions/DownloadAction.tsx +15 -10
  8. package/src/common/FloatingToolbar/actions/ExpandAction.tsx +33 -0
  9. package/src/common/FloatingToolbar/actions/FullscreenAction.tsx +38 -0
  10. package/src/{components → common}/FloatingToolbar/index.tsx +39 -0
  11. package/src/lib/http.ts +64 -0
  12. package/src/tools/chat/index.ts +1 -1
  13. package/src/tools/chat/launcher/ChatFAB.tsx +66 -74
  14. package/src/tools/chat/launcher/header/ChatHeaderActionButton.tsx +2 -3
  15. package/src/tools/chat/lazy.tsx +1 -1
  16. package/src/tools/chat/messages/MessageBubble.tsx +1 -1
  17. package/src/tools/chat/messages/blocks/builtin.tsx +1 -1
  18. package/src/tools/chat/messages/blocks/renderers/CodeBlock.tsx +2 -2
  19. package/src/tools/chat/messages/blocks/renderers/JsonBlock.tsx +12 -1
  20. package/src/tools/data/DataGrid/lazy.tsx +1 -1
  21. package/src/tools/data/DataTable/lazy.tsx +1 -1
  22. package/src/tools/data/JsonTree/JsonViewer.tsx +720 -0
  23. package/src/tools/data/JsonTree/README.md +126 -73
  24. package/src/tools/data/JsonTree/index.tsx +3 -95
  25. package/src/tools/data/JsonTree/lazy.tsx +10 -50
  26. package/src/tools/data/JsonTree/types.ts +82 -63
  27. package/src/tools/data/Kanban/lazy.tsx +1 -1
  28. package/src/tools/data/Listbox/lazy.tsx +1 -1
  29. package/src/tools/data/Masonry/lazy.tsx +1 -1
  30. package/src/tools/data/Timeline/lazy.tsx +1 -1
  31. package/src/tools/data/Tree/lazy.tsx +1 -1
  32. package/src/tools/dev/Map/lazy.tsx +1 -1
  33. package/src/tools/dev/Mermaid/Mermaid.client.tsx +2 -2
  34. package/src/tools/dev/Mermaid/lazy.tsx +1 -1
  35. package/src/tools/dev/api/ApiRefTable/ApiRefTable.tsx +65 -0
  36. package/src/tools/dev/api/ApiRefTable/README.md +31 -0
  37. package/src/tools/dev/api/ApiRefTable/components/Row.tsx +96 -0
  38. package/src/tools/dev/api/ApiRefTable/components/TypeDisplay.tsx +44 -0
  39. package/src/tools/dev/api/ApiRefTable/index.ts +6 -0
  40. package/src/tools/dev/api/ApiRefTable/lazy.tsx +21 -0
  41. package/src/tools/dev/api/ApiRefTable/types.ts +82 -0
  42. package/src/tools/dev/api/ApiRefTable/utils.ts +42 -0
  43. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/ApiIntroSection.tsx +1 -1
  44. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/CodeSamples/index.tsx +1 -1
  45. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Header/index.tsx +1 -1
  46. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Responses/ResponseBody.tsx +7 -21
  47. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/RequestPanel.tsx +1 -1
  48. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/PrettyView.tsx +13 -19
  49. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/types.ts +1 -1
  50. package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/lazy.tsx +1 -1
  51. package/src/tools/dev/api/RequestViewer/README.md +33 -0
  52. package/src/tools/dev/api/RequestViewer/RequestViewer.tsx +121 -0
  53. package/src/tools/dev/api/RequestViewer/components/BodyTab.tsx +44 -0
  54. package/src/tools/dev/api/RequestViewer/components/EmptyState.tsx +13 -0
  55. package/src/tools/dev/api/RequestViewer/components/HeadersTab.tsx +78 -0
  56. package/src/tools/dev/api/RequestViewer/components/TimingTab.tsx +113 -0
  57. package/src/tools/dev/api/RequestViewer/components/utils.ts +31 -0
  58. package/src/tools/dev/api/RequestViewer/index.ts +16 -0
  59. package/src/tools/dev/api/RequestViewer/lazy.tsx +30 -0
  60. package/src/tools/dev/api/RequestViewer/types.ts +81 -0
  61. package/src/tools/dev/code/DiffViewer/DiffViewer.tsx +144 -0
  62. package/src/tools/dev/code/DiffViewer/README.md +33 -0
  63. package/src/tools/dev/code/DiffViewer/components/CopyButton.tsx +49 -0
  64. package/src/tools/dev/code/DiffViewer/components/DiffLineContent.tsx +48 -0
  65. package/src/tools/dev/code/DiffViewer/components/SplitView.tsx +220 -0
  66. package/src/tools/dev/code/DiffViewer/components/UnifiedView.tsx +154 -0
  67. package/src/tools/dev/code/DiffViewer/hooks/useDiff.ts +47 -0
  68. package/src/tools/dev/code/DiffViewer/hooks/useHighlighter.ts +54 -0
  69. package/src/tools/dev/code/DiffViewer/index.ts +22 -0
  70. package/src/tools/dev/code/DiffViewer/lazy.tsx +22 -0
  71. package/src/tools/dev/code/DiffViewer/types.ts +109 -0
  72. package/src/tools/dev/code/DiffViewer/utils/computeDiff.ts +159 -0
  73. package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/CollapseToggle.tsx +1 -1
  74. package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/MarkdownMessage.tsx +1 -1
  75. package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/components.tsx +2 -2
  76. package/src/tools/dev/{PrettyCode → code/PrettyCode}/PrettyCode.client.tsx +2 -2
  77. package/src/tools/dev/{PrettyCode → code/PrettyCode}/lazy.tsx +1 -1
  78. package/src/tools/dev/ops/EnvTable/EnvTable.tsx +228 -0
  79. package/src/tools/dev/ops/EnvTable/README.md +29 -0
  80. package/src/tools/dev/ops/EnvTable/hooks/useEnvMask.ts +121 -0
  81. package/src/tools/dev/ops/EnvTable/index.ts +12 -0
  82. package/src/tools/dev/ops/EnvTable/lazy.tsx +21 -0
  83. package/src/tools/dev/ops/EnvTable/types.ts +76 -0
  84. package/src/tools/dev/ops/LogViewer/LogViewer.tsx +194 -0
  85. package/src/tools/dev/ops/LogViewer/README.md +30 -0
  86. package/src/tools/dev/ops/LogViewer/components/LogRow.tsx +151 -0
  87. package/src/tools/dev/ops/LogViewer/components/Toolbar.tsx +199 -0
  88. package/src/tools/dev/ops/LogViewer/hooks/useAutoScroll.ts +68 -0
  89. package/src/tools/dev/ops/LogViewer/hooks/useLogFilter.ts +58 -0
  90. package/src/tools/dev/ops/LogViewer/index.ts +18 -0
  91. package/src/tools/dev/ops/LogViewer/lazy.tsx +25 -0
  92. package/src/tools/dev/ops/LogViewer/types.ts +142 -0
  93. package/src/tools/dev/ops/LogViewer/utils/ansi.ts +231 -0
  94. package/src/tools/forms/CodeEditor/hooks/useEditorTheme.ts +13 -73
  95. package/src/tools/forms/CodeEditor/lazy.tsx +1 -1
  96. package/src/tools/forms/FileUpload/lazy.tsx +1 -1
  97. package/src/tools/forms/JsonEditor/JsonEditor.tsx +115 -0
  98. package/src/tools/forms/JsonEditor/index.ts +1 -0
  99. package/src/tools/forms/JsonEditor/lazy.tsx +24 -0
  100. package/src/tools/forms/JsonForm/index.ts +1 -1
  101. package/src/tools/forms/JsonForm/lazy.tsx +1 -1
  102. package/src/tools/forms/MarkdownEditor/lazy.tsx +1 -1
  103. package/src/tools/forms/NotionEditor/README.md +237 -0
  104. package/src/tools/forms/NotionEditor/lazy.tsx +1 -1
  105. package/src/tools/index.ts +153 -13
  106. package/src/tools/input/Combobox/lazy.tsx +1 -1
  107. package/src/tools/input/CronScheduler/components/CronPreview.README.md +28 -0
  108. package/src/tools/input/CronScheduler/components/CronPreview.tsx +136 -0
  109. package/src/tools/input/CronScheduler/components/index.ts +3 -0
  110. package/src/tools/input/CronScheduler/index.tsx +5 -1
  111. package/src/tools/input/CronScheduler/lazy.tsx +5 -1
  112. package/src/tools/input/CronScheduler/utils/cron-next-runs.ts +122 -0
  113. package/src/tools/input/CronScheduler/utils/index.ts +1 -0
  114. package/src/tools/input/Scroller/lazy.tsx +1 -1
  115. package/src/tools/input/Sortable/lazy.tsx +1 -1
  116. package/src/tools/input/SpeechRecognition/lazy.tsx +1 -1
  117. package/src/tools/input/SpeechRecognition/widgets/VoiceComposerSlot.tsx +41 -36
  118. package/src/tools/media/ImageViewer/components/ImageToolbar.tsx +58 -47
  119. package/src/tools/media/ImageViewer/components/ImageViewer.tsx +27 -19
  120. package/src/tools/media/ImageViewer/lazy.tsx +1 -1
  121. package/src/tools/media/LottiePlayer/lazy.tsx +1 -1
  122. package/src/tools/media/VideoPlayer/VideoPlayer.tsx +28 -1
  123. package/src/tools/media/VideoPlayer/parts/fullscreen.tsx +21 -4
  124. package/src/tools/media/VideoPlayer/parts/pip.tsx +21 -4
  125. package/src/tools/media/VideoPlayer/parts/play-button.tsx +21 -4
  126. package/src/tools/media/VideoPlayer/parts/playback-rate.tsx +19 -3
  127. package/src/tools/media/VideoPlayer/parts/volume.tsx +237 -18
  128. package/src/tools/media/VideoPlayer/styles/video-player.css +87 -7
  129. package/src/tools/overlay/ResponsiveDialog/lazy.tsx +1 -1
  130. package/src/tools/overlay/ScrollSpy/lazy.tsx +1 -1
  131. package/src/tools/overlay/SelectionToolbar/lazy.tsx +1 -1
  132. package/src/tools/overlay/Tour/lazy.tsx +1 -1
  133. package/src/tools/visual/Marquee/lazy.tsx +1 -1
  134. package/src/tools/visual/QRCode/lazy.tsx +1 -1
  135. package/src/tools/visual/charts/ActivityGraph/ActivityGraph.tsx +195 -0
  136. package/src/tools/visual/charts/ActivityGraph/README.md +28 -0
  137. package/src/tools/visual/charts/ActivityGraph/index.ts +8 -0
  138. package/src/tools/visual/charts/ActivityGraph/lazy.tsx +21 -0
  139. package/src/tools/visual/charts/ActivityGraph/types.ts +59 -0
  140. package/src/tools/visual/charts/ActivityGraph/utils.ts +88 -0
  141. package/src/tools/visual/charts/CommitGraph/CommitGraph.tsx +80 -0
  142. package/src/tools/visual/charts/CommitGraph/README.md +28 -0
  143. package/src/tools/visual/charts/CommitGraph/components/CommitDetail.tsx +107 -0
  144. package/src/tools/visual/charts/CommitGraph/components/CommitRow.tsx +122 -0
  145. package/src/tools/visual/charts/CommitGraph/components/Rails.tsx +171 -0
  146. package/src/tools/visual/charts/CommitGraph/hooks/useGraphLayout.ts +169 -0
  147. package/src/tools/visual/charts/CommitGraph/hooks/useLaneColors.ts +45 -0
  148. package/src/tools/visual/charts/CommitGraph/index.ts +14 -0
  149. package/src/tools/visual/charts/CommitGraph/lazy.tsx +25 -0
  150. package/src/tools/visual/charts/CommitGraph/types.ts +85 -0
  151. package/src/tools/visual/charts/CommitGraph/utils.ts +53 -0
  152. package/src/tools/visual/{Gauge → charts/Gauge}/lazy.tsx +1 -1
  153. package/src/tools/visual/charts/Sparkline/README.md +29 -0
  154. package/src/tools/visual/charts/Sparkline/Sparkline.tsx +217 -0
  155. package/src/tools/visual/charts/Sparkline/index.ts +9 -0
  156. package/src/tools/visual/charts/Sparkline/lazy.tsx +26 -0
  157. package/src/tools/visual/charts/Sparkline/types.ts +58 -0
  158. package/src/tools/visual/design/ColorPalette/ColorPalette.tsx +129 -0
  159. package/src/tools/visual/design/ColorPalette/README.md +34 -0
  160. package/src/tools/visual/design/ColorPalette/components/Swatch.tsx +102 -0
  161. package/src/tools/visual/design/ColorPalette/hooks/useCopyToClipboard.ts +41 -0
  162. package/src/tools/visual/design/ColorPalette/index.ts +12 -0
  163. package/src/tools/visual/design/ColorPalette/lazy.tsx +21 -0
  164. package/src/tools/visual/design/ColorPalette/types.ts +63 -0
  165. package/src/tools/visual/design/ColorPalette/utils.ts +83 -0
  166. package/src/tools/visual/{ColorPicker → design/ColorPicker}/lazy.tsx +1 -1
  167. package/src/tools/visual/{FileIcon → design/FileIcon}/treeAdapter.tsx +1 -1
  168. package/src/tools/visual/{Fps → indicators/Fps}/lazy.tsx +1 -1
  169. package/src/tools/visual/{Rating → indicators/Rating}/lazy.tsx +1 -1
  170. package/src/tools/visual/indicators/StatusIndicator/README.md +28 -0
  171. package/src/tools/visual/indicators/StatusIndicator/StatusIndicator.tsx +83 -0
  172. package/src/tools/visual/indicators/StatusIndicator/index.ts +14 -0
  173. package/src/tools/visual/indicators/StatusIndicator/lazy.tsx +21 -0
  174. package/src/tools/visual/indicators/StatusIndicator/types.ts +133 -0
  175. package/src/components/FloatingToolbar/actions/CopyAction.tsx +0 -22
  176. package/src/components/FloatingToolbar/actions/ExpandAction.tsx +0 -25
  177. package/src/components/FloatingToolbar/actions/FullscreenAction.tsx +0 -30
  178. package/src/tools/data/JsonTree/components/JsonContent.tsx +0 -197
  179. package/src/tools/data/JsonTree/hooks/useJsonExpand.ts +0 -50
  180. /package/src/{components → common}/FloatingToolbar/FloatingToolbar.css +0 -0
  181. /package/src/{components → common}/FloatingToolbar/actions/index.ts +0 -0
  182. /package/src/{components → common}/FloatingToolbar/hooks/useElementCorner.ts +0 -0
  183. /package/src/{components → common}/FloatingToolbar/hooks/useScrollIsolation.ts +0 -0
  184. /package/src/{components → common}/index.ts +0 -0
  185. /package/src/{components → common}/lazy-wrapper.tsx +0 -0
  186. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/README.md +0 -0
  187. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/DocsView.tsx +0 -0
  188. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/CodeSamples/LanguageTabs.tsx +0 -0
  189. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/CodeSamples/useCodeSnippet.ts +0 -0
  190. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Header/MetaActions.tsx +0 -0
  191. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Header/MethodBadge.tsx +0 -0
  192. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Header/PathDisplay.tsx +0 -0
  193. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Parameters/ParamGroup.tsx +0 -0
  194. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Parameters/ParamRow.tsx +0 -0
  195. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Parameters/index.tsx +0 -0
  196. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/RequestBody/index.tsx +0 -0
  197. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Responses/ResponseRow.tsx +0 -0
  198. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Responses/StatusTag.tsx +0 -0
  199. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Responses/index.tsx +0 -0
  200. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/SchemaFields/FieldRow.tsx +0 -0
  201. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/SchemaFields/buildTree.ts +0 -0
  202. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/SchemaFields/index.tsx +0 -0
  203. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/SchemaFields/types.ts +0 -0
  204. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Section/SectionHeader.tsx +0 -0
  205. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Section/defaults.ts +0 -0
  206. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Section/index.tsx +0 -0
  207. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/context.tsx +0 -0
  208. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/hooks/useSectionHash.ts +0 -0
  209. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/index.tsx +0 -0
  210. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/store/index.ts +0 -0
  211. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/store/selectors.ts +0 -0
  212. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/types.ts +0 -0
  213. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/SchemaCopyMenu.tsx +0 -0
  214. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/BrandHeader.tsx +0 -0
  215. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/CategoryBlock.tsx +0 -0
  216. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/EndpointRow.tsx +0 -0
  217. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/SchemaSection.tsx +0 -0
  218. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/SearchInput.tsx +0 -0
  219. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/SidebarBody.tsx +0 -0
  220. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/Toolbar.tsx +0 -0
  221. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/buildVM.ts +0 -0
  222. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/index.tsx +0 -0
  223. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/types.ts +0 -0
  224. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/useDebouncedValue.ts +0 -0
  225. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/SlideInPlayground.tsx +0 -0
  226. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/TryItSheet.tsx +0 -0
  227. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/anchor.ts +0 -0
  228. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/grouping.ts +0 -0
  229. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/index.tsx +0 -0
  230. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/sidebarLabel.ts +0 -0
  231. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/index.ts +0 -0
  232. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/BodyFormEditor.tsx +0 -0
  233. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/EndpointDraftSync.tsx +0 -0
  234. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/EndpointResetButton.tsx +0 -0
  235. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/PreviewView.tsx +0 -0
  236. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/RawView.tsx +0 -0
  237. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/StatusBar.tsx +0 -0
  238. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/ViewTabs.tsx +0 -0
  239. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/detectContent.ts +0 -0
  240. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/index.tsx +0 -0
  241. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/useResponseView.ts +0 -0
  242. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/SendButton.tsx +0 -0
  243. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ui.tsx +0 -0
  244. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/constants.ts +0 -0
  245. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/context/PlaygroundContext.tsx +0 -0
  246. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/index.ts +0 -0
  247. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/useDocsUrlSync.ts +0 -0
  248. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/useEndpointDraft.ts +0 -0
  249. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/useMobile.ts +0 -0
  250. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/useOpenApiSchema.ts +0 -0
  251. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/index.tsx +0 -0
  252. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/types.ts +0 -0
  253. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/apiKeyManager.ts +0 -0
  254. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/codeSamples.ts +0 -0
  255. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/formatters.ts +0 -0
  256. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/index.ts +0 -0
  257. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/operationToHar.ts +0 -0
  258. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/sampler.ts +0 -0
  259. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/schemaExport.ts +0 -0
  260. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/scrollParent.ts +0 -0
  261. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/url.ts +0 -0
  262. /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/versionManager.ts +0 -0
  263. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/ActionRow.tsx +0 -0
  264. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/ChatMessageRow.tsx +0 -0
  265. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/CodeBlock.tsx +0 -0
  266. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/README.md +0 -0
  267. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/index.ts +0 -0
  268. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/linkRules.ts +0 -0
  269. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/plainText.ts +0 -0
  270. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/sanitize.ts +0 -0
  271. /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/types.ts +0 -0
  272. /package/src/tools/dev/{PrettyCode → code/PrettyCode}/README.md +0 -0
  273. /package/src/tools/dev/{PrettyCode → code/PrettyCode}/index.tsx +0 -0
  274. /package/src/tools/dev/{PrettyCode → code/PrettyCode}/registerPrismLanguages.ts +0 -0
  275. /package/src/tools/visual/{Gauge → charts/Gauge}/Gauge.tsx +0 -0
  276. /package/src/tools/visual/{Gauge → charts/Gauge}/index.ts +0 -0
  277. /package/src/tools/visual/{Gauge → charts/Gauge}/types.ts +0 -0
  278. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/ColorPicker.tsx +0 -0
  279. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/context/ColorPickerContext.tsx +0 -0
  280. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/context/ColorPickerStore.tsx +0 -0
  281. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/context/index.ts +0 -0
  282. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/index.ts +0 -0
  283. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/lib/color-utils.ts +0 -0
  284. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerAlphaSlider.tsx +0 -0
  285. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerArea.tsx +0 -0
  286. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerEyeDropper.tsx +0 -0
  287. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerFormatSelect.tsx +0 -0
  288. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerHueSlider.tsx +0 -0
  289. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerInput.tsx +0 -0
  290. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerSwatch.tsx +0 -0
  291. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/index.ts +0 -0
  292. /package/src/tools/visual/{ColorPicker → design/ColorPicker}/types.ts +0 -0
  293. /package/src/tools/visual/{FileIcon → design/FileIcon}/FileIcon.tsx +0 -0
  294. /package/src/tools/visual/{FileIcon → design/FileIcon}/get-file-icon.ts +0 -0
  295. /package/src/tools/visual/{FileIcon → design/FileIcon}/icons/icon-data.ts +0 -0
  296. /package/src/tools/visual/{FileIcon → design/FileIcon}/index.ts +0 -0
  297. /package/src/tools/visual/{FileIcon → design/FileIcon}/loader.ts +0 -0
  298. /package/src/tools/visual/{FileIcon → design/FileIcon}/specialFolders.ts +0 -0
  299. /package/src/tools/visual/{Fps → indicators/Fps}/Fps.tsx +0 -0
  300. /package/src/tools/visual/{Fps → indicators/Fps}/index.ts +0 -0
  301. /package/src/tools/visual/{Fps → indicators/Fps}/types.ts +0 -0
  302. /package/src/tools/visual/{Rating → indicators/Rating}/Rating.tsx +0 -0
  303. /package/src/tools/visual/{Rating → indicators/Rating}/index.ts +0 -0
  304. /package/src/tools/visual/{Rating → indicators/Rating}/types.ts +0 -0
@@ -2,12 +2,20 @@
2
2
 
3
3
  import { MediaPipButton } from 'media-chrome/react';
4
4
  import { cn } from '@djangocfg/ui-core/lib';
5
- import type { ComponentProps } from 'react';
5
+ import {
6
+ Tooltip,
7
+ TooltipContent,
8
+ TooltipTrigger,
9
+ } from '@djangocfg/ui-core/components';
10
+ import type { ComponentProps, ReactNode } from 'react';
6
11
 
7
- export type PipProps = ComponentProps<typeof MediaPipButton>;
12
+ export type PipProps = ComponentProps<typeof MediaPipButton> & {
13
+ /** Tooltip copy. Defaults to `"Picture in picture"`. Pass `false` to opt out. */
14
+ readonly label?: ReactNode | false;
15
+ };
8
16
 
9
- export function Pip({ className, ...props }: PipProps) {
10
- return (
17
+ export function Pip({ className, label, ...props }: PipProps) {
18
+ const button = (
11
19
  <MediaPipButton
12
20
  {...props}
13
21
  className={cn(
@@ -16,4 +24,13 @@ export function Pip({ className, ...props }: PipProps) {
16
24
  )}
17
25
  />
18
26
  );
27
+
28
+ if (label === false) return button;
29
+
30
+ return (
31
+ <Tooltip>
32
+ <TooltipTrigger asChild>{button}</TooltipTrigger>
33
+ <TooltipContent side="top">{label ?? 'Picture in picture'}</TooltipContent>
34
+ </Tooltip>
35
+ );
19
36
  }
@@ -2,12 +2,20 @@
2
2
 
3
3
  import { MediaPlayButton } from 'media-chrome/react';
4
4
  import { cn } from '@djangocfg/ui-core/lib';
5
- import type { ComponentProps } from 'react';
5
+ import {
6
+ Tooltip,
7
+ TooltipContent,
8
+ TooltipTrigger,
9
+ } from '@djangocfg/ui-core/components';
10
+ import type { ComponentProps, ReactNode } from 'react';
6
11
 
7
- export type PlayButtonProps = ComponentProps<typeof MediaPlayButton>;
12
+ export type PlayButtonProps = ComponentProps<typeof MediaPlayButton> & {
13
+ /** Tooltip copy. Defaults to `"Play / Pause"`. Pass `false` to opt out. */
14
+ readonly label?: ReactNode | false;
15
+ };
8
16
 
9
- export function PlayButton({ className, ...props }: PlayButtonProps) {
10
- return (
17
+ export function PlayButton({ className, label, ...props }: PlayButtonProps) {
18
+ const button = (
11
19
  <MediaPlayButton
12
20
  {...props}
13
21
  className={cn(
@@ -16,4 +24,13 @@ export function PlayButton({ className, ...props }: PlayButtonProps) {
16
24
  )}
17
25
  />
18
26
  );
27
+
28
+ if (label === false) return button;
29
+
30
+ return (
31
+ <Tooltip>
32
+ <TooltipTrigger asChild>{button}</TooltipTrigger>
33
+ <TooltipContent side="top">{label ?? 'Play / Pause'}</TooltipContent>
34
+ </Tooltip>
35
+ );
19
36
  }
@@ -2,7 +2,12 @@
2
2
 
3
3
  import { MediaPlaybackRateButton } from 'media-chrome/react';
4
4
  import { cn } from '@djangocfg/ui-core/lib';
5
- import type { ComponentProps } from 'react';
5
+ import {
6
+ Tooltip,
7
+ TooltipContent,
8
+ TooltipTrigger,
9
+ } from '@djangocfg/ui-core/components';
10
+ import type { ComponentProps, ReactNode } from 'react';
6
11
 
7
12
  export type PlaybackRateProps = Omit<
8
13
  ComponentProps<typeof MediaPlaybackRateButton>,
@@ -10,13 +15,15 @@ export type PlaybackRateProps = Omit<
10
15
  > & {
11
16
  /** Space-separated list, e.g. `'0.5 1 1.5 2'`, or an array of numbers. */
12
17
  readonly rates?: string | readonly number[];
18
+ /** Tooltip copy. Defaults to `"Playback speed"`. Pass `false` to opt out. */
19
+ readonly label?: ReactNode | false;
13
20
  };
14
21
 
15
22
  const DEFAULT_RATES: readonly number[] = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
16
23
 
17
- export function PlaybackRate({ className, rates, ...props }: PlaybackRateProps) {
24
+ export function PlaybackRate({ className, rates, label, ...props }: PlaybackRateProps) {
18
25
  const value = rates ?? DEFAULT_RATES;
19
- return (
26
+ const button = (
20
27
  <MediaPlaybackRateButton
21
28
  {...props}
22
29
  // media-chrome's setter accepts `string | ArrayLike<number>` — the
@@ -28,4 +35,13 @@ export function PlaybackRate({ className, rates, ...props }: PlaybackRateProps)
28
35
  )}
29
36
  />
30
37
  );
38
+
39
+ if (label === false) return button;
40
+
41
+ return (
42
+ <Tooltip>
43
+ <TooltipTrigger asChild>{button}</TooltipTrigger>
44
+ <TooltipContent side="top">{label ?? 'Playback speed'}</TooltipContent>
45
+ </Tooltip>
46
+ );
31
47
  }
@@ -1,32 +1,251 @@
1
1
  'use client';
2
2
 
3
- import { MediaMuteButton, MediaVolumeRange } from 'media-chrome/react';
3
+ import {
4
+ forwardRef,
5
+ useCallback,
6
+ useEffect,
7
+ useRef,
8
+ useState,
9
+ type ButtonHTMLAttributes,
10
+ type ReactNode,
11
+ } from 'react';
12
+ import { Volume2, VolumeX, Volume1 } from 'lucide-react';
4
13
  import { cn } from '@djangocfg/ui-core/lib';
5
- import type { ComponentProps } from 'react';
14
+ import {
15
+ Popover,
16
+ PopoverContent,
17
+ PopoverTrigger,
18
+ Slider,
19
+ Tooltip,
20
+ TooltipContent,
21
+ TooltipTrigger,
22
+ } from '@djangocfg/ui-core/components';
6
23
 
7
24
  export interface VolumeProps {
8
25
  readonly className?: string;
26
+ /**
27
+ * Reserved for backwards compatibility. The control is always a single
28
+ * icon button that opens a popover with a vertical slider on hover/focus,
29
+ * so this flag is now a no-op. Kept so existing consumers
30
+ * (`<Volume iconOnly />`) don't break.
31
+ */
9
32
  readonly iconOnly?: boolean;
10
- readonly muteProps?: ComponentProps<typeof MediaMuteButton>;
11
- readonly rangeProps?: ComponentProps<typeof MediaVolumeRange>;
33
+ /** Mute-button tooltip copy. Defaults to `"Volume"`. Pass `false` to opt out. */
34
+ readonly muteLabel?: ReactNode | false;
12
35
  }
13
36
 
14
- export function Volume({ className, iconOnly, muteProps, rangeProps }: VolumeProps) {
37
+ // Hide the popover slider on iOS Safari `video.volume` is read-only
38
+ // there (controlled by hardware buttons), so a JS slider does nothing.
39
+ // The trigger still toggles mute, which iOS *does* honour.
40
+ function isIosSafari(): boolean {
41
+ if (typeof navigator === 'undefined') return false;
42
+ const ua = navigator.userAgent;
43
+ const iOS =
44
+ /iPad|iPhone|iPod/.test(ua) ||
45
+ (navigator.platform === 'MacIntel' &&
46
+ (navigator as { maxTouchPoints?: number }).maxTouchPoints! > 1);
47
+ return iOS;
48
+ }
49
+
50
+ // media-chrome request event names. Dispatched on any descendant of
51
+ // `<media-controller>`; the controller catches them and updates its
52
+ // internal store, which then propagates state back via attributes.
53
+ const MEDIA_VOLUME_REQUEST = 'mediavolumerequest';
54
+ const MEDIA_MUTE_REQUEST = 'mediamuterequest';
55
+ const MEDIA_UNMUTE_REQUEST = 'mediaunmuterequest';
56
+
57
+ /**
58
+ * Click-style trigger that visually matches the rest of the VideoPlayer
59
+ * control bar. Mirrors `.video-player__control` styling from
60
+ * `styles/video-player.css` so it slots in next to `<MediaPlayButton>` &
61
+ * friends without standing out.
62
+ */
63
+ const TriggerButton = forwardRef<
64
+ HTMLButtonElement,
65
+ ButtonHTMLAttributes<HTMLButtonElement>
66
+ >(function TriggerButton({ className, children, ...rest }, ref) {
15
67
  return (
16
- <div className={cn('flex items-center', className)}>
17
- <MediaMuteButton
18
- {...muteProps}
19
- className={cn(
20
- 'media-control-square video-player__control h-8 w-8',
21
- muteProps?.className,
22
- )}
23
- />
24
- {!iconOnly && (
25
- <MediaVolumeRange
26
- {...rangeProps}
27
- className={cn('h-8 w-20', rangeProps?.className)}
28
- />
68
+ <button
69
+ ref={ref}
70
+ type="button"
71
+ className={cn(
72
+ 'video-player__control',
73
+ 'grid h-8 w-8 place-items-center rounded-md',
74
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60',
75
+ className,
29
76
  )}
77
+ {...rest}
78
+ >
79
+ {children}
80
+ </button>
81
+ );
82
+ });
83
+
84
+ /**
85
+ * VideoPlayer volume control.
86
+ *
87
+ * - **Click** the trigger → mute / unmute toggle (dispatches a
88
+ * `mediamuterequest` / `mediaunmuterequest` so media-chrome's store
89
+ * stays the single source of truth — no parallel state machine).
90
+ * - **Hover / keyboard focus** → opens a popover containing a vertical
91
+ * `<Slider>` (0..100). Drag = volume change via `mediavolumerequest`.
92
+ * - Icon reflects level (mute / low / high) and mirrors `media.muted`.
93
+ *
94
+ * State is read directly off the underlying `HTMLMediaElement` (located
95
+ * via the closest `<media-controller>`'s `.media` accessor); we never
96
+ * shadow media-chrome's store.
97
+ */
98
+ export function Volume({ className, muteLabel }: VolumeProps) {
99
+ const triggerRef = useRef<HTMLButtonElement | null>(null);
100
+ const [volume, setVolume] = useState(1);
101
+ const [muted, setMuted] = useState(false);
102
+ const [open, setOpen] = useState(false);
103
+ const [iosSafari] = useState(isIosSafari);
104
+
105
+ // Resolve & track the underlying HTMLMediaElement so we can read live
106
+ // volume / muted. media-chrome fires `mediaelementchange` on the
107
+ // controller whenever the slotted media element swaps (e.g. source
108
+ // change), so we re-bind listeners on each swap.
109
+ useEffect(() => {
110
+ const trigger = triggerRef.current;
111
+ if (!trigger) return;
112
+ const controller = trigger.closest('media-controller') as
113
+ | (HTMLElement & { media?: HTMLMediaElement | null })
114
+ | null;
115
+ if (!controller) return;
116
+
117
+ let media: HTMLMediaElement | null = controller.media ?? null;
118
+ const sync = () => {
119
+ if (!media) return;
120
+ setVolume(media.volume);
121
+ setMuted(media.muted);
122
+ };
123
+ const bind = (el: HTMLMediaElement | null) => {
124
+ if (!el) return;
125
+ el.addEventListener('volumechange', sync);
126
+ sync();
127
+ };
128
+ const unbind = (el: HTMLMediaElement | null) => {
129
+ if (!el) return;
130
+ el.removeEventListener('volumechange', sync);
131
+ };
132
+
133
+ bind(media);
134
+
135
+ const onMediaChange = (e: Event) => {
136
+ unbind(media);
137
+ const detail = (e as CustomEvent).detail as HTMLMediaElement | null;
138
+ media = detail ?? controller.media ?? null;
139
+ bind(media);
140
+ };
141
+ controller.addEventListener('mediaelementchange', onMediaChange);
142
+
143
+ return () => {
144
+ unbind(media);
145
+ controller.removeEventListener('mediaelementchange', onMediaChange);
146
+ };
147
+ }, []);
148
+
149
+ const dispatch = useCallback((name: string, detail?: number) => {
150
+ const trigger = triggerRef.current;
151
+ if (!trigger) return;
152
+ trigger.dispatchEvent(
153
+ new CustomEvent(name, { detail, bubbles: true, composed: true }),
154
+ );
155
+ }, []);
156
+
157
+ const toggleMute = useCallback(() => {
158
+ dispatch(muted ? MEDIA_UNMUTE_REQUEST : MEDIA_MUTE_REQUEST);
159
+ }, [dispatch, muted]);
160
+
161
+ const onSlider = useCallback(
162
+ (value: number) => {
163
+ dispatch(MEDIA_VOLUME_REQUEST, value);
164
+ // If the user nudges the slider above zero, treat that as an
165
+ // implicit unmute — matches what the native HTML5 volume slider does.
166
+ if (value > 0 && muted) dispatch(MEDIA_UNMUTE_REQUEST);
167
+ },
168
+ [dispatch, muted],
169
+ );
170
+
171
+ const effectiveVolume = muted ? 0 : volume;
172
+ const Icon =
173
+ muted || volume === 0 ? VolumeX : volume < 0.5 ? Volume1 : Volume2;
174
+
175
+ const trigger = (
176
+ <TriggerButton
177
+ ref={triggerRef}
178
+ aria-label={muted ? 'Unmute' : 'Mute'}
179
+ aria-pressed={muted}
180
+ onClick={toggleMute}
181
+ >
182
+ <Icon className="h-4 w-4" strokeWidth={1.75} />
183
+ </TriggerButton>
184
+ );
185
+
186
+ // On iOS Safari volume is hardware-only — skip the popover entirely
187
+ // and let the trigger work as a plain mute/unmute button.
188
+ if (iosSafari) {
189
+ if (muteLabel === false) return <div className={cn('flex', className)}>{trigger}</div>;
190
+ return (
191
+ <div className={cn('flex items-center', className)}>
192
+ <Tooltip>
193
+ <TooltipTrigger asChild>{trigger}</TooltipTrigger>
194
+ <TooltipContent side="top">{muteLabel ?? 'Mute / unmute'}</TooltipContent>
195
+ </Tooltip>
196
+ </div>
197
+ );
198
+ }
199
+
200
+ return (
201
+ <div
202
+ className={cn('flex items-center', className)}
203
+ // Hover-driven open: opening on pointerenter of the wrapper (not
204
+ // just the button) gives the user a forgiving hit-area when their
205
+ // cursor drifts between trigger and popover. The popover itself
206
+ // also catches pointerenter via Radix portal — so once it's open,
207
+ // moving into it keeps it open.
208
+ onPointerEnter={() => setOpen(true)}
209
+ onPointerLeave={() => setOpen(false)}
210
+ onFocus={() => setOpen(true)}
211
+ onBlur={(e) => {
212
+ // Don't close when focus moves between the trigger and the
213
+ // popover content (both live in this wrapper / its portal).
214
+ if (!e.currentTarget.contains(e.relatedTarget as Node | null)) {
215
+ setOpen(false);
216
+ }
217
+ }}
218
+ >
219
+ <Popover open={open} onOpenChange={setOpen}>
220
+ <PopoverTrigger asChild>{trigger}</PopoverTrigger>
221
+ <PopoverContent
222
+ side="top"
223
+ align="center"
224
+ sideOffset={8}
225
+ // Keep focus on the trigger so click-to-mute still works while
226
+ // the popover is visible; the slider remains keyboard-reachable
227
+ // via Tab once a user explicitly tabs into it.
228
+ onOpenAutoFocus={(e) => e.preventDefault()}
229
+ onCloseAutoFocus={(e) => e.preventDefault()}
230
+ onPointerEnter={() => setOpen(true)}
231
+ onPointerLeave={() => setOpen(false)}
232
+ className="flex w-12 flex-col items-center gap-2 p-3"
233
+ >
234
+ <span className="w-full text-center text-[10px] tabular-nums text-muted-foreground">
235
+ {Math.round(effectiveVolume * 100)}
236
+ </span>
237
+ <Slider
238
+ orientation="vertical"
239
+ min={0}
240
+ max={1}
241
+ step={0.01}
242
+ value={[effectiveVolume]}
243
+ onValueChange={([v]) => onSlider(v)}
244
+ aria-label="Volume"
245
+ className="h-24"
246
+ />
247
+ </PopoverContent>
248
+ </Popover>
30
249
  </div>
31
250
  );
32
251
  }
@@ -42,11 +42,6 @@ media-controller {
42
42
  --media-range-thumb-opacity: 0;
43
43
  --media-range-thumb-transition: opacity 0.15s ease;
44
44
 
45
- /* Tooltip */
46
- --media-tooltip-background: var(--popover);
47
- --media-tooltip-color: var(--popover-foreground);
48
- --media-tooltip-border-radius: 6px;
49
-
50
45
  /* Font */
51
46
  --media-font-family: inherit;
52
47
  --media-font-size: 12px;
@@ -87,6 +82,29 @@ media-control-bar {
87
82
  background: transparent;
88
83
  }
89
84
 
85
+ /*
86
+ * Suppress media-chrome's built-in tooltips. They are sticky elements
87
+ * slotted under each control button's shadow root (exposed via
88
+ * `part="tooltip"`) and paint a permanent "Play" / "Mute" / "Enter
89
+ * fullscreen" label below the bar. We wrap each control with our own
90
+ * Radix-backed <Tooltip> from @djangocfg/ui-core, which fires only on
91
+ * hover/focus and matches the rest of the platform. Reach into the
92
+ * shadow DOM via ::part(tooltip) — a global `media-tooltip` selector
93
+ * cannot pierce the boundary.
94
+ */
95
+ media-play-button::part(tooltip),
96
+ media-mute-button::part(tooltip),
97
+ media-fullscreen-button::part(tooltip),
98
+ media-pip-button::part(tooltip),
99
+ media-playback-rate-button::part(tooltip),
100
+ media-captions-button::part(tooltip),
101
+ media-airplay-button::part(tooltip),
102
+ media-cast-button::part(tooltip),
103
+ media-seek-forward-button::part(tooltip),
104
+ media-seek-backward-button::part(tooltip) {
105
+ display: none !important;
106
+ }
107
+
90
108
  /*
91
109
  * Auto-hide. media-chrome flags inactivity by setting `userinactive` on
92
110
  * the <media-controller>; it only does so while playback is running, and
@@ -120,17 +138,79 @@ media-time-range {
120
138
  --media-preview-background: var(--popover);
121
139
  --media-preview-border-radius: 6px;
122
140
  --media-text-color: var(--popover-foreground);
141
+
142
+ /* Kill media-chrome's default blue focus rectangle on the range track.
143
+ media-chrome paints a `box-shadow: inset 0 0 0 2px rgb(27 127 204 / .9)`
144
+ via `--media-focus-box-shadow` whenever the inner `<input type=range>`
145
+ matches `:focus-visible`, which wraps the entire seek-bar in a big
146
+ blue rectangle on click/Tab. We opt out of the track-wide ring and
147
+ surface focus on the thumb instead (see :focus-visible below). */
148
+ --media-focus-box-shadow: none;
123
149
  }
124
150
 
125
- /* Reveal the accent thumb only while hovering / scrubbing the rail. */
126
- media-time-range:hover {
151
+ /* Reveal the accent thumb only while hovering / scrubbing the rail, OR
152
+ when the rail is keyboard-focused so a11y keyboard users still see
153
+ where focus lives. */
154
+ media-time-range:hover,
155
+ media-time-range:focus-within {
127
156
  --media-range-thumb-opacity: 1;
128
157
  }
129
158
 
159
+ /* Keyboard focus indicator: a ring around the thumb (not the track).
160
+ Uses the platform `--ring` semantic token so it matches every other
161
+ focusable surface. */
162
+ media-time-range:focus-within {
163
+ --media-range-thumb-box-shadow: 0 0 0 2px var(--ring);
164
+ }
165
+
130
166
  media-time-range::part(preview-box) {
131
167
  display: none;
132
168
  }
133
169
 
170
+ /*
171
+ * YouTube iframe bleed-through suppression.
172
+ *
173
+ * YouTube's IFrame embed ToS requires showing some chrome that cannot be
174
+ * hidden via player params: the title bar at the top, the large pause
175
+ * button on the pause screen, and the bottom branding/share tray on
176
+ * hover/pause. We can't remove them, but we CAN make them non-interactive
177
+ * — so the user never triggers YouTube's hover-state, never gets a
178
+ * "More videos" overlay, and clicks never reach the YT iframe.
179
+ *
180
+ * The <youtube-video> custom element renders an inner <iframe>; disable
181
+ * pointer events on it (and on the wrapper itself, just in case the
182
+ * element later swaps layout). The companion `.vp-yt-click-shield` div
183
+ * inside <media-controller> absorbs clicks and converts them into
184
+ * media-chrome play/pause requests — so click-to-toggle still works.
185
+ *
186
+ * Our control bar lives above the shield and re-enables pointer events
187
+ * for the slot, so the controls stay clickable.
188
+ */
189
+ youtube-video,
190
+ youtube-video iframe {
191
+ pointer-events: none;
192
+ }
193
+
194
+ .vp-yt-click-shield {
195
+ position: absolute;
196
+ inset: 0;
197
+ cursor: pointer;
198
+ background: transparent;
199
+ pointer-events: auto;
200
+ /* Sit above the iframe but below the slotted control bar. */
201
+ z-index: 1;
202
+ }
203
+
204
+ /* media-chrome slots its control surfaces directly under
205
+ <media-controller>; raise them above the click-shield and restore
206
+ pointer events so buttons remain interactive. */
207
+ media-controller > media-control-bar,
208
+ media-controller > [slot='centered-chrome'],
209
+ media-controller > [slot='top-chrome'] {
210
+ z-index: 2;
211
+ pointer-events: auto;
212
+ }
213
+
134
214
  media-time-range::part(current-box) {
135
215
  padding: 2px 6px;
136
216
  border-radius: 6px;
@@ -10,7 +10,7 @@
10
10
  * import { LazyResponsiveDialog, LazyResponsiveDialogContent } from '@djangocfg/ui-tools/responsive-dialog';
11
11
  */
12
12
 
13
- import { createLazyComponent, LoadingFallback } from '../../../components/lazy-wrapper';
13
+ import { createLazyComponent, LoadingFallback } from '../../../common/lazy-wrapper';
14
14
  import type {
15
15
  ResponsiveDialogProps,
16
16
  ResponsiveDialogContentProps,
@@ -4,7 +4,7 @@
4
4
  * Lazy-loaded ScrollSpy Component
5
5
  */
6
6
 
7
- import { createLazyComponent, LoadingFallback } from '../../../components/lazy-wrapper';
7
+ import { createLazyComponent, LoadingFallback } from '../../../common/lazy-wrapper';
8
8
  import type {
9
9
  ScrollSpyProps,
10
10
  ScrollSpyNavProps,
@@ -4,7 +4,7 @@
4
4
  * Lazy-loaded SelectionToolbar Component
5
5
  */
6
6
 
7
- import { createLazyComponent, LoadingFallback } from '../../../components/lazy-wrapper';
7
+ import { createLazyComponent, LoadingFallback } from '../../../common/lazy-wrapper';
8
8
  import type {
9
9
  SelectionToolbarProps,
10
10
  SelectionToolbarContentProps,
@@ -4,7 +4,7 @@
4
4
  * Lazy-loaded Tour Component
5
5
  */
6
6
 
7
- import { createLazyComponent, LoadingFallback } from '../../../components/lazy-wrapper';
7
+ import { createLazyComponent, LoadingFallback } from '../../../common/lazy-wrapper';
8
8
  import type {
9
9
  TourProps,
10
10
  TourPopoverProps,
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { createLazyComponent } from '../../../components/lazy-wrapper';
3
+ import { createLazyComponent } from '../../../common/lazy-wrapper';
4
4
  import type { MarqueeProps } from './types';
5
5
 
6
6
  export const LazyMarquee = createLazyComponent<MarqueeProps>(
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { createLazyComponent } from '../../../components/lazy-wrapper';
3
+ import { createLazyComponent } from '../../../common/lazy-wrapper';
4
4
  import type { QRCodeProps } from './types';
5
5
 
6
6
  export const LazyQRCode = createLazyComponent<QRCodeProps>(