@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
@@ -0,0 +1,169 @@
1
+ // Adapted from jalcoui (MIT) — github.com/jal-co/ui
2
+
3
+ 'use client';
4
+
5
+ import { useMemo } from 'react';
6
+ import type { Commit, Edge, GraphRow } from '../types';
7
+ import { pickLaneColor } from './useLaneColors';
8
+
9
+ /**
10
+ * Topological layout pass for the commit graph.
11
+ *
12
+ * Walks the commit list in order (newest first) and tracks active rails —
13
+ * each slot holds the hash of the parent the rail is "waiting for". The
14
+ * algorithm produces:
15
+ *
16
+ * - The rail a commit's dot occupies.
17
+ * - The rails state after the row (for the next iteration).
18
+ * - Edges to draw on this row (pass-throughs, merge curves, fork curves).
19
+ *
20
+ * Rail colors are looked up at layout time so the rendered SVG can use raw
21
+ * hex `stroke=` values — Canvas2D/SVG won't parse Tailwind classes.
22
+ */
23
+ function computeLayout(commits: Commit[], laneColors: string[]): GraphRow[] {
24
+ const rows: GraphRow[] = [];
25
+ const rails: (string | null)[] = [];
26
+ const color = (rail: number) => pickLaneColor(laneColors, rail);
27
+
28
+ for (const commit of commits) {
29
+ const hash = commit.hash;
30
+
31
+ // Find which rail this commit occupies (if any rail is waiting for it).
32
+ let commitRail = rails.indexOf(hash);
33
+
34
+ if (commitRail === -1) {
35
+ // New branch — find first empty slot or append.
36
+ const emptySlot = rails.indexOf(null);
37
+ if (emptySlot !== -1) {
38
+ commitRail = emptySlot;
39
+ rails[commitRail] = hash;
40
+ } else {
41
+ commitRail = rails.length;
42
+ rails.push(hash);
43
+ }
44
+ }
45
+
46
+ const commitColor = color(commitRail);
47
+ const edges: Edge[] = [];
48
+
49
+ // Pass-through rails (everything not on the commit rail).
50
+ for (let r = 0; r < rails.length; r++) {
51
+ if (r !== commitRail && rails[r] !== null) {
52
+ edges.push({ fromRail: r, toRail: r, color: color(r), type: 'straight' });
53
+ }
54
+ }
55
+
56
+ // Clear this rail — the commit has been rendered.
57
+ rails[commitRail] = null;
58
+
59
+ // First parent continues on the commit's rail unless already expected
60
+ // elsewhere (merge of two existing branches).
61
+ const parents = commit.parents;
62
+ if (parents.length >= 1) {
63
+ const firstParent = parents[0];
64
+ const existingRail = rails.indexOf(firstParent);
65
+ if (existingRail !== -1) {
66
+ edges.push({
67
+ fromRail: commitRail,
68
+ toRail: existingRail,
69
+ color: commitColor,
70
+ type: 'merge-in',
71
+ });
72
+ } else {
73
+ rails[commitRail] = firstParent;
74
+ edges.push({
75
+ fromRail: commitRail,
76
+ toRail: commitRail,
77
+ color: commitColor,
78
+ type: 'straight',
79
+ });
80
+ }
81
+ }
82
+
83
+ // Second+ parents (merge sources / forks).
84
+ for (let p = 1; p < parents.length; p++) {
85
+ const parentHash = parents[p];
86
+ const existingRail = rails.indexOf(parentHash);
87
+ if (existingRail !== -1) {
88
+ edges.push({
89
+ fromRail: existingRail,
90
+ toRail: commitRail,
91
+ color: color(existingRail),
92
+ type: 'merge-in',
93
+ });
94
+ } else {
95
+ const emptySlot = rails.indexOf(null);
96
+ const newRail = emptySlot !== -1 ? emptySlot : rails.length;
97
+ if (newRail >= rails.length) rails.push(null);
98
+ rails[newRail] = parentHash;
99
+ edges.push({
100
+ fromRail: commitRail,
101
+ toRail: newRail,
102
+ color: color(newRail),
103
+ type: 'fork-out',
104
+ });
105
+ }
106
+ }
107
+
108
+ // Trim trailing nulls so `maxRails` stays accurate.
109
+ while (rails.length > 0 && rails[rails.length - 1] === null) {
110
+ rails.pop();
111
+ }
112
+
113
+ rows.push({
114
+ commit,
115
+ rail: commitRail,
116
+ rails: [...rails],
117
+ edges,
118
+ });
119
+ }
120
+
121
+ return rows;
122
+ }
123
+
124
+ /**
125
+ * Auto-infer a linear topology when no commit declares parents — the
126
+ * jalcoui examples ship a flat list and rely on the component to chain
127
+ * them.
128
+ */
129
+ function ensureTopology(commits: Commit[]): Commit[] {
130
+ const hasTopology = commits.some((c) => c.parents && c.parents.length > 0);
131
+ if (hasTopology) return commits;
132
+ return commits.map((c, i) => ({
133
+ ...c,
134
+ parents: i < commits.length - 1 ? [commits[i + 1].hash] : [],
135
+ }));
136
+ }
137
+
138
+ export interface GraphLayout {
139
+ rows: GraphRow[];
140
+ maxRails: number;
141
+ }
142
+
143
+ /**
144
+ * React-friendly wrapper around {@link computeLayout}. Memoizes on
145
+ * `commits` + `laneColors` identity so theme switches re-color but do not
146
+ * reshuffle topology.
147
+ */
148
+ export function useGraphLayout(
149
+ commits: Commit[],
150
+ laneColors: string[],
151
+ ): GraphLayout {
152
+ return useMemo(() => {
153
+ const resolved = ensureTopology(commits);
154
+ if (resolved.length === 0) {
155
+ return { rows: [], maxRails: 0 };
156
+ }
157
+ const rows = computeLayout(resolved, laneColors);
158
+ const maxRails = Math.max(
159
+ ...rows.map((r) =>
160
+ Math.max(
161
+ r.rail + 1,
162
+ r.rails.length,
163
+ ...r.edges.map((e) => Math.max(e.fromRail, e.toRail) + 1),
164
+ ),
165
+ ),
166
+ );
167
+ return { rows, maxRails };
168
+ }, [commits, laneColors]);
169
+ }
@@ -0,0 +1,45 @@
1
+ // Adapted from jalcoui (MIT) — github.com/jal-co/ui
2
+
3
+ 'use client';
4
+
5
+ import { useMemo } from 'react';
6
+ import { useStylePresets } from '@djangocfg/ui-core/styles/palette';
7
+
8
+ /**
9
+ * Hook returning the categorical lane palette as an array of hex strings.
10
+ *
11
+ * jalcoui hard-codes 8 raw colors (`#3b82f6`, `#22c55e`, …) — that would
12
+ * break every non-default theme preset. We instead derive the palette from
13
+ * {@link useStylePresets}: 8 distinguishable categorical fills that already
14
+ * respect the active theme. Branches beyond index 7 cycle modulo the
15
+ * palette length.
16
+ *
17
+ * Order is chosen for maximum perceptual distance between adjacent rails:
18
+ * primary → success → warning → danger → info → chart3 → chart4 → chart5.
19
+ */
20
+ export function useLaneColors(): string[] {
21
+ const presets = useStylePresets();
22
+
23
+ return useMemo(
24
+ () => [
25
+ presets.primary.fill,
26
+ presets.success.fill,
27
+ presets.warning.fill,
28
+ presets.danger.fill,
29
+ presets.info.fill,
30
+ presets.chart3.fill,
31
+ presets.chart4.fill,
32
+ presets.chart5.fill,
33
+ ],
34
+ [presets],
35
+ );
36
+ }
37
+
38
+ /**
39
+ * Pick the color for a rail index, cycling when there are more rails than
40
+ * palette entries.
41
+ */
42
+ export function pickLaneColor(colors: string[], rail: number): string {
43
+ if (colors.length === 0) return '#000000';
44
+ return colors[((rail % colors.length) + colors.length) % colors.length];
45
+ }
@@ -0,0 +1,14 @@
1
+ // Adapted from jalcoui (MIT) — github.com/jal-co/ui
2
+
3
+ export { CommitGraph } from './CommitGraph';
4
+ export { useLaneColors, pickLaneColor } from './hooks/useLaneColors';
5
+ export { useGraphLayout } from './hooks/useGraphLayout';
6
+ export { ROW_HEIGHT } from './types';
7
+ export type {
8
+ Commit,
9
+ CommitAuthor,
10
+ CommitGraphProps,
11
+ Edge,
12
+ EdgeType,
13
+ GraphRow,
14
+ } from './types';
@@ -0,0 +1,25 @@
1
+ // Adapted from jalcoui (MIT) — github.com/jal-co/ui
2
+
3
+ 'use client';
4
+
5
+ import { createLazyComponent } from '../../../../common/lazy-wrapper';
6
+ import type { CommitGraphProps } from './types';
7
+
8
+ export const LazyCommitGraph = createLazyComponent<CommitGraphProps>(
9
+ () => import('./CommitGraph').then((mod) => ({ default: mod.CommitGraph })),
10
+ {
11
+ displayName: 'LazyCommitGraph',
12
+ fallback: (
13
+ <div
14
+ data-slot="commit-graph-skeleton"
15
+ className="h-40 w-full animate-pulse rounded-xl bg-muted"
16
+ />
17
+ ),
18
+ },
19
+ );
20
+
21
+ export type {
22
+ CommitGraphProps,
23
+ Commit,
24
+ CommitAuthor,
25
+ } from './types';
@@ -0,0 +1,85 @@
1
+ // Adapted from jalcoui (MIT) — github.com/jal-co/ui
2
+
3
+ import type * as React from 'react';
4
+
5
+ /**
6
+ * Author metadata rendered next to each commit row and inside the detail
7
+ * popover. Avatar URLs are optional — when omitted, the initials of
8
+ * {@link CommitAuthor.name} are shown instead.
9
+ */
10
+ export interface CommitAuthor {
11
+ name: string;
12
+ avatarUrl?: string;
13
+ }
14
+
15
+ /**
16
+ * Single commit node fed into {@link CommitGraph}. Commits must be passed in
17
+ * topological order (newest first). The `parents` array drives the rail
18
+ * topology — empty for root commits, one entry for normal commits, two or
19
+ * more for merges.
20
+ */
21
+ export interface Commit {
22
+ /** Commit hash (full or abbreviated). */
23
+ hash: string;
24
+ /** Commit message (first line). */
25
+ message: string;
26
+ /** Commit author. */
27
+ author: CommitAuthor;
28
+ /** ISO date string or Date object. */
29
+ date: string | Date;
30
+ /** Parent commit hashes. Empty for root commits. Two parents = merge commit. */
31
+ parents: string[];
32
+ /** Branch or ref labels (e.g. `"main"`, `"feat/auth"`). */
33
+ refs?: string[];
34
+ /** Tag label (e.g. `"v1.0.0"`). */
35
+ tag?: string;
36
+ }
37
+
38
+ /**
39
+ * Props for {@link CommitGraph}.
40
+ */
41
+ export interface CommitGraphProps
42
+ extends Omit<React.ComponentProps<'div'>, 'children'> {
43
+ /** Commits in topological order (newest first). */
44
+ commits: Commit[];
45
+ /** Number of hash characters to display. @default 7 */
46
+ truncateHash?: number;
47
+ /** Pixel width per rail column. @default 24 */
48
+ railWidth?: number;
49
+ }
50
+
51
+ /**
52
+ * Type of edge a rail segment renders inside a row. The layout pass tags
53
+ * every drawn segment with one of these — the SVG renderer only needs to
54
+ * pick the geometry per type.
55
+ */
56
+ export type EdgeType = 'straight' | 'merge-in' | 'fork-out';
57
+
58
+ /**
59
+ * A single edge inside a {@link GraphRow}. Indices refer to rail slots
60
+ * (left-to-right) and `color` is a hex string already resolved through the
61
+ * theme palette — never a raw scale.
62
+ */
63
+ export interface Edge {
64
+ fromRail: number;
65
+ toRail: number;
66
+ color: string;
67
+ type: EdgeType;
68
+ }
69
+
70
+ /**
71
+ * Output of {@link computeLayout}. One row per commit, with the rail
72
+ * topology snapshot needed to draw rails + edges.
73
+ */
74
+ export interface GraphRow {
75
+ commit: Commit;
76
+ /** Rail index this commit's dot occupies. */
77
+ rail: number;
78
+ /** Rails state after this row (`null` = empty slot). */
79
+ rails: (string | null)[];
80
+ /** Edges to draw between the previous row and this row. */
81
+ edges: Edge[];
82
+ }
83
+
84
+ /** Pixel height of a single commit row. */
85
+ export const ROW_HEIGHT = 40;
@@ -0,0 +1,53 @@
1
+ // Adapted from jalcoui (MIT) — github.com/jal-co/ui
2
+
3
+ /**
4
+ * Author initials fallback for the avatar slot. Returns up to 2 uppercase
5
+ * characters drawn from the first letter of each whitespace-separated word.
6
+ */
7
+ export function initials(name: string): string {
8
+ return name
9
+ .split(/\s+/)
10
+ .map((w) => w[0] ?? '')
11
+ .join('')
12
+ .toUpperCase()
13
+ .slice(0, 2);
14
+ }
15
+
16
+ /**
17
+ * Relative "x ago" formatter used on each commit row. Falls back to a
18
+ * locale-formatted date once the gap exceeds a week.
19
+ */
20
+ export function formatRelativeDate(date: string | Date): string {
21
+ const d = typeof date === 'string' ? new Date(date) : date;
22
+ const now = new Date();
23
+ const diffMs = now.getTime() - d.getTime();
24
+ const diffMins = Math.floor(diffMs / 60_000);
25
+ const diffHours = Math.floor(diffMs / 3_600_000);
26
+ const diffDays = Math.floor(diffMs / 86_400_000);
27
+
28
+ if (diffMins < 1) return 'just now';
29
+ if (diffMins < 60) return `${diffMins}m ago`;
30
+ if (diffHours < 24) return `${diffHours}h ago`;
31
+ if (diffDays < 7) return `${diffDays}d ago`;
32
+
33
+ return d.toLocaleDateString('en-US', {
34
+ month: 'short',
35
+ day: 'numeric',
36
+ year: d.getFullYear() !== now.getFullYear() ? 'numeric' : undefined,
37
+ });
38
+ }
39
+
40
+ /**
41
+ * Fully-qualified date shown inside the commit detail popover.
42
+ */
43
+ export function formatFullDate(date: string | Date): string {
44
+ const d = typeof date === 'string' ? new Date(date) : date;
45
+ return d.toLocaleDateString('en-US', {
46
+ weekday: 'short',
47
+ month: 'short',
48
+ day: 'numeric',
49
+ year: 'numeric',
50
+ hour: 'numeric',
51
+ minute: '2-digit',
52
+ });
53
+ }
@@ -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 { GaugeProps } from './types';
5
5
 
