@djangocfg/ui-tools 2.1.94 → 2.1.96

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/index.d.cts CHANGED
@@ -1567,6 +1567,43 @@ interface MarkdownMessageProps {
1567
1567
  isUser?: boolean;
1568
1568
  /** Use compact size (text-xs instead of text-sm) */
1569
1569
  isCompact?: boolean;
1570
+ /**
1571
+ * Enable collapsible "Read more..." functionality
1572
+ * When enabled, long content will be truncated with a toggle button
1573
+ * @default false
1574
+ */
1575
+ collapsible?: boolean;
1576
+ /**
1577
+ * Maximum character length before showing "Read more..."
1578
+ * Only applies when collapsible is true
1579
+ * If both maxLength and maxLines are set, the stricter limit applies
1580
+ */
1581
+ maxLength?: number;
1582
+ /**
1583
+ * Maximum number of lines before showing "Read more..."
1584
+ * Only applies when collapsible is true
1585
+ * If both maxLength and maxLines are set, the stricter limit applies
1586
+ */
1587
+ maxLines?: number;
1588
+ /**
1589
+ * Custom "Read more" button text
1590
+ * @default "Read more..."
1591
+ */
1592
+ readMoreLabel?: string;
1593
+ /**
1594
+ * Custom "Show less" button text
1595
+ * @default "Show less"
1596
+ */
1597
+ showLessLabel?: string;
1598
+ /**
1599
+ * Start expanded (only applies when collapsible is true)
1600
+ * @default false
1601
+ */
1602
+ defaultExpanded?: boolean;
1603
+ /**
1604
+ * Callback when collapsed state changes
1605
+ */
1606
+ onCollapseChange?: (isCollapsed: boolean) => void;
1570
1607
  }
1571
1608
  /**
1572
1609
  * MarkdownMessage - Renders markdown content with syntax highlighting and GFM support
@@ -1578,6 +1615,7 @@ interface MarkdownMessageProps {
1578
1615
  * - Tables, lists, blockquotes
1579
1616
  * - User/assistant styling modes
1580
1617
  * - Plain text optimization (skips ReactMarkdown for simple text)
1618
+ * - Collapsible "Read more..." for long messages
1581
1619
  *
1582
1620
  * @example
1583
1621
  * ```tsx
@@ -1585,8 +1623,72 @@ interface MarkdownMessageProps {
1585
1623
  *
1586
1624
  * // User message styling
1587
1625
  * <MarkdownMessage content="Some content" isUser />
1626
+ *
1627
+ * // Collapsible long content (for chat apps)
1628
+ * <MarkdownMessage
1629
+ * content={longText}
1630
+ * collapsible
1631
+ * maxLength={300}
1632
+ * maxLines={5}
1633
+ * />
1588
1634
  * ```
1589
1635
  */
1590
1636
  declare const MarkdownMessage: React__default.FC<MarkdownMessageProps>;
1591
1637
 
