@ai-react-markdown/mantine 2.4.5 → 2.5.0
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 -9
- package/dist/index.cjs +65 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +14 -10
- package/dist/index.css.map +1 -1
- package/dist/index.js +65 -21
- package/dist/index.js.map +1 -1
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ Mantine UI integration for `@ai-react-markdown/core`. Provides a drop-in `<Manti
|
|
|
24
24
|
- **Mantine typography** -- markdown content is wrapped in Mantine's `<Typography>` so it inherits the active theme's font family, line height, and color tokens
|
|
25
25
|
- **Syntax highlighting** -- code blocks render via `@mantine/code-highlight` (powered by highlight.js), with language-labelled tabs, expand/collapse, and optional auto-detection for unlabelled blocks
|
|
26
26
|
- **Mermaid diagrams** -- fenced `mermaid` code blocks render as interactive SVG diagrams with dark/light theme support, source toggle, copy, and open-in-new-window
|
|
27
|
-
- **JSON pretty-print** -- fenced `json` code blocks are
|
|
27
|
+
- **JSON pretty-print** -- fenced `json` code blocks are parsed and re-serialized with 2-space indent before highlighting; string values that are themselves JSON documents (an object or array — the tool-call transcript shape) are expanded too, primitive-looking strings (`"true"`, `"123"`) are left as written
|
|
28
28
|
- **Automatic color scheme** -- detects Mantine's computed color scheme (`useComputedColorScheme`) and forwards it to the core renderer when no explicit `colorScheme` prop is supplied
|
|
29
29
|
- **Mantine-scoped CSS** -- extra-styles wrapper overrides Mantine spacing/font-size custom properties to use relative `em` units, giving consistent scaling at any base font size
|
|
30
30
|
|
|
@@ -69,7 +69,7 @@ yarn add @ai-react-markdown/mantine @ai-react-markdown/core
|
|
|
69
69
|
{
|
|
70
70
|
"react": ">=19",
|
|
71
71
|
"react-dom": ">=19",
|
|
72
|
-
"@ai-react-markdown/core": "^2.
|
|
72
|
+
"@ai-react-markdown/core": "^2.5.0",
|
|
73
73
|
"@mantine/core": "^9.0.0",
|
|
74
74
|
"@mantine/code-highlight": "^9.0.0",
|
|
75
75
|
"highlight.js": "^11.11.2"
|
|
@@ -237,13 +237,13 @@ Activated by importing `@ai-react-markdown/mantine/styles.css` in your app entry
|
|
|
237
237
|
|
|
238
238
|
The Mantine package installs a default `<pre>` renderer (`MantineAIMPreCode`) that powers all code-block features. Behavior by code-block flavor:
|
|
239
239
|
|
|
240
|
-
| Code-block flavor | Rendered as | Notes
|
|
241
|
-
| ------------------------------------------ | --------------------------- |
|
|
242
|
-
| Annotated, known language (e.g. ` ```ts `) | `<CodeHighlightTabs>` | Tab label = language name (lower-cased)
|
|
243
|
-
| Annotated, unknown language identifier | `<CodeHighlightTabs>` | Tab label = the identifier (lower-cased); Mantine's highlight adapter degrades an unknown language to plaintext
|
|
244
|
-
| No language annotation | `<CodeHighlight>` plaintext | Label = `"unknown"`. With `codeBlock.autoDetectUnknownLanguage: true`, `hljs.highlightAuto` guesses early, re-checks as the block grows, and settles at end of stream — label/highlighting upgrade in place
|
|
245
|
-
| ` ```mermaid ` (any case) | Interactive Mermaid diagram | See [Mermaid Diagrams](#mermaid-diagrams); the language match is case-insensitive
|
|
246
|
-
| ` ```json ` (any case) | Pretty-printed JSON | As soon as the block looks complete (ends in `}`/`]` with balanced brackets outside strings),
|
|
240
|
+
| Code-block flavor | Rendered as | Notes |
|
|
241
|
+
| ------------------------------------------ | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
242
|
+
| Annotated, known language (e.g. ` ```ts `) | `<CodeHighlightTabs>` | Tab label = language name (lower-cased) |
|
|
243
|
+
| Annotated, unknown language identifier | `<CodeHighlightTabs>` | Tab label = the identifier (lower-cased); Mantine's highlight adapter degrades an unknown language to plaintext |
|
|
244
|
+
| No language annotation | `<CodeHighlight>` plaintext | Label = `"unknown"`. With `codeBlock.autoDetectUnknownLanguage: true`, `hljs.highlightAuto` guesses early, re-checks as the block grows, and settles at end of stream — label/highlighting upgrade in place |
|
|
245
|
+
| ` ```mermaid ` (any case) | Interactive Mermaid diagram | See [Mermaid Diagrams](#mermaid-diagrams); the language match is case-insensitive |
|
|
246
|
+
| ` ```json ` (any case) | Pretty-printed JSON | As soon as the block looks complete (ends in `}`/`]` with balanced brackets outside strings), parsed, string values holding a nested JSON object/array expanded (primitive-looking strings such as `"true"` stay strings), then re-serialized with 2-space indent before rendering |
|
|
247
247
|
|
|
248
248
|
All non-special blocks render with `withBorder` and `withExpandButton`, collapsing to `maxCollapsedHeight="320px"` until expanded.
|
|
249
249
|
|
package/dist/index.cjs
CHANGED
|
@@ -64,7 +64,6 @@ var DefaultExtraStyles_default = MantineAIMDefaultExtraStyles;
|
|
|
64
64
|
// src/components/customized/PreCode.tsx
|
|
65
65
|
var import_react4 = require("react");
|
|
66
66
|
var import_code_highlight2 = require("@mantine/code-highlight");
|
|
67
|
-
var import_deep_parse_json = require("deep-parse-json");
|
|
68
67
|
var import_core5 = require("@ai-react-markdown/core");
|
|
69
68
|
|
|
70
69
|
// src/hooks/useMantineCodeBlockOptions.ts
|
|
@@ -115,7 +114,9 @@ var loadMermaid = () => {
|
|
|
115
114
|
var initializedTheme = null;
|
|
116
115
|
var ensureMermaidInitialized = (mermaid, isDark) => {
|
|
117
116
|
const theme = isDark ? "dark" : "light";
|
|
118
|
-
|
|
117
|
+
const api = mermaid.mermaidAPI;
|
|
118
|
+
const currentLevel = api?.getConfig?.().securityLevel;
|
|
119
|
+
if (initializedTheme === theme && currentLevel === "strict") return;
|
|
119
120
|
mermaid.initialize({
|
|
120
121
|
startOnLoad: false,
|
|
121
122
|
securityLevel: "strict",
|
|
@@ -313,6 +314,37 @@ var MantineAIMMermaidCode = (0, import_react3.memo)((props) => {
|
|
|
313
314
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "chart-header", children: [
|
|
314
315
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "chart-type-tag", children: view.kind === "diagram" ? view.chartType : "unknown" }),
|
|
315
316
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_core3.Flex, { align: "center", justify: "flex-end", gap: 0, children: [
|
|
317
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.Tooltip, { label: "Open in new window", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
318
|
+
import_core3.ActionIcon,
|
|
319
|
+
{
|
|
320
|
+
size: 28,
|
|
321
|
+
className: "action-icon",
|
|
322
|
+
variant: "transparent",
|
|
323
|
+
"aria-label": "Open Mermaid diagram in a new window",
|
|
324
|
+
onClick: viewSvgInNewWindow,
|
|
325
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
326
|
+
"svg",
|
|
327
|
+
{
|
|
328
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
329
|
+
viewBox: "0 0 24 24",
|
|
330
|
+
strokeWidth: "2",
|
|
331
|
+
stroke: "currentColor",
|
|
332
|
+
fill: "none",
|
|
333
|
+
strokeLinecap: "round",
|
|
334
|
+
strokeLinejoin: "round",
|
|
335
|
+
width: "18px",
|
|
336
|
+
height: "18px",
|
|
337
|
+
"aria-hidden": "true",
|
|
338
|
+
children: [
|
|
339
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { stroke: "none", d: "M0 0h24v24H0z", fill: "none" }),
|
|
340
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 6h-6a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-6" }),
|
|
341
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M11 13l9 -9" }),
|
|
342
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M15 4h5v5" })
|
|
343
|
+
]
|
|
344
|
+
}
|
|
345
|
+
)
|
|
346
|
+
}
|
|
347
|
+
) }),
|
|
316
348
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.Tooltip, { label: "Show Mermaid Code", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
317
349
|
import_core3.ActionIcon,
|
|
318
350
|
{
|
|
@@ -357,23 +389,7 @@ var MantineAIMMermaidCode = (0, import_react3.memo)((props) => {
|
|
|
357
389
|
) }) })
|
|
358
390
|
] })
|
|
359
391
|
] }),
|
|
360
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
361
|
-
"pre",
|
|
362
|
-
{
|
|
363
|
-
ref,
|
|
364
|
-
style: PRE_STYLE,
|
|
365
|
-
role: "button",
|
|
366
|
-
tabIndex: 0,
|
|
367
|
-
"aria-label": "Open Mermaid diagram in a new window",
|
|
368
|
-
onClick: viewSvgInNewWindow,
|
|
369
|
-
onKeyDown: (event) => {
|
|
370
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
371
|
-
event.preventDefault();
|
|
372
|
-
viewSvgInNewWindow();
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
)
|
|
392
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("pre", { ref, style: PRE_STYLE, onClick: viewSvgInNewWindow })
|
|
377
393
|
]
|
|
378
394
|
}
|
|
379
395
|
)
|
|
@@ -445,6 +461,35 @@ function preloadMantineCodeAssets() {
|
|
|
445
461
|
() => void 0
|
|
446
462
|
);
|
|
447
463
|
}
|
|
464
|
+
function prettyPrintJson(text) {
|
|
465
|
+
let parsed;
|
|
466
|
+
try {
|
|
467
|
+
parsed = JSON.parse(text);
|
|
468
|
+
} catch {
|
|
469
|
+
return text;
|
|
470
|
+
}
|
|
471
|
+
return JSON.stringify(expandNestedJson(parsed), null, 2);
|
|
472
|
+
}
|
|
473
|
+
function expandNestedJson(value) {
|
|
474
|
+
if (typeof value === "string") {
|
|
475
|
+
const t = value.trim();
|
|
476
|
+
if (t.length > 1 && (t[0] === "{" || t[0] === "[")) {
|
|
477
|
+
try {
|
|
478
|
+
const inner = JSON.parse(t);
|
|
479
|
+
if (inner !== null && typeof inner === "object") return expandNestedJson(inner);
|
|
480
|
+
} catch {
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return value;
|
|
484
|
+
}
|
|
485
|
+
if (Array.isArray(value)) return value.map(expandNestedJson);
|
|
486
|
+
if (value !== null && typeof value === "object") {
|
|
487
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
488
|
+
for (const [k, v] of Object.entries(value)) out[k] = expandNestedJson(v);
|
|
489
|
+
return out;
|
|
490
|
+
}
|
|
491
|
+
return value;
|
|
492
|
+
}
|
|
448
493
|
function jsonLooksComplete(text) {
|
|
449
494
|
if (!/[}\]]\s*$/.test(text)) return false;
|
|
450
495
|
let depth = 0;
|
|
@@ -490,8 +535,7 @@ var MantineAIMPreCode = (0, import_react4.memo)(
|
|
|
490
535
|
if (isSpecialCodeBlock) return null;
|
|
491
536
|
let usedCodeStr = props.codeText;
|
|
492
537
|
if (usedCodeStr && usedCodeLanguage === "json" && (!streaming || jsonLooksComplete(usedCodeStr))) {
|
|
493
|
-
|
|
494
|
-
usedCodeStr = typeof deepParsedResult === "string" ? deepParsedResult : JSON.stringify(deepParsedResult, null, 2);
|
|
538
|
+
usedCodeStr = prettyPrintJson(usedCodeStr);
|
|
495
539
|
}
|
|
496
540
|
return usedFileName === "unknown" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
497
541
|
import_code_highlight2.CodeHighlight,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx","../src/MantineAIMarkdown.tsx","../src/components/typography/MantineTypography.tsx","../src/components/extra-styles/DefaultExtraStyles/index.tsx","../src/components/customized/PreCode.tsx","../src/hooks/useMantineCodeBlockOptions.ts","../src/defs.tsx","../src/components/customized/MermaidCode/index.tsx","../src/define.ts","../src/hooks/useMantineAIMarkdownMetadata.ts"],"sourcesContent":["/**\n * Public API surface for `@ai-react-markdown/mantine`.\n *\n * Re-exports the Mantine-integrated AI markdown component, its supporting\n * sub-components, extended types, default configuration, and typed hooks.\n *\n * @packageDocumentation\n */\n\n// --- Components ---\n\n/** Props for the main {@link MantineAIMarkdown} component. */\nexport type { MantineAIMarkdownProps } from './MantineAIMarkdown';\n\n/** Main component -- Mantine-integrated AI markdown renderer (default export). */\nexport { default } from './MantineAIMarkdown';\n\n/** Mantine-themed typography wrapper used by default inside {@link MantineAIMarkdown}. */\nexport { default as MantineAIMarkdownTypography } from './components/typography/MantineTypography';\n\n/** Default extra styles wrapper providing Mantine-compatible CSS scoping and overrides. */\nexport { default as MantineAIMDefaultExtraStyles } from './components/extra-styles/DefaultExtraStyles';\n\n// --- Types, config, and hooks ---\n\n/** Extended render configuration and metadata types for the Mantine integration. */\nexport type { MantineAIMarkdownMetadata, MantineCodeBlockOptions } from './defs';\n\n// ── v2 surface (props-api v2) ───────────────────────────────────────────────\n\n/** Shipped defaults of the `codeBlock` behavior group. */\nexport { defaultMantineCodeBlockOptions } from './defs';\n\n/** Narrow hook for the `codeBlock` behavior group — the single assertion site. */\nexport { useMantineCodeBlockOptions } from './hooks/useMantineCodeBlockOptions';\n\n/** Optional eager loading of the on-demand code-block assets (mermaid, highlight.js). */\nexport { preloadMantineCodeAssets } from './components/customized/PreCode';\n\n/** Widened behaviors factory (core fields + mantine's `codeBlock` group). */\nexport { defineMantineBehaviors } from './define';\nexport type { MantineBehaviorProps } from './define';\n\n/** Typed hook for accessing metadata within the Mantine AI markdown tree. */\nexport { useMantineAIMarkdownMetadata } from './hooks/useMantineAIMarkdownMetadata';\n","/**\n * Main Mantine integration component for AI markdown rendering.\n *\n * Wraps the core {@link AIMarkdown} component with Mantine-specific defaults:\n * - {@link MantineAIMarkdownTypography} as the typography wrapper\n * - {@link MantineAIMDefaultExtraStyles} as the extra styles wrapper\n * - {@link MantineAIMPreCode} as the default `<pre>` component (with syntax\n * highlighting via Mantine's CodeHighlight and mermaid diagram support)\n * - Automatic color scheme detection via Mantine's `useComputedColorScheme`\n *\n * @module MantineAIMarkdown\n */\n\nimport { memo, useMemo } from 'react';\nimport AIMarkdown from '@ai-react-markdown/core';\nimport {\n type AIMarkdownProps,\n type AIMarkdownCustomComponents,\n type AIMarkdownBehaviorGroups,\n type AIMarkdownStabilityTable,\n AIMarkdownBehaviorsProvider,\n AIMarkdownStabilityPolicy,\n useStableRecord,\n useStableValue,\n} from '@ai-react-markdown/core';\nimport MantineAIMarkdownTypography from './components/typography/MantineTypography';\nimport MantineAIMDefaultExtraStyles from './components/extra-styles/DefaultExtraStyles';\nimport { MantineAIMarkdownMetadata, MantineCodeBlockOptions } from './defs';\nimport MantineAIMPreCode from './components/customized/PreCode';\nimport { useComputedColorScheme } from '@mantine/core';\n\n/**\n * Props for the {@link MantineAIMarkdown} component.\n *\n * Extends {@link AIMarkdownProps} with the mantine behavior groups.\n * All core props (`content`, `streaming`, `fontSize`, `enginePlugins`, etc.)\n * are inherited.\n *\n * @typeParam TMetadata - Metadata type, defaults to {@link MantineAIMarkdownMetadata}.\n */\nexport interface MantineAIMarkdownProps<\n TMetadata extends MantineAIMarkdownMetadata = MantineAIMarkdownMetadata,\n> extends AIMarkdownProps<TMetadata> {\n /**\n * Code-block behavior group (Behaviors system). The group value replaces\n * atomically; omitted fields resolve to the shipped defaults inside\n * `useMantineCodeBlockOptions()`. `null` counts as absent. When absent,\n * this wrapper contributes NO `codeBlock` group, so a group provided by\n * an outer app-level `AIMarkdownBehaviorsProvider` passes through; when\n * present, this prop wins over any outer group (inner-wins merge).\n */\n codeBlock?: Partial<MantineCodeBlockOptions>;\n}\n\n/**\n * Stable empty CONTRIBUTION for the absent-prop case. Deliberately carries\n * no `codeBlock` key at all: contributing `codeBlock: {}` would shadow a\n * group provided by an outer app-level `AIMarkdownBehaviorsProvider`\n * (inner-wins merge) even though this wrapper has nothing to say — the\n * documented app-level extension path would silently go dead.\n */\nconst NO_GROUPS: AIMarkdownBehaviorGroups = Object.freeze({});\n\n/**\n * Mantine's stability-firewall table — one row today: `codeBlock` is the\n * only object prop this wrapper TERMINATES (consumes in its own machinery).\n * Forwarded object props ride core's firewall untouched; the merged\n * `customComponents` derived below is caught by core's wall.\n */\nconst MANTINE_STABILITY_TABLE: AIMarkdownStabilityTable<{\n codeBlock: Partial<MantineCodeBlockOptions> | undefined;\n}> = {\n codeBlock: AIMarkdownStabilityPolicy.DEEP_EQUAL,\n};\n\n/**\n * Default custom component overrides applied by the Mantine integration.\n *\n * Overrides the `<pre>` element to extract code blocks and render them via\n * {@link MantineAIMPreCode}, which provides syntax highlighting, expand/collapse,\n * and mermaid diagram support. Falls back to a plain `<pre>` when the child\n * is not a recognized code element.\n */\nconst DefaultCustomComponents: AIMarkdownCustomComponents = {\n pre: ({ node, ...usefulProps }) => {\n const code = node?.children[0] as\n | {\n type: string;\n tagName?: string;\n position?: { start?: { offset?: number } };\n properties?: Record<string, unknown>;\n children: { value?: string }[];\n }\n | undefined;\n if (!code || code.type !== 'element' || code.tagName !== 'code' || !code.position) {\n return <pre {...usefulProps} />;\n }\n const key = `pre-code-${node?.position?.start?.offset || 0}`;\n // hast allows `className` as a string as well as an array (a consumer's\n // rehype plugin may write either); `.find` on a string threw and took\n // the whole tree down (2026-08-19 review).\n const classNames = code.properties?.className;\n const classList = Array.isArray(classNames)\n ? (classNames as unknown[]).filter((c): c is string => typeof c === 'string')\n : typeof classNames === 'string'\n ? classNames.split(/\\s+/)\n : [];\n const detectedLanguage = classList\n .find((className) => className.startsWith('language-'))\n ?.substring('language-'.length);\n // A `<code>` inside `<pre>` normally carries ONE text child; if an\n // upstream plugin splits it, the pieces are contiguous source — join\n // with '' (a '\\n' joiner would invent line breaks the source lacks).\n const codeText = code.children.map((child: { value?: string }) => child.value ?? '').join('');\n return <MantineAIMPreCode key={key} codeText={codeText} existLanguage={detectedLanguage} />;\n },\n};\n\n/**\n * Inner (non-memoized) implementation of the Mantine AI markdown component.\n *\n * Merges caller-provided `customComponents` with the Mantine defaults (the caller's\n * overrides take precedence). Automatically resolves the color scheme from Mantine's\n * `useComputedColorScheme` when no explicit `colorScheme` prop is provided.\n *\n * @typeParam TMetadata - Metadata type.\n */\nconst MantineAIMarkdownComponent = <TMetadata extends MantineAIMarkdownMetadata = MantineAIMarkdownMetadata>({\n Typography = MantineAIMarkdownTypography,\n ExtraStyles = MantineAIMDefaultExtraStyles,\n customComponents,\n colorScheme,\n codeBlock,\n ...props\n}: MantineAIMarkdownProps<TMetadata>) => {\n const stableCustomComponents = useStableValue(customComponents);\n\n const usedComponents = useMemo(() => {\n return stableCustomComponents ? { ...DefaultCustomComponents, ...stableCustomComponents } : DefaultCustomComponents;\n }, [stableCustomComponents]);\n\n const computedColorScheme = useComputedColorScheme('light');\n\n // Mantine's stability firewall: `codeBlock` is terminated here (it feeds\n // the behaviors Provider below, not the core prop surface).\n const stable = useStableRecord({ codeBlock }, MANTINE_STABILITY_TABLE);\n\n // Contribute the group through the additive behaviors Provider — firewall\n // output used directly, record identity memoized so the context value\n // stays stable across unrelated re-renders. `null`/absent prop ≡ no\n // contribution (NOT an empty group): an outer app-level Provider's\n // `codeBlock` group then stays visible; when the prop IS present the\n // inner-wins merge gives this wrapper's value precedence. The narrow hook\n // fills the defaults for the no-group-anywhere case.\n const behaviorGroups = useMemo<AIMarkdownBehaviorGroups>(\n () => (stable.codeBlock != null ? { codeBlock: stable.codeBlock } : NO_GROUPS),\n [stable.codeBlock]\n );\n\n return (\n <AIMarkdownBehaviorsProvider value={behaviorGroups}>\n <AIMarkdown<MantineAIMarkdownMetadata>\n Typography={Typography}\n ExtraStyles={ExtraStyles}\n customComponents={usedComponents}\n colorScheme={colorScheme ?? computedColorScheme}\n {...props}\n />\n </AIMarkdownBehaviorsProvider>\n );\n};\n\n/**\n * Mantine-integrated AI markdown renderer.\n *\n * A memoized wrapper around the core `<AIMarkdown>` component that provides\n * Mantine-themed typography, code highlighting (via `@mantine/code-highlight`),\n * mermaid diagram rendering, and automatic color scheme detection.\n *\n * This is the default export of `@ai-react-markdown/mantine`.\n *\n * @example\n * ```tsx\n * import MantineAIMarkdown from '@ai-react-markdown/mantine';\n *\n * function Chat({ content }: { content: string }) {\n * return <MantineAIMarkdown content={content} />;\n * }\n * ```\n */\nexport const MantineAIMarkdown = memo(MantineAIMarkdownComponent);\n\nMantineAIMarkdown.displayName = 'MantineAIMarkdown';\n\nexport default MantineAIMarkdown as typeof MantineAIMarkdownComponent;\n","import { memo } from 'react';\nimport { Typography } from '@mantine/core';\nimport type { AIMarkdownTypographyProps } from '@ai-react-markdown/core';\n\n/**\n * Mantine-themed typography wrapper for AI markdown content.\n *\n * Replaces the core default typography component with Mantine's `<Typography>`\n * element, applying the configured `fontSize` at full width. This ensures all\n * rendered markdown inherits Mantine's font family, line height, and theming.\n *\n * Used as the default `Typography` prop in {@link MantineAIMarkdown}.\n * Can be replaced by passing a custom `Typography` component.\n *\n * @param props - Standard {@link AIMarkdownTypographyProps} from the core package.\n */\nconst MantineAIMarkdownTypography = memo(({ children, fontSize, style }: AIMarkdownTypographyProps) => (\n <Typography w=\"100%\" fz={fontSize} style={style}>\n {children}\n </Typography>\n));\n\nMantineAIMarkdownTypography.displayName = 'MantineAIMarkdownTypography';\n\nexport default MantineAIMarkdownTypography;\n","import React from 'react';\nimport { AIMarkdownExtraStylesComponent } from '@ai-react-markdown/core';\nimport './styles.scss';\n\n/**\n * Default extra styles wrapper for the Mantine integration.\n *\n * Wraps markdown content in a `<div>` with the `aim-mantine-extra-styles` CSS class,\n * which provides Mantine-compatible typography overrides including:\n * - Relative `em`-based Mantine spacing and font-size CSS custom properties\n * - Heading, list, paragraph, blockquote, and code styling\n * - Definition list layout\n *\n * Used as the default `ExtraStyles` prop in {@link MantineAIMarkdown}.\n */\nconst MantineAIMDefaultExtraStyles: AIMarkdownExtraStylesComponent = ({ children }) => {\n return <div className=\"aim-mantine-extra-styles\">{children}</div>;\n};\n\nexport default MantineAIMDefaultExtraStyles;\n","'use client';\n\nimport { HTMLAttributes, memo, useEffect, useMemo, useRef, useState } from 'react';\nimport { CodeHighlight, CodeHighlightTabs } from '@mantine/code-highlight';\nimport { deepParseJson } from 'deep-parse-json';\nimport { useAIMarkdownState, useAIMarkdownTheme } from '@ai-react-markdown/core';\nimport { useMantineCodeBlockOptions } from '../../hooks/useMantineCodeBlockOptions';\nimport MantineAIMMermaidCode from './MermaidCode';\n\n/**\n * highlight.js is NOT imported statically any more: the root entry carries\n * every language definition (~130 KB gzip) and the only always-on use was a\n * `getLanguage()` existence check that Mantine's own adapter already\n * performs (unknown language → plaintext). Auto-detection is the one real\n * consumer, and it loads the module on demand — only when\n * `autoDetectUnknownLanguage` is on and an unlabelled block shows up\n * (2026-08 project review, pkg-small-02: the static import defeated\n * consumers' `highlight.js/lib/core` slimming). Consumers who want it (and\n * mermaid) in the main bundle up front call `preloadMantineCodeAssets()`\n * at app start, or simply import the modules themselves.\n */\nlet hljsAutoPromise: Promise<{ highlightAuto: (code: string) => { language?: string } }> | null = null;\nexport const loadHljsForAutoDetect = () => {\n // A rejected load (transient network failure) is NOT cached: the next\n // attempt retries instead of leaving autodetection dead for the page.\n hljsAutoPromise ??= import('highlight.js').then(\n (m) => m.default,\n (err: unknown) => {\n hljsAutoPromise = null;\n throw err;\n }\n );\n return hljsAutoPromise;\n};\n\n/** Below this many characters a guess is noise; the block stays \"unknown\". */\nconst AUTODETECT_MIN_CHARS = 32;\n/** Bounded automatic retries of a failed highlight.js module download. */\nconst HLJS_LOAD_RETRIES = 3;\nconst HLJS_LOAD_RETRY_MS = 1500;\n\n/**\n * The language highlight.js guesses for an unlabelled block.\n *\n * `highlightAuto` scores every registered language against the whole text,\n * so re-running it on every streamed chunk was O(languages × n) per chunk —\n * O(n²) over a long block (pkg-small-06). Schedule instead:\n * - first guess as soon as the block has AUTODETECT_MIN_CHARS (an early\n * label rather than \"unknown\" for the whole stream);\n * - a corrective re-run each time the block has DOUBLED in length since\n * the last guess (32 → 64 → 128 → …): a wrong early guess on a long\n * block is fixed within its next doubling, and the total work stays\n * O(n) — at most log₂(n) runs;\n * - a final verdict when streaming ends (the last run always sees the\n * complete block).\n * Returns '' while disabled, still loading, or below the minimum, so the\n * block renders as plaintext/\"unknown\" and upgrades in place.\n */\nfunction useAutoDetectedLanguage(codeText: string, enabled: boolean, streaming: boolean): string {\n const [detected, setDetected] = useState<{ language: string; atLength: number; finalFor: string | null } | null>(\n null\n );\n // Bumped after a failed `import('highlight.js')` so the effect re-runs on\n // otherwise unchanged inputs and retries the download — the mermaid\n // renderer's counterpart. Without it a static document whose only load\n // attempt failed stayed \"unknown\" for good (v2.4.2 review P2-2). Bounded.\n const [loadAttempt, setLoadAttempt] = useState(0);\n const loadFailuresRef = useRef(0);\n useEffect(() => {\n if (!enabled) return;\n // The block was REPLACED, not appended to (a regenerate reuses this\n // instance — the key is the block's source offset — or a same-offset\n // swap): a guess made for the old text is worthless for the new one.\n // Drop it so the schedule restarts (v2.4.0 review: the old label stuck\n // for the whole new stream until its end).\n // Do NOT return here: `detected` is not a dep, so a state reset alone\n // would never re-run the effect and a non-streaming replacement stayed\n // \"unknown\" for good (v2.4.1 review) — evaluate the schedule against\n // the cleared prior in this same pass.\n const prior = detected !== null && codeText.length < detected.atLength ? null : detected;\n if (prior !== detected) setDetected(null);\n if (codeText.length < AUTODETECT_MIN_CHARS) return;\n const due =\n prior === null ||\n // Not streaming: the verdict must be for THIS text (end-of-stream, or a\n // static content update).\n (!streaming && prior.finalFor !== codeText) ||\n // Streaming: doubled since the last guess.\n (streaming && codeText.length >= prior.atLength * 2);\n if (!due) return;\n let cancelled = false;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n loadHljsForAutoDetect().then(\n (hljs) => {\n if (cancelled) return;\n loadFailuresRef.current = 0;\n setDetected({\n language: hljs.highlightAuto(codeText).language ?? '',\n atLength: codeText.length,\n finalFor: streaming ? null : codeText,\n });\n },\n () => {\n // Load failed — stay \"unknown\" and retry the download a bounded\n // number of times (the loader does not cache rejections).\n if (cancelled || loadFailuresRef.current >= HLJS_LOAD_RETRIES) return;\n loadFailuresRef.current += 1;\n retryTimer = setTimeout(() => setLoadAttempt((n) => n + 1), HLJS_LOAD_RETRY_MS);\n }\n );\n return () => {\n cancelled = true;\n if (retryTimer !== undefined) clearTimeout(retryTimer);\n };\n // `detected` is deliberately not a dep: a completed guess must not\n // re-trigger the effect (it re-runs on the next content/streaming\n // change, which is when the schedule is re-evaluated). `loadAttempt`\n // re-runs it after a failed module download.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [codeText, enabled, streaming, loadAttempt]);\n return enabled ? (detected?.language ?? '') : '';\n}\n\n/**\n * Loads mermaid and highlight.js ahead of time. Both are imported on demand\n * by the code-block renderers (the first diagram / the first auto-detected\n * block pays the download); an app that would rather take that cost at\n * startup — a documentation page whose first screen shows a diagram, say —\n * calls this once at boot. Safe to call repeatedly; failures are swallowed\n * (the renderers will simply load lazily later).\n */\nexport function preloadMantineCodeAssets(): Promise<void> {\n return Promise.all([import('mermaid'), loadHljsForAutoDetect()]).then(\n () => undefined,\n () => undefined\n );\n}\n\n/**\n * Cheap tell that a streamed JSON block is complete: it ends with a closing\n * bracket AND its brackets balance to zero outside string literals. A\n * balanced prefix can still be invalid JSON (deepParseJson then just\n * returns the text), but an in-progress pretty-printed block is never\n * balanced, so the parse is skipped on the way through.\n */\nexport function jsonLooksComplete(text: string): boolean {\n if (!/[}\\]]\\s*$/.test(text)) return false;\n let depth = 0;\n let inString = false;\n for (let i = 0; i < text.length; i++) {\n const c = text.charCodeAt(i);\n if (inString) {\n if (c === 92 /* \\\\ */) i += 1;\n else if (c === 34 /* \" */) inString = false;\n } else if (c === 34) {\n inString = true;\n } else if (c === 123 || c === 91) {\n depth += 1;\n } else if (c === 125 || c === 93) {\n depth -= 1;\n if (depth < 0) return false;\n }\n }\n return depth === 0 && !inString;\n}\n\n/**\n * Code languages that receive specialized rendering instead of standard\n * syntax-highlighted code blocks. Adding a new member here automatically\n * marks that language as \"special\" — you only need to add the corresponding\n * rendering branch in the component's return.\n */\nenum SpecialCodeLanguage {\n /** Rendered as interactive diagrams via {@link MantineAIMMermaidCode} */\n Mermaid = 'mermaid',\n}\n\n/** O(1) lookup set, derived from {@link SpecialCodeLanguage}. */\nconst SPECIAL_LANGUAGES = new Set<string>(Object.values(SpecialCodeLanguage));\n\n/**\n * Mantine code block renderer for `<pre>` elements.\n *\n * Replaces the default `<pre>` rendering with Mantine's {@link CodeHighlight} or\n * {@link CodeHighlightTabs} components, providing syntax highlighting, expand/collapse\n * behavior, and file-name tabs.\n *\n * Behavior:\n * - If the code block has an explicit language annotation, uses that language.\n * - If no language is specified and the `codeBlock` group's\n * `autoDetectUnknownLanguage` option is enabled, uses `highlight.js`\n * auto-detection.\n * - Mermaid code blocks (`language-mermaid`) are rendered as interactive diagrams\n * via {@link MantineAIMMermaidCode}.\n * - JSON code blocks are deep-parsed and pretty-printed before display.\n * - Unrecognized languages render as plaintext with an \"unknown\" label using\n * {@link CodeHighlight} (no tabs).\n * - Recognized languages render with {@link CodeHighlightTabs} showing the\n * language name as the tab label.\n *\n * @param props.codeText - The raw text content of the code block.\n * @param props.existLanguage - Language identifier extracted from the `language-*` CSS class, if present.\n */\nconst MantineAIMPreCode = memo(\n (\n props: HTMLAttributes<HTMLPreElement> & {\n codeText: string;\n existLanguage?: string;\n }\n ) => {\n const { fontSize } = useAIMarkdownTheme();\n const { streaming } = useAIMarkdownState();\n const { autoDetectUnknownLanguage, defaultExpanded } = useMantineCodeBlockOptions();\n\n const detectedLanguage = useAutoDetectedLanguage(\n props.codeText,\n autoDetectUnknownLanguage && !props.existLanguage,\n streaming\n );\n // Lower-cased once for every decision below: fence languages arrive in\n // whatever case the model wrote (` ```Mermaid `, ` ```JSON `), and both\n // the special-language switch and the JSON branch must agree\n // (2026-08 project review, pkg-small-08 — the mermaid check was\n // case-sensitive while the JSON check was not).\n const codeLanguage = (props.existLanguage || detectedLanguage).toLowerCase();\n\n // The language is passed straight to Mantine's highlighter, whose\n // adapter already degrades unknown languages to plaintext; the label\n // is \"unknown\" only when there is no language at all.\n const [usedCodeLanguage, usedFileName] = useMemo(\n () => (codeLanguage ? [codeLanguage, codeLanguage] : ['plaintext', 'unknown']),\n [codeLanguage]\n );\n\n const isSpecialCodeBlock = SPECIAL_LANGUAGES.has(codeLanguage);\n\n const normalCodeBlockContent = useMemo(() => {\n if (isSpecialCodeBlock) return null;\n let usedCodeStr = props.codeText;\n // JSON pretty-print as soon as the block LOOKS complete: a streamed\n // prefix never parses, so trying deepParseJson on every chunk of a\n // growing block was O(n²) work for nothing (pkg-small-06) — but a\n // block that finished mid-document must not wait for the whole\n // message to end. \"Ends with a closing bracket\" alone was not enough\n // of a tell: pretty-printed JSON (the common LLM shape) ends a chunk\n // on `}` / `]` at almost every nesting level, so the parse still ran\n // on nearly every chunk (v2.4.1 review). Only a BALANCED bracket\n // scan (strings skipped, one linear pass) admits the parse.\n if (usedCodeStr && usedCodeLanguage === 'json' && (!streaming || jsonLooksComplete(usedCodeStr))) {\n const deepParsedResult = deepParseJson(usedCodeStr);\n usedCodeStr =\n typeof deepParsedResult === 'string' ? deepParsedResult : JSON.stringify(deepParsedResult, null, 2);\n }\n return usedFileName === 'unknown' ? (\n <CodeHighlight\n mb={15}\n fz={fontSize}\n w=\"100%\"\n code={usedCodeStr}\n withBorder\n withExpandButton\n defaultExpanded={defaultExpanded}\n maxCollapsedHeight=\"320px\"\n />\n ) : (\n <CodeHighlightTabs\n mb={15}\n fz={fontSize}\n w=\"100%\"\n code={[\n {\n fileName: usedFileName,\n code: usedCodeStr,\n language: usedCodeLanguage,\n },\n ]}\n withBorder\n withExpandButton\n defaultExpanded={defaultExpanded}\n maxCollapsedHeight=\"320px\"\n />\n );\n }, [isSpecialCodeBlock, props.codeText, usedCodeLanguage, usedFileName, fontSize, defaultExpanded, streaming]);\n\n const specialCodeBlockContent = useMemo(() => {\n switch (codeLanguage) {\n case SpecialCodeLanguage.Mermaid:\n return <MantineAIMMermaidCode code={props.codeText} />;\n default:\n return null;\n }\n }, [codeLanguage, props.codeText]);\n\n return isSpecialCodeBlock ? specialCodeBlockContent : normalCodeBlockContent;\n }\n);\n\nMantineAIMPreCode.displayName = 'MantineAIMPreCode';\n\nexport default MantineAIMPreCode;\n","/**\n * Narrow hook for the mantine `codeBlock` behavior group.\n *\n * This is THE single type-assertion site for the group (the pattern that\n * retires the public caller-asserted `TConfig` generic): the opaque\n * extension record from `useAIMarkdownBehaviors()` is narrowed here, and\n * group defaults are applied here — read sites must consume this hook and\n * never re-apply defaults with bare `??` (multiple read sites duplicating\n * defaults will drift).\n *\n * @module hooks/useMantineCodeBlockOptions\n */\n\nimport { useMemo } from 'react';\nimport { useAIMarkdownBehaviors } from '@ai-react-markdown/core';\nimport { defaultMantineCodeBlockOptions, type MantineCodeBlockOptions } from '../defs';\n\n/**\n * Read the resolved code-block options from the behaviors context.\n *\n * Group values replace atomically at the transport layer; defaults are\n * filled in here, so a partial group (e.g. `codeBlock={{ defaultExpanded:\n * false }}`) resolves the omitted fields to the shipped defaults.\n *\n * Must be called inside a `<MantineAIMarkdown>` (or any `<AIMarkdown>`\n * wrapped in the mantine Provider stack) — throws outside, same contract\n * as the core narrow hooks.\n */\nexport function useMantineCodeBlockOptions(): Required<MantineCodeBlockOptions> {\n const behaviors = useAIMarkdownBehaviors();\n // The single assertion: the `codeBlock` group key is owned by this\n // package, contributed by `MantineAIMarkdown` via its behaviors Provider.\n const group = behaviors.codeBlock as Partial<MantineCodeBlockOptions> | undefined;\n return useMemo(() => {\n // Field-wise `??` rather than a spread: `codeBlock={{ defaultExpanded:\n // undefined }}` type-checks, and a spread would let that explicit\n // undefined punch through the default while the signature promises\n // `Required<…>` (2026-08 project review, pkg-small-12).\n const resolved = { ...defaultMantineCodeBlockOptions } as Required<MantineCodeBlockOptions>;\n for (const key of Object.keys(defaultMantineCodeBlockOptions) as Array<keyof MantineCodeBlockOptions>) {\n const value = group?.[key];\n if (value !== undefined) (resolved as Record<string, unknown>)[key] = value;\n }\n return resolved;\n }, [group]);\n}\n","/**\n * Mantine-specific type definitions and defaults: the `codeBlock` behavior\n * group and the metadata extension point.\n *\n * @module defs\n */\n\nimport { AIMarkdownMetadata } from '@ai-react-markdown/core';\n\n/**\n * Code block rendering options (the mantine `codeBlock` behavior group).\n *\n * v2 transport: passed as the flat `codeBlock` prop on `MantineAIMarkdown`\n * (group value replaces atomically) and read through\n * `useMantineCodeBlockOptions()`, which applies the defaults below inside\n * the hook — the single place defaults live at read time.\n */\nexport interface MantineCodeBlockOptions {\n /**\n * Whether code blocks start in their expanded state.\n * When `false`, long code blocks are collapsed with an expand button.\n *\n * @default true\n */\n defaultExpanded: boolean;\n\n /**\n * When `true`, uses `highlight.js` auto-detection to determine the language\n * of code blocks that lack an explicit language annotation.\n *\n * @default false\n */\n autoDetectUnknownLanguage: boolean;\n}\n\n/** Shipped defaults for the `codeBlock` behavior group. */\nexport const defaultMantineCodeBlockOptions: Readonly<MantineCodeBlockOptions> = Object.freeze({\n defaultExpanded: true,\n autoDetectUnknownLanguage: false,\n});\n\n/**\n * Metadata type for the Mantine integration.\n *\n * Currently identical to {@link AIMarkdownMetadata}. Exists as an extension point\n * so that consumers can augment metadata in Mantine-specific wrappers without\n * needing to reference the core type directly.\n */\nexport interface MantineAIMarkdownMetadata extends AIMarkdownMetadata {}\n","'use client';\n\nimport React, { memo, useEffect, useRef, useState, useCallback } from 'react';\nimport { CodeHighlightControl, CodeHighlightTabs } from '@mantine/code-highlight';\nimport { ActionIcon, CopyButton, Flex, Tooltip } from '@mantine/core';\nimport type mermaidModule from 'mermaid';\nimport { useAIMarkdownState, useAIMarkdownTheme } from '@ai-react-markdown/core';\nimport { useMantineCodeBlockOptions } from '../../../hooks/useMantineCodeBlockOptions';\nimport './styles.scss';\n\n/** Static `<pre>` style for the mermaid container. */\nconst PRE_STYLE = { cursor: 'pointer', overflow: 'auto', width: '100%', padding: '0.5rem' } as const;\n\n/**\n * What the component currently shows. One value instead of separate\n * `hasRendered`/`renderError`/`chartType` fields whose combinations had to\n * be kept coherent by hand:\n * - `source`: warm-up / SSR fallback — raw code as a plain code block\n * (nothing rendered yet this generation).\n * - `diagram`: the last successful SVG is up.\n * - `error`: the error tab — only a post-stream corrective failure or a\n * never-rendered static failure can enter this state.\n *\n * The user's source toggle (`showOriginalCode`) is deliberately NOT a\n * phase: it overlays any view and flipping it back must restore the prior\n * one unchanged.\n */\ntype MermaidView = { kind: 'source' } | { kind: 'diagram'; chartType: string } | { kind: 'error' };\n\n/** Equality used to skip no-op view updates — repeat mid-stream successes\n * of the same chart type must not re-render the host per chunk. */\nconst sameView = (a: MermaidView, b: MermaidView): boolean =>\n a.kind === 'diagram' && b.kind === 'diagram' ? a.chartType === b.chartType : a.kind === b.kind;\n\ntype Mermaid = typeof mermaidModule;\n\n/**\n * mermaid is loaded on demand — the FIRST diagram that actually renders\n * pays the import; an app whose content never contains a mermaid fence\n * never downloads the ~1.5 MB module (2026-08 project review,\n * pkg-small-03: the static import sat on the default `pre` component's\n * import chain, so every consumer's main bundle carried it). The promise is\n * cached module-wide; the source-view warm-up covers the loading window.\n */\nlet mermaidPromise: Promise<Mermaid> | null = null;\n/** Bounded automatic retries of a failed mermaid module download. */\nconst MERMAID_LOAD_RETRIES = 3;\nconst MERMAID_LOAD_RETRY_MS = 1500;\nconst loadMermaid = (): Promise<Mermaid> => {\n // A rejected load is not cached — the next render attempt retries.\n mermaidPromise ??= import('mermaid').then(\n (m) => m.default,\n (err: unknown) => {\n mermaidPromise = null;\n throw err;\n }\n );\n return mermaidPromise;\n};\n\n/** Theme mermaid.initialize was last called with. mermaid's config is a\n * module-level singleton, so re-asserting an unchanged theme before every\n * render attempt (each streamed chunk re-runs the effect) is pure waste —\n * but instances under providers with DIFFERENT schemes must each\n * re-assert before their own render, so the cache is module-level and\n * checked per attempt rather than hoisted into a per-instance effect. */\nlet initializedTheme: 'dark' | 'light' | null = null;\n\n/**\n * PREMISE (documented, not enforced — v2.4.2 review P3-3): mermaid's config\n * is a module-level singleton shared with the host application when the\n * bundler dedupes the package. This renderer asserts `securityLevel:\n * 'strict'` whenever it (re)initializes for a theme; a host that calls\n * `mermaid.initialize({ securityLevel: 'loose' })` in between runs the\n * next diagram under its own setting until the next theme flip here.\n * Re-asserting on every streamed chunk would re-run mermaid's config merge\n * per frame; hosts sharing the instance should keep it strict themselves.\n */\nconst ensureMermaidInitialized = (mermaid: Mermaid, isDark: boolean) => {\n const theme = isDark ? 'dark' : 'light';\n if (initializedTheme === theme) return;\n mermaid.initialize({\n startOnLoad: false,\n securityLevel: 'strict',\n theme: isDark ? 'dark' : 'base',\n darkMode: isDark,\n // Without a svgContainingElement, a draw-phase throw (an error that\n // got past mermaid.parse) leaves mermaid's temp element orphaned in\n // document.body — its error path only cleans up when this flag is\n // set. We render our own error tab anyway, so mermaid's built-in\n // error diagram is dead weight here regardless.\n suppressErrorRendering: true,\n });\n initializedTheme = theme;\n};\n\n/**\n * Generate a unique ID for mermaid SVG rendering.\n * Combines a timestamp with a random suffix to avoid collisions when\n * multiple mermaid diagrams render concurrently.\n *\n * @returns A unique string in the format `mermaid-{timestamp}-{random}`.\n */\nconst generateMermaidUUID = () => {\n return `mermaid-${new Date().getTime()}-${Math.random().toString(36).slice(2, 10)}`;\n};\n\n/**\n * Open the rendered mermaid SVG in a new browser window.\n *\n * Clones the SVG element, applies a background color matching the current\n * color scheme, serializes it to an object URL, and opens it in a new tab.\n * The object URL is revoked after a short delay to free memory.\n *\n * @param svgElement - The rendered SVG element to view, or `null`/`undefined` to no-op.\n * @param isDark - Whether the current color scheme is dark (used for background color).\n */\nconst handleViewSVGInNewWindow = (svgElement: SVGElement | null | undefined, isDark: boolean) => {\n if (!svgElement) return;\n const targetSvg = svgElement.cloneNode(true) as SVGElement;\n targetSvg.style.backgroundColor = isDark ? '#242424' : 'white';\n const text = new XMLSerializer().serializeToString(targetSvg);\n const blob = new Blob([text], { type: 'image/svg+xml' });\n const url = URL.createObjectURL(blob);\n // `noopener`: the blob URL is same-origin and opens as a top-level SVG\n // document; under mermaid's default strict securityLevel it is DOMPurify\n // output, but a host that flips the shared singleton to 'loose' (see the\n // module note above) would hand that document a live `opener` — cut it\n // (2026-08-19 review). Costs nothing in the strict case.\n window.open(url, '_blank', 'noopener');\n // Revoke either way (a blocked popup would otherwise leak the Blob until\n // page unload — 2026-08 project review, pkg-small-09). With `noopener`\n // `window.open` returns null even on success, so the blocked case cannot\n // be told apart any more: always give the opened document the grace\n // period to finish loading before the URL goes away.\n setTimeout(() => URL.revokeObjectURL(url), 5000);\n};\n\n/**\n * Interactive mermaid diagram renderer.\n *\n * Parses and renders mermaid diagram source code into an inline SVG visualization.\n * Automatically adapts to the current Mantine color scheme (light/dark) by\n * re-initializing mermaid with the appropriate theme.\n *\n * Features:\n * - Live SVG rendering with automatic dark/light theme switching\n * - Fallback to raw source code display on parse/render errors\n * - Toggle between rendered diagram and raw mermaid source\n * - Click on the rendered diagram to open the SVG in a new browser window\n * - Copy button for the raw mermaid source code\n * - Chart type label extracted from mermaid's parse result\n * - Preserves the last successful render across transient parse failures\n *\n * ## Streaming contract\n *\n * While `streaming` is true (from render state), the code prop is usually a\n * truncated prefix of the final diagram, so parse failures are *expected*,\n * not exceptional:\n * - Before the first successful render, the raw source is shown as a plain\n * code block (never the error tab).\n * - After a success, the last good SVG stays up; each subsequent chunk is\n * re-attempted and the diagram refreshes only on the next success.\n * - When streaming ends (`streaming` is an effect dep), one corrective pass\n * runs on the final code: success refreshes the diagram, failure surfaces\n * the real error tab — even over a previously rendered mid-stream diagram,\n * because that diagram no longer matches the final source. The pending\n * corrective obligation is tracked by `needsCorrectiveRef` (armed on the\n * streaming→false edge, consumed by the next completed attempt), so ONLY\n * that one pass may clobber a rendered diagram; any later failure (e.g. a\n * transient throw on a theme-flip re-render) falls back to the static rule\n * below.\n * - A streaming→true edge marks a NEW generation (chat \"regenerate\" reuses\n * the same component instance when the block's source offset — and thus\n * its React key — is unchanged). All per-generation state is reset so the\n * warm-up shows the new source instead of the previous generation's stale\n * diagram or error tab.\n *\n * ## Static contract (`streaming` stays false)\n *\n * Without streaming edges, failures follow the original conservative rule:\n * the error tab shows only while nothing has rendered yet. Once a diagram is\n * up, later failures (theme-flip re-render, a not-yet-complete `code` update\n * from a consumer that didn't pass `streaming`) keep the last good diagram\n * instead of clobbering it with an error.\n *\n * @param props.code - Raw mermaid diagram source code to render.\n */\nconst MantineAIMMermaidCode = memo((props: { code: string }) => {\n const { colorScheme, fontSize } = useAIMarkdownTheme();\n const { streaming } = useAIMarkdownState();\n const { defaultExpanded } = useMantineCodeBlockOptions();\n const isDark = colorScheme === 'dark';\n\n const ref = useRef<HTMLPreElement>(null);\n const renderVersionRef = useRef(0);\n /** Mirrors `view` for reads inside the async render closure — state reads\n * there can be stale when deps change mid-flight. */\n const viewRef = useRef<MermaidView>({ kind: 'source' });\n /** Previous `streaming` value, for edge detection in the effect. */\n const prevStreamingRef = useRef(false);\n /** Armed on the streaming→false edge: the next completed render attempt is\n * the end-of-stream corrective pass, whose failure must surface even over\n * a rendered diagram. Consumed (reset) by that attempt's success OR\n * surfaced failure, so later unrelated failures can't clobber the SVG. */\n const needsCorrectiveRef = useRef(false);\n /** Inputs of the render whose SVG currently sits in the host `<pre>`.\n * When the effect re-runs with the same (code, theme) pair — the\n * post-stream corrective flip on an already-final diagram, or returning\n * from the source view — the DOM already holds that exact render, so\n * the attempt (and its parse + temp-element render) is skipped. */\n const lastSuccessRef = useRef<{ code: string; isDark: boolean } | null>(null);\n const [view, setViewState] = useState<MermaidView>({ kind: 'source' });\n const [showOriginalCode, setShowOriginalCode] = useState(false);\n /** Bumped (after a short delay) when the mermaid MODULE failed to load, so\n * the effect re-runs on otherwise unchanged inputs and retries the\n * download. A download failure is not a diagram error: it must neither\n * consume the corrective obligation nor show the error tab (v2.4.1\n * review — the corrective pass is one-shot, so a transient network\n * failure on it left a permanent \"Render Error\" that nothing re-tried).\n * Bounded by MERMAID_LOAD_RETRIES per generation. */\n const [loadAttempt, setLoadAttempt] = useState(0);\n const loadFailuresRef = useRef(0);\n\n useEffect(() => {\n // View updates funnel through here so the ref mirror can't desync from\n // the state, and no-op updates are dropped (repeat mid-stream successes\n // and idempotent edge resets must not re-render the host per chunk).\n const applyView = (next: MermaidView) => {\n viewRef.current = next;\n setViewState((prev) => (sameView(prev, next) ? prev : next));\n };\n\n // Streaming edge detection MUST run before any early return — the first\n // chunk of a new stream can arrive while the code is still empty.\n if (streaming && !prevStreamingRef.current) {\n // Rising edge = a new generation is starting on this same instance\n // (same block offset → same React key → no remount on regenerate).\n // Reset all per-generation state so warm-up shows the incoming source,\n // not the previous generation's stale diagram or error tab. Everything\n // here is idempotent — a StrictMode double-run is harmless.\n needsCorrectiveRef.current = false;\n lastSuccessRef.current = null;\n loadFailuresRef.current = 0;\n applyView({ kind: 'source' });\n if (ref.current) {\n ref.current.innerHTML = '';\n }\n } else if (!streaming && prevStreamingRef.current) {\n // Falling edge = the stream just ended; arm the corrective pass.\n needsCorrectiveRef.current = true;\n }\n prevStreamingRef.current = streaming;\n if (!props.code || !ref.current || showOriginalCode) {\n return;\n }\n\n // The SVG in the DOM already came from exactly this (code, theme) pair —\n // nothing to recompute. This also SATISFIES a pending corrective\n // obligation: the identical successful render IS the verdict on the\n // final source, so the obligation is consumed, not left armed for some\n // later unrelated failure to inherit.\n if (lastSuccessRef.current?.code === props.code && lastSuccessRef.current.isDark === isDark) {\n needsCorrectiveRef.current = false;\n return;\n }\n\n const renderVersion = ++renderVersionRef.current;\n let cancelled = false;\n\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n const renderMermaid = async () => {\n let mermaid: Mermaid;\n try {\n mermaid = await loadMermaid();\n } catch {\n // Module load failed: keep whatever is showing (source view or the\n // last diagram), leave the corrective obligation armed, and retry\n // the download a bounded number of times.\n if (cancelled || renderVersion !== renderVersionRef.current) return;\n if (loadFailuresRef.current < MERMAID_LOAD_RETRIES) {\n loadFailuresRef.current += 1;\n retryTimer = setTimeout(() => setLoadAttempt((n) => n + 1), MERMAID_LOAD_RETRY_MS);\n }\n return;\n }\n loadFailuresRef.current = 0;\n try {\n if (!ref.current || cancelled || renderVersion !== renderVersionRef.current) {\n return;\n }\n ensureMermaidInitialized(mermaid, isDark);\n const parseResult = await mermaid.parse(props.code);\n if (!parseResult) {\n throw new Error('Failed to parse mermaid code');\n }\n\n if (!ref.current || cancelled || renderVersion !== renderVersionRef.current) {\n return;\n }\n\n // Deliberately NOT passing `ref.current` as mermaid's\n // svgContainingElement: before the first success the host container\n // is hidden with `display: none` (source fallback is showing), and\n // mermaid measures text via getBBox during render — inside a\n // display:none subtree layout never runs, every measurement is 0,\n // and the diagram comes out as a ~16px SVG. With the argument\n // omitted, mermaid renders in a temp element appended to\n // `document.body` (its default path, cleaned up internally), so\n // measurement works no matter what our container is doing. The SVG\n // string is written into our own <pre> below either way.\n // mermaid's config is a module singleton and the awaits above yield:\n // an instance under the OTHER color scheme may have re-initialized\n // in between, in which case this render came out in the wrong theme.\n // Re-assert and render once more; a second flip is vanishingly\n // unlikely and would self-heal on the next attempt anyway\n // (2026-08 project review, pkg-small-11).\n let rendered = await mermaid.render(generateMermaidUUID(), props.code);\n if (initializedTheme !== (isDark ? 'dark' : 'light')) {\n if (!ref.current || cancelled || renderVersion !== renderVersionRef.current) {\n return;\n }\n ensureMermaidInitialized(mermaid, isDark);\n rendered = await mermaid.render(generateMermaidUUID(), props.code);\n }\n const { svg, bindFunctions, diagramType } = rendered;\n if (!ref.current || cancelled || renderVersion !== renderVersionRef.current) {\n return;\n }\n\n ref.current.innerHTML = svg;\n bindFunctions?.(ref.current);\n needsCorrectiveRef.current = false;\n lastSuccessRef.current = { code: props.code, isDark };\n applyView({ kind: 'diagram', chartType: diagramType });\n } catch {\n if (cancelled || renderVersion !== renderVersionRef.current) {\n return;\n }\n // Mid-stream failures are expected (truncated code) — keep the last\n // good diagram / source placeholder and wait for more bytes. The\n // corrective pass after streaming ends reports real errors.\n if (streaming) {\n return;\n }\n // End-of-stream corrective pass: the final source no longer renders,\n // so the error must surface even over a mid-stream diagram. Consume\n // the obligation so later unrelated failures don't inherit it.\n if (needsCorrectiveRef.current) {\n needsCorrectiveRef.current = false;\n applyView({ kind: 'error' });\n return;\n }\n // Static rule: never clobber a rendered diagram (theme-flip\n // re-renders, un-flagged code updates from static consumers).\n if (viewRef.current.kind === 'diagram') {\n return;\n }\n applyView({ kind: 'error' });\n }\n };\n\n void renderMermaid();\n\n return () => {\n cancelled = true;\n if (retryTimer !== undefined) clearTimeout(retryTimer);\n };\n // `streaming` in the deps is what drives the end-of-stream corrective\n // pass: the flip to false re-runs this effect on the (unchanged) final\n // code, so the last state reflects the full diagram source.\n // `loadAttempt` re-runs it after a failed module download.\n }, [props.code, isDark, showOriginalCode, streaming, loadAttempt]);\n\n const viewSvgInNewWindow = useCallback(() => {\n handleViewSVGInNewWindow(ref.current?.querySelector('svg'), isDark);\n }, [isDark]);\n\n // Show the raw source instead of the diagram container when the user asked\n // for it, when the (post-stream) render failed, or before the first\n // successful render (SSR output and the streaming warm-up phase). The\n // diagram container below stays MOUNTED throughout — merely hidden — so\n // `ref` is always available for mermaid to render into; unmounting it would\n // make the effect's `!ref.current` guard bail forever.\n const showSourceFallback = showOriginalCode || view.kind !== 'diagram';\n\n return (\n <>\n {showSourceFallback && (\n <CodeHighlightTabs\n mb={15}\n fz={fontSize}\n w=\"100%\"\n code={[\n {\n fileName: view.kind === 'error' ? 'Mermaid Render Error' : 'mermaid',\n code: props.code,\n language: 'mermaid',\n },\n ]}\n defaultExpanded={defaultExpanded}\n maxCollapsedHeight=\"320px\"\n styles={{\n filesScrollarea: {\n right: '90px',\n },\n }}\n controls={\n // The \"Render Mermaid\" control only makes sense as the way back\n // from the user-toggled source view. In the error and warm-up\n // fallbacks `showOriginalCode` is already false, so the control\n // would be a no-op — hide it there. (No view-kind conjunct: the\n // toggle is only reachable from the visible diagram view, and\n // while the source view is open the effect early-returns, so\n // showOriginalCode && view.kind === 'error' is unreachable.)\n showOriginalCode\n ? [\n <CodeHighlightControl\n tooltipLabel=\"Render Mermaid\"\n key=\"gpt\"\n onClick={() => {\n setShowOriginalCode(false);\n }}\n >\n <Flex align=\"center\" justify=\"center\" w={18} h={18}>\n <span className=\"icon-[gravity-ui--logo-mermaid] relative bottom-[1px] text-[16px]\"></span>\n </Flex>\n </CodeHighlightControl>,\n ]\n : []\n }\n withBorder\n withExpandButton\n />\n )}\n <div\n className={`aim-mantine-mermaid-code ${isDark ? 'dark' : ''}`}\n style={\n showSourceFallback\n ? {\n display: 'none',\n }\n : {}\n }\n >\n <div className=\"chart-header\">\n <div className=\"chart-type-tag\">{view.kind === 'diagram' ? view.chartType : 'unknown'}</div>\n <Flex align=\"center\" justify=\"flex-end\" gap={0}>\n <Tooltip label=\"Show Mermaid Code\">\n <ActionIcon\n size={28}\n className=\"action-icon\"\n variant=\"transparent\"\n aria-label=\"Show Mermaid code\"\n onClick={() => {\n setShowOriginalCode(true);\n }}\n >\n <Flex align=\"center\" justify=\"center\" w={18} h={18}>\n <span className=\"icon-[entypo--code] relative bottom-[0.25px] text-[16px]\"></span>\n </Flex>\n </ActionIcon>\n </Tooltip>\n <CopyButton value={props.code}>\n {({ copied, copy }) => (\n <Tooltip label={copied ? 'Copied' : 'Copy'} withArrow position=\"right\">\n <ActionIcon\n variant=\"transparent\"\n size={28}\n className=\"action-icon\"\n aria-label={copied ? 'Mermaid code copied' : 'Copy Mermaid code'}\n onClick={copy}\n >\n {copied ? (\n <span className=\"icon-origin-[lucide--check] text-[18px]\"></span>\n ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n strokeWidth=\"2\"\n stroke=\"currentColor\"\n fill=\"none\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width=\"18px\"\n height=\"18px\"\n >\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"></path>\n <path d=\"M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z\"></path>\n <path d=\"M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2\"></path>\n </svg>\n )}\n </ActionIcon>\n </Tooltip>\n )}\n </CopyButton>\n </Flex>\n </div>\n <pre\n ref={ref}\n style={PRE_STYLE}\n role=\"button\"\n tabIndex={0}\n aria-label=\"Open Mermaid diagram in a new window\"\n onClick={viewSvgInNewWindow}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n viewSvgInNewWindow();\n }\n }}\n />\n </div>\n </>\n );\n});\n\nMantineAIMMermaidCode.displayName = 'MantineAIMMermaidCode';\n\nexport default MantineAIMMermaidCode;\n","/**\n * Widened `define*` factory for the mantine wrapper (EXECUTION-PLAN §4\n * item 8): identity + mantine prop types + freeze, zero logic. Core\n * factories accept core fields only — passing `codeBlock` to core's\n * `defineBehaviors` is a TS error; this widened factory is the wrapper's\n * one-line obligation.\n *\n * @module define\n */\n\nimport type { AIMarkdownBehaviorProps } from '@ai-react-markdown/core';\nimport type { MantineCodeBlockOptions } from './defs';\n\n/** Behavior-system props packagable at integration time, mantine-widened. */\nexport interface MantineBehaviorProps extends AIMarkdownBehaviorProps {\n /** The mantine `codeBlock` behavior group (atomic replacement; defaults applied at read time). */\n codeBlock?: Partial<MantineCodeBlockOptions>;\n}\n\n// NON-generic on purpose — see core's `define.ts`: a fresh literal is\n// excess-property checked against the concrete parameter type.\n\n/** Freeze a mantine behaviors fragment. Identity + types + freeze; zero logic. */\nexport function defineMantineBehaviors(values: MantineBehaviorProps): Readonly<MantineBehaviorProps> {\n return Object.freeze(values);\n}\n","import { useAIMarkdownMetadata } from '@ai-react-markdown/core';\nimport { MantineAIMarkdownMetadata } from '../defs';\n\n/**\n * Typed wrapper around the core {@link useAIMarkdownMetadata} hook.\n *\n * Returns the current metadata defaulting to {@link MantineAIMarkdownMetadata}.\n * Accepts an optional generic parameter for further extension.\n *\n * Metadata lives in a separate React context from the render state, meaning\n * metadata updates do not trigger re-renders in components that only consume\n * render state.\n *\n * Must be called inside a component rendered within the `<MantineAIMarkdown>` tree.\n *\n * @typeParam TMetadata - Metadata type (defaults to {@link MantineAIMarkdownMetadata}).\n * @returns The current metadata, or `undefined` if none was provided.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const metadata = useMantineAIMarkdownMetadata();\n * // Access Mantine-specific metadata fields\n * }\n * ```\n */\nexport const useMantineAIMarkdownMetadata = <\n TMetadata extends MantineAIMarkdownMetadata = MantineAIMarkdownMetadata,\n>() => {\n return useAIMarkdownMetadata<TMetadata>();\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACaA,IAAAA,gBAA8B;AAC9B,IAAAC,eAAuB;AACvB,IAAAA,eASO;;;ACxBP,mBAAqB;AACrB,kBAA2B;AAgBzB;AADF,IAAM,kCAA8B,mBAAK,CAAC,EAAE,UAAU,UAAU,MAAM,MACpE,4CAAC,0BAAW,GAAE,QAAO,IAAI,UAAU,OAChC,UACH,CACD;AAED,4BAA4B,cAAc;AAE1C,IAAO,4BAAQ;;;ACRN,IAAAC,sBAAA;AADT,IAAM,+BAA+D,CAAC,EAAE,SAAS,MAAM;AACrF,SAAO,6CAAC,SAAI,WAAU,4BAA4B,UAAS;AAC7D;AAEA,IAAO,6BAAQ;;;ACjBf,IAAAC,gBAA2E;AAC3E,IAAAC,yBAAiD;AACjD,6BAA8B;AAC9B,IAAAC,eAAuD;;;ACQvD,IAAAC,gBAAwB;AACxB,IAAAC,eAAuC;;;ACsBhC,IAAM,iCAAoE,OAAO,OAAO;AAAA,EAC7F,iBAAiB;AAAA,EACjB,2BAA2B;AAC7B,CAAC;;;ADXM,SAAS,6BAAgE;AAC9E,QAAM,gBAAY,qCAAuB;AAGzC,QAAM,QAAQ,UAAU;AACxB,aAAO,uBAAQ,MAAM;AAKnB,UAAM,WAAW,EAAE,GAAG,+BAA+B;AACrD,eAAW,OAAO,OAAO,KAAK,8BAA8B,GAA2C;AACrG,YAAM,QAAQ,QAAQ,GAAG;AACzB,UAAI,UAAU,OAAW,CAAC,SAAqC,GAAG,IAAI;AAAA,IACxE;AACA,WAAO;AAAA,EACT,GAAG,CAAC,KAAK,CAAC;AACZ;;;AE3CA,IAAAC,gBAAsE;AACtE,4BAAwD;AACxD,IAAAC,eAAsD;AAEtD,IAAAA,eAAuD;AA6XnD,IAAAC,sBAAA;AAxXJ,IAAM,YAAY,EAAE,QAAQ,WAAW,UAAU,QAAQ,OAAO,QAAQ,SAAS,SAAS;AAoB1F,IAAM,WAAW,CAAC,GAAgB,MAChC,EAAE,SAAS,aAAa,EAAE,SAAS,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE;AAY5F,IAAI,iBAA0C;AAE9C,IAAM,uBAAuB;AAC7B,IAAM,wBAAwB;AAC9B,IAAM,cAAc,MAAwB;AAE1C,qBAAmB,OAAO,SAAS,EAAE;AAAA,IACnC,CAAC,MAAM,EAAE;AAAA,IACT,CAAC,QAAiB;AAChB,uBAAiB;AACjB,YAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO;AACT;AAQA,IAAI,mBAA4C;AAYhD,IAAM,2BAA2B,CAAC,SAAkB,WAAoB;AACtE,QAAM,QAAQ,SAAS,SAAS;AAChC,MAAI,qBAAqB,MAAO;AAChC,UAAQ,WAAW;AAAA,IACjB,aAAa;AAAA,IACb,eAAe;AAAA,IACf,OAAO,SAAS,SAAS;AAAA,IACzB,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMV,wBAAwB;AAAA,EAC1B,CAAC;AACD,qBAAmB;AACrB;AASA,IAAM,sBAAsB,MAAM;AAChC,SAAO,YAAW,oBAAI,KAAK,GAAE,QAAQ,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACnF;AAYA,IAAM,2BAA2B,CAAC,YAA2C,WAAoB;AAC/F,MAAI,CAAC,WAAY;AACjB,QAAM,YAAY,WAAW,UAAU,IAAI;AAC3C,YAAU,MAAM,kBAAkB,SAAS,YAAY;AACvD,QAAM,OAAO,IAAI,cAAc,EAAE,kBAAkB,SAAS;AAC5D,QAAM,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACvD,QAAM,MAAM,IAAI,gBAAgB,IAAI;AAMpC,SAAO,KAAK,KAAK,UAAU,UAAU;AAMrC,aAAW,MAAM,IAAI,gBAAgB,GAAG,GAAG,GAAI;AACjD;AAoDA,IAAM,4BAAwB,oBAAK,CAAC,UAA4B;AAC9D,QAAM,EAAE,aAAa,SAAS,QAAI,iCAAmB;AACrD,QAAM,EAAE,UAAU,QAAI,iCAAmB;AACzC,QAAM,EAAE,gBAAgB,IAAI,2BAA2B;AACvD,QAAM,SAAS,gBAAgB;AAE/B,QAAM,UAAM,sBAAuB,IAAI;AACvC,QAAM,uBAAmB,sBAAO,CAAC;AAGjC,QAAM,cAAU,sBAAoB,EAAE,MAAM,SAAS,CAAC;AAEtD,QAAM,uBAAmB,sBAAO,KAAK;AAKrC,QAAM,yBAAqB,sBAAO,KAAK;AAMvC,QAAM,qBAAiB,sBAAiD,IAAI;AAC5E,QAAM,CAAC,MAAM,YAAY,QAAI,wBAAsB,EAAE,MAAM,SAAS,CAAC;AACrE,QAAM,CAAC,kBAAkB,mBAAmB,QAAI,wBAAS,KAAK;AAQ9D,QAAM,CAAC,aAAa,cAAc,QAAI,wBAAS,CAAC;AAChD,QAAM,sBAAkB,sBAAO,CAAC;AAEhC,+BAAU,MAAM;AAId,UAAM,YAAY,CAAC,SAAsB;AACvC,cAAQ,UAAU;AAClB,mBAAa,CAAC,SAAU,SAAS,MAAM,IAAI,IAAI,OAAO,IAAK;AAAA,IAC7D;AAIA,QAAI,aAAa,CAAC,iBAAiB,SAAS;AAM1C,yBAAmB,UAAU;AAC7B,qBAAe,UAAU;AACzB,sBAAgB,UAAU;AAC1B,gBAAU,EAAE,MAAM,SAAS,CAAC;AAC5B,UAAI,IAAI,SAAS;AACf,YAAI,QAAQ,YAAY;AAAA,MAC1B;AAAA,IACF,WAAW,CAAC,aAAa,iBAAiB,SAAS;AAEjD,yBAAmB,UAAU;AAAA,IAC/B;AACA,qBAAiB,UAAU;AAC3B,QAAI,CAAC,MAAM,QAAQ,CAAC,IAAI,WAAW,kBAAkB;AACnD;AAAA,IACF;AAOA,QAAI,eAAe,SAAS,SAAS,MAAM,QAAQ,eAAe,QAAQ,WAAW,QAAQ;AAC3F,yBAAmB,UAAU;AAC7B;AAAA,IACF;AAEA,UAAM,gBAAgB,EAAE,iBAAiB;AACzC,QAAI,YAAY;AAEhB,QAAI;AACJ,UAAM,gBAAgB,YAAY;AAChC,UAAI;AACJ,UAAI;AACF,kBAAU,MAAM,YAAY;AAAA,MAC9B,QAAQ;AAIN,YAAI,aAAa,kBAAkB,iBAAiB,QAAS;AAC7D,YAAI,gBAAgB,UAAU,sBAAsB;AAClD,0BAAgB,WAAW;AAC3B,uBAAa,WAAW,MAAM,eAAe,CAAC,MAAM,IAAI,CAAC,GAAG,qBAAqB;AAAA,QACnF;AACA;AAAA,MACF;AACA,sBAAgB,UAAU;AAC1B,UAAI;AACF,YAAI,CAAC,IAAI,WAAW,aAAa,kBAAkB,iBAAiB,SAAS;AAC3E;AAAA,QACF;AACA,iCAAyB,SAAS,MAAM;AACxC,cAAM,cAAc,MAAM,QAAQ,MAAM,MAAM,IAAI;AAClD,YAAI,CAAC,aAAa;AAChB,gBAAM,IAAI,MAAM,8BAA8B;AAAA,QAChD;AAEA,YAAI,CAAC,IAAI,WAAW,aAAa,kBAAkB,iBAAiB,SAAS;AAC3E;AAAA,QACF;AAkBA,YAAI,WAAW,MAAM,QAAQ,OAAO,oBAAoB,GAAG,MAAM,IAAI;AACrE,YAAI,sBAAsB,SAAS,SAAS,UAAU;AACpD,cAAI,CAAC,IAAI,WAAW,aAAa,kBAAkB,iBAAiB,SAAS;AAC3E;AAAA,UACF;AACA,mCAAyB,SAAS,MAAM;AACxC,qBAAW,MAAM,QAAQ,OAAO,oBAAoB,GAAG,MAAM,IAAI;AAAA,QACnE;AACA,cAAM,EAAE,KAAK,eAAe,YAAY,IAAI;AAC5C,YAAI,CAAC,IAAI,WAAW,aAAa,kBAAkB,iBAAiB,SAAS;AAC3E;AAAA,QACF;AAEA,YAAI,QAAQ,YAAY;AACxB,wBAAgB,IAAI,OAAO;AAC3B,2BAAmB,UAAU;AAC7B,uBAAe,UAAU,EAAE,MAAM,MAAM,MAAM,OAAO;AACpD,kBAAU,EAAE,MAAM,WAAW,WAAW,YAAY,CAAC;AAAA,MACvD,QAAQ;AACN,YAAI,aAAa,kBAAkB,iBAAiB,SAAS;AAC3D;AAAA,QACF;AAIA,YAAI,WAAW;AACb;AAAA,QACF;AAIA,YAAI,mBAAmB,SAAS;AAC9B,6BAAmB,UAAU;AAC7B,oBAAU,EAAE,MAAM,QAAQ,CAAC;AAC3B;AAAA,QACF;AAGA,YAAI,QAAQ,QAAQ,SAAS,WAAW;AACtC;AAAA,QACF;AACA,kBAAU,EAAE,MAAM,QAAQ,CAAC;AAAA,MAC7B;AAAA,IACF;AAEA,SAAK,cAAc;AAEnB,WAAO,MAAM;AACX,kBAAY;AACZ,UAAI,eAAe,OAAW,cAAa,UAAU;AAAA,IACvD;AAAA,EAKF,GAAG,CAAC,MAAM,MAAM,QAAQ,kBAAkB,WAAW,WAAW,CAAC;AAEjE,QAAM,yBAAqB,2BAAY,MAAM;AAC3C,6BAAyB,IAAI,SAAS,cAAc,KAAK,GAAG,MAAM;AAAA,EACpE,GAAG,CAAC,MAAM,CAAC;AAQX,QAAM,qBAAqB,oBAAoB,KAAK,SAAS;AAE7D,SACE,8EACG;AAAA,0BACC;AAAA,MAAC;AAAA;AAAA,QACC,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,GAAE;AAAA,QACF,MAAM;AAAA,UACJ;AAAA,YACE,UAAU,KAAK,SAAS,UAAU,yBAAyB;AAAA,YAC3D,MAAM,MAAM;AAAA,YACZ,UAAU;AAAA,UACZ;AAAA,QACF;AAAA,QACA;AAAA,QACA,oBAAmB;AAAA,QACnB,QAAQ;AAAA,UACN,iBAAiB;AAAA,YACf,OAAO;AAAA,UACT;AAAA,QACF;AAAA,QACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAQE,mBACI;AAAA,YACE;AAAA,cAAC;AAAA;AAAA,gBACC,cAAa;AAAA,gBAEb,SAAS,MAAM;AACb,sCAAoB,KAAK;AAAA,gBAC3B;AAAA,gBAEA,uDAAC,qBAAK,OAAM,UAAS,SAAQ,UAAS,GAAG,IAAI,GAAG,IAC9C,uDAAC,UAAK,WAAU,qEAAoE,GACtF;AAAA;AAAA,cAPI;AAAA,YAQN;AAAA,UACF,IACA,CAAC;AAAA;AAAA,QAEP,YAAU;AAAA,QACV,kBAAgB;AAAA;AAAA,IAClB;AAAA,IAEF;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,4BAA4B,SAAS,SAAS,EAAE;AAAA,QAC3D,OACE,qBACI;AAAA,UACE,SAAS;AAAA,QACX,IACA,CAAC;AAAA,QAGP;AAAA,wDAAC,SAAI,WAAU,gBACb;AAAA,yDAAC,SAAI,WAAU,kBAAkB,eAAK,SAAS,YAAY,KAAK,YAAY,WAAU;AAAA,YACtF,8CAAC,qBAAK,OAAM,UAAS,SAAQ,YAAW,KAAK,GAC3C;AAAA,2DAAC,wBAAQ,OAAM,qBACb;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAM;AAAA,kBACN,WAAU;AAAA,kBACV,SAAQ;AAAA,kBACR,cAAW;AAAA,kBACX,SAAS,MAAM;AACb,wCAAoB,IAAI;AAAA,kBAC1B;AAAA,kBAEA,uDAAC,qBAAK,OAAM,UAAS,SAAQ,UAAS,GAAG,IAAI,GAAG,IAC9C,uDAAC,UAAK,WAAU,4DAA2D,GAC7E;AAAA;AAAA,cACF,GACF;AAAA,cACA,6CAAC,2BAAW,OAAO,MAAM,MACtB,WAAC,EAAE,QAAQ,KAAK,MACf,6CAAC,wBAAQ,OAAO,SAAS,WAAW,QAAQ,WAAS,MAAC,UAAS,SAC7D;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,MAAM;AAAA,kBACN,WAAU;AAAA,kBACV,cAAY,SAAS,wBAAwB;AAAA,kBAC7C,SAAS;AAAA,kBAER,mBACC,6CAAC,UAAK,WAAU,2CAA0C,IAE1D;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAM;AAAA,sBACN,SAAQ;AAAA,sBACR,aAAY;AAAA,sBACZ,QAAO;AAAA,sBACP,MAAK;AAAA,sBACL,eAAc;AAAA,sBACd,gBAAe;AAAA,sBACf,OAAM;AAAA,sBACN,QAAO;AAAA,sBAEP;AAAA,qEAAC,UAAK,QAAO,QAAO,GAAE,iBAAgB,MAAK,QAAO;AAAA,wBAClD,6CAAC,UAAK,GAAE,gFAA+E;AAAA,wBACvF,6CAAC,UAAK,GAAE,gEAA+D;AAAA;AAAA;AAAA,kBACzE;AAAA;AAAA,cAEJ,GACF,GAEJ;AAAA,eACF;AAAA,aACF;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,OAAO;AAAA,cACP,MAAK;AAAA,cACL,UAAU;AAAA,cACV,cAAW;AAAA,cACX,SAAS;AAAA,cACT,WAAW,CAAC,UAAU;AACpB,oBAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;AAC9C,wBAAM,eAAe;AACrB,qCAAmB;AAAA,gBACrB;AAAA,cACF;AAAA;AAAA,UACF;AAAA;AAAA;AAAA,IACF;AAAA,KACF;AAEJ,CAAC;AAED,sBAAsB,cAAc;AAEpC,IAAO,sBAAQ;;;AHzQP,IAAAC,sBAAA;AAzOR,IAAI,kBAA8F;AAC3F,IAAM,wBAAwB,MAAM;AAGzC,sBAAoB,OAAO,cAAc,EAAE;AAAA,IACzC,CAAC,MAAM,EAAE;AAAA,IACT,CAAC,QAAiB;AAChB,wBAAkB;AAClB,YAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO;AACT;AAGA,IAAM,uBAAuB;AAE7B,IAAM,oBAAoB;AAC1B,IAAM,qBAAqB;AAmB3B,SAAS,wBAAwB,UAAkB,SAAkB,WAA4B;AAC/F,QAAM,CAAC,UAAU,WAAW,QAAI;AAAA,IAC9B;AAAA,EACF;AAKA,QAAM,CAAC,aAAa,cAAc,QAAI,wBAAS,CAAC;AAChD,QAAM,sBAAkB,sBAAO,CAAC;AAChC,+BAAU,MAAM;AACd,QAAI,CAAC,QAAS;AAUd,UAAM,QAAQ,aAAa,QAAQ,SAAS,SAAS,SAAS,WAAW,OAAO;AAChF,QAAI,UAAU,SAAU,aAAY,IAAI;AACxC,QAAI,SAAS,SAAS,qBAAsB;AAC5C,UAAM,MACJ,UAAU;AAAA;AAAA,IAGT,CAAC,aAAa,MAAM,aAAa;AAAA,IAEjC,aAAa,SAAS,UAAU,MAAM,WAAW;AACpD,QAAI,CAAC,IAAK;AACV,QAAI,YAAY;AAChB,QAAI;AACJ,0BAAsB,EAAE;AAAA,MACtB,CAAC,SAAS;AACR,YAAI,UAAW;AACf,wBAAgB,UAAU;AAC1B,oBAAY;AAAA,UACV,UAAU,KAAK,cAAc,QAAQ,EAAE,YAAY;AAAA,UACnD,UAAU,SAAS;AAAA,UACnB,UAAU,YAAY,OAAO;AAAA,QAC/B,CAAC;AAAA,MACH;AAAA,MACA,MAAM;AAGJ,YAAI,aAAa,gBAAgB,WAAW,kBAAmB;AAC/D,wBAAgB,WAAW;AAC3B,qBAAa,WAAW,MAAM,eAAe,CAAC,MAAM,IAAI,CAAC,GAAG,kBAAkB;AAAA,MAChF;AAAA,IACF;AACA,WAAO,MAAM;AACX,kBAAY;AACZ,UAAI,eAAe,OAAW,cAAa,UAAU;AAAA,IACvD;AAAA,EAMF,GAAG,CAAC,UAAU,SAAS,WAAW,WAAW,CAAC;AAC9C,SAAO,UAAW,UAAU,YAAY,KAAM;AAChD;AAUO,SAAS,2BAA0C;AACxD,SAAO,QAAQ,IAAI,CAAC,OAAO,SAAS,GAAG,sBAAsB,CAAC,CAAC,EAAE;AAAA,IAC/D,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AASO,SAAS,kBAAkB,MAAuB;AACvD,MAAI,CAAC,YAAY,KAAK,IAAI,EAAG,QAAO;AACpC,MAAI,QAAQ;AACZ,MAAI,WAAW;AACf,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,KAAK,WAAW,CAAC;AAC3B,QAAI,UAAU;AACZ,UAAI,MAAM,GAAa,MAAK;AAAA,eACnB,MAAM,GAAY,YAAW;AAAA,IACxC,WAAW,MAAM,IAAI;AACnB,iBAAW;AAAA,IACb,WAAW,MAAM,OAAO,MAAM,IAAI;AAChC,eAAS;AAAA,IACX,WAAW,MAAM,OAAO,MAAM,IAAI;AAChC,eAAS;AACT,UAAI,QAAQ,EAAG,QAAO;AAAA,IACxB;AAAA,EACF;AACA,SAAO,UAAU,KAAK,CAAC;AACzB;AAQA,IAAK,sBAAL,kBAAKC,yBAAL;AAEE,EAAAA,qBAAA,aAAU;AAFP,SAAAA;AAAA,GAAA;AAML,IAAM,oBAAoB,IAAI,IAAY,OAAO,OAAO,mBAAmB,CAAC;AAyB5E,IAAM,wBAAoB;AAAA,EACxB,CACE,UAIG;AACH,UAAM,EAAE,SAAS,QAAI,iCAAmB;AACxC,UAAM,EAAE,UAAU,QAAI,iCAAmB;AACzC,UAAM,EAAE,2BAA2B,gBAAgB,IAAI,2BAA2B;AAElF,UAAM,mBAAmB;AAAA,MACvB,MAAM;AAAA,MACN,6BAA6B,CAAC,MAAM;AAAA,MACpC;AAAA,IACF;AAMA,UAAM,gBAAgB,MAAM,iBAAiB,kBAAkB,YAAY;AAK3E,UAAM,CAAC,kBAAkB,YAAY,QAAI;AAAA,MACvC,MAAO,eAAe,CAAC,cAAc,YAAY,IAAI,CAAC,aAAa,SAAS;AAAA,MAC5E,CAAC,YAAY;AAAA,IACf;AAEA,UAAM,qBAAqB,kBAAkB,IAAI,YAAY;AAE7D,UAAM,6BAAyB,uBAAQ,MAAM;AAC3C,UAAI,mBAAoB,QAAO;AAC/B,UAAI,cAAc,MAAM;AAUxB,UAAI,eAAe,qBAAqB,WAAW,CAAC,aAAa,kBAAkB,WAAW,IAAI;AAChG,cAAM,uBAAmB,sCAAc,WAAW;AAClD,sBACE,OAAO,qBAAqB,WAAW,mBAAmB,KAAK,UAAU,kBAAkB,MAAM,CAAC;AAAA,MACtG;AACA,aAAO,iBAAiB,YACtB;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,IAAI;AAAA,UACJ,GAAE;AAAA,UACF,MAAM;AAAA,UACN,YAAU;AAAA,UACV,kBAAgB;AAAA,UAChB;AAAA,UACA,oBAAmB;AAAA;AAAA,MACrB,IAEA;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,IAAI;AAAA,UACJ,GAAE;AAAA,UACF,MAAM;AAAA,YACJ;AAAA,cACE,UAAU;AAAA,cACV,MAAM;AAAA,cACN,UAAU;AAAA,YACZ;AAAA,UACF;AAAA,UACA,YAAU;AAAA,UACV,kBAAgB;AAAA,UAChB;AAAA,UACA,oBAAmB;AAAA;AAAA,MACrB;AAAA,IAEJ,GAAG,CAAC,oBAAoB,MAAM,UAAU,kBAAkB,cAAc,UAAU,iBAAiB,SAAS,CAAC;AAE7G,UAAM,8BAA0B,uBAAQ,MAAM;AAC5C,cAAQ,cAAc;AAAA,QACpB,KAAK;AACH,iBAAO,6CAAC,uBAAsB,MAAM,MAAM,UAAU;AAAA,QACtD;AACE,iBAAO;AAAA,MACX;AAAA,IACF,GAAG,CAAC,cAAc,MAAM,QAAQ,CAAC;AAEjC,WAAO,qBAAqB,0BAA0B;AAAA,EACxD;AACF;AAEA,kBAAkB,cAAc;AAEhC,IAAO,kBAAQ;;;AH9Qf,IAAAC,eAAuC;AAkE1B,IAAAC,sBAAA;AAlCb,IAAM,YAAsC,OAAO,OAAO,CAAC,CAAC;AAQ5D,IAAM,0BAED;AAAA,EACH,WAAW,uCAA0B;AACvC;AAUA,IAAM,0BAAsD;AAAA,EAC1D,KAAK,CAAC,EAAE,MAAM,GAAG,YAAY,MAAM;AACjC,UAAM,OAAO,MAAM,SAAS,CAAC;AAS7B,QAAI,CAAC,QAAQ,KAAK,SAAS,aAAa,KAAK,YAAY,UAAU,CAAC,KAAK,UAAU;AACjF,aAAO,6CAAC,SAAK,GAAG,aAAa;AAAA,IAC/B;AACA,UAAM,MAAM,YAAY,MAAM,UAAU,OAAO,UAAU,CAAC;AAI1D,UAAM,aAAa,KAAK,YAAY;AACpC,UAAM,YAAY,MAAM,QAAQ,UAAU,IACrC,WAAyB,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,IAC1E,OAAO,eAAe,WACpB,WAAW,MAAM,KAAK,IACtB,CAAC;AACP,UAAM,mBAAmB,UACtB,KAAK,CAAC,cAAc,UAAU,WAAW,WAAW,CAAC,GACpD,UAAU,YAAY,MAAM;AAIhC,UAAM,WAAW,KAAK,SAAS,IAAI,CAAC,UAA8B,MAAM,SAAS,EAAE,EAAE,KAAK,EAAE;AAC5F,WAAO,6CAAC,mBAA4B,UAAoB,eAAe,oBAAxC,GAA0D;AAAA,EAC3F;AACF;AAWA,IAAM,6BAA6B,CAA0E;AAAA,EAC3G,YAAAC,cAAa;AAAA,EACb,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAyC;AACvC,QAAM,6BAAyB,6BAAe,gBAAgB;AAE9D,QAAM,qBAAiB,uBAAQ,MAAM;AACnC,WAAO,yBAAyB,EAAE,GAAG,yBAAyB,GAAG,uBAAuB,IAAI;AAAA,EAC9F,GAAG,CAAC,sBAAsB,CAAC;AAE3B,QAAM,0BAAsB,qCAAuB,OAAO;AAI1D,QAAM,aAAS,8BAAgB,EAAE,UAAU,GAAG,uBAAuB;AASrE,QAAM,qBAAiB;AAAA,IACrB,MAAO,OAAO,aAAa,OAAO,EAAE,WAAW,OAAO,UAAU,IAAI;AAAA,IACpE,CAAC,OAAO,SAAS;AAAA,EACnB;AAEA,SACE,6CAAC,4CAA4B,OAAO,gBAClC;AAAA,IAAC,aAAAC;AAAA,IAAA;AAAA,MACC,YAAYD;AAAA,MACZ;AAAA,MACA,kBAAkB;AAAA,MAClB,aAAa,eAAe;AAAA,MAC3B,GAAG;AAAA;AAAA,EACN,GACF;AAEJ;AAoBO,IAAM,wBAAoB,oBAAK,0BAA0B;AAEhE,kBAAkB,cAAc;AAEhC,IAAO,4BAAQ;;;AO3KR,SAAS,uBAAuB,QAA8D;AACnG,SAAO,OAAO,OAAO,MAAM;AAC7B;;;ACzBA,IAAAE,eAAsC;AA0B/B,IAAM,+BAA+B,MAErC;AACL,aAAO,oCAAiC;AAC1C;","names":["import_react","import_core","import_jsx_runtime","import_react","import_code_highlight","import_core","import_react","import_core","import_react","import_core","import_jsx_runtime","import_jsx_runtime","SpecialCodeLanguage","import_core","import_jsx_runtime","Typography","AIMarkdown","import_core"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx","../src/MantineAIMarkdown.tsx","../src/components/typography/MantineTypography.tsx","../src/components/extra-styles/DefaultExtraStyles/index.tsx","../src/components/customized/PreCode.tsx","../src/hooks/useMantineCodeBlockOptions.ts","../src/defs.tsx","../src/components/customized/MermaidCode/index.tsx","../src/define.ts","../src/hooks/useMantineAIMarkdownMetadata.ts"],"sourcesContent":["/**\n * Public API surface for `@ai-react-markdown/mantine`.\n *\n * Re-exports the Mantine-integrated AI markdown component, its supporting\n * sub-components, extended types, default configuration, and typed hooks.\n *\n * @packageDocumentation\n */\n\n// --- Components ---\n\n/** Props for the main {@link MantineAIMarkdown} component. */\nexport type { MantineAIMarkdownProps } from './MantineAIMarkdown';\n\n/** Main component -- Mantine-integrated AI markdown renderer (default export). */\nexport { default } from './MantineAIMarkdown';\n\n/** Mantine-themed typography wrapper used by default inside {@link MantineAIMarkdown}. */\nexport { default as MantineAIMarkdownTypography } from './components/typography/MantineTypography';\n\n/** Default extra styles wrapper providing Mantine-compatible CSS scoping and overrides. */\nexport { default as MantineAIMDefaultExtraStyles } from './components/extra-styles/DefaultExtraStyles';\n\n// --- Types, config, and hooks ---\n\n/** Extended render configuration and metadata types for the Mantine integration. */\nexport type { MantineAIMarkdownMetadata, MantineCodeBlockOptions } from './defs';\n\n// ── v2 surface (props-api v2) ───────────────────────────────────────────────\n\n/** Shipped defaults of the `codeBlock` behavior group. */\nexport { defaultMantineCodeBlockOptions } from './defs';\n\n/** Narrow hook for the `codeBlock` behavior group — the single assertion site. */\nexport { useMantineCodeBlockOptions } from './hooks/useMantineCodeBlockOptions';\n\n/** Optional eager loading of the on-demand code-block assets (mermaid, highlight.js). */\nexport { preloadMantineCodeAssets } from './components/customized/PreCode';\n\n/** Widened behaviors factory (core fields + mantine's `codeBlock` group). */\nexport { defineMantineBehaviors } from './define';\nexport type { MantineBehaviorProps } from './define';\n\n/** Typed hook for accessing metadata within the Mantine AI markdown tree. */\nexport { useMantineAIMarkdownMetadata } from './hooks/useMantineAIMarkdownMetadata';\n","/**\n * Main Mantine integration component for AI markdown rendering.\n *\n * Wraps the core {@link AIMarkdown} component with Mantine-specific defaults:\n * - {@link MantineAIMarkdownTypography} as the typography wrapper\n * - {@link MantineAIMDefaultExtraStyles} as the extra styles wrapper\n * - {@link MantineAIMPreCode} as the default `<pre>` component (with syntax\n * highlighting via Mantine's CodeHighlight and mermaid diagram support)\n * - Automatic color scheme detection via Mantine's `useComputedColorScheme`\n *\n * @module MantineAIMarkdown\n */\n\nimport { memo, useMemo } from 'react';\nimport AIMarkdown from '@ai-react-markdown/core';\nimport {\n type AIMarkdownProps,\n type AIMarkdownCustomComponents,\n type AIMarkdownBehaviorGroups,\n type AIMarkdownStabilityTable,\n AIMarkdownBehaviorsProvider,\n AIMarkdownStabilityPolicy,\n useStableRecord,\n useStableValue,\n} from '@ai-react-markdown/core';\nimport MantineAIMarkdownTypography from './components/typography/MantineTypography';\nimport MantineAIMDefaultExtraStyles from './components/extra-styles/DefaultExtraStyles';\nimport { MantineAIMarkdownMetadata, MantineCodeBlockOptions } from './defs';\nimport MantineAIMPreCode from './components/customized/PreCode';\nimport { useComputedColorScheme } from '@mantine/core';\n\n/**\n * Props for the {@link MantineAIMarkdown} component.\n *\n * Extends {@link AIMarkdownProps} with the mantine behavior groups.\n * All core props (`content`, `streaming`, `fontSize`, `enginePlugins`, etc.)\n * are inherited.\n *\n * @typeParam TMetadata - Metadata type, defaults to {@link MantineAIMarkdownMetadata}.\n */\nexport interface MantineAIMarkdownProps<\n TMetadata extends MantineAIMarkdownMetadata = MantineAIMarkdownMetadata,\n> extends AIMarkdownProps<TMetadata> {\n /**\n * Code-block behavior group (Behaviors system). The group value replaces\n * atomically; omitted fields resolve to the shipped defaults inside\n * `useMantineCodeBlockOptions()`. `null` counts as absent. When absent,\n * this wrapper contributes NO `codeBlock` group, so a group provided by\n * an outer app-level `AIMarkdownBehaviorsProvider` passes through; when\n * present, this prop wins over any outer group (inner-wins merge).\n */\n codeBlock?: Partial<MantineCodeBlockOptions>;\n}\n\n/**\n * Stable empty CONTRIBUTION for the absent-prop case. Deliberately carries\n * no `codeBlock` key at all: contributing `codeBlock: {}` would shadow a\n * group provided by an outer app-level `AIMarkdownBehaviorsProvider`\n * (inner-wins merge) even though this wrapper has nothing to say — the\n * documented app-level extension path would silently go dead.\n */\nconst NO_GROUPS: AIMarkdownBehaviorGroups = Object.freeze({});\n\n/**\n * Mantine's stability-firewall table — one row today: `codeBlock` is the\n * only object prop this wrapper TERMINATES (consumes in its own machinery).\n * Forwarded object props ride core's firewall untouched; the merged\n * `customComponents` derived below is caught by core's wall.\n */\nconst MANTINE_STABILITY_TABLE: AIMarkdownStabilityTable<{\n codeBlock: Partial<MantineCodeBlockOptions> | undefined;\n}> = {\n codeBlock: AIMarkdownStabilityPolicy.DEEP_EQUAL,\n};\n\n/**\n * Default custom component overrides applied by the Mantine integration.\n *\n * Overrides the `<pre>` element to extract code blocks and render them via\n * {@link MantineAIMPreCode}, which provides syntax highlighting, expand/collapse,\n * and mermaid diagram support. Falls back to a plain `<pre>` when the child\n * is not a recognized code element.\n */\nconst DefaultCustomComponents: AIMarkdownCustomComponents = {\n pre: ({ node, ...usefulProps }) => {\n const code = node?.children[0] as\n | {\n type: string;\n tagName?: string;\n position?: { start?: { offset?: number } };\n properties?: Record<string, unknown>;\n children: { value?: string }[];\n }\n | undefined;\n if (!code || code.type !== 'element' || code.tagName !== 'code' || !code.position) {\n return <pre {...usefulProps} />;\n }\n const key = `pre-code-${node?.position?.start?.offset || 0}`;\n // hast allows `className` as a string as well as an array (a consumer's\n // rehype plugin may write either); `.find` on a string threw and took\n // the whole tree down (2026-08-19 review).\n const classNames = code.properties?.className;\n const classList = Array.isArray(classNames)\n ? (classNames as unknown[]).filter((c): c is string => typeof c === 'string')\n : typeof classNames === 'string'\n ? classNames.split(/\\s+/)\n : [];\n const detectedLanguage = classList\n .find((className) => className.startsWith('language-'))\n ?.substring('language-'.length);\n // A `<code>` inside `<pre>` normally carries ONE text child; if an\n // upstream plugin splits it, the pieces are contiguous source — join\n // with '' (a '\\n' joiner would invent line breaks the source lacks).\n const codeText = code.children.map((child: { value?: string }) => child.value ?? '').join('');\n return <MantineAIMPreCode key={key} codeText={codeText} existLanguage={detectedLanguage} />;\n },\n};\n\n/**\n * Inner (non-memoized) implementation of the Mantine AI markdown component.\n *\n * Merges caller-provided `customComponents` with the Mantine defaults (the caller's\n * overrides take precedence). Automatically resolves the color scheme from Mantine's\n * `useComputedColorScheme` when no explicit `colorScheme` prop is provided.\n *\n * @typeParam TMetadata - Metadata type.\n */\nconst MantineAIMarkdownComponent = <TMetadata extends MantineAIMarkdownMetadata = MantineAIMarkdownMetadata>({\n Typography = MantineAIMarkdownTypography,\n ExtraStyles = MantineAIMDefaultExtraStyles,\n customComponents,\n colorScheme,\n codeBlock,\n ...props\n}: MantineAIMarkdownProps<TMetadata>) => {\n const stableCustomComponents = useStableValue(customComponents);\n\n const usedComponents = useMemo(() => {\n return stableCustomComponents ? { ...DefaultCustomComponents, ...stableCustomComponents } : DefaultCustomComponents;\n }, [stableCustomComponents]);\n\n const computedColorScheme = useComputedColorScheme('light');\n\n // Mantine's stability firewall: `codeBlock` is terminated here (it feeds\n // the behaviors Provider below, not the core prop surface).\n const stable = useStableRecord({ codeBlock }, MANTINE_STABILITY_TABLE);\n\n // Contribute the group through the additive behaviors Provider — firewall\n // output used directly, record identity memoized so the context value\n // stays stable across unrelated re-renders. `null`/absent prop ≡ no\n // contribution (NOT an empty group): an outer app-level Provider's\n // `codeBlock` group then stays visible; when the prop IS present the\n // inner-wins merge gives this wrapper's value precedence. The narrow hook\n // fills the defaults for the no-group-anywhere case.\n const behaviorGroups = useMemo<AIMarkdownBehaviorGroups>(\n () => (stable.codeBlock != null ? { codeBlock: stable.codeBlock } : NO_GROUPS),\n [stable.codeBlock]\n );\n\n return (\n <AIMarkdownBehaviorsProvider value={behaviorGroups}>\n <AIMarkdown<MantineAIMarkdownMetadata>\n Typography={Typography}\n ExtraStyles={ExtraStyles}\n customComponents={usedComponents}\n colorScheme={colorScheme ?? computedColorScheme}\n {...props}\n />\n </AIMarkdownBehaviorsProvider>\n );\n};\n\n/**\n * Mantine-integrated AI markdown renderer.\n *\n * A memoized wrapper around the core `<AIMarkdown>` component that provides\n * Mantine-themed typography, code highlighting (via `@mantine/code-highlight`),\n * mermaid diagram rendering, and automatic color scheme detection.\n *\n * This is the default export of `@ai-react-markdown/mantine`.\n *\n * @example\n * ```tsx\n * import MantineAIMarkdown from '@ai-react-markdown/mantine';\n *\n * function Chat({ content }: { content: string }) {\n * return <MantineAIMarkdown content={content} />;\n * }\n * ```\n */\nexport const MantineAIMarkdown = memo(MantineAIMarkdownComponent);\n\nMantineAIMarkdown.displayName = 'MantineAIMarkdown';\n\nexport default MantineAIMarkdown as typeof MantineAIMarkdownComponent;\n","import { memo } from 'react';\nimport { Typography } from '@mantine/core';\nimport type { AIMarkdownTypographyProps } from '@ai-react-markdown/core';\n\n/**\n * Mantine-themed typography wrapper for AI markdown content.\n *\n * Replaces the core default typography component with Mantine's `<Typography>`\n * element, applying the configured `fontSize` at full width. This ensures all\n * rendered markdown inherits Mantine's font family, line height, and theming.\n *\n * Used as the default `Typography` prop in {@link MantineAIMarkdown}.\n * Can be replaced by passing a custom `Typography` component.\n *\n * @param props - Standard {@link AIMarkdownTypographyProps} from the core package.\n */\nconst MantineAIMarkdownTypography = memo(({ children, fontSize, style }: AIMarkdownTypographyProps) => (\n <Typography w=\"100%\" fz={fontSize} style={style}>\n {children}\n </Typography>\n));\n\nMantineAIMarkdownTypography.displayName = 'MantineAIMarkdownTypography';\n\nexport default MantineAIMarkdownTypography;\n","import React from 'react';\nimport { AIMarkdownExtraStylesComponent } from '@ai-react-markdown/core';\nimport './styles.scss';\n\n/**\n * Default extra styles wrapper for the Mantine integration.\n *\n * Wraps markdown content in a `<div>` with the `aim-mantine-extra-styles` CSS class,\n * which provides Mantine-compatible typography overrides including:\n * - Relative `em`-based Mantine spacing and font-size CSS custom properties\n * - Heading, list, paragraph, blockquote, and code styling\n * - Definition list layout\n *\n * Used as the default `ExtraStyles` prop in {@link MantineAIMarkdown}.\n */\nconst MantineAIMDefaultExtraStyles: AIMarkdownExtraStylesComponent = ({ children }) => {\n return <div className=\"aim-mantine-extra-styles\">{children}</div>;\n};\n\nexport default MantineAIMDefaultExtraStyles;\n","'use client';\n\nimport { HTMLAttributes, memo, useEffect, useMemo, useRef, useState } from 'react';\nimport { CodeHighlight, CodeHighlightTabs } from '@mantine/code-highlight';\nimport { useAIMarkdownState, useAIMarkdownTheme } from '@ai-react-markdown/core';\nimport { useMantineCodeBlockOptions } from '../../hooks/useMantineCodeBlockOptions';\nimport MantineAIMMermaidCode from './MermaidCode';\n\n/**\n * highlight.js is NOT imported statically any more: the root entry carries\n * every language definition (~130 KB gzip) and the only always-on use was a\n * `getLanguage()` existence check that Mantine's own adapter already\n * performs (unknown language → plaintext). Auto-detection is the one real\n * consumer, and it loads the module on demand — only when\n * `autoDetectUnknownLanguage` is on and an unlabelled block shows up\n * (2026-08 project review, pkg-small-02: the static import defeated\n * consumers' `highlight.js/lib/core` slimming). Consumers who want it (and\n * mermaid) in the main bundle up front call `preloadMantineCodeAssets()`\n * at app start, or simply import the modules themselves.\n */\nlet hljsAutoPromise: Promise<{ highlightAuto: (code: string) => { language?: string } }> | null = null;\nexport const loadHljsForAutoDetect = () => {\n // A rejected load (transient network failure) is NOT cached: the next\n // attempt retries instead of leaving autodetection dead for the page.\n hljsAutoPromise ??= import('highlight.js').then(\n (m) => m.default,\n (err: unknown) => {\n hljsAutoPromise = null;\n throw err;\n }\n );\n return hljsAutoPromise;\n};\n\n/** Below this many characters a guess is noise; the block stays \"unknown\". */\nconst AUTODETECT_MIN_CHARS = 32;\n/** Bounded automatic retries of a failed highlight.js module download. */\nconst HLJS_LOAD_RETRIES = 3;\nconst HLJS_LOAD_RETRY_MS = 1500;\n\n/**\n * The language highlight.js guesses for an unlabelled block.\n *\n * `highlightAuto` scores every registered language against the whole text,\n * so re-running it on every streamed chunk was O(languages × n) per chunk —\n * O(n²) over a long block (pkg-small-06). Schedule instead:\n * - first guess as soon as the block has AUTODETECT_MIN_CHARS (an early\n * label rather than \"unknown\" for the whole stream);\n * - a corrective re-run each time the block has DOUBLED in length since\n * the last guess (32 → 64 → 128 → …): a wrong early guess on a long\n * block is fixed within its next doubling, and the total work stays\n * O(n) — at most log₂(n) runs;\n * - a final verdict when streaming ends (the last run always sees the\n * complete block).\n * Returns '' while disabled, still loading, or below the minimum, so the\n * block renders as plaintext/\"unknown\" and upgrades in place.\n */\nfunction useAutoDetectedLanguage(codeText: string, enabled: boolean, streaming: boolean): string {\n const [detected, setDetected] = useState<{ language: string; atLength: number; finalFor: string | null } | null>(\n null\n );\n // Bumped after a failed `import('highlight.js')` so the effect re-runs on\n // otherwise unchanged inputs and retries the download — the mermaid\n // renderer's counterpart. Without it a static document whose only load\n // attempt failed stayed \"unknown\" for good (v2.4.2 review P2-2). Bounded.\n const [loadAttempt, setLoadAttempt] = useState(0);\n const loadFailuresRef = useRef(0);\n useEffect(() => {\n if (!enabled) return;\n // The block was REPLACED, not appended to (a regenerate reuses this\n // instance — the key is the block's source offset — or a same-offset\n // swap): a guess made for the old text is worthless for the new one.\n // Drop it so the schedule restarts (v2.4.0 review: the old label stuck\n // for the whole new stream until its end).\n // Do NOT return here: `detected` is not a dep, so a state reset alone\n // would never re-run the effect and a non-streaming replacement stayed\n // \"unknown\" for good (v2.4.1 review) — evaluate the schedule against\n // the cleared prior in this same pass.\n const prior = detected !== null && codeText.length < detected.atLength ? null : detected;\n if (prior !== detected) setDetected(null);\n if (codeText.length < AUTODETECT_MIN_CHARS) return;\n const due =\n prior === null ||\n // Not streaming: the verdict must be for THIS text (end-of-stream, or a\n // static content update).\n (!streaming && prior.finalFor !== codeText) ||\n // Streaming: doubled since the last guess.\n (streaming && codeText.length >= prior.atLength * 2);\n if (!due) return;\n let cancelled = false;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n loadHljsForAutoDetect().then(\n (hljs) => {\n if (cancelled) return;\n loadFailuresRef.current = 0;\n setDetected({\n language: hljs.highlightAuto(codeText).language ?? '',\n atLength: codeText.length,\n finalFor: streaming ? null : codeText,\n });\n },\n () => {\n // Load failed — stay \"unknown\" and retry the download a bounded\n // number of times (the loader does not cache rejections).\n if (cancelled || loadFailuresRef.current >= HLJS_LOAD_RETRIES) return;\n loadFailuresRef.current += 1;\n retryTimer = setTimeout(() => setLoadAttempt((n) => n + 1), HLJS_LOAD_RETRY_MS);\n }\n );\n return () => {\n cancelled = true;\n if (retryTimer !== undefined) clearTimeout(retryTimer);\n };\n // `detected` is deliberately not a dep: a completed guess must not\n // re-trigger the effect (it re-runs on the next content/streaming\n // change, which is when the schedule is re-evaluated). `loadAttempt`\n // re-runs it after a failed module download.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [codeText, enabled, streaming, loadAttempt]);\n return enabled ? (detected?.language ?? '') : '';\n}\n\n/**\n * Loads mermaid and highlight.js ahead of time. Both are imported on demand\n * by the code-block renderers (the first diagram / the first auto-detected\n * block pays the download); an app that would rather take that cost at\n * startup — a documentation page whose first screen shows a diagram, say —\n * calls this once at boot. Safe to call repeatedly; failures are swallowed\n * (the renderers will simply load lazily later).\n */\nexport function preloadMantineCodeAssets(): Promise<void> {\n return Promise.all([import('mermaid'), loadHljsForAutoDetect()]).then(\n () => undefined,\n () => undefined\n );\n}\n\n/**\n * Pretty-print helper: `JSON.parse` the block and expand string values that\n * are themselves JSON DOCUMENTS (an object or array — the tool-call\n * transcript shape, where a `tool_result` field is one escaped blob), so\n * both levels print indented. Strings that merely parse as a JSON\n * PRIMITIVE (`\"true\"`, `\"123\"`, `\"null\"`) are left alone: the previous\n * `deep-parse-json` dependency turned `{\"flag\":\"true\"}` into\n * `{\"flag\":true}` — a type rewrite of what the model wrote, and the copy\n * button ships the rewritten bytes (2026-08-19 review r2 P2-14). Returns\n * the input unchanged when it is not valid JSON.\n */\nexport function prettyPrintJson(text: string): string {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return text;\n }\n return JSON.stringify(expandNestedJson(parsed), null, 2);\n}\n\nfunction expandNestedJson(value: unknown): unknown {\n if (typeof value === 'string') {\n const t = value.trim();\n if (t.length > 1 && (t[0] === '{' || t[0] === '[')) {\n try {\n const inner: unknown = JSON.parse(t);\n if (inner !== null && typeof inner === 'object') return expandNestedJson(inner);\n } catch {\n /* not a nested document — keep the string */\n }\n }\n return value;\n }\n if (Array.isArray(value)) return value.map(expandNestedJson);\n if (value !== null && typeof value === 'object') {\n // Null-prototype target: a `\"__proto__\"` key (an OWN property after\n // JSON.parse) must stay a property, not become the prototype and vanish\n // from the output (oracle review of the r2 batch).\n const out: Record<string, unknown> = Object.create(null) as Record<string, unknown>;\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) out[k] = expandNestedJson(v);\n return out;\n }\n return value;\n}\n\n/**\n * Cheap tell that a streamed JSON block is complete: it ends with a closing\n * bracket AND its brackets balance to zero outside string literals. A\n * balanced prefix can still be invalid JSON (prettyPrintJson then just\n * returns the text), but an in-progress pretty-printed block is never\n * balanced, so the parse is skipped on the way through.\n */\nexport function jsonLooksComplete(text: string): boolean {\n if (!/[}\\]]\\s*$/.test(text)) return false;\n let depth = 0;\n let inString = false;\n for (let i = 0; i < text.length; i++) {\n const c = text.charCodeAt(i);\n if (inString) {\n if (c === 92 /* \\\\ */) i += 1;\n else if (c === 34 /* \" */) inString = false;\n } else if (c === 34) {\n inString = true;\n } else if (c === 123 || c === 91) {\n depth += 1;\n } else if (c === 125 || c === 93) {\n depth -= 1;\n if (depth < 0) return false;\n }\n }\n return depth === 0 && !inString;\n}\n\n/**\n * Code languages that receive specialized rendering instead of standard\n * syntax-highlighted code blocks. Adding a new member here automatically\n * marks that language as \"special\" — you only need to add the corresponding\n * rendering branch in the component's return.\n */\nenum SpecialCodeLanguage {\n /** Rendered as interactive diagrams via {@link MantineAIMMermaidCode} */\n Mermaid = 'mermaid',\n}\n\n/** O(1) lookup set, derived from {@link SpecialCodeLanguage}. */\nconst SPECIAL_LANGUAGES = new Set<string>(Object.values(SpecialCodeLanguage));\n\n/**\n * Mantine code block renderer for `<pre>` elements.\n *\n * Replaces the default `<pre>` rendering with Mantine's {@link CodeHighlight} or\n * {@link CodeHighlightTabs} components, providing syntax highlighting, expand/collapse\n * behavior, and file-name tabs.\n *\n * Behavior:\n * - If the code block has an explicit language annotation, uses that language.\n * - If no language is specified and the `codeBlock` group's\n * `autoDetectUnknownLanguage` option is enabled, uses `highlight.js`\n * auto-detection.\n * - Mermaid code blocks (`language-mermaid`) are rendered as interactive diagrams\n * via {@link MantineAIMMermaidCode}.\n * - JSON code blocks are deep-parsed and pretty-printed before display.\n * - Unrecognized languages render as plaintext with an \"unknown\" label using\n * {@link CodeHighlight} (no tabs).\n * - Recognized languages render with {@link CodeHighlightTabs} showing the\n * language name as the tab label.\n *\n * @param props.codeText - The raw text content of the code block.\n * @param props.existLanguage - Language identifier extracted from the `language-*` CSS class, if present.\n */\nconst MantineAIMPreCode = memo(\n (\n props: HTMLAttributes<HTMLPreElement> & {\n codeText: string;\n existLanguage?: string;\n }\n ) => {\n const { fontSize } = useAIMarkdownTheme();\n const { streaming } = useAIMarkdownState();\n const { autoDetectUnknownLanguage, defaultExpanded } = useMantineCodeBlockOptions();\n\n const detectedLanguage = useAutoDetectedLanguage(\n props.codeText,\n autoDetectUnknownLanguage && !props.existLanguage,\n streaming\n );\n // Lower-cased once for every decision below: fence languages arrive in\n // whatever case the model wrote (` ```Mermaid `, ` ```JSON `), and both\n // the special-language switch and the JSON branch must agree\n // (2026-08 project review, pkg-small-08 — the mermaid check was\n // case-sensitive while the JSON check was not).\n const codeLanguage = (props.existLanguage || detectedLanguage).toLowerCase();\n\n // The language is passed straight to Mantine's highlighter, whose\n // adapter already degrades unknown languages to plaintext; the label\n // is \"unknown\" only when there is no language at all.\n const [usedCodeLanguage, usedFileName] = useMemo(\n () => (codeLanguage ? [codeLanguage, codeLanguage] : ['plaintext', 'unknown']),\n [codeLanguage]\n );\n\n const isSpecialCodeBlock = SPECIAL_LANGUAGES.has(codeLanguage);\n\n const normalCodeBlockContent = useMemo(() => {\n if (isSpecialCodeBlock) return null;\n let usedCodeStr = props.codeText;\n // JSON pretty-print as soon as the block LOOKS complete: a streamed\n // prefix never parses, so trying to pretty-print every chunk of a\n // growing block was O(n²) work for nothing (pkg-small-06) — but a\n // block that finished mid-document must not wait for the whole\n // message to end. \"Ends with a closing bracket\" alone was not enough\n // of a tell: pretty-printed JSON (the common LLM shape) ends a chunk\n // on `}` / `]` at almost every nesting level, so the parse still ran\n // on nearly every chunk (v2.4.1 review). Only a BALANCED bracket\n // scan (strings skipped, one linear pass) admits the parse.\n if (usedCodeStr && usedCodeLanguage === 'json' && (!streaming || jsonLooksComplete(usedCodeStr))) {\n usedCodeStr = prettyPrintJson(usedCodeStr);\n }\n return usedFileName === 'unknown' ? (\n <CodeHighlight\n mb={15}\n fz={fontSize}\n w=\"100%\"\n code={usedCodeStr}\n withBorder\n withExpandButton\n defaultExpanded={defaultExpanded}\n maxCollapsedHeight=\"320px\"\n />\n ) : (\n <CodeHighlightTabs\n mb={15}\n fz={fontSize}\n w=\"100%\"\n code={[\n {\n fileName: usedFileName,\n code: usedCodeStr,\n language: usedCodeLanguage,\n },\n ]}\n withBorder\n withExpandButton\n defaultExpanded={defaultExpanded}\n maxCollapsedHeight=\"320px\"\n />\n );\n }, [isSpecialCodeBlock, props.codeText, usedCodeLanguage, usedFileName, fontSize, defaultExpanded, streaming]);\n\n const specialCodeBlockContent = useMemo(() => {\n switch (codeLanguage) {\n case SpecialCodeLanguage.Mermaid:\n return <MantineAIMMermaidCode code={props.codeText} />;\n default:\n return null;\n }\n }, [codeLanguage, props.codeText]);\n\n return isSpecialCodeBlock ? specialCodeBlockContent : normalCodeBlockContent;\n }\n);\n\nMantineAIMPreCode.displayName = 'MantineAIMPreCode';\n\nexport default MantineAIMPreCode;\n","/**\n * Narrow hook for the mantine `codeBlock` behavior group.\n *\n * This is THE single type-assertion site for the group (the pattern that\n * retires the public caller-asserted `TConfig` generic): the opaque\n * extension record from `useAIMarkdownBehaviors()` is narrowed here, and\n * group defaults are applied here — read sites must consume this hook and\n * never re-apply defaults with bare `??` (multiple read sites duplicating\n * defaults will drift).\n *\n * @module hooks/useMantineCodeBlockOptions\n */\n\nimport { useMemo } from 'react';\nimport { useAIMarkdownBehaviors } from '@ai-react-markdown/core';\nimport { defaultMantineCodeBlockOptions, type MantineCodeBlockOptions } from '../defs';\n\n/**\n * Read the resolved code-block options from the behaviors context.\n *\n * Group values replace atomically at the transport layer; defaults are\n * filled in here, so a partial group (e.g. `codeBlock={{ defaultExpanded:\n * false }}`) resolves the omitted fields to the shipped defaults.\n *\n * Must be called inside a `<MantineAIMarkdown>` (or any `<AIMarkdown>`\n * wrapped in the mantine Provider stack) — throws outside, same contract\n * as the core narrow hooks.\n */\nexport function useMantineCodeBlockOptions(): Required<MantineCodeBlockOptions> {\n const behaviors = useAIMarkdownBehaviors();\n // The single assertion: the `codeBlock` group key is owned by this\n // package, contributed by `MantineAIMarkdown` via its behaviors Provider.\n const group = behaviors.codeBlock as Partial<MantineCodeBlockOptions> | undefined;\n return useMemo(() => {\n // Field-wise `??` rather than a spread: `codeBlock={{ defaultExpanded:\n // undefined }}` type-checks, and a spread would let that explicit\n // undefined punch through the default while the signature promises\n // `Required<…>` (2026-08 project review, pkg-small-12).\n const resolved = { ...defaultMantineCodeBlockOptions } as Required<MantineCodeBlockOptions>;\n for (const key of Object.keys(defaultMantineCodeBlockOptions) as Array<keyof MantineCodeBlockOptions>) {\n const value = group?.[key];\n if (value !== undefined) (resolved as Record<string, unknown>)[key] = value;\n }\n return resolved;\n }, [group]);\n}\n","/**\n * Mantine-specific type definitions and defaults: the `codeBlock` behavior\n * group and the metadata extension point.\n *\n * @module defs\n */\n\nimport { AIMarkdownMetadata } from '@ai-react-markdown/core';\n\n/**\n * Code block rendering options (the mantine `codeBlock` behavior group).\n *\n * v2 transport: passed as the flat `codeBlock` prop on `MantineAIMarkdown`\n * (group value replaces atomically) and read through\n * `useMantineCodeBlockOptions()`, which applies the defaults below inside\n * the hook — the single place defaults live at read time.\n */\nexport interface MantineCodeBlockOptions {\n /**\n * Whether code blocks start in their expanded state.\n * When `false`, long code blocks are collapsed with an expand button.\n *\n * @default true\n */\n defaultExpanded: boolean;\n\n /**\n * When `true`, uses `highlight.js` auto-detection to determine the language\n * of code blocks that lack an explicit language annotation.\n *\n * @default false\n */\n autoDetectUnknownLanguage: boolean;\n}\n\n/** Shipped defaults for the `codeBlock` behavior group. */\nexport const defaultMantineCodeBlockOptions: Readonly<MantineCodeBlockOptions> = Object.freeze({\n defaultExpanded: true,\n autoDetectUnknownLanguage: false,\n});\n\n/**\n * Metadata type for the Mantine integration.\n *\n * Currently identical to {@link AIMarkdownMetadata}. Exists as an extension point\n * so that consumers can augment metadata in Mantine-specific wrappers without\n * needing to reference the core type directly.\n */\nexport interface MantineAIMarkdownMetadata extends AIMarkdownMetadata {}\n","'use client';\n\nimport React, { memo, useEffect, useRef, useState, useCallback } from 'react';\nimport { CodeHighlightControl, CodeHighlightTabs } from '@mantine/code-highlight';\nimport { ActionIcon, CopyButton, Flex, Tooltip } from '@mantine/core';\nimport type mermaidModule from 'mermaid';\nimport { useAIMarkdownState, useAIMarkdownTheme } from '@ai-react-markdown/core';\nimport { useMantineCodeBlockOptions } from '../../../hooks/useMantineCodeBlockOptions';\nimport './styles.scss';\n\n/** Static `<pre>` style for the mermaid container. */\nconst PRE_STYLE = { cursor: 'pointer', overflow: 'auto', width: '100%', padding: '0.5rem' } as const;\n\n/**\n * What the component currently shows. One value instead of separate\n * `hasRendered`/`renderError`/`chartType` fields whose combinations had to\n * be kept coherent by hand:\n * - `source`: warm-up / SSR fallback — raw code as a plain code block\n * (nothing rendered yet this generation).\n * - `diagram`: the last successful SVG is up.\n * - `error`: the error tab — only a post-stream corrective failure or a\n * never-rendered static failure can enter this state.\n *\n * The user's source toggle (`showOriginalCode`) is deliberately NOT a\n * phase: it overlays any view and flipping it back must restore the prior\n * one unchanged.\n */\ntype MermaidView = { kind: 'source' } | { kind: 'diagram'; chartType: string } | { kind: 'error' };\n\n/** Equality used to skip no-op view updates — repeat mid-stream successes\n * of the same chart type must not re-render the host per chunk. */\nconst sameView = (a: MermaidView, b: MermaidView): boolean =>\n a.kind === 'diagram' && b.kind === 'diagram' ? a.chartType === b.chartType : a.kind === b.kind;\n\ntype Mermaid = typeof mermaidModule;\n\n/**\n * mermaid is loaded on demand — the FIRST diagram that actually renders\n * pays the import; an app whose content never contains a mermaid fence\n * never downloads the ~1.5 MB module (2026-08 project review,\n * pkg-small-03: the static import sat on the default `pre` component's\n * import chain, so every consumer's main bundle carried it). The promise is\n * cached module-wide; the source-view warm-up covers the loading window.\n */\nlet mermaidPromise: Promise<Mermaid> | null = null;\n/** Bounded automatic retries of a failed mermaid module download. */\nconst MERMAID_LOAD_RETRIES = 3;\nconst MERMAID_LOAD_RETRY_MS = 1500;\nconst loadMermaid = (): Promise<Mermaid> => {\n // A rejected load is not cached — the next render attempt retries.\n mermaidPromise ??= import('mermaid').then(\n (m) => m.default,\n (err: unknown) => {\n mermaidPromise = null;\n throw err;\n }\n );\n return mermaidPromise;\n};\n\n/** Theme mermaid.initialize was last called with. mermaid's config is a\n * module-level singleton, so re-asserting an unchanged theme before every\n * render attempt (each streamed chunk re-runs the effect) is pure waste —\n * but instances under providers with DIFFERENT schemes must each\n * re-assert before their own render, so the cache is module-level and\n * checked per attempt rather than hoisted into a per-instance effect. */\nlet initializedTheme: 'dark' | 'light' | null = null;\n\n/**\n * mermaid's config is a module-level singleton shared with the host\n * application when the bundler dedupes the package, and a host that enables\n * `click` interactions calls `mermaid.initialize({ securityLevel: 'loose' })`\n * — the officially documented way. Under `loose` mermaid skips DOMPurify\n * and its output goes into this component's `innerHTML` verbatim: an\n * LLM-authored diagram string could then run script in the page origin.\n * So the theme cache alone is not enough of a guard: before every render\n * the current `securityLevel` is read back (`mermaidAPI.getConfig()` — a\n * config copy, still far cheaper than `initialize`'s merge + theme\n * variables + diagram registration) and a non-strict value forces a\n * re-initialize\n * (2026-08-19 review r2 P2-11; the v2.4.2 \"documented premise\" made this\n * the host's problem — it is ours, the innerHTML is ours).\n */\nconst ensureMermaidInitialized = (mermaid: Mermaid, isDark: boolean) => {\n const theme = isDark ? 'dark' : 'light';\n // `getConfig` lives on `mermaid.mermaidAPI` (deprecated in the types, present\n // at runtime in mermaid 11) — the default export has none, a cast hid that\n // and the guard never short-circuited (oracle review of the r2 batch).\n const api = (mermaid as { mermaidAPI?: { getConfig?: () => { securityLevel?: string } } }).mermaidAPI;\n const currentLevel = api?.getConfig?.().securityLevel;\n if (initializedTheme === theme && currentLevel === 'strict') return;\n mermaid.initialize({\n startOnLoad: false,\n securityLevel: 'strict',\n theme: isDark ? 'dark' : 'base',\n darkMode: isDark,\n // Without a svgContainingElement, a draw-phase throw (an error that\n // got past mermaid.parse) leaves mermaid's temp element orphaned in\n // document.body — its error path only cleans up when this flag is\n // set. We render our own error tab anyway, so mermaid's built-in\n // error diagram is dead weight here regardless.\n suppressErrorRendering: true,\n });\n initializedTheme = theme;\n};\n\n/**\n * Generate a unique ID for mermaid SVG rendering.\n * Combines a timestamp with a random suffix to avoid collisions when\n * multiple mermaid diagrams render concurrently.\n *\n * @returns A unique string in the format `mermaid-{timestamp}-{random}`.\n */\nconst generateMermaidUUID = () => {\n return `mermaid-${new Date().getTime()}-${Math.random().toString(36).slice(2, 10)}`;\n};\n\n/**\n * Open the rendered mermaid SVG in a new browser window.\n *\n * Clones the SVG element, applies a background color matching the current\n * color scheme, serializes it to an object URL, and opens it in a new tab.\n * The object URL is revoked after a short delay to free memory.\n *\n * @param svgElement - The rendered SVG element to view, or `null`/`undefined` to no-op.\n * @param isDark - Whether the current color scheme is dark (used for background color).\n */\nconst handleViewSVGInNewWindow = (svgElement: SVGElement | null | undefined, isDark: boolean) => {\n if (!svgElement) return;\n const targetSvg = svgElement.cloneNode(true) as SVGElement;\n targetSvg.style.backgroundColor = isDark ? '#242424' : 'white';\n const text = new XMLSerializer().serializeToString(targetSvg);\n const blob = new Blob([text], { type: 'image/svg+xml' });\n const url = URL.createObjectURL(blob);\n // `noopener`: the blob URL is same-origin and opens as a top-level SVG\n // document; under mermaid's default strict securityLevel it is DOMPurify\n // output, but a host that flips the shared singleton to 'loose' (see the\n // module note above) would hand that document a live `opener` — cut it\n // (2026-08-19 review). Costs nothing in the strict case.\n window.open(url, '_blank', 'noopener');\n // Revoke either way (a blocked popup would otherwise leak the Blob until\n // page unload — 2026-08 project review, pkg-small-09). With `noopener`\n // `window.open` returns null even on success, so the blocked case cannot\n // be told apart any more: always give the opened document the grace\n // period to finish loading before the URL goes away.\n setTimeout(() => URL.revokeObjectURL(url), 5000);\n};\n\n/**\n * Interactive mermaid diagram renderer.\n *\n * Parses and renders mermaid diagram source code into an inline SVG visualization.\n * Automatically adapts to the current Mantine color scheme (light/dark) by\n * re-initializing mermaid with the appropriate theme.\n *\n * Features:\n * - Live SVG rendering with automatic dark/light theme switching\n * - Fallback to raw source code display on parse/render errors\n * - Toggle between rendered diagram and raw mermaid source\n * - Click on the rendered diagram to open the SVG in a new browser window\n * - Copy button for the raw mermaid source code\n * - Chart type label extracted from mermaid's parse result\n * - Preserves the last successful render across transient parse failures\n *\n * ## Streaming contract\n *\n * While `streaming` is true (from render state), the code prop is usually a\n * truncated prefix of the final diagram, so parse failures are *expected*,\n * not exceptional:\n * - Before the first successful render, the raw source is shown as a plain\n * code block (never the error tab).\n * - After a success, the last good SVG stays up; each subsequent chunk is\n * re-attempted and the diagram refreshes only on the next success.\n * - When streaming ends (`streaming` is an effect dep), one corrective pass\n * runs on the final code: success refreshes the diagram, failure surfaces\n * the real error tab — even over a previously rendered mid-stream diagram,\n * because that diagram no longer matches the final source. The pending\n * corrective obligation is tracked by `needsCorrectiveRef` (armed on the\n * streaming→false edge, consumed by the next completed attempt), so ONLY\n * that one pass may clobber a rendered diagram; any later failure (e.g. a\n * transient throw on a theme-flip re-render) falls back to the static rule\n * below.\n * - A streaming→true edge marks a NEW generation (chat \"regenerate\" reuses\n * the same component instance when the block's source offset — and thus\n * its React key — is unchanged). All per-generation state is reset so the\n * warm-up shows the new source instead of the previous generation's stale\n * diagram or error tab.\n *\n * ## Static contract (`streaming` stays false)\n *\n * Without streaming edges, failures follow the original conservative rule:\n * the error tab shows only while nothing has rendered yet. Once a diagram is\n * up, later failures (theme-flip re-render, a not-yet-complete `code` update\n * from a consumer that didn't pass `streaming`) keep the last good diagram\n * instead of clobbering it with an error.\n *\n * @param props.code - Raw mermaid diagram source code to render.\n */\nconst MantineAIMMermaidCode = memo((props: { code: string }) => {\n const { colorScheme, fontSize } = useAIMarkdownTheme();\n const { streaming } = useAIMarkdownState();\n const { defaultExpanded } = useMantineCodeBlockOptions();\n const isDark = colorScheme === 'dark';\n\n const ref = useRef<HTMLPreElement>(null);\n const renderVersionRef = useRef(0);\n /** Mirrors `view` for reads inside the async render closure — state reads\n * there can be stale when deps change mid-flight. */\n const viewRef = useRef<MermaidView>({ kind: 'source' });\n /** Previous `streaming` value, for edge detection in the effect. */\n const prevStreamingRef = useRef(false);\n /** Armed on the streaming→false edge: the next completed render attempt is\n * the end-of-stream corrective pass, whose failure must surface even over\n * a rendered diagram. Consumed (reset) by that attempt's success OR\n * surfaced failure, so later unrelated failures can't clobber the SVG. */\n const needsCorrectiveRef = useRef(false);\n /** Inputs of the render whose SVG currently sits in the host `<pre>`.\n * When the effect re-runs with the same (code, theme) pair — the\n * post-stream corrective flip on an already-final diagram, or returning\n * from the source view — the DOM already holds that exact render, so\n * the attempt (and its parse + temp-element render) is skipped. */\n const lastSuccessRef = useRef<{ code: string; isDark: boolean } | null>(null);\n const [view, setViewState] = useState<MermaidView>({ kind: 'source' });\n const [showOriginalCode, setShowOriginalCode] = useState(false);\n /** Bumped (after a short delay) when the mermaid MODULE failed to load, so\n * the effect re-runs on otherwise unchanged inputs and retries the\n * download. A download failure is not a diagram error: it must neither\n * consume the corrective obligation nor show the error tab (v2.4.1\n * review — the corrective pass is one-shot, so a transient network\n * failure on it left a permanent \"Render Error\" that nothing re-tried).\n * Bounded by MERMAID_LOAD_RETRIES per generation. */\n const [loadAttempt, setLoadAttempt] = useState(0);\n const loadFailuresRef = useRef(0);\n\n useEffect(() => {\n // View updates funnel through here so the ref mirror can't desync from\n // the state, and no-op updates are dropped (repeat mid-stream successes\n // and idempotent edge resets must not re-render the host per chunk).\n const applyView = (next: MermaidView) => {\n viewRef.current = next;\n setViewState((prev) => (sameView(prev, next) ? prev : next));\n };\n\n // Streaming edge detection MUST run before any early return — the first\n // chunk of a new stream can arrive while the code is still empty.\n if (streaming && !prevStreamingRef.current) {\n // Rising edge = a new generation is starting on this same instance\n // (same block offset → same React key → no remount on regenerate).\n // Reset all per-generation state so warm-up shows the incoming source,\n // not the previous generation's stale diagram or error tab. Everything\n // here is idempotent — a StrictMode double-run is harmless.\n needsCorrectiveRef.current = false;\n lastSuccessRef.current = null;\n loadFailuresRef.current = 0;\n applyView({ kind: 'source' });\n if (ref.current) {\n ref.current.innerHTML = '';\n }\n } else if (!streaming && prevStreamingRef.current) {\n // Falling edge = the stream just ended; arm the corrective pass.\n needsCorrectiveRef.current = true;\n }\n prevStreamingRef.current = streaming;\n if (!props.code || !ref.current || showOriginalCode) {\n return;\n }\n\n // The SVG in the DOM already came from exactly this (code, theme) pair —\n // nothing to recompute. This also SATISFIES a pending corrective\n // obligation: the identical successful render IS the verdict on the\n // final source, so the obligation is consumed, not left armed for some\n // later unrelated failure to inherit.\n if (lastSuccessRef.current?.code === props.code && lastSuccessRef.current.isDark === isDark) {\n needsCorrectiveRef.current = false;\n return;\n }\n\n const renderVersion = ++renderVersionRef.current;\n let cancelled = false;\n\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n const renderMermaid = async () => {\n let mermaid: Mermaid;\n try {\n mermaid = await loadMermaid();\n } catch {\n // Module load failed: keep whatever is showing (source view or the\n // last diagram), leave the corrective obligation armed, and retry\n // the download a bounded number of times.\n if (cancelled || renderVersion !== renderVersionRef.current) return;\n if (loadFailuresRef.current < MERMAID_LOAD_RETRIES) {\n loadFailuresRef.current += 1;\n retryTimer = setTimeout(() => setLoadAttempt((n) => n + 1), MERMAID_LOAD_RETRY_MS);\n }\n return;\n }\n loadFailuresRef.current = 0;\n try {\n if (!ref.current || cancelled || renderVersion !== renderVersionRef.current) {\n return;\n }\n ensureMermaidInitialized(mermaid, isDark);\n const parseResult = await mermaid.parse(props.code);\n if (!parseResult) {\n throw new Error('Failed to parse mermaid code');\n }\n\n if (!ref.current || cancelled || renderVersion !== renderVersionRef.current) {\n return;\n }\n\n // Deliberately NOT passing `ref.current` as mermaid's\n // svgContainingElement: before the first success the host container\n // is hidden with `display: none` (source fallback is showing), and\n // mermaid measures text via getBBox during render — inside a\n // display:none subtree layout never runs, every measurement is 0,\n // and the diagram comes out as a ~16px SVG. With the argument\n // omitted, mermaid renders in a temp element appended to\n // `document.body` (its default path, cleaned up internally), so\n // measurement works no matter what our container is doing. The SVG\n // string is written into our own <pre> below either way.\n // mermaid's config is a module singleton and the awaits above yield:\n // an instance under the OTHER color scheme may have re-initialized\n // in between, in which case this render came out in the wrong theme.\n // Re-assert and render once more; a second flip is vanishingly\n // unlikely and would self-heal on the next attempt anyway\n // (2026-08 project review, pkg-small-11).\n let rendered = await mermaid.render(generateMermaidUUID(), props.code);\n if (initializedTheme !== (isDark ? 'dark' : 'light')) {\n if (!ref.current || cancelled || renderVersion !== renderVersionRef.current) {\n return;\n }\n ensureMermaidInitialized(mermaid, isDark);\n rendered = await mermaid.render(generateMermaidUUID(), props.code);\n }\n const { svg, bindFunctions, diagramType } = rendered;\n if (!ref.current || cancelled || renderVersion !== renderVersionRef.current) {\n return;\n }\n\n ref.current.innerHTML = svg;\n bindFunctions?.(ref.current);\n needsCorrectiveRef.current = false;\n lastSuccessRef.current = { code: props.code, isDark };\n applyView({ kind: 'diagram', chartType: diagramType });\n } catch {\n if (cancelled || renderVersion !== renderVersionRef.current) {\n return;\n }\n // Mid-stream failures are expected (truncated code) — keep the last\n // good diagram / source placeholder and wait for more bytes. The\n // corrective pass after streaming ends reports real errors.\n if (streaming) {\n return;\n }\n // End-of-stream corrective pass: the final source no longer renders,\n // so the error must surface even over a mid-stream diagram. Consume\n // the obligation so later unrelated failures don't inherit it.\n if (needsCorrectiveRef.current) {\n needsCorrectiveRef.current = false;\n applyView({ kind: 'error' });\n return;\n }\n // Static rule: never clobber a rendered diagram (theme-flip\n // re-renders, un-flagged code updates from static consumers).\n if (viewRef.current.kind === 'diagram') {\n return;\n }\n applyView({ kind: 'error' });\n }\n };\n\n void renderMermaid();\n\n return () => {\n cancelled = true;\n if (retryTimer !== undefined) clearTimeout(retryTimer);\n };\n // `streaming` in the deps is what drives the end-of-stream corrective\n // pass: the flip to false re-runs this effect on the (unchanged) final\n // code, so the last state reflects the full diagram source.\n // `loadAttempt` re-runs it after a failed module download.\n }, [props.code, isDark, showOriginalCode, streaming, loadAttempt]);\n\n const viewSvgInNewWindow = useCallback(() => {\n handleViewSVGInNewWindow(ref.current?.querySelector('svg'), isDark);\n }, [isDark]);\n\n // Show the raw source instead of the diagram container when the user asked\n // for it, when the (post-stream) render failed, or before the first\n // successful render (SSR output and the streaming warm-up phase). The\n // diagram container below stays MOUNTED throughout — merely hidden — so\n // `ref` is always available for mermaid to render into; unmounting it would\n // make the effect's `!ref.current` guard bail forever.\n const showSourceFallback = showOriginalCode || view.kind !== 'diagram';\n\n return (\n <>\n {showSourceFallback && (\n <CodeHighlightTabs\n mb={15}\n fz={fontSize}\n w=\"100%\"\n code={[\n {\n fileName: view.kind === 'error' ? 'Mermaid Render Error' : 'mermaid',\n code: props.code,\n language: 'mermaid',\n },\n ]}\n defaultExpanded={defaultExpanded}\n maxCollapsedHeight=\"320px\"\n styles={{\n filesScrollarea: {\n right: '90px',\n },\n }}\n controls={\n // The \"Render Mermaid\" control only makes sense as the way back\n // from the user-toggled source view. In the error and warm-up\n // fallbacks `showOriginalCode` is already false, so the control\n // would be a no-op — hide it there. (No view-kind conjunct: the\n // toggle is only reachable from the visible diagram view, and\n // while the source view is open the effect early-returns, so\n // showOriginalCode && view.kind === 'error' is unreachable.)\n showOriginalCode\n ? [\n <CodeHighlightControl\n tooltipLabel=\"Render Mermaid\"\n key=\"gpt\"\n onClick={() => {\n setShowOriginalCode(false);\n }}\n >\n <Flex align=\"center\" justify=\"center\" w={18} h={18}>\n <span className=\"icon-[gravity-ui--logo-mermaid] relative bottom-[1px] text-[16px]\"></span>\n </Flex>\n </CodeHighlightControl>,\n ]\n : []\n }\n withBorder\n withExpandButton\n />\n )}\n <div\n className={`aim-mantine-mermaid-code ${isDark ? 'dark' : ''}`}\n style={\n showSourceFallback\n ? {\n display: 'none',\n }\n : {}\n }\n >\n <div className=\"chart-header\">\n <div className=\"chart-type-tag\">{view.kind === 'diagram' ? view.chartType : 'unknown'}</div>\n <Flex align=\"center\" justify=\"flex-end\" gap={0}>\n {/* The \"open in a new window\" action is a real button here rather\n than a `role=\"button\"` on the SVG container: a button's\n content is presentational to assistive tech, so the diagram's\n own text and mermaid's accTitle/accDescr were unreachable, and\n any `click … href` link mermaid emitted sat inside a button\n (invalid, not tabbable) — 2026-08-19 review r2 P3. The\n container below carries no role at all, for the same reason. */}\n {/* Always rendered (also under SSR / the source warm-up, where it\n is a no-op until the SVG exists) so server and client markup\n agree. */}\n {\n <Tooltip label=\"Open in new window\">\n <ActionIcon\n size={28}\n className=\"action-icon\"\n variant=\"transparent\"\n aria-label=\"Open Mermaid diagram in a new window\"\n onClick={viewSvgInNewWindow}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n strokeWidth=\"2\"\n stroke=\"currentColor\"\n fill=\"none\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width=\"18px\"\n height=\"18px\"\n aria-hidden=\"true\"\n >\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"></path>\n <path d=\"M12 6h-6a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-6\"></path>\n <path d=\"M11 13l9 -9\"></path>\n <path d=\"M15 4h5v5\"></path>\n </svg>\n </ActionIcon>\n </Tooltip>\n }\n <Tooltip label=\"Show Mermaid Code\">\n <ActionIcon\n size={28}\n className=\"action-icon\"\n variant=\"transparent\"\n aria-label=\"Show Mermaid code\"\n onClick={() => {\n setShowOriginalCode(true);\n }}\n >\n <Flex align=\"center\" justify=\"center\" w={18} h={18}>\n <span className=\"icon-[entypo--code] relative bottom-[0.25px] text-[16px]\"></span>\n </Flex>\n </ActionIcon>\n </Tooltip>\n <CopyButton value={props.code}>\n {({ copied, copy }) => (\n <Tooltip label={copied ? 'Copied' : 'Copy'} withArrow position=\"right\">\n <ActionIcon\n variant=\"transparent\"\n size={28}\n className=\"action-icon\"\n aria-label={copied ? 'Mermaid code copied' : 'Copy Mermaid code'}\n onClick={copy}\n >\n {copied ? (\n <span className=\"icon-origin-[lucide--check] text-[18px]\"></span>\n ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n strokeWidth=\"2\"\n stroke=\"currentColor\"\n fill=\"none\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width=\"18px\"\n height=\"18px\"\n >\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"></path>\n <path d=\"M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z\"></path>\n <path d=\"M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2\"></path>\n </svg>\n )}\n </ActionIcon>\n </Tooltip>\n )}\n </CopyButton>\n </Flex>\n </div>\n {/* No ARIA role on the container: `role=\"img\"` (like the old\n `role=\"button\"`) makes its children presentational and hides the\n SVG's own `role=\"graphics-document\"` + accTitle/accDescr that\n mermaid emits — the SVG names itself. Click-to-open stays as a\n pointer convenience; the keyboard/AT path is the header button. */}\n <pre ref={ref} style={PRE_STYLE} onClick={viewSvgInNewWindow} />\n </div>\n </>\n );\n});\n\nMantineAIMMermaidCode.displayName = 'MantineAIMMermaidCode';\n\nexport default MantineAIMMermaidCode;\n","/**\n * Widened `define*` factory for the mantine wrapper (EXECUTION-PLAN §4\n * item 8): identity + mantine prop types + freeze, zero logic. Core\n * factories accept core fields only — passing `codeBlock` to core's\n * `defineBehaviors` is a TS error; this widened factory is the wrapper's\n * one-line obligation.\n *\n * @module define\n */\n\nimport type { AIMarkdownBehaviorProps } from '@ai-react-markdown/core';\nimport type { MantineCodeBlockOptions } from './defs';\n\n/** Behavior-system props packagable at integration time, mantine-widened. */\nexport interface MantineBehaviorProps extends AIMarkdownBehaviorProps {\n /** The mantine `codeBlock` behavior group (atomic replacement; defaults applied at read time). */\n codeBlock?: Partial<MantineCodeBlockOptions>;\n}\n\n// NON-generic on purpose — see core's `define.ts`: a fresh literal is\n// excess-property checked against the concrete parameter type.\n\n/** Freeze a mantine behaviors fragment. Identity + types + freeze; zero logic. */\nexport function defineMantineBehaviors(values: MantineBehaviorProps): Readonly<MantineBehaviorProps> {\n return Object.freeze(values);\n}\n","import { useAIMarkdownMetadata } from '@ai-react-markdown/core';\nimport { MantineAIMarkdownMetadata } from '../defs';\n\n/**\n * Typed wrapper around the core {@link useAIMarkdownMetadata} hook.\n *\n * Returns the current metadata defaulting to {@link MantineAIMarkdownMetadata}.\n * Accepts an optional generic parameter for further extension.\n *\n * Metadata lives in a separate React context from the render state, meaning\n * metadata updates do not trigger re-renders in components that only consume\n * render state.\n *\n * Must be called inside a component rendered within the `<MantineAIMarkdown>` tree.\n *\n * @typeParam TMetadata - Metadata type (defaults to {@link MantineAIMarkdownMetadata}).\n * @returns The current metadata, or `undefined` if none was provided.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const metadata = useMantineAIMarkdownMetadata();\n * // Access Mantine-specific metadata fields\n * }\n * ```\n */\nexport const useMantineAIMarkdownMetadata = <\n TMetadata extends MantineAIMarkdownMetadata = MantineAIMarkdownMetadata,\n>() => {\n return useAIMarkdownMetadata<TMetadata>();\n};\n"],"mappings":"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","names":["import_react","import_core","import_jsx_runtime","import_react","import_code_highlight","import_core","import_react","import_core","import_react","import_core","import_jsx_runtime","import_jsx_runtime","SpecialCodeLanguage","import_core","import_jsx_runtime","Typography","AIMarkdown","import_core"]}
|
package/dist/index.css
CHANGED
|
@@ -103,26 +103,28 @@
|
|
|
103
103
|
.aim-mantine-extra-styles dl > * {
|
|
104
104
|
padding-top: calc(var(--aim-font-size-mantine-base) * 0.5);
|
|
105
105
|
}
|
|
106
|
+
.aim-mantine-extra-styles {
|
|
107
|
+
}
|
|
106
108
|
.aim-mantine-extra-styles dt {
|
|
107
109
|
width: 30%;
|
|
108
110
|
font-weight: bold;
|
|
109
|
-
text-align:
|
|
111
|
+
text-align: end;
|
|
110
112
|
}
|
|
111
113
|
.aim-mantine-extra-styles dd {
|
|
112
114
|
width: 60%;
|
|
113
|
-
padding-
|
|
114
|
-
margin-
|
|
115
|
+
padding-inline-start: calc(var(--aim-font-size-mantine-base) * 0.5);
|
|
116
|
+
margin-inline-start: 0px;
|
|
115
117
|
}
|
|
116
118
|
.aim-mantine-extra-styles dd + dd {
|
|
117
119
|
width: 100%;
|
|
118
|
-
padding-
|
|
120
|
+
padding-inline-start: calc(30% + var(--aim-font-size-mantine-base));
|
|
119
121
|
}
|
|
120
122
|
.aim-mantine-extra-styles dt + dt {
|
|
121
|
-
padding-
|
|
123
|
+
padding-inline-end: 60%;
|
|
122
124
|
}
|
|
123
125
|
.aim-mantine-extra-styles dt + dt + dd {
|
|
124
126
|
margin-top: calc(var(--aim-font-size-mantine-base) * -1.625);
|
|
125
|
-
padding-
|
|
127
|
+
padding-inline-start: calc(30% + var(--aim-font-size-mantine-base));
|
|
126
128
|
}
|
|
127
129
|
|
|
128
130
|
/* src/components/customized/MermaidCode/styles.scss */
|
|
@@ -148,19 +150,18 @@
|
|
|
148
150
|
}
|
|
149
151
|
.aim-mantine-mermaid-code .chart-header .chart-type-tag {
|
|
150
152
|
padding: calc(0.2125rem * var(--mantine-scale)) calc(0.5625rem * var(--mantine-scale));
|
|
151
|
-
color: var(--mantine-color-
|
|
153
|
+
color: var(--mantine-color-black);
|
|
152
154
|
border: 1px solid var(--mantine-color-gray-3);
|
|
153
|
-
background: var(--mantine-color-
|
|
155
|
+
background: var(--mantine-color-white);
|
|
154
156
|
border-radius: var(--mantine-radius-default);
|
|
155
157
|
font-size: var(--mantine-font-size-xs);
|
|
156
158
|
font-weight: 700;
|
|
157
159
|
}
|
|
158
160
|
.aim-mantine-mermaid-code .chart-header .action-icon {
|
|
159
|
-
color: var(--mantine-color-
|
|
161
|
+
color: var(--mantine-color-black);
|
|
160
162
|
opacity: 0.5;
|
|
161
163
|
}
|
|
162
164
|
.aim-mantine-mermaid-code .chart-header .action-icon:hover {
|
|
163
|
-
color: var(--mantine-color-bright);
|
|
164
165
|
opacity: 1;
|
|
165
166
|
}
|
|
166
167
|
.aim-mantine-mermaid-code > pre {
|
|
@@ -182,4 +183,7 @@
|
|
|
182
183
|
.aim-mantine-mermaid-code.dark .chart-header .action-icon {
|
|
183
184
|
color: var(--mantine-color-dark-0);
|
|
184
185
|
}
|
|
186
|
+
.aim-mantine-mermaid-code.dark .chart-header .action-icon:hover {
|
|
187
|
+
color: var(--mantine-color-white);
|
|
188
|
+
}
|
|
185
189
|
/*# sourceMappingURL=index.css.map */
|