6
6
  export const LazyGauge = createLazyComponent<GaugeProps>(
@@ -0,0 +1,29 @@
1
+ # Sparkline
2
+
3
+ Compact inline trend chart (line / area / bar). Resolves stroke + fill via `useThemeColor(color)` — semantic tokens only, no raw scales.
4
+
5
+ ```tsx
6
+ import { Sparkline } from '@djangocfg/ui-tools/sparkline';
7
+
8
+ <Sparkline data={[3, 5, 4, 7, 9, 8, 12]} variant="area" color="success" />
9
+ ```
10
+
11
+ ## Props
12
+
13
+ | Prop | Type | Default | Description |
14
+ |---|---|---|---|
15
+ | `data` | `SparklineDatum[]` | — | `number` or `{ value, label? }`. Empty array renders nothing. |
16
+ | `variant` | `'line' \| 'area' \| 'bar'` | `'line'` | Visual style. |
17
+ | `color` | `'primary' \| 'success' \| 'warning' \| 'destructive' \| 'info'` | `'primary'` | Semantic theme color. |
18
+ | `width` | `number` | `120` | SVG width. |
19
+ | `height` | `number` | `32` | SVG height. |
20
+ | `strokeWidth` | `number` | `1.5` | Line stroke (ignored for `bar`). |
21
+ | `showEndpoint` | `boolean` | `true` | Filled dot at latest point. |
22
+ | `showBaseline` | `boolean` | `false` | Dashed average line. |
23
+ | `ariaLabel` | `string` | — | Accessible label. |
24
+
25
+ Storybook: `apps/storybook/stories/ui-tools/visual/Sparkline.stories.tsx`
26
+
27
+ ---
28
+
29
+ Adapted from jalcoui (MIT).
@@ -0,0 +1,217 @@
1
+ // Adapted from jalcoui (MIT) — github.com/jal-co/ui
2
+ //
3
+ // Generic inline SVG sparkline. Pure SVG, no charting deps. Color resolves
4
+ // through the theme palette (semantic token → hex), so the stroke and area
5
+ // fill follow the active preset.
6
+ //
7
+ // Requires <UiProviders> mounted by the host app (no nested providers here).
8
+
9
+ 'use client';
10
+
11
+ import * as React from 'react';
12
+ import { cn } from '@djangocfg/ui-core/lib';
13
+ import { useThemeColor, alpha } from '@djangocfg/ui-core/styles/palette';
14
+ import type { SparklineDatum, SparklineProps } from './types';
15
+
16
+ function toValue(d: SparklineDatum): number {
17
+ return typeof d === 'number' ? d : d.value;
18
+ }
19
+
20
+ interface Stats {
21
+ values: number[];
22
+ min: number;
23
+ max: number;
24
+ range: number;
25
+ avg: number;
26
+ }
27
+
28
+ function computeStats(data: SparklineDatum[]): Stats {
29
+ const values = data.map(toValue);
30
+ const max = Math.max(...values, 1);
31
+ const min = Math.min(...values);
32
+ const range = max - min || 1;
33
+ const total = values.reduce((s, v) => s + v, 0);
34
+ const avg = values.length > 0 ? total / values.length : 0;
35
+ return { values, min, max, range, avg };
36
+ }
37
+
38
+ function buildLinePath(
39
+ values: number[],
40
+ width: number,
41
+ height: number,
42
+ padding: number,
43
+ min: number,
44
+ range: number,
45
+ ): string {
46
+ if (values.length === 0) return '';
47
+ const drawHeight = height - padding * 2;
48
+ const drawWidth = width - padding * 2;
49
+ const denom = values.length - 1 || 1;
50
+
51
+ return values
52
+ .map((v, i) => {
53
+ const x = padding + (i / denom) * drawWidth;
54
+ const y = padding + drawHeight - ((v - min) / range) * drawHeight;
55
+ return `${i === 0 ? 'M' : 'L'} ${x.toFixed(2)} ${y.toFixed(2)}`;
56
+ })
57
+ .join(' ');
58
+ }
59
+
60
+ function buildAreaPath(
61
+ linePath: string,
62
+ width: number,
63
+ height: number,
64
+ padding: number,
65
+ ): string {
66
+ if (!linePath) return '';
67
+ const lastX = width - padding;
68
+ const firstX = padding;
69
+ const bottom = height - padding;
70
+ return `${linePath} L ${lastX.toFixed(2)} ${bottom.toFixed(2)} L ${firstX.toFixed(2)} ${bottom.toFixed(2)} Z`;
71
+ }
72
+
73
+ function getEndpoint(
74
+ values: number[],
75
+ width: number,
76
+ height: number,
77
+ padding: number,
78
+ min: number,
79
+ range: number,
80
+ ): { x: number; y: number } | null {
81
+ if (values.length === 0) return null;
82
+ const drawHeight = height - padding * 2;
83
+ const lastV = values[values.length - 1];
84
+ return {
85
+ x: width - padding,
86
+ y: padding + drawHeight - ((lastV - min) / range) * drawHeight,
87
+ };
88
+ }
89
+
90
+ function getBaselineY(
91
+ avg: number,
92
+ height: number,
93
+ padding: number,
94
+ min: number,
95
+ range: number,
96
+ ): number {
97
+ const drawHeight = height - padding * 2;
98
+ return padding + drawHeight - ((avg - min) / range) * drawHeight;
99
+ }
100
+
101
+ export function Sparkline({
102
+ data,
103
+ variant = 'line',
104
+ color = 'primary',
105
+ width = 120,
106
+ height = 32,
107
+ strokeWidth = 1.5,
108
+ showEndpoint = true,
109
+ showBaseline = false,
110
+ ariaLabel,
111
+ className,
112
+ ...rest
113
+ }: SparklineProps) {
114
+ const stroke = useThemeColor(color);
115
+ const fill = alpha(stroke, 0.15);
116
+ const baselineStroke = alpha(stroke, 0.4);
117
+
118
+ if (data.length === 0) return null;
119
+
120
+ const stats = computeStats(data);
121
+ const padding = variant === 'bar' ? 2 : 2 + strokeWidth;
122
+ const linePath =
123
+ variant !== 'bar'
124
+ ? buildLinePath(stats.values, width, height, padding, stats.min, stats.range)
125
+ : '';
126
+ const areaPath = variant === 'area' ? buildAreaPath(linePath, width, height, padding) : '';
127
+ const endpoint =
128
+ showEndpoint && variant !== 'bar'
129
+ ? getEndpoint(stats.values, width, height, padding, stats.min, stats.range)
130
+ : null;
131
+ const baselineY = showBaseline
132
+ ? getBaselineY(stats.avg, height, padding, stats.min, stats.range)
133
+ : null;
134
+
135
+ return (
136
+ <div
137
+ data-slot="sparkline"
138
+ data-variant={variant}
139
+ data-color={color}
140
+ className={cn('inline-flex items-center', className)}
141
+ {...rest}
142
+ >
143
+ <svg
144
+ viewBox={`0 0 ${width} ${height}`}
145
+ width={width}
146
+ height={height}
147
+ fill="none"
148
+ role="img"
149
+ aria-label={ariaLabel}
150
+ aria-hidden={ariaLabel ? undefined : true}
151
+ className="block"
152
+ >
153
+ {baselineY != null && (
154
+ <line
155
+ x1={padding}
156
+ y1={baselineY}
157
+ x2={width - padding}
158
+ y2={baselineY}
159
+ stroke={baselineStroke}
160
+ strokeWidth={0.75}
161
+ strokeDasharray="3 3"
162
+ />
163
+ )}
164
+
165
+ {variant === 'bar' && (() => {
166
+ const drawHeight = height - padding * 2;
167
+ const drawWidth = width - padding * 2;
168
+ const gap = 1;
169
+ const barWidth = Math.max(
170
+ 1,
171
+ (drawWidth - gap * (stats.values.length - 1)) / stats.values.length,
172
+ );
173
+ const denom = stats.values.length - 1 || 1;
174
+ return stats.values.map((v, i) => {
175
+ const barHeight = Math.max(1, ((v - stats.min) / stats.range) * drawHeight);
176
+ const x = padding + i * (barWidth + gap);
177
+ const y = padding + drawHeight - barHeight;
178
+ return (
179
+ <rect
180
+ key={i}
181
+ x={x}
182
+ y={y}
183
+ width={barWidth}
184
+ height={barHeight}
185
+ rx={Math.min(barWidth / 2, 1)}
186
+ fill={stroke}
187
+ opacity={0.7 + 0.3 * (i / denom)}
188
+ />
189
+ );
190
+ });
191
+ })()}
192
+
193
+ {variant === 'area' && areaPath && <path d={areaPath} fill={fill} />}
194
+
195
+ {variant !== 'bar' && linePath && (
196
+ <path
197
+ d={linePath}
198
+ stroke={stroke}
199
+ strokeWidth={strokeWidth}
200
+ strokeLinecap="round"
201
+ strokeLinejoin="round"
202
+ fill="none"
203
+ />
204
+ )}
205
+
206
+ {endpoint && (
207
+ <circle
208
+ cx={endpoint.x}
209
+ cy={endpoint.y}
210
+ r={strokeWidth + 0.5}
211
+ fill={stroke}
212
+ />
213
+ )}
214
+ </svg>
215
+ </div>
216
+ );
217
+ }
@@ -0,0 +1,9 @@
1
+ // Adapted from jalcoui (MIT) — github.com/jal-co/ui
2
+
3
+ export { Sparkline } from './Sparkline';
4
+ export type {
5
+ SparklineProps,
6
+ SparklineColor,
7
+ SparklineVariant,
8
+ SparklineDatum,
9
+ } from './types';
@@ -0,0 +1,26 @@
1
+ // Adapted from jalcoui (MIT) — github.com/jal-co/ui
2
+
3
+ 'use client';
4
+
5
+ import { createLazyComponent } from '../../../../common/lazy-wrapper';
6
+ import type { SparklineProps } from './types';
7
+
8
+ export const LazySparkline = createLazyComponent<SparklineProps>(
9
+ () => import('./Sparkline').then((mod) => ({ default: mod.Sparkline })),
10
+ {
11
+ displayName: 'LazySparkline',
12
+ fallback: (
13
+ <span
14
+ data-slot="sparkline-skeleton"
15
+ className="inline-block h-8 w-[120px] animate-pulse rounded bg-muted"
16
+ />
17
+ ),
18
+ },
19
+ );
20
+
21
+ export type {
22
+ SparklineProps,
23
+ SparklineColor,
24
+ SparklineVariant,
25
+ SparklineDatum,
26
+ } from './types';