1592
- export { ArrayFieldItemTemplate, ArrayFieldTemplate, type AspectRatioValue, type AudioLevels, AudioReactiveCover, type AudioReactiveCoverProps, BaseInputTemplate, type BlobSource, COLOR_SCHEMES, COLOR_SCHEME_INFO, CheckboxWidget, ColorWidget, type CreateVideoErrorFallbackOptions, type DASHSource, type DataUrlSource, EFFECT_ANIMATIONS, type EffectColorScheme, type EffectColors, type EffectConfig$1 as EffectConfig, type EffectIntensity, type EffectLayer, type EffectVariant, type EqualizerOptions, type ErrorFallbackProps, ErrorListTemplate, FieldTemplate, GlowEffect, type GlowEffectData, type HLSSource, type HybridAudioContextValue, type HybridAudioControls, HybridAudioPlayer, type HybridAudioPlayerProps, HybridAudioProvider, type HybridAudioProviderProps, type HybridAudioState, HybridSimplePlayer, type HybridSimplePlayerProps, HybridWaveform, type HybridWaveformProps, type HybridWebAudioAPI, INTENSITY_CONFIG, INTENSITY_INFO, type ImageFile, ImageViewer, type ImageViewerProps, JsonSchemaForm, type JsonSchemaFormProps, JsonTreeComponent as JsonTree, type JsonTreeConfig, type LottieDirection, LottiePlayer, type LottiePlayerProps, type LottieSize, type LottieSpeed, MarkdownMessage, type MarkdownMessageProps, Mermaid, MeshEffect, NativeProvider, NumberWidget, ObjectFieldTemplate, Playground as OpenapiViewer, OrbsEffect, type PlayerMode, type PlaygroundConfig, type PlaygroundProps, PrettyCode, type ResolveFileSourceOptions, type SchemaSource, SelectWidget, type SimpleStreamSource, SliderWidget, SpotlightEffect, StreamProvider, type StreamSource, SwitchWidget, TextWidget, type UrlSource, type UseAudioVisualizationReturn, type UseHybridAudioOptions, type UseHybridAudioReturn, type UseLottieOptions, type UseLottieReturn, type UseVisualizationReturn, VARIANT_INFO, VideoControls, VideoErrorFallback, type VideoErrorFallbackProps, VideoPlayer, type VideoPlayerContextValue, type VideoPlayerProps, VideoPlayerProvider, type VideoPlayerProviderProps, type VideoPlayerRef, type VideoSourceUnion, VidstackProvider, type VimeoSource, type VisualizationColorScheme, type VisualizationIntensity, VisualizationProvider, type VisualizationProviderProps, type VisualizationSettings, type VisualizationVariant, type YouTubeSource, calculateGlowLayers, calculateMeshGradients, calculateOrbs, calculateSpotlight, createVideoErrorFallback, formatTime, generateContentKey, getColors, getEffectConfig, getRequiredFields, hasRequiredFields, isSimpleStreamSource, mergeDefaults, normalizeFormData, prepareEffectColors, resolveFileSource, resolvePlayerMode, resolveStreamSource, safeJsonParse, safeJsonStringify, useAudioCache, useAudioVisualization, useBlobUrlCleanup, useHybridAudio, useHybridAudioAnalysis, useHybridAudioContext, useHybridAudioControls, useHybridAudioLevels, useHybridAudioState, useHybridWebAudio, useImageCache, useLottie, useMediaCacheStore, useVideoCache, useVideoPlayerContext, useVideoPlayerSettings, useVisualization, validateRequiredFields, validateSchema };
1638
+ interface UseCollapsibleContentOptions {
1639
+ /**
1640
+ * Maximum character length before collapsing
1641
+ * If both maxLength and maxLines are set, the stricter limit applies
1642
+ */
1643
+ maxLength?: number;
1644
+ /**
1645
+ * Maximum number of lines before collapsing
1646
+ * If both maxLength and maxLines are set, the stricter limit applies
1647
+ */
1648
+ maxLines?: number;
1649
+ /**
1650
+ * Start in expanded state (default: false - starts collapsed)
1651
+ */
1652
+ defaultExpanded?: boolean;
1653
+ }
1654
+ interface UseCollapsibleContentResult {
1655
+ /** Whether content is currently collapsed */
1656
+ isCollapsed: boolean;
1657
+ /** Toggle between collapsed/expanded state */
1658
+ toggleCollapsed: () => void;
1659
+ /** Set collapsed state directly */
1660
+ setCollapsed: (collapsed: boolean) => void;
1661
+ /** Content to display (truncated if collapsed, full if expanded) */
1662
+ displayContent: string;
1663
+ /** Whether the content exceeds limits and should be collapsible */
1664
+ shouldCollapse: boolean;
1665
+ /** Original content length */
1666
+ originalLength: number;
1667
+ /** Original line count */
1668
+ originalLineCount: number;
1669
+ }
1670
+ /**
1671
+ * Hook for managing collapsible content with "Read more..." functionality
1672
+ *
1673
+ * @example
1674
+ * ```tsx
1675
+ * const { isCollapsed, toggleCollapsed, displayContent, shouldCollapse } = useCollapsibleContent(
1676
+ * longText,
1677
+ * { maxLength: 300, maxLines: 5 }
1678
+ * );
1679
+ *
1680
+ * return (
1681
+ * <div>
1682
+ * <Markdown content={displayContent} />
1683
+ * {shouldCollapse && (
1684
+ * <button onClick={toggleCollapsed}>
1685
+ * {isCollapsed ? 'Read more...' : 'Show less'}
1686
+ * </button>
1687
+ * )}
1688
+ * </div>
1689
+ * );
1690
+ * ```
1691
+ */
1692
+ declare function useCollapsibleContent(content: string, options?: UseCollapsibleContentOptions): UseCollapsibleContentResult;
1693
+
1694
+ export { ArrayFieldItemTemplate, ArrayFieldTemplate, type AspectRatioValue, type AudioLevels, AudioReactiveCover, type AudioReactiveCoverProps, BaseInputTemplate, type BlobSource, COLOR_SCHEMES, COLOR_SCHEME_INFO, CheckboxWidget, ColorWidget, type CreateVideoErrorFallbackOptions, type DASHSource, type DataUrlSource, EFFECT_ANIMATIONS, type EffectColorScheme, type EffectColors, type EffectConfig$1 as EffectConfig, type EffectIntensity, type EffectLayer, type EffectVariant, type EqualizerOptions, type ErrorFallbackProps, ErrorListTemplate, FieldTemplate, GlowEffect, type GlowEffectData, type HLSSource, type HybridAudioContextValue, type HybridAudioControls, HybridAudioPlayer, type HybridAudioPlayerProps, HybridAudioProvider, type HybridAudioProviderProps, type HybridAudioState, HybridSimplePlayer, type HybridSimplePlayerProps, HybridWaveform, type HybridWaveformProps, type HybridWebAudioAPI, INTENSITY_CONFIG, INTENSITY_INFO, type ImageFile, ImageViewer, type ImageViewerProps, JsonSchemaForm, type JsonSchemaFormProps, JsonTreeComponent as JsonTree, type JsonTreeConfig, type LottieDirection, LottiePlayer, type LottiePlayerProps, type LottieSize, type LottieSpeed, MarkdownMessage, type MarkdownMessageProps, Mermaid, MeshEffect, NativeProvider, NumberWidget, ObjectFieldTemplate, Playground as OpenapiViewer, OrbsEffect, type PlayerMode, type PlaygroundConfig, type PlaygroundProps, PrettyCode, type ResolveFileSourceOptions, type SchemaSource, SelectWidget, type SimpleStreamSource, SliderWidget, SpotlightEffect, StreamProvider, type StreamSource, SwitchWidget, TextWidget, type UrlSource, type UseAudioVisualizationReturn, type UseCollapsibleContentOptions, type UseCollapsibleContentResult, type UseHybridAudioOptions, type UseHybridAudioReturn, type UseLottieOptions, type UseLottieReturn, type UseVisualizationReturn, VARIANT_INFO, VideoControls, VideoErrorFallback, type VideoErrorFallbackProps, VideoPlayer, type VideoPlayerContextValue, type VideoPlayerProps, VideoPlayerProvider, type VideoPlayerProviderProps, type VideoPlayerRef, type VideoSourceUnion, VidstackProvider, type VimeoSource, type VisualizationColorScheme, type VisualizationIntensity, VisualizationProvider, type VisualizationProviderProps, type VisualizationSettings, type VisualizationVariant, type YouTubeSource, calculateGlowLayers, calculateMeshGradients, calculateOrbs, calculateSpotlight, createVideoErrorFallback, formatTime, generateContentKey, getColors, getEffectConfig, getRequiredFields, hasRequiredFields, isSimpleStreamSource, mergeDefaults, normalizeFormData, prepareEffectColors, resolveFileSource, resolvePlayerMode, resolveStreamSource, safeJsonParse, safeJsonStringify, useAudioCache, useAudioVisualization, useBlobUrlCleanup, useCollapsibleContent, useHybridAudio, useHybridAudioAnalysis, useHybridAudioContext, useHybridAudioControls, useHybridAudioLevels, useHybridAudioState, useHybridWebAudio, useImageCache, useLottie, useMediaCacheStore, useVideoCache, useVideoPlayerContext, useVideoPlayerSettings, useVisualization, validateRequiredFields, validateSchema };
package/dist/index.d.ts CHANGED
@@ -1567,6 +1567,43 @@ interface MarkdownMessageProps {
1567
1567
  isUser?: boolean;
1568
1568
  /** Use compact size (text-xs instead of text-sm) */
1569
1569
  isCompact?: boolean;
1570
+ /**
1571
+ * Enable collapsible "Read more..." functionality
1572
+ * When enabled, long content will be truncated with a toggle button
1573
+ * @default false
1574
+ */
1575
+ collapsible?: boolean;
1576
+ /**
1577
+ * Maximum character length before showing "Read more..."
1578
+ * Only applies when collapsible is true
1579
+ * If both maxLength and maxLines are set, the stricter limit applies
1580
+ */
1581
+ maxLength?: number;
1582
+ /**
1583
+ * Maximum number of lines before showing "Read more..."
1584
+ * Only applies when collapsible is true
1585
+ * If both maxLength and maxLines are set, the stricter limit applies
1586
+ */
1587
+ maxLines?: number;
1588
+ /**
1589
+ * Custom "Read more" button text
1590
+ * @default "Read more..."
1591
+ */
1592
+ readMoreLabel?: string;
1593
+ /**
1594
+ * Custom "Show less" button text
1595
+ * @default "Show less"
1596
+ */
1597
+ showLessLabel?: string;
1598
+ /**
1599
+ * Start expanded (only applies when collapsible is true)
1600
+ * @default false
1601
+ */
1602
+ defaultExpanded?: boolean;
1603
+ /**
1604
+ * Callback when collapsed state changes
1605
+ */
1606
+ onCollapseChange?: (isCollapsed: boolean) => void;
1570
1607
  }
