@djangocfg/ui-tools 2.1.407 → 2.1.409
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/README.md +9 -10
- package/dist/file-icon/index.cjs +449 -61
- package/dist/file-icon/index.cjs.map +1 -1
- package/dist/file-icon/index.d.cts +56 -18
- package/dist/file-icon/index.d.ts +56 -18
- package/dist/file-icon/index.mjs +448 -62
- package/dist/file-icon/index.mjs.map +1 -1
- package/dist/tree/index.cjs +49 -22
- package/dist/tree/index.cjs.map +1 -1
- package/dist/tree/index.d.cts +9 -3
- package/dist/tree/index.d.ts +9 -3
- package/dist/tree/index.mjs +49 -22
- package/dist/tree/index.mjs.map +1 -1
- package/dist/{types-B_zhyAqR.d.cts → types-eEu8SeiQ.d.cts} +4 -0
- package/dist/{types-B_zhyAqR.d.ts → types-eEu8SeiQ.d.ts} +4 -0
- package/package.json +8 -13
- package/src/components/FloatingToolbar/index.tsx +37 -3
- package/src/lib/page-snapshot/__tests__/capture-integration.test.ts +85 -0
- package/src/lib/page-snapshot/__tests__/engine.test.ts +36 -0
- package/src/lib/page-snapshot/__tests__/redaction-integration.test.ts +99 -0
- package/src/lib/page-snapshot/__tests__/tokens.test.ts +17 -0
- package/src/lib/page-snapshot/capture/__tests__/budget.test.ts +49 -0
- package/src/lib/page-snapshot/capture/__tests__/chrome-filter.test.ts +47 -0
- package/src/lib/page-snapshot/capture/__tests__/fold.test.ts +66 -0
- package/src/lib/page-snapshot/capture/__tests__/scope.test.ts +74 -0
- package/src/lib/page-snapshot/capture/__tests__/walk.test.ts +129 -0
- package/src/lib/page-snapshot/capture/accessible-name.ts +73 -0
- package/src/lib/page-snapshot/capture/budget.ts +95 -0
- package/src/lib/page-snapshot/capture/chrome-filter.ts +81 -0
- package/src/lib/page-snapshot/capture/classify.ts +111 -0
- package/src/lib/page-snapshot/capture/dom-utils.ts +111 -0
- package/src/lib/page-snapshot/capture/fold.ts +96 -0
- package/src/lib/page-snapshot/capture/scope.ts +169 -0
- package/src/lib/page-snapshot/capture/walk.ts +250 -0
- package/src/lib/page-snapshot/cst/__tests__/serialize.test.ts +50 -0
- package/src/lib/page-snapshot/cst/directives.ts +47 -0
- package/src/lib/page-snapshot/cst/payload.ts +50 -0
- package/src/lib/page-snapshot/cst/serialize.ts +84 -0
- package/src/lib/page-snapshot/cst/types.ts +115 -0
- package/src/lib/page-snapshot/engine.ts +176 -0
- package/src/lib/page-snapshot/index.ts +93 -0
- package/src/lib/page-snapshot/react/PageSnapshotChip.tsx +72 -0
- package/src/lib/page-snapshot/react/PageSnapshotPreview.tsx +78 -0
- package/src/lib/page-snapshot/react/__tests__/PageSnapshotChip.test.tsx +54 -0
- package/src/lib/page-snapshot/react/__tests__/provider.test.tsx +103 -0
- package/src/lib/page-snapshot/react/__tests__/use-page-snapshot-toggle.test.tsx +62 -0
- package/src/lib/page-snapshot/react/provider.tsx +162 -0
- package/src/lib/page-snapshot/react/use-page-snapshot-toggle.ts +47 -0
- package/src/lib/page-snapshot/react/use-page-snapshot.ts +67 -0
- package/src/lib/page-snapshot/redaction/__tests__/audit.test.ts +25 -0
- package/src/lib/page-snapshot/redaction/__tests__/heuristics.test.ts +73 -0
- package/src/lib/page-snapshot/redaction/__tests__/luhn.test.ts +26 -0
- package/src/lib/page-snapshot/redaction/__tests__/patterns.test.ts +60 -0
- package/src/lib/page-snapshot/redaction/audit.ts +58 -0
- package/src/lib/page-snapshot/redaction/heuristics.ts +75 -0
- package/src/lib/page-snapshot/redaction/index.ts +75 -0
- package/src/lib/page-snapshot/redaction/luhn.ts +25 -0
- package/src/lib/page-snapshot/redaction/patterns.ts +111 -0
- package/src/lib/page-snapshot/refs/__tests__/registry.test.ts +24 -0
- package/src/lib/page-snapshot/refs/registry.ts +46 -0
- package/src/lib/page-snapshot/staleness/__tests__/hash.test.ts +34 -0
- package/src/lib/page-snapshot/staleness/hash.ts +20 -0
- package/src/lib/page-snapshot/tokens.ts +15 -0
- package/src/tools/AudioPlayer/context/PlayerProvider.tsx +13 -14
- package/src/tools/AudioPlayer/hooks/useAudioElementEvents.ts +55 -6
- package/src/tools/AudioPlayer/parts/Meta/TimeDisplay.tsx +2 -5
- package/src/tools/Chat/README.md +277 -39
- package/src/tools/Chat/composer/Composer.tsx +471 -0
- package/src/tools/Chat/composer/ComposerActionBar.tsx +65 -0
- package/src/tools/Chat/composer/ComposerBanner.tsx +128 -0
- package/src/tools/Chat/composer/ComposerButton.tsx +64 -0
- package/src/tools/Chat/composer/ComposerFooter.tsx +90 -0
- package/src/tools/Chat/composer/ComposerMenuButton.tsx +62 -0
- package/src/tools/Chat/composer/ComposerModelPicker.tsx +104 -0
- package/src/tools/Chat/composer/ComposerRichTextarea.tsx +88 -0
- package/src/tools/Chat/composer/ComposerToolPill.tsx +95 -0
- package/src/tools/Chat/composer/index.ts +45 -0
- package/src/tools/Chat/composer/size-context.tsx +26 -0
- package/src/tools/Chat/composer/types.ts +143 -0
- package/src/tools/Chat/composer/useComposerActions.tsx +164 -0
- package/src/tools/Chat/context/ChatProvider.tsx +54 -3
- package/src/tools/Chat/core/__tests__/metadata.test.ts +69 -0
- package/src/tools/Chat/core/index.ts +23 -1
- package/src/tools/Chat/core/markdown.ts +1 -1
- package/src/tools/Chat/core/metadata.ts +47 -0
- package/src/tools/Chat/core/payload-dispatch.ts +1 -1
- package/src/tools/Chat/core/transport/http.ts +71 -32
- package/src/tools/Chat/core/transport/sse.ts +18 -10
- package/src/tools/Chat/highlight/HighlightOverlay.tsx +101 -0
- package/src/tools/Chat/highlight/README.md +103 -0
- package/src/tools/Chat/highlight/SpotlightCanvas.tsx +153 -0
- package/src/tools/Chat/highlight/__tests__/HighlightOverlay.test.tsx +112 -0
- package/src/tools/Chat/highlight/__tests__/resolveRef.test.ts +55 -0
- package/src/tools/Chat/highlight/index.ts +21 -0
- package/src/tools/Chat/highlight/resolveRef.ts +42 -0
- package/src/tools/Chat/highlight/types.ts +49 -0
- package/src/tools/Chat/highlight/useHighlightTargets.ts +128 -0
- package/src/tools/Chat/hooks/index.ts +0 -5
- package/src/tools/Chat/hooks/useAutoFocusOnStreamEnd.ts +28 -47
- package/src/tools/Chat/hooks/useChat.ts +47 -14
- package/src/tools/Chat/hooks/useChatComposer.ts +2 -2
- package/src/tools/Chat/hooks/useChatLayout.ts +1 -1
- package/src/tools/Chat/hooks/useStreamEndFocus.ts +54 -0
- package/src/tools/Chat/index.ts +25 -219
- package/src/tools/Chat/launcher/ChatDock.tsx +1 -1
- package/src/tools/Chat/launcher/ChatLauncher.tsx +1 -1
- package/src/tools/Chat/launcher/{ChatHeader.tsx → header/ChatHeader.tsx} +24 -11
- package/src/tools/Chat/launcher/{ChatHeaderActionButton.tsx → header/ChatHeaderActionButton.tsx} +34 -3
- package/src/tools/Chat/launcher/{ChatHeaderLanguageButton.tsx → header/ChatHeaderLanguageButton.tsx} +2 -2
- package/src/tools/Chat/launcher/{ChatHeaderModeToggle.tsx → header/ChatHeaderModeToggle.tsx} +1 -1
- package/src/tools/Chat/launcher/{ChatHeaderResetButton.tsx → header/ChatHeaderResetButton.tsx} +2 -1
- package/src/tools/Chat/launcher/{HeaderSlots.tsx → header/HeaderSlots.tsx} +3 -3
- package/src/tools/Chat/launcher/header/index.ts +26 -0
- package/src/tools/Chat/launcher/index.ts +3 -10
- package/src/tools/Chat/lazy.tsx +38 -284
- package/src/tools/Chat/{components → messages}/MessageBubble.tsx +58 -5
- package/src/tools/Chat/{components → messages}/MessageList.tsx +8 -25
- package/src/tools/Chat/messages/blocks/MessageBlocks.tsx +131 -0
- package/src/tools/Chat/messages/blocks/builtin.tsx +91 -0
- package/src/tools/Chat/messages/blocks/index.ts +12 -0
- package/src/tools/Chat/messages/blocks/registry.tsx +42 -0
- package/src/tools/Chat/messages/blocks/renderers/AudioBlock.tsx +20 -0
- package/src/tools/Chat/messages/blocks/renderers/CodeBlock.tsx +19 -0
- package/src/tools/Chat/messages/blocks/renderers/GalleryBlock.tsx +26 -0
- package/src/tools/Chat/messages/blocks/renderers/ImageBlock.tsx +27 -0
- package/src/tools/Chat/messages/blocks/renderers/JsonBlock.tsx +12 -0
- package/src/tools/Chat/messages/blocks/renderers/LottieBlock.tsx +11 -0
- package/src/tools/Chat/messages/blocks/renderers/MapBlock.tsx +36 -0
- package/src/tools/Chat/messages/blocks/renderers/MermaidBlock.tsx +11 -0
- package/src/tools/Chat/messages/blocks/renderers/VideoBlock.tsx +24 -0
- package/src/tools/Chat/messages/blocks/renderers/types.ts +8 -0
- package/src/tools/Chat/{components → messages}/index.ts +11 -5
- package/src/tools/Chat/public.ts +212 -0
- package/src/tools/Chat/shell/ChatRoot.tsx +345 -0
- package/src/tools/Chat/{components → shell}/EmptyState.tsx +4 -2
- package/src/tools/Chat/shell/index.ts +15 -0
- package/src/tools/Chat/types/block.ts +120 -0
- package/src/tools/Chat/types/config.ts +0 -5
- package/src/tools/Chat/types/index.ts +17 -0
- package/src/tools/Chat/types/message.ts +3 -0
- package/src/tools/Chat/utils/index.ts +4 -0
- package/src/tools/CodeEditor/README.md +4 -6
- package/src/tools/CodeEditor/components/DiffEditor.tsx +48 -13
- package/src/tools/CodeEditor/components/Editor.tsx +96 -44
- package/src/tools/CodeEditor/context/EditorProvider.tsx +34 -17
- package/src/tools/CodeEditor/hooks/useEditorTheme.ts +92 -99
- package/src/tools/CodeEditor/hooks/useMonaco.ts +37 -22
- package/src/tools/CodeEditor/lazy.tsx +6 -0
- package/src/tools/CodeEditor/lib/index.ts +1 -1
- package/src/tools/CodeEditor/lib/themes.ts +3 -39
- package/src/tools/CronScheduler/CronScheduler.client.tsx +230 -61
- package/src/tools/CronScheduler/components/CustomInput.tsx +21 -4
- package/src/tools/CronScheduler/components/DayChips.tsx +13 -11
- package/src/tools/CronScheduler/components/MonthDayGrid.tsx +4 -4
- package/src/tools/CronScheduler/components/SchedulePreview.tsx +7 -3
- package/src/tools/CronScheduler/components/TimeSelector.tsx +1 -1
- package/src/tools/CronScheduler/index.tsx +1 -1
- package/src/tools/CronScheduler/types/index.ts +8 -3
- package/src/tools/CronScheduler/utils/cron-humanize.ts +61 -16
- package/src/tools/CronScheduler/utils/cron-parser.ts +13 -4
- package/src/tools/FileIcon/FileIcon.tsx +24 -39
- package/src/tools/FileIcon/get-file-icon.ts +73 -0
- package/src/tools/FileIcon/icons/icon-data.ts +399 -0
- package/src/tools/FileIcon/index.ts +4 -0
- package/src/tools/FileIcon/loader.ts +17 -35
- package/src/tools/FileIcon/specialFolders.ts +18 -0
- package/src/tools/Gallery/components/lightbox/GalleryLightbox.tsx +112 -35
- package/src/tools/Gallery/components/media/GalleryVideo.tsx +21 -2
- package/src/tools/Gallery/components/preview/GalleryCarousel.tsx +11 -1
- package/src/tools/Gallery/hooks/usePreloadImages.ts +54 -7
- package/src/tools/ImageViewer/components/ImageInfo.tsx +12 -1
- package/src/tools/ImageViewer/components/ImageToolbar.tsx +51 -43
- package/src/tools/ImageViewer/components/ImageViewer.tsx +96 -24
- package/src/tools/ImageViewer/hooks/useImageLoading.ts +13 -0
- package/src/tools/ImageViewer/utils/constants.ts +3 -0
- package/src/tools/ImageViewer/utils/index.ts +1 -0
- package/src/tools/JsonForm/JsonSchemaForm.tsx +4 -1
- package/src/tools/JsonForm/templates/ArrayFieldTemplate.tsx +5 -3
- package/src/tools/JsonForm/templates/BaseInputTemplate.tsx +7 -4
- package/src/tools/JsonForm/templates/ErrorListTemplate.tsx +3 -1
- package/src/tools/JsonForm/templates/ObjectFieldTemplate.tsx +23 -3
- package/src/tools/JsonForm/widgets/ColorWidget.tsx +20 -12
- package/src/tools/JsonForm/widgets/NumberWidget.tsx +14 -9
- package/src/tools/JsonForm/widgets/RadioWidget.tsx +78 -0
- package/src/tools/JsonForm/widgets/SelectWidget.tsx +1 -0
- package/src/tools/JsonForm/widgets/SliderWidget.tsx +7 -4
- package/src/tools/JsonForm/widgets/TextWidget.tsx +41 -17
- package/src/tools/JsonForm/widgets/index.ts +1 -0
- package/src/tools/JsonTree/components/JsonContent.tsx +115 -40
- package/src/tools/LottiePlayer/LottiePlayer.client.tsx +177 -72
- package/src/tools/LottiePlayer/index.tsx +14 -4
- package/src/tools/LottiePlayer/lazy.tsx +11 -3
- package/src/tools/LottiePlayer/types.ts +31 -1
- package/src/tools/LottiePlayer/useLottie.ts +32 -9
- package/src/tools/LottiePlayer/usePrefersReducedMotion.ts +46 -0
- package/src/tools/Map/components/LayerSwitcher.tsx +54 -21
- package/src/tools/Map/components/MapCluster.tsx +28 -21
- package/src/tools/Map/components/MapContainer.tsx +11 -4
- package/src/tools/Map/components/MapLegend.tsx +46 -15
- package/src/tools/Map/components/MapMarker.tsx +31 -2
- package/src/tools/Map/hooks/useMapEvents.ts +64 -105
- package/src/tools/MarkdownEditor/MarkdownEditor.tsx +61 -6
- package/src/tools/MarkdownEditor/MentionList.tsx +37 -4
- package/src/tools/MarkdownEditor/createMentionSuggestion.ts +11 -0
- package/src/tools/MarkdownEditor/lazy.tsx +32 -7
- package/src/tools/MarkdownEditor/styles.css +13 -0
- package/src/tools/MarkdownMessage/CodeBlock.tsx +40 -17
- package/src/tools/MarkdownMessage/MarkdownMessage.tsx +26 -6
- package/src/tools/MarkdownMessage/components.tsx +22 -9
- package/src/tools/MarkdownMessage/types.ts +24 -1
- package/src/tools/Mermaid/Mermaid.client.tsx +27 -5
- package/src/tools/Mermaid/components/MermaidErrorPanel.tsx +31 -0
- package/src/tools/Mermaid/components/MermaidFullscreenModal.tsx +14 -17
- package/src/tools/Mermaid/hooks/useMermaidRenderer.ts +264 -168
- package/src/tools/Mermaid/hooks/useMermaidValidation.ts +76 -10
- package/src/tools/Mermaid/index.tsx +6 -0
- package/src/tools/Mermaid/utils/mermaid-helpers.ts +141 -18
- package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/SchemaFields/FieldRow.tsx +11 -1
- package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/SchemaFields/buildTree.ts +49 -20
- package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/index.tsx +7 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/grouping.ts +7 -4
- package/src/tools/OpenapiViewer/constants.ts +3 -0
- package/src/tools/OpenapiViewer/hooks/useOpenApiSchema.ts +73 -11
- package/src/tools/OpenapiViewer/utils/schemaExport.ts +26 -6
- package/src/tools/PrettyCode/PrettyCode.client.tsx +23 -16
- package/src/tools/PrettyCode/lazy.tsx +1 -1
- package/src/tools/SpeechRecognition/README.md +1 -1
- package/src/tools/SpeechRecognition/__tests__/language.test.ts +9 -3
- package/src/tools/SpeechRecognition/components/RecordingPulse.tsx +59 -0
- package/src/tools/SpeechRecognition/components/index.ts +2 -0
- package/src/tools/SpeechRecognition/core/engine/external.ts +24 -7
- package/src/tools/SpeechRecognition/core/language.ts +23 -6
- package/src/tools/SpeechRecognition/hooks/usePushToTalk.ts +36 -5
- package/src/tools/SpeechRecognition/hooks/useSpeechRecognition.ts +18 -11
- package/src/tools/SpeechRecognition/widgets/VoiceComposerSlot.tsx +94 -26
- package/src/tools/SpeechRecognition/widgets/index.ts +1 -1
- package/src/tools/Tree/README.md +4 -8
- package/src/tools/Tree/TreeRoot.tsx +22 -10
- package/src/tools/Tree/components/TreeContent.tsx +24 -4
- package/src/tools/Tree/components/TreeLabel.tsx +8 -2
- package/src/tools/Tree/components/TreeRow.tsx +16 -6
- package/src/tools/Tree/data/flatten.ts +10 -4
- package/src/tools/Tree/types.ts +4 -0
- package/src/tools/Uploader/components/UploadAddButton.tsx +29 -6
- package/src/tools/Uploader/components/UploadDropzone.tsx +63 -7
- package/src/tools/Uploader/components/UploadPageDropOverlay.tsx +19 -5
- package/src/tools/Uploader/components/UploadPreviewItem.tsx +47 -17
- package/src/tools/Uploader/components/UploadPreviewList.tsx +24 -12
- package/src/tools/Uploader/utils/formatters.ts +8 -3
- package/src/tools/VideoPlayer/canvas/hls-canvas.tsx +1 -0
- package/src/tools/VideoPlayer/canvas/{jsx.d.ts → jsx-augmentation.ts} +12 -19
- package/src/tools/VideoPlayer/canvas/vimeo-canvas.tsx +1 -0
- package/src/tools/VideoPlayer/canvas/youtube-canvas.tsx +1 -0
- package/src/tools/VideoPlayer/parts/fullscreen.tsx +1 -1
- package/src/tools/VideoPlayer/parts/pip.tsx +1 -1
- package/src/tools/VideoPlayer/parts/playback-rate.tsx +1 -1
- package/src/tools/VideoPlayer/parts/seek-bar.tsx +2 -2
- package/src/tools/VideoPlayer/parts/volume.tsx +2 -2
- package/src/tools/index.ts +2 -1
- package/src/tools/Chat/components/AudioToggle.tsx +0 -78
- package/src/tools/Chat/components/ChatRoot.tsx +0 -305
- package/src/tools/Chat/components/Composer.tsx +0 -216
- package/src/tools/Chat/hooks/useChatScroll.ts +0 -145
- package/src/tools/Chat/types.ts +0 -9
- package/src/tools/JsonTree/components/JsonToolbar.tsx +0 -95
- package/src/tools/JsonTree/hooks/useElementCorner.ts +0 -84
- package/src/tools/JsonTree/hooks/useNavbarHeight.ts +0 -83
- package/src/tools/OpenapiViewer/components/DocsLayout/schemaFields.ts +0 -121
- package/src/tools/Tour/README.md +0 -373
- package/src/tools/Tour/components/Tour.tsx +0 -12
- package/src/tools/Tour/components/TourContent.tsx +0 -171
- package/src/tools/Tour/components/TourNavigation.tsx +0 -77
- package/src/tools/Tour/components/TourProgress.tsx +0 -88
- package/src/tools/Tour/components/TourSpotlight.tsx +0 -199
- package/src/tools/Tour/components/index.ts +0 -5
- package/src/tools/Tour/context/TourContext.ts +0 -19
- package/src/tools/Tour/context/TourProvider.tsx +0 -292
- package/src/tools/Tour/context/index.ts +0 -2
- package/src/tools/Tour/hooks/index.ts +0 -3
- package/src/tools/Tour/hooks/useKeyboardNavigation.ts +0 -59
- package/src/tools/Tour/hooks/useStepTarget.ts +0 -121
- package/src/tools/Tour/hooks/useTour.ts +0 -42
- package/src/tools/Tour/index.ts +0 -38
- package/src/tools/Tour/types/index.ts +0 -224
- package/src/tools/Tour/utils/dom.ts +0 -98
- package/src/tools/Tour/utils/index.ts +0 -3
- package/src/tools/Tour/utils/logger.ts +0 -3
- package/src/tools/Tour/utils/scrollIntoView.ts +0 -24
- /package/src/tools/Chat/{config.ts → constants.ts} +0 -0
- /package/src/tools/Chat/launcher/{ChatHeaderAudioToggle.tsx → header/ChatHeaderAudioToggle.tsx} +0 -0
- /package/src/tools/Chat/{components → messages}/Attachments.tsx +0 -0
- /package/src/tools/Chat/{components → messages}/JumpToLatest.tsx +0 -0
- /package/src/tools/Chat/{components → messages}/MessageActions.tsx +0 -0
- /package/src/tools/Chat/{components → messages}/Sources.tsx +0 -0
- /package/src/tools/Chat/{components → messages}/StreamingIndicator.tsx +0 -0
- /package/src/tools/Chat/{components → messages}/ToolCalls.tsx +0 -0
- /package/src/tools/Chat/{components → shell}/ErrorBanner.tsx +0 -0
|
@@ -19,6 +19,20 @@ import { createMarkdownComponents } from './components';
|
|
|
19
19
|
import { CollapseToggle } from './CollapseToggle';
|
|
20
20
|
import { applyPreprocess, buildLinkRulesComponent, collectProtocols } from './linkRules';
|
|
21
21
|
|
|
22
|
+
/** Body text size class for the plain-text / prose wrapper. */
|
|
23
|
+
const SIZE_TO_TEXT: Record<'xs' | 'sm' | 'base', string> = {
|
|
24
|
+
xs: 'text-xs',
|
|
25
|
+
sm: 'text-sm',
|
|
26
|
+
base: 'text-base',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** Tailwind-typography modifier per size level. */
|
|
30
|
+
const SIZE_TO_PROSE: Record<'xs' | 'sm' | 'base', string> = {
|
|
31
|
+
xs: 'prose-xs',
|
|
32
|
+
sm: 'prose-sm',
|
|
33
|
+
base: 'prose-base',
|
|
34
|
+
};
|
|
35
|
+
|
|
22
36
|
/**
|
|
23
37
|
* MarkdownMessage — chat-tuned markdown renderer.
|
|
24
38
|
*
|
|
@@ -51,7 +65,7 @@ import { applyPreprocess, buildLinkRulesComponent, collectProtocols } from './li
|
|
|
51
65
|
* ```
|
|
52
66
|
*
|
|
53
67
|
* Memoised: re-renders only when props change. `content` is the main
|
|
54
|
-
* trigger — all other props (className, isUser,
|
|
68
|
+
* trigger — all other props (className, isUser, size, etc.) are
|
|
55
69
|
* compared by value/reference. `onCollapseChange` is compared by
|
|
56
70
|
* reference — callers should stabilise it with useCallback.
|
|
57
71
|
*/
|
|
@@ -59,6 +73,7 @@ function MarkdownMessageRaw({
|
|
|
59
73
|
content,
|
|
60
74
|
className = '',
|
|
61
75
|
isUser = false,
|
|
76
|
+
size,
|
|
62
77
|
isCompact = false,
|
|
63
78
|
plainText,
|
|
64
79
|
customComponents,
|
|
@@ -71,6 +86,7 @@ function MarkdownMessageRaw({
|
|
|
71
86
|
showLessLabel = 'Show less',
|
|
72
87
|
defaultExpanded = false,
|
|
73
88
|
onCollapseChange,
|
|
89
|
+
codeTheme = 'dark',
|
|
74
90
|
}: MarkdownMessageProps) {
|
|
75
91
|
// Pre-process content through any rules that requested it. Done
|
|
76
92
|
// before trim so a rule can rewrite multi-line shapes too.
|
|
@@ -117,10 +133,14 @@ function MarkdownMessageRaw({
|
|
|
117
133
|
}
|
|
118
134
|
}, [isCollapsed, collapsible, shouldCollapse, onCollapseChange]);
|
|
119
135
|
|
|
136
|
+
// `size` wins when set explicitly; otherwise fall back to the
|
|
137
|
+
// legacy binary `isCompact` so existing callers keep working.
|
|
138
|
+
const resolvedSize: 'xs' | 'sm' | 'base' = size ?? (isCompact ? 'xs' : 'sm');
|
|
139
|
+
|
|
120
140
|
const components = React.useMemo(() => {
|
|
121
|
-
const base = createMarkdownComponents(isUser,
|
|
141
|
+
const base = createMarkdownComponents(isUser, resolvedSize, codeTheme);
|
|
122
142
|
return effectiveCustomComponents ? { ...base, ...effectiveCustomComponents } : base;
|
|
123
|
-
}, [isUser,
|
|
143
|
+
}, [isUser, resolvedSize, codeTheme, effectiveCustomComponents]);
|
|
124
144
|
|
|
125
145
|
const schema = React.useMemo(() => buildSchema(effectiveProtocols), [effectiveProtocols]);
|
|
126
146
|
const urlTransform = React.useMemo(
|
|
@@ -128,8 +148,8 @@ function MarkdownMessageRaw({
|
|
|
128
148
|
[effectiveProtocols],
|
|
129
149
|
);
|
|
130
150
|
|
|
131
|
-
const textSizeClass =
|
|
132
|
-
const proseClass =
|
|
151
|
+
const textSizeClass = SIZE_TO_TEXT[resolvedSize];
|
|
152
|
+
const proseClass = SIZE_TO_PROSE[resolvedSize];
|
|
133
153
|
|
|
134
154
|
// Resolve plain-vs-markdown branch:
|
|
135
155
|
// 1. Caller-passed `plainText` wins outright (explicit beats clever).
|
|
@@ -170,7 +190,7 @@ function MarkdownMessageRaw({
|
|
|
170
190
|
readMoreLabel={readMoreLabel}
|
|
171
191
|
showLessLabel={showLessLabel}
|
|
172
192
|
isUser={isUser}
|
|
173
|
-
isCompact={
|
|
193
|
+
isCompact={resolvedSize === 'xs'}
|
|
174
194
|
/>
|
|
175
195
|
</>
|
|
176
196
|
)}
|
|
@@ -5,20 +5,33 @@ import { ANCHOR } from '../Chat/styles/bubbleTokens';
|
|
|
5
5
|
import { CodeBlock, CodeBlockFallback } from './CodeBlock';
|
|
6
6
|
import { extractTextFromChildren } from './plainText';
|
|
7
7
|
|
|
8
|
+
/** Body / heading size classes per `size` level. */
|
|
9
|
+
const SIZE_CLASSES: Record<'xs' | 'sm' | 'base', {
|
|
10
|
+
text: string;
|
|
11
|
+
headingBase: string;
|
|
12
|
+
headingSm: string;
|
|
13
|
+
}> = {
|
|
14
|
+
xs: { text: 'text-xs', headingBase: 'text-sm', headingSm: 'text-xs' },
|
|
15
|
+
sm: { text: 'text-sm', headingBase: 'text-base', headingSm: 'text-sm' },
|
|
16
|
+
base: { text: 'text-base', headingBase: 'text-lg', headingSm: 'text-base' },
|
|
17
|
+
};
|
|
18
|
+
|
|
8
19
|
/**
|
|
9
20
|
* Build the chat-tuned markdown component map.
|
|
10
21
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
22
|
+
* Body text size follows `size` (xs/sm/base → 12/14/16px). Heading
|
|
23
|
+
* sizes are scaled a notch above the body so inline-in-chat headings
|
|
24
|
+
* stand out without dominating.
|
|
14
25
|
*/
|
|
15
26
|
export function createMarkdownComponents(
|
|
16
27
|
isUser: boolean = false,
|
|
17
|
-
|
|
28
|
+
size: 'xs' | 'sm' | 'base' = 'sm',
|
|
29
|
+
codeTheme: 'dark' | 'light' = 'dark',
|
|
18
30
|
): Components {
|
|
19
|
-
const textSize
|
|
20
|
-
|
|
21
|
-
|
|
31
|
+
const { text: textSize, headingBase, headingSm } = SIZE_CLASSES[size];
|
|
32
|
+
// Code blocks / diagrams only have a binary compact mode — treat the
|
|
33
|
+
// smallest text level as compact, larger ones as roomy.
|
|
34
|
+
const isCompact = size === 'xs';
|
|
22
35
|
|
|
23
36
|
return {
|
|
24
37
|
h1: ({ children }) => (
|
|
@@ -115,11 +128,11 @@ export function createMarkdownComponents(
|
|
|
115
128
|
}
|
|
116
129
|
|
|
117
130
|
try {
|
|
118
|
-
return <CodeBlock code={codeContent} language={language} isUser={isUser} isCompact={isCompact} />;
|
|
131
|
+
return <CodeBlock code={codeContent} language={language} isUser={isUser} isCompact={isCompact} codeTheme={codeTheme} />;
|
|
119
132
|
} catch (error) {
|
|
120
133
|
// eslint-disable-next-line no-console
|
|
121
134
|
console.warn('CodeBlock failed, using fallback:', error);
|
|
122
|
-
return <CodeBlockFallback code={codeContent} language={language} isUser={isUser} isCompact={isCompact} />;
|
|
135
|
+
return <CodeBlockFallback code={codeContent} language={language} isUser={isUser} isCompact={isCompact} codeTheme={codeTheme} />;
|
|
123
136
|
}
|
|
124
137
|
},
|
|
125
138
|
|
|
@@ -50,7 +50,24 @@ export interface MarkdownMessageProps {
|
|
|
50
50
|
className?: string;
|
|
51
51
|
/** Whether the message is from the user (affects styling) */
|
|
52
52
|
isUser?: boolean;
|
|
53
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* Body text size — drives `<p>/<li>/<table>` etc. and scales
|
|
55
|
+
* headings a notch above the body.
|
|
56
|
+
*
|
|
57
|
+
* - `xs` — text-xs (12px), dense
|
|
58
|
+
* - `sm` — text-sm (14px), default
|
|
59
|
+
* - `base` — text-base (16px), large / `appearance="full"` chats
|
|
60
|
+
*
|
|
61
|
+
* When set, `size` wins over `isCompact`.
|
|
62
|
+
* @default 'sm'
|
|
63
|
+
*/
|
|
64
|
+
size?: 'xs' | 'sm' | 'base';
|
|
65
|
+
/**
|
|
66
|
+
* Use compact size (text-xs instead of text-sm).
|
|
67
|
+
* @deprecated Use `size` instead — `isCompact` maps to
|
|
68
|
+
* `size="xs"` (true) / `size="sm"` (false) and is ignored when
|
|
69
|
+
* `size` is set explicitly.
|
|
70
|
+
*/
|
|
54
71
|
isCompact?: boolean;
|
|
55
72
|
/**
|
|
56
73
|
* Force the plain-text rendering path (single `<div>` with
|
|
@@ -114,4 +131,10 @@ export interface MarkdownMessageProps {
|
|
|
114
131
|
defaultExpanded?: boolean;
|
|
115
132
|
/** Callback when collapsed state changes */
|
|
116
133
|
onCollapseChange?: (isCollapsed: boolean) => void;
|
|
134
|
+
/**
|
|
135
|
+
* Code-fence surface palette. @default 'dark' — syntax highlighting
|
|
136
|
+
* ships its own contrast model and reads washed out on a light
|
|
137
|
+
* surface. Pass `'light'` to opt into a light code surface.
|
|
138
|
+
*/
|
|
139
|
+
codeTheme?: 'dark' | 'light';
|
|
117
140
|
}
|
|
@@ -5,6 +5,7 @@ import React, { useRef } from 'react';
|
|
|
5
5
|
import { useResolvedTheme } from '@djangocfg/ui-core/hooks';
|
|
6
6
|
import { FloatingToolbar } from '../../components/FloatingToolbar';
|
|
7
7
|
import { CopyAction, FullscreenAction } from '../../components/FloatingToolbar/actions';
|
|
8
|
+
import { MermaidErrorPanel } from './components/MermaidErrorPanel';
|
|
8
9
|
import { MermaidFullscreenModal } from './components/MermaidFullscreenModal';
|
|
9
10
|
import { useMermaidFullscreen } from './hooks/useMermaidFullscreen';
|
|
10
11
|
import { useMermaidRenderer } from './hooks/useMermaidRenderer';
|
|
@@ -23,6 +24,12 @@ interface MermaidProps {
|
|
|
23
24
|
* they have a reason to.
|
|
24
25
|
*/
|
|
25
26
|
scrollIsolation?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Debounce window (ms) before (re)rendering after `chart` changes.
|
|
29
|
+
* Lower values feel snappier for static charts; higher values
|
|
30
|
+
* reduce churn while a diagram is streamed in. Default 300.
|
|
31
|
+
*/
|
|
32
|
+
debounceMs?: number;
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
const Mermaid: React.FC<MermaidProps> = ({
|
|
@@ -31,15 +38,17 @@ const Mermaid: React.FC<MermaidProps> = ({
|
|
|
31
38
|
isCompact = false,
|
|
32
39
|
fullscreen = true,
|
|
33
40
|
scrollIsolation = false,
|
|
41
|
+
debounceMs = 300,
|
|
34
42
|
}) => {
|
|
35
43
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
36
44
|
const theme = useResolvedTheme();
|
|
37
45
|
|
|
38
46
|
// Rendering logic
|
|
39
|
-
const { mermaidRef, svgContent, isVertical, isRendering } = useMermaidRenderer({
|
|
47
|
+
const { mermaidRef, svgContent, isVertical, isRendering, error } = useMermaidRenderer({
|
|
40
48
|
chart,
|
|
41
49
|
theme,
|
|
42
50
|
isCompact,
|
|
51
|
+
debounceMs,
|
|
43
52
|
});
|
|
44
53
|
|
|
45
54
|
// Fullscreen modal logic (only used if fullscreen prop is true)
|
|
@@ -51,22 +60,35 @@ const Mermaid: React.FC<MermaidProps> = ({
|
|
|
51
60
|
handleBackdropClick,
|
|
52
61
|
} = useMermaidFullscreen();
|
|
53
62
|
|
|
63
|
+
// Hoist derived UI state out of JSX (data-before-JSX).
|
|
64
|
+
const hasError = error !== null;
|
|
65
|
+
// The spinner needs a box to sit in while the first diagram renders
|
|
66
|
+
// (empty SVG host has no intrinsic height).
|
|
67
|
+
const showPlaceholderHeight = isRendering && !svgContent && !hasError;
|
|
68
|
+
const showToolbar = !!svgContent && !isRendering && !hasError;
|
|
54
69
|
|
|
55
70
|
return (
|
|
56
71
|
<>
|
|
57
72
|
<div ref={containerRef} className={`relative ${className}`}>
|
|
73
|
+
{hasError && <MermaidErrorPanel message={error} />}
|
|
74
|
+
|
|
58
75
|
<div
|
|
59
76
|
ref={mermaidRef}
|
|
60
77
|
className="flex justify-center items-center"
|
|
61
|
-
style={{
|
|
78
|
+
style={{
|
|
79
|
+
isolation: 'isolate',
|
|
80
|
+
minHeight: showPlaceholderHeight ? 100 : undefined,
|
|
81
|
+
display: hasError ? 'none' : undefined,
|
|
82
|
+
}}
|
|
62
83
|
/>
|
|
63
|
-
|
|
64
|
-
|
|
84
|
+
|
|
85
|
+
{isRendering && !hasError && (
|
|
86
|
+
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
|
|
65
87
|
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-primary" />
|
|
66
88
|
</div>
|
|
67
89
|
)}
|
|
68
90
|
|
|
69
|
-
{
|
|
91
|
+
{showToolbar && (
|
|
70
92
|
<FloatingToolbar containerRef={containerRef} scrollIsolation={scrollIsolation}>
|
|
71
93
|
<CopyAction value={chart} title="Copy source" />
|
|
72
94
|
{fullscreen && (
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { AlertTriangle } from 'lucide-react';
|
|
5
|
+
|
|
6
|
+
interface MermaidErrorPanelProps {
|
|
7
|
+
/** Human-readable error message from the Mermaid parser. */
|
|
8
|
+
message: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Inline error panel shown when a Mermaid diagram fails to parse.
|
|
13
|
+
*
|
|
14
|
+
* Replaces the previous `innerHTML`-injected markup — keeps rendering in
|
|
15
|
+
* React, uses semantic `destructive` tokens, and stays accessible
|
|
16
|
+
* (`role="alert"`).
|
|
17
|
+
*/
|
|
18
|
+
export const MermaidErrorPanel: React.FC<MermaidErrorPanelProps> = ({ message }) => {
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
role="alert"
|
|
22
|
+
className="flex items-start gap-3 rounded-md border border-destructive/30 bg-destructive/10 p-4 text-destructive"
|
|
23
|
+
>
|
|
24
|
+
<AlertTriangle className="mt-0.5 h-4 w-4 shrink-0" aria-hidden="true" />
|
|
25
|
+
<div className="min-w-0">
|
|
26
|
+
<p className="text-sm font-semibold">Diagram syntax error</p>
|
|
27
|
+
<p className="mt-0.5 break-words text-sm text-destructive/90">{message}</p>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
@@ -6,14 +6,20 @@ import { X, ZoomIn, ZoomOut, RotateCcw } from 'lucide-react';
|
|
|
6
6
|
import { TransformWrapper, TransformComponent, useControls } from 'react-zoom-pan-pinch';
|
|
7
7
|
|
|
8
8
|
import { Button } from '@djangocfg/ui-core/components';
|
|
9
|
-
import { applyMermaidTextColors } from '../utils/mermaid-helpers';
|
|
9
|
+
import { applyMermaidTextColors, getTextColor } from '../utils/mermaid-helpers';
|
|
10
10
|
|
|
11
11
|
interface MermaidFullscreenModalProps {
|
|
12
12
|
isOpen: boolean;
|
|
13
13
|
svgContent: string;
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Whether the source diagram is vertical. Kept for API compatibility
|
|
16
|
+
* with callers; the modal now auto-fits via measured bbox so it no
|
|
17
|
+
* longer needs an orientation hint.
|
|
18
|
+
*/
|
|
19
|
+
isVertical?: boolean;
|
|
15
20
|
theme: string;
|
|
16
|
-
|
|
21
|
+
/** Diagram source. Reserved for future modal actions (copy/export). */
|
|
22
|
+
chart?: string;
|
|
17
23
|
fullscreenRef: React.RefObject<HTMLDivElement | null>;
|
|
18
24
|
onClose: () => void;
|
|
19
25
|
onBackdropClick: (e: React.MouseEvent) => void;
|
|
@@ -41,7 +47,6 @@ function ZoomControls() {
|
|
|
41
47
|
export const MermaidFullscreenModal: React.FC<MermaidFullscreenModalProps> = ({
|
|
42
48
|
isOpen,
|
|
43
49
|
svgContent,
|
|
44
|
-
isVertical,
|
|
45
50
|
theme,
|
|
46
51
|
fullscreenRef,
|
|
47
52
|
onClose,
|
|
@@ -99,22 +104,14 @@ export const MermaidFullscreenModal: React.FC<MermaidFullscreenModalProps> = ({
|
|
|
99
104
|
};
|
|
100
105
|
}, [isOpen, svgContent, fullscreenRef]);
|
|
101
106
|
|
|
102
|
-
//
|
|
107
|
+
// Re-assert theme text colors on the fullscreen SVG. The shared
|
|
108
|
+
// `getTextColor` reads the (already fully-wrapped) `--foreground`
|
|
109
|
+
// token — it never double-wraps `hsl(...)`.
|
|
103
110
|
useEffect(() => {
|
|
104
111
|
if (isOpen && fullscreenRef.current) {
|
|
105
|
-
|
|
106
|
-
if (typeof document === 'undefined') return '';
|
|
107
|
-
const value = getComputedStyle(document.documentElement).getPropertyValue(variable).trim();
|
|
108
|
-
return value ? `hsl(${value})` : '';
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const textColor = theme === 'dark'
|
|
112
|
-
? getCSSVariable('--foreground') || 'hsl(0 0% 90%)'
|
|
113
|
-
: getCSSVariable('--foreground') || 'hsl(222.2 84% 4.9%)';
|
|
114
|
-
|
|
115
|
-
applyMermaidTextColors(fullscreenRef.current, textColor);
|
|
112
|
+
applyMermaidTextColors(fullscreenRef.current, getTextColor(theme));
|
|
116
113
|
}
|
|
117
|
-
}, [isOpen, theme,
|
|
114
|
+
}, [isOpen, theme, fullscreenRef, svgContent]);
|
|
118
115
|
|
|
119
116
|
// Handle escape key
|
|
120
117
|
useEffect(() => {
|