@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.
- package/dist/audio-player/index.cjs +1 -2
- package/dist/audio-player/index.cjs.map +1 -1
- package/dist/audio-player/index.d.cts +3 -11
- package/dist/audio-player/index.d.ts +3 -11
- package/dist/audio-player/index.mjs +1 -2
- package/dist/audio-player/index.mjs.map +1 -1
- package/dist/file-icon/index.cjs +3 -3
- package/dist/file-icon/index.cjs.map +1 -1
- package/dist/file-icon/index.mjs +3 -3
- package/dist/file-icon/index.mjs.map +1 -1
- package/dist/tree/index.cjs +0 -3
- package/dist/tree/index.cjs.map +1 -1
- package/dist/tree/index.mjs +0 -3
- package/dist/tree/index.mjs.map +1 -1
- package/package.json +117 -36
- package/src/common/FloatingToolbar/actions/CopyAction.tsx +31 -0
- package/src/{components → common}/FloatingToolbar/actions/DownloadAction.tsx +15 -10
- package/src/common/FloatingToolbar/actions/ExpandAction.tsx +33 -0
- package/src/common/FloatingToolbar/actions/FullscreenAction.tsx +38 -0
- package/src/{components → common}/FloatingToolbar/index.tsx +39 -0
- package/src/lib/http.ts +64 -0
- package/src/tools/chat/index.ts +1 -1
- package/src/tools/chat/launcher/ChatFAB.tsx +66 -74
- package/src/tools/chat/launcher/header/ChatHeaderActionButton.tsx +2 -3
- package/src/tools/chat/lazy.tsx +1 -1
- package/src/tools/chat/messages/MessageBubble.tsx +1 -1
- package/src/tools/chat/messages/blocks/builtin.tsx +1 -1
- package/src/tools/chat/messages/blocks/renderers/CodeBlock.tsx +2 -2
- package/src/tools/chat/messages/blocks/renderers/JsonBlock.tsx +12 -1
- package/src/tools/data/DataGrid/lazy.tsx +1 -1
- package/src/tools/data/DataTable/lazy.tsx +1 -1
- package/src/tools/data/JsonTree/JsonViewer.tsx +720 -0
- package/src/tools/data/JsonTree/README.md +126 -73
- package/src/tools/data/JsonTree/index.tsx +3 -95
- package/src/tools/data/JsonTree/lazy.tsx +10 -50
- package/src/tools/data/JsonTree/types.ts +82 -63
- package/src/tools/data/Kanban/lazy.tsx +1 -1
- package/src/tools/data/Listbox/lazy.tsx +1 -1
- package/src/tools/data/Masonry/lazy.tsx +1 -1
- package/src/tools/data/Timeline/lazy.tsx +1 -1
- package/src/tools/data/Tree/components/TreeRow.tsx +0 -11
- package/src/tools/data/Tree/lazy.tsx +1 -1
- package/src/tools/dev/Map/lazy.tsx +1 -1
- package/src/tools/dev/Mermaid/Mermaid.client.tsx +2 -2
- package/src/tools/dev/Mermaid/lazy.tsx +1 -1
- package/src/tools/dev/api/ApiRefTable/ApiRefTable.tsx +65 -0
- package/src/tools/dev/api/ApiRefTable/README.md +31 -0
- package/src/tools/dev/api/ApiRefTable/components/Row.tsx +96 -0
- package/src/tools/dev/api/ApiRefTable/components/TypeDisplay.tsx +44 -0
- package/src/tools/dev/api/ApiRefTable/index.ts +6 -0
- package/src/tools/dev/api/ApiRefTable/lazy.tsx +21 -0
- package/src/tools/dev/api/ApiRefTable/types.ts +82 -0
- package/src/tools/dev/api/ApiRefTable/utils.ts +42 -0
- package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/ApiIntroSection.tsx +1 -1
- package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/CodeSamples/index.tsx +1 -1
- package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Header/index.tsx +1 -1
- package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Responses/ResponseBody.tsx +7 -21
- package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/RequestPanel.tsx +1 -1
- package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/PrettyView.tsx +13 -19
- package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/types.ts +1 -1
- package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/lazy.tsx +1 -1
- package/src/tools/dev/api/RequestViewer/README.md +33 -0
- package/src/tools/dev/api/RequestViewer/RequestViewer.tsx +121 -0
- package/src/tools/dev/api/RequestViewer/components/BodyTab.tsx +44 -0
- package/src/tools/dev/api/RequestViewer/components/EmptyState.tsx +13 -0
- package/src/tools/dev/api/RequestViewer/components/HeadersTab.tsx +78 -0
- package/src/tools/dev/api/RequestViewer/components/TimingTab.tsx +113 -0
- package/src/tools/dev/api/RequestViewer/components/utils.ts +31 -0
- package/src/tools/dev/api/RequestViewer/index.ts +16 -0
- package/src/tools/dev/api/RequestViewer/lazy.tsx +30 -0
- package/src/tools/dev/api/RequestViewer/types.ts +81 -0
- package/src/tools/dev/code/DiffViewer/DiffViewer.tsx +144 -0
- package/src/tools/dev/code/DiffViewer/README.md +33 -0
- package/src/tools/dev/code/DiffViewer/components/CopyButton.tsx +49 -0
- package/src/tools/dev/code/DiffViewer/components/DiffLineContent.tsx +48 -0
- package/src/tools/dev/code/DiffViewer/components/SplitView.tsx +220 -0
- package/src/tools/dev/code/DiffViewer/components/UnifiedView.tsx +154 -0
- package/src/tools/dev/code/DiffViewer/hooks/useDiff.ts +47 -0
- package/src/tools/dev/code/DiffViewer/hooks/useHighlighter.ts +54 -0
- package/src/tools/dev/code/DiffViewer/index.ts +22 -0
- package/src/tools/dev/code/DiffViewer/lazy.tsx +22 -0
- package/src/tools/dev/code/DiffViewer/types.ts +109 -0
- package/src/tools/dev/code/DiffViewer/utils/computeDiff.ts +159 -0
- package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/CollapseToggle.tsx +1 -1
- package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/MarkdownMessage.tsx +1 -1
- package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/components.tsx +2 -2
- package/src/tools/dev/{PrettyCode → code/PrettyCode}/PrettyCode.client.tsx +2 -2
- package/src/tools/dev/{PrettyCode → code/PrettyCode}/lazy.tsx +1 -1
- package/src/tools/dev/ops/EnvTable/EnvTable.tsx +228 -0
- package/src/tools/dev/ops/EnvTable/README.md +29 -0
- package/src/tools/dev/ops/EnvTable/hooks/useEnvMask.ts +121 -0
- package/src/tools/dev/ops/EnvTable/index.ts +12 -0
- package/src/tools/dev/ops/EnvTable/lazy.tsx +21 -0
- package/src/tools/dev/ops/EnvTable/types.ts +76 -0
- package/src/tools/dev/ops/LogViewer/LogViewer.tsx +194 -0
- package/src/tools/dev/ops/LogViewer/README.md +30 -0
- package/src/tools/dev/ops/LogViewer/components/LogRow.tsx +151 -0
- package/src/tools/dev/ops/LogViewer/components/Toolbar.tsx +199 -0
- package/src/tools/dev/ops/LogViewer/hooks/useAutoScroll.ts +68 -0
- package/src/tools/dev/ops/LogViewer/hooks/useLogFilter.ts +58 -0
- package/src/tools/dev/ops/LogViewer/index.ts +18 -0
- package/src/tools/dev/ops/LogViewer/lazy.tsx +25 -0
- package/src/tools/dev/ops/LogViewer/types.ts +142 -0
- package/src/tools/dev/ops/LogViewer/utils/ansi.ts +231 -0
- package/src/tools/forms/CodeEditor/components/Editor.tsx +19 -0
- package/src/tools/forms/CodeEditor/hooks/useEditorTheme.ts +13 -73
- package/src/tools/forms/CodeEditor/lazy.tsx +1 -1
- package/src/tools/forms/CodeEditor/types/index.ts +7 -0
- package/src/tools/forms/FileUpload/lazy.tsx +1 -1
- package/src/tools/forms/JsonEditor/JsonEditor.tsx +115 -0
- package/src/tools/forms/JsonEditor/index.ts +1 -0
- package/src/tools/forms/JsonEditor/lazy.tsx +24 -0
- package/src/tools/forms/JsonForm/index.ts +1 -1
- package/src/tools/forms/JsonForm/lazy.tsx +1 -1
- package/src/tools/forms/MarkdownEditor/MarkdownEditor.tsx +40 -0
- package/src/tools/forms/MarkdownEditor/lazy.tsx +1 -1
- package/src/tools/forms/MarkdownEditor/styles.css +174 -21
- package/src/tools/forms/NotionEditor/CustomKeymap.ts +48 -0
- package/src/tools/forms/NotionEditor/LinkDialog.tsx +133 -0
- package/src/tools/forms/NotionEditor/NotionEditor.tsx +304 -0
- package/src/tools/forms/NotionEditor/README.md +237 -0
- package/src/tools/forms/NotionEditor/SlashExtension.ts +32 -0
- package/src/tools/forms/NotionEditor/SlashList.tsx +136 -0
- package/src/tools/forms/NotionEditor/TaskItemView.tsx +41 -0
- package/src/tools/forms/NotionEditor/createSlashSuggestion.ts +121 -0
- package/src/tools/forms/NotionEditor/extensions.ts +105 -0
- package/src/tools/forms/NotionEditor/index.ts +1 -0
- package/src/tools/forms/NotionEditor/lazy.tsx +44 -0
- package/src/tools/forms/NotionEditor/slashItems.ts +159 -0
- package/src/tools/forms/NotionEditor/styles.css +478 -0
- package/src/tools/forms/NotionEditor/types.ts +28 -0
- package/src/tools/index.ts +153 -13
- package/src/tools/input/Combobox/lazy.tsx +1 -1
- package/src/tools/input/CronScheduler/components/CronPreview.README.md +28 -0
- package/src/tools/input/CronScheduler/components/CronPreview.tsx +136 -0
- package/src/tools/input/CronScheduler/components/index.ts +3 -0
- package/src/tools/input/CronScheduler/index.tsx +5 -1
- package/src/tools/input/CronScheduler/lazy.tsx +5 -1
- package/src/tools/input/CronScheduler/utils/cron-next-runs.ts +122 -0
- package/src/tools/input/CronScheduler/utils/index.ts +1 -0
- package/src/tools/input/Scroller/lazy.tsx +1 -1
- package/src/tools/input/Sortable/lazy.tsx +1 -1
- package/src/tools/input/SpeechRecognition/lazy.tsx +1 -1
- package/src/tools/input/SpeechRecognition/widgets/VoiceComposerSlot.tsx +41 -36
- package/src/tools/media/AudioPlayer/PlayerShell.tsx +3 -11
- package/src/tools/media/AudioPlayer/types.ts +4 -11
- package/src/tools/media/ImageViewer/components/ImageToolbar.tsx +58 -47
- package/src/tools/media/ImageViewer/components/ImageViewer.tsx +35 -19
- package/src/tools/media/ImageViewer/lazy.tsx +1 -1
- package/src/tools/media/ImageViewer/types.ts +4 -0
- package/src/tools/media/LottiePlayer/lazy.tsx +1 -1
- package/src/tools/media/VideoPlayer/VideoPlayer.tsx +47 -1
- package/src/tools/media/VideoPlayer/parts/fullscreen.tsx +21 -4
- package/src/tools/media/VideoPlayer/parts/pip.tsx +21 -4
- package/src/tools/media/VideoPlayer/parts/play-button.tsx +21 -4
- package/src/tools/media/VideoPlayer/parts/playback-rate.tsx +19 -3
- package/src/tools/media/VideoPlayer/parts/volume.tsx +237 -18
- package/src/tools/media/VideoPlayer/styles/video-player.css +87 -7
- package/src/tools/media/VideoPlayer/types.ts +4 -0
- package/src/tools/overlay/ResponsiveDialog/lazy.tsx +1 -1
- package/src/tools/overlay/ScrollSpy/lazy.tsx +1 -1
- package/src/tools/overlay/SelectionToolbar/lazy.tsx +1 -1
- package/src/tools/overlay/Tour/lazy.tsx +1 -1
- package/src/tools/visual/Marquee/lazy.tsx +1 -1
- package/src/tools/visual/QRCode/lazy.tsx +1 -1
- package/src/tools/visual/charts/ActivityGraph/ActivityGraph.tsx +195 -0
- package/src/tools/visual/charts/ActivityGraph/README.md +28 -0
- package/src/tools/visual/charts/ActivityGraph/index.ts +8 -0
- package/src/tools/visual/charts/ActivityGraph/lazy.tsx +21 -0
- package/src/tools/visual/charts/ActivityGraph/types.ts +59 -0
- package/src/tools/visual/charts/ActivityGraph/utils.ts +88 -0
- package/src/tools/visual/charts/CommitGraph/CommitGraph.tsx +80 -0
- package/src/tools/visual/charts/CommitGraph/README.md +28 -0
- package/src/tools/visual/charts/CommitGraph/components/CommitDetail.tsx +107 -0
- package/src/tools/visual/charts/CommitGraph/components/CommitRow.tsx +122 -0
- package/src/tools/visual/charts/CommitGraph/components/Rails.tsx +171 -0
- package/src/tools/visual/charts/CommitGraph/hooks/useGraphLayout.ts +169 -0
- package/src/tools/visual/charts/CommitGraph/hooks/useLaneColors.ts +45 -0
- package/src/tools/visual/charts/CommitGraph/index.ts +14 -0
- package/src/tools/visual/charts/CommitGraph/lazy.tsx +25 -0
- package/src/tools/visual/charts/CommitGraph/types.ts +85 -0
- package/src/tools/visual/charts/CommitGraph/utils.ts +53 -0
- package/src/tools/visual/{Gauge → charts/Gauge}/lazy.tsx +1 -1
- package/src/tools/visual/charts/Sparkline/README.md +29 -0
- package/src/tools/visual/charts/Sparkline/Sparkline.tsx +217 -0
- package/src/tools/visual/charts/Sparkline/index.ts +9 -0
- package/src/tools/visual/charts/Sparkline/lazy.tsx +26 -0
- package/src/tools/visual/charts/Sparkline/types.ts +58 -0
- package/src/tools/visual/design/ColorPalette/ColorPalette.tsx +129 -0
- package/src/tools/visual/design/ColorPalette/README.md +34 -0
- package/src/tools/visual/design/ColorPalette/components/Swatch.tsx +102 -0
- package/src/tools/visual/design/ColorPalette/hooks/useCopyToClipboard.ts +41 -0
- package/src/tools/visual/design/ColorPalette/index.ts +12 -0
- package/src/tools/visual/design/ColorPalette/lazy.tsx +21 -0
- package/src/tools/visual/design/ColorPalette/types.ts +63 -0
- package/src/tools/visual/design/ColorPalette/utils.ts +83 -0
- package/src/tools/visual/{ColorPicker → design/ColorPicker}/lazy.tsx +1 -1
- package/src/tools/visual/{FileIcon → design/FileIcon}/treeAdapter.tsx +1 -1
- package/src/tools/visual/{Fps → indicators/Fps}/lazy.tsx +1 -1
- package/src/tools/visual/{Rating → indicators/Rating}/lazy.tsx +1 -1
- package/src/tools/visual/indicators/StatusIndicator/README.md +28 -0
- package/src/tools/visual/indicators/StatusIndicator/StatusIndicator.tsx +83 -0
- package/src/tools/visual/indicators/StatusIndicator/index.ts +14 -0
- package/src/tools/visual/indicators/StatusIndicator/lazy.tsx +21 -0
- package/src/tools/visual/indicators/StatusIndicator/types.ts +133 -0
- package/src/components/FloatingToolbar/actions/CopyAction.tsx +0 -22
- package/src/components/FloatingToolbar/actions/ExpandAction.tsx +0 -25
- package/src/components/FloatingToolbar/actions/FullscreenAction.tsx +0 -30
- package/src/tools/data/JsonTree/components/JsonContent.tsx +0 -197
- package/src/tools/data/JsonTree/hooks/useJsonExpand.ts +0 -50
- /package/src/{components → common}/FloatingToolbar/FloatingToolbar.css +0 -0
- /package/src/{components → common}/FloatingToolbar/actions/index.ts +0 -0
- /package/src/{components → common}/FloatingToolbar/hooks/useElementCorner.ts +0 -0
- /package/src/{components → common}/FloatingToolbar/hooks/useScrollIsolation.ts +0 -0
- /package/src/{components → common}/index.ts +0 -0
- /package/src/{components → common}/lazy-wrapper.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/README.md +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/DocsView.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/CodeSamples/LanguageTabs.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/CodeSamples/useCodeSnippet.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Header/MetaActions.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Header/MethodBadge.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Header/PathDisplay.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Parameters/ParamGroup.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Parameters/ParamRow.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Parameters/index.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/RequestBody/index.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Responses/ResponseRow.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Responses/StatusTag.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Responses/index.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/SchemaFields/FieldRow.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/SchemaFields/buildTree.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/SchemaFields/index.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/SchemaFields/types.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Section/SectionHeader.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Section/defaults.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/Section/index.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/context.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/hooks/useSectionHash.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/index.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/store/index.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/store/selectors.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/EndpointDoc/types.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/SchemaCopyMenu.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/BrandHeader.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/CategoryBlock.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/EndpointRow.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/SchemaSection.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/SearchInput.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/SidebarBody.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/Toolbar.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/buildVM.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/index.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/types.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/Sidebar/useDebouncedValue.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/SlideInPlayground.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/TryItSheet.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/anchor.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/grouping.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/index.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/DocsLayout/sidebarLabel.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/index.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/BodyFormEditor.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/EndpointDraftSync.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/EndpointResetButton.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/PreviewView.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/RawView.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/StatusBar.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/ViewTabs.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/detectContent.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/index.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ResponsePanel/useResponseView.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/SendButton.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/components/shared/ui.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/constants.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/context/PlaygroundContext.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/index.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/useDocsUrlSync.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/useEndpointDraft.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/useMobile.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/hooks/useOpenApiSchema.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/index.tsx +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/types.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/apiKeyManager.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/codeSamples.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/formatters.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/index.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/operationToHar.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/sampler.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/schemaExport.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/scrollParent.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/url.ts +0 -0
- /package/src/tools/dev/{OpenapiViewer → api/OpenapiViewer}/utils/versionManager.ts +0 -0
- /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/ActionRow.tsx +0 -0
- /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/ChatMessageRow.tsx +0 -0
- /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/CodeBlock.tsx +0 -0
- /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/README.md +0 -0
- /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/index.ts +0 -0
- /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/linkRules.ts +0 -0
- /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/plainText.ts +0 -0
- /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/sanitize.ts +0 -0
- /package/src/tools/dev/{MarkdownMessage → code/MarkdownMessage}/types.ts +0 -0
- /package/src/tools/dev/{PrettyCode → code/PrettyCode}/README.md +0 -0
- /package/src/tools/dev/{PrettyCode → code/PrettyCode}/index.tsx +0 -0
- /package/src/tools/dev/{PrettyCode → code/PrettyCode}/registerPrismLanguages.ts +0 -0
- /package/src/tools/visual/{Gauge → charts/Gauge}/Gauge.tsx +0 -0
- /package/src/tools/visual/{Gauge → charts/Gauge}/index.ts +0 -0
- /package/src/tools/visual/{Gauge → charts/Gauge}/types.ts +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/ColorPicker.tsx +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/context/ColorPickerContext.tsx +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/context/ColorPickerStore.tsx +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/context/index.ts +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/index.ts +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/lib/color-utils.ts +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerAlphaSlider.tsx +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerArea.tsx +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerEyeDropper.tsx +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerFormatSelect.tsx +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerHueSlider.tsx +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerInput.tsx +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/ColorPickerSwatch.tsx +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/parts/index.ts +0 -0
- /package/src/tools/visual/{ColorPicker → design/ColorPicker}/types.ts +0 -0
- /package/src/tools/visual/{FileIcon → design/FileIcon}/FileIcon.tsx +0 -0
- /package/src/tools/visual/{FileIcon → design/FileIcon}/get-file-icon.ts +0 -0
- /package/src/tools/visual/{FileIcon → design/FileIcon}/icons/icon-data.ts +0 -0
- /package/src/tools/visual/{FileIcon → design/FileIcon}/index.ts +0 -0
- /package/src/tools/visual/{FileIcon → design/FileIcon}/loader.ts +0 -0
- /package/src/tools/visual/{FileIcon → design/FileIcon}/specialFolders.ts +0 -0
- /package/src/tools/visual/{Fps → indicators/Fps}/Fps.tsx +0 -0
- /package/src/tools/visual/{Fps → indicators/Fps}/index.ts +0 -0
- /package/src/tools/visual/{Fps → indicators/Fps}/types.ts +0 -0
- /package/src/tools/visual/{Rating → indicators/Rating}/Rating.tsx +0 -0
- /package/src/tools/visual/{Rating → indicators/Rating}/index.ts +0 -0
- /package/src/tools/visual/{Rating → indicators/Rating}/types.ts +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
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 { ActivityGraphProps } from './types';
|
|
7
|
+
|
|
8
|
+
export const LazyActivityGraph = createLazyComponent<ActivityGraphProps>(
|
|
9
|
+
() => import('./ActivityGraph').then((mod) => ({ default: mod.ActivityGraph })),
|
|
10
|
+
{
|
|
11
|
+
displayName: 'LazyActivityGraph',
|
|
12
|
+
fallback: (
|
|
13
|
+
<div
|
|
14
|
+
data-slot="activity-graph-skeleton"
|
|
15
|
+
className="h-[120px] w-full animate-pulse rounded-md bg-muted"
|
|
16
|
+
/>
|
|
17
|
+
),
|
|
18
|
+
},
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export type { ActivityGraphProps, ActivityEntry } from './types';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Adapted from jalcoui (MIT) — github.com/jal-co/ui
|
|
2
|
+
|
|
3
|
+
import type * as React from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Single day entry in the contribution heatmap.
|
|
7
|
+
*/
|
|
8
|
+
export interface ActivityEntry {
|
|
9
|
+
/** ISO date string (YYYY-MM-DD). */
|
|
10
|
+
date: string;
|
|
11
|
+
/** Activity count for this date. */
|
|
12
|
+
count: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Five opacity stops applied to the resolved theme `primary` color for
|
|
17
|
+
* intensity levels 0–4. Level 0 is the empty / no-activity surface and is
|
|
18
|
+
* intentionally low (almost equal to `bg-muted`).
|
|
19
|
+
*
|
|
20
|
+
* Audit notes (AUDIT.md §1) collapse the full emerald scale to
|
|
21
|
+
* `alpha(primary, …)`, so the same five stops cover light and dark themes.
|
|
22
|
+
*/
|
|
23
|
+
export const DEFAULT_INTENSITY_OPACITY: readonly [number, number, number, number, number] = [
|
|
24
|
+
0.08, 0.18, 0.35, 0.6, 0.95,
|
|
25
|
+
] as const;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Thresholds (ratios of `value / max`) that map a normalized count into
|
|
29
|
+
* one of four non-zero intensity buckets. Combined with the empty bucket
|
|
30
|
+
* for `count === 0` they yield the 5 levels expected by the heatmap.
|
|
31
|
+
*
|
|
32
|
+
* Mirrors the original jalcoui `getIntensity` (`<=0.25 / 0.5 / 0.75`).
|
|
33
|
+
*/
|
|
34
|
+
export const DEFAULT_INTENSITY_THRESHOLDS: readonly [number, number, number] = [0.25, 0.5, 0.75];
|
|
35
|
+
|
|
36
|
+
export interface ActivityGraphProps extends Omit<React.ComponentProps<'div'>, 'children'> {
|
|
37
|
+
/** Activity data entries. Duplicates with the same `date` are summed. */
|
|
38
|
+
data: ActivityEntry[];
|
|
39
|
+
/**
|
|
40
|
+
* Override the 5 opacity stops applied to the active theme `primary`
|
|
41
|
+
* color. Index 0 is the empty surface; index 4 is the peak.
|
|
42
|
+
*/
|
|
43
|
+
intensityOpacity?: readonly [number, number, number, number, number];
|
|
44
|
+
/**
|
|
45
|
+
* Fixed cell size in pixels. When omitted the component auto-sizes
|
|
46
|
+
* blocks to fill the available container width via `useResizeObserver`.
|
|
47
|
+
*/
|
|
48
|
+
blockSize?: number;
|
|
49
|
+
/** Cell border radius in pixels. @default 2 */
|
|
50
|
+
blockRadius?: number;
|
|
51
|
+
/** Number of trailing weeks to display. @default 52 */
|
|
52
|
+
weeks?: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const GAP = 2;
|
|
56
|
+
export const DAY_LABEL_WIDTH = 28;
|
|
57
|
+
export const MONTH_LABEL_HEIGHT = 16;
|
|
58
|
+
export const DAY_LABELS = ['Mon', 'Wed', 'Fri'] as const;
|
|
59
|
+
export const DAY_LABEL_INDICES = [1, 3, 5] as const;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Adapted from jalcoui (MIT) — github.com/jal-co/ui
|
|
2
|
+
|
|
3
|
+
import type { ActivityEntry } from './types';
|
|
4
|
+
import { GAP } from './types';
|
|
5
|
+
|
|
6
|
+
export interface WeekDay {
|
|
7
|
+
date: Date;
|
|
8
|
+
count: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Bucket the supplied entries into a fixed-size grid that ends on the
|
|
13
|
+
* current week and spans `weekCount` weeks. Missing dates fill with 0.
|
|
14
|
+
*/
|
|
15
|
+
export function buildWeeks(data: ActivityEntry[], weekCount: number): WeekDay[][] {
|
|
16
|
+
const countMap = new Map<string, number>();
|
|
17
|
+
for (const entry of data) {
|
|
18
|
+
countMap.set(entry.date, (countMap.get(entry.date) ?? 0) + entry.count);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const today = new Date();
|
|
22
|
+
today.setHours(0, 0, 0, 0);
|
|
23
|
+
const todayDay = today.getDay();
|
|
24
|
+
|
|
25
|
+
const endOfWeek = new Date(today);
|
|
26
|
+
endOfWeek.setDate(today.getDate() + (6 - todayDay));
|
|
27
|
+
|
|
28
|
+
const totalDays = weekCount * 7;
|
|
29
|
+
const startDate = new Date(endOfWeek);
|
|
30
|
+
startDate.setDate(endOfWeek.getDate() - totalDays + 1);
|
|
31
|
+
|
|
32
|
+
const weeks: WeekDay[][] = [];
|
|
33
|
+
let currentWeek: WeekDay[] = [];
|
|
34
|
+
|
|
35
|
+
for (let i = 0; i < totalDays; i++) {
|
|
36
|
+
const d = new Date(startDate);
|
|
37
|
+
d.setDate(startDate.getDate() + i);
|
|
38
|
+
const key = d.toISOString().slice(0, 10);
|
|
39
|
+
currentWeek.push({ date: d, count: countMap.get(key) ?? 0 });
|
|
40
|
+
|
|
41
|
+
if (currentWeek.length === 7) {
|
|
42
|
+
weeks.push(currentWeek);
|
|
43
|
+
currentWeek = [];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (currentWeek.length > 0) {
|
|
48
|
+
weeks.push(currentWeek);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return weeks;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Find the column offset for the first week of every new month. Used to
|
|
56
|
+
* lay month labels along the top of the grid.
|
|
57
|
+
*/
|
|
58
|
+
export function getMonthLabels(
|
|
59
|
+
weeks: WeekDay[][],
|
|
60
|
+
blockSize: number,
|
|
61
|
+
): { label: string; offset: number }[] {
|
|
62
|
+
const months: { label: string; offset: number }[] = [];
|
|
63
|
+
let lastKey = '';
|
|
64
|
+
|
|
65
|
+
for (let w = 0; w < weeks.length; w++) {
|
|
66
|
+
const firstDay = weeks[w][0];
|
|
67
|
+
const key = `${firstDay.date.getFullYear()}-${firstDay.date.getMonth()}`;
|
|
68
|
+
|
|
69
|
+
if (key !== lastKey) {
|
|
70
|
+
months.push({
|
|
71
|
+
label: firstDay.date.toLocaleString('en-US', { month: 'short' }),
|
|
72
|
+
offset: w * (blockSize + GAP),
|
|
73
|
+
});
|
|
74
|
+
lastKey = key;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return months;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function formatDate(date: Date): string {
|
|
82
|
+
return date.toLocaleDateString('en-US', {
|
|
83
|
+
weekday: 'short',
|
|
84
|
+
month: 'short',
|
|
85
|
+
day: 'numeric',
|
|
86
|
+
year: 'numeric',
|
|
87
|
+
});
|
|
88
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Adapted from jalcoui (MIT) — github.com/jal-co/ui
|
|
2
|
+
//
|
|
3
|
+
// Topological git graph with rail lines showing branch forks, merges, and
|
|
4
|
+
// commit ancestry. Renders the same visual as GitKraken / Fork / Tower.
|
|
5
|
+
//
|
|
6
|
+
// Composer only — heavy lifting lives in:
|
|
7
|
+
// - hooks/useGraphLayout.ts topology pass
|
|
8
|
+
// - hooks/useLaneColors.ts theme-aware categorical palette
|
|
9
|
+
// - components/Rails.tsx SVG rails + dot
|
|
10
|
+
// - components/CommitRow.tsx row body (refs, message, meta)
|
|
11
|
+
// - components/CommitDetail.tsx popover detail
|
|
12
|
+
//
|
|
13
|
+
// Project rules exercised here: semantic tokens for chrome (no raw scales),
|
|
14
|
+
// theme-derived hex colors for SVG strokes (no Tailwind classes inside
|
|
15
|
+
// `stroke=`), no nested overlay providers, attribution header, lazy entry.
|
|
16
|
+
|
|
17
|
+
'use client';
|
|
18
|
+
|
|
19
|
+
import * as React from 'react';
|
|
20
|
+
import { cn } from '@djangocfg/ui-core/lib';
|
|
21
|
+
import type { CommitGraphProps } from './types';
|
|
22
|
+
import { useGraphLayout } from './hooks/useGraphLayout';
|
|
23
|
+
import { useLaneColors, pickLaneColor } from './hooks/useLaneColors';
|
|
24
|
+
import { CommitRow } from './components/CommitRow';
|
|
25
|
+
|
|
26
|
+
function CommitGraph({
|
|
27
|
+
commits,
|
|
28
|
+
truncateHash = 7,
|
|
29
|
+
railWidth = 24,
|
|
30
|
+
className,
|
|
31
|
+
...props
|
|
32
|
+
}: CommitGraphProps) {
|
|
33
|
+
const laneColors = useLaneColors();
|
|
34
|
+
const { rows, maxRails } = useGraphLayout(commits, laneColors);
|
|
35
|
+
const svgWidth = maxRails * railWidth;
|
|
36
|
+
|
|
37
|
+
if (rows.length === 0) {
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
data-slot="commit-graph"
|
|
41
|
+
className={cn(
|
|
42
|
+
'flex items-center justify-center rounded-xl border border-border/60 bg-card py-10 text-sm text-muted-foreground shadow-sm',
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
>
|
|
47
|
+
No commits.
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<div
|
|
54
|
+
data-slot="commit-graph"
|
|
55
|
+
className={cn(
|
|
56
|
+
'overflow-hidden rounded-xl border border-border/60 bg-card shadow-sm',
|
|
57
|
+
className,
|
|
58
|
+
)}
|
|
59
|
+
style={{ ['--commit-graph-rail-width' as string]: `${svgWidth}px` }}
|
|
60
|
+
{...props}
|
|
61
|
+
>
|
|
62
|
+
<div className="overflow-x-auto">
|
|
63
|
+
{rows.map((row, i) => (
|
|
64
|
+
<CommitRow
|
|
65
|
+
key={`${row.commit.hash}-${i}`}
|
|
66
|
+
row={row}
|
|
67
|
+
prevRow={i > 0 ? rows[i - 1] : null}
|
|
68
|
+
railWidth={railWidth}
|
|
69
|
+
maxRails={maxRails}
|
|
70
|
+
truncateHash={truncateHash}
|
|
71
|
+
laneColors={laneColors}
|
|
72
|
+
railColor={pickLaneColor(laneColors, row.rail)}
|
|
73
|
+
/>
|
|
74
|
+
))}
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export { CommitGraph };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# CommitGraph
|
|
2
|
+
|
|
3
|
+
Git-style commit rail visualisation. Computes rail topology from `parents` and renders SVG rails + edges. Lane colors come from `useStylePresets()` so every theme preset re-skins consistently.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { CommitGraph } from '@djangocfg/ui-tools/commit-graph';
|
|
7
|
+
|
|
8
|
+
<CommitGraph
|
|
9
|
+
commits={[
|
|
10
|
+
{ hash: 'a1b2c3d', message: 'init', author: { name: 'Mark' }, date: '2025-01-01', parents: [] },
|
|
11
|
+
{ hash: 'd4e5f6g', message: 'feat: auth', author: { name: 'Mark' }, date: '2025-01-02', parents: ['a1b2c3d'] },
|
|
12
|
+
]}
|
|
13
|
+
/>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Props
|
|
17
|
+
|
|
18
|
+
| Prop | Type | Default | Description |
|
|
19
|
+
|---|---|---|---|
|
|
20
|
+
| `commits` | `Commit[]` | — | Commits in topological order (newest first). Merge = two+ `parents`. |
|
|
21
|
+
| `truncateHash` | `number` | `7` | Number of hash characters to display. |
|
|
22
|
+
| `railWidth` | `number` | `24` | Pixel width per rail column. |
|
|
23
|
+
|
|
24
|
+
Storybook: `apps/storybook/stories/ui-tools/visual/CommitGraph.stories.tsx`
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
Adapted from jalcoui (MIT).
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Adapted from jalcoui (MIT) — github.com/jal-co/ui
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/* eslint-disable @next/next/no-img-element */
|
|
6
|
+
|
|
7
|
+
import * as React from 'react';
|
|
8
|
+
import { Popover, PopoverContent, PopoverTrigger } from '@djangocfg/ui-core';
|
|
9
|
+
import { alpha } from '@djangocfg/ui-core/styles/palette';
|
|
10
|
+
import type { Commit } from '../types';
|
|
11
|
+
import { formatFullDate, initials } from '../utils';
|
|
12
|
+
|
|
13
|
+
interface CommitDetailProps {
|
|
14
|
+
commit: Commit;
|
|
15
|
+
hashLength: number;
|
|
16
|
+
railColor: string;
|
|
17
|
+
children: React.ReactNode;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Popover with the full commit message, refs, tag and parent hashes. The
|
|
22
|
+
* trigger is the row button — the parent component owns the row markup and
|
|
23
|
+
* passes it through `children`.
|
|
24
|
+
*
|
|
25
|
+
* Requires the host app to mount `<UiProviders>` at the root (we do not
|
|
26
|
+
* remount a Popover provider here — see CONTRACT §5).
|
|
27
|
+
*/
|
|
28
|
+
export function CommitDetail({
|
|
29
|
+
commit,
|
|
30
|
+
hashLength,
|
|
31
|
+
railColor,
|
|
32
|
+
children,
|
|
33
|
+
}: CommitDetailProps) {
|
|
34
|
+
// Pre-compute style strings outside JSX (per project rule: hoist derived
|
|
35
|
+
// values into named consts before `return (...)`).
|
|
36
|
+
const tagStyle = {
|
|
37
|
+
backgroundColor: alpha(railColor, 0.125),
|
|
38
|
+
color: railColor,
|
|
39
|
+
};
|
|
40
|
+
const initialsLabel = initials(commit.author.name);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Popover>
|
|
44
|
+
<PopoverTrigger asChild>{children}</PopoverTrigger>
|
|
45
|
+
<PopoverContent side="right" sideOffset={8} className="w-80 p-3">
|
|
46
|
+
<div className="flex flex-col gap-2">
|
|
47
|
+
<p className="text-sm font-medium leading-snug">{commit.message}</p>
|
|
48
|
+
|
|
49
|
+
<div className="flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
|
|
50
|
+
<span className="inline-flex items-center gap-1.5">
|
|
51
|
+
{commit.author.avatarUrl ? (
|
|
52
|
+
<img
|
|
53
|
+
src={commit.author.avatarUrl}
|
|
54
|
+
alt=""
|
|
55
|
+
width={14}
|
|
56
|
+
height={14}
|
|
57
|
+
className="size-3.5 rounded-full border border-border/60 bg-muted"
|
|
58
|
+
/>
|
|
59
|
+
) : (
|
|
60
|
+
<span className="flex size-3.5 items-center justify-center rounded-full bg-muted text-[7px] font-bold">
|
|
61
|
+
{initialsLabel}
|
|
62
|
+
</span>
|
|
63
|
+
)}
|
|
64
|
+
{commit.author.name}
|
|
65
|
+
</span>
|
|
66
|
+
<span className="text-border">·</span>
|
|
67
|
+
<code className="rounded bg-muted px-1 py-0.5 font-mono text-[10px]">
|
|
68
|
+
{commit.hash.slice(0, hashLength)}
|
|
69
|
+
</code>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<div className="text-[11px] text-muted-foreground">
|
|
73
|
+
{formatFullDate(commit.date)}
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
{(commit.refs || commit.tag) && (
|
|
77
|
+
<div className="flex flex-wrap gap-1">
|
|
78
|
+
{commit.refs?.map((ref) => (
|
|
79
|
+
<span
|
|
80
|
+
key={ref}
|
|
81
|
+
className="inline-flex items-center gap-1 rounded-md border border-border/60 bg-muted/50 px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground"
|
|
82
|
+
>
|
|
83
|
+
{ref}
|
|
84
|
+
</span>
|
|
85
|
+
))}
|
|
86
|
+
{commit.tag && (
|
|
87
|
+
<span
|
|
88
|
+
className="inline-flex items-center rounded-md px-1.5 py-0.5 text-[10px] font-medium"
|
|
89
|
+
style={tagStyle}
|
|
90
|
+
>
|
|
91
|
+
{commit.tag}
|
|
92
|
+
</span>
|
|
93
|
+
)}
|
|
94
|
+
</div>
|
|
95
|
+
)}
|
|
96
|
+
|
|
97
|
+
{commit.parents.length > 0 && (
|
|
98
|
+
<div className="text-[10px] text-muted-foreground/60">
|
|
99
|
+
{commit.parents.length === 1 ? 'Parent' : 'Parents'}:{' '}
|
|
100
|
+
{commit.parents.map((p) => p.slice(0, hashLength)).join(', ')}
|
|
101
|
+
</div>
|
|
102
|
+
)}
|
|
103
|
+
</div>
|
|
104
|
+
</PopoverContent>
|
|
105
|
+
</Popover>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Adapted from jalcoui (MIT) — github.com/jal-co/ui
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/* eslint-disable @next/next/no-img-element */
|
|
6
|
+
|
|
7
|
+
import * as React from 'react';
|
|
8
|
+
import { alpha } from '@djangocfg/ui-core/styles/palette';
|
|
9
|
+
import { ROW_HEIGHT, type GraphRow } from '../types';
|
|
10
|
+
import { formatRelativeDate, initials } from '../utils';
|
|
11
|
+
import { CommitDetail } from './CommitDetail';
|
|
12
|
+
import { Rails } from './Rails';
|
|
13
|
+
|
|
14
|
+
interface CommitRowProps {
|
|
15
|
+
row: GraphRow;
|
|
16
|
+
prevRow: GraphRow | null;
|
|
17
|
+
railWidth: number;
|
|
18
|
+
maxRails: number;
|
|
19
|
+
truncateHash: number;
|
|
20
|
+
laneColors: string[];
|
|
21
|
+
railColor: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Single commit row: rails column, refs, message, hash + author + time.
|
|
26
|
+
* Wrapped in a {@link CommitDetail} popover.
|
|
27
|
+
*/
|
|
28
|
+
export function CommitRow({
|
|
29
|
+
row,
|
|
30
|
+
prevRow,
|
|
31
|
+
railWidth,
|
|
32
|
+
maxRails,
|
|
33
|
+
truncateHash,
|
|
34
|
+
laneColors,
|
|
35
|
+
railColor,
|
|
36
|
+
}: CommitRowProps) {
|
|
37
|
+
const svgWidth = maxRails * railWidth;
|
|
38
|
+
const refStyle = {
|
|
39
|
+
borderColor: alpha(railColor, 0.25),
|
|
40
|
+
backgroundColor: alpha(railColor, 0.0625),
|
|
41
|
+
color: railColor,
|
|
42
|
+
};
|
|
43
|
+
const tagStyle = {
|
|
44
|
+
backgroundColor: alpha(railColor, 0.125),
|
|
45
|
+
color: railColor,
|
|
46
|
+
};
|
|
47
|
+
const initialsLabel = initials(row.commit.author.name);
|
|
48
|
+
const shortHash = row.commit.hash.slice(0, truncateHash);
|
|
49
|
+
const relativeDate = formatRelativeDate(row.commit.date);
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<CommitDetail commit={row.commit} hashLength={truncateHash} railColor={railColor}>
|
|
53
|
+
<button
|
|
54
|
+
type="button"
|
|
55
|
+
data-slot="commit-entry"
|
|
56
|
+
className="flex w-full items-center gap-0 border-b border-border/30 transition-colors hover:bg-muted/30 focus-visible:bg-muted/30 focus-visible:outline-none last:border-b-0"
|
|
57
|
+
style={{ height: ROW_HEIGHT }}
|
|
58
|
+
>
|
|
59
|
+
{/* Rails */}
|
|
60
|
+
<div style={{ width: svgWidth }} className="shrink-0">
|
|
61
|
+
<Rails
|
|
62
|
+
row={row}
|
|
63
|
+
prevRow={prevRow}
|
|
64
|
+
railWidth={railWidth}
|
|
65
|
+
maxRails={maxRails}
|
|
66
|
+
laneColors={laneColors}
|
|
67
|
+
/>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
{/* Refs + tag */}
|
|
71
|
+
<div className="flex shrink-0 items-center gap-1 px-2">
|
|
72
|
+
{row.commit.refs?.map((ref) => (
|
|
73
|
+
<span
|
|
74
|
+
key={ref}
|
|
75
|
+
className="inline-flex items-center gap-1 rounded-md border px-1.5 py-0.5 text-[10px] font-semibold leading-none"
|
|
76
|
+
style={refStyle}
|
|
77
|
+
>
|
|
78
|
+
{ref}
|
|
79
|
+
</span>
|
|
80
|
+
))}
|
|
81
|
+
{row.commit.tag && (
|
|
82
|
+
<span
|
|
83
|
+
className="inline-flex items-center rounded-md px-1.5 py-0.5 text-[10px] font-semibold leading-none"
|
|
84
|
+
style={tagStyle}
|
|
85
|
+
>
|
|
86
|
+
{row.commit.tag}
|
|
87
|
+
</span>
|
|
88
|
+
)}
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
{/* Message */}
|
|
92
|
+
<p className="min-w-0 flex-1 truncate px-2 text-left text-sm text-foreground/80">
|
|
93
|
+
{row.commit.message}
|
|
94
|
+
</p>
|
|
95
|
+
|
|
96
|
+
{/* Meta */}
|
|
97
|
+
<div className="flex shrink-0 items-center gap-3 px-3">
|
|
98
|
+
<code className="font-mono text-[11px] text-muted-foreground/60">
|
|
99
|
+
{shortHash}
|
|
100
|
+
</code>
|
|
101
|
+
<span className="inline-flex items-center gap-1.5 text-xs text-muted-foreground">
|
|
102
|
+
{row.commit.author.avatarUrl ? (
|
|
103
|
+
<img
|
|
104
|
+
src={row.commit.author.avatarUrl}
|
|
105
|
+
alt=""
|
|
106
|
+
width={16}
|
|
107
|
+
height={16}
|
|
108
|
+
className="size-4 rounded-full border border-border/60 bg-muted"
|
|
109
|
+
/>
|
|
110
|
+
) : (
|
|
111
|
+
<span className="flex size-4 items-center justify-center rounded-full bg-muted text-[8px] font-bold text-muted-foreground">
|
|
112
|
+
{initialsLabel}
|
|
113
|
+
</span>
|
|
114
|
+
)}
|
|
115
|
+
<span className="hidden sm:inline">{row.commit.author.name}</span>
|
|
116
|
+
</span>
|
|
117
|
+
<span className="text-[11px] text-muted-foreground/50">{relativeDate}</span>
|
|
118
|
+
</div>
|
|
119
|
+
</button>
|
|
120
|
+
</CommitDetail>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// Adapted from jalcoui (MIT) — github.com/jal-co/ui
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { useThemeColor } from '@djangocfg/ui-core/styles/palette';
|
|
7
|
+
import { ROW_HEIGHT, type GraphRow } from '../types';
|
|
8
|
+
import { pickLaneColor } from '../hooks/useLaneColors';
|
|
9
|
+
|
|
10
|
+
interface RailsProps {
|
|
11
|
+
row: GraphRow;
|
|
12
|
+
prevRow: GraphRow | null;
|
|
13
|
+
railWidth: number;
|
|
14
|
+
maxRails: number;
|
|
15
|
+
laneColors: string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* SVG renderer for the rail column of a single commit row.
|
|
20
|
+
*
|
|
21
|
+
* Draws four classes of geometry:
|
|
22
|
+
* 1. Pass-through rails — straight vertical line top→bottom for any rail
|
|
23
|
+
* that is active above *and* below this row and is not the commit rail.
|
|
24
|
+
* 2. Commit rail incoming/outgoing — half-height verticals on the commit's
|
|
25
|
+
* own rail, depending on whether the rail was active above/below.
|
|
26
|
+
* 3. Fork-out curves — bezier from the commit's rail down to a freshly
|
|
27
|
+
* allocated rail (a new branch coming off this commit).
|
|
28
|
+
* 4. Merge curves — bezier from a source rail into the commit dot
|
|
29
|
+
* (or from the dot down to a target rail).
|
|
30
|
+
*
|
|
31
|
+
* SVG fill/stroke values are hex strings resolved via the theme palette;
|
|
32
|
+
* raw Tailwind classes do not work inside `stroke=`.
|
|
33
|
+
*/
|
|
34
|
+
export function Rails({ row, prevRow, railWidth, maxRails, laneColors }: RailsProps) {
|
|
35
|
+
// Background color for the commit dot ring — matches the surface the row
|
|
36
|
+
// is mounted on so the dot reads as "popped out" on every preset.
|
|
37
|
+
const background = useThemeColor('background');
|
|
38
|
+
|
|
39
|
+
const w = maxRails * railWidth;
|
|
40
|
+
const h = ROW_HEIGHT;
|
|
41
|
+
const cy = h / 2;
|
|
42
|
+
const rx = (rail: number) => rail * railWidth + railWidth / 2;
|
|
43
|
+
const color = (rail: number) => pickLaneColor(laneColors, rail);
|
|
44
|
+
|
|
45
|
+
const commitX = rx(row.rail);
|
|
46
|
+
|
|
47
|
+
const activeAbove = new Set<number>();
|
|
48
|
+
if (prevRow) {
|
|
49
|
+
for (let r = 0; r < prevRow.rails.length; r++) {
|
|
50
|
+
if (prevRow.rails[r] !== null) activeAbove.add(r);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const activeBelow = new Set<number>();
|
|
54
|
+
for (let r = 0; r < row.rails.length; r++) {
|
|
55
|
+
if (row.rails[r] !== null) activeBelow.add(r);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const passThroughRails = Array.from(activeAbove).filter(
|
|
59
|
+
(r) => r !== row.rail && activeBelow.has(r),
|
|
60
|
+
);
|
|
61
|
+
const endingRails = Array.from(activeAbove).filter(
|
|
62
|
+
(r) => r !== row.rail && !activeBelow.has(r),
|
|
63
|
+
);
|
|
64
|
+
const forkEdges = row.edges.filter((e) => e.type === 'fork-out');
|
|
65
|
+
const mergeEdges = row.edges.filter((e) => e.type === 'merge-in');
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<svg
|
|
69
|
+
width={w}
|
|
70
|
+
height={h}
|
|
71
|
+
viewBox={`0 0 ${w} ${h}`}
|
|
72
|
+
className="shrink-0"
|
|
73
|
+
aria-hidden="true"
|
|
74
|
+
>
|
|
75
|
+
{passThroughRails.map((r) => {
|
|
76
|
+
const x = rx(r);
|
|
77
|
+
return (
|
|
78
|
+
<line
|
|
79
|
+
key={`pt-${r}`}
|
|
80
|
+
x1={x}
|
|
81
|
+
y1={0}
|
|
82
|
+
x2={x}
|
|
83
|
+
y2={h}
|
|
84
|
+
stroke={color(r)}
|
|
85
|
+
strokeWidth={2}
|
|
86
|
+
strokeOpacity={0.6}
|
|
87
|
+
/>
|
|
88
|
+
);
|
|
89
|
+
})}
|
|
90
|
+
|
|
91
|
+
{activeAbove.has(row.rail) && (
|
|
92
|
+
<line
|
|
93
|
+
x1={commitX}
|
|
94
|
+
y1={0}
|
|
95
|
+
x2={commitX}
|
|
96
|
+
y2={cy}
|
|
97
|
+
stroke={color(row.rail)}
|
|
98
|
+
strokeWidth={2}
|
|
99
|
+
strokeOpacity={0.6}
|
|
100
|
+
/>
|
|
101
|
+
)}
|
|
102
|
+
|
|
103
|
+
{activeBelow.has(row.rail) && (
|
|
104
|
+
<line
|
|
105
|
+
x1={commitX}
|
|
106
|
+
y1={cy}
|
|
107
|
+
x2={commitX}
|
|
108
|
+
y2={h}
|
|
109
|
+
stroke={color(row.rail)}
|
|
110
|
+
strokeWidth={2}
|
|
111
|
+
strokeOpacity={0.6}
|
|
112
|
+
/>
|
|
113
|
+
)}
|
|
114
|
+
|
|
115
|
+
{forkEdges.map((edge, i) => (
|
|
116
|
+
<path
|
|
117
|
+
key={`f-${i}`}
|
|
118
|
+
d={`M${rx(edge.fromRail)},${cy} C${rx(edge.fromRail)},${h} ${rx(edge.toRail)},${cy} ${rx(edge.toRail)},${h}`}
|
|
119
|
+
stroke={edge.color}
|
|
120
|
+
strokeWidth={2}
|
|
121
|
+
strokeOpacity={0.6}
|
|
122
|
+
fill="none"
|
|
123
|
+
/>
|
|
124
|
+
))}
|
|
125
|
+
|
|
126
|
+
{mergeEdges.map((edge, i) => {
|
|
127
|
+
const isOutgoing = edge.fromRail === row.rail;
|
|
128
|
+
const x1 = rx(edge.fromRail);
|
|
129
|
+
const x2 = rx(edge.toRail);
|
|
130
|
+
const d = isOutgoing
|
|
131
|
+
? `M${x1},${cy} C${x1},${h} ${x2},${cy} ${x2},${h}`
|
|
132
|
+
: `M${x1},${0} C${x1},${cy} ${x2},${0} ${x2},${cy}`;
|
|
133
|
+
return (
|
|
134
|
+
<path
|
|
135
|
+
key={`m-${i}`}
|
|
136
|
+
d={d}
|
|
137
|
+
stroke={edge.color}
|
|
138
|
+
strokeWidth={2}
|
|
139
|
+
strokeOpacity={0.6}
|
|
140
|
+
fill="none"
|
|
141
|
+
/>
|
|
142
|
+
);
|
|
143
|
+
})}
|
|
144
|
+
|
|
145
|
+
{endingRails.map((r) => {
|
|
146
|
+
const x = rx(r);
|
|
147
|
+
return (
|
|
148
|
+
<line
|
|
149
|
+
key={`end-${r}`}
|
|
150
|
+
x1={x}
|
|
151
|
+
y1={0}
|
|
152
|
+
x2={x}
|
|
153
|
+
y2={cy}
|
|
154
|
+
stroke={color(r)}
|
|
155
|
+
strokeWidth={2}
|
|
156
|
+
strokeOpacity={0.6}
|
|
157
|
+
/>
|
|
158
|
+
);
|
|
159
|
+
})}
|
|
160
|
+
|
|
161
|
+
<circle
|
|
162
|
+
cx={commitX}
|
|
163
|
+
cy={cy}
|
|
164
|
+
r={5}
|
|
165
|
+
fill={color(row.rail)}
|
|
166
|
+
stroke={background}
|
|
167
|
+
strokeWidth={2}
|
|
168
|
+
/>
|
|
169
|
+
</svg>
|
|
170
|
+
);
|
|
171
|
+
}
|