1571
1608
  /**
1572
1609
  * MarkdownMessage - Renders markdown content with syntax highlighting and GFM support
@@ -1578,6 +1615,7 @@ interface MarkdownMessageProps {
1578
1615
  * - Tables, lists, blockquotes
1579
1616
  * - User/assistant styling modes
1580
1617
  * - Plain text optimization (skips ReactMarkdown for simple text)
1618
+ * - Collapsible "Read more..." for long messages
1581
1619
  *
1582
1620
  * @example
1583
1621
  * ```tsx
@@ -1585,8 +1623,72 @@ interface MarkdownMessageProps {
1585
1623
  *
1586
1624
  * // User message styling
1587
1625
  * <MarkdownMessage content="Some content" isUser />
1626
+ *
1627
+ * // Collapsible long content (for chat apps)
1628
+ * <MarkdownMessage
1629
+ * content={longText}
1630
+ * collapsible
1631
+ * maxLength={300}
1632
+ * maxLines={5}
1633
+ * />
1588
1634
  * ```
1589
1635
  */
1590
1636
  declare const MarkdownMessage: React__default.FC<MarkdownMessageProps>;
1591
1637
 
1592
- export { ArrayFieldItemTemplate, ArrayFieldTemplate, type AspectRatioValue, type AudioLevels, AudioReactiveCover, type AudioReactiveCoverProps, BaseInputTemplate, type BlobSource, COLOR_SCHEMES, COLOR_SCHEME_INFO, CheckboxWidget, ColorWidget, type CreateVideoErrorFallbackOptions, type DASHSource, type DataUrlSource, EFFECT_ANIMATIONS, type EffectColorScheme, type EffectColors, type EffectConfig$1 as EffectConfig, type EffectIntensity, type EffectLayer, type EffectVariant, type EqualizerOptions, type ErrorFallbackProps, ErrorListTemplate, FieldTemplate, GlowEffect, type GlowEffectData, type HLSSource, type HybridAudioContextValue, type HybridAudioControls, HybridAudioPlayer, type HybridAudioPlayerProps, HybridAudioProvider, type HybridAudioProviderProps, type HybridAudioState, HybridSimplePlayer, type HybridSimplePlayerProps, HybridWaveform, type HybridWaveformProps, type HybridWebAudioAPI, INTENSITY_CONFIG, INTENSITY_INFO, type ImageFile, ImageViewer, type ImageViewerProps, JsonSchemaForm, type JsonSchemaFormProps, JsonTreeComponent as JsonTree, type JsonTreeConfig, type LottieDirection, LottiePlayer, type LottiePlayerProps, type LottieSize, type LottieSpeed, MarkdownMessage, type MarkdownMessageProps, Mermaid, MeshEffect, NativeProvider, NumberWidget, ObjectFieldTemplate, Playground as OpenapiViewer, OrbsEffect, type PlayerMode, type PlaygroundConfig, type PlaygroundProps, PrettyCode, type ResolveFileSourceOptions, type SchemaSource, SelectWidget, type SimpleStreamSource, SliderWidget, SpotlightEffect, StreamProvider, type StreamSource, SwitchWidget, TextWidget, type UrlSource, type UseAudioVisualizationReturn, type UseHybridAudioOptions, type UseHybridAudioReturn, type UseLottieOptions, type UseLottieReturn, type UseVisualizationReturn, VARIANT_INFO, VideoControls, VideoErrorFallback, type VideoErrorFallbackProps, VideoPlayer, type VideoPlayerContextValue, type VideoPlayerProps, VideoPlayerProvider, type VideoPlayerProviderProps, type VideoPlayerRef, type VideoSourceUnion, VidstackProvider, type VimeoSource, type VisualizationColorScheme, type VisualizationIntensity, VisualizationProvider, type VisualizationProviderProps, type VisualizationSettings, type VisualizationVariant, type YouTubeSource, calculateGlowLayers, calculateMeshGradients, calculateOrbs, calculateSpotlight, createVideoErrorFallback, formatTime, generateContentKey, getColors, getEffectConfig, getRequiredFields, hasRequiredFields, isSimpleStreamSource, mergeDefaults, normalizeFormData, prepareEffectColors, resolveFileSource, resolvePlayerMode, resolveStreamSource, safeJsonParse, safeJsonStringify, useAudioCache, useAudioVisualization, useBlobUrlCleanup, useHybridAudio, useHybridAudioAnalysis, useHybridAudioContext, useHybridAudioControls, useHybridAudioLevels, useHybridAudioState, useHybridWebAudio, useImageCache, useLottie, useMediaCacheStore, useVideoCache, useVideoPlayerContext, useVideoPlayerSettings, useVisualization, validateRequiredFields, validateSchema };
1638
+ interface UseCollapsibleContentOptions {
1639
+ /**
1640
+ * Maximum character length before collapsing
1641
+ * If both maxLength and maxLines are set, the stricter limit applies
1642
+ */
1643
+ maxLength?: number;
1644
+ /**
1645
+ * Maximum number of lines before collapsing
1646
+ * If both maxLength and maxLines are set, the stricter limit applies
1647
+ */
1648
+ maxLines?: number;
1649
+ /**
1650
+ * Start in expanded state (default: false - starts collapsed)
1651
+ */
1652
+ defaultExpanded?: boolean;
1653
+ }
1654
+ interface UseCollapsibleContentResult {
1655
+ /** Whether content is currently collapsed */
1656
+ isCollapsed: boolean;
1657
+ /** Toggle between collapsed/expanded state */
1658
+ toggleCollapsed: () => void;
1659
+ /** Set collapsed state directly */
1660
+ setCollapsed: (collapsed: boolean) => void;
1661
+ /** Content to display (truncated if collapsed, full if expanded) */
1662
+ displayContent: string;
1663
+ /** Whether the content exceeds limits and should be collapsible */
1664
+ shouldCollapse: boolean;
1665
+ /** Original content length */
1666
+ originalLength: number;
1667
+ /** Original line count */
1668
+ originalLineCount: number;
1669
+ }
1670
+ /**
1671
+ * Hook for managing collapsible content with "Read more..." functionality
1672
+ *
1673
+ * @example
1674
+ * ```tsx
1675
+ * const { isCollapsed, toggleCollapsed, displayContent, shouldCollapse } = useCollapsibleContent(
1676
+ * longText,
1677
+ * { maxLength: 300, maxLines: 5 }
1678
+ * );
1679
+ *
1680
+ * return (
1681
+ * <div>
1682
+ * <Markdown content={displayContent} />
1683
+ * {shouldCollapse && (
1684
+ * <button onClick={toggleCollapsed}>
1685
+ * {isCollapsed ? 'Read more...' : 'Show less'}
1686
+ * </button>
1687
+ * )}
1688
+ * </div>
1689
+ * );
1690
+ * ```
1691
+ */
1692
+ declare function useCollapsibleContent(content: string, options?: UseCollapsibleContentOptions): UseCollapsibleContentResult;
1693
+
1694
+ export { ArrayFieldItemTemplate, ArrayFieldTemplate, type AspectRatioValue, type AudioLevels, AudioReactiveCover, type AudioReactiveCoverProps, BaseInputTemplate, type BlobSource, COLOR_SCHEMES, COLOR_SCHEME_INFO, CheckboxWidget, ColorWidget, type CreateVideoErrorFallbackOptions, type DASHSource, type DataUrlSource, EFFECT_ANIMATIONS, type EffectColorScheme, type EffectColors, type EffectConfig$1 as EffectConfig, type EffectIntensity, type EffectLayer, type EffectVariant, type EqualizerOptions, type ErrorFallbackProps, ErrorListTemplate, FieldTemplate, GlowEffect, type GlowEffectData, type HLSSource, type HybridAudioContextValue, type HybridAudioControls, HybridAudioPlayer, type HybridAudioPlayerProps, HybridAudioProvider, type HybridAudioProviderProps, type HybridAudioState, HybridSimplePlayer, type HybridSimplePlayerProps, HybridWaveform, type HybridWaveformProps, type HybridWebAudioAPI, INTENSITY_CONFIG, INTENSITY_INFO, type ImageFile, ImageViewer, type ImageViewerProps, JsonSchemaForm, type JsonSchemaFormProps, JsonTreeComponent as JsonTree, type JsonTreeConfig, type LottieDirection, LottiePlayer, type LottiePlayerProps, type LottieSize, type LottieSpeed, MarkdownMessage, type MarkdownMessageProps, Mermaid, MeshEffect, NativeProvider, NumberWidget, ObjectFieldTemplate, Playground as OpenapiViewer, OrbsEffect, type PlayerMode, type PlaygroundConfig, type PlaygroundProps, PrettyCode, type ResolveFileSourceOptions, type SchemaSource, SelectWidget, type SimpleStreamSource, SliderWidget, SpotlightEffect, StreamProvider, type StreamSource, SwitchWidget, TextWidget, type UrlSource, type UseAudioVisualizationReturn, type UseCollapsibleContentOptions, type UseCollapsibleContentResult, type UseHybridAudioOptions, type UseHybridAudioReturn, type UseLottieOptions, type UseLottieReturn, type UseVisualizationReturn, VARIANT_INFO, VideoControls, VideoErrorFallback, type VideoErrorFallbackProps, VideoPlayer, type VideoPlayerContextValue, type VideoPlayerProps, VideoPlayerProvider, type VideoPlayerProviderProps, type VideoPlayerRef, type VideoSourceUnion, VidstackProvider, type VimeoSource, type VisualizationColorScheme, type VisualizationIntensity, VisualizationProvider, type VisualizationProviderProps, type VisualizationSettings, type VisualizationVariant, type YouTubeSource, calculateGlowLayers, calculateMeshGradients, calculateOrbs, calculateSpotlight, createVideoErrorFallback, formatTime, generateContentKey, getColors, getEffectConfig, getRequiredFields, hasRequiredFields, isSimpleStreamSource, mergeDefaults, normalizeFormData, prepareEffectColors, resolveFileSource, resolvePlayerMode, resolveStreamSource, safeJsonParse, safeJsonStringify, useAudioCache, useAudioVisualization, useBlobUrlCleanup, useCollapsibleContent, useHybridAudio, useHybridAudioAnalysis, useHybridAudioContext, useHybridAudioControls, useHybridAudioLevels, useHybridAudioState, useHybridWebAudio, useImageCache, useLottie, useMediaCacheStore, useVideoCache, useVideoPlayerContext, useVideoPlayerSettings, useVisualization, validateRequiredFields, validateSchema };
package/dist/index.mjs CHANGED
@@ -4753,6 +4753,121 @@ function ImageViewer({ file, content, src: directSrc, inDialog = false }) {
4753
4753
  );
