@frontmcp/ui 1.11.1 → 1.11.3
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/bridge/adapters/index.d.ts.map +1 -1
- package/bridge/core/adapter-registry.d.ts +1 -1
- package/bridge/core/adapter-registry.d.ts.map +1 -1
- package/components/Alert/Alert.d.ts.map +1 -1
- package/components/Alert/index.js +1 -1
- package/components/Avatar/Avatar.d.ts.map +1 -1
- package/components/Badge/Badge.d.ts.map +1 -1
- package/components/Badge/index.js +1 -1
- package/components/Button/Button.d.ts.map +1 -1
- package/components/Button/index.js +1 -1
- package/components/Card/Card.d.ts +3 -3
- package/components/Card/Card.d.ts.map +1 -1
- package/components/Card/index.js +4 -4
- package/components/List/List.d.ts.map +1 -1
- package/components/List/index.js +2 -2
- package/components/Loader/Loader.d.ts +1 -1
- package/components/Loader/Loader.d.ts.map +1 -1
- package/components/Loader/index.js +2 -2
- package/components/Modal/Modal.d.ts +1 -1
- package/components/Modal/Modal.d.ts.map +1 -1
- package/components/Modal/index.js +3 -3
- package/components/Select/Select.d.ts.map +1 -1
- package/components/Select/index.js +1 -1
- package/components/Table/Table.d.ts.map +1 -1
- package/components/Table/index.js +1 -1
- package/components/TextField/TextField.d.ts.map +1 -1
- package/components/index.js +16 -16
- package/esm/components/Alert/index.mjs +1 -1
- package/esm/components/Badge/index.mjs +1 -1
- package/esm/components/Button/index.mjs +1 -1
- package/esm/components/Card/index.mjs +4 -4
- package/esm/components/List/index.mjs +2 -2
- package/esm/components/Loader/index.mjs +2 -2
- package/esm/components/Modal/index.mjs +3 -3
- package/esm/components/Select/index.mjs +1 -1
- package/esm/components/Table/index.mjs +1 -1
- package/esm/components/index.mjs +16 -16
- package/esm/package.json +2 -2
- package/esm/renderer/charts/index.mjs +21 -21
- package/esm/renderer/common/index.mjs +2 -2
- package/esm/renderer/csv/index.mjs +3 -3
- package/esm/renderer/flow/index.mjs +31 -31
- package/esm/renderer/html/index.mjs +1 -1
- package/esm/renderer/image/index.mjs +3 -3
- package/esm/renderer/index.mjs +1584 -1578
- package/esm/renderer/maps/index.mjs +16 -16
- package/esm/renderer/math/index.mjs +15 -15
- package/esm/renderer/mdx/index.mjs +7 -5
- package/esm/renderer/media/index.mjs +2 -2
- package/esm/renderer/mermaid/index.mjs +3 -3
- package/esm/renderer/pdf/index.mjs +4 -4
- package/esm/renderer/react/index.mjs +8 -8
- package/esm/theme/index.mjs +1 -1
- package/package.json +2 -2
- package/renderer/auto-detect.d.ts +1 -1
- package/renderer/auto-detect.d.ts.map +1 -1
- package/renderer/charts/index.d.ts.map +1 -1
- package/renderer/charts/index.js +22 -22
- package/renderer/common/index.js +1 -1
- package/renderer/common/use-lazy-module.d.ts.map +1 -1
- package/renderer/common/use-renderer-theme.d.ts.map +1 -1
- package/renderer/csv/index.d.ts.map +1 -1
- package/renderer/csv/index.js +3 -3
- package/renderer/flow/index.d.ts.map +1 -1
- package/renderer/flow/index.js +32 -32
- package/renderer/html/index.d.ts.map +1 -1
- package/renderer/html/index.js +1 -1
- package/renderer/image/index.d.ts.map +1 -1
- package/renderer/image/index.js +3 -3
- package/renderer/index.d.ts.map +1 -1
- package/renderer/index.js +1593 -1587
- package/renderer/maps/index.d.ts.map +1 -1
- package/renderer/maps/index.js +15 -15
- package/renderer/math/index.d.ts.map +1 -1
- package/renderer/math/index.js +14 -14
- package/renderer/mdx/index.d.ts.map +1 -1
- package/renderer/mdx/index.js +6 -4
- package/renderer/media/index.d.ts.map +1 -1
- package/renderer/media/index.js +1 -1
- package/renderer/mermaid/index.d.ts.map +1 -1
- package/renderer/mermaid/index.js +3 -3
- package/renderer/pdf/index.d.ts.map +1 -1
- package/renderer/pdf/index.js +3 -3
- package/renderer/react/index.d.ts.map +1 -1
- package/renderer/react/index.js +8 -8
- package/renderer/types.d.ts +1 -1
- package/renderer/types.d.ts.map +1 -1
- package/theme/FrontMcpThemeProvider.d.ts.map +1 -1
- package/theme/create-theme.d.ts.map +1 -1
- package/theme/index.js +1 -1
package/renderer/index.js
CHANGED
|
@@ -262,54 +262,12 @@ function ContentViewInner({ content, options }) {
|
|
|
262
262
|
return renderContent(content, options);
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
-
// libs/ui/src/renderer/
|
|
266
|
-
var
|
|
267
|
-
var
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
mode: palette.mode,
|
|
272
|
-
primary: palette.primary.main,
|
|
273
|
-
secondary: palette.secondary.main,
|
|
274
|
-
error: palette.error.main,
|
|
275
|
-
warning: palette.warning.main,
|
|
276
|
-
success: palette.success.main,
|
|
277
|
-
info: palette.info.main,
|
|
278
|
-
background: palette.background.default,
|
|
279
|
-
paper: palette.background.paper,
|
|
280
|
-
textPrimary: palette.text.primary,
|
|
281
|
-
textSecondary: palette.text.secondary,
|
|
282
|
-
divider: palette.divider,
|
|
283
|
-
fontFamily: theme.typography.fontFamily ?? "sans-serif",
|
|
284
|
-
monoFontFamily: theme.typography["monoFontFamily"] ?? '"SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", monospace',
|
|
285
|
-
fontSize: theme.typography.fontSize ?? 14,
|
|
286
|
-
borderRadius: typeof theme.shape.borderRadius === "number" ? theme.shape.borderRadius : 4,
|
|
287
|
-
seriesColors: [
|
|
288
|
-
palette.primary.main,
|
|
289
|
-
palette.secondary.main,
|
|
290
|
-
palette.error.main,
|
|
291
|
-
palette.warning.main,
|
|
292
|
-
palette.success.main,
|
|
293
|
-
palette.info.main
|
|
294
|
-
]
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
function useRendererTheme() {
|
|
298
|
-
const theme = (0, import_styles.useTheme)();
|
|
299
|
-
return (0, import_react2.useMemo)(() => extractThemeValues(theme), [theme]);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// libs/ui/src/renderer/common/inject-stylesheet.ts
|
|
303
|
-
function injectStylesheet(href, id) {
|
|
304
|
-
if (typeof document === "undefined") return;
|
|
305
|
-
if (document.getElementById(id)) return;
|
|
306
|
-
const link = document.createElement("link");
|
|
307
|
-
link.id = id;
|
|
308
|
-
link.rel = "stylesheet";
|
|
309
|
-
link.href = href;
|
|
310
|
-
link.crossOrigin = "anonymous";
|
|
311
|
-
document.head.appendChild(link);
|
|
312
|
-
}
|
|
265
|
+
// libs/ui/src/renderer/charts/index.ts
|
|
266
|
+
var import_Alert = __toESM(require("@mui/material/Alert"));
|
|
267
|
+
var import_Box = __toESM(require("@mui/material/Box"));
|
|
268
|
+
var import_styles2 = require("@mui/material/styles");
|
|
269
|
+
var import_Typography = __toESM(require("@mui/material/Typography"));
|
|
270
|
+
var import_react4 = __toESM(require("react"));
|
|
313
271
|
|
|
314
272
|
// libs/ui/src/renderer/common/lazy-import.ts
|
|
315
273
|
var ESM_SH_BASE = "https://esm.sh/";
|
|
@@ -371,10 +329,10 @@ function createLazyImport(moduleId, importer) {
|
|
|
371
329
|
}
|
|
372
330
|
|
|
373
331
|
// libs/ui/src/renderer/common/use-lazy-module.ts
|
|
374
|
-
var
|
|
332
|
+
var import_react2 = require("react");
|
|
375
333
|
function useLazyModule(lazy) {
|
|
376
|
-
const [, forceUpdate] = (0,
|
|
377
|
-
(0,
|
|
334
|
+
const [, forceUpdate] = (0, import_react2.useState)(0);
|
|
335
|
+
(0, import_react2.useEffect)(() => {
|
|
378
336
|
if (lazy.getState().status === "loaded") {
|
|
379
337
|
forceUpdate((n) => n + 1);
|
|
380
338
|
return;
|
|
@@ -387,206 +345,605 @@ function useLazyModule(lazy) {
|
|
|
387
345
|
return lazy.get();
|
|
388
346
|
}
|
|
389
347
|
|
|
390
|
-
// libs/ui/src/renderer/
|
|
391
|
-
var
|
|
392
|
-
var
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
var import_Table = __toESM(require("@mui/material/Table"));
|
|
396
|
-
var import_TableBody = __toESM(require("@mui/material/TableBody"));
|
|
397
|
-
var import_TableCell = __toESM(require("@mui/material/TableCell"));
|
|
398
|
-
var import_TableHead = __toESM(require("@mui/material/TableHead"));
|
|
399
|
-
var import_TableRow = __toESM(require("@mui/material/TableRow"));
|
|
400
|
-
var import_styles2 = require("@mui/material/styles");
|
|
401
|
-
var lazyReactMarkdown = createLazyImport(
|
|
402
|
-
"react-markdown",
|
|
403
|
-
async () => {
|
|
404
|
-
const mod = await runtimeImportWithFallback(
|
|
405
|
-
"react-markdown",
|
|
406
|
-
esmShUrl("react-markdown@9", { external: ["react", "react-dom"] })
|
|
407
|
-
);
|
|
408
|
-
return mod;
|
|
409
|
-
}
|
|
410
|
-
);
|
|
411
|
-
var lazyRemarkGfm = createLazyImport("remark-gfm", async () => {
|
|
412
|
-
const mod = await runtimeImportWithFallback("remark-gfm", esmShUrl("remark-gfm@4"));
|
|
413
|
-
return mod;
|
|
414
|
-
});
|
|
415
|
-
var lazyRehypeHighlight = createLazyImport("rehype-highlight", async () => {
|
|
416
|
-
const mod = await runtimeImportWithFallback("rehype-highlight", esmShUrl("rehype-highlight@7"));
|
|
417
|
-
return mod;
|
|
418
|
-
});
|
|
419
|
-
var lazyRehypeRaw = createLazyImport("rehype-raw", async () => {
|
|
420
|
-
const mod = await runtimeImportWithFallback("rehype-raw", esmShUrl("rehype-raw@7"));
|
|
421
|
-
return mod;
|
|
422
|
-
});
|
|
423
|
-
var MarkdownRoot = (0, import_styles2.styled)(import_Box.default, {
|
|
424
|
-
name: "FrontMcpMarkdown",
|
|
425
|
-
slot: "Root"
|
|
426
|
-
})(() => ({
|
|
427
|
-
lineHeight: 1.7,
|
|
428
|
-
"& > *:first-of-type": { marginTop: 0 },
|
|
429
|
-
"& > *:last-child": { marginBottom: 0 },
|
|
430
|
-
"& img": { maxWidth: "100%", height: "auto" }
|
|
431
|
-
}));
|
|
432
|
-
var CodeBlock = (0, import_styles2.styled)("pre", {
|
|
433
|
-
name: "FrontMcpMarkdown",
|
|
434
|
-
slot: "Code"
|
|
435
|
-
})(({ theme }) => {
|
|
436
|
-
const monoFont = String(
|
|
437
|
-
theme.typography["monoFontFamily"] ?? '"SF Mono", "Fira Code", "Roboto Mono", monospace'
|
|
438
|
-
);
|
|
439
|
-
return {
|
|
440
|
-
backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[900] : theme.palette.grey[100],
|
|
441
|
-
padding: theme.spacing(2),
|
|
442
|
-
borderRadius: Number(theme.shape.borderRadius),
|
|
443
|
-
overflow: "auto",
|
|
444
|
-
fontFamily: monoFont,
|
|
445
|
-
fontSize: "0.875rem",
|
|
446
|
-
"& code": {
|
|
447
|
-
backgroundColor: "transparent",
|
|
448
|
-
padding: 0,
|
|
449
|
-
fontSize: "inherit",
|
|
450
|
-
fontFamily: "inherit"
|
|
451
|
-
}
|
|
452
|
-
};
|
|
453
|
-
});
|
|
454
|
-
var InlineCode = (0, import_styles2.styled)("code")(({ theme }) => {
|
|
455
|
-
const monoFont = String(
|
|
456
|
-
theme.typography["monoFontFamily"] ?? '"SF Mono", "Fira Code", "Roboto Mono", monospace'
|
|
457
|
-
);
|
|
458
|
-
return {
|
|
459
|
-
backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[800] : theme.palette.grey[200],
|
|
460
|
-
padding: "2px 6px",
|
|
461
|
-
borderRadius: Number(theme.shape.borderRadius) / 2,
|
|
462
|
-
fontFamily: monoFont,
|
|
463
|
-
fontSize: "0.85em"
|
|
464
|
-
};
|
|
465
|
-
});
|
|
466
|
-
var Blockquote = (0, import_styles2.styled)("blockquote", {
|
|
467
|
-
name: "FrontMcpMarkdown",
|
|
468
|
-
slot: "Blockquote"
|
|
469
|
-
})(({ theme }) => ({
|
|
470
|
-
borderLeft: `4px solid ${theme.palette.primary.main}`,
|
|
471
|
-
margin: theme.spacing(2, 0),
|
|
472
|
-
padding: theme.spacing(1, 2),
|
|
473
|
-
color: theme.palette.text.secondary,
|
|
474
|
-
"& > p": { margin: 0 }
|
|
475
|
-
}));
|
|
476
|
-
function createMuiComponents() {
|
|
348
|
+
// libs/ui/src/renderer/common/use-renderer-theme.ts
|
|
349
|
+
var import_styles = require("@mui/material/styles");
|
|
350
|
+
var import_react3 = require("react");
|
|
351
|
+
function extractThemeValues(theme) {
|
|
352
|
+
const palette = theme.palette;
|
|
477
353
|
return {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
354
|
+
mode: palette.mode,
|
|
355
|
+
primary: palette.primary.main,
|
|
356
|
+
secondary: palette.secondary.main,
|
|
357
|
+
error: palette.error.main,
|
|
358
|
+
warning: palette.warning.main,
|
|
359
|
+
success: palette.success.main,
|
|
360
|
+
info: palette.info.main,
|
|
361
|
+
background: palette.background.default,
|
|
362
|
+
paper: palette.background.paper,
|
|
363
|
+
textPrimary: palette.text.primary,
|
|
364
|
+
textSecondary: palette.text.secondary,
|
|
365
|
+
divider: palette.divider,
|
|
366
|
+
fontFamily: theme.typography.fontFamily ?? "sans-serif",
|
|
367
|
+
monoFontFamily: theme.typography["monoFontFamily"] ?? '"SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", monospace',
|
|
368
|
+
fontSize: theme.typography.fontSize ?? 14,
|
|
369
|
+
borderRadius: typeof theme.shape.borderRadius === "number" ? theme.shape.borderRadius : 4,
|
|
370
|
+
seriesColors: [
|
|
371
|
+
palette.primary.main,
|
|
372
|
+
palette.secondary.main,
|
|
373
|
+
palette.error.main,
|
|
374
|
+
palette.warning.main,
|
|
375
|
+
palette.success.main,
|
|
376
|
+
palette.info.main
|
|
377
|
+
]
|
|
498
378
|
};
|
|
499
379
|
}
|
|
500
|
-
function
|
|
501
|
-
const
|
|
502
|
-
|
|
503
|
-
const remarkGfmMod = lazyRemarkGfm.get();
|
|
504
|
-
const rehypeHighlightMod = lazyRehypeHighlight.get();
|
|
505
|
-
const rehypeRawMod = lazyRehypeRaw.get();
|
|
506
|
-
if (ReactMarkdownMod) {
|
|
507
|
-
const ReactMarkdown = ReactMarkdownMod.default;
|
|
508
|
-
const remarkPlugins = [];
|
|
509
|
-
const rehypePlugins = [];
|
|
510
|
-
if (remarkGfmMod) remarkPlugins.push(remarkGfmMod.default);
|
|
511
|
-
if (rehypeHighlightMod) rehypePlugins.push(rehypeHighlightMod.default);
|
|
512
|
-
if (rehypeRawMod) rehypePlugins.push(rehypeRawMod.default);
|
|
513
|
-
return import_react4.default.createElement(
|
|
514
|
-
MarkdownRoot,
|
|
515
|
-
{ className },
|
|
516
|
-
import_react4.default.createElement(ReactMarkdown, {
|
|
517
|
-
children: content,
|
|
518
|
-
remarkPlugins,
|
|
519
|
-
rehypePlugins,
|
|
520
|
-
components
|
|
521
|
-
})
|
|
522
|
-
);
|
|
523
|
-
}
|
|
524
|
-
return import_react4.default.createElement(MarkdownRoot, { className }, ...renderFallback(content));
|
|
380
|
+
function useRendererTheme() {
|
|
381
|
+
const theme = (0, import_styles.useTheme)();
|
|
382
|
+
return (0, import_react3.useMemo)(() => extractThemeValues(theme), [theme]);
|
|
525
383
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
} else if (line.startsWith("## ")) {
|
|
534
|
-
elements.push(import_react4.default.createElement(import_Typography.default, { key: i, variant: "h5", gutterBottom: true }, line.slice(3)));
|
|
535
|
-
} else if (line.startsWith("### ")) {
|
|
536
|
-
elements.push(import_react4.default.createElement(import_Typography.default, { key: i, variant: "h6", gutterBottom: true }, line.slice(4)));
|
|
537
|
-
} else if (line.startsWith("- ") || line.startsWith("* ")) {
|
|
538
|
-
elements.push(import_react4.default.createElement("li", { key: i }, line.slice(2)));
|
|
539
|
-
} else if (line.startsWith("**") && line.endsWith("**")) {
|
|
540
|
-
elements.push(import_react4.default.createElement(import_Typography.default, { key: i, variant: "body1", sx: { fontWeight: 700 } }, line.slice(2, -2)));
|
|
541
|
-
} else if (line.trim()) {
|
|
542
|
-
elements.push(import_react4.default.createElement(import_Typography.default, { key: i, variant: "body1", sx: { mb: 2 } }, line));
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
return elements;
|
|
384
|
+
|
|
385
|
+
// libs/ui/src/renderer/charts/index.ts
|
|
386
|
+
var CHART_TYPE_RE2 = /"type"\s*:\s*"(?:bar|line|area|pie|scatter|radar|composed)"/;
|
|
387
|
+
function isChart(content) {
|
|
388
|
+
const trimmed = content.trim();
|
|
389
|
+
if (trimmed.charCodeAt(0) !== 123) return false;
|
|
390
|
+
return CHART_TYPE_RE2.test(trimmed) && trimmed.includes('"data"');
|
|
546
391
|
}
|
|
547
|
-
|
|
548
|
-
});
|
|
549
|
-
|
|
550
|
-
});
|
|
551
|
-
lazyRehypeHighlight.load().catch(() => {
|
|
552
|
-
});
|
|
553
|
-
lazyRehypeRaw.load().catch(() => {
|
|
392
|
+
var lazyRecharts = createLazyImport("recharts", async () => {
|
|
393
|
+
const mod = await runtimeImportWithFallback("recharts", esmShUrl("recharts@2", { external: ["react", "react-dom"] }));
|
|
394
|
+
return mod;
|
|
554
395
|
});
|
|
555
|
-
var
|
|
556
|
-
|
|
557
|
-
priority = 5;
|
|
558
|
-
canHandle(content) {
|
|
559
|
-
return /^---\s*\n/.test(content) || /import\s+/.test(content) || /<[A-Z]/.test(content) || /^#{1,6}\s+\S/m.test(content) || /^\s*[-*+]\s+\S/m.test(content);
|
|
560
|
-
}
|
|
561
|
-
render(content, options) {
|
|
562
|
-
return import_react4.default.createElement(MarkdownView, {
|
|
563
|
-
content,
|
|
564
|
-
className: options?.className ?? "fmcp-mdx-content"
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
};
|
|
568
|
-
var mdxRenderer = new MdxRenderer();
|
|
569
|
-
|
|
570
|
-
// libs/ui/src/renderer/html/index.ts
|
|
571
|
-
var import_react5 = __toESM(require("react"));
|
|
572
|
-
var import_Box2 = __toESM(require("@mui/material/Box"));
|
|
573
|
-
var import_styles3 = require("@mui/material/styles");
|
|
574
|
-
var HtmlRoot = (0, import_styles3.styled)(import_Box2.default, {
|
|
575
|
-
name: "FrontMcpHtml",
|
|
396
|
+
var ChartRoot = (0, import_styles2.styled)(import_Box.default, {
|
|
397
|
+
name: "FrontMcpChart",
|
|
576
398
|
slot: "Root"
|
|
577
399
|
})(({ theme }) => ({
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
"& th, & td": { border: `1px solid ${theme.palette.divider}`, padding: theme.spacing(1) },
|
|
581
|
-
"& pre": {
|
|
582
|
-
backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[900] : theme.palette.grey[100],
|
|
583
|
-
padding: theme.spacing(1.5),
|
|
584
|
-
borderRadius: theme.shape.borderRadius,
|
|
585
|
-
overflow: "auto"
|
|
586
|
-
}
|
|
400
|
+
width: "100%",
|
|
401
|
+
padding: theme.spacing(2)
|
|
587
402
|
}));
|
|
588
|
-
|
|
589
|
-
|
|
403
|
+
function ChartView({ config, className }) {
|
|
404
|
+
const themeValues = useRendererTheme();
|
|
405
|
+
const recharts = useLazyModule(lazyRecharts);
|
|
406
|
+
const colors = (0, import_react4.useMemo)(() => config.colors ?? themeValues.seriesColors, [config.colors, themeValues.seriesColors]);
|
|
407
|
+
if (!recharts) {
|
|
408
|
+
return import_react4.default.createElement(import_Alert.default, { severity: "info" }, "Loading chart library...");
|
|
409
|
+
}
|
|
410
|
+
const { ResponsiveContainer, Tooltip, Legend, CartesianGrid, XAxis, YAxis } = recharts;
|
|
411
|
+
const height = config.height ?? 400;
|
|
412
|
+
const xKey = config.xKey ?? "name";
|
|
413
|
+
const yKeys = config.yKeys ?? Object.keys(config.data?.[0] ?? {}).filter((k) => k !== xKey);
|
|
414
|
+
const chartContent = renderChartType(
|
|
415
|
+
recharts,
|
|
416
|
+
config.type,
|
|
417
|
+
config.data,
|
|
418
|
+
xKey,
|
|
419
|
+
yKeys,
|
|
420
|
+
colors,
|
|
421
|
+
themeValues.borderRadius
|
|
422
|
+
);
|
|
423
|
+
return import_react4.default.createElement(
|
|
424
|
+
ChartRoot,
|
|
425
|
+
{ className },
|
|
426
|
+
config.title && import_react4.default.createElement(
|
|
427
|
+
import_Typography.default,
|
|
428
|
+
{ variant: "subtitle1", gutterBottom: true, sx: { fontWeight: 600, textAlign: "center" } },
|
|
429
|
+
config.title
|
|
430
|
+
),
|
|
431
|
+
import_react4.default.createElement(ResponsiveContainer, { width: "100%", height }, chartContent)
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
function renderChartType(rc, type, data, xKey, yKeys, colors, borderRadius) {
|
|
435
|
+
const commonProps = { data };
|
|
436
|
+
const grid = import_react4.default.createElement(rc.CartesianGrid, { strokeDasharray: "3 3", opacity: 0.3 });
|
|
437
|
+
const xAxis = import_react4.default.createElement(rc.XAxis, { dataKey: xKey });
|
|
438
|
+
const yAxis = import_react4.default.createElement(rc.YAxis);
|
|
439
|
+
const tooltip = import_react4.default.createElement(rc.Tooltip, { contentStyle: { borderRadius } });
|
|
440
|
+
const legend = import_react4.default.createElement(rc.Legend);
|
|
441
|
+
switch (type) {
|
|
442
|
+
case "bar":
|
|
443
|
+
return import_react4.default.createElement(
|
|
444
|
+
rc.BarChart,
|
|
445
|
+
commonProps,
|
|
446
|
+
grid,
|
|
447
|
+
xAxis,
|
|
448
|
+
yAxis,
|
|
449
|
+
tooltip,
|
|
450
|
+
legend,
|
|
451
|
+
...yKeys.map(
|
|
452
|
+
(key, i) => import_react4.default.createElement(rc.Bar, {
|
|
453
|
+
key,
|
|
454
|
+
dataKey: key,
|
|
455
|
+
fill: colors[i % colors.length],
|
|
456
|
+
radius: [borderRadius, borderRadius, 0, 0]
|
|
457
|
+
})
|
|
458
|
+
)
|
|
459
|
+
);
|
|
460
|
+
case "line":
|
|
461
|
+
return import_react4.default.createElement(
|
|
462
|
+
rc.LineChart,
|
|
463
|
+
commonProps,
|
|
464
|
+
grid,
|
|
465
|
+
xAxis,
|
|
466
|
+
yAxis,
|
|
467
|
+
tooltip,
|
|
468
|
+
legend,
|
|
469
|
+
...yKeys.map(
|
|
470
|
+
(key, i) => import_react4.default.createElement(rc.Line, {
|
|
471
|
+
key,
|
|
472
|
+
type: "monotone",
|
|
473
|
+
dataKey: key,
|
|
474
|
+
stroke: colors[i % colors.length],
|
|
475
|
+
strokeWidth: 2
|
|
476
|
+
})
|
|
477
|
+
)
|
|
478
|
+
);
|
|
479
|
+
case "area":
|
|
480
|
+
return import_react4.default.createElement(
|
|
481
|
+
rc.AreaChart,
|
|
482
|
+
commonProps,
|
|
483
|
+
grid,
|
|
484
|
+
xAxis,
|
|
485
|
+
yAxis,
|
|
486
|
+
tooltip,
|
|
487
|
+
legend,
|
|
488
|
+
...yKeys.map(
|
|
489
|
+
(key, i) => import_react4.default.createElement(rc.Area, {
|
|
490
|
+
key,
|
|
491
|
+
type: "monotone",
|
|
492
|
+
dataKey: key,
|
|
493
|
+
stroke: colors[i % colors.length],
|
|
494
|
+
fill: colors[i % colors.length],
|
|
495
|
+
fillOpacity: 0.3
|
|
496
|
+
})
|
|
497
|
+
)
|
|
498
|
+
);
|
|
499
|
+
case "pie":
|
|
500
|
+
return import_react4.default.createElement(
|
|
501
|
+
rc.PieChart,
|
|
502
|
+
{},
|
|
503
|
+
tooltip,
|
|
504
|
+
legend,
|
|
505
|
+
import_react4.default.createElement(
|
|
506
|
+
rc.Pie,
|
|
507
|
+
{ data, dataKey: yKeys[0] ?? "value", nameKey: xKey, cx: "50%", cy: "50%", outerRadius: "80%", label: true },
|
|
508
|
+
...data.map((_, i) => import_react4.default.createElement(rc.Cell, { key: i, fill: colors[i % colors.length] }))
|
|
509
|
+
)
|
|
510
|
+
);
|
|
511
|
+
case "scatter":
|
|
512
|
+
return import_react4.default.createElement(
|
|
513
|
+
rc.ScatterChart,
|
|
514
|
+
{},
|
|
515
|
+
grid,
|
|
516
|
+
xAxis,
|
|
517
|
+
yAxis,
|
|
518
|
+
tooltip,
|
|
519
|
+
legend,
|
|
520
|
+
...yKeys.map(
|
|
521
|
+
(key, i) => import_react4.default.createElement(rc.Scatter, { key, name: key, dataKey: key, data, fill: colors[i % colors.length] })
|
|
522
|
+
)
|
|
523
|
+
);
|
|
524
|
+
case "radar":
|
|
525
|
+
return import_react4.default.createElement(
|
|
526
|
+
rc.RadarChart,
|
|
527
|
+
{ cx: "50%", cy: "50%", outerRadius: "80%", data },
|
|
528
|
+
import_react4.default.createElement(rc.PolarGrid),
|
|
529
|
+
import_react4.default.createElement(rc.PolarAngleAxis, { dataKey: xKey }),
|
|
530
|
+
import_react4.default.createElement(rc.PolarRadiusAxis),
|
|
531
|
+
tooltip,
|
|
532
|
+
legend,
|
|
533
|
+
...yKeys.map(
|
|
534
|
+
(key, i) => import_react4.default.createElement(rc.Radar, {
|
|
535
|
+
key,
|
|
536
|
+
name: key,
|
|
537
|
+
dataKey: key,
|
|
538
|
+
stroke: colors[i % colors.length],
|
|
539
|
+
fill: colors[i % colors.length],
|
|
540
|
+
fillOpacity: 0.3
|
|
541
|
+
})
|
|
542
|
+
)
|
|
543
|
+
);
|
|
544
|
+
case "composed":
|
|
545
|
+
return import_react4.default.createElement(
|
|
546
|
+
rc.ComposedChart,
|
|
547
|
+
commonProps,
|
|
548
|
+
grid,
|
|
549
|
+
xAxis,
|
|
550
|
+
yAxis,
|
|
551
|
+
tooltip,
|
|
552
|
+
legend,
|
|
553
|
+
...yKeys.map((key, i) => {
|
|
554
|
+
if (i % 2 === 0) {
|
|
555
|
+
return import_react4.default.createElement(rc.Bar, {
|
|
556
|
+
key,
|
|
557
|
+
dataKey: key,
|
|
558
|
+
fill: colors[i % colors.length],
|
|
559
|
+
radius: [borderRadius, borderRadius, 0, 0]
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
return import_react4.default.createElement(rc.Line, {
|
|
563
|
+
key,
|
|
564
|
+
type: "monotone",
|
|
565
|
+
dataKey: key,
|
|
566
|
+
stroke: colors[i % colors.length],
|
|
567
|
+
strokeWidth: 2
|
|
568
|
+
});
|
|
569
|
+
})
|
|
570
|
+
);
|
|
571
|
+
default:
|
|
572
|
+
return import_react4.default.createElement(rc.BarChart, commonProps, grid, xAxis, yAxis, tooltip, legend);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
lazyRecharts.load().catch(() => {
|
|
576
|
+
});
|
|
577
|
+
var ChartsRenderer = class {
|
|
578
|
+
type = "chart";
|
|
579
|
+
priority = 80;
|
|
580
|
+
canHandle(content) {
|
|
581
|
+
return isChart(content);
|
|
582
|
+
}
|
|
583
|
+
render(content, options) {
|
|
584
|
+
try {
|
|
585
|
+
const config = JSON.parse(content);
|
|
586
|
+
return import_react4.default.createElement(ChartView, {
|
|
587
|
+
config,
|
|
588
|
+
className: options?.className ?? "fmcp-chart-content"
|
|
589
|
+
});
|
|
590
|
+
} catch {
|
|
591
|
+
return import_react4.default.createElement(import_Alert.default, { severity: "error" }, "Invalid chart JSON");
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
var chartsRenderer = new ChartsRenderer();
|
|
596
|
+
|
|
597
|
+
// libs/ui/src/renderer/csv/index.ts
|
|
598
|
+
var import_Box2 = __toESM(require("@mui/material/Box"));
|
|
599
|
+
var import_styles3 = require("@mui/material/styles");
|
|
600
|
+
var import_Table = __toESM(require("@mui/material/Table"));
|
|
601
|
+
var import_TableBody = __toESM(require("@mui/material/TableBody"));
|
|
602
|
+
var import_TableCell = __toESM(require("@mui/material/TableCell"));
|
|
603
|
+
var import_TableContainer = __toESM(require("@mui/material/TableContainer"));
|
|
604
|
+
var import_TableHead = __toESM(require("@mui/material/TableHead"));
|
|
605
|
+
var import_TablePagination = __toESM(require("@mui/material/TablePagination"));
|
|
606
|
+
var import_TableRow = __toESM(require("@mui/material/TableRow"));
|
|
607
|
+
var import_TableSortLabel = __toESM(require("@mui/material/TableSortLabel"));
|
|
608
|
+
var import_TextField = __toESM(require("@mui/material/TextField"));
|
|
609
|
+
var import_react5 = __toESM(require("react"));
|
|
610
|
+
function detectDelimiter(content) {
|
|
611
|
+
const firstLine = content.split("\n")[0];
|
|
612
|
+
const commas = (firstLine.match(/,/g) ?? []).length;
|
|
613
|
+
const tabs = (firstLine.match(/\t/g) ?? []).length;
|
|
614
|
+
const semicolons = (firstLine.match(/;/g) ?? []).length;
|
|
615
|
+
if (tabs > commas && tabs > semicolons) return " ";
|
|
616
|
+
if (semicolons > commas) return ";";
|
|
617
|
+
return ",";
|
|
618
|
+
}
|
|
619
|
+
function parseCsv(content, delimiter) {
|
|
620
|
+
return content.trim().split("\n").map((line) => line.split(delimiter).map((cell) => cell.trim()));
|
|
621
|
+
}
|
|
622
|
+
var CsvRoot = (0, import_styles3.styled)(import_Box2.default, {
|
|
623
|
+
name: "FrontMcpCsvTable",
|
|
624
|
+
slot: "Root"
|
|
625
|
+
})({
|
|
626
|
+
width: "100%"
|
|
627
|
+
});
|
|
628
|
+
var StyledHeaderCell = (0, import_styles3.styled)(import_TableCell.default, {
|
|
629
|
+
name: "FrontMcpCsvTable",
|
|
630
|
+
slot: "Header"
|
|
631
|
+
})(({ theme }) => ({
|
|
632
|
+
fontWeight: 600,
|
|
633
|
+
backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[900] : theme.palette.grey[50],
|
|
634
|
+
whiteSpace: "nowrap"
|
|
635
|
+
}));
|
|
636
|
+
var FilterToolbar = (0, import_styles3.styled)(import_Box2.default, {
|
|
637
|
+
name: "FrontMcpCsvTable",
|
|
638
|
+
slot: "Toolbar"
|
|
639
|
+
})(({ theme }) => ({
|
|
640
|
+
padding: theme.spacing(1, 2),
|
|
641
|
+
display: "flex",
|
|
642
|
+
gap: theme.spacing(1)
|
|
643
|
+
}));
|
|
644
|
+
function CsvTableView({ content, className, pageSize = 25 }) {
|
|
645
|
+
const delimiter = (0, import_react5.useMemo)(() => detectDelimiter(content), [content]);
|
|
646
|
+
const allRows = (0, import_react5.useMemo)(() => parseCsv(content, delimiter), [content, delimiter]);
|
|
647
|
+
const headers = allRows[0] ?? [];
|
|
648
|
+
const dataRows = (0, import_react5.useMemo)(() => allRows.slice(1), [allRows]);
|
|
649
|
+
const [page, setPage] = (0, import_react5.useState)(0);
|
|
650
|
+
const [rowsPerPage, setRowsPerPage] = (0, import_react5.useState)(pageSize);
|
|
651
|
+
const [sortCol, setSortCol] = (0, import_react5.useState)(null);
|
|
652
|
+
const [sortDir, setSortDir] = (0, import_react5.useState)("asc");
|
|
653
|
+
const [filter, setFilter] = (0, import_react5.useState)("");
|
|
654
|
+
const filteredRows = (0, import_react5.useMemo)(() => {
|
|
655
|
+
if (!filter) return dataRows;
|
|
656
|
+
const lower = filter.toLowerCase();
|
|
657
|
+
return dataRows.filter((row) => row.some((cell) => cell.toLowerCase().includes(lower)));
|
|
658
|
+
}, [dataRows, filter]);
|
|
659
|
+
const sortedRows = (0, import_react5.useMemo)(() => {
|
|
660
|
+
if (sortCol === null) return filteredRows;
|
|
661
|
+
const sorted = [...filteredRows];
|
|
662
|
+
sorted.sort((a, b) => {
|
|
663
|
+
const va = a[sortCol] ?? "";
|
|
664
|
+
const vb = b[sortCol] ?? "";
|
|
665
|
+
const numA = Number(va);
|
|
666
|
+
const numB = Number(vb);
|
|
667
|
+
if (!isNaN(numA) && !isNaN(numB)) {
|
|
668
|
+
return sortDir === "asc" ? numA - numB : numB - numA;
|
|
669
|
+
}
|
|
670
|
+
return sortDir === "asc" ? va.localeCompare(vb) : vb.localeCompare(va);
|
|
671
|
+
});
|
|
672
|
+
return sorted;
|
|
673
|
+
}, [filteredRows, sortCol, sortDir]);
|
|
674
|
+
const pageRows = (0, import_react5.useMemo)(
|
|
675
|
+
() => sortedRows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage),
|
|
676
|
+
[sortedRows, page, rowsPerPage]
|
|
677
|
+
);
|
|
678
|
+
const handleSort = (0, import_react5.useCallback)((colIndex) => {
|
|
679
|
+
setSortCol((prev) => {
|
|
680
|
+
if (prev === colIndex) {
|
|
681
|
+
setSortDir((d) => d === "asc" ? "desc" : "asc");
|
|
682
|
+
return colIndex;
|
|
683
|
+
}
|
|
684
|
+
setSortDir("asc");
|
|
685
|
+
return colIndex;
|
|
686
|
+
});
|
|
687
|
+
}, []);
|
|
688
|
+
const handleChangePage = (0, import_react5.useCallback)((_, newPage) => setPage(newPage), []);
|
|
689
|
+
const handleChangeRowsPerPage = (0, import_react5.useCallback)((e) => {
|
|
690
|
+
setRowsPerPage(parseInt(e.target.value, 10));
|
|
691
|
+
setPage(0);
|
|
692
|
+
}, []);
|
|
693
|
+
return import_react5.default.createElement(
|
|
694
|
+
CsvRoot,
|
|
695
|
+
{ className },
|
|
696
|
+
import_react5.default.createElement(
|
|
697
|
+
FilterToolbar,
|
|
698
|
+
null,
|
|
699
|
+
import_react5.default.createElement(import_TextField.default, {
|
|
700
|
+
size: "small",
|
|
701
|
+
placeholder: "Filter rows...",
|
|
702
|
+
value: filter,
|
|
703
|
+
onChange: (e) => {
|
|
704
|
+
setFilter(e.target.value);
|
|
705
|
+
setPage(0);
|
|
706
|
+
},
|
|
707
|
+
sx: { minWidth: 200 }
|
|
708
|
+
})
|
|
709
|
+
),
|
|
710
|
+
import_react5.default.createElement(
|
|
711
|
+
import_TableContainer.default,
|
|
712
|
+
{ sx: { border: 1, borderColor: "divider", borderRadius: 1 } },
|
|
713
|
+
import_react5.default.createElement(
|
|
714
|
+
import_Table.default,
|
|
715
|
+
{ size: "small", stickyHeader: true },
|
|
716
|
+
import_react5.default.createElement(
|
|
717
|
+
import_TableHead.default,
|
|
718
|
+
null,
|
|
719
|
+
import_react5.default.createElement(
|
|
720
|
+
import_TableRow.default,
|
|
721
|
+
null,
|
|
722
|
+
headers.map(
|
|
723
|
+
(header, i) => import_react5.default.createElement(
|
|
724
|
+
StyledHeaderCell,
|
|
725
|
+
{ key: i },
|
|
726
|
+
import_react5.default.createElement(
|
|
727
|
+
import_TableSortLabel.default,
|
|
728
|
+
{
|
|
729
|
+
active: sortCol === i,
|
|
730
|
+
direction: sortCol === i ? sortDir : "asc",
|
|
731
|
+
onClick: () => handleSort(i)
|
|
732
|
+
},
|
|
733
|
+
header
|
|
734
|
+
)
|
|
735
|
+
)
|
|
736
|
+
)
|
|
737
|
+
)
|
|
738
|
+
),
|
|
739
|
+
import_react5.default.createElement(
|
|
740
|
+
import_TableBody.default,
|
|
741
|
+
null,
|
|
742
|
+
pageRows.map(
|
|
743
|
+
(row, ri) => import_react5.default.createElement(
|
|
744
|
+
import_TableRow.default,
|
|
745
|
+
{ key: ri, hover: true },
|
|
746
|
+
row.map((cell, ci) => import_react5.default.createElement(import_TableCell.default, { key: ci }, cell))
|
|
747
|
+
)
|
|
748
|
+
)
|
|
749
|
+
)
|
|
750
|
+
)
|
|
751
|
+
),
|
|
752
|
+
sortedRows.length > rowsPerPage && import_react5.default.createElement(import_TablePagination.default, {
|
|
753
|
+
count: sortedRows.length,
|
|
754
|
+
page,
|
|
755
|
+
rowsPerPage,
|
|
756
|
+
onPageChange: handleChangePage,
|
|
757
|
+
onRowsPerPageChange: handleChangeRowsPerPage,
|
|
758
|
+
rowsPerPageOptions: [10, 25, 50, 100]
|
|
759
|
+
})
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
var CsvRenderer = class {
|
|
763
|
+
type = "csv";
|
|
764
|
+
priority = 10;
|
|
765
|
+
canHandle(content) {
|
|
766
|
+
const lines = content.trim().split("\n").slice(0, 5);
|
|
767
|
+
if (lines.length < 2) return false;
|
|
768
|
+
for (const delim of [",", " ", ";"]) {
|
|
769
|
+
const counts = lines.map((line) => line.split(delim).length);
|
|
770
|
+
if (counts[0] > 1 && counts.every((c) => c === counts[0])) return true;
|
|
771
|
+
}
|
|
772
|
+
return false;
|
|
773
|
+
}
|
|
774
|
+
render(content, options) {
|
|
775
|
+
const pageSize = options?.rendererOptions?.["pageSize"];
|
|
776
|
+
return import_react5.default.createElement(CsvTableView, {
|
|
777
|
+
content,
|
|
778
|
+
className: options?.className ?? "fmcp-csv-table",
|
|
779
|
+
pageSize
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
};
|
|
783
|
+
var csvRenderer = new CsvRenderer();
|
|
784
|
+
|
|
785
|
+
// libs/ui/src/renderer/flow/index.ts
|
|
786
|
+
var import_Alert2 = __toESM(require("@mui/material/Alert"));
|
|
787
|
+
var import_Box3 = __toESM(require("@mui/material/Box"));
|
|
788
|
+
var import_styles4 = require("@mui/material/styles");
|
|
789
|
+
var import_Typography2 = __toESM(require("@mui/material/Typography"));
|
|
790
|
+
var import_react6 = __toESM(require("react"));
|
|
791
|
+
|
|
792
|
+
// libs/ui/src/renderer/common/inject-stylesheet.ts
|
|
793
|
+
function injectStylesheet(href, id) {
|
|
794
|
+
if (typeof document === "undefined") return;
|
|
795
|
+
if (document.getElementById(id)) return;
|
|
796
|
+
const link = document.createElement("link");
|
|
797
|
+
link.id = id;
|
|
798
|
+
link.rel = "stylesheet";
|
|
799
|
+
link.href = href;
|
|
800
|
+
link.crossOrigin = "anonymous";
|
|
801
|
+
document.head.appendChild(link);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// libs/ui/src/renderer/flow/index.ts
|
|
805
|
+
var XYFLOW_CSS_URL = "https://esm.sh/@xyflow/react@12/dist/style.css";
|
|
806
|
+
var XYFLOW_CSS_ID = "fmcp-xyflow-css";
|
|
807
|
+
function isFlow(content) {
|
|
808
|
+
const trimmed = content.trim();
|
|
809
|
+
if (trimmed.charCodeAt(0) !== 123) return false;
|
|
810
|
+
return trimmed.includes('"nodes"') && trimmed.includes('"edges"');
|
|
811
|
+
}
|
|
812
|
+
var lazyXYFlow = createLazyImport("@xyflow/react", async () => {
|
|
813
|
+
const mod = await runtimeImportWithFallback(
|
|
814
|
+
"@xyflow/react",
|
|
815
|
+
esmShUrl("@xyflow/react@12", { external: ["react", "react-dom"] })
|
|
816
|
+
);
|
|
817
|
+
return mod;
|
|
818
|
+
});
|
|
819
|
+
var FlowRoot = (0, import_styles4.styled)(import_Box3.default, {
|
|
820
|
+
name: "FrontMcpFlow",
|
|
821
|
+
slot: "Root"
|
|
822
|
+
})(({ theme }) => ({
|
|
823
|
+
width: "100%",
|
|
824
|
+
borderRadius: theme.shape.borderRadius,
|
|
825
|
+
overflow: "hidden",
|
|
826
|
+
border: `1px solid ${theme.palette.divider}`
|
|
827
|
+
}));
|
|
828
|
+
function FlowView({ config, className }) {
|
|
829
|
+
(0, import_react6.useEffect)(() => {
|
|
830
|
+
injectStylesheet(XYFLOW_CSS_URL, XYFLOW_CSS_ID);
|
|
831
|
+
}, []);
|
|
832
|
+
const themeValues = useRendererTheme();
|
|
833
|
+
const xyflow = useLazyModule(lazyXYFlow);
|
|
834
|
+
const height = config.height ?? 500;
|
|
835
|
+
const styledNodes = (0, import_react6.useMemo)(() => {
|
|
836
|
+
return config.nodes.map((node) => ({
|
|
837
|
+
...node,
|
|
838
|
+
style: {
|
|
839
|
+
background: themeValues.paper,
|
|
840
|
+
color: themeValues.textPrimary,
|
|
841
|
+
border: `1px solid ${themeValues.divider}`,
|
|
842
|
+
borderRadius: themeValues.borderRadius,
|
|
843
|
+
padding: 8,
|
|
844
|
+
fontSize: themeValues.fontSize,
|
|
845
|
+
fontFamily: themeValues.fontFamily,
|
|
846
|
+
...node.style
|
|
847
|
+
}
|
|
848
|
+
}));
|
|
849
|
+
}, [config.nodes, themeValues]);
|
|
850
|
+
const styledEdges = (0, import_react6.useMemo)(() => {
|
|
851
|
+
return config.edges.map((edge, i) => ({
|
|
852
|
+
...edge,
|
|
853
|
+
style: {
|
|
854
|
+
stroke: themeValues.seriesColors[i % themeValues.seriesColors.length],
|
|
855
|
+
strokeWidth: 2,
|
|
856
|
+
...edge.style
|
|
857
|
+
}
|
|
858
|
+
}));
|
|
859
|
+
}, [config.edges, themeValues]);
|
|
860
|
+
if (!xyflow) {
|
|
861
|
+
return import_react6.default.createElement(import_Alert2.default, { severity: "info" }, "Loading flow diagram library...");
|
|
862
|
+
}
|
|
863
|
+
const { ReactFlow, Controls, MiniMap, Background } = xyflow;
|
|
864
|
+
return import_react6.default.createElement(
|
|
865
|
+
FlowRoot,
|
|
866
|
+
{ className },
|
|
867
|
+
config.title && import_react6.default.createElement(
|
|
868
|
+
import_Typography2.default,
|
|
869
|
+
{ variant: "subtitle1", sx: { fontWeight: 600, p: 1.5, borderBottom: 1, borderColor: "divider" } },
|
|
870
|
+
config.title
|
|
871
|
+
),
|
|
872
|
+
import_react6.default.createElement(
|
|
873
|
+
import_Box3.default,
|
|
874
|
+
{ sx: { height } },
|
|
875
|
+
import_react6.default.createElement(
|
|
876
|
+
ReactFlow,
|
|
877
|
+
{
|
|
878
|
+
nodes: styledNodes,
|
|
879
|
+
edges: styledEdges,
|
|
880
|
+
fitView: config.fitView !== false,
|
|
881
|
+
proOptions: { hideAttribution: true }
|
|
882
|
+
},
|
|
883
|
+
import_react6.default.createElement(Controls, {
|
|
884
|
+
style: {
|
|
885
|
+
backgroundColor: themeValues.paper,
|
|
886
|
+
borderRadius: themeValues.borderRadius,
|
|
887
|
+
border: `1px solid ${themeValues.divider}`
|
|
888
|
+
}
|
|
889
|
+
}),
|
|
890
|
+
import_react6.default.createElement(MiniMap, {
|
|
891
|
+
style: {
|
|
892
|
+
backgroundColor: themeValues.background,
|
|
893
|
+
borderRadius: themeValues.borderRadius
|
|
894
|
+
},
|
|
895
|
+
nodeColor: themeValues.primary
|
|
896
|
+
}),
|
|
897
|
+
Background && import_react6.default.createElement(Background, {
|
|
898
|
+
color: themeValues.divider,
|
|
899
|
+
gap: 16
|
|
900
|
+
})
|
|
901
|
+
)
|
|
902
|
+
)
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
lazyXYFlow.load().catch(() => {
|
|
906
|
+
});
|
|
907
|
+
var FlowRenderer = class {
|
|
908
|
+
type = "flow";
|
|
909
|
+
priority = 70;
|
|
910
|
+
canHandle(content) {
|
|
911
|
+
return isFlow(content);
|
|
912
|
+
}
|
|
913
|
+
render(content, options) {
|
|
914
|
+
try {
|
|
915
|
+
const config = JSON.parse(content);
|
|
916
|
+
return import_react6.default.createElement(FlowView, {
|
|
917
|
+
config,
|
|
918
|
+
className: options?.className ?? "fmcp-flow-content"
|
|
919
|
+
});
|
|
920
|
+
} catch {
|
|
921
|
+
return import_react6.default.createElement(import_Alert2.default, { severity: "error" }, "Invalid flow JSON");
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
};
|
|
925
|
+
var flowRenderer = new FlowRenderer();
|
|
926
|
+
|
|
927
|
+
// libs/ui/src/renderer/html/index.ts
|
|
928
|
+
var import_Box4 = __toESM(require("@mui/material/Box"));
|
|
929
|
+
var import_styles5 = require("@mui/material/styles");
|
|
930
|
+
var import_react7 = __toESM(require("react"));
|
|
931
|
+
var HtmlRoot = (0, import_styles5.styled)(import_Box4.default, {
|
|
932
|
+
name: "FrontMcpHtml",
|
|
933
|
+
slot: "Root"
|
|
934
|
+
})(({ theme }) => ({
|
|
935
|
+
"& a": { color: theme.palette.primary.main },
|
|
936
|
+
"& table": { borderCollapse: "collapse", width: "100%" },
|
|
937
|
+
"& th, & td": { border: `1px solid ${theme.palette.divider}`, padding: theme.spacing(1) },
|
|
938
|
+
"& pre": {
|
|
939
|
+
backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[900] : theme.palette.grey[100],
|
|
940
|
+
padding: theme.spacing(1.5),
|
|
941
|
+
borderRadius: theme.shape.borderRadius,
|
|
942
|
+
overflow: "auto"
|
|
943
|
+
}
|
|
944
|
+
}));
|
|
945
|
+
var purifyModule = null;
|
|
946
|
+
var purifyPromise = null;
|
|
590
947
|
function loadDOMPurify() {
|
|
591
948
|
if (purifyModule) return Promise.resolve(purifyModule);
|
|
592
949
|
if (purifyPromise) return purifyPromise;
|
|
@@ -610,16 +967,16 @@ function sanitizeSync(html) {
|
|
|
610
967
|
}
|
|
611
968
|
loadDOMPurify();
|
|
612
969
|
function HtmlView({ html, className }) {
|
|
613
|
-
const [purifyReady, setPurifyReady] = (0,
|
|
614
|
-
(0,
|
|
970
|
+
const [purifyReady, setPurifyReady] = (0, import_react7.useState)(!!purifyModule);
|
|
971
|
+
(0, import_react7.useEffect)(() => {
|
|
615
972
|
if (!purifyModule) {
|
|
616
973
|
loadDOMPurify().then((mod) => {
|
|
617
974
|
if (mod) setPurifyReady(true);
|
|
618
975
|
});
|
|
619
976
|
}
|
|
620
977
|
}, []);
|
|
621
|
-
const sanitized = (0,
|
|
622
|
-
return
|
|
978
|
+
const sanitized = (0, import_react7.useMemo)(() => sanitizeSync(html), [html, purifyReady]);
|
|
979
|
+
return import_react7.default.createElement(HtmlRoot, {
|
|
623
980
|
className,
|
|
624
981
|
dangerouslySetInnerHTML: { __html: sanitized }
|
|
625
982
|
});
|
|
@@ -631,7 +988,7 @@ var HtmlRenderer = class {
|
|
|
631
988
|
return /^\s*</.test(content) && /<\/\w+>/.test(content);
|
|
632
989
|
}
|
|
633
990
|
render(content, options) {
|
|
634
|
-
return
|
|
991
|
+
return import_react7.default.createElement(HtmlView, {
|
|
635
992
|
html: content,
|
|
636
993
|
className: options?.className ?? "fmcp-html-content"
|
|
637
994
|
});
|
|
@@ -639,251 +996,158 @@ var HtmlRenderer = class {
|
|
|
639
996
|
};
|
|
640
997
|
var htmlRenderer = new HtmlRenderer();
|
|
641
998
|
|
|
642
|
-
// libs/ui/src/renderer/
|
|
643
|
-
var
|
|
644
|
-
var
|
|
645
|
-
var
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
var
|
|
649
|
-
var
|
|
650
|
-
var
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
if (babelState.status === "loading") {
|
|
656
|
-
return babelState.promise;
|
|
657
|
-
}
|
|
658
|
-
if (babelState.status === "error") {
|
|
659
|
-
throw babelState.error;
|
|
660
|
-
}
|
|
661
|
-
const promise = doLoadBabel();
|
|
662
|
-
babelState = { status: "loading", promise };
|
|
663
|
-
try {
|
|
664
|
-
const babel = await promise;
|
|
665
|
-
babelState = { status: "loaded", babel };
|
|
666
|
-
return babel;
|
|
667
|
-
} catch (error) {
|
|
668
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
669
|
-
babelState = { status: "error", error: err };
|
|
670
|
-
throw err;
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
async function doLoadBabel() {
|
|
674
|
-
const globalBabel = globalThis["Babel"];
|
|
675
|
-
if (globalBabel && typeof globalBabel.transform === "function") {
|
|
676
|
-
return globalBabel;
|
|
677
|
-
}
|
|
678
|
-
try {
|
|
679
|
-
const module2 = await import(
|
|
680
|
-
/* @vite-ignore */
|
|
681
|
-
/* webpackIgnore: true */
|
|
682
|
-
BABEL_STANDALONE_CDN
|
|
683
|
-
);
|
|
684
|
-
if (module2 && typeof module2.transform === "function") {
|
|
685
|
-
return module2;
|
|
686
|
-
}
|
|
687
|
-
if (module2.default && typeof module2.default.transform === "function") {
|
|
688
|
-
return module2.default;
|
|
689
|
-
}
|
|
690
|
-
} catch {
|
|
691
|
-
}
|
|
692
|
-
return new Promise((resolve, reject) => {
|
|
693
|
-
if (typeof document === "undefined") {
|
|
694
|
-
reject(new Error("Babel Standalone requires a browser environment"));
|
|
695
|
-
return;
|
|
696
|
-
}
|
|
697
|
-
const script = document.createElement("script");
|
|
698
|
-
script.src = BABEL_STANDALONE_FALLBACK_CDN;
|
|
699
|
-
script.crossOrigin = "anonymous";
|
|
700
|
-
script.onload = () => {
|
|
701
|
-
const babel = globalThis["Babel"];
|
|
702
|
-
if (babel && typeof babel.transform === "function") {
|
|
703
|
-
resolve(babel);
|
|
704
|
-
} else {
|
|
705
|
-
reject(new Error("Babel Standalone loaded but transform function not found"));
|
|
706
|
-
}
|
|
707
|
-
};
|
|
708
|
-
script.onerror = () => {
|
|
709
|
-
reject(new Error(`Failed to load Babel Standalone from ${BABEL_STANDALONE_FALLBACK_CDN}`));
|
|
710
|
-
};
|
|
711
|
-
document.head.appendChild(script);
|
|
712
|
-
});
|
|
713
|
-
}
|
|
714
|
-
async function transpileJsx(source, filename = "component.jsx") {
|
|
715
|
-
const babel = await loadBabel();
|
|
716
|
-
const result = babel.transform(source, {
|
|
717
|
-
presets: ["react"],
|
|
718
|
-
filename
|
|
719
|
-
});
|
|
720
|
-
return result.code;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
// libs/ui/src/renderer/react/index.ts
|
|
724
|
-
function isReactJsx(content) {
|
|
725
|
-
if (/^#{1,6}\s+\S/m.test(content)) return false;
|
|
726
|
-
return /(?:function|const|class)\s+\w+/.test(content) && /(?:return|=>)[\s(]*</.test(content);
|
|
727
|
-
}
|
|
728
|
-
function parseImports(source) {
|
|
729
|
-
const results = [];
|
|
730
|
-
const defaultRe = /^import\s+(\w+)\s+from\s+['"]([^'"]+)['"][\s;]*$/gm;
|
|
731
|
-
let m;
|
|
732
|
-
while ((m = defaultRe.exec(source)) !== null) {
|
|
733
|
-
results.push({ line: m[0], localName: m[1], specifier: m[2], named: false });
|
|
734
|
-
}
|
|
735
|
-
const namedRe = /^import\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"][\s;]*$/gm;
|
|
736
|
-
while ((m = namedRe.exec(source)) !== null) {
|
|
737
|
-
const names = m[1].split(",").map((n) => n.trim()).filter(Boolean);
|
|
738
|
-
for (const name of names) {
|
|
739
|
-
results.push({ line: m[0], localName: name, specifier: m[2], named: true });
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
return results;
|
|
743
|
-
}
|
|
744
|
-
function stripImports(source) {
|
|
745
|
-
return source.replace(/^import\s+\w+\s+from\s+['"][^'"]+['"][\s;]*$/gm, "").replace(/^import\s+\{[^}]+\}\s+from\s+['"][^'"]+['"][\s;]*$/gm, "");
|
|
746
|
-
}
|
|
747
|
-
function rewriteExportDefault(source) {
|
|
748
|
-
let result = source.replace(/^export\s+default\s+(function|class)\b/gm, "var __default__ = $1");
|
|
749
|
-
result = result.replace(/^export\s+default\s+(\([^)]*\)\s*=>)/gm, "var __default__ = $1");
|
|
750
|
-
result = result.replace(/^export\s+default\s+(\w+)\s*;?\s*$/gm, "var __default__ = $1;");
|
|
751
|
-
return result;
|
|
752
|
-
}
|
|
753
|
-
function isReactSpecifier(specifier) {
|
|
754
|
-
return specifier === "react" || /^https?:\/\/esm\.sh\/react(?:@[\d.]+)?$/.test(specifier);
|
|
755
|
-
}
|
|
756
|
-
async function resolveModules(imports) {
|
|
757
|
-
const modules = {};
|
|
758
|
-
const specifierMap = /* @__PURE__ */ new Map();
|
|
759
|
-
for (const imp of imports) {
|
|
760
|
-
const existing = specifierMap.get(imp.specifier) ?? [];
|
|
761
|
-
existing.push(imp);
|
|
762
|
-
specifierMap.set(imp.specifier, existing);
|
|
763
|
-
}
|
|
764
|
-
for (const [specifier, specImports] of specifierMap) {
|
|
765
|
-
let mod;
|
|
766
|
-
if (isReactSpecifier(specifier)) {
|
|
767
|
-
mod = import_react6.default;
|
|
768
|
-
} else {
|
|
769
|
-
mod = await runtimeImport(specifier);
|
|
770
|
-
}
|
|
771
|
-
for (const imp of specImports) {
|
|
772
|
-
if (imp.named) {
|
|
773
|
-
modules[imp.localName] = mod[imp.localName] ?? mod["default"]?.[imp.localName];
|
|
774
|
-
} else {
|
|
775
|
-
modules[imp.localName] = mod["default"] ?? mod;
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
return modules;
|
|
999
|
+
// libs/ui/src/renderer/image/index.ts
|
|
1000
|
+
var import_Alert3 = __toESM(require("@mui/material/Alert"));
|
|
1001
|
+
var import_Box5 = __toESM(require("@mui/material/Box"));
|
|
1002
|
+
var import_Skeleton = __toESM(require("@mui/material/Skeleton"));
|
|
1003
|
+
var import_styles6 = require("@mui/material/styles");
|
|
1004
|
+
var import_Typography3 = __toESM(require("@mui/material/Typography"));
|
|
1005
|
+
var import_react8 = __toESM(require("react"));
|
|
1006
|
+
var IMAGE_DATA_URI = /^data:image\/(?:png|jpeg|jpg|gif|webp|svg\+xml|avif)[;,]/;
|
|
1007
|
+
var IMAGE_URL = /^https?:\/\/[^?#\s]+\.(?:png|jpe?g|gif|webp|svg|avif|ico)(?:\?[^#\s]*)?$/i;
|
|
1008
|
+
var IMAGE_SERVICE_URL = /^https?:\/\/(?:picsum\.photos|images\.unsplash\.com|i\.imgur\.com|placekitten\.com|via\.placeholder\.com)\//i;
|
|
1009
|
+
function isImage(content) {
|
|
1010
|
+
const trimmed = content.trim();
|
|
1011
|
+
return IMAGE_DATA_URI.test(trimmed) || IMAGE_URL.test(trimmed) || IMAGE_SERVICE_URL.test(trimmed);
|
|
780
1012
|
}
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
1013
|
+
var ImageRoot = (0, import_styles6.styled)(import_Box5.default, {
|
|
1014
|
+
name: "FrontMcpImage",
|
|
1015
|
+
slot: "Root"
|
|
1016
|
+
})({
|
|
1017
|
+
display: "inline-block",
|
|
1018
|
+
position: "relative",
|
|
1019
|
+
maxWidth: "100%"
|
|
1020
|
+
});
|
|
1021
|
+
var StyledImage = (0, import_styles6.styled)("img", {
|
|
1022
|
+
name: "FrontMcpImage",
|
|
1023
|
+
slot: "Image"
|
|
1024
|
+
})({
|
|
1025
|
+
maxWidth: "100%",
|
|
1026
|
+
height: "auto",
|
|
1027
|
+
display: "block",
|
|
1028
|
+
cursor: "pointer",
|
|
1029
|
+
borderRadius: "inherit"
|
|
1030
|
+
});
|
|
1031
|
+
var LightboxBackdrop = (0, import_styles6.styled)(import_Box5.default, {
|
|
1032
|
+
name: "FrontMcpImage",
|
|
1033
|
+
slot: "Lightbox"
|
|
1034
|
+
})({
|
|
1035
|
+
display: "flex",
|
|
1036
|
+
alignItems: "center",
|
|
1037
|
+
justifyContent: "center",
|
|
1038
|
+
padding: 16
|
|
1039
|
+
});
|
|
1040
|
+
var LightboxImage = (0, import_styles6.styled)("img")({
|
|
1041
|
+
maxWidth: "90vw",
|
|
1042
|
+
maxHeight: "90vh",
|
|
1043
|
+
objectFit: "contain",
|
|
1044
|
+
borderRadius: 8
|
|
1045
|
+
});
|
|
1046
|
+
function LightboxOverlay({ src, alt, onClose }) {
|
|
1047
|
+
return import_react8.default.createElement(
|
|
1048
|
+
LightboxBackdrop,
|
|
1049
|
+
{
|
|
1050
|
+
onClick: onClose,
|
|
1051
|
+
sx: {
|
|
1052
|
+
position: "fixed",
|
|
1053
|
+
inset: 0,
|
|
1054
|
+
zIndex: 1300,
|
|
1055
|
+
bgcolor: "rgba(0,0,0,0.8)"
|
|
1056
|
+
}
|
|
1057
|
+
},
|
|
1058
|
+
import_react8.default.createElement(LightboxImage, { src, alt })
|
|
1059
|
+
);
|
|
1060
|
+
}
|
|
1061
|
+
function ImageView({ src, alt, caption, className }) {
|
|
1062
|
+
const [loaded, setLoaded] = (0, import_react8.useState)(false);
|
|
1063
|
+
const [error, setError] = (0, import_react8.useState)(false);
|
|
1064
|
+
const [lightboxOpen, setLightboxOpen] = (0, import_react8.useState)(false);
|
|
1065
|
+
(0, import_react8.useEffect)(() => {
|
|
1066
|
+
setLoaded(false);
|
|
1067
|
+
setError(false);
|
|
1068
|
+
setLightboxOpen(false);
|
|
1069
|
+
}, [src]);
|
|
1070
|
+
const handleLoad = (0, import_react8.useCallback)(() => setLoaded(true), []);
|
|
1071
|
+
const handleError = (0, import_react8.useCallback)(() => {
|
|
1072
|
+
setLoaded(true);
|
|
1073
|
+
setError(true);
|
|
1074
|
+
}, []);
|
|
823
1075
|
if (error) {
|
|
824
|
-
return
|
|
825
|
-
import_Box3.default,
|
|
826
|
-
{ className },
|
|
827
|
-
import_react6.default.createElement(import_Alert.default, { severity: "error", sx: { mb: 1 } }, `JSX render error: ${error}`),
|
|
828
|
-
import_react6.default.createElement(
|
|
829
|
-
"pre",
|
|
830
|
-
{ style: { fontFamily: "monospace", whiteSpace: "pre-wrap", fontSize: "0.85em" } },
|
|
831
|
-
source
|
|
832
|
-
)
|
|
833
|
-
);
|
|
834
|
-
}
|
|
835
|
-
if (!Component) {
|
|
836
|
-
return import_react6.default.createElement(
|
|
837
|
-
import_Box3.default,
|
|
838
|
-
{ className },
|
|
839
|
-
import_react6.default.createElement(import_Alert.default, { severity: "warning" }, "No component exported. Use `export default MyComponent`.")
|
|
840
|
-
);
|
|
1076
|
+
return import_react8.default.createElement(import_Alert3.default, { severity: "error" }, `Failed to load image: ${src}`);
|
|
841
1077
|
}
|
|
842
|
-
return
|
|
1078
|
+
return import_react8.default.createElement(
|
|
1079
|
+
ImageRoot,
|
|
1080
|
+
{ className },
|
|
1081
|
+
!loaded && import_react8.default.createElement(import_Skeleton.default, { variant: "rectangular", width: 400, height: 300 }),
|
|
1082
|
+
import_react8.default.createElement(StyledImage, {
|
|
1083
|
+
src,
|
|
1084
|
+
alt: alt ?? "Image",
|
|
1085
|
+
onLoad: handleLoad,
|
|
1086
|
+
onError: handleError,
|
|
1087
|
+
onClick: () => setLightboxOpen(true),
|
|
1088
|
+
style: loaded ? void 0 : { display: "none" }
|
|
1089
|
+
}),
|
|
1090
|
+
caption && import_react8.default.createElement(
|
|
1091
|
+
import_Typography3.default,
|
|
1092
|
+
{ variant: "caption", color: "text.secondary", sx: { mt: 0.5, display: "block", textAlign: "center" } },
|
|
1093
|
+
caption
|
|
1094
|
+
),
|
|
1095
|
+
lightboxOpen && import_react8.default.createElement(LightboxOverlay, {
|
|
1096
|
+
src,
|
|
1097
|
+
alt: alt ?? "Image",
|
|
1098
|
+
onClose: () => setLightboxOpen(false)
|
|
1099
|
+
})
|
|
1100
|
+
);
|
|
843
1101
|
}
|
|
844
|
-
var
|
|
845
|
-
type = "
|
|
846
|
-
priority =
|
|
1102
|
+
var ImageRenderer = class {
|
|
1103
|
+
type = "image";
|
|
1104
|
+
priority = 30;
|
|
847
1105
|
canHandle(content) {
|
|
848
|
-
return
|
|
1106
|
+
return isImage(content);
|
|
849
1107
|
}
|
|
850
1108
|
render(content, options) {
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
1109
|
+
const caption = options?.rendererOptions?.["caption"];
|
|
1110
|
+
return import_react8.default.createElement(ImageView, {
|
|
1111
|
+
src: content.trim(),
|
|
1112
|
+
alt: options?.toolName ?? "Image",
|
|
1113
|
+
caption,
|
|
1114
|
+
className: options?.className ?? "fmcp-image-content"
|
|
854
1115
|
});
|
|
855
1116
|
}
|
|
856
1117
|
};
|
|
857
|
-
var
|
|
1118
|
+
var imageRenderer = new ImageRenderer();
|
|
858
1119
|
|
|
859
|
-
// libs/ui/src/renderer/
|
|
860
|
-
var
|
|
861
|
-
var
|
|
862
|
-
var
|
|
863
|
-
var
|
|
864
|
-
var
|
|
865
|
-
var
|
|
866
|
-
var
|
|
1120
|
+
// libs/ui/src/renderer/maps/index.ts
|
|
1121
|
+
var import_Alert4 = __toESM(require("@mui/material/Alert"));
|
|
1122
|
+
var import_Box6 = __toESM(require("@mui/material/Box"));
|
|
1123
|
+
var import_Paper = __toESM(require("@mui/material/Paper"));
|
|
1124
|
+
var import_styles7 = require("@mui/material/styles");
|
|
1125
|
+
var import_Typography4 = __toESM(require("@mui/material/Typography"));
|
|
1126
|
+
var import_react9 = __toESM(require("react"));
|
|
1127
|
+
var LEAFLET_CSS_URL = "https://esm.sh/leaflet@1.9.4/dist/leaflet.css";
|
|
1128
|
+
var LEAFLET_CSS_ID = "fmcp-leaflet-css";
|
|
1129
|
+
var DEFAULT_TILE_URL = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
|
|
1130
|
+
var DEFAULT_ATTRIBUTION = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
|
|
1131
|
+
var GEOJSON_TYPE_RE2 = /"type"\s*:\s*"(?:FeatureCollection|Feature|Point|LineString|Polygon|MultiPoint|MultiLineString|MultiPolygon|GeometryCollection)"/;
|
|
1132
|
+
function isMap(content) {
|
|
1133
|
+
const trimmed = content.trim();
|
|
1134
|
+
if (trimmed.charCodeAt(0) === 123 && GEOJSON_TYPE_RE2.test(trimmed)) return true;
|
|
1135
|
+
try {
|
|
1136
|
+
const parsed = JSON.parse(trimmed);
|
|
1137
|
+
return !!(parsed.center && Array.isArray(parsed.center) || parsed.markers && Array.isArray(parsed.markers) || parsed.geojson && typeof parsed.geojson === "object");
|
|
1138
|
+
} catch {
|
|
1139
|
+
return false;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
var lazyReactLeaflet = createLazyImport("react-leaflet", async () => {
|
|
867
1143
|
const mod = await runtimeImportWithFallback(
|
|
868
|
-
"react-
|
|
869
|
-
esmShUrl("react-
|
|
1144
|
+
"react-leaflet",
|
|
1145
|
+
esmShUrl("react-leaflet@5", { external: ["react", "react-dom"] })
|
|
870
1146
|
);
|
|
871
|
-
const pdfjs = mod["pdfjs"];
|
|
872
|
-
if (pdfjs?.GlobalWorkerOptions) {
|
|
873
|
-
pdfjs.GlobalWorkerOptions.workerSrc = `${ESM_SH_BASE}pdfjs-dist@${pdfjs.version ?? "4"}/build/pdf.worker.min.mjs?raw`;
|
|
874
|
-
}
|
|
875
1147
|
return mod;
|
|
876
1148
|
});
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
if (content.startsWith("%PDF-")) {
|
|
880
|
-
const base64 = typeof btoa === "function" ? btoa(content) : Buffer.from(content).toString("base64");
|
|
881
|
-
return `data:application/pdf;base64,${base64}`;
|
|
882
|
-
}
|
|
883
|
-
return `data:application/pdf;base64,${content}`;
|
|
884
|
-
}
|
|
885
|
-
var PdfRoot = (0, import_styles4.styled)(import_Box4.default, {
|
|
886
|
-
name: "FrontMcpPdf",
|
|
1149
|
+
var MapRoot = (0, import_styles7.styled)(import_Box6.default, {
|
|
1150
|
+
name: "FrontMcpMap",
|
|
887
1151
|
slot: "Root"
|
|
888
1152
|
})(({ theme }) => ({
|
|
889
1153
|
width: "100%",
|
|
@@ -891,650 +1155,562 @@ var PdfRoot = (0, import_styles4.styled)(import_Box4.default, {
|
|
|
891
1155
|
overflow: "hidden",
|
|
892
1156
|
border: `1px solid ${theme.palette.divider}`
|
|
893
1157
|
}));
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
1158
|
+
function parseMapConfig(content) {
|
|
1159
|
+
const parsed = JSON.parse(content);
|
|
1160
|
+
if (parsed.type && [
|
|
1161
|
+
"FeatureCollection",
|
|
1162
|
+
"Feature",
|
|
1163
|
+
"Point",
|
|
1164
|
+
"LineString",
|
|
1165
|
+
"Polygon",
|
|
1166
|
+
"MultiPoint",
|
|
1167
|
+
"MultiLineString",
|
|
1168
|
+
"MultiPolygon",
|
|
1169
|
+
"GeometryCollection"
|
|
1170
|
+
].includes(parsed.type)) {
|
|
1171
|
+
return {
|
|
1172
|
+
center: [0, 0],
|
|
1173
|
+
zoom: 2,
|
|
1174
|
+
geojson: parsed
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
return parsed;
|
|
1178
|
+
}
|
|
1179
|
+
function MapView({ config, className }) {
|
|
1180
|
+
(0, import_react9.useEffect)(() => {
|
|
1181
|
+
injectStylesheet(LEAFLET_CSS_URL, LEAFLET_CSS_ID);
|
|
1182
|
+
}, []);
|
|
1183
|
+
const leaflet = useLazyModule(lazyReactLeaflet);
|
|
1184
|
+
const height = config.height ?? 400;
|
|
1185
|
+
const center = config.center ?? [51.505, -0.09];
|
|
1186
|
+
const zoom = config.zoom ?? 13;
|
|
1187
|
+
if (!leaflet) {
|
|
1188
|
+
return import_react9.default.createElement(import_Alert4.default, { severity: "info" }, "Loading map library...");
|
|
1189
|
+
}
|
|
1190
|
+
const { MapContainer, TileLayer, Marker, Popup, GeoJSON } = leaflet;
|
|
1191
|
+
const tileUrl = config.tileLayer?.url ?? DEFAULT_TILE_URL;
|
|
1192
|
+
const attribution = config.tileLayer?.attribution ?? DEFAULT_ATTRIBUTION;
|
|
1193
|
+
return import_react9.default.createElement(
|
|
1194
|
+
MapRoot,
|
|
1195
|
+
{ className },
|
|
1196
|
+
config.title && import_react9.default.createElement(
|
|
1197
|
+
import_Typography4.default,
|
|
1198
|
+
{ variant: "subtitle1", sx: { fontWeight: 600, p: 1.5, borderBottom: 1, borderColor: "divider" } },
|
|
1199
|
+
config.title
|
|
1200
|
+
),
|
|
1201
|
+
import_react9.default.createElement(
|
|
1202
|
+
MapContainer,
|
|
1203
|
+
{
|
|
1204
|
+
center,
|
|
1205
|
+
zoom,
|
|
1206
|
+
style: { height, width: "100%" },
|
|
1207
|
+
scrollWheelZoom: true
|
|
1208
|
+
},
|
|
1209
|
+
import_react9.default.createElement(TileLayer, { url: tileUrl, attribution }),
|
|
1210
|
+
config.markers?.map(
|
|
1211
|
+
(marker, i) => import_react9.default.createElement(
|
|
1212
|
+
Marker,
|
|
1213
|
+
{ key: i, position: marker.position },
|
|
1214
|
+
marker.popup && import_react9.default.createElement(Popup, null, import_react9.default.createElement(import_Paper.default, { elevation: 0, sx: { p: 1 } }, marker.popup))
|
|
1215
|
+
)
|
|
1216
|
+
),
|
|
1217
|
+
config.geojson && import_react9.default.createElement(GeoJSON, { data: config.geojson })
|
|
1218
|
+
)
|
|
1219
|
+
);
|
|
1220
|
+
}
|
|
1221
|
+
lazyReactLeaflet.load().catch(() => {
|
|
1222
|
+
});
|
|
1223
|
+
var MapsRenderer = class {
|
|
1224
|
+
type = "map";
|
|
1225
|
+
priority = 60;
|
|
1226
|
+
canHandle(content) {
|
|
1227
|
+
return isMap(content);
|
|
1228
|
+
}
|
|
1229
|
+
render(content, options) {
|
|
1230
|
+
try {
|
|
1231
|
+
const config = parseMapConfig(content);
|
|
1232
|
+
return import_react9.default.createElement(MapView, {
|
|
1233
|
+
config,
|
|
1234
|
+
className: options?.className ?? "fmcp-map-content"
|
|
1235
|
+
});
|
|
1236
|
+
} catch {
|
|
1237
|
+
return import_react9.default.createElement(import_Alert4.default, { severity: "error" }, "Invalid map/GeoJSON data");
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
};
|
|
1241
|
+
var mapsRenderer = new MapsRenderer();
|
|
1242
|
+
|
|
1243
|
+
// libs/ui/src/renderer/math/index.ts
|
|
1244
|
+
var import_Alert5 = __toESM(require("@mui/material/Alert"));
|
|
1245
|
+
var import_Box7 = __toESM(require("@mui/material/Box"));
|
|
1246
|
+
var import_styles8 = require("@mui/material/styles");
|
|
1247
|
+
var import_react10 = __toESM(require("react"));
|
|
1248
|
+
var KATEX_CSS_URL = "https://esm.sh/katex@0.16.11/dist/katex.min.css";
|
|
1249
|
+
var KATEX_CSS_ID = "fmcp-katex-css";
|
|
1250
|
+
var MATH_DISPLAY = /\$\$(?:[^$]|\$(?!\$))+\$\$/s;
|
|
1251
|
+
var MATH_INLINE = /\$[^$\n]+?\$/;
|
|
1252
|
+
var MATH_BRACKET_DISPLAY = /\\\[(?:[^\\]|\\.)*\\\]/s;
|
|
1253
|
+
var MATH_PAREN_INLINE = /\\\((?:[^\\]|\\.)*\\\)/s;
|
|
1254
|
+
var MATH_BEGIN = /\\begin\{(?:equation|align|gather|matrix|pmatrix|bmatrix|cases)\}/;
|
|
1255
|
+
function isMath(content) {
|
|
1256
|
+
const trimmed = content.trim();
|
|
1257
|
+
return MATH_DISPLAY.test(trimmed) || MATH_INLINE.test(trimmed) || MATH_BRACKET_DISPLAY.test(trimmed) || MATH_PAREN_INLINE.test(trimmed) || MATH_BEGIN.test(trimmed);
|
|
1258
|
+
}
|
|
1259
|
+
var lazyKatex = createLazyImport("katex", async () => {
|
|
1260
|
+
const mod = await runtimeImportWithFallback("katex", esmShUrl("katex@0.16"));
|
|
1261
|
+
return mod;
|
|
1262
|
+
});
|
|
1263
|
+
var MathRoot = (0, import_styles8.styled)(import_Box7.default, {
|
|
1264
|
+
name: "FrontMcpMath",
|
|
1265
|
+
slot: "Root"
|
|
897
1266
|
})(({ theme }) => ({
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[900] : theme.palette.grey[50]
|
|
1267
|
+
color: theme.palette.text.primary,
|
|
1268
|
+
"& .katex-display": {
|
|
1269
|
+
margin: theme.spacing(2, 0),
|
|
1270
|
+
textAlign: "center"
|
|
1271
|
+
}
|
|
904
1272
|
}));
|
|
905
|
-
var
|
|
906
|
-
name: "
|
|
907
|
-
slot: "
|
|
1273
|
+
var MathDisplay = (0, import_styles8.styled)(import_Box7.default, {
|
|
1274
|
+
name: "FrontMcpMath",
|
|
1275
|
+
slot: "Display"
|
|
1276
|
+
})(({ theme }) => ({
|
|
1277
|
+
display: "block",
|
|
1278
|
+
textAlign: "center",
|
|
1279
|
+
margin: theme.spacing(2, 0),
|
|
1280
|
+
fontSize: "1.2em",
|
|
1281
|
+
overflow: "auto"
|
|
1282
|
+
}));
|
|
1283
|
+
var MathInline = (0, import_styles8.styled)("span", {
|
|
1284
|
+
name: "FrontMcpMath",
|
|
1285
|
+
slot: "Inline"
|
|
908
1286
|
})({
|
|
909
|
-
display: "
|
|
910
|
-
justifyContent: "center",
|
|
911
|
-
overflow: "auto",
|
|
912
|
-
maxHeight: 700
|
|
1287
|
+
display: "inline"
|
|
913
1288
|
});
|
|
914
|
-
function
|
|
915
|
-
const
|
|
916
|
-
const
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
1289
|
+
function parseMathContent(source) {
|
|
1290
|
+
const segments = [];
|
|
1291
|
+
const mathRegex = /(\$\$(?:[^$]|\$(?!\$))+\$\$|\$[^$\n]+?\$|\\\[(?:[^\\]|\\.)*\\\]|\\\((?:[^\\]|\\.)*\\\)|\\begin\{(?:[^\\]|\\.)*\\end\{[^}]+\})/gs;
|
|
1292
|
+
let lastIndex = 0;
|
|
1293
|
+
let match;
|
|
1294
|
+
while ((match = mathRegex.exec(source)) !== null) {
|
|
1295
|
+
if (match.index > lastIndex) {
|
|
1296
|
+
segments.push({ type: "text", content: source.slice(lastIndex, match.index) });
|
|
1297
|
+
}
|
|
1298
|
+
const raw = match[0];
|
|
1299
|
+
if (raw.startsWith("$$")) {
|
|
1300
|
+
segments.push({ type: "display", content: raw.slice(2, -2).trim() });
|
|
1301
|
+
} else if (raw.startsWith("\\[")) {
|
|
1302
|
+
segments.push({ type: "display", content: raw.slice(2, -2).trim() });
|
|
1303
|
+
} else if (raw.startsWith("\\begin")) {
|
|
1304
|
+
segments.push({ type: "display", content: raw });
|
|
1305
|
+
} else if (raw.startsWith("\\(")) {
|
|
1306
|
+
segments.push({ type: "inline", content: raw.slice(2, -2).trim() });
|
|
1307
|
+
} else if (raw.startsWith("$")) {
|
|
1308
|
+
segments.push({ type: "inline", content: raw.slice(1, -1).trim() });
|
|
1309
|
+
}
|
|
1310
|
+
lastIndex = match.index + raw.length;
|
|
1311
|
+
}
|
|
1312
|
+
if (lastIndex < source.length) {
|
|
1313
|
+
segments.push({ type: "text", content: source.slice(lastIndex) });
|
|
1314
|
+
}
|
|
1315
|
+
return segments;
|
|
1316
|
+
}
|
|
1317
|
+
function MathView({ content, className }) {
|
|
1318
|
+
(0, import_react10.useEffect)(() => {
|
|
1319
|
+
injectStylesheet(KATEX_CSS_URL, KATEX_CSS_ID);
|
|
922
1320
|
}, []);
|
|
923
|
-
const
|
|
924
|
-
const
|
|
925
|
-
const
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
title: title ?? "PDF Document"
|
|
933
|
-
});
|
|
1321
|
+
const katexMod = useLazyModule(lazyKatex);
|
|
1322
|
+
const segments = (0, import_react10.useMemo)(() => parseMathContent(content), [content]);
|
|
1323
|
+
const renderToString = katexMod?.default?.renderToString ?? katexMod?.renderToString;
|
|
1324
|
+
if (!renderToString) {
|
|
1325
|
+
return import_react10.default.createElement(
|
|
1326
|
+
MathRoot,
|
|
1327
|
+
{ className },
|
|
1328
|
+
import_react10.default.createElement("pre", { style: { fontFamily: "monospace", whiteSpace: "pre-wrap" } }, content)
|
|
1329
|
+
);
|
|
934
1330
|
}
|
|
935
|
-
const
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
import_react7.default.createElement(import_IconButton.default, { size: "small", onClick: zoomIn, "aria-label": "Zoom in" }, "+"),
|
|
965
|
-
import_react7.default.createElement(import_Box4.default, { sx: { flex: 1 } }),
|
|
966
|
-
import_react7.default.createElement(import_TextField.default, {
|
|
967
|
-
size: "small",
|
|
968
|
-
type: "number",
|
|
969
|
-
value: pageNumber,
|
|
970
|
-
onChange: (e) => {
|
|
971
|
-
const n = parseInt(e.target.value, 10);
|
|
972
|
-
if (n >= 1 && n <= numPages) setPageNumber(n);
|
|
973
|
-
},
|
|
974
|
-
sx: { width: 70 },
|
|
975
|
-
slotProps: { htmlInput: { min: 1, max: numPages, "aria-label": "Go to page" } }
|
|
976
|
-
})
|
|
977
|
-
),
|
|
978
|
-
import_react7.default.createElement(
|
|
979
|
-
PageContainer,
|
|
980
|
-
null,
|
|
981
|
-
import_react7.default.createElement(
|
|
982
|
-
Document,
|
|
983
|
-
{ file: dataUri, onLoadSuccess: onDocumentLoadSuccess },
|
|
984
|
-
import_react7.default.createElement(Page, { pageNumber, scale, renderTextLayer: false, renderAnnotationLayer: false })
|
|
985
|
-
)
|
|
986
|
-
)
|
|
987
|
-
);
|
|
1331
|
+
const elements = segments.map((seg, i) => {
|
|
1332
|
+
if (seg.type === "text") {
|
|
1333
|
+
return import_react10.default.createElement("span", { key: i }, seg.content);
|
|
1334
|
+
}
|
|
1335
|
+
try {
|
|
1336
|
+
const html = renderToString(seg.content, {
|
|
1337
|
+
displayMode: seg.type === "display",
|
|
1338
|
+
throwOnError: false
|
|
1339
|
+
});
|
|
1340
|
+
if (seg.type === "display") {
|
|
1341
|
+
return import_react10.default.createElement(MathDisplay, {
|
|
1342
|
+
key: i,
|
|
1343
|
+
dangerouslySetInnerHTML: { __html: html }
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
return import_react10.default.createElement(MathInline, {
|
|
1347
|
+
key: i,
|
|
1348
|
+
dangerouslySetInnerHTML: { __html: html }
|
|
1349
|
+
});
|
|
1350
|
+
} catch (err) {
|
|
1351
|
+
return import_react10.default.createElement(
|
|
1352
|
+
import_Alert5.default,
|
|
1353
|
+
{ key: i, severity: "error", sx: { my: 1 } },
|
|
1354
|
+
`LaTeX error: ${err instanceof Error ? err.message : String(err)}
|
|
1355
|
+
Source: ${seg.content}`
|
|
1356
|
+
);
|
|
1357
|
+
}
|
|
1358
|
+
});
|
|
1359
|
+
return import_react10.default.createElement(MathRoot, { className }, ...elements);
|
|
988
1360
|
}
|
|
989
|
-
|
|
1361
|
+
lazyKatex.load().catch(() => {
|
|
990
1362
|
});
|
|
991
|
-
var
|
|
992
|
-
type = "
|
|
993
|
-
priority =
|
|
1363
|
+
var MathRenderer = class {
|
|
1364
|
+
type = "math";
|
|
1365
|
+
priority = 40;
|
|
994
1366
|
canHandle(content) {
|
|
995
|
-
return
|
|
1367
|
+
return isMath(content);
|
|
996
1368
|
}
|
|
997
1369
|
render(content, options) {
|
|
998
|
-
return
|
|
1370
|
+
return import_react10.default.createElement(MathView, {
|
|
999
1371
|
content,
|
|
1000
|
-
className: options?.className ?? "fmcp-
|
|
1001
|
-
title: options?.toolName ?? "PDF Document"
|
|
1372
|
+
className: options?.className ?? "fmcp-math-content"
|
|
1002
1373
|
});
|
|
1003
1374
|
}
|
|
1004
1375
|
};
|
|
1005
|
-
var
|
|
1376
|
+
var mathRenderer = new MathRenderer();
|
|
1006
1377
|
|
|
1007
|
-
// libs/ui/src/renderer/
|
|
1008
|
-
var
|
|
1009
|
-
var
|
|
1378
|
+
// libs/ui/src/renderer/mdx/index.ts
|
|
1379
|
+
var import_Box8 = __toESM(require("@mui/material/Box"));
|
|
1380
|
+
var import_Link = __toESM(require("@mui/material/Link"));
|
|
1381
|
+
var import_styles9 = require("@mui/material/styles");
|
|
1010
1382
|
var import_Table2 = __toESM(require("@mui/material/Table"));
|
|
1011
1383
|
var import_TableBody2 = __toESM(require("@mui/material/TableBody"));
|
|
1012
1384
|
var import_TableCell2 = __toESM(require("@mui/material/TableCell"));
|
|
1013
|
-
var import_TableContainer = __toESM(require("@mui/material/TableContainer"));
|
|
1014
1385
|
var import_TableHead2 = __toESM(require("@mui/material/TableHead"));
|
|
1015
1386
|
var import_TableRow2 = __toESM(require("@mui/material/TableRow"));
|
|
1016
|
-
var
|
|
1017
|
-
var
|
|
1018
|
-
var
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
if (semicolons > commas) return ";";
|
|
1027
|
-
return ",";
|
|
1028
|
-
}
|
|
1029
|
-
function parseCsv(content, delimiter) {
|
|
1030
|
-
return content.trim().split("\n").map((line) => line.split(delimiter).map((cell) => cell.trim()));
|
|
1031
|
-
}
|
|
1032
|
-
var CsvRoot = (0, import_styles5.styled)(import_Box5.default, {
|
|
1033
|
-
name: "FrontMcpCsvTable",
|
|
1034
|
-
slot: "Root"
|
|
1035
|
-
})({
|
|
1036
|
-
width: "100%"
|
|
1037
|
-
});
|
|
1038
|
-
var StyledHeaderCell = (0, import_styles5.styled)(import_TableCell2.default, {
|
|
1039
|
-
name: "FrontMcpCsvTable",
|
|
1040
|
-
slot: "Header"
|
|
1041
|
-
})(({ theme }) => ({
|
|
1042
|
-
fontWeight: 600,
|
|
1043
|
-
backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[900] : theme.palette.grey[50],
|
|
1044
|
-
whiteSpace: "nowrap"
|
|
1045
|
-
}));
|
|
1046
|
-
var FilterToolbar = (0, import_styles5.styled)(import_Box5.default, {
|
|
1047
|
-
name: "FrontMcpCsvTable",
|
|
1048
|
-
slot: "Toolbar"
|
|
1049
|
-
})(({ theme }) => ({
|
|
1050
|
-
padding: theme.spacing(1, 2),
|
|
1051
|
-
display: "flex",
|
|
1052
|
-
gap: theme.spacing(1)
|
|
1053
|
-
}));
|
|
1054
|
-
function CsvTableView({ content, className, pageSize = 25 }) {
|
|
1055
|
-
const delimiter = (0, import_react8.useMemo)(() => detectDelimiter(content), [content]);
|
|
1056
|
-
const allRows = (0, import_react8.useMemo)(() => parseCsv(content, delimiter), [content, delimiter]);
|
|
1057
|
-
const headers = allRows[0] ?? [];
|
|
1058
|
-
const dataRows = (0, import_react8.useMemo)(() => allRows.slice(1), [allRows]);
|
|
1059
|
-
const [page, setPage] = (0, import_react8.useState)(0);
|
|
1060
|
-
const [rowsPerPage, setRowsPerPage] = (0, import_react8.useState)(pageSize);
|
|
1061
|
-
const [sortCol, setSortCol] = (0, import_react8.useState)(null);
|
|
1062
|
-
const [sortDir, setSortDir] = (0, import_react8.useState)("asc");
|
|
1063
|
-
const [filter, setFilter] = (0, import_react8.useState)("");
|
|
1064
|
-
const filteredRows = (0, import_react8.useMemo)(() => {
|
|
1065
|
-
if (!filter) return dataRows;
|
|
1066
|
-
const lower = filter.toLowerCase();
|
|
1067
|
-
return dataRows.filter((row) => row.some((cell) => cell.toLowerCase().includes(lower)));
|
|
1068
|
-
}, [dataRows, filter]);
|
|
1069
|
-
const sortedRows = (0, import_react8.useMemo)(() => {
|
|
1070
|
-
if (sortCol === null) return filteredRows;
|
|
1071
|
-
const sorted = [...filteredRows];
|
|
1072
|
-
sorted.sort((a, b) => {
|
|
1073
|
-
const va = a[sortCol] ?? "";
|
|
1074
|
-
const vb = b[sortCol] ?? "";
|
|
1075
|
-
const numA = Number(va);
|
|
1076
|
-
const numB = Number(vb);
|
|
1077
|
-
if (!isNaN(numA) && !isNaN(numB)) {
|
|
1078
|
-
return sortDir === "asc" ? numA - numB : numB - numA;
|
|
1079
|
-
}
|
|
1080
|
-
return sortDir === "asc" ? va.localeCompare(vb) : vb.localeCompare(va);
|
|
1081
|
-
});
|
|
1082
|
-
return sorted;
|
|
1083
|
-
}, [filteredRows, sortCol, sortDir]);
|
|
1084
|
-
const pageRows = (0, import_react8.useMemo)(
|
|
1085
|
-
() => sortedRows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage),
|
|
1086
|
-
[sortedRows, page, rowsPerPage]
|
|
1087
|
-
);
|
|
1088
|
-
const handleSort = (0, import_react8.useCallback)((colIndex) => {
|
|
1089
|
-
setSortCol((prev) => {
|
|
1090
|
-
if (prev === colIndex) {
|
|
1091
|
-
setSortDir((d) => d === "asc" ? "desc" : "asc");
|
|
1092
|
-
return colIndex;
|
|
1093
|
-
}
|
|
1094
|
-
setSortDir("asc");
|
|
1095
|
-
return colIndex;
|
|
1096
|
-
});
|
|
1097
|
-
}, []);
|
|
1098
|
-
const handleChangePage = (0, import_react8.useCallback)((_, newPage) => setPage(newPage), []);
|
|
1099
|
-
const handleChangeRowsPerPage = (0, import_react8.useCallback)((e) => {
|
|
1100
|
-
setRowsPerPage(parseInt(e.target.value, 10));
|
|
1101
|
-
setPage(0);
|
|
1102
|
-
}, []);
|
|
1103
|
-
return import_react8.default.createElement(
|
|
1104
|
-
CsvRoot,
|
|
1105
|
-
{ className },
|
|
1106
|
-
import_react8.default.createElement(
|
|
1107
|
-
FilterToolbar,
|
|
1108
|
-
null,
|
|
1109
|
-
import_react8.default.createElement(import_TextField2.default, {
|
|
1110
|
-
size: "small",
|
|
1111
|
-
placeholder: "Filter rows...",
|
|
1112
|
-
value: filter,
|
|
1113
|
-
onChange: (e) => {
|
|
1114
|
-
setFilter(e.target.value);
|
|
1115
|
-
setPage(0);
|
|
1116
|
-
},
|
|
1117
|
-
sx: { minWidth: 200 }
|
|
1118
|
-
})
|
|
1119
|
-
),
|
|
1120
|
-
import_react8.default.createElement(
|
|
1121
|
-
import_TableContainer.default,
|
|
1122
|
-
{ sx: { border: 1, borderColor: "divider", borderRadius: 1 } },
|
|
1123
|
-
import_react8.default.createElement(
|
|
1124
|
-
import_Table2.default,
|
|
1125
|
-
{ size: "small", stickyHeader: true },
|
|
1126
|
-
import_react8.default.createElement(
|
|
1127
|
-
import_TableHead2.default,
|
|
1128
|
-
null,
|
|
1129
|
-
import_react8.default.createElement(
|
|
1130
|
-
import_TableRow2.default,
|
|
1131
|
-
null,
|
|
1132
|
-
headers.map(
|
|
1133
|
-
(header, i) => import_react8.default.createElement(
|
|
1134
|
-
StyledHeaderCell,
|
|
1135
|
-
{ key: i },
|
|
1136
|
-
import_react8.default.createElement(
|
|
1137
|
-
import_TableSortLabel.default,
|
|
1138
|
-
{
|
|
1139
|
-
active: sortCol === i,
|
|
1140
|
-
direction: sortCol === i ? sortDir : "asc",
|
|
1141
|
-
onClick: () => handleSort(i)
|
|
1142
|
-
},
|
|
1143
|
-
header
|
|
1144
|
-
)
|
|
1145
|
-
)
|
|
1146
|
-
)
|
|
1147
|
-
)
|
|
1148
|
-
),
|
|
1149
|
-
import_react8.default.createElement(
|
|
1150
|
-
import_TableBody2.default,
|
|
1151
|
-
null,
|
|
1152
|
-
pageRows.map(
|
|
1153
|
-
(row, ri) => import_react8.default.createElement(
|
|
1154
|
-
import_TableRow2.default,
|
|
1155
|
-
{ key: ri, hover: true },
|
|
1156
|
-
row.map((cell, ci) => import_react8.default.createElement(import_TableCell2.default, { key: ci }, cell))
|
|
1157
|
-
)
|
|
1158
|
-
)
|
|
1159
|
-
)
|
|
1160
|
-
)
|
|
1161
|
-
),
|
|
1162
|
-
sortedRows.length > rowsPerPage && import_react8.default.createElement(import_TablePagination.default, {
|
|
1163
|
-
count: sortedRows.length,
|
|
1164
|
-
page,
|
|
1165
|
-
rowsPerPage,
|
|
1166
|
-
onPageChange: handleChangePage,
|
|
1167
|
-
onRowsPerPageChange: handleChangeRowsPerPage,
|
|
1168
|
-
rowsPerPageOptions: [10, 25, 50, 100]
|
|
1169
|
-
})
|
|
1170
|
-
);
|
|
1171
|
-
}
|
|
1172
|
-
var CsvRenderer = class {
|
|
1173
|
-
type = "csv";
|
|
1174
|
-
priority = 10;
|
|
1175
|
-
canHandle(content) {
|
|
1176
|
-
const lines = content.trim().split("\n").slice(0, 5);
|
|
1177
|
-
if (lines.length < 2) return false;
|
|
1178
|
-
for (const delim of [",", " ", ";"]) {
|
|
1179
|
-
const counts = lines.map((line) => line.split(delim).length);
|
|
1180
|
-
if (counts[0] > 1 && counts.every((c) => c === counts[0])) return true;
|
|
1181
|
-
}
|
|
1182
|
-
return false;
|
|
1183
|
-
}
|
|
1184
|
-
render(content, options) {
|
|
1185
|
-
const pageSize = options?.rendererOptions?.["pageSize"];
|
|
1186
|
-
return import_react8.default.createElement(CsvTableView, {
|
|
1187
|
-
content,
|
|
1188
|
-
className: options?.className ?? "fmcp-csv-table",
|
|
1189
|
-
pageSize
|
|
1190
|
-
});
|
|
1387
|
+
var import_Typography5 = __toESM(require("@mui/material/Typography"));
|
|
1388
|
+
var import_react11 = __toESM(require("react"));
|
|
1389
|
+
var lazyReactMarkdown = createLazyImport(
|
|
1390
|
+
"react-markdown",
|
|
1391
|
+
async () => {
|
|
1392
|
+
const mod = await runtimeImportWithFallback(
|
|
1393
|
+
"react-markdown",
|
|
1394
|
+
esmShUrl("react-markdown@9", { external: ["react", "react-dom"] })
|
|
1395
|
+
);
|
|
1396
|
+
return mod;
|
|
1191
1397
|
}
|
|
1192
|
-
|
|
1193
|
-
var
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
var import_react9 = __toESM(require("react"));
|
|
1197
|
-
var import_Box6 = __toESM(require("@mui/material/Box"));
|
|
1198
|
-
var import_Skeleton = __toESM(require("@mui/material/Skeleton"));
|
|
1199
|
-
var import_Alert2 = __toESM(require("@mui/material/Alert"));
|
|
1200
|
-
var import_Typography3 = __toESM(require("@mui/material/Typography"));
|
|
1201
|
-
var import_styles6 = require("@mui/material/styles");
|
|
1202
|
-
var IMAGE_DATA_URI = /^data:image\/(?:png|jpeg|jpg|gif|webp|svg\+xml|avif)[;,]/;
|
|
1203
|
-
var IMAGE_URL = /^https?:\/\/[^?#\s]+\.(?:png|jpe?g|gif|webp|svg|avif|ico)(?:\?[^#\s]*)?$/i;
|
|
1204
|
-
var IMAGE_SERVICE_URL = /^https?:\/\/(?:picsum\.photos|images\.unsplash\.com|i\.imgur\.com|placekitten\.com|via\.placeholder\.com)\//i;
|
|
1205
|
-
function isImage(content) {
|
|
1206
|
-
const trimmed = content.trim();
|
|
1207
|
-
return IMAGE_DATA_URI.test(trimmed) || IMAGE_URL.test(trimmed) || IMAGE_SERVICE_URL.test(trimmed);
|
|
1208
|
-
}
|
|
1209
|
-
var ImageRoot = (0, import_styles6.styled)(import_Box6.default, {
|
|
1210
|
-
name: "FrontMcpImage",
|
|
1211
|
-
slot: "Root"
|
|
1212
|
-
})({
|
|
1213
|
-
display: "inline-block",
|
|
1214
|
-
position: "relative",
|
|
1215
|
-
maxWidth: "100%"
|
|
1398
|
+
);
|
|
1399
|
+
var lazyRemarkGfm = createLazyImport("remark-gfm", async () => {
|
|
1400
|
+
const mod = await runtimeImportWithFallback("remark-gfm", esmShUrl("remark-gfm@4"));
|
|
1401
|
+
return mod;
|
|
1216
1402
|
});
|
|
1217
|
-
var
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
})({
|
|
1221
|
-
maxWidth: "100%",
|
|
1222
|
-
height: "auto",
|
|
1223
|
-
display: "block",
|
|
1224
|
-
cursor: "pointer",
|
|
1225
|
-
borderRadius: "inherit"
|
|
1403
|
+
var lazyRehypeHighlight = createLazyImport("rehype-highlight", async () => {
|
|
1404
|
+
const mod = await runtimeImportWithFallback("rehype-highlight", esmShUrl("rehype-highlight@7"));
|
|
1405
|
+
return mod;
|
|
1226
1406
|
});
|
|
1227
|
-
var
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
})({
|
|
1231
|
-
display: "flex",
|
|
1232
|
-
alignItems: "center",
|
|
1233
|
-
justifyContent: "center",
|
|
1234
|
-
padding: 16
|
|
1407
|
+
var lazyRehypeRaw = createLazyImport("rehype-raw", async () => {
|
|
1408
|
+
const mod = await runtimeImportWithFallback("rehype-raw", esmShUrl("rehype-raw@7"));
|
|
1409
|
+
return mod;
|
|
1235
1410
|
});
|
|
1236
|
-
var
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1411
|
+
var MarkdownRoot = (0, import_styles9.styled)(import_Box8.default, {
|
|
1412
|
+
name: "FrontMcpMarkdown",
|
|
1413
|
+
slot: "Root"
|
|
1414
|
+
})(() => ({
|
|
1415
|
+
lineHeight: 1.7,
|
|
1416
|
+
"& > *:first-of-type": { marginTop: 0 },
|
|
1417
|
+
"& > *:last-child": { marginBottom: 0 },
|
|
1418
|
+
"& img": { maxWidth: "100%", height: "auto" }
|
|
1419
|
+
}));
|
|
1420
|
+
var CodeBlock = (0, import_styles9.styled)("pre", {
|
|
1421
|
+
name: "FrontMcpMarkdown",
|
|
1422
|
+
slot: "Code"
|
|
1423
|
+
})(({ theme }) => {
|
|
1424
|
+
const monoFont = String(
|
|
1425
|
+
theme.typography["monoFontFamily"] ?? '"SF Mono", "Fira Code", "Roboto Mono", monospace'
|
|
1426
|
+
);
|
|
1427
|
+
return {
|
|
1428
|
+
backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[900] : theme.palette.grey[100],
|
|
1429
|
+
padding: theme.spacing(2),
|
|
1430
|
+
borderRadius: Number(theme.shape.borderRadius),
|
|
1431
|
+
overflow: "auto",
|
|
1432
|
+
fontFamily: monoFont,
|
|
1433
|
+
fontSize: "0.875rem",
|
|
1434
|
+
"& code": {
|
|
1435
|
+
backgroundColor: "transparent",
|
|
1436
|
+
padding: 0,
|
|
1437
|
+
fontSize: "inherit",
|
|
1438
|
+
fontFamily: "inherit"
|
|
1439
|
+
}
|
|
1440
|
+
};
|
|
1241
1441
|
});
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
{
|
|
1246
|
-
onClick: onClose,
|
|
1247
|
-
sx: {
|
|
1248
|
-
position: "fixed",
|
|
1249
|
-
inset: 0,
|
|
1250
|
-
zIndex: 1300,
|
|
1251
|
-
bgcolor: "rgba(0,0,0,0.8)"
|
|
1252
|
-
}
|
|
1253
|
-
},
|
|
1254
|
-
import_react9.default.createElement(LightboxImage, { src, alt })
|
|
1442
|
+
var InlineCode = (0, import_styles9.styled)("code")(({ theme }) => {
|
|
1443
|
+
const monoFont = String(
|
|
1444
|
+
theme.typography["monoFontFamily"] ?? '"SF Mono", "Fira Code", "Roboto Mono", monospace'
|
|
1255
1445
|
);
|
|
1446
|
+
return {
|
|
1447
|
+
backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[800] : theme.palette.grey[200],
|
|
1448
|
+
padding: "2px 6px",
|
|
1449
|
+
borderRadius: Number(theme.shape.borderRadius) / 2,
|
|
1450
|
+
fontFamily: monoFont,
|
|
1451
|
+
fontSize: "0.85em"
|
|
1452
|
+
};
|
|
1453
|
+
});
|
|
1454
|
+
var Blockquote = (0, import_styles9.styled)("blockquote", {
|
|
1455
|
+
name: "FrontMcpMarkdown",
|
|
1456
|
+
slot: "Blockquote"
|
|
1457
|
+
})(({ theme }) => ({
|
|
1458
|
+
borderLeft: `4px solid ${theme.palette.primary.main}`,
|
|
1459
|
+
margin: theme.spacing(2, 0),
|
|
1460
|
+
padding: theme.spacing(1, 2),
|
|
1461
|
+
color: theme.palette.text.secondary,
|
|
1462
|
+
"& > p": { margin: 0 }
|
|
1463
|
+
}));
|
|
1464
|
+
function createMuiComponents() {
|
|
1465
|
+
return {
|
|
1466
|
+
h1: (props) => import_react11.default.createElement(import_Typography5.default, { ...props, variant: "h4", gutterBottom: true }),
|
|
1467
|
+
h2: (props) => import_react11.default.createElement(import_Typography5.default, { ...props, variant: "h5", gutterBottom: true }),
|
|
1468
|
+
h3: (props) => import_react11.default.createElement(import_Typography5.default, { ...props, variant: "h6", gutterBottom: true }),
|
|
1469
|
+
h4: (props) => import_react11.default.createElement(import_Typography5.default, { ...props, variant: "subtitle1", gutterBottom: true, fontWeight: 600 }),
|
|
1470
|
+
h5: (props) => import_react11.default.createElement(import_Typography5.default, { ...props, variant: "subtitle2", gutterBottom: true }),
|
|
1471
|
+
h6: (props) => import_react11.default.createElement(import_Typography5.default, { ...props, variant: "subtitle2", gutterBottom: true }),
|
|
1472
|
+
p: (props) => import_react11.default.createElement(import_Typography5.default, { ...props, variant: "body1", paragraph: true }),
|
|
1473
|
+
a: (props) => import_react11.default.createElement(import_Link.default, { ...props, target: "_blank", rel: "noopener noreferrer" }),
|
|
1474
|
+
blockquote: (props) => import_react11.default.createElement(Blockquote, props),
|
|
1475
|
+
pre: (props) => import_react11.default.createElement(CodeBlock, props),
|
|
1476
|
+
code: ({ inline, className, children, ...rest }) => {
|
|
1477
|
+
if (inline) return import_react11.default.createElement(InlineCode, rest, children);
|
|
1478
|
+
return import_react11.default.createElement("code", { className, ...rest }, children);
|
|
1479
|
+
},
|
|
1480
|
+
table: (props) => import_react11.default.createElement(import_Table2.default, { ...props, size: "small" }),
|
|
1481
|
+
thead: (props) => import_react11.default.createElement(import_TableHead2.default, props),
|
|
1482
|
+
tbody: (props) => import_react11.default.createElement(import_TableBody2.default, props),
|
|
1483
|
+
tr: (props) => import_react11.default.createElement(import_TableRow2.default, { ...props, hover: true }),
|
|
1484
|
+
th: (props) => import_react11.default.createElement(import_TableCell2.default, { ...props, sx: { fontWeight: 600 } }),
|
|
1485
|
+
td: (props) => import_react11.default.createElement(import_TableCell2.default, props)
|
|
1486
|
+
};
|
|
1256
1487
|
}
|
|
1257
|
-
function
|
|
1258
|
-
const
|
|
1259
|
-
const
|
|
1260
|
-
const
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1488
|
+
function MarkdownView({ content, className }) {
|
|
1489
|
+
const components = (0, import_react11.useMemo)(() => createMuiComponents(), []);
|
|
1490
|
+
const ReactMarkdownMod = useLazyModule(lazyReactMarkdown);
|
|
1491
|
+
const remarkGfmMod = lazyRemarkGfm.get();
|
|
1492
|
+
const rehypeHighlightMod = lazyRehypeHighlight.get();
|
|
1493
|
+
const rehypeRawMod = lazyRehypeRaw.get();
|
|
1494
|
+
if (ReactMarkdownMod) {
|
|
1495
|
+
const ReactMarkdown = ReactMarkdownMod.default;
|
|
1496
|
+
const remarkPlugins = [];
|
|
1497
|
+
const rehypePlugins = [];
|
|
1498
|
+
if (remarkGfmMod) remarkPlugins.push(remarkGfmMod.default);
|
|
1499
|
+
if (rehypeHighlightMod) rehypePlugins.push(rehypeHighlightMod.default);
|
|
1500
|
+
if (rehypeRawMod) rehypePlugins.push(rehypeRawMod.default);
|
|
1501
|
+
return import_react11.default.createElement(
|
|
1502
|
+
MarkdownRoot,
|
|
1503
|
+
{ className },
|
|
1504
|
+
import_react11.default.createElement(ReactMarkdown, {
|
|
1505
|
+
children: content,
|
|
1506
|
+
remarkPlugins,
|
|
1507
|
+
rehypePlugins,
|
|
1508
|
+
components
|
|
1509
|
+
})
|
|
1510
|
+
);
|
|
1273
1511
|
}
|
|
1274
|
-
return
|
|
1275
|
-
ImageRoot,
|
|
1276
|
-
{ className },
|
|
1277
|
-
!loaded && import_react9.default.createElement(import_Skeleton.default, { variant: "rectangular", width: 400, height: 300 }),
|
|
1278
|
-
import_react9.default.createElement(StyledImage, {
|
|
1279
|
-
src,
|
|
1280
|
-
alt: alt ?? "Image",
|
|
1281
|
-
onLoad: handleLoad,
|
|
1282
|
-
onError: handleError,
|
|
1283
|
-
onClick: () => setLightboxOpen(true),
|
|
1284
|
-
style: loaded ? void 0 : { display: "none" }
|
|
1285
|
-
}),
|
|
1286
|
-
caption && import_react9.default.createElement(
|
|
1287
|
-
import_Typography3.default,
|
|
1288
|
-
{ variant: "caption", color: "text.secondary", sx: { mt: 0.5, display: "block", textAlign: "center" } },
|
|
1289
|
-
caption
|
|
1290
|
-
),
|
|
1291
|
-
lightboxOpen && import_react9.default.createElement(LightboxOverlay, {
|
|
1292
|
-
src,
|
|
1293
|
-
alt: alt ?? "Image",
|
|
1294
|
-
onClose: () => setLightboxOpen(false)
|
|
1295
|
-
})
|
|
1296
|
-
);
|
|
1512
|
+
return import_react11.default.createElement(MarkdownRoot, { className }, ...renderFallback(content));
|
|
1297
1513
|
}
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1514
|
+
function renderFallback(content) {
|
|
1515
|
+
const lines = content.split("\n");
|
|
1516
|
+
const elements = [];
|
|
1517
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1518
|
+
const line = lines[i];
|
|
1519
|
+
if (line.startsWith("# ")) {
|
|
1520
|
+
elements.push(import_react11.default.createElement(import_Typography5.default, { key: i, variant: "h4", gutterBottom: true }, line.slice(2)));
|
|
1521
|
+
} else if (line.startsWith("## ")) {
|
|
1522
|
+
elements.push(import_react11.default.createElement(import_Typography5.default, { key: i, variant: "h5", gutterBottom: true }, line.slice(3)));
|
|
1523
|
+
} else if (line.startsWith("### ")) {
|
|
1524
|
+
elements.push(import_react11.default.createElement(import_Typography5.default, { key: i, variant: "h6", gutterBottom: true }, line.slice(4)));
|
|
1525
|
+
} else if (line.startsWith("- ") || line.startsWith("* ")) {
|
|
1526
|
+
elements.push(import_react11.default.createElement("li", { key: i }, line.slice(2)));
|
|
1527
|
+
} else if (line.startsWith("**") && line.endsWith("**")) {
|
|
1528
|
+
elements.push(
|
|
1529
|
+
import_react11.default.createElement(import_Typography5.default, { key: i, variant: "body1", sx: { fontWeight: 700 } }, line.slice(2, -2))
|
|
1530
|
+
);
|
|
1531
|
+
} else if (line.trim()) {
|
|
1532
|
+
elements.push(import_react11.default.createElement(import_Typography5.default, { key: i, variant: "body1", sx: { mb: 2 } }, line));
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
return elements;
|
|
1536
|
+
}
|
|
1537
|
+
lazyReactMarkdown.load().catch(() => {
|
|
1538
|
+
});
|
|
1539
|
+
lazyRemarkGfm.load().catch(() => {
|
|
1540
|
+
});
|
|
1541
|
+
lazyRehypeHighlight.load().catch(() => {
|
|
1542
|
+
});
|
|
1543
|
+
lazyRehypeRaw.load().catch(() => {
|
|
1544
|
+
});
|
|
1545
|
+
var MdxRenderer = class {
|
|
1546
|
+
type = "mdx";
|
|
1547
|
+
priority = 5;
|
|
1301
1548
|
canHandle(content) {
|
|
1302
|
-
return
|
|
1549
|
+
return /^---\s*\n/.test(content) || /import\s+/.test(content) || /<[A-Z]/.test(content) || /^#{1,6}\s+\S/m.test(content) || /^\s*[-*+]\s+\S/m.test(content);
|
|
1303
1550
|
}
|
|
1304
1551
|
render(content, options) {
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
alt: options?.toolName ?? "Image",
|
|
1309
|
-
caption,
|
|
1310
|
-
className: options?.className ?? "fmcp-image-content"
|
|
1552
|
+
return import_react11.default.createElement(MarkdownView, {
|
|
1553
|
+
content,
|
|
1554
|
+
className: options?.className ?? "fmcp-mdx-content"
|
|
1311
1555
|
});
|
|
1312
1556
|
}
|
|
1313
1557
|
};
|
|
1314
|
-
var
|
|
1558
|
+
var mdxRenderer = new MdxRenderer();
|
|
1315
1559
|
|
|
1316
|
-
// libs/ui/src/renderer/
|
|
1317
|
-
var
|
|
1318
|
-
var
|
|
1319
|
-
var
|
|
1320
|
-
var
|
|
1321
|
-
var
|
|
1322
|
-
|
|
1323
|
-
|
|
1560
|
+
// libs/ui/src/renderer/media/index.ts
|
|
1561
|
+
var import_Box9 = __toESM(require("@mui/material/Box"));
|
|
1562
|
+
var import_Paper2 = __toESM(require("@mui/material/Paper"));
|
|
1563
|
+
var import_styles10 = require("@mui/material/styles");
|
|
1564
|
+
var import_react12 = __toESM(require("react"));
|
|
1565
|
+
var VIDEO_PATTERNS2 = [
|
|
1566
|
+
/^https?:\/\/[^?#\s]+\.(?:mp4|webm|ogg|mov)(?:\?[^#\s]*)?$/i,
|
|
1567
|
+
/^https?:\/\/(?:www\.)?(?:youtube\.com|youtu\.be|vimeo\.com)\//i,
|
|
1568
|
+
/^data:video\//
|
|
1569
|
+
];
|
|
1570
|
+
var AUDIO_PATTERNS2 = [
|
|
1571
|
+
/^https?:\/\/[^?#\s]+\.(?:mp3|wav|ogg|aac|flac|m4a)(?:\?[^#\s]*)?$/i,
|
|
1572
|
+
/^https?:\/\/(?:www\.)?soundcloud\.com\//i,
|
|
1573
|
+
/^data:audio\//
|
|
1574
|
+
];
|
|
1575
|
+
function isVideo(content) {
|
|
1324
1576
|
const trimmed = content.trim();
|
|
1325
|
-
|
|
1326
|
-
return CHART_TYPE_RE2.test(trimmed) && trimmed.includes('"data"');
|
|
1577
|
+
return VIDEO_PATTERNS2.some((p) => p.test(trimmed));
|
|
1327
1578
|
}
|
|
1328
|
-
|
|
1329
|
-
const
|
|
1579
|
+
function isAudio(content) {
|
|
1580
|
+
const trimmed = content.trim();
|
|
1581
|
+
return AUDIO_PATTERNS2.some((p) => p.test(trimmed));
|
|
1582
|
+
}
|
|
1583
|
+
function isMedia(content) {
|
|
1584
|
+
return isVideo(content) || isAudio(content);
|
|
1585
|
+
}
|
|
1586
|
+
var lazyReactPlayer = createLazyImport("react-player", async () => {
|
|
1587
|
+
const mod = await runtimeImportWithFallback(
|
|
1588
|
+
"react-player",
|
|
1589
|
+
esmShUrl("react-player@2", { external: ["react", "react-dom"] })
|
|
1590
|
+
);
|
|
1330
1591
|
return mod;
|
|
1331
1592
|
});
|
|
1332
|
-
var
|
|
1333
|
-
name: "
|
|
1593
|
+
var MediaRoot = (0, import_styles10.styled)(import_Paper2.default, {
|
|
1594
|
+
name: "FrontMcpMedia",
|
|
1334
1595
|
slot: "Root"
|
|
1335
1596
|
})(({ theme }) => ({
|
|
1336
|
-
|
|
1337
|
-
|
|
1597
|
+
overflow: "hidden",
|
|
1598
|
+
borderRadius: theme.shape.borderRadius
|
|
1338
1599
|
}));
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1600
|
+
var VideoWrapper = (0, import_styles10.styled)(import_Box9.default)({
|
|
1601
|
+
position: "relative",
|
|
1602
|
+
paddingTop: "56.25%",
|
|
1603
|
+
// 16:9 aspect ratio
|
|
1604
|
+
"& > *": {
|
|
1605
|
+
position: "absolute",
|
|
1606
|
+
top: 0,
|
|
1607
|
+
left: 0
|
|
1345
1608
|
}
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
{ variant: "subtitle1", gutterBottom: true, sx: { fontWeight: 600, textAlign: "center" } },
|
|
1365
|
-
config.title
|
|
1366
|
-
),
|
|
1367
|
-
import_react10.default.createElement(ResponsiveContainer, { width: "100%", height }, chartContent)
|
|
1368
|
-
);
|
|
1369
|
-
}
|
|
1370
|
-
function renderChartType(rc, type, data, xKey, yKeys, colors, borderRadius) {
|
|
1371
|
-
const commonProps = { data };
|
|
1372
|
-
const grid = import_react10.default.createElement(rc.CartesianGrid, { strokeDasharray: "3 3", opacity: 0.3 });
|
|
1373
|
-
const xAxis = import_react10.default.createElement(rc.XAxis, { dataKey: xKey });
|
|
1374
|
-
const yAxis = import_react10.default.createElement(rc.YAxis);
|
|
1375
|
-
const tooltip = import_react10.default.createElement(rc.Tooltip, { contentStyle: { borderRadius } });
|
|
1376
|
-
const legend = import_react10.default.createElement(rc.Legend);
|
|
1377
|
-
switch (type) {
|
|
1378
|
-
case "bar":
|
|
1379
|
-
return import_react10.default.createElement(
|
|
1380
|
-
rc.BarChart,
|
|
1381
|
-
commonProps,
|
|
1382
|
-
grid,
|
|
1383
|
-
xAxis,
|
|
1384
|
-
yAxis,
|
|
1385
|
-
tooltip,
|
|
1386
|
-
legend,
|
|
1387
|
-
...yKeys.map(
|
|
1388
|
-
(key, i) => import_react10.default.createElement(rc.Bar, {
|
|
1389
|
-
key,
|
|
1390
|
-
dataKey: key,
|
|
1391
|
-
fill: colors[i % colors.length],
|
|
1392
|
-
radius: [borderRadius, borderRadius, 0, 0]
|
|
1393
|
-
})
|
|
1394
|
-
)
|
|
1395
|
-
);
|
|
1396
|
-
case "line":
|
|
1397
|
-
return import_react10.default.createElement(
|
|
1398
|
-
rc.LineChart,
|
|
1399
|
-
commonProps,
|
|
1400
|
-
grid,
|
|
1401
|
-
xAxis,
|
|
1402
|
-
yAxis,
|
|
1403
|
-
tooltip,
|
|
1404
|
-
legend,
|
|
1405
|
-
...yKeys.map(
|
|
1406
|
-
(key, i) => import_react10.default.createElement(rc.Line, {
|
|
1407
|
-
key,
|
|
1408
|
-
type: "monotone",
|
|
1409
|
-
dataKey: key,
|
|
1410
|
-
stroke: colors[i % colors.length],
|
|
1411
|
-
strokeWidth: 2
|
|
1412
|
-
})
|
|
1413
|
-
)
|
|
1414
|
-
);
|
|
1415
|
-
case "area":
|
|
1416
|
-
return import_react10.default.createElement(
|
|
1417
|
-
rc.AreaChart,
|
|
1418
|
-
commonProps,
|
|
1419
|
-
grid,
|
|
1420
|
-
xAxis,
|
|
1421
|
-
yAxis,
|
|
1422
|
-
tooltip,
|
|
1423
|
-
legend,
|
|
1424
|
-
...yKeys.map(
|
|
1425
|
-
(key, i) => import_react10.default.createElement(rc.Area, {
|
|
1426
|
-
key,
|
|
1427
|
-
type: "monotone",
|
|
1428
|
-
dataKey: key,
|
|
1429
|
-
stroke: colors[i % colors.length],
|
|
1430
|
-
fill: colors[i % colors.length],
|
|
1431
|
-
fillOpacity: 0.3
|
|
1432
|
-
})
|
|
1433
|
-
)
|
|
1434
|
-
);
|
|
1435
|
-
case "pie":
|
|
1436
|
-
return import_react10.default.createElement(
|
|
1437
|
-
rc.PieChart,
|
|
1438
|
-
{},
|
|
1439
|
-
tooltip,
|
|
1440
|
-
legend,
|
|
1441
|
-
import_react10.default.createElement(
|
|
1442
|
-
rc.Pie,
|
|
1443
|
-
{ data, dataKey: yKeys[0] ?? "value", nameKey: xKey, cx: "50%", cy: "50%", outerRadius: "80%", label: true },
|
|
1444
|
-
...data.map((_, i) => import_react10.default.createElement(rc.Cell, { key: i, fill: colors[i % colors.length] }))
|
|
1445
|
-
)
|
|
1446
|
-
);
|
|
1447
|
-
case "scatter":
|
|
1448
|
-
return import_react10.default.createElement(
|
|
1449
|
-
rc.ScatterChart,
|
|
1450
|
-
{},
|
|
1451
|
-
grid,
|
|
1452
|
-
xAxis,
|
|
1453
|
-
yAxis,
|
|
1454
|
-
tooltip,
|
|
1455
|
-
legend,
|
|
1456
|
-
...yKeys.map(
|
|
1457
|
-
(key, i) => import_react10.default.createElement(rc.Scatter, { key, name: key, dataKey: key, data, fill: colors[i % colors.length] })
|
|
1458
|
-
)
|
|
1459
|
-
);
|
|
1460
|
-
case "radar":
|
|
1461
|
-
return import_react10.default.createElement(
|
|
1462
|
-
rc.RadarChart,
|
|
1463
|
-
{ cx: "50%", cy: "50%", outerRadius: "80%", data },
|
|
1464
|
-
import_react10.default.createElement(rc.PolarGrid),
|
|
1465
|
-
import_react10.default.createElement(rc.PolarAngleAxis, { dataKey: xKey }),
|
|
1466
|
-
import_react10.default.createElement(rc.PolarRadiusAxis),
|
|
1467
|
-
tooltip,
|
|
1468
|
-
legend,
|
|
1469
|
-
...yKeys.map(
|
|
1470
|
-
(key, i) => import_react10.default.createElement(rc.Radar, {
|
|
1471
|
-
key,
|
|
1472
|
-
name: key,
|
|
1473
|
-
dataKey: key,
|
|
1474
|
-
stroke: colors[i % colors.length],
|
|
1475
|
-
fill: colors[i % colors.length],
|
|
1476
|
-
fillOpacity: 0.3
|
|
1477
|
-
})
|
|
1609
|
+
});
|
|
1610
|
+
var AudioWrapper = (0, import_styles10.styled)(import_Box9.default)(({ theme }) => ({
|
|
1611
|
+
padding: theme.spacing(1),
|
|
1612
|
+
"& > *": {
|
|
1613
|
+
width: "100%"
|
|
1614
|
+
}
|
|
1615
|
+
}));
|
|
1616
|
+
function MediaView({ url, isAudioContent, className }) {
|
|
1617
|
+
const reactPlayerMod = useLazyModule(lazyReactPlayer);
|
|
1618
|
+
if (!reactPlayerMod) {
|
|
1619
|
+
if (isAudioContent) {
|
|
1620
|
+
return import_react12.default.createElement(
|
|
1621
|
+
MediaRoot,
|
|
1622
|
+
{ variant: "outlined", className },
|
|
1623
|
+
import_react12.default.createElement(
|
|
1624
|
+
AudioWrapper,
|
|
1625
|
+
null,
|
|
1626
|
+
import_react12.default.createElement("audio", { controls: true, src: url, style: { width: "100%" } })
|
|
1478
1627
|
)
|
|
1479
1628
|
);
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
return import_react10.default.createElement(rc.Bar, {
|
|
1492
|
-
key,
|
|
1493
|
-
dataKey: key,
|
|
1494
|
-
fill: colors[i % colors.length],
|
|
1495
|
-
radius: [borderRadius, borderRadius, 0, 0]
|
|
1496
|
-
});
|
|
1497
|
-
}
|
|
1498
|
-
return import_react10.default.createElement(rc.Line, {
|
|
1499
|
-
key,
|
|
1500
|
-
type: "monotone",
|
|
1501
|
-
dataKey: key,
|
|
1502
|
-
stroke: colors[i % colors.length],
|
|
1503
|
-
strokeWidth: 2
|
|
1504
|
-
});
|
|
1629
|
+
}
|
|
1630
|
+
return import_react12.default.createElement(
|
|
1631
|
+
MediaRoot,
|
|
1632
|
+
{ variant: "outlined", className },
|
|
1633
|
+
import_react12.default.createElement(
|
|
1634
|
+
VideoWrapper,
|
|
1635
|
+
null,
|
|
1636
|
+
import_react12.default.createElement("video", {
|
|
1637
|
+
controls: true,
|
|
1638
|
+
src: url,
|
|
1639
|
+
style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }
|
|
1505
1640
|
})
|
|
1506
|
-
)
|
|
1507
|
-
|
|
1508
|
-
|
|
1641
|
+
)
|
|
1642
|
+
);
|
|
1643
|
+
}
|
|
1644
|
+
const ReactPlayer = reactPlayerMod.default;
|
|
1645
|
+
if (isAudioContent) {
|
|
1646
|
+
return import_react12.default.createElement(
|
|
1647
|
+
MediaRoot,
|
|
1648
|
+
{ variant: "outlined", className },
|
|
1649
|
+
import_react12.default.createElement(
|
|
1650
|
+
AudioWrapper,
|
|
1651
|
+
null,
|
|
1652
|
+
import_react12.default.createElement(ReactPlayer, {
|
|
1653
|
+
url,
|
|
1654
|
+
controls: true,
|
|
1655
|
+
width: "100%",
|
|
1656
|
+
height: 50
|
|
1657
|
+
})
|
|
1658
|
+
)
|
|
1659
|
+
);
|
|
1509
1660
|
}
|
|
1661
|
+
return import_react12.default.createElement(
|
|
1662
|
+
MediaRoot,
|
|
1663
|
+
{ variant: "outlined", className },
|
|
1664
|
+
import_react12.default.createElement(
|
|
1665
|
+
VideoWrapper,
|
|
1666
|
+
null,
|
|
1667
|
+
import_react12.default.createElement(ReactPlayer, {
|
|
1668
|
+
url,
|
|
1669
|
+
controls: true,
|
|
1670
|
+
width: "100%",
|
|
1671
|
+
height: "100%"
|
|
1672
|
+
})
|
|
1673
|
+
)
|
|
1674
|
+
);
|
|
1510
1675
|
}
|
|
1511
|
-
|
|
1676
|
+
lazyReactPlayer.load().catch(() => {
|
|
1512
1677
|
});
|
|
1513
|
-
var
|
|
1514
|
-
type = "
|
|
1515
|
-
priority =
|
|
1678
|
+
var VideoRenderer = class {
|
|
1679
|
+
type = "video";
|
|
1680
|
+
priority = 20;
|
|
1516
1681
|
canHandle(content) {
|
|
1517
|
-
return
|
|
1682
|
+
return isVideo(content);
|
|
1518
1683
|
}
|
|
1519
1684
|
render(content, options) {
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
});
|
|
1526
|
-
} catch {
|
|
1527
|
-
return import_react10.default.createElement(import_Alert3.default, { severity: "error" }, "Invalid chart JSON");
|
|
1528
|
-
}
|
|
1685
|
+
return import_react12.default.createElement(MediaView, {
|
|
1686
|
+
url: content.trim(),
|
|
1687
|
+
isAudioContent: false,
|
|
1688
|
+
className: options?.className ?? "fmcp-media-content"
|
|
1689
|
+
});
|
|
1529
1690
|
}
|
|
1530
1691
|
};
|
|
1531
|
-
var
|
|
1692
|
+
var AudioRenderer = class {
|
|
1693
|
+
type = "audio";
|
|
1694
|
+
priority = 20;
|
|
1695
|
+
canHandle(content) {
|
|
1696
|
+
return isAudio(content);
|
|
1697
|
+
}
|
|
1698
|
+
render(content, options) {
|
|
1699
|
+
return import_react12.default.createElement(MediaView, {
|
|
1700
|
+
url: content.trim(),
|
|
1701
|
+
isAudioContent: true,
|
|
1702
|
+
className: options?.className ?? "fmcp-media-content"
|
|
1703
|
+
});
|
|
1704
|
+
}
|
|
1705
|
+
};
|
|
1706
|
+
var videoRenderer = new VideoRenderer();
|
|
1707
|
+
var audioRenderer = new AudioRenderer();
|
|
1532
1708
|
|
|
1533
1709
|
// libs/ui/src/renderer/mermaid/index.ts
|
|
1534
|
-
var
|
|
1535
|
-
var
|
|
1536
|
-
var
|
|
1537
|
-
var
|
|
1710
|
+
var import_Alert6 = __toESM(require("@mui/material/Alert"));
|
|
1711
|
+
var import_Box10 = __toESM(require("@mui/material/Box"));
|
|
1712
|
+
var import_styles11 = require("@mui/material/styles");
|
|
1713
|
+
var import_react13 = __toESM(require("react"));
|
|
1538
1714
|
var MERMAID_PATTERN2 = /^\s*(?:graph|sequenceDiagram|classDiagram|stateDiagram|flowchart|erDiagram|gantt|pie|journey|gitGraph)\b/;
|
|
1539
1715
|
function isMermaid(content) {
|
|
1540
1716
|
return MERMAID_PATTERN2.test(content.trim());
|
|
@@ -1544,7 +1720,7 @@ var lazyMermaid = createLazyImport("mermaid", async () => {
|
|
|
1544
1720
|
const mermaid = mod["default"] ?? mod;
|
|
1545
1721
|
return mermaid;
|
|
1546
1722
|
});
|
|
1547
|
-
var MermaidRoot = (0,
|
|
1723
|
+
var MermaidRoot = (0, import_styles11.styled)(import_Box10.default, {
|
|
1548
1724
|
name: "FrontMcpMermaid",
|
|
1549
1725
|
slot: "Root"
|
|
1550
1726
|
})(({ theme }) => ({
|
|
@@ -1573,12 +1749,12 @@ function getMermaidThemeVariables(tv) {
|
|
|
1573
1749
|
};
|
|
1574
1750
|
}
|
|
1575
1751
|
function MermaidView({ definition, className }) {
|
|
1576
|
-
const containerRef = (0,
|
|
1577
|
-
const [svg, setSvg] = (0,
|
|
1578
|
-
const [error, setError] = (0,
|
|
1752
|
+
const containerRef = (0, import_react13.useRef)(null);
|
|
1753
|
+
const [svg, setSvg] = (0, import_react13.useState)(null);
|
|
1754
|
+
const [error, setError] = (0, import_react13.useState)(null);
|
|
1579
1755
|
const themeValues = useRendererTheme();
|
|
1580
|
-
const uniqueId = (0,
|
|
1581
|
-
(0,
|
|
1756
|
+
const uniqueId = (0, import_react13.useId)().replace(/:/g, "-");
|
|
1757
|
+
(0, import_react13.useEffect)(() => {
|
|
1582
1758
|
let cancelled = false;
|
|
1583
1759
|
async function renderDiagram() {
|
|
1584
1760
|
try {
|
|
@@ -1607,341 +1783,75 @@ function MermaidView({ definition, className }) {
|
|
|
1607
1783
|
};
|
|
1608
1784
|
}, [definition, themeValues, uniqueId]);
|
|
1609
1785
|
if (error) {
|
|
1610
|
-
return import_react11.default.createElement(
|
|
1611
|
-
import_Box8.default,
|
|
1612
|
-
{ className },
|
|
1613
|
-
import_react11.default.createElement(import_Alert4.default, { severity: "error", sx: { mb: 1 } }, `Mermaid parse error: ${error}`),
|
|
1614
|
-
import_react11.default.createElement(
|
|
1615
|
-
"pre",
|
|
1616
|
-
{ style: { fontFamily: "monospace", whiteSpace: "pre-wrap", fontSize: "0.85em" } },
|
|
1617
|
-
definition
|
|
1618
|
-
)
|
|
1619
|
-
);
|
|
1620
|
-
}
|
|
1621
|
-
if (!svg) {
|
|
1622
|
-
return import_react11.default.createElement(
|
|
1623
|
-
MermaidRoot,
|
|
1624
|
-
{ className },
|
|
1625
|
-
import_react11.default.createElement(import_Box8.default, { sx: { color: "text.secondary" } }, "Rendering diagram...")
|
|
1626
|
-
);
|
|
1627
|
-
}
|
|
1628
|
-
return import_react11.default.createElement(MermaidRoot, {
|
|
1629
|
-
ref: containerRef,
|
|
1630
|
-
className,
|
|
1631
|
-
dangerouslySetInnerHTML: { __html: svg }
|
|
1632
|
-
});
|
|
1633
|
-
}
|
|
1634
|
-
lazyMermaid.load().catch(() => {
|
|
1635
|
-
});
|
|
1636
|
-
var MermaidRenderer = class {
|
|
1637
|
-
type = "mermaid";
|
|
1638
|
-
priority = 50;
|
|
1639
|
-
canHandle(content) {
|
|
1640
|
-
return isMermaid(content);
|
|
1641
|
-
}
|
|
1642
|
-
render(content, options) {
|
|
1643
|
-
return import_react11.default.createElement(MermaidView, {
|
|
1644
|
-
definition: content.trim(),
|
|
1645
|
-
className: options?.className ?? "fmcp-mermaid-content"
|
|
1646
|
-
});
|
|
1647
|
-
}
|
|
1648
|
-
};
|
|
1649
|
-
var mermaidRenderer = new MermaidRenderer();
|
|
1650
|
-
|
|
1651
|
-
// libs/ui/src/renderer/flow/index.ts
|
|
1652
|
-
var import_react12 = __toESM(require("react"));
|
|
1653
|
-
var import_Box9 = __toESM(require("@mui/material/Box"));
|
|
1654
|
-
var import_Alert5 = __toESM(require("@mui/material/Alert"));
|
|
1655
|
-
var import_Typography5 = __toESM(require("@mui/material/Typography"));
|
|
1656
|
-
var import_styles9 = require("@mui/material/styles");
|
|
1657
|
-
var XYFLOW_CSS_URL = "https://esm.sh/@xyflow/react@12/dist/style.css";
|
|
1658
|
-
var XYFLOW_CSS_ID = "fmcp-xyflow-css";
|
|
1659
|
-
function isFlow(content) {
|
|
1660
|
-
const trimmed = content.trim();
|
|
1661
|
-
if (trimmed.charCodeAt(0) !== 123) return false;
|
|
1662
|
-
return trimmed.includes('"nodes"') && trimmed.includes('"edges"');
|
|
1663
|
-
}
|
|
1664
|
-
var lazyXYFlow = createLazyImport("@xyflow/react", async () => {
|
|
1665
|
-
const mod = await runtimeImportWithFallback(
|
|
1666
|
-
"@xyflow/react",
|
|
1667
|
-
esmShUrl("@xyflow/react@12", { external: ["react", "react-dom"] })
|
|
1668
|
-
);
|
|
1669
|
-
return mod;
|
|
1670
|
-
});
|
|
1671
|
-
var FlowRoot = (0, import_styles9.styled)(import_Box9.default, {
|
|
1672
|
-
name: "FrontMcpFlow",
|
|
1673
|
-
slot: "Root"
|
|
1674
|
-
})(({ theme }) => ({
|
|
1675
|
-
width: "100%",
|
|
1676
|
-
borderRadius: theme.shape.borderRadius,
|
|
1677
|
-
overflow: "hidden",
|
|
1678
|
-
border: `1px solid ${theme.palette.divider}`
|
|
1679
|
-
}));
|
|
1680
|
-
function FlowView({ config, className }) {
|
|
1681
|
-
(0, import_react12.useEffect)(() => {
|
|
1682
|
-
injectStylesheet(XYFLOW_CSS_URL, XYFLOW_CSS_ID);
|
|
1683
|
-
}, []);
|
|
1684
|
-
const themeValues = useRendererTheme();
|
|
1685
|
-
const xyflow = useLazyModule(lazyXYFlow);
|
|
1686
|
-
const height = config.height ?? 500;
|
|
1687
|
-
const styledNodes = (0, import_react12.useMemo)(() => {
|
|
1688
|
-
return config.nodes.map((node) => ({
|
|
1689
|
-
...node,
|
|
1690
|
-
style: {
|
|
1691
|
-
background: themeValues.paper,
|
|
1692
|
-
color: themeValues.textPrimary,
|
|
1693
|
-
border: `1px solid ${themeValues.divider}`,
|
|
1694
|
-
borderRadius: themeValues.borderRadius,
|
|
1695
|
-
padding: 8,
|
|
1696
|
-
fontSize: themeValues.fontSize,
|
|
1697
|
-
fontFamily: themeValues.fontFamily,
|
|
1698
|
-
...node.style
|
|
1699
|
-
}
|
|
1700
|
-
}));
|
|
1701
|
-
}, [config.nodes, themeValues]);
|
|
1702
|
-
const styledEdges = (0, import_react12.useMemo)(() => {
|
|
1703
|
-
return config.edges.map((edge, i) => ({
|
|
1704
|
-
...edge,
|
|
1705
|
-
style: {
|
|
1706
|
-
stroke: themeValues.seriesColors[i % themeValues.seriesColors.length],
|
|
1707
|
-
strokeWidth: 2,
|
|
1708
|
-
...edge.style
|
|
1709
|
-
}
|
|
1710
|
-
}));
|
|
1711
|
-
}, [config.edges, themeValues]);
|
|
1712
|
-
if (!xyflow) {
|
|
1713
|
-
return import_react12.default.createElement(import_Alert5.default, { severity: "info" }, "Loading flow diagram library...");
|
|
1714
|
-
}
|
|
1715
|
-
const { ReactFlow, Controls, MiniMap, Background } = xyflow;
|
|
1716
|
-
return import_react12.default.createElement(
|
|
1717
|
-
FlowRoot,
|
|
1718
|
-
{ className },
|
|
1719
|
-
config.title && import_react12.default.createElement(
|
|
1720
|
-
import_Typography5.default,
|
|
1721
|
-
{ variant: "subtitle1", sx: { fontWeight: 600, p: 1.5, borderBottom: 1, borderColor: "divider" } },
|
|
1722
|
-
config.title
|
|
1723
|
-
),
|
|
1724
|
-
import_react12.default.createElement(
|
|
1725
|
-
import_Box9.default,
|
|
1726
|
-
{ sx: { height } },
|
|
1727
|
-
import_react12.default.createElement(
|
|
1728
|
-
ReactFlow,
|
|
1729
|
-
{
|
|
1730
|
-
nodes: styledNodes,
|
|
1731
|
-
edges: styledEdges,
|
|
1732
|
-
fitView: config.fitView !== false,
|
|
1733
|
-
proOptions: { hideAttribution: true }
|
|
1734
|
-
},
|
|
1735
|
-
import_react12.default.createElement(Controls, {
|
|
1736
|
-
style: {
|
|
1737
|
-
backgroundColor: themeValues.paper,
|
|
1738
|
-
borderRadius: themeValues.borderRadius,
|
|
1739
|
-
border: `1px solid ${themeValues.divider}`
|
|
1740
|
-
}
|
|
1741
|
-
}),
|
|
1742
|
-
import_react12.default.createElement(MiniMap, {
|
|
1743
|
-
style: {
|
|
1744
|
-
backgroundColor: themeValues.background,
|
|
1745
|
-
borderRadius: themeValues.borderRadius
|
|
1746
|
-
},
|
|
1747
|
-
nodeColor: themeValues.primary
|
|
1748
|
-
}),
|
|
1749
|
-
Background && import_react12.default.createElement(Background, {
|
|
1750
|
-
color: themeValues.divider,
|
|
1751
|
-
gap: 16
|
|
1752
|
-
})
|
|
1753
|
-
)
|
|
1754
|
-
)
|
|
1755
|
-
);
|
|
1756
|
-
}
|
|
1757
|
-
lazyXYFlow.load().catch(() => {
|
|
1758
|
-
});
|
|
1759
|
-
var FlowRenderer = class {
|
|
1760
|
-
type = "flow";
|
|
1761
|
-
priority = 70;
|
|
1762
|
-
canHandle(content) {
|
|
1763
|
-
return isFlow(content);
|
|
1764
|
-
}
|
|
1765
|
-
render(content, options) {
|
|
1766
|
-
try {
|
|
1767
|
-
const config = JSON.parse(content);
|
|
1768
|
-
return import_react12.default.createElement(FlowView, {
|
|
1769
|
-
config,
|
|
1770
|
-
className: options?.className ?? "fmcp-flow-content"
|
|
1771
|
-
});
|
|
1772
|
-
} catch {
|
|
1773
|
-
return import_react12.default.createElement(import_Alert5.default, { severity: "error" }, "Invalid flow JSON");
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
};
|
|
1777
|
-
var flowRenderer = new FlowRenderer();
|
|
1778
|
-
|
|
1779
|
-
// libs/ui/src/renderer/math/index.ts
|
|
1780
|
-
var import_react13 = __toESM(require("react"));
|
|
1781
|
-
var import_Box10 = __toESM(require("@mui/material/Box"));
|
|
1782
|
-
var import_Alert6 = __toESM(require("@mui/material/Alert"));
|
|
1783
|
-
var import_styles10 = require("@mui/material/styles");
|
|
1784
|
-
var KATEX_CSS_URL = "https://esm.sh/katex@0.16.11/dist/katex.min.css";
|
|
1785
|
-
var KATEX_CSS_ID = "fmcp-katex-css";
|
|
1786
|
-
var MATH_DISPLAY = /\$\$(?:[^$]|\$(?!\$))+\$\$/s;
|
|
1787
|
-
var MATH_INLINE = /\$[^$\n]+?\$/;
|
|
1788
|
-
var MATH_BRACKET_DISPLAY = /\\\[(?:[^\\]|\\.)*\\\]/s;
|
|
1789
|
-
var MATH_PAREN_INLINE = /\\\((?:[^\\]|\\.)*\\\)/s;
|
|
1790
|
-
var MATH_BEGIN = /\\begin\{(?:equation|align|gather|matrix|pmatrix|bmatrix|cases)\}/;
|
|
1791
|
-
function isMath(content) {
|
|
1792
|
-
const trimmed = content.trim();
|
|
1793
|
-
return MATH_DISPLAY.test(trimmed) || MATH_INLINE.test(trimmed) || MATH_BRACKET_DISPLAY.test(trimmed) || MATH_PAREN_INLINE.test(trimmed) || MATH_BEGIN.test(trimmed);
|
|
1794
|
-
}
|
|
1795
|
-
var lazyKatex = createLazyImport("katex", async () => {
|
|
1796
|
-
const mod = await runtimeImportWithFallback("katex", esmShUrl("katex@0.16"));
|
|
1797
|
-
return mod;
|
|
1798
|
-
});
|
|
1799
|
-
var MathRoot = (0, import_styles10.styled)(import_Box10.default, {
|
|
1800
|
-
name: "FrontMcpMath",
|
|
1801
|
-
slot: "Root"
|
|
1802
|
-
})(({ theme }) => ({
|
|
1803
|
-
color: theme.palette.text.primary,
|
|
1804
|
-
"& .katex-display": {
|
|
1805
|
-
margin: theme.spacing(2, 0),
|
|
1806
|
-
textAlign: "center"
|
|
1807
|
-
}
|
|
1808
|
-
}));
|
|
1809
|
-
var MathDisplay = (0, import_styles10.styled)(import_Box10.default, {
|
|
1810
|
-
name: "FrontMcpMath",
|
|
1811
|
-
slot: "Display"
|
|
1812
|
-
})(({ theme }) => ({
|
|
1813
|
-
display: "block",
|
|
1814
|
-
textAlign: "center",
|
|
1815
|
-
margin: theme.spacing(2, 0),
|
|
1816
|
-
fontSize: "1.2em",
|
|
1817
|
-
overflow: "auto"
|
|
1818
|
-
}));
|
|
1819
|
-
var MathInline = (0, import_styles10.styled)("span", {
|
|
1820
|
-
name: "FrontMcpMath",
|
|
1821
|
-
slot: "Inline"
|
|
1822
|
-
})({
|
|
1823
|
-
display: "inline"
|
|
1824
|
-
});
|
|
1825
|
-
function parseMathContent(source) {
|
|
1826
|
-
const segments = [];
|
|
1827
|
-
const mathRegex = /(\$\$(?:[^$]|\$(?!\$))+\$\$|\$[^$\n]+?\$|\\\[(?:[^\\]|\\.)*\\\]|\\\((?:[^\\]|\\.)*\\\)|\\begin\{(?:[^\\]|\\.)*\\end\{[^}]+\})/gs;
|
|
1828
|
-
let lastIndex = 0;
|
|
1829
|
-
let match;
|
|
1830
|
-
while ((match = mathRegex.exec(source)) !== null) {
|
|
1831
|
-
if (match.index > lastIndex) {
|
|
1832
|
-
segments.push({ type: "text", content: source.slice(lastIndex, match.index) });
|
|
1833
|
-
}
|
|
1834
|
-
const raw = match[0];
|
|
1835
|
-
if (raw.startsWith("$$")) {
|
|
1836
|
-
segments.push({ type: "display", content: raw.slice(2, -2).trim() });
|
|
1837
|
-
} else if (raw.startsWith("\\[")) {
|
|
1838
|
-
segments.push({ type: "display", content: raw.slice(2, -2).trim() });
|
|
1839
|
-
} else if (raw.startsWith("\\begin")) {
|
|
1840
|
-
segments.push({ type: "display", content: raw });
|
|
1841
|
-
} else if (raw.startsWith("\\(")) {
|
|
1842
|
-
segments.push({ type: "inline", content: raw.slice(2, -2).trim() });
|
|
1843
|
-
} else if (raw.startsWith("$")) {
|
|
1844
|
-
segments.push({ type: "inline", content: raw.slice(1, -1).trim() });
|
|
1845
|
-
}
|
|
1846
|
-
lastIndex = match.index + raw.length;
|
|
1847
|
-
}
|
|
1848
|
-
if (lastIndex < source.length) {
|
|
1849
|
-
segments.push({ type: "text", content: source.slice(lastIndex) });
|
|
1850
|
-
}
|
|
1851
|
-
return segments;
|
|
1852
|
-
}
|
|
1853
|
-
function MathView({ content, className }) {
|
|
1854
|
-
(0, import_react13.useEffect)(() => {
|
|
1855
|
-
injectStylesheet(KATEX_CSS_URL, KATEX_CSS_ID);
|
|
1856
|
-
}, []);
|
|
1857
|
-
const katexMod = useLazyModule(lazyKatex);
|
|
1858
|
-
const segments = (0, import_react13.useMemo)(() => parseMathContent(content), [content]);
|
|
1859
|
-
const renderToString = katexMod?.default?.renderToString ?? katexMod?.renderToString;
|
|
1860
|
-
if (!renderToString) {
|
|
1861
1786
|
return import_react13.default.createElement(
|
|
1862
|
-
|
|
1863
|
-
{ className },
|
|
1864
|
-
import_react13.default.createElement(
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
}
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
key: i,
|
|
1884
|
-
dangerouslySetInnerHTML: { __html: html }
|
|
1885
|
-
});
|
|
1886
|
-
} catch (err) {
|
|
1887
|
-
return import_react13.default.createElement(
|
|
1888
|
-
import_Alert6.default,
|
|
1889
|
-
{ key: i, severity: "error", sx: { my: 1 } },
|
|
1890
|
-
`LaTeX error: ${err instanceof Error ? err.message : String(err)}
|
|
1891
|
-
Source: ${seg.content}`
|
|
1892
|
-
);
|
|
1893
|
-
}
|
|
1787
|
+
import_Box10.default,
|
|
1788
|
+
{ className },
|
|
1789
|
+
import_react13.default.createElement(import_Alert6.default, { severity: "error", sx: { mb: 1 } }, `Mermaid parse error: ${error}`),
|
|
1790
|
+
import_react13.default.createElement(
|
|
1791
|
+
"pre",
|
|
1792
|
+
{ style: { fontFamily: "monospace", whiteSpace: "pre-wrap", fontSize: "0.85em" } },
|
|
1793
|
+
definition
|
|
1794
|
+
)
|
|
1795
|
+
);
|
|
1796
|
+
}
|
|
1797
|
+
if (!svg) {
|
|
1798
|
+
return import_react13.default.createElement(
|
|
1799
|
+
MermaidRoot,
|
|
1800
|
+
{ className },
|
|
1801
|
+
import_react13.default.createElement(import_Box10.default, { sx: { color: "text.secondary" } }, "Rendering diagram...")
|
|
1802
|
+
);
|
|
1803
|
+
}
|
|
1804
|
+
return import_react13.default.createElement(MermaidRoot, {
|
|
1805
|
+
ref: containerRef,
|
|
1806
|
+
className,
|
|
1807
|
+
dangerouslySetInnerHTML: { __html: svg }
|
|
1894
1808
|
});
|
|
1895
|
-
return import_react13.default.createElement(MathRoot, { className }, ...elements);
|
|
1896
1809
|
}
|
|
1897
|
-
|
|
1810
|
+
lazyMermaid.load().catch(() => {
|
|
1898
1811
|
});
|
|
1899
|
-
var
|
|
1900
|
-
type = "
|
|
1901
|
-
priority =
|
|
1812
|
+
var MermaidRenderer = class {
|
|
1813
|
+
type = "mermaid";
|
|
1814
|
+
priority = 50;
|
|
1902
1815
|
canHandle(content) {
|
|
1903
|
-
return
|
|
1816
|
+
return isMermaid(content);
|
|
1904
1817
|
}
|
|
1905
1818
|
render(content, options) {
|
|
1906
|
-
return import_react13.default.createElement(
|
|
1907
|
-
content,
|
|
1908
|
-
className: options?.className ?? "fmcp-
|
|
1819
|
+
return import_react13.default.createElement(MermaidView, {
|
|
1820
|
+
definition: content.trim(),
|
|
1821
|
+
className: options?.className ?? "fmcp-mermaid-content"
|
|
1909
1822
|
});
|
|
1910
1823
|
}
|
|
1911
1824
|
};
|
|
1912
|
-
var
|
|
1825
|
+
var mermaidRenderer = new MermaidRenderer();
|
|
1913
1826
|
|
|
1914
|
-
// libs/ui/src/renderer/
|
|
1915
|
-
var import_react14 = __toESM(require("react"));
|
|
1827
|
+
// libs/ui/src/renderer/pdf/index.ts
|
|
1916
1828
|
var import_Box11 = __toESM(require("@mui/material/Box"));
|
|
1917
|
-
var
|
|
1918
|
-
var
|
|
1829
|
+
var import_IconButton = __toESM(require("@mui/material/IconButton"));
|
|
1830
|
+
var import_styles12 = require("@mui/material/styles");
|
|
1831
|
+
var import_TextField2 = __toESM(require("@mui/material/TextField"));
|
|
1919
1832
|
var import_Typography6 = __toESM(require("@mui/material/Typography"));
|
|
1920
|
-
var
|
|
1921
|
-
var
|
|
1922
|
-
var LEAFLET_CSS_ID = "fmcp-leaflet-css";
|
|
1923
|
-
var DEFAULT_TILE_URL = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
|
|
1924
|
-
var DEFAULT_ATTRIBUTION = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
|
|
1925
|
-
var GEOJSON_TYPE_RE2 = /"type"\s*:\s*"(?:FeatureCollection|Feature|Point|LineString|Polygon|MultiPoint|MultiLineString|MultiPolygon|GeometryCollection)"/;
|
|
1926
|
-
function isMap(content) {
|
|
1927
|
-
const trimmed = content.trim();
|
|
1928
|
-
if (trimmed.charCodeAt(0) === 123 && GEOJSON_TYPE_RE2.test(trimmed)) return true;
|
|
1929
|
-
try {
|
|
1930
|
-
const parsed = JSON.parse(trimmed);
|
|
1931
|
-
return !!(parsed.center && Array.isArray(parsed.center) || parsed.markers && Array.isArray(parsed.markers) || parsed.geojson && typeof parsed.geojson === "object");
|
|
1932
|
-
} catch {
|
|
1933
|
-
return false;
|
|
1934
|
-
}
|
|
1935
|
-
}
|
|
1936
|
-
var lazyReactLeaflet = createLazyImport("react-leaflet", async () => {
|
|
1833
|
+
var import_react14 = __toESM(require("react"));
|
|
1834
|
+
var lazyReactPdf = createLazyImport("react-pdf", async () => {
|
|
1937
1835
|
const mod = await runtimeImportWithFallback(
|
|
1938
|
-
"react-
|
|
1939
|
-
esmShUrl("react-
|
|
1836
|
+
"react-pdf",
|
|
1837
|
+
esmShUrl("react-pdf@9", { external: ["react", "react-dom"] })
|
|
1940
1838
|
);
|
|
1839
|
+
const pdfjs = mod["pdfjs"];
|
|
1840
|
+
if (pdfjs?.GlobalWorkerOptions) {
|
|
1841
|
+
pdfjs.GlobalWorkerOptions.workerSrc = `${ESM_SH_BASE}pdfjs-dist@${pdfjs.version ?? "4"}/build/pdf.worker.min.mjs?raw`;
|
|
1842
|
+
}
|
|
1941
1843
|
return mod;
|
|
1942
1844
|
});
|
|
1943
|
-
|
|
1944
|
-
|
|
1845
|
+
function toDataUri(content) {
|
|
1846
|
+
if (content.startsWith("data:")) return content;
|
|
1847
|
+
if (content.startsWith("%PDF-")) {
|
|
1848
|
+
const base64 = typeof btoa === "function" ? btoa(content) : Buffer.from(content).toString("base64");
|
|
1849
|
+
return `data:application/pdf;base64,${base64}`;
|
|
1850
|
+
}
|
|
1851
|
+
return `data:application/pdf;base64,${content}`;
|
|
1852
|
+
}
|
|
1853
|
+
var PdfRoot = (0, import_styles12.styled)(import_Box11.default, {
|
|
1854
|
+
name: "FrontMcpPdf",
|
|
1945
1855
|
slot: "Root"
|
|
1946
1856
|
})(({ theme }) => ({
|
|
1947
1857
|
width: "100%",
|
|
@@ -1949,239 +1859,335 @@ var MapRoot = (0, import_styles11.styled)(import_Box11.default, {
|
|
|
1949
1859
|
overflow: "hidden",
|
|
1950
1860
|
border: `1px solid ${theme.palette.divider}`
|
|
1951
1861
|
}));
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
}
|
|
1973
|
-
|
|
1974
|
-
(0, import_react14.
|
|
1975
|
-
|
|
1862
|
+
var Toolbar = (0, import_styles12.styled)(import_Box11.default, {
|
|
1863
|
+
name: "FrontMcpPdf",
|
|
1864
|
+
slot: "Toolbar"
|
|
1865
|
+
})(({ theme }) => ({
|
|
1866
|
+
display: "flex",
|
|
1867
|
+
alignItems: "center",
|
|
1868
|
+
gap: theme.spacing(1),
|
|
1869
|
+
padding: theme.spacing(1, 2),
|
|
1870
|
+
borderBottom: `1px solid ${theme.palette.divider}`,
|
|
1871
|
+
backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[900] : theme.palette.grey[50]
|
|
1872
|
+
}));
|
|
1873
|
+
var PageContainer = (0, import_styles12.styled)(import_Box11.default, {
|
|
1874
|
+
name: "FrontMcpPdf",
|
|
1875
|
+
slot: "PageContainer"
|
|
1876
|
+
})({
|
|
1877
|
+
display: "flex",
|
|
1878
|
+
justifyContent: "center",
|
|
1879
|
+
overflow: "auto",
|
|
1880
|
+
maxHeight: 700
|
|
1881
|
+
});
|
|
1882
|
+
function PdfView({ content, className, title }) {
|
|
1883
|
+
const [numPages, setNumPages] = (0, import_react14.useState)(0);
|
|
1884
|
+
const [pageNumber, setPageNumber] = (0, import_react14.useState)(1);
|
|
1885
|
+
const [scale, setScale] = (0, import_react14.useState)(1);
|
|
1886
|
+
const reactPdf = useLazyModule(lazyReactPdf);
|
|
1887
|
+
const dataUri = (0, import_react14.useMemo)(() => toDataUri(content), [content]);
|
|
1888
|
+
const onDocumentLoadSuccess = (0, import_react14.useCallback)(({ numPages: n }) => {
|
|
1889
|
+
setNumPages(n);
|
|
1976
1890
|
}, []);
|
|
1977
|
-
const
|
|
1978
|
-
const
|
|
1979
|
-
const
|
|
1980
|
-
const
|
|
1981
|
-
if (!
|
|
1982
|
-
return import_react14.default.createElement(
|
|
1891
|
+
const goToPrev = (0, import_react14.useCallback)(() => setPageNumber((p) => Math.max(1, p - 1)), []);
|
|
1892
|
+
const goToNext = (0, import_react14.useCallback)(() => setPageNumber((p) => Math.min(numPages, p + 1)), []);
|
|
1893
|
+
const zoomIn = (0, import_react14.useCallback)(() => setScale((s) => Math.min(3, s + 0.25)), []);
|
|
1894
|
+
const zoomOut = (0, import_react14.useCallback)(() => setScale((s) => Math.max(0.25, s - 0.25)), []);
|
|
1895
|
+
if (!reactPdf) {
|
|
1896
|
+
return import_react14.default.createElement("iframe", {
|
|
1897
|
+
className: className ?? "fmcp-pdf-content",
|
|
1898
|
+
src: dataUri,
|
|
1899
|
+
style: { width: "100%", height: "600px", border: "none" },
|
|
1900
|
+
title: title ?? "PDF Document"
|
|
1901
|
+
});
|
|
1983
1902
|
}
|
|
1984
|
-
const {
|
|
1985
|
-
const tileUrl = config.tileLayer?.url ?? DEFAULT_TILE_URL;
|
|
1986
|
-
const attribution = config.tileLayer?.attribution ?? DEFAULT_ATTRIBUTION;
|
|
1903
|
+
const { Document, Page } = reactPdf;
|
|
1987
1904
|
return import_react14.default.createElement(
|
|
1988
|
-
|
|
1905
|
+
PdfRoot,
|
|
1989
1906
|
{ className },
|
|
1990
|
-
config.title && import_react14.default.createElement(
|
|
1991
|
-
import_Typography6.default,
|
|
1992
|
-
{ variant: "subtitle1", sx: { fontWeight: 600, p: 1.5, borderBottom: 1, borderColor: "divider" } },
|
|
1993
|
-
config.title
|
|
1994
|
-
),
|
|
1995
1907
|
import_react14.default.createElement(
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
import_react14.default.createElement(
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
{ key: i, position: marker.position },
|
|
2008
|
-
marker.popup && import_react14.default.createElement(Popup, null, import_react14.default.createElement(import_Paper.default, { elevation: 0, sx: { p: 1 } }, marker.popup))
|
|
2009
|
-
)
|
|
1908
|
+
Toolbar,
|
|
1909
|
+
null,
|
|
1910
|
+
import_react14.default.createElement(
|
|
1911
|
+
import_IconButton.default,
|
|
1912
|
+
{ size: "small", onClick: goToPrev, disabled: pageNumber <= 1, "aria-label": "Previous page" },
|
|
1913
|
+
"\u25C0"
|
|
1914
|
+
),
|
|
1915
|
+
import_react14.default.createElement(
|
|
1916
|
+
import_Typography6.default,
|
|
1917
|
+
{ variant: "body2", sx: { minWidth: 80, textAlign: "center" } },
|
|
1918
|
+
`${pageNumber} / ${numPages || "..."}`
|
|
2010
1919
|
),
|
|
2011
|
-
|
|
1920
|
+
import_react14.default.createElement(
|
|
1921
|
+
import_IconButton.default,
|
|
1922
|
+
{ size: "small", onClick: goToNext, disabled: pageNumber >= numPages, "aria-label": "Next page" },
|
|
1923
|
+
"\u25B6"
|
|
1924
|
+
),
|
|
1925
|
+
import_react14.default.createElement(import_Box11.default, { sx: { flex: 1 } }),
|
|
1926
|
+
import_react14.default.createElement(import_IconButton.default, { size: "small", onClick: zoomOut, "aria-label": "Zoom out" }, "\u2212"),
|
|
1927
|
+
import_react14.default.createElement(
|
|
1928
|
+
import_Typography6.default,
|
|
1929
|
+
{ variant: "body2", sx: { minWidth: 50, textAlign: "center" } },
|
|
1930
|
+
`${Math.round(scale * 100)}%`
|
|
1931
|
+
),
|
|
1932
|
+
import_react14.default.createElement(import_IconButton.default, { size: "small", onClick: zoomIn, "aria-label": "Zoom in" }, "+"),
|
|
1933
|
+
import_react14.default.createElement(import_Box11.default, { sx: { flex: 1 } }),
|
|
1934
|
+
import_react14.default.createElement(import_TextField2.default, {
|
|
1935
|
+
size: "small",
|
|
1936
|
+
type: "number",
|
|
1937
|
+
value: pageNumber,
|
|
1938
|
+
onChange: (e) => {
|
|
1939
|
+
const n = parseInt(e.target.value, 10);
|
|
1940
|
+
if (n >= 1 && n <= numPages) setPageNumber(n);
|
|
1941
|
+
},
|
|
1942
|
+
sx: { width: 70 },
|
|
1943
|
+
slotProps: { htmlInput: { min: 1, max: numPages, "aria-label": "Go to page" } }
|
|
1944
|
+
})
|
|
1945
|
+
),
|
|
1946
|
+
import_react14.default.createElement(
|
|
1947
|
+
PageContainer,
|
|
1948
|
+
null,
|
|
1949
|
+
import_react14.default.createElement(
|
|
1950
|
+
Document,
|
|
1951
|
+
{ file: dataUri, onLoadSuccess: onDocumentLoadSuccess },
|
|
1952
|
+
import_react14.default.createElement(Page, { pageNumber, scale, renderTextLayer: false, renderAnnotationLayer: false })
|
|
1953
|
+
)
|
|
2012
1954
|
)
|
|
2013
1955
|
);
|
|
2014
1956
|
}
|
|
2015
|
-
|
|
2016
|
-
});
|
|
2017
|
-
var
|
|
2018
|
-
type = "
|
|
2019
|
-
priority =
|
|
2020
|
-
canHandle(content) {
|
|
2021
|
-
return
|
|
1957
|
+
lazyReactPdf.load().catch(() => {
|
|
1958
|
+
});
|
|
1959
|
+
var PdfRenderer = class {
|
|
1960
|
+
type = "pdf";
|
|
1961
|
+
priority = 90;
|
|
1962
|
+
canHandle(content) {
|
|
1963
|
+
return content.startsWith("%PDF-") || content.trim().startsWith("JVBER") || /^data:application\/pdf[;,]/.test(content.trim());
|
|
1964
|
+
}
|
|
1965
|
+
render(content, options) {
|
|
1966
|
+
return import_react14.default.createElement(PdfView, {
|
|
1967
|
+
content,
|
|
1968
|
+
className: options?.className ?? "fmcp-pdf-content",
|
|
1969
|
+
title: options?.toolName ?? "PDF Document"
|
|
1970
|
+
});
|
|
1971
|
+
}
|
|
1972
|
+
};
|
|
1973
|
+
var pdfRenderer = new PdfRenderer();
|
|
1974
|
+
|
|
1975
|
+
// libs/ui/src/renderer/react/index.ts
|
|
1976
|
+
var import_Alert7 = __toESM(require("@mui/material/Alert"));
|
|
1977
|
+
var import_Box12 = __toESM(require("@mui/material/Box"));
|
|
1978
|
+
var import_react15 = __toESM(require("react"));
|
|
1979
|
+
|
|
1980
|
+
// libs/ui/src/runtime/babel-runtime.ts
|
|
1981
|
+
var BABEL_STANDALONE_CDN = "https://esm.sh/@babel/standalone@7";
|
|
1982
|
+
var BABEL_STANDALONE_FALLBACK_CDN = "https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.26.10/babel.min.js";
|
|
1983
|
+
var babelState = { status: "idle" };
|
|
1984
|
+
async function loadBabel() {
|
|
1985
|
+
if (babelState.status === "loaded") {
|
|
1986
|
+
return babelState.babel;
|
|
1987
|
+
}
|
|
1988
|
+
if (babelState.status === "loading") {
|
|
1989
|
+
return babelState.promise;
|
|
1990
|
+
}
|
|
1991
|
+
if (babelState.status === "error") {
|
|
1992
|
+
throw babelState.error;
|
|
1993
|
+
}
|
|
1994
|
+
const promise = doLoadBabel();
|
|
1995
|
+
babelState = { status: "loading", promise };
|
|
1996
|
+
try {
|
|
1997
|
+
const babel = await promise;
|
|
1998
|
+
babelState = { status: "loaded", babel };
|
|
1999
|
+
return babel;
|
|
2000
|
+
} catch (error) {
|
|
2001
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2002
|
+
babelState = { status: "error", error: err };
|
|
2003
|
+
throw err;
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
async function doLoadBabel() {
|
|
2007
|
+
const globalBabel = globalThis["Babel"];
|
|
2008
|
+
if (globalBabel && typeof globalBabel.transform === "function") {
|
|
2009
|
+
return globalBabel;
|
|
2010
|
+
}
|
|
2011
|
+
try {
|
|
2012
|
+
const module2 = await import(
|
|
2013
|
+
/* @vite-ignore */
|
|
2014
|
+
/* webpackIgnore: true */
|
|
2015
|
+
BABEL_STANDALONE_CDN
|
|
2016
|
+
);
|
|
2017
|
+
if (module2 && typeof module2.transform === "function") {
|
|
2018
|
+
return module2;
|
|
2019
|
+
}
|
|
2020
|
+
if (module2.default && typeof module2.default.transform === "function") {
|
|
2021
|
+
return module2.default;
|
|
2022
|
+
}
|
|
2023
|
+
} catch {
|
|
2024
|
+
}
|
|
2025
|
+
return new Promise((resolve, reject) => {
|
|
2026
|
+
if (typeof document === "undefined") {
|
|
2027
|
+
reject(new Error("Babel Standalone requires a browser environment"));
|
|
2028
|
+
return;
|
|
2029
|
+
}
|
|
2030
|
+
const script = document.createElement("script");
|
|
2031
|
+
script.src = BABEL_STANDALONE_FALLBACK_CDN;
|
|
2032
|
+
script.crossOrigin = "anonymous";
|
|
2033
|
+
script.onload = () => {
|
|
2034
|
+
const babel = globalThis["Babel"];
|
|
2035
|
+
if (babel && typeof babel.transform === "function") {
|
|
2036
|
+
resolve(babel);
|
|
2037
|
+
} else {
|
|
2038
|
+
reject(new Error("Babel Standalone loaded but transform function not found"));
|
|
2039
|
+
}
|
|
2040
|
+
};
|
|
2041
|
+
script.onerror = () => {
|
|
2042
|
+
reject(new Error(`Failed to load Babel Standalone from ${BABEL_STANDALONE_FALLBACK_CDN}`));
|
|
2043
|
+
};
|
|
2044
|
+
document.head.appendChild(script);
|
|
2045
|
+
});
|
|
2046
|
+
}
|
|
2047
|
+
async function transpileJsx(source, filename = "component.jsx") {
|
|
2048
|
+
const babel = await loadBabel();
|
|
2049
|
+
const result = babel.transform(source, {
|
|
2050
|
+
presets: ["react"],
|
|
2051
|
+
filename
|
|
2052
|
+
});
|
|
2053
|
+
return result.code;
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2056
|
+
// libs/ui/src/renderer/react/index.ts
|
|
2057
|
+
function isReactJsx(content) {
|
|
2058
|
+
if (/^#{1,6}\s+\S/m.test(content)) return false;
|
|
2059
|
+
return /(?:function|const|class)\s+\w+/.test(content) && /(?:return|=>)[\s(]*</.test(content);
|
|
2060
|
+
}
|
|
2061
|
+
function parseImports(source) {
|
|
2062
|
+
const results = [];
|
|
2063
|
+
const defaultRe = /^import\s+(\w+)\s+from\s+['"]([^'"]+)['"][\s;]*$/gm;
|
|
2064
|
+
let m;
|
|
2065
|
+
while ((m = defaultRe.exec(source)) !== null) {
|
|
2066
|
+
results.push({ line: m[0], localName: m[1], specifier: m[2], named: false });
|
|
2022
2067
|
}
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
className: options?.className ?? "fmcp-map-content"
|
|
2029
|
-
});
|
|
2030
|
-
} catch {
|
|
2031
|
-
return import_react14.default.createElement(import_Alert7.default, { severity: "error" }, "Invalid map/GeoJSON data");
|
|
2068
|
+
const namedRe = /^import\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"][\s;]*$/gm;
|
|
2069
|
+
while ((m = namedRe.exec(source)) !== null) {
|
|
2070
|
+
const names = m[1].split(",").map((n) => n.trim()).filter(Boolean);
|
|
2071
|
+
for (const name of names) {
|
|
2072
|
+
results.push({ line: m[0], localName: name, specifier: m[2], named: true });
|
|
2032
2073
|
}
|
|
2033
2074
|
}
|
|
2034
|
-
|
|
2035
|
-
var mapsRenderer = new MapsRenderer();
|
|
2036
|
-
|
|
2037
|
-
// libs/ui/src/renderer/media/index.ts
|
|
2038
|
-
var import_react15 = __toESM(require("react"));
|
|
2039
|
-
var import_Box12 = __toESM(require("@mui/material/Box"));
|
|
2040
|
-
var import_Paper2 = __toESM(require("@mui/material/Paper"));
|
|
2041
|
-
var import_styles12 = require("@mui/material/styles");
|
|
2042
|
-
var VIDEO_PATTERNS2 = [
|
|
2043
|
-
/^https?:\/\/[^?#\s]+\.(?:mp4|webm|ogg|mov)(?:\?[^#\s]*)?$/i,
|
|
2044
|
-
/^https?:\/\/(?:www\.)?(?:youtube\.com|youtu\.be|vimeo\.com)\//i,
|
|
2045
|
-
/^data:video\//
|
|
2046
|
-
];
|
|
2047
|
-
var AUDIO_PATTERNS2 = [
|
|
2048
|
-
/^https?:\/\/[^?#\s]+\.(?:mp3|wav|ogg|aac|flac|m4a)(?:\?[^#\s]*)?$/i,
|
|
2049
|
-
/^https?:\/\/(?:www\.)?soundcloud\.com\//i,
|
|
2050
|
-
/^data:audio\//
|
|
2051
|
-
];
|
|
2052
|
-
function isVideo(content) {
|
|
2053
|
-
const trimmed = content.trim();
|
|
2054
|
-
return VIDEO_PATTERNS2.some((p) => p.test(trimmed));
|
|
2075
|
+
return results;
|
|
2055
2076
|
}
|
|
2056
|
-
function
|
|
2057
|
-
|
|
2058
|
-
return AUDIO_PATTERNS2.some((p) => p.test(trimmed));
|
|
2077
|
+
function stripImports(source) {
|
|
2078
|
+
return source.replace(/^import\s+\w+\s+from\s+['"][^'"]+['"][\s;]*$/gm, "").replace(/^import\s+\{[^}]+\}\s+from\s+['"][^'"]+['"][\s;]*$/gm, "");
|
|
2059
2079
|
}
|
|
2060
|
-
function
|
|
2061
|
-
|
|
2080
|
+
function rewriteExportDefault(source) {
|
|
2081
|
+
let result = source.replace(/^export\s+default\s+(function|class)\b/gm, "var __default__ = $1");
|
|
2082
|
+
result = result.replace(/^export\s+default\s+(\([^)]*\)\s*=>)/gm, "var __default__ = $1");
|
|
2083
|
+
result = result.replace(/^export\s+default\s+(\w+)\s*;?\s*$/gm, "var __default__ = $1;");
|
|
2084
|
+
return result;
|
|
2062
2085
|
}
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
})(({ theme }) => ({
|
|
2074
|
-
overflow: "hidden",
|
|
2075
|
-
borderRadius: theme.shape.borderRadius
|
|
2076
|
-
}));
|
|
2077
|
-
var VideoWrapper = (0, import_styles12.styled)(import_Box12.default)({
|
|
2078
|
-
position: "relative",
|
|
2079
|
-
paddingTop: "56.25%",
|
|
2080
|
-
// 16:9 aspect ratio
|
|
2081
|
-
"& > *": {
|
|
2082
|
-
position: "absolute",
|
|
2083
|
-
top: 0,
|
|
2084
|
-
left: 0
|
|
2086
|
+
function isReactSpecifier(specifier) {
|
|
2087
|
+
return specifier === "react" || /^https?:\/\/esm\.sh\/react(?:@[\d.]+)?$/.test(specifier);
|
|
2088
|
+
}
|
|
2089
|
+
async function resolveModules(imports) {
|
|
2090
|
+
const modules = {};
|
|
2091
|
+
const specifierMap = /* @__PURE__ */ new Map();
|
|
2092
|
+
for (const imp of imports) {
|
|
2093
|
+
const existing = specifierMap.get(imp.specifier) ?? [];
|
|
2094
|
+
existing.push(imp);
|
|
2095
|
+
specifierMap.set(imp.specifier, existing);
|
|
2085
2096
|
}
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2097
|
+
for (const [specifier, specImports] of specifierMap) {
|
|
2098
|
+
let mod;
|
|
2099
|
+
if (isReactSpecifier(specifier)) {
|
|
2100
|
+
mod = import_react15.default;
|
|
2101
|
+
} else {
|
|
2102
|
+
mod = await runtimeImport(specifier);
|
|
2103
|
+
}
|
|
2104
|
+
for (const imp of specImports) {
|
|
2105
|
+
if (imp.named) {
|
|
2106
|
+
modules[imp.localName] = mod[imp.localName] ?? mod["default"]?.[imp.localName];
|
|
2107
|
+
} else {
|
|
2108
|
+
modules[imp.localName] = mod["default"] ?? mod;
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2091
2111
|
}
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
)
|
|
2105
|
-
|
|
2112
|
+
return modules;
|
|
2113
|
+
}
|
|
2114
|
+
function ReactJsxView({ source, className }) {
|
|
2115
|
+
const [Component, setComponent] = (0, import_react15.useState)(null);
|
|
2116
|
+
const [error, setError] = (0, import_react15.useState)(null);
|
|
2117
|
+
const [loading, setLoading] = (0, import_react15.useState)(true);
|
|
2118
|
+
(0, import_react15.useEffect)(() => {
|
|
2119
|
+
let cancelled = false;
|
|
2120
|
+
async function transpileAndRender() {
|
|
2121
|
+
try {
|
|
2122
|
+
const imports = parseImports(source);
|
|
2123
|
+
const modules = await resolveModules(imports);
|
|
2124
|
+
let code = stripImports(source);
|
|
2125
|
+
code = rewriteExportDefault(code);
|
|
2126
|
+
code = await transpileJsx(code, "component.jsx");
|
|
2127
|
+
code += "\nreturn __default__;";
|
|
2128
|
+
const argNames = Object.keys(modules);
|
|
2129
|
+
const argValues = argNames.map((n) => modules[n]);
|
|
2130
|
+
const factory = new Function(...argNames, code);
|
|
2131
|
+
const Comp = factory(...argValues);
|
|
2132
|
+
if (!cancelled) {
|
|
2133
|
+
setComponent(() => Comp);
|
|
2134
|
+
setError(null);
|
|
2135
|
+
setLoading(false);
|
|
2136
|
+
}
|
|
2137
|
+
} catch (err) {
|
|
2138
|
+
if (!cancelled) {
|
|
2139
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2140
|
+
setComponent(null);
|
|
2141
|
+
setLoading(false);
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2106
2144
|
}
|
|
2145
|
+
setLoading(true);
|
|
2146
|
+
setError(null);
|
|
2147
|
+
setComponent(null);
|
|
2148
|
+
transpileAndRender();
|
|
2149
|
+
return () => {
|
|
2150
|
+
cancelled = true;
|
|
2151
|
+
};
|
|
2152
|
+
}, [source]);
|
|
2153
|
+
if (loading) {
|
|
2154
|
+
return import_react15.default.createElement(import_Box12.default, { className, sx: { p: 2, color: "text.secondary" } }, "Transpiling JSX...");
|
|
2155
|
+
}
|
|
2156
|
+
if (error) {
|
|
2107
2157
|
return import_react15.default.createElement(
|
|
2108
|
-
|
|
2109
|
-
{
|
|
2158
|
+
import_Box12.default,
|
|
2159
|
+
{ className },
|
|
2160
|
+
import_react15.default.createElement(import_Alert7.default, { severity: "error", sx: { mb: 1 } }, `JSX render error: ${error}`),
|
|
2110
2161
|
import_react15.default.createElement(
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
controls: true,
|
|
2115
|
-
src: url,
|
|
2116
|
-
style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }
|
|
2117
|
-
})
|
|
2162
|
+
"pre",
|
|
2163
|
+
{ style: { fontFamily: "monospace", whiteSpace: "pre-wrap", fontSize: "0.85em" } },
|
|
2164
|
+
source
|
|
2118
2165
|
)
|
|
2119
2166
|
);
|
|
2120
2167
|
}
|
|
2121
|
-
|
|
2122
|
-
if (isAudioContent) {
|
|
2168
|
+
if (!Component) {
|
|
2123
2169
|
return import_react15.default.createElement(
|
|
2124
|
-
|
|
2125
|
-
{
|
|
2126
|
-
import_react15.default.createElement(
|
|
2127
|
-
AudioWrapper,
|
|
2128
|
-
null,
|
|
2129
|
-
import_react15.default.createElement(ReactPlayer, {
|
|
2130
|
-
url,
|
|
2131
|
-
controls: true,
|
|
2132
|
-
width: "100%",
|
|
2133
|
-
height: 50
|
|
2134
|
-
})
|
|
2135
|
-
)
|
|
2170
|
+
import_Box12.default,
|
|
2171
|
+
{ className },
|
|
2172
|
+
import_react15.default.createElement(import_Alert7.default, { severity: "warning" }, "No component exported. Use `export default MyComponent`.")
|
|
2136
2173
|
);
|
|
2137
2174
|
}
|
|
2138
|
-
return import_react15.default.createElement(
|
|
2139
|
-
MediaRoot,
|
|
2140
|
-
{ variant: "outlined", className },
|
|
2141
|
-
import_react15.default.createElement(
|
|
2142
|
-
VideoWrapper,
|
|
2143
|
-
null,
|
|
2144
|
-
import_react15.default.createElement(ReactPlayer, {
|
|
2145
|
-
url,
|
|
2146
|
-
controls: true,
|
|
2147
|
-
width: "100%",
|
|
2148
|
-
height: "100%"
|
|
2149
|
-
})
|
|
2150
|
-
)
|
|
2151
|
-
);
|
|
2175
|
+
return import_react15.default.createElement(import_Box12.default, { className }, import_react15.default.createElement(Component, {}));
|
|
2152
2176
|
}
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
type = "video";
|
|
2157
|
-
priority = 20;
|
|
2158
|
-
canHandle(content) {
|
|
2159
|
-
return isVideo(content);
|
|
2160
|
-
}
|
|
2161
|
-
render(content, options) {
|
|
2162
|
-
return import_react15.default.createElement(MediaView, {
|
|
2163
|
-
url: content.trim(),
|
|
2164
|
-
isAudioContent: false,
|
|
2165
|
-
className: options?.className ?? "fmcp-media-content"
|
|
2166
|
-
});
|
|
2167
|
-
}
|
|
2168
|
-
};
|
|
2169
|
-
var AudioRenderer = class {
|
|
2170
|
-
type = "audio";
|
|
2171
|
-
priority = 20;
|
|
2177
|
+
var ReactJsxRenderer = class {
|
|
2178
|
+
type = "jsx";
|
|
2179
|
+
priority = 10;
|
|
2172
2180
|
canHandle(content) {
|
|
2173
|
-
return
|
|
2181
|
+
return isReactJsx(content);
|
|
2174
2182
|
}
|
|
2175
2183
|
render(content, options) {
|
|
2176
|
-
return import_react15.default.createElement(
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
className: options?.className ?? "fmcp-media-content"
|
|
2184
|
+
return import_react15.default.createElement(ReactJsxView, {
|
|
2185
|
+
source: content,
|
|
2186
|
+
className: options?.className ?? "fmcp-jsx-content"
|
|
2180
2187
|
});
|
|
2181
2188
|
}
|
|
2182
2189
|
};
|
|
2183
|
-
var
|
|
2184
|
-
var audioRenderer = new AudioRenderer();
|
|
2190
|
+
var reactJsxRenderer = new ReactJsxRenderer();
|
|
2185
2191
|
|
|
2186
2192
|
// libs/ui/src/renderer/index.ts
|
|
2187
2193
|
function registerAllRenderers() {
|