@lofcz/streamdown 2.9.1 → 2.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/chunk-NE4QKYRI.js +29 -0
  2. package/dist/highlighted-body-5PIGDDHF.js +2 -0
  3. package/dist/hooks/use-deferred-render.d.ts +57 -0
  4. package/dist/index.d.ts +53 -498
  5. package/dist/index.js +1 -1
  6. package/dist/lib/animate.d.ts +66 -0
  7. package/dist/lib/block-incomplete-context.d.ts +14 -0
  8. package/dist/lib/code-block/body.d.ts +12 -0
  9. package/dist/lib/code-block/container.d.ts +8 -0
  10. package/dist/lib/code-block/context.d.ts +6 -0
  11. package/dist/lib/code-block/copy-button.d.ts +9 -0
  12. package/dist/lib/code-block/download-button.d.ts +9 -0
  13. package/dist/lib/code-block/header.d.ts +5 -0
  14. package/dist/lib/code-block/highlighted-body.d.ts +12 -0
  15. package/dist/lib/code-block/index.d.ts +13 -0
  16. package/dist/lib/code-block/skeleton.d.ts +1 -0
  17. package/dist/lib/components.d.ts +2 -0
  18. package/dist/lib/detect-direction.d.ts +13 -0
  19. package/dist/lib/icon-context.d.ts +23 -0
  20. package/dist/lib/icons.d.ts +14 -0
  21. package/dist/lib/image.d.ts +5 -0
  22. package/dist/lib/incomplete-code-utils.d.ts +24 -0
  23. package/dist/lib/link-modal.d.ts +8 -0
  24. package/dist/lib/markdown.d.ts +30 -0
  25. package/dist/lib/mermaid/download-button.d.ts +11 -0
  26. package/dist/lib/mermaid/fullscreen-button.d.ts +10 -0
  27. package/dist/lib/mermaid/index.d.ts +10 -0
  28. package/dist/lib/mermaid/pan-zoom.d.ts +19 -0
  29. package/dist/lib/mermaid/utils.d.ts +41 -0
  30. package/dist/lib/parse-blocks.d.ts +12 -0
  31. package/dist/lib/plugin-context.d.ts +29 -0
  32. package/dist/lib/plugin-types.d.ts +156 -0
  33. package/dist/lib/prefix-context.d.ts +12 -0
  34. package/dist/lib/preprocess-custom-tags.d.ts +19 -0
  35. package/dist/lib/preprocess-literal-tag-content.d.ts +24 -0
  36. package/dist/lib/rehype/literal-tag-content.d.ts +12 -0
  37. package/dist/lib/rehype/markdown-in-custom-tags.d.ts +16 -0
  38. package/dist/lib/remark/code-meta.d.ts +9 -0
  39. package/dist/lib/remark/container-alerts.d.ts +60 -0
  40. package/dist/lib/remark/escape-html.d.ts +3 -0
  41. package/dist/lib/remark/github-alerts.d.ts +16 -0
  42. package/dist/lib/scroll-lock.d.ts +2 -0
  43. package/dist/lib/scrollable.d.ts +7 -0
  44. package/dist/lib/streamdown-context.d.ts +107 -0
  45. package/dist/lib/table/copy-dropdown.d.ts +8 -0
  46. package/dist/lib/table/download-dropdown.d.ts +16 -0
  47. package/dist/lib/table/fullscreen-button.d.ts +8 -0
  48. package/dist/lib/table/index.d.ts +10 -0
  49. package/dist/lib/table/utils.d.ts +9 -0
  50. package/dist/lib/tailwind-classes.d.ts +2 -4
  51. package/dist/lib/tailwind-classes.js +1 -1
  52. package/dist/lib/translations-context.d.ts +39 -0
  53. package/dist/lib/utils.d.ts +23 -0
  54. package/dist/mermaid-L7RAWDBU.js +2 -0
  55. package/package.json +8 -5
  56. package/styles.css +28 -0
  57. package/dist/chunk-WRHXGPDT.js +0 -27
  58. package/dist/highlighted-body-33HEA3YT.js +0 -2
  59. package/dist/mermaid-RQAJEEXV.js +0 -2