4754
4754
  }
4755
4755
  __name(ImageViewer, "ImageViewer");
4756
+ function smartTruncate(content, maxLength) {
4757
+ if (content.length <= maxLength) {
4758
+ return content;
4759
+ }
4760
+ let breakPoint = maxLength;
4761
+ while (breakPoint > maxLength - 50 && breakPoint > 0) {
4762
+ const char = content[breakPoint];
4763
+ if (char === " " || char === "\n" || char === " ") {
4764
+ break;
4765
+ }
4766
+ breakPoint--;
4767
+ }
4768
+ if (breakPoint <= maxLength - 50) {
4769
+ breakPoint = maxLength;
4770
+ }
4771
+ let truncated = content.slice(0, breakPoint).trimEnd();
4772
+ truncated = fixUnclosedMarkdown(truncated);
4773
+ return truncated;
4774
+ }
4775
+ __name(smartTruncate, "smartTruncate");
4776
+ function truncateByLines(content, maxLines) {
4777
+ const lines = content.split("\n");
4778
+ if (lines.length <= maxLines) {
4779
+ return content;
4780
+ }
4781
+ let truncated = lines.slice(0, maxLines).join("\n").trimEnd();
4782
+ truncated = fixUnclosedMarkdown(truncated);
4783
+ return truncated;
4784
+ }
4785
+ __name(truncateByLines, "truncateByLines");
4786
+ function fixUnclosedMarkdown(content) {
4787
+ let result = content;
4788
+ const countOccurrences = /* @__PURE__ */ __name((str, marker) => {
4789
+ const escaped = marker.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4790
+ const matches = str.match(new RegExp(escaped, "g"));
4791
+ return matches ? matches.length : 0;
4792
+ }, "countOccurrences");
4793
+ const boldCount = countOccurrences(result, "**");
4794
+ if (boldCount % 2 !== 0) {
4795
+ result += "**";
4796
+ }
4797
+ const withoutBold = result.replace(/\*\*/g, "");
4798
+ const italicCount = countOccurrences(withoutBold, "*");
4799
+ if (italicCount % 2 !== 0) {
4800
+ result += "*";
4801
+ }
4802
+ const codeCount = countOccurrences(result, "`");
4803
+ const tripleCount = countOccurrences(result, "```");
4804
+ const singleCodeCount = codeCount - tripleCount * 3;
4805
+ if (singleCodeCount % 2 !== 0) {
4806
+ result += "`";
4807
+ }
4808
+ if (tripleCount % 2 !== 0) {
4809
+ result += "\n```";
4810
+ }
4811
+ const strikeCount = countOccurrences(result, "~~");
4812
+ if (strikeCount % 2 !== 0) {
4813
+ result += "~~";
4814
+ }
4815
+ const underlineBoldCount = countOccurrences(result, "__");
4816
+ if (underlineBoldCount % 2 !== 0) {
4817
+ result += "__";
4818
+ }
4819
+ const withoutUnderlineBold = result.replace(/__/g, "");
4820
+ const underlineItalicCount = countOccurrences(withoutUnderlineBold, "_");
4821
+ if (underlineItalicCount % 2 !== 0) {
4822
+ result += "_";
4823
+ }
4824
+ return result;
4825
+ }
4826
+ __name(fixUnclosedMarkdown, "fixUnclosedMarkdown");
4827
+ function useCollapsibleContent(content, options = {}) {
4828
+ const { maxLength, maxLines, defaultExpanded = false } = options;
4829
+ const [isCollapsed, setIsCollapsed] = useState(!defaultExpanded);
4830
+ const originalLength = content.length;
4831
+ const originalLineCount = content.split("\n").length;
4832
+ const { shouldCollapse, truncatedContent } = useMemo(() => {
4833
+ if (maxLength === void 0 && maxLines === void 0) {
4834
+ return { shouldCollapse: false, truncatedContent: content };
4835
+ }
4836
+ let needsCollapse = false;
4837
+ let result = content;
4838
+ if (maxLines !== void 0 && originalLineCount > maxLines) {
4839
+ needsCollapse = true;
4840
+ result = truncateByLines(result, maxLines);
4841
+ }
4842
+ if (maxLength !== void 0 && result.length > maxLength) {
4843
+ needsCollapse = true;
4844
+ result = smartTruncate(result, maxLength);
4845
+ }
4846
+ return { shouldCollapse: needsCollapse, truncatedContent: result };
4847
+ }, [content, maxLength, maxLines, originalLineCount]);
4848
+ const displayContent = useMemo(() => {
4849
+ if (!shouldCollapse || !isCollapsed) {
4850
+ return content;
4851
+ }
4852
+ return truncatedContent;
4853
+ }, [content, truncatedContent, shouldCollapse, isCollapsed]);
4854
+ const toggleCollapsed = useCallback(() => {
4855
+ setIsCollapsed((prev) => !prev);
4856
+ }, []);
4857
+ const setCollapsed = useCallback((collapsed) => {
4858
+ setIsCollapsed(collapsed);
4859
+ }, []);
4860
+ return {
4861
+ isCollapsed,
4862
+ toggleCollapsed,
4863
+ setCollapsed,
4864
+ displayContent,
4865
+ shouldCollapse,
4866
+ originalLength,
4867
+ originalLineCount
4868
+ };
4869
+ }
4870
+ __name(useCollapsibleContent, "useCollapsibleContent");
4756
4871
  var extractTextFromChildren = /* @__PURE__ */ __name((children) => {
4757
4872
  if (typeof children === "string") {
4758
4873
  return children;
@@ -4937,48 +5052,168 @@ var hasMarkdownSyntax = /* @__PURE__ */ __name((text) => {
4937
5052
  ];
4938
5053
  return markdownPatterns.some((pattern) => pattern.test(text));
4939
5054
  }, "hasMarkdownSyntax");
5055
+ var CollapseToggle = /* @__PURE__ */ __name(({
5056
+ isCollapsed,
5057
+ onClick,
5058
+ readMoreLabel,
5059
+ showLessLabel,
5060
+ isUser,
5061
+ isCompact
5062
+ }) => {
5063
+ const textSize = isCompact ? "text-xs" : "text-sm";
5064
+ return /* @__PURE__ */ jsx(
5065
+ "button",
5066
+ {
5067
+ type: "button",
5068
+ onClick,
5069
+ className: `
5070
+ ${textSize} font-medium cursor-pointer
5071
+ transition-colors duration-200
5072
+ ${isUser ? "text-white/80 hover:text-white" : "text-primary hover:text-primary/80"}
5073
+ inline-flex items-center gap-1
5074
+ mt-1
5075
+ `,
5076
+ children: isCollapsed ? /* @__PURE__ */ jsxs(Fragment, { children: [
5077
+ readMoreLabel,
5078
+ /* @__PURE__ */ jsx(
5079
+ "svg",
5080
+ {
5081
+ className: "w-3 h-3",
5082
+ fill: "none",
5083
+ stroke: "currentColor",
5084
+ viewBox: "0 0 24 24",
5085
+ children: /* @__PURE__ */ jsx(
5086
+ "path",
5087
+ {
5088
+ strokeLinecap: "round",
5089
+ strokeLinejoin: "round",
5090
+ strokeWidth: 2,
5091
+ d: "M19 9l-7 7-7-7"
5092
+ }
5093
+ )
5094
+ }
5095
+ )
5096
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
5097
+ showLessLabel,
5098
+ /* @__PURE__ */ jsx(
5099
+ "svg",
5100
+ {
5101
+ className: "w-3 h-3",
5102
+ fill: "none",
5103
+ stroke: "currentColor",
5104
+ viewBox: "0 0 24 24",
5105
+ children: /* @__PURE__ */ jsx(
5106
+ "path",
5107
+ {
5108
+ strokeLinecap: "round",
5109
+ strokeLinejoin: "round",
5110
+ strokeWidth: 2,
5111
+ d: "M5 15l7-7 7 7"
5112
+ }
5113
+ )
5114
+ }
5115
+ )
5116
+ ] })
5117
+ }
5118
+ );
5119
+ }, "CollapseToggle");
4940
5120
  var MarkdownMessage = /* @__PURE__ */ __name(({
4941
5121
  content,
4942
5122
  className = "",
4943
5123
  isUser = false,
4944
- isCompact = false
5124
+ isCompact = false,
5125
+ collapsible = false,
5126
+ maxLength,
5127
+ maxLines,
5128
+ readMoreLabel = "Read more...",
5129
+ showLessLabel = "Show less",
5130
+ defaultExpanded = false,
5131
+ onCollapseChange
4945
5132
  }) => {
4946
5133
  const trimmedContent = content.trim();
5134
+ const collapsibleOptions = React17.useMemo(() => {
5135
+ if (!collapsible) return {};
5136
+ const effectiveMaxLength = maxLength ?? 1e3;
5137
+ const effectiveMaxLines = maxLines ?? 10;
5138
+ return { maxLength: effectiveMaxLength, maxLines: effectiveMaxLines, defaultExpanded };
5139
+ }, [collapsible, maxLength, maxLines, defaultExpanded]);
5140
+ const {
5141
+ isCollapsed,
5142
+ toggleCollapsed,
5143
+ displayContent,
5144
+ shouldCollapse
5145
+ } = useCollapsibleContent(
5146
+ trimmedContent,
5147
+ collapsible ? collapsibleOptions : {}
5148
+ );
5149
+ React17.useEffect(() => {
5150
+ if (collapsible && shouldCollapse && onCollapseChange) {
5151
+ onCollapseChange(isCollapsed);
5152
+ }
5153
+ }, [isCollapsed, collapsible, shouldCollapse, onCollapseChange]);
4947
5154
  const components = React17.useMemo(() => createMarkdownComponents(isUser, isCompact), [isUser, isCompact]);
4948
5155
  const textSizeClass = isCompact ? "text-xs" : "text-sm";
4949
5156
  const proseClass = isCompact ? "prose-xs" : "prose-sm";
4950
- const isPlainText = !hasMarkdownSyntax(trimmedContent);
5157
+ const isPlainText = !hasMarkdownSyntax(displayContent);
4951
5158
  if (isPlainText) {
4952
- return /* @__PURE__ */ jsx("span", { className: `${textSizeClass} leading-relaxed break-words ${className}`, children: trimmedContent });
5159
+ return /* @__PURE__ */ jsxs("span", { className: `${textSizeClass} leading-relaxed break-words ${className}`, children: [
5160
+ displayContent,
5161
+ collapsible && shouldCollapse && /* @__PURE__ */ jsxs(Fragment, { children: [
5162
+ isCollapsed && "... ",
5163
+ /* @__PURE__ */ jsx(
5164
+ CollapseToggle,
5165
+ {
5166
+ isCollapsed,
5167
+ onClick: toggleCollapsed,
5168
+ readMoreLabel,
5169
+ showLessLabel,
5170
+ isUser,
5171
+ isCompact
5172
+ }
5173
+ )
5174
+ ] })
5175
+ ] });
4953
5176
  }
4954
- return /* @__PURE__ */ jsx(
4955
- "div",
4956
- {
4957
- className: `
4958
- prose ${proseClass} max-w-none break-words overflow-hidden ${textSizeClass}
4959
- ${isUser ? "prose-invert" : "dark:prose-invert"}
4960
- ${className}
4961
- `,
4962
- style: {
4963
- // Inherit colors from parent - fixes issues with external CSS variables
4964
- "--tw-prose-body": "inherit",
4965
- "--tw-prose-headings": "inherit",
4966
- "--tw-prose-bold": "inherit",
4967
- "--tw-prose-links": "inherit",
4968
- color: "inherit"
4969
- },
4970
- children: /* @__PURE__ */ jsx(
4971
- ReactMarkdown,
4972
- {
4973
- remarkPlugins: [remarkGfm],
4974
- components,
4975
- children: trimmedContent
4976
- }
4977
- )
4978
- }
4979
- );
5177
+ return /* @__PURE__ */ jsxs("div", { className, children: [
5178
+ /* @__PURE__ */ jsx(
5179
+ "div",
5180
+ {
5181
+ className: `
5182
+ prose ${proseClass} max-w-none break-words overflow-hidden ${textSizeClass}
5183
+ ${isUser ? "prose-invert" : "dark:prose-invert"}
5184
+ `,
5185
+ style: {
5186
+ // Inherit colors from parent - fixes issues with external CSS variables
5187
+ "--tw-prose-body": "inherit",
5188
+ "--tw-prose-headings": "inherit",
5189
+ "--tw-prose-bold": "inherit",
5190
+ "--tw-prose-links": "inherit",
5191
+ color: "inherit"
5192
+ },
5193
+ children: /* @__PURE__ */ jsx(
5194
+ ReactMarkdown,
5195
+ {
5196
+ remarkPlugins: [remarkGfm],
5197
+ components,
5198
+ children: displayContent
5199
+ }
5200
+ )
5201
+ }
5202
+ ),
5203
+ collapsible && shouldCollapse && /* @__PURE__ */ jsx(
5204
+ CollapseToggle,
5205
+ {
5206
+ isCollapsed,
5207
+ onClick: toggleCollapsed,
5208
+ readMoreLabel,
5209
+ showLessLabel,
5210
+ isUser,
5211
+ isCompact
5212
+ }
5213
+ )
5214
+ ] });
4980
5215
  }, "MarkdownMessage");
4981
5216
 
4982
- export { ArrayFieldItemTemplate, ArrayFieldTemplate, AudioReactiveCover, BaseInputTemplate, COLOR_SCHEMES2 as COLOR_SCHEMES, COLOR_SCHEME_INFO, CheckboxWidget, ColorWidget, EFFECT_ANIMATIONS, ErrorListTemplate, FieldTemplate, GlowEffect, HybridAudioPlayer, HybridAudioProvider, HybridSimplePlayer, HybridWaveform, INTENSITY_CONFIG, INTENSITY_INFO, ImageViewer, JsonSchemaForm, LottiePlayer, MarkdownMessage, Mermaid_default as Mermaid, MeshEffect, NativeProvider, NumberWidget, ObjectFieldTemplate, OpenapiViewer_default as OpenapiViewer, OrbsEffect, SelectWidget, SliderWidget, SpotlightEffect, StreamProvider, SwitchWidget, TextWidget, VARIANT_INFO, VideoControls, VideoErrorFallback, VideoPlayer, VideoPlayerProvider, VidstackProvider, VisualizationProvider, calculateGlowLayers, calculateMeshGradients, calculateOrbs, calculateSpotlight, createVideoErrorFallback, formatTime, generateContentKey, getColors, getEffectConfig, getRequiredFields, hasRequiredFields, isSimpleStreamSource, mergeDefaults, normalizeFormData, prepareEffectColors, resolveFileSource, resolvePlayerMode, resolveStreamSource, safeJsonParse, safeJsonStringify, useAudioCache, useAudioVisualization, useBlobUrlCleanup, useHybridAudio, useHybridAudioAnalysis, useHybridAudioContext, useHybridAudioControls, useHybridAudioLevels, useHybridAudioState, useHybridWebAudio, useImageCache, useMediaCacheStore, useVideoCache, useVideoPlayerContext, useVideoPlayerSettings, useVisualization, validateRequiredFields, validateSchema };
5217
+ export { ArrayFieldItemTemplate, ArrayFieldTemplate, AudioReactiveCover, BaseInputTemplate, COLOR_SCHEMES2 as COLOR_SCHEMES, COLOR_SCHEME_INFO, CheckboxWidget, ColorWidget, EFFECT_ANIMATIONS, ErrorListTemplate, FieldTemplate, GlowEffect, HybridAudioPlayer, HybridAudioProvider, HybridSimplePlayer, HybridWaveform, INTENSITY_CONFIG, INTENSITY_INFO, ImageViewer, JsonSchemaForm, LottiePlayer, MarkdownMessage, Mermaid_default as Mermaid, MeshEffect, NativeProvider, NumberWidget, ObjectFieldTemplate, OpenapiViewer_default as OpenapiViewer, OrbsEffect, SelectWidget, SliderWidget, SpotlightEffect, StreamProvider, SwitchWidget, TextWidget, VARIANT_INFO, VideoControls, VideoErrorFallback, VideoPlayer, VideoPlayerProvider, VidstackProvider, VisualizationProvider, calculateGlowLayers, calculateMeshGradients, calculateOrbs, calculateSpotlight, createVideoErrorFallback, formatTime, generateContentKey, getColors, getEffectConfig, getRequiredFields, hasRequiredFields, isSimpleStreamSource, mergeDefaults, normalizeFormData, prepareEffectColors, resolveFileSource, resolvePlayerMode, resolveStreamSource, safeJsonParse, safeJsonStringify, useAudioCache, useAudioVisualization, useBlobUrlCleanup, useCollapsibleContent, useHybridAudio, useHybridAudioAnalysis, useHybridAudioContext, useHybridAudioControls, useHybridAudioLevels, useHybridAudioState, useHybridWebAudio, useImageCache, useMediaCacheStore, useVideoCache, useVideoPlayerContext, useVideoPlayerSettings, useVisualization, validateRequiredFields, validateSchema };
4983
5218
  //# sourceMappingURL=index.mjs.map
4984
5219
  //# sourceMappingURL=index.mjs.map