@djangocfg/ui-tools 2.1.404 → 2.1.408
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 -11
- 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 +13 -16
- 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/lazy.tsx +13 -27
- package/src/tools/AudioPlayer/parts/Meta/TimeDisplay.tsx +2 -5
- package/src/tools/Chat/README.md +267 -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 +326 -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 +106 -26
- 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/README.md +87 -230
- package/src/tools/VideoPlayer/VideoPlayer.tsx +82 -0
- package/src/tools/VideoPlayer/canvas/canvas-dispatcher.tsx +34 -0
- package/src/tools/VideoPlayer/canvas/hls-canvas.tsx +39 -0
- package/src/tools/VideoPlayer/canvas/iframe-canvas.tsx +33 -0
- package/src/tools/VideoPlayer/canvas/index.ts +12 -0
- package/src/tools/VideoPlayer/canvas/jsx-augmentation.ts +47 -0
- package/src/tools/VideoPlayer/canvas/native-canvas.tsx +38 -0
- package/src/tools/VideoPlayer/canvas/vimeo-canvas.tsx +40 -0
- package/src/tools/VideoPlayer/canvas/youtube-canvas.tsx +78 -0
- package/src/tools/VideoPlayer/index.ts +51 -65
- package/src/tools/VideoPlayer/lazy.tsx +11 -54
- package/src/tools/VideoPlayer/parts/controls-bar.tsx +35 -0
- package/src/tools/VideoPlayer/parts/fullscreen.tsx +19 -0
- package/src/tools/VideoPlayer/parts/index.ts +15 -0
- package/src/tools/VideoPlayer/parts/pip.tsx +19 -0
- package/src/tools/VideoPlayer/parts/play-button.tsx +19 -0
- package/src/tools/VideoPlayer/parts/playback-rate.tsx +31 -0
- package/src/tools/VideoPlayer/parts/poster.tsx +3 -0
- package/src/tools/VideoPlayer/parts/seek-bar.tsx +26 -0
- package/src/tools/VideoPlayer/parts/volume.tsx +32 -0
- package/src/tools/VideoPlayer/styles/video-player.css +141 -0
- package/src/tools/VideoPlayer/types.ts +82 -0
- package/src/tools/VideoPlayer/utils/parse-embed-url.ts +70 -0
- package/src/tools/VideoPlayer/utils/vimeo-id.ts +24 -0
- package/src/tools/VideoPlayer/utils/youtube-id.ts +64 -0
- package/src/tools/index.ts +37 -29
- 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/VideoPlayer/components/VideoControls.tsx +0 -138
- package/src/tools/VideoPlayer/components/VideoErrorFallback.tsx +0 -172
- package/src/tools/VideoPlayer/components/VideoPlayer.tsx +0 -201
- package/src/tools/VideoPlayer/components/index.ts +0 -14
- package/src/tools/VideoPlayer/context/VideoPlayerContext.tsx +0 -52
- package/src/tools/VideoPlayer/context/index.ts +0 -8
- package/src/tools/VideoPlayer/hooks/index.ts +0 -12
- package/src/tools/VideoPlayer/hooks/useVideoPlayerSettings.ts +0 -71
- package/src/tools/VideoPlayer/hooks/useVideoPositionCache.ts +0 -117
- package/src/tools/VideoPlayer/providers/NativeProvider.tsx +0 -284
- package/src/tools/VideoPlayer/providers/StreamProvider.tsx +0 -505
- package/src/tools/VideoPlayer/providers/VidstackProvider.tsx +0 -397
- package/src/tools/VideoPlayer/providers/index.ts +0 -8
- package/src/tools/VideoPlayer/types/index.ts +0 -38
- package/src/tools/VideoPlayer/types/player.ts +0 -116
- package/src/tools/VideoPlayer/types/provider.ts +0 -93
- package/src/tools/VideoPlayer/types/sources.ts +0 -97
- package/src/tools/VideoPlayer/utils/debug.ts +0 -14
- package/src/tools/VideoPlayer/utils/fileSource.ts +0 -78
- package/src/tools/VideoPlayer/utils/index.ts +0 -12
- package/src/tools/VideoPlayer/utils/resolvers.ts +0 -75
- /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
package/src/tools/Chat/README.md
CHANGED
|
@@ -51,11 +51,11 @@ export function MyChat() {
|
|
|
51
51
|
- **Rich attachments.** `AttachmentsGrid` for thumbnails, `AttachmentsList` for custom renderers; `onAttachmentOpen` for lightbox.
|
|
52
52
|
- **Tool-payload dispatcher.** `dispatchToolPayload(matchers, fallback)` — pluggable predicates render `<LazyJsonTree>` / `<LazyMap>` / etc.
|
|
53
53
|
- **Persisted dock prefs.** `headerSlots.modeToggle.persistAs: 'my.key'` stores `mode` / `side` / `width` in localStorage; the toggle lets users flip popover ↔ side and survives reloads. (`useChatDockPrefs()` is now owned by the launcher internally — no longer a consumer-facing hook.)
|
|
54
|
-
- **UX guards.** Auto-focus composer on dock open, two-step Escape (textarea blur → close), click-to-focus on empty message area (Slack / Linear style), `useHotkey('mod+/')` toggle.
|
|
54
|
+
- **UX guards.** Auto-focus composer on dock open, two-step Escape (textarea blur → close), click-to-focus on empty message area **and** on the composer surface padding (Slack / Linear / ChatGPT style), `useHotkey('mod+/')` toggle.
|
|
55
55
|
- **ChatGPT-style autoscroll.** `MessageList` follows the bottom while the user is within `atBottomThreshold` px (default 120). Every user-sent message bumps `scrollAnchorId` and re-anchors the viewport with `behavior: 'smooth'` — sending no longer leaves your own bubble stuck above the fold. Scrolling up by hand breaks the lock; `<JumpToLatest>` brings it back.
|
|
56
|
-
- **Voice composer slot.** `<VoiceComposerSlot />` drops into `
|
|
56
|
+
- **Voice composer slot.** `<VoiceComposerSlot />` drops into `composer.slots.blockStart` with **zero props** — reads/writes the composer through the `ComposerHandle` registered in chat context. The built-in `<Composer>` and TipTap-backed `MarkdownEditor` register themselves automatically; custom composers wire it via `useRegisterComposer({ focus, moveCursorToEnd, getValue, setValue })`. Auto-gates on Firefox / in-app WebViews / missing `getUserMedia`, preserves typed prefix, 90-second countdown, silence auto-stop, Esc / Enter hotkeys, start / stop earcons. See [`SpeechRecognition`](../SpeechRecognition/README.md).
|
|
57
57
|
- **Language flag button.** `headerSlots.languagePicker: true` slots a 28×28 country flag into the dock header — opens a searchable `<Combobox>` with 66 BCP-47 tags from the Chrome Web Speech catalogue. Selection persists via `useSpeechPrefs`, picked up by every `useSpeechRecognition` downstream. (Raw `<ChatHeaderLanguageButton>` still exported for custom shells.)
|
|
58
|
-
- **Auto-focus on stream end.**
|
|
58
|
+
- **Auto-focus on stream end.** `<ChatProvider>` re-focuses the registered composer on the streaming → idle edge — type → send → read → keep typing without reaching for the mouse. Works for **every** usage pattern (`ChatRoot`, hand-rolled `ChatProvider` + `Composer`, headless), not just `ChatRoot`. Opt out with `<ChatProvider autoFocusOnStreamEnd={false}>`. The standalone `useAutoFocusOnStreamEnd()` hook is still exported for advanced cases (focus a non-composer target, drive `isStreaming` from your own store).
|
|
59
59
|
- **Centralized colors.** Role-aware className tokens (`BUBBLE_SURFACE` / `ANCHOR` / `TOGGLE` / `DESTRUCTIVE_SURFACE`) + hooks (`useChatBubbleStyles`, `useChatRoleStyles`, `useChatDestructiveStyles`).
|
|
60
60
|
- **Responsive.** FAB `size='responsive'` (default): phone → `sm`, tablet → `md`, desktop → `lg`. Side mode is desktop-only and falls back to popover below `lg`.
|
|
61
61
|
- **Mobile fullscreen.** Dock auto-fills viewport below 768px via `useIsMobile`. Heights use `dvh/svh/lvh` so iOS Safari URL bar doesn't clip the chat.
|
|
@@ -68,7 +68,7 @@ Transport (interface) ← Pydantic-AI / HTTP+SSE / Wails / mock
|
|
|
68
68
|
↓
|
|
69
69
|
Reducer (pure state machine)
|
|
70
70
|
↓
|
|
71
|
-
Hooks (useChat / useChatComposer /
|
|
71
|
+
Hooks (useChat / useChatComposer / useChatHistory / useChatLayout)
|
|
72
72
|
↓
|
|
73
73
|
ChatProvider (context)
|
|
74
74
|
↓
|
|
@@ -79,18 +79,25 @@ ChatRoot (one-line preset) ◄── optionally wrapped by ──► ChatLau
|
|
|
79
79
|
|
|
80
80
|
`ChatLauncher` mounts the `ChatProvider` itself — pass `transport` / `config` / `audio` / `initialSessionId` / `autoCreateSession` / `streaming` / `debug` to the launcher and use `<ChatRoot />` without props as the child. `ChatRoot` detects the ambient provider and reuses it; standalone `<ChatRoot transport={…}>` still works for non-launcher embeds. This is what makes declarative `headerSlots` (which render in the dock header) able to call `useChatContext()` and read `sessionId` / `clearMessages` / etc.
|
|
81
81
|
|
|
82
|
+
`ChatProvider` also owns chat-wide UX behaviour that must hold regardless of which preset wraps it — notably **stream-end composer re-focus** (`autoFocusOnStreamEnd`, default `true`). Putting it in the provider means a hand-rolled `ChatProvider` + `MessageList` + `Composer` layout behaves identically to `ChatRoot` with no extra wiring.
|
|
83
|
+
|
|
82
84
|
Module boundaries:
|
|
83
85
|
|
|
84
86
|
| Layer | May import | May NOT import |
|
|
85
87
|
| ---------------- | -------------------------------- | ------------------------ |
|
|
86
88
|
| `types/` | — | anything |
|
|
87
|
-
| `
|
|
89
|
+
| `constants.ts` | — | anything |
|
|
90
|
+
| `core/transport` | `types/` | React, hooks, UI |
|
|
88
91
|
| `core/reducer` | `types/` | React, transport |
|
|
89
|
-
| `hooks` | `core/*`, `ui-core` hooks |
|
|
90
|
-
| `context` | `hooks` |
|
|
91
|
-
| `styles/` | `types/` | hooks,
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
92
|
+
| `hooks` | `core/*`, `ui-core` hooks | UI folders |
|
|
93
|
+
| `context` | `hooks` | UI folders |
|
|
94
|
+
| `styles/` | `types/` | hooks, UI folders |
|
|
95
|
+
| `utils/` | `types/` | React, UI folders |
|
|
96
|
+
| `messages/` | `hooks`, `context`, `styles`, `ui-core` UI | transport implementations |
|
|
97
|
+
| `composer/` | `hooks`, `context`, `styles`, `messages`, `ui-core` UI | transport implementations |
|
|
98
|
+
| `shell/` | `messages`, `composer`, `hooks`, `context`, `ui-core` UI | transport implementations |
|
|
99
|
+
| `launcher/` | `shell`, `messages`, `composer`, `styles`, `ui-core` UI | transport implementations |
|
|
100
|
+
| `launcher/header/` | `context`, `hooks`, `launcher` siblings | transport implementations |
|
|
94
101
|
|
|
95
102
|
## Types
|
|
96
103
|
|
|
@@ -107,6 +114,7 @@ Single source of truth in [`types/`](./types/index.ts). Split by domain — impo
|
|
|
107
114
|
| `events` | `ChatStreamEvent` SSE union |
|
|
108
115
|
| `session` | `SessionInfo`, `HistoryPage`, `Stream/Send/CreateSessionOptions` |
|
|
109
116
|
| `transport` | `ChatTransport` |
|
|
117
|
+
| `block` | `MessageBlock` union + `BlockAppearance` (see Message blocks) |
|
|
110
118
|
|
|
111
119
|
## Launcher (FAB + Dock + Greeting)
|
|
112
120
|
|
|
@@ -525,6 +533,58 @@ function MyError() {
|
|
|
525
533
|
}
|
|
526
534
|
```
|
|
527
535
|
|
|
536
|
+
## Message blocks
|
|
537
|
+
|
|
538
|
+
A message can carry typed, serializable rich content beyond its markdown
|
|
539
|
+
`content`: an optional `blocks: MessageBlock[]`. `MessageBlock` is a
|
|
540
|
+
discriminated union on `kind` — `text`, `markdown`, `audio`, `video`,
|
|
541
|
+
`image`, `gallery`, `map`, `json`, `mermaid`, `code`, `lottie`, plus a
|
|
542
|
+
`custom` escape hatch. Payloads are plain JSON, so blocks survive history
|
|
543
|
+
persistence and SSE transport.
|
|
544
|
+
|
|
545
|
+
`<MessageBubble>` renders blocks **after** the markdown bubble, before
|
|
546
|
+
`toolCalls`. `text`/`markdown` blocks keep the bubble surface; media
|
|
547
|
+
blocks render full-width below it. Legacy messages (no `blocks`) render
|
|
548
|
+
byte-for-byte unchanged.
|
|
549
|
+
|
|
550
|
+
```ts
|
|
551
|
+
const msg: ChatMessage = {
|
|
552
|
+
id: 'm-42', role: 'assistant', createdAt: Date.now(), content: '',
|
|
553
|
+
blocks: [
|
|
554
|
+
{ kind: 'markdown', id: 'b1', markdown: 'Recording from **vps-audi**:' },
|
|
555
|
+
{ kind: 'audio', id: 'b2', src: 'https://cdn…/call.mp3', title: 'Call · 04:12' },
|
|
556
|
+
{ kind: 'map', id: 'b3', caption: 'Server', center: { lat: 52.52, lng: 13.405 }, zoom: 11 },
|
|
557
|
+
],
|
|
558
|
+
};
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
### The registry
|
|
562
|
+
|
|
563
|
+
Each `kind` maps to a `BlockRenderer` in a `BlockRegistry` — same idea as
|
|
564
|
+
`AttachmentRendererMap`, but keyed by the discriminant. Built-in renderers
|
|
565
|
+
cover the in-house tools (`BUILTIN_BLOCK_REGISTRY`); each is reached
|
|
566
|
+
through a `React.lazy` chunk, so a chat with no map block never downloads
|
|
567
|
+
MapLibre.
|
|
568
|
+
|
|
569
|
+
Merge host overrides with `createBlockRegistry`:
|
|
570
|
+
|
|
571
|
+
```ts
|
|
572
|
+
const registry = createBlockRegistry({
|
|
573
|
+
json: (block) => <MyJsonCard data={block.data} />, // override one kind
|
|
574
|
+
});
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
Pass it via `<ChatRoot messages={{ blockRegistry }}>` — it is threaded
|
|
578
|
+
through context to every `<MessageBubble>`. `<MessageBubble>` also accepts
|
|
579
|
+
a direct `blockRegistry` prop (prop beats context) for standalone /
|
|
580
|
+
Storybook use. An unknown `kind` is skipped silently (lenient default);
|
|
581
|
+
`<MessageBlocks strict>` surfaces a dev notice. Each block is wrapped in
|
|
582
|
+
an error boundary so one malformed block can't blank the transcript.
|
|
583
|
+
|
|
584
|
+
Exports (`@djangocfg/ui-tools/chat`): `MessageBlocks`,
|
|
585
|
+
`createBlockRegistry`, `BUILTIN_BLOCK_REGISTRY`, and the `MessageBlock` /
|
|
586
|
+
`BlockRegistry` / `BlockRenderer` / `BlockRenderContext` types.
|
|
587
|
+
|
|
528
588
|
## Transport contract
|
|
529
589
|
|
|
530
590
|
A single I/O seam.
|
|
@@ -564,11 +624,161 @@ for await (const event of parseSSE(res, { map: createPydanticAISSEMap() })) {
|
|
|
564
624
|
}
|
|
565
625
|
```
|
|
566
626
|
|
|
567
|
-
##
|
|
627
|
+
## `ChatRoot` props
|
|
628
|
+
|
|
629
|
+
`<ChatRootProps>` groups ~13 keys by concern — no flat `composer*` namespace:
|
|
630
|
+
|
|
631
|
+
```tsx
|
|
632
|
+
<ChatRoot
|
|
633
|
+
// core wiring
|
|
634
|
+
transport={transport}
|
|
635
|
+
config={{ greeting: 'Hi!' }}
|
|
636
|
+
session={{ initialId, autoCreate: true }}
|
|
637
|
+
streaming
|
|
638
|
+
audio={{}}
|
|
639
|
+
debug
|
|
640
|
+
|
|
641
|
+
// presentation
|
|
642
|
+
appearance="compact" // 'compact' | 'full' — scales the whole chat
|
|
643
|
+
className="…"
|
|
644
|
+
listClassName="px-6 pt-6" // padding inside the scroll viewport
|
|
645
|
+
|
|
646
|
+
// composition (grouped)
|
|
647
|
+
slots={{
|
|
648
|
+
banner: <QuotaWarning />,
|
|
649
|
+
header: (ctx) => <MyHeader sessionId={ctx.sessionId} />, // node or fn
|
|
650
|
+
empty: ({ setValue, focus }) => <MyEmpty seed={setValue} />, // node or fn
|
|
651
|
+
jumpToLatest: <MyPill />,
|
|
652
|
+
}}
|
|
653
|
+
composer={{
|
|
654
|
+
size: 'lg', // 'sm' | 'md' | 'lg'
|
|
655
|
+
layout: 'stacked', // 'stacked' | 'inline'
|
|
656
|
+
className: '…',
|
|
657
|
+
hidden: false, // unmount the composer (human-in-the-loop pause)
|
|
658
|
+
showAttachmentButton: true,
|
|
659
|
+
onPickFiles: () => openPicker(),
|
|
660
|
+
slots: { actionsStart, actionsEnd, blockStart }, // ComposerSlots
|
|
661
|
+
footer: { showCounter: true } /* | false to hide */,
|
|
662
|
+
render: ({ composer, config }) => <MyComposer composer={composer} />,
|
|
663
|
+
}}
|
|
664
|
+
messages={{
|
|
665
|
+
render: (m, i) => <MyBubble message={m} />,
|
|
666
|
+
renderAfter: (m) => <SideChannelWidget messageId={m.id} />,
|
|
667
|
+
toolCallsProps: { defaultExpanded: true },
|
|
668
|
+
attachmentRenderers: { image: MyImageTile },
|
|
669
|
+
onAttachmentOpen: (a) => openLightbox(a),
|
|
670
|
+
}}
|
|
671
|
+
|
|
672
|
+
// behavior
|
|
673
|
+
focusOnEmptyClick // default true
|
|
674
|
+
/>
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
The `slots.header` / `slots.empty` accept either a `ReactNode` or a render
|
|
678
|
+
function — there is no separate `renderHeader` / `renderEmpty` prop and no
|
|
679
|
+
"which one wins" precedence. `composer.render` fully replaces the built-in
|
|
680
|
+
`<Composer>`; it receives `{ composer, config }` — the live composer hook
|
|
681
|
+
plus the same config object. See **[Slots inventory](#slots-inventory)** below.
|
|
682
|
+
|
|
683
|
+
## Composer slot system
|
|
684
|
+
|
|
685
|
+
`<Composer>` is a single bordered input surface — textarea on top, an
|
|
686
|
+
action bar pinned to the bottom inside the same frame (attach
|
|
687
|
+
bottom-left, mic + send bottom-right). Two layouts:
|
|
688
|
+
|
|
689
|
+
- `layout="stacked"` (default) — Telegram-style two-tier surface.
|
|
690
|
+
- `layout="inline"` — compact single row. `size="sm"` defaults to this.
|
|
568
691
|
|
|
569
|
-
|
|
692
|
+
### Tier A — declarative actions
|
|
570
693
|
|
|
571
|
-
|
|
694
|
+
Pass `ComposerAction[]` arrays; the composer renders consistent,
|
|
695
|
+
correctly-aligned, fully-labelled buttons. Built-in send/stop/attach are
|
|
696
|
+
themselves descriptors — host extras land between attach and mic/send.
|
|
697
|
+
|
|
698
|
+
```tsx
|
|
699
|
+
<Composer
|
|
700
|
+
composer={composer}
|
|
701
|
+
composerSlots={{
|
|
702
|
+
actionsStart: [{ id: 'emoji', icon: <Smile />, label: 'Emoji', onClick }],
|
|
703
|
+
actionsEnd: [{ id: 'model', icon: <Sparkles />, label: 'Model', onClick }],
|
|
704
|
+
blockStart: <ReplyBanner />, // full-width row above the textarea
|
|
705
|
+
}}
|
|
706
|
+
/>
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
`ComposerAction` fields: `id`, `icon`, `label` (required — `aria-label` +
|
|
710
|
+
tooltip), `onClick`, `disabled?`, `pressed?` (→ `aria-pressed`),
|
|
711
|
+
`variant?`, `hideWhen?` (`streaming` | `empty` | `hasText` | `disabled`),
|
|
712
|
+
`order?`. Memoize the arrays so the action bar does not churn.
|
|
713
|
+
|
|
714
|
+
### Tier B — slot replacement
|
|
715
|
+
|
|
716
|
+
Replace a primitive entirely via `slots` / tweak its props via
|
|
717
|
+
`slotProps`:
|
|
718
|
+
|
|
719
|
+
```tsx
|
|
720
|
+
<Composer composer={composer}
|
|
721
|
+
slots={{ SendButton: MyBrandedSend, Textarea: MyEditor }}
|
|
722
|
+
slotProps={{ textarea: { className: 'font-mono' } }}
|
|
723
|
+
/>
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
Swappable: `SendButton`, `AttachButton`, `Textarea`, `ActionBar`.
|
|
727
|
+
|
|
728
|
+
### mic ↔ send swap
|
|
729
|
+
|
|
730
|
+
`micSendSwap` (default `true`) — Telegram behaviour: an action with
|
|
731
|
+
`id: 'mic'` (or `hideWhen: 'hasText'`) shows only while the draft is
|
|
732
|
+
empty; once there is text, send takes its place. Set `false` to keep
|
|
733
|
+
both visible (voice-message hosts).
|
|
734
|
+
|
|
735
|
+
### Footer toolbar
|
|
736
|
+
|
|
737
|
+
`<ComposerFooter>` is the quiet strip below the surface — three zones:
|
|
738
|
+
`start` (auto keyboard hint), `center` (host extras), `end` (auto char
|
|
739
|
+
counter that only appears near `maxLength`). Configure via the
|
|
740
|
+
`footer` prop on `<Composer>` or `composer.footer` on `<ChatRoot>`;
|
|
741
|
+
pass `false` to hide.
|
|
742
|
+
|
|
743
|
+
### Composer kit — ready-made slot widgets
|
|
744
|
+
|
|
745
|
+
ChatGPT / Gemini-style controls that drop straight into `composerSlots`.
|
|
746
|
+
All are exported from `@djangocfg/ui-tools/chat` and size-aware (they
|
|
747
|
+
inherit the composer `size` via context, no prop needed).
|
|
748
|
+
|
|
749
|
+
| Component | Slot | What it is |
|
|
750
|
+
|---|---|---|
|
|
751
|
+
| `<ComposerMenuButton items={MenuItem[]}>` | `inlineStart` | The ChatGPT `+` button — opens a declarative `MenuBuilder` dropdown (sections, submenus, shortcuts). |
|
|
752
|
+
| `<ComposerToolPill icon label active onRemove>` | `inlineStart` | Gemini-style capsule for a selected tool/mode with an optional `×` to clear it. |
|
|
753
|
+
| `<ComposerModelPicker value options onChange>` | `inlineEnd` | "Flash-Lite ▾" pill — opens a radio-group model picker. |
|
|
754
|
+
| `<ComposerBanner variant title description actions onDismiss>` | `blockStart` | Standalone notice bubble above the composer (upsell / quota / info). |
|
|
755
|
+
| `<ComposerRichTextarea mentions>` | `slots.Textarea` (Tier B) | Ready-made TipTap chat editor — unstyled, no toolbar, size-matched height, Enter-to-send, `@`-mention support. |
|
|
756
|
+
|
|
757
|
+
```tsx
|
|
758
|
+
<Composer
|
|
759
|
+
composer={composer}
|
|
760
|
+
composerSlots={{
|
|
761
|
+
blockStart: <ComposerBanner variant="upgrade" title="Free plan limit" … />,
|
|
762
|
+
inlineStart: <ComposerMenuButton items={MENU_ITEMS} />,
|
|
763
|
+
inlineEnd: <ComposerModelPicker value={model} options={MODELS} onChange={setModel} />,
|
|
764
|
+
}}
|
|
765
|
+
/>
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
### `appearance` — compact vs full
|
|
769
|
+
|
|
770
|
+
`<Composer appearance="full">` layers extra spaciousness (radius,
|
|
771
|
+
padding, taller textarea, larger text) over the chosen `size` — for a
|
|
772
|
+
full-page ChatGPT/Gemini surface. `compact` (default) keeps the embedded
|
|
773
|
+
docked-chat geometry. Orthogonal to `size`; `<ChatRoot appearance="full">`
|
|
774
|
+
threads it to both the composer and the message bubbles.
|
|
775
|
+
|
|
776
|
+
### Click-to-focus surface
|
|
777
|
+
|
|
778
|
+
The whole input panel reads as a text field — the padding around the
|
|
779
|
+
editor shows a text caret and a `mousedown` on the bare surface (not a
|
|
780
|
+
button) focuses the editor. Works for both the plain `<textarea>` and the
|
|
781
|
+
TipTap (`contenteditable`) backend.
|
|
572
782
|
|
|
573
783
|
## Three usage patterns
|
|
574
784
|
|
|
@@ -627,7 +837,7 @@ type HttpTransportConfig, type MockTransportOptions, type ParseSSEOptions,
|
|
|
627
837
|
type PydanticAIChatTransportOpts, type PydanticAIEvent, type ToolIdQueue
|
|
628
838
|
|
|
629
839
|
// Hooks
|
|
630
|
-
useChat, useChatComposer,
|
|
840
|
+
useChat, useChatComposer, useChatHistory, useChatLayout,
|
|
631
841
|
useChatLightbox, useAutoFocusOnStreamEnd, useRegisterComposer,
|
|
632
842
|
useChatReset, useVisitorFingerprint, useChatUnread, useChatUnreadNotifier,
|
|
633
843
|
createBrowserNotifier, createCrossTabNotifier, createTitleRotator, createFaviconBadge,
|
|
@@ -682,22 +892,41 @@ JumpToLatest, StreamingIndicator
|
|
|
682
892
|
// `MessageList` exposes `atBottomThreshold` (default 120 px) and
|
|
683
893
|
// `scrollAnchorId` props for ChatGPT-style autoscroll — see "What you get".
|
|
684
894
|
|
|
895
|
+
// Composer kit — slot widgets + types
|
|
896
|
+
ComposerButton, ComposerActionBar, ComposerFooter,
|
|
897
|
+
ComposerMenuButton, ComposerToolPill, ComposerModelPicker,
|
|
898
|
+
ComposerBanner, ComposerRichTextarea, useComposerActions, useResolvedComposerSize
|
|
899
|
+
type ComposerProps, type ComposerSize, type ComposerAppearance,
|
|
900
|
+
type ComposerLayout, type ComposerAction, type ComposerActionVisibility,
|
|
901
|
+
type ComposerSlots, type ComposerSlotComponents, type ComposerSlotProps,
|
|
902
|
+
type ComposerFooterProps, type ComposerMenuButtonProps, type ComposerToolPillProps,
|
|
903
|
+
type ComposerModelPickerProps, type ComposerModelOption,
|
|
904
|
+
type ComposerBannerProps, type ComposerBannerAction, type ComposerRichTextareaProps,
|
|
905
|
+
type ComposerTextareaProps, type SendButtonProps, type AttachButtonProps
|
|
906
|
+
|
|
907
|
+
// Message blocks
|
|
908
|
+
MessageBlocks, createBlockRegistry, BUILTIN_BLOCK_REGISTRY
|
|
909
|
+
type MessageBlock, type BlockAppearance, type BlockRegistry,
|
|
910
|
+
type BlockRenderer, type BlockRenderContext
|
|
911
|
+
|
|
685
912
|
// Lazy preset
|
|
686
913
|
LazyChat
|
|
687
914
|
```
|
|
688
915
|
|
|
689
916
|
## Storybook
|
|
690
917
|
|
|
691
|
-
Stories
|
|
918
|
+
Stories are grouped into five feature sub-groups under `UI Tools/Chat`,
|
|
919
|
+
plus `Overview` (MDX) and `Showcase` (a one-screen living demo):
|
|
692
920
|
|
|
693
|
-
-
|
|
694
|
-
|
|
695
|
-
-
|
|
696
|
-
|
|
697
|
-
-
|
|
698
|
-
|
|
699
|
-
-
|
|
700
|
-
|
|
921
|
+
- **Getting Started** — `ChatRoot`, `Composition` (bring-your-own-layout),
|
|
922
|
+
`Appearance` (compact / full / huge).
|
|
923
|
+
- **Messages** — `Bubbles`, `Markdown`, `Message Blocks`,
|
|
924
|
+
`Tool Calls & Sources`, `Streaming`, `Personas`.
|
|
925
|
+
- **Composer** — `Playground`, `Layout & Actions`, `Menu & Tools`,
|
|
926
|
+
`Banner`, `Mentions`, `Speech & Attachments`.
|
|
927
|
+
- **Launcher** — `Playground`, `Parts`, `Header`,
|
|
928
|
+
`Unread & Notifications`.
|
|
929
|
+
- **Transports** — the three shipped transports with a stubbed `fetchImpl`.
|
|
701
930
|
|
|
702
931
|
---
|
|
703
932
|
|
|
@@ -705,37 +934,36 @@ Stories live next to components — open `@djangocfg/playground`:
|
|
|
705
934
|
|
|
706
935
|
## Slots inventory
|
|
707
936
|
|
|
708
|
-
|
|
|
937
|
+
| Key | Position | Type |
|
|
709
938
|
|---|---|---|
|
|
710
|
-
| `
|
|
711
|
-
| `
|
|
712
|
-
| `
|
|
713
|
-
| `
|
|
714
|
-
| `
|
|
715
|
-
| `
|
|
716
|
-
| `
|
|
717
|
-
| `
|
|
718
|
-
| `
|
|
719
|
-
| `
|
|
939
|
+
| `slots.banner` | Top of message list | `ReactNode` |
|
|
940
|
+
| `slots.header` | Above messages | `ReactNode \| (ctx) => ReactNode` |
|
|
941
|
+
| `slots.empty` | Empty state | `ReactNode \| ({ setValue, focus }) => ReactNode` |
|
|
942
|
+
| `slots.jumpToLatest` | Sticky overlay | `ReactNode` |
|
|
943
|
+
| `composer.slots.actionsStart` / `actionsEnd` | Composer action clusters | `ComposerAction[]` |
|
|
944
|
+
| `composer.slots.blockStart` | Above composer textarea | `ReactNode` |
|
|
945
|
+
| `composer.footer` | Below composer | `ComposerFooterProps \| false` |
|
|
946
|
+
| `composer.render` | Replace `<Composer>` | `({ composer, config }) => ReactNode` |
|
|
947
|
+
| `messages.render` | Replace each bubble | `(m, i) => ReactNode` |
|
|
948
|
+
| `messages.renderAfter` | Below every assistant bubble | `(m) => ReactNode` — fires for every message, independent of `toolCalls` |
|
|
720
949
|
|
|
721
950
|
Flags:
|
|
722
951
|
|
|
723
|
-
- `
|
|
724
|
-
- `hideToolCalls` — show only `renderAfterCalls` rich UI without raw tool panels.
|
|
952
|
+
- `composer.hidden` — agent-pause / human-in-the-loop pause; composer is unmounted.
|
|
725
953
|
|
|
726
|
-
### Which slot for product widgets — `renderAfterCalls` vs `
|
|
954
|
+
### Which slot for product widgets — `renderAfterCalls` vs `messages.renderAfter`?
|
|
727
955
|
|
|
728
956
|
Both put custom content under the assistant bubble; the difference is **what triggers them**.
|
|
729
957
|
|
|
730
958
|
- `renderAfterCalls` is gated on `message.toolCalls?.length > 0`. Use it when the widget is **derived from raw tool output** (read `call.output`) and you can rely on the host streaming the `tool_call` / `tool_result` SSE frames. Admin / dev flows typically work this way.
|
|
731
|
-
- `
|
|
959
|
+
- `messages.renderAfter` fires **for every message**, regardless of `toolCalls`. Use it when the widget is driven by a side channel — e.g. typed `ui_payload` SSE frames the host emits independently of the raw tool surface. This is the correct slot when the public-prod stream **hides** `tool_call` events for security: the message lands with `toolCalls === undefined`, so `renderAfterCalls` would never mount, but `messages.renderAfter` still runs and the widget renders from the side channel.
|
|
732
960
|
|
|
733
961
|
Recommended pairing for a "vehicle cards" / "tax breakdown" / "chart" widget on a public chat:
|
|
734
962
|
|
|
735
963
|
```tsx
|
|
736
964
|
<ChatRoot
|
|
737
965
|
transport={transport}
|
|
738
|
-
|
|
966
|
+
messages={{ renderAfter: (m) => <VehicleCardsForMessage messageId={m.id} /> }}
|
|
739
967
|
/>
|
|
740
968
|
```
|
|
741
969
|
|