@@ -0,0 +1,60 @@
1
+ import type { Root } from "mdast";
2
+ import type { Plugin } from "unified";
3
+ /**
4
+ * Custom container alerts / callouts:
5
+ *
6
+ * ```
7
+ * >>> [My Section]{red}
8
+ * body markdown
9
+ * <<<
10
+ * ```
11
+ *
12
+ * Variants:
13
+ * - `>>> [Title]` — no color (neutral tint)
14
+ * - `>>> (heart)[Title]{red}` — optional icon before the title
15
+ * - `>>> {heart}[Title]{red}` — wrong-brace icon, tolerated
16
+ * - color may be a named color (`red`) or hex (`#FF0000`)
17
+ *
18
+ * Graceful degradation (critical for streaming): a missing or malformed
19
+ * closer (`>>>`, `>`, `<`, or end-of-input) still renders the callout with
20
+ * whatever content is present, never crashes, and never swallows the
21
+ * leftover marker line.
22
+ *
23
+ * Implementation note: `>>>` is not standard markdown. CommonMark lexes it
24
+ * as three nested blockquotes whose content lazily continues plain text but
25
+ * breaks at lists, blank lines, and inline-markdown splits — so a post-
26
+ * parse AST collapse cannot reliably recover the whole container body.
27
+ * Instead, {@link extractCallouts} scans the raw source **before** markdown
28
+ * parsing (the Streamdown component runs it on the raw text before the
29
+ * streaming block-splitter): it extracts each `>>> ... <<<` region and
30
+ * replaces it with a placeholder HTML node that carries the body verbatim
31
+ * (base64) in `data-callout-body`. The React component (MemoCallout) decodes
32
+ * and re-parses that body as markdown, so nested markdown/lists/math render
33
+ * correctly and streaming partial input works.
34
+ */
35
+ export interface CalloutData {
36
+ /** Raw markdown body (never includes the opener/closer lines). */
37
+ body: string;
38
+ color?: string;
39
+ icon?: string;
40
+ title?: string;
41
+ }
42
+ /**
43
+ * Extract `>>> ... <<<` regions from the raw markdown source, replacing each
44
+ * with a placeholder HTML node. Exported so the streaming pipeline can run it
45
+ * on the raw source *before* the marked block-splitter (which would otherwise
46
+ * split a container at a list/blank line and truncate the body).
47
+ */
48
+ export declare const extractCallouts: (source: string) => string;
49
+ /**
50
+ * Remark plugin for custom container alerts (`>>> [Title]{color} ... <<<`).
51
+ *
52
+ * The actual extraction is done by {@link extractCallouts}, which the
53
+ * Streamdown component runs on the raw source before the streaming
54
+ * block-splitter (and the same path feeds static mode). This transformer is
55
+ * registered so the plugin appears in `defaultRemarkPlugins` (and so a
56
+ * consumer using only the remark plugin list still has the extraction
57
+ * applied); it is a no-op on the already-parsed tree because the placeholder
58
+ * `<div class="sdm-callout">` parses as an ordinary HTML block.
59
+ */
60
+ export declare const remarkContainerAlerts: Plugin<[], Root>;
@@ -0,0 +1,3 @@
1
+ import type { Root } from "mdast";
2
+ import type { Plugin } from "unified";
3
+ export declare const remarkEscapeHtml: Plugin<[], Root>;
@@ -0,0 +1,16 @@
1
+ import type { Root } from "mdast";
2
+ import type { Plugin } from "unified";
3
+ export type AlertKind = "note" | "tip" | "important" | "warning" | "caution";
4
+ /**
5
+ * Remark plugin for GitHub-flavored alerts (`> [!NOTE]`, `> [!TIP]`,
6
+ * `> [!IMPORTANT]`, `> [!WARNING]`, `> [!CAUTION]`), aligned with
7
+ * `rehype-github-alerts` / GitHub rendering semantics:
8
+ *
9
+ * - Marker must be alone on the blockquote's first line; any same-line text
10
+ * after `[!TYPE]` renders as a plain blockquote.
11
+ * - Output is `<div class="markdown-alert markdown-alert-{kind}">` with a
12
+ * `<p class="markdown-alert-title">` (octicon + capitalized title) followed
13
+ * by the body content.
14
+ * - An alert with no body stays a plain blockquote (GitHub behavior).
15
+ */
16
+ export declare const remarkGithubAlerts: Plugin<[], Root>;
@@ -0,0 +1,2 @@
1
+ export declare const lockBodyScroll: () => void;
2
+ export declare const unlockBodyScroll: () => void;
@@ -0,0 +1,7 @@
1
+ import type { ScrollableProps } from "./streamdown-context";
2
+ /**
3
+ * Default horizontal-scroll region: a plain `<div>`. Consumers can override
4
+ * via the `scrollable` prop / `StreamdownContext.scrollable` to plug in a
5
+ * custom scrollbar implementation declaratively.
6
+ */
7
+ export declare const DefaultScrollable: ({ scrollRef, ...props }: ScrollableProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,107 @@
1
+ import { type ComponentProps, type ComponentType, type CSSProperties } from "react";
2
+ import type { PluggableList } from "unified";
3
+ import type { Components } from "./markdown";
4
+ import type { MermaidConfig, ThemeInput } from "./plugin-types";
5
+ export type ControlsConfig = boolean | {
6
+ table?: boolean | {
7
+ copy?: boolean;
8
+ download?: boolean;
9
+ fullscreen?: boolean;
10
+ };
11
+ code?: boolean | {
12
+ copy?: boolean;
13
+ download?: boolean;
14
+ };
15
+ mermaid?: boolean | {
16
+ download?: boolean;
17
+ copy?: boolean;
18
+ fullscreen?: boolean;
19
+ panZoom?: boolean;
20
+ };
21
+ image?: boolean | {
22
+ download?: boolean;
23
+ fullscreen?: boolean;
24
+ };
25
+ };
26
+ export interface LinkSafetyModalProps {
27
+ isOpen: boolean;
28
+ onClose: () => void;
29
+ onConfirm: () => void;
30
+ url: string;
31
+ }
32
+ export interface LinkSafetyConfig {
33
+ enabled: boolean;
34
+ onLinkCheck?: (url: string) => Promise<boolean> | boolean;
35
+ renderModal?: (props: LinkSafetyModalProps) => React.ReactNode;
36
+ }
37
+ export interface MermaidErrorComponentProps {
38
+ chart: string;
39
+ error: string;
40
+ retry: () => void;
41
+ }
42
+ export interface MermaidOptions {
43
+ config?: MermaidConfig;
44
+ errorComponent?: React.ComponentType<MermaidErrorComponentProps>;
45
+ }
46
+ /**
47
+ * Built-in list bullet style presets for nested unordered lists.
48
+ * - `"flat"` — all levels use disc
49
+ * - `"hierarchical"` — disc → circle → square, cycling
50
+ */
51
+ export type ListStylePreset = "flat" | "hierarchical";
52
+ /**
53
+ * Resolves a custom-callout icon name (`>>> (heart)[Title]`) to a node.
54
+ * Consumer supplies e.g. lucide's DynamicIcon; return `null`/`undefined`
55
+ * for a blank placeholder while the icon chunk loads.
56
+ */
57
+ export type CalloutIconResolver = (name: string) => React.ReactNode;
58
+ /**
59
+ * Computes the inline style (background tint + accent border/title color)
60
+ * for a custom callout from its optional `{color}` value. Default is a
61
+ * neutral `color-mix()` tint (see components.tsx).
62
+ */
63
+ export type CalloutStyleResolver = (color?: string) => CSSProperties;
64
+ /**
65
+ * Props passed to the component used for a horizontal-scroll region
66
+ * (code-block body, table inner scroll). `scrollRef` must be attached to the
67
+ * actual scrolling element so Streamdown's auto-pin-on-stream logic keeps
68
+ * working.
69
+ */
70
+ export type ScrollableProps = ComponentProps<"div"> & {
71
+ scrollRef?: React.Ref<HTMLDivElement>;
72
+ };
73
+ /**
74
+ * Component used to render a horizontal-scroll region (code-block body,
75
+ * table inner scroll). Defaults to a plain `<div>`; override to plug in a
76
+ * custom scrollbar implementation (e.g. OverlayScrollbars) declaratively,
77
+ * without DOM observers or per-element wiring.
78
+ */
79
+ export type ScrollableComponent = ComponentType<ScrollableProps>;
80
+ export interface StreamdownContextType {
81
+ /** Icon resolver for custom callouts (`>>> (icon)[Title]{color}`). */
82
+ calloutIcon?: CalloutIconResolver;
83
+ /** Style resolver for custom callouts (background tint + accent). */
84
+ calloutStyle?: CalloutStyleResolver;
85
+ /** Max height for code blocks (px number or CSS length). `0` / `Infinity` disables. @default 400 */
86
+ codeBlockMaxHeight?: number | string;
87
+ /** Merged components/plugins so custom renderers (e.g. callout body) can re-parse nested markdown identically to the outer pass. */
88
+ components?: Components;
89
+ controls: ControlsConfig;
90
+ isAnimating: boolean;
91
+ /** Show line numbers in code blocks. @default true */
92
+ lineNumbers: boolean;
93
+ linkSafety?: LinkSafetyConfig;
94
+ /** Bullet style cycling for nested unordered lists. @default "hierarchical" */
95
+ listStyle: ListStylePreset;
96
+ mermaid?: MermaidOptions;
97
+ mode: "static" | "streaming";
98
+ rehypePlugins?: PluggableList;
99
+ remarkPlugins?: PluggableList;
100
+ /** Component used for horizontal-scroll regions (code body, table). @default plain div */
101
+ scrollable?: ScrollableComponent;
102
+ shikiTheme: [ThemeInput, ThemeInput];
103
+ /** Max height for tables (px number or CSS length). `0` / `Infinity` disables. @default 300 */
104
+ tableMaxHeight?: number | string;
105
+ }
106
+ export declare const defaultStreamdownContext: StreamdownContextType;
107
+ export declare const StreamdownContext: import("react").Context<StreamdownContextType>;
@@ -0,0 +1,8 @@
1
+ export interface TableCopyDropdownProps {
2
+ children?: React.ReactNode;
3
+ className?: string;
4
+ onCopy?: (format: "csv" | "tsv" | "md") => void;
5
+ onError?: (error: Error) => void;
6
+ timeout?: number;
7
+ }
8
+ export declare const TableCopyDropdown: ({ children, className, onCopy, onError, timeout, }: TableCopyDropdownProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,16 @@
1
+ export interface TableDownloadButtonProps {
2
+ children?: React.ReactNode;
3
+ className?: string;
4
+ filename?: string;
5
+ format?: "csv" | "markdown";
6
+ onDownload?: () => void;
7
+ onError?: (error: Error) => void;
8
+ }
9
+ export declare const TableDownloadButton: ({ children, className, onDownload, onError, format, filename, }: TableDownloadButtonProps) => import("react/jsx-runtime").JSX.Element;
10
+ export interface TableDownloadDropdownProps {
11
+ children?: React.ReactNode;
12
+ className?: string;
13
+ onDownload?: (format: "csv" | "markdown") => void;
14
+ onError?: (error: Error) => void;
15
+ }
16
+ export declare const TableDownloadDropdown: ({ children, className, onDownload, onError, }: TableDownloadDropdownProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ interface TableFullscreenButtonProps {
2
+ children: React.ReactNode;
3
+ className?: string;
4
+ showCopy?: boolean;
5
+ showDownload?: boolean;
6
+ }
7
+ export declare const TableFullscreenButton: ({ children, className, showCopy, showDownload, }: TableFullscreenButtonProps) => import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,10 @@
1
+ import { type ComponentProps } from "react";
2
+ type TableProps = ComponentProps<"table"> & {
3
+ maxHeight?: number | string;
4
+ showControls?: boolean;
5
+ showCopy?: boolean;
6
+ showDownload?: boolean;
7
+ showFullscreen?: boolean;
8
+ };
9
+ export declare const Table: ({ children, className, maxHeight, showControls, showCopy, showDownload, showFullscreen, ...props }: TableProps) => import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -0,0 +1,9 @@
1
+ export interface TableData {
2
+ headers: string[];
3
+ rows: string[][];
4
+ }
5
+ export declare const extractTableDataFromElement: (tableElement: HTMLElement) => TableData;
6
+ export declare const tableDataToCSV: (data: TableData) => string;
7
+ export declare const tableDataToTSV: (data: TableData) => string;
8
+ export declare const escapeMarkdownTableCell: (cell: string) => string;
9
+ export declare const tableDataToMarkdown: (data: TableData) => string;
@@ -6,7 +6,7 @@
6
6
  * Use this list to configure Tailwind v4's `@source inline()` directive when
7
7
  * you need a custom prefix. See the README for details.
8
8
  */
9
- declare const STREAMDOWN_CLASSES: readonly string[];
9
+ export declare const STREAMDOWN_CLASSES: readonly string[];
10
10
  /**
11
11
  * Generates a Tailwind v4 `@source inline()` directive containing all
12
12
  * streamdown classes, optionally prefixed.
@@ -21,6 +21,4 @@ declare const STREAMDOWN_CLASSES: readonly string[];
21
21
  * console.log(getSourceInline('tw'));
22
22
  * // → @source inline("tw:{absolute,animate-spin,...}");
23
23
  */
24
- declare function getSourceInline(prefix?: string): string;
25
-
26
- export { STREAMDOWN_CLASSES, getSourceInline };
24
+ export declare function getSourceInline(prefix?: string): string;
@@ -1 +1 @@
1
- var t=["-mt-10","[&>p]:inline","[&_svg]:h-auto","[&_svg]:w-auto","[counter-increment:line_0]","[counter-reset:line]","[li_&]:pl-6","absolute","animate-spin","appearance-none","backdrop-blur-sm","before:[counter-increment:line]","before:content-[counter(line)]","before:font-mono","before:inline-block","before:mr-4","before:select-none","before:text-[13px]","before:text-muted-foreground/50","before:text-right","before:w-6","bg-[var(--sdm-bg,inherit]","bg-[var(--sdm-tbg)]","bg-background","bg-background/50","bg-background/80","bg-background/90","bg-background/95","bg-black/10","bg-muted","bg-muted/40","bg-muted/80","bg-primary","bg-red-100","bg-red-50","bg-sidebar","bg-sidebar/80","block","border","border-b","border-b-2","border-border","border-collapse","border-current","border-l-4","border-muted-foreground/30","border-red-200","border-sidebar","border-t","bottom-2","bottom-4","break-all","cursor-pointer","dark:bg-[var(--shiki-dark-bg,var(--sdm-bg,inherit)]","dark:bg-[var(--shiki-dark-bg,var(--sdm-tbg))]","dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]","disabled:cursor-not-allowed","disabled:opacity-50","divide-border","divide-y","duration-150","duration-200","ease-out","fixed","flex","flex-1","flex-col","font-medium","font-mono","font-semibold","gap-1","gap-2","gap-4","group","group-hover:block","group-hover:opacity-100","h-4","h-8","h-[46px]","h-auto","h-full","hidden","hover:bg-background","hover:bg-muted","hover:bg-muted/40","hover:bg-primary/90","hover:text-foreground","inline-block","inset-0","italic","items-center","justify-between","justify-center","justify-end","left-2","left-4","list-decimal","list-disc","list-inside","lowercase","max-h-32","max-w-full","max-w-md","mb-2","min-h-28","min-h-[200px]","min-w-[120px]","ml-1","mt-1","mt-2","mt-6","mx-4","my-4","my-6","opacity-0","origin-center","overflow-hidden","overflow-x-auto","overflow-y-auto","overscroll-y-auto","p-1","p-1.5","p-2","p-3","p-4","p-6","pl-4","pointer-events-auto","pointer-events-none","px-1.5","px-3","px-4","py-0.5","py-1","py-2","relative","right-0","right-2","right-4","rounded","rounded-full","rounded-lg","rounded-md","rounded-xl","shadow-lg","shadow-sm","shrink-0","size-4","size-full","space-x-2","space-y-2","space-y-4","sticky","table-fixed","supports-[backdrop-filter]:backdrop-blur","supports-[backdrop-filter]:backdrop-blur-sm","supports-[backdrop-filter]:bg-background/70","supports-[backdrop-filter]:bg-sidebar/70","text-2xl","text-3xl","text-[var(--sdm-c,inherit)]","text-base","text-left","text-lg","text-muted-foreground","text-primary","text-primary-foreground","text-red-600","text-red-700","text-red-800","text-sm","text-xl","text-xs","top-2","top-4","top-full","transition-all","transition-colors","transition-transform","w-4","w-8","w-full","whitespace-normal","whitespace-nowrap","wrap-anywhere","z-10","z-50"];function n(e){let r=[...t];return `@source inline("${e?`${e}:{${r.join(",")}}`:`{${r.join(",")}}`}");`}export{t as STREAMDOWN_CLASSES,n as getSourceInline};
1
+ var t=["-mt-10","[&>p]:inline","[&>p:last-child]:mb-0","[&>svg]:inline-block","[&_svg]:h-auto","[&_svg]:w-auto","[counter-increment:line_0]","[counter-reset:line]","[li_&]:pl-6","absolute","animate-spin","appearance-none","backdrop-blur-sm","before:[counter-increment:line]","before:content-[counter(line)]","before:font-mono","before:inline-block","before:mr-4","before:select-none","before:text-[13px]","before:text-muted-foreground/50","before:text-right","before:w-6","bg-[var(--sdm-bg,inherit]","bg-[var(--sdm-tbg)]","bg-background","bg-background/50","bg-background/80","bg-background/90","bg-background/95","bg-black/10","bg-muted","bg-muted/40","bg-muted/80","bg-primary","bg-red-100","bg-red-50","bg-sidebar","bg-sidebar/80","block","border","border-b","border-b-2","border-border","border-collapse","border-current","border-l-4","border-muted-foreground/30","border-red-200","border-sidebar","border-t","bottom-2","bottom-4","break-all","cursor-pointer","dark:bg-[var(--shiki-dark-bg,var(--sdm-bg,inherit)]","dark:bg-[var(--shiki-dark-bg,var(--sdm-tbg))]","dark:text-[var(--shiki-dark,var(--sdm-c,inherit))]","disabled:cursor-not-allowed","disabled:opacity-50","divide-border","divide-y","duration-150","duration-200","ease-out","fixed","flex","flex-1","flex-col","font-medium","font-mono","font-semibold","gap-1","gap-2","gap-4","group","group-hover:block","group-hover:opacity-100","h-4","h-8","h-[46px]","h-auto","h-full","hidden","hover:bg-background","hover:bg-muted","hover:bg-muted/40","hover:bg-primary/90","hover:text-foreground","inline-block","inset-0","italic","items-center","justify-between","justify-center","justify-end","left-2","left-4","list-decimal","list-disc","list-inside","lowercase","max-h-32","max-w-full","max-w-md","mb-2","min-h-28","min-h-[200px]","min-w-[120px]","ml-1","mt-1","mt-2","mt-6","mx-4","my-4","my-6","opacity-0","origin-center","overflow-hidden","overflow-x-auto","overflow-y-auto","overscroll-y-auto","p-1","p-1.5","p-2","p-3","p-4","p-6","pl-4","pointer-events-auto","pointer-events-none","px-1.5","px-3","px-4","py-0.5","py-1","py-2","relative","right-0","right-2","right-4","rounded","rounded-full","rounded-lg","rounded-md","rounded-r-md","rounded-xl","shadow-lg","shadow-sm","shrink-0","size-4","size-full","space-x-2","space-y-2","space-y-4","sticky","table-fixed","supports-[backdrop-filter]:backdrop-blur","supports-[backdrop-filter]:backdrop-blur-sm","supports-[backdrop-filter]:bg-background/70","supports-[backdrop-filter]:bg-sidebar/70","text-2xl","text-3xl","text-[var(--sdm-c,inherit)]","text-base","text-left","text-lg","text-muted-foreground","text-primary","text-primary-foreground","text-red-600","text-red-700","text-red-800","text-sm","text-xl","text-xs","top-2","top-4","top-full","transition-all","transition-colors","transition-transform","w-4","w-8","w-full","whitespace-normal","whitespace-nowrap","wrap-anywhere","z-10","z-50"];function n(e){let r=[...t];return `@source inline("${e?`${e}:{${r.join(",")}}`:`{${r.join(",")}}`}");`}export{t as STREAMDOWN_CLASSES,n as getSourceInline};
@@ -0,0 +1,39 @@
1
+ export interface StreamdownTranslations {
2
+ alertCaution: string;
3
+ alertImportant: string;
4
+ alertNote: string;
5
+ alertTip: string;
6
+ alertWarning: string;
7
+ close: string;
8
+ copied: string;
9
+ copyCode: string;
10
+ copyLink: string;
11
+ copyTable: string;
12
+ copyTableAsCsv: string;
13
+ copyTableAsMarkdown: string;
14
+ copyTableAsTsv: string;
15
+ downloadDiagram: string;
16
+ downloadDiagramAsMmd: string;
17
+ downloadDiagramAsPng: string;
18
+ downloadDiagramAsSvg: string;
19
+ downloadFile: string;
20
+ downloadImage: string;
21
+ downloadTable: string;
22
+ downloadTableAsCsv: string;
23
+ downloadTableAsMarkdown: string;
24
+ exitFullscreen: string;
25
+ externalLinkWarning: string;
26
+ imageNotAvailable: string;
27
+ mermaidFormatMmd: string;
28
+ mermaidFormatPng: string;
29
+ mermaidFormatSvg: string;
30
+ openExternalLink: string;
31
+ openLink: string;
32
+ tableFormatCsv: string;
33
+ tableFormatMarkdown: string;
34
+ tableFormatTsv: string;
35
+ viewFullscreen: string;
36
+ }
37
+ export declare const defaultTranslations: StreamdownTranslations;
38
+ export declare const TranslationsContext: import("react").Context<StreamdownTranslations>;
39
+ export declare const useTranslations: () => StreamdownTranslations;
@@ -0,0 +1,23 @@
1
+ import { type ClassValue } from 'clsx';
2
+ export declare const cn: (...inputs: ClassValue[]) => string;
3
+ /**
4
+ * Resolve a max-height prop to a CSS length string.
5
+ * `undefined`, non-finite numbers, and `<= 0` disable the constraint.
6
+ */
7
+ export declare const resolveMaxHeight: (maxHeight: number | string | undefined) => string | undefined;
8
+ export type CnFunction = (...inputs: ClassValue[]) => string;
9
+ /**
10
+ * Prepends a prefix to each Tailwind utility class in a class string.
11
+ * Used to support Tailwind v4's `prefix()` feature.
12
+ *
13
+ * @example
14
+ * prefixClasses("tw", "flex items-center") // "tw:flex tw:items-center"
15
+ * prefixClasses("tw", "dark:bg-red-500") // "tw:dark:bg-red-500"
16
+ */
17
+ export declare const prefixClasses: (prefix: string, classString: string) => string;
18
+ /**
19
+ * Creates a prefix-aware `cn` function. When no prefix is provided,
20
+ * returns the standard `cn` with zero overhead.
21
+ */
22
+ export declare const createCn: (prefix?: string) => CnFunction;
23
+ export declare const save: (filename: string, content: string | Blob, mimeType: string) => void;
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ export{p as Mermaid}from'./chunk-NE4QKYRI.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lofcz/streamdown",
3
- "version": "2.9.1",
3
+ "version": "2.9.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -24,7 +24,7 @@
24
24
  "homepage": "https://streamdown.ai",
25
25
  "repository": {
26
26
  "type": "git",
27
- "url": "git+https://github.com/lofcz/streamdown.git",
27
+ "url": "git+https://github.com/lofcz/streamdown-ng.git",
28
28
  "directory": "packages/streamdown"
29
29
  },
30
30
  "publishConfig": {
@@ -37,17 +37,20 @@
37
37
  "@testing-library/jest-dom": "^6.9.1",
38
38
  "@testing-library/react": "^16.3.0",
39
39
  "@types/hast": "^3.0.4",
40
+ "@types/mdast": "^4.0.4",
40
41
  "@types/react": "^19.2.7",
41
42
  "@types/react-dom": "^19.2.3",
42
- "react-dom": "^19.2.3",
43
+ "@types/unist": "^2.0.11",
43
44
  "@vitejs/plugin-react": "^5.1.2",
44
45
  "@vitest/coverage-v8": "^4.0.15",
45
46
  "jsdom": "^27.3.0",
47
+ "react-dom": "^19.2.3",
46
48
  "react-markdown": "^10.1.0",
47
49
  "rehype-parse": "^9.0.1",
48
50
  "rehype-stringify": "^10.0.1",
49
51
  "shiki": "^3.19.0",
50
52
  "tsup": "^8.5.1",
53
+ "typescript": "^7.0.2",
51
54
  "vitest": "^4.0.15",
52
55
  "@streamdown/math": "npm:@lofcz/streamdown-math@1.0.3",
53
56
  "@streamdown/cjk": "npm:@lofcz/streamdown-cjk@1.0.3",
@@ -61,7 +64,7 @@
61
64
  "clsx": "^2.1.1",
62
65
  "hast-util-to-jsx-runtime": "^2.3.6",
63
66
  "html-url-attributes": "^3.0.1",
64
- "marked": "^17.0.1",
67
+ "marked": "^18.0.9",
65
68
  "rehype-harden": "^1.1.8",
66
69
  "rehype-raw": "^7.0.0",
67
70
  "rehype-sanitize": "^6.0.0",
@@ -75,7 +78,7 @@
75
78
  "unist-util-visit-parents": "^6.0.0"
76
79
  },
77
80
  "scripts": {
78
- "build": "tsup",
81
+ "build": "node scripts/build.mjs",
79
82
  "postbuild": "node scripts/postbuild.js",
80
83
  "test": "vitest run",
81
84
  "test:ui": "vitest --ui run",
package/styles.css CHANGED
@@ -108,3 +108,31 @@
108
108
  color: hsl(0 84% 60%);
109
109
  }
110
110
  }
111
+
112
+ /*
113
+ * The caret has nowhere sensible to sit after a code block or a table, so it is
114
+ * suppressed while one of those trails the stream. Expressing that in CSS rather
115
+ * than in the container's class list keeps the container's style constant for the
116
+ * life of the stream: a container whose class or custom property changes per token
117
+ * invalidates style for the whole document subtree, which on a large document costs
118
+ * tens of milliseconds of recalculation per token.
119
+ *
120
+ * The second selector covers per-block direction, which wraps each block in a
121
+ * display:contents element.
122
+ */
123
+ [data-streamdown="container"]
124
+ > :last-child:is(
125
+ [data-streamdown="code-block"][data-incomplete],
126
+ [data-streamdown="mermaid-block"][data-incomplete],
127
+ [data-streamdown="table-wrapper"]
128
+ )::after,
129
+ [data-streamdown="container"]
130
+ > :last-child:has(
131
+ > :is(
132
+ [data-streamdown="code-block"][data-incomplete],
133
+ [data-streamdown="mermaid-block"][data-incomplete],
134
+ [data-streamdown="table-wrapper"]
135
+ ):last-child
136
+ )::after {
137
+ content: none;
138
+ }