@frontmcp/ui 0.12.2 → 1.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/README.md +279 -72
  2. package/bridge/adapters/claude.adapter.d.ts.map +1 -1
  3. package/bridge/adapters/gemini.adapter.d.ts.map +1 -1
  4. package/bridge/index.js +2 -36
  5. package/components/Alert/Alert.d.ts +11 -0
  6. package/components/Alert/Alert.d.ts.map +1 -0
  7. package/components/Alert/index.d.ts +4 -0
  8. package/components/Alert/index.d.ts.map +1 -0
  9. package/components/Alert/index.js +61 -0
  10. package/components/Avatar/Avatar.d.ts +10 -0
  11. package/components/Avatar/Avatar.d.ts.map +1 -0
  12. package/components/Avatar/index.d.ts +4 -0
  13. package/components/Avatar/index.d.ts.map +1 -0
  14. package/components/Avatar/index.js +43 -0
  15. package/components/Badge/Badge.d.ts +13 -0
  16. package/components/Badge/Badge.d.ts.map +1 -0
  17. package/components/Badge/index.d.ts +4 -0
  18. package/components/Badge/index.d.ts.map +1 -0
  19. package/{render → components/Badge}/index.js +54 -42
  20. package/components/Button/Button.d.ts +16 -0
  21. package/components/Button/Button.d.ts.map +1 -0
  22. package/components/Button/index.d.ts +4 -0
  23. package/components/Button/index.d.ts.map +1 -0
  24. package/components/Button/index.js +91 -0
  25. package/components/Card/Card.d.ts +25 -0
  26. package/components/Card/Card.d.ts.map +1 -0
  27. package/components/Card/index.d.ts +4 -0
  28. package/components/Card/index.d.ts.map +1 -0
  29. package/components/Card/index.js +110 -0
  30. package/components/List/List.d.ts +15 -0
  31. package/components/List/List.d.ts.map +1 -0
  32. package/components/List/index.d.ts +4 -0
  33. package/components/List/index.d.ts.map +1 -0
  34. package/components/List/index.js +58 -0
  35. package/components/Loader/Loader.d.ts +28 -0
  36. package/components/Loader/Loader.d.ts.map +1 -0
  37. package/components/Loader/LoaderContext.d.ts +20 -0
  38. package/components/Loader/LoaderContext.d.ts.map +1 -0
  39. package/components/Loader/index.d.ts +6 -0
  40. package/components/Loader/index.d.ts.map +1 -0
  41. package/components/Loader/index.js +174 -0
  42. package/components/Modal/Modal.d.ts +22 -0
  43. package/components/Modal/Modal.d.ts.map +1 -0
  44. package/components/Modal/index.d.ts +4 -0
  45. package/components/Modal/index.d.ts.map +1 -0
  46. package/components/Modal/index.js +80 -0
  47. package/components/Select/Select.d.ts +21 -0
  48. package/components/Select/Select.d.ts.map +1 -0
  49. package/components/Select/index.d.ts +4 -0
  50. package/components/Select/index.d.ts.map +1 -0
  51. package/components/Select/index.js +78 -0
  52. package/components/Table/Table.d.ts +15 -0
  53. package/components/Table/Table.d.ts.map +1 -0
  54. package/components/Table/index.d.ts +4 -0
  55. package/components/Table/index.d.ts.map +1 -0
  56. package/components/Table/index.js +70 -0
  57. package/components/TextField/TextField.d.ts +19 -0
  58. package/components/TextField/TextField.d.ts.map +1 -0
  59. package/components/TextField/index.d.ts +4 -0
  60. package/components/TextField/index.d.ts.map +1 -0
  61. package/components/TextField/index.js +77 -0
  62. package/components/index.d.ts +22 -28
  63. package/components/index.d.ts.map +1 -1
  64. package/components/index.js +523 -2521
  65. package/esm/bridge/index.mjs +2 -6
  66. package/esm/components/Alert/index.mjs +28 -0
  67. package/esm/components/Avatar/index.mjs +10 -0
  68. package/esm/components/Badge/index.mjs +56 -0
  69. package/esm/components/Button/index.mjs +58 -0
  70. package/esm/components/Card/index.mjs +77 -0
  71. package/esm/components/List/index.mjs +25 -0
  72. package/esm/components/Loader/index.mjs +141 -0
  73. package/esm/components/Modal/index.mjs +47 -0
  74. package/esm/components/Select/index.mjs +45 -0
  75. package/esm/components/Table/index.mjs +37 -0
  76. package/esm/components/TextField/index.mjs +44 -0
  77. package/esm/components/index.mjs +513 -2415
  78. package/esm/index.mjs +62 -4652
  79. package/esm/package.json +372 -16
  80. package/esm/react/index.mjs +2 -285
  81. package/esm/renderer/charts/index.mjs +336 -0
  82. package/esm/renderer/common/index.mjs +135 -0
  83. package/esm/renderer/csv/index.mjs +193 -0
  84. package/esm/renderer/flow/index.mjs +259 -0
  85. package/esm/renderer/html/index.mjs +99 -0
  86. package/esm/renderer/image/index.mjs +125 -0
  87. package/esm/renderer/index.mjs +2173 -0
  88. package/esm/renderer/maps/index.mjs +217 -0
  89. package/esm/renderer/math/index.mjs +229 -0
  90. package/esm/renderer/mdx/index.mjs +261 -0
  91. package/esm/renderer/media/index.mjs +235 -0
  92. package/esm/renderer/mermaid/index.mjs +220 -0
  93. package/esm/renderer/pdf/index.mjs +229 -0
  94. package/esm/renderer/react/index.mjs +230 -0
  95. package/esm/runtime/index.mjs +194 -0
  96. package/esm/theme/index.mjs +93 -0
  97. package/index.d.ts +10 -18
  98. package/index.d.ts.map +1 -1
  99. package/index.js +63 -4806
  100. package/package.json +372 -16
  101. package/react/index.d.ts +8 -54
  102. package/react/index.d.ts.map +1 -1
  103. package/react/index.js +2 -295
  104. package/renderer/auto-detect.d.ts +39 -0
  105. package/renderer/auto-detect.d.ts.map +1 -0
  106. package/renderer/charts/index.d.ts +22 -0
  107. package/renderer/charts/index.d.ts.map +1 -0
  108. package/renderer/charts/index.js +367 -0
  109. package/renderer/common/index.d.ts +5 -0
  110. package/renderer/common/index.d.ts.map +1 -0
  111. package/renderer/common/index.js +158 -0
  112. package/renderer/common/inject-stylesheet.d.ts +9 -0
  113. package/renderer/common/inject-stylesheet.d.ts.map +1 -0
  114. package/renderer/common/lazy-import.d.ts +85 -0
  115. package/renderer/common/lazy-import.d.ts.map +1 -0
  116. package/renderer/common/use-lazy-module.d.ts +13 -0
  117. package/renderer/common/use-lazy-module.d.ts.map +1 -0
  118. package/renderer/common/use-renderer-theme.d.ts +35 -0
  119. package/renderer/common/use-renderer-theme.d.ts.map +1 -0
  120. package/renderer/csv/index.d.ts +12 -0
  121. package/renderer/csv/index.d.ts.map +1 -0
  122. package/renderer/csv/index.js +224 -0
  123. package/renderer/flow/index.d.ts +40 -0
  124. package/renderer/flow/index.d.ts.map +1 -0
  125. package/renderer/flow/index.js +290 -0
  126. package/renderer/html/index.d.ts +12 -0
  127. package/renderer/html/index.d.ts.map +1 -0
  128. package/renderer/html/index.js +130 -0
  129. package/renderer/image/index.d.ts +11 -0
  130. package/renderer/image/index.d.ts.map +1 -0
  131. package/renderer/image/index.js +156 -0
  132. package/renderer/index.d.ts +32 -0
  133. package/renderer/index.d.ts.map +1 -0
  134. package/renderer/index.js +2206 -0
  135. package/renderer/maps/index.d.ts +27 -0
  136. package/renderer/maps/index.d.ts.map +1 -0
  137. package/renderer/maps/index.js +248 -0
  138. package/renderer/math/index.d.ts +11 -0
  139. package/renderer/math/index.d.ts.map +1 -0
  140. package/renderer/math/index.js +260 -0
  141. package/renderer/mdx/index.d.ts +10 -0
  142. package/renderer/mdx/index.d.ts.map +1 -0
  143. package/renderer/mdx/index.js +292 -0
  144. package/renderer/media/index.d.ts +20 -0
  145. package/renderer/media/index.d.ts.map +1 -0
  146. package/renderer/media/index.js +266 -0
  147. package/renderer/mermaid/index.d.ts +11 -0
  148. package/renderer/mermaid/index.d.ts.map +1 -0
  149. package/renderer/mermaid/index.js +251 -0
  150. package/renderer/pdf/index.d.ts +10 -0
  151. package/renderer/pdf/index.d.ts.map +1 -0
  152. package/renderer/pdf/index.js +260 -0
  153. package/renderer/react/index.d.ts +45 -0
  154. package/renderer/react/index.d.ts.map +1 -0
  155. package/renderer/react/index.js +261 -0
  156. package/renderer/types.d.ts +24 -0
  157. package/renderer/types.d.ts.map +1 -0
  158. package/runtime/babel-runtime.d.ts +70 -0
  159. package/runtime/babel-runtime.d.ts.map +1 -0
  160. package/runtime/content-detector.d.ts +43 -0
  161. package/runtime/content-detector.d.ts.map +1 -0
  162. package/runtime/index.d.ts +10 -0
  163. package/runtime/index.d.ts.map +1 -0
  164. package/runtime/index.js +217 -0
  165. package/theme/FrontMcpThemeProvider.d.ts +4 -0
  166. package/theme/FrontMcpThemeProvider.d.ts.map +1 -0
  167. package/theme/create-theme.d.ts +9 -0
  168. package/theme/create-theme.d.ts.map +1 -0
  169. package/theme/index.d.ts +5 -0
  170. package/theme/index.d.ts.map +1 -0
  171. package/theme/index.js +126 -0
  172. package/theme/types.d.ts +28 -0
  173. package/theme/types.d.ts.map +1 -0
  174. package/theme/use-theme.d.ts +3 -0
  175. package/theme/use-theme.d.ts.map +1 -0
  176. package/bundler/browser-components.d.ts +0 -42
  177. package/bundler/browser-components.d.ts.map +0 -1
  178. package/bundler/bundler.d.ts +0 -282
  179. package/bundler/bundler.d.ts.map +0 -1
  180. package/bundler/index.d.ts +0 -43
  181. package/bundler/index.d.ts.map +0 -1
  182. package/bundler/index.js +0 -3168
  183. package/bundler/types.d.ts +0 -883
  184. package/bundler/types.d.ts.map +0 -1
  185. package/components/alert.d.ts +0 -83
  186. package/components/alert.d.ts.map +0 -1
  187. package/components/alert.schema.d.ts +0 -98
  188. package/components/alert.schema.d.ts.map +0 -1
  189. package/components/avatar.d.ts +0 -77
  190. package/components/avatar.d.ts.map +0 -1
  191. package/components/avatar.schema.d.ts +0 -170
  192. package/components/avatar.schema.d.ts.map +0 -1
  193. package/components/badge.d.ts +0 -78
  194. package/components/badge.d.ts.map +0 -1
  195. package/components/badge.schema.d.ts +0 -91
  196. package/components/badge.schema.d.ts.map +0 -1
  197. package/components/button.d.ts +0 -100
  198. package/components/button.d.ts.map +0 -1
  199. package/components/button.schema.d.ts +0 -120
  200. package/components/button.schema.d.ts.map +0 -1
  201. package/components/card.d.ts +0 -76
  202. package/components/card.d.ts.map +0 -1
  203. package/components/card.schema.d.ts +0 -93
  204. package/components/card.schema.d.ts.map +0 -1
  205. package/components/form.d.ts +0 -227
  206. package/components/form.d.ts.map +0 -1
  207. package/components/form.schema.d.ts +0 -365
  208. package/components/form.schema.d.ts.map +0 -1
  209. package/components/list.d.ts +0 -121
  210. package/components/list.d.ts.map +0 -1
  211. package/components/list.schema.d.ts +0 -129
  212. package/components/list.schema.d.ts.map +0 -1
  213. package/components/modal.d.ts +0 -100
  214. package/components/modal.d.ts.map +0 -1
  215. package/components/modal.schema.d.ts +0 -151
  216. package/components/modal.schema.d.ts.map +0 -1
  217. package/components/table.d.ts +0 -91
  218. package/components/table.d.ts.map +0 -1
  219. package/components/table.schema.d.ts +0 -123
  220. package/components/table.schema.d.ts.map +0 -1
  221. package/esm/bundler/index.mjs +0 -3136
  222. package/esm/layouts/index.mjs +0 -409
  223. package/esm/render/index.mjs +0 -45
  224. package/esm/renderers/index.mjs +0 -621
  225. package/esm/universal/index.mjs +0 -1946
  226. package/esm/web-components/index.mjs +0 -2023
  227. package/layouts/base.d.ts +0 -86
  228. package/layouts/base.d.ts.map +0 -1
  229. package/layouts/index.d.ts +0 -8
  230. package/layouts/index.d.ts.map +0 -1
  231. package/layouts/index.js +0 -437
  232. package/layouts/presets.d.ts +0 -134
  233. package/layouts/presets.d.ts.map +0 -1
  234. package/react/Alert.d.ts +0 -101
  235. package/react/Alert.d.ts.map +0 -1
  236. package/react/Badge.d.ts +0 -100
  237. package/react/Badge.d.ts.map +0 -1
  238. package/react/Button.d.ts +0 -108
  239. package/react/Button.d.ts.map +0 -1
  240. package/react/Card.d.ts +0 -103
  241. package/react/Card.d.ts.map +0 -1
  242. package/react/types.d.ts +0 -105
  243. package/react/types.d.ts.map +0 -1
  244. package/render/index.d.ts +0 -8
  245. package/render/index.d.ts.map +0 -1
  246. package/render/prerender.d.ts +0 -57
  247. package/render/prerender.d.ts.map +0 -1
  248. package/renderers/index.d.ts +0 -26
  249. package/renderers/index.d.ts.map +0 -1
  250. package/renderers/index.js +0 -666
  251. package/renderers/mdx.renderer.d.ts +0 -99
  252. package/renderers/mdx.renderer.d.ts.map +0 -1
  253. package/renderers/react.adapter.d.ts +0 -70
  254. package/renderers/react.adapter.d.ts.map +0 -1
  255. package/renderers/react.renderer.d.ts +0 -105
  256. package/renderers/react.renderer.d.ts.map +0 -1
  257. package/renderers/transpiler.d.ts +0 -49
  258. package/renderers/transpiler.d.ts.map +0 -1
  259. package/universal/UniversalApp.d.ts +0 -108
  260. package/universal/UniversalApp.d.ts.map +0 -1
  261. package/universal/cached-runtime.d.ts +0 -139
  262. package/universal/cached-runtime.d.ts.map +0 -1
  263. package/universal/context.d.ts +0 -122
  264. package/universal/context.d.ts.map +0 -1
  265. package/universal/index.d.ts +0 -57
  266. package/universal/index.d.ts.map +0 -1
  267. package/universal/index.js +0 -2032
  268. package/universal/renderers/html.renderer.d.ts +0 -36
  269. package/universal/renderers/html.renderer.d.ts.map +0 -1
  270. package/universal/renderers/index.d.ts +0 -112
  271. package/universal/renderers/index.d.ts.map +0 -1
  272. package/universal/renderers/markdown.renderer.d.ts +0 -33
  273. package/universal/renderers/markdown.renderer.d.ts.map +0 -1
  274. package/universal/renderers/mdx.renderer.d.ts +0 -38
  275. package/universal/renderers/mdx.renderer.d.ts.map +0 -1
  276. package/universal/renderers/react.renderer.d.ts +0 -46
  277. package/universal/renderers/react.renderer.d.ts.map +0 -1
  278. package/universal/runtime-builder.d.ts +0 -33
  279. package/universal/runtime-builder.d.ts.map +0 -1
  280. package/universal/store.d.ts +0 -135
  281. package/universal/store.d.ts.map +0 -1
  282. package/universal/types.d.ts +0 -199
  283. package/universal/types.d.ts.map +0 -1
  284. package/web-components/core/attribute-parser.d.ts +0 -82
  285. package/web-components/core/attribute-parser.d.ts.map +0 -1
  286. package/web-components/core/base-element.d.ts +0 -197
  287. package/web-components/core/base-element.d.ts.map +0 -1
  288. package/web-components/core/index.d.ts +0 -9
  289. package/web-components/core/index.d.ts.map +0 -1
  290. package/web-components/elements/fmcp-alert.d.ts +0 -46
  291. package/web-components/elements/fmcp-alert.d.ts.map +0 -1
  292. package/web-components/elements/fmcp-badge.d.ts +0 -47
  293. package/web-components/elements/fmcp-badge.d.ts.map +0 -1
  294. package/web-components/elements/fmcp-button.d.ts +0 -117
  295. package/web-components/elements/fmcp-button.d.ts.map +0 -1
  296. package/web-components/elements/fmcp-card.d.ts +0 -53
  297. package/web-components/elements/fmcp-card.d.ts.map +0 -1
  298. package/web-components/elements/fmcp-input.d.ts +0 -96
  299. package/web-components/elements/fmcp-input.d.ts.map +0 -1
  300. package/web-components/elements/fmcp-select.d.ts +0 -100
  301. package/web-components/elements/fmcp-select.d.ts.map +0 -1
  302. package/web-components/elements/index.d.ts +0 -13
  303. package/web-components/elements/index.d.ts.map +0 -1
  304. package/web-components/index.d.ts +0 -49
  305. package/web-components/index.d.ts.map +0 -1
  306. package/web-components/index.js +0 -2058
  307. package/web-components/register.d.ts +0 -57
  308. package/web-components/register.d.ts.map +0 -1
  309. package/web-components/types.d.ts +0 -122
  310. package/web-components/types.d.ts.map +0 -1
@@ -0,0 +1,235 @@
1
+ // libs/ui/src/renderer/media/index.ts
2
+ import React from "react";
3
+ import Box from "@mui/material/Box";
4
+ import Paper from "@mui/material/Paper";
5
+ import { styled } from "@mui/material/styles";
6
+
7
+ // libs/ui/src/renderer/common/lazy-import.ts
8
+ var ESM_SH_BASE = "https://esm.sh/";
9
+ function esmShUrl(pkg, options) {
10
+ let url = `${ESM_SH_BASE}${pkg}`;
11
+ if (options?.external?.length) {
12
+ url += `?external=${options.external.join(",")}`;
13
+ }
14
+ return url;
15
+ }
16
+ function runtimeImport(specifier) {
17
+ const dynamicImport = new Function("s", "return import(s)");
18
+ return dynamicImport(specifier);
19
+ }
20
+ async function runtimeImportWithFallback(bareSpecifier, fallbackUrl) {
21
+ try {
22
+ return await runtimeImport(bareSpecifier);
23
+ } catch {
24
+ return runtimeImport(fallbackUrl);
25
+ }
26
+ }
27
+ function createLazyImport(moduleId, importer) {
28
+ let state = { status: "idle" };
29
+ const doImport = importer ?? (async () => {
30
+ const mod = await runtimeImport(moduleId);
31
+ return mod["default"] ?? mod;
32
+ });
33
+ return {
34
+ load() {
35
+ if (state.status === "loaded") return Promise.resolve(state.module);
36
+ if (state.status === "loading") return state.promise;
37
+ if (state.status === "error") {
38
+ state = { status: "idle" };
39
+ }
40
+ const promise = doImport().then(
41
+ (mod) => {
42
+ state = { status: "loaded", module: mod };
43
+ return mod;
44
+ },
45
+ (err) => {
46
+ const error = err instanceof Error ? err : new Error(`Failed to load module "${moduleId}": ${String(err)}`);
47
+ state = { status: "error", error };
48
+ throw error;
49
+ }
50
+ );
51
+ state = { status: "loading", promise };
52
+ return promise;
53
+ },
54
+ get() {
55
+ return state.status === "loaded" ? state.module : void 0;
56
+ },
57
+ getState() {
58
+ return state;
59
+ },
60
+ reset() {
61
+ state = { status: "idle" };
62
+ }
63
+ };
64
+ }
65
+
66
+ // libs/ui/src/renderer/common/use-lazy-module.ts
67
+ import { useState, useEffect } from "react";
68
+ function useLazyModule(lazy) {
69
+ const [, forceUpdate] = useState(0);
70
+ useEffect(() => {
71
+ if (lazy.getState().status === "loaded") {
72
+ forceUpdate((n) => n + 1);
73
+ return;
74
+ }
75
+ lazy.load().then(
76
+ () => forceUpdate((n) => n + 1),
77
+ () => forceUpdate((n) => n + 1)
78
+ );
79
+ }, [lazy]);
80
+ return lazy.get();
81
+ }
82
+
83
+ // libs/ui/src/renderer/media/index.ts
84
+ var VIDEO_PATTERNS = [
85
+ /^https?:\/\/[^?#\s]+\.(?:mp4|webm|ogg|mov)(?:\?[^#\s]*)?$/i,
86
+ /^https?:\/\/(?:www\.)?(?:youtube\.com|youtu\.be|vimeo\.com)\//i,
87
+ /^data:video\//
88
+ ];
89
+ var AUDIO_PATTERNS = [
90
+ /^https?:\/\/[^?#\s]+\.(?:mp3|wav|ogg|aac|flac|m4a)(?:\?[^#\s]*)?$/i,
91
+ /^https?:\/\/(?:www\.)?soundcloud\.com\//i,
92
+ /^data:audio\//
93
+ ];
94
+ function isVideo(content) {
95
+ const trimmed = content.trim();
96
+ return VIDEO_PATTERNS.some((p) => p.test(trimmed));
97
+ }
98
+ function isAudio(content) {
99
+ const trimmed = content.trim();
100
+ return AUDIO_PATTERNS.some((p) => p.test(trimmed));
101
+ }
102
+ function isMedia(content) {
103
+ return isVideo(content) || isAudio(content);
104
+ }
105
+ var lazyReactPlayer = createLazyImport("react-player", async () => {
106
+ const mod = await runtimeImportWithFallback(
107
+ "react-player",
108
+ esmShUrl("react-player@2", { external: ["react", "react-dom"] })
109
+ );
110
+ return mod;
111
+ });
112
+ var MediaRoot = styled(Paper, {
113
+ name: "FrontMcpMedia",
114
+ slot: "Root"
115
+ })(({ theme }) => ({
116
+ overflow: "hidden",
117
+ borderRadius: theme.shape.borderRadius
118
+ }));
119
+ var VideoWrapper = styled(Box)({
120
+ position: "relative",
121
+ paddingTop: "56.25%",
122
+ // 16:9 aspect ratio
123
+ "& > *": {
124
+ position: "absolute",
125
+ top: 0,
126
+ left: 0
127
+ }
128
+ });
129
+ var AudioWrapper = styled(Box)(({ theme }) => ({
130
+ padding: theme.spacing(1),
131
+ "& > *": {
132
+ width: "100%"
133
+ }
134
+ }));
135
+ function MediaView({ url, isAudioContent, className }) {
136
+ const reactPlayerMod = useLazyModule(lazyReactPlayer);
137
+ if (!reactPlayerMod) {
138
+ if (isAudioContent) {
139
+ return React.createElement(
140
+ MediaRoot,
141
+ { variant: "outlined", className },
142
+ React.createElement(
143
+ AudioWrapper,
144
+ null,
145
+ React.createElement("audio", { controls: true, src: url, style: { width: "100%" } })
146
+ )
147
+ );
148
+ }
149
+ return React.createElement(
150
+ MediaRoot,
151
+ { variant: "outlined", className },
152
+ React.createElement(
153
+ VideoWrapper,
154
+ null,
155
+ React.createElement("video", {
156
+ controls: true,
157
+ src: url,
158
+ style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }
159
+ })
160
+ )
161
+ );
162
+ }
163
+ const ReactPlayer = reactPlayerMod.default;
164
+ if (isAudioContent) {
165
+ return React.createElement(
166
+ MediaRoot,
167
+ { variant: "outlined", className },
168
+ React.createElement(
169
+ AudioWrapper,
170
+ null,
171
+ React.createElement(ReactPlayer, {
172
+ url,
173
+ controls: true,
174
+ width: "100%",
175
+ height: 50
176
+ })
177
+ )
178
+ );
179
+ }
180
+ return React.createElement(
181
+ MediaRoot,
182
+ { variant: "outlined", className },
183
+ React.createElement(
184
+ VideoWrapper,
185
+ null,
186
+ React.createElement(ReactPlayer, {
187
+ url,
188
+ controls: true,
189
+ width: "100%",
190
+ height: "100%"
191
+ })
192
+ )
193
+ );
194
+ }
195
+ lazyReactPlayer.load().catch(() => {
196
+ });
197
+ var VideoRenderer = class {
198
+ type = "video";
199
+ priority = 20;
200
+ canHandle(content) {
201
+ return isVideo(content);
202
+ }
203
+ render(content, options) {
204
+ return React.createElement(MediaView, {
205
+ url: content.trim(),
206
+ isAudioContent: false,
207
+ className: options?.className ?? "fmcp-media-content"
208
+ });
209
+ }
210
+ };
211
+ var AudioRenderer = class {
212
+ type = "audio";
213
+ priority = 20;
214
+ canHandle(content) {
215
+ return isAudio(content);
216
+ }
217
+ render(content, options) {
218
+ return React.createElement(MediaView, {
219
+ url: content.trim(),
220
+ isAudioContent: true,
221
+ className: options?.className ?? "fmcp-media-content"
222
+ });
223
+ }
224
+ };
225
+ var videoRenderer = new VideoRenderer();
226
+ var audioRenderer = new AudioRenderer();
227
+ export {
228
+ AudioRenderer,
229
+ VideoRenderer,
230
+ audioRenderer,
231
+ isAudio,
232
+ isMedia,
233
+ isVideo,
234
+ videoRenderer
235
+ };
@@ -0,0 +1,220 @@
1
+ // libs/ui/src/renderer/mermaid/index.ts
2
+ import React, { useEffect, useRef, useState, useId } from "react";
3
+ import Box from "@mui/material/Box";
4
+ import Alert from "@mui/material/Alert";
5
+ import { styled } from "@mui/material/styles";
6
+
7
+ // libs/ui/src/renderer/common/lazy-import.ts
8
+ var ESM_SH_BASE = "https://esm.sh/";
9
+ function esmShUrl(pkg, options) {
10
+ let url = `${ESM_SH_BASE}${pkg}`;
11
+ if (options?.external?.length) {
12
+ url += `?external=${options.external.join(",")}`;
13
+ }
14
+ return url;
15
+ }
16
+ function runtimeImport(specifier) {
17
+ const dynamicImport = new Function("s", "return import(s)");
18
+ return dynamicImport(specifier);
19
+ }
20
+ async function runtimeImportWithFallback(bareSpecifier, fallbackUrl) {
21
+ try {
22
+ return await runtimeImport(bareSpecifier);
23
+ } catch {
24
+ return runtimeImport(fallbackUrl);
25
+ }
26
+ }
27
+ function createLazyImport(moduleId, importer) {
28
+ let state = { status: "idle" };
29
+ const doImport = importer ?? (async () => {
30
+ const mod = await runtimeImport(moduleId);
31
+ return mod["default"] ?? mod;
32
+ });
33
+ return {
34
+ load() {
35
+ if (state.status === "loaded") return Promise.resolve(state.module);
36
+ if (state.status === "loading") return state.promise;
37
+ if (state.status === "error") {
38
+ state = { status: "idle" };
39
+ }
40
+ const promise = doImport().then(
41
+ (mod) => {
42
+ state = { status: "loaded", module: mod };
43
+ return mod;
44
+ },
45
+ (err) => {
46
+ const error = err instanceof Error ? err : new Error(`Failed to load module "${moduleId}": ${String(err)}`);
47
+ state = { status: "error", error };
48
+ throw error;
49
+ }
50
+ );
51
+ state = { status: "loading", promise };
52
+ return promise;
53
+ },
54
+ get() {
55
+ return state.status === "loaded" ? state.module : void 0;
56
+ },
57
+ getState() {
58
+ return state;
59
+ },
60
+ reset() {
61
+ state = { status: "idle" };
62
+ }
63
+ };
64
+ }
65
+
66
+ // libs/ui/src/renderer/common/use-renderer-theme.ts
67
+ import { useMemo } from "react";
68
+ import { useTheme } from "@mui/material/styles";
69
+ function extractThemeValues(theme) {
70
+ const palette = theme.palette;
71
+ return {
72
+ mode: palette.mode,
73
+ primary: palette.primary.main,
74
+ secondary: palette.secondary.main,
75
+ error: palette.error.main,
76
+ warning: palette.warning.main,
77
+ success: palette.success.main,
78
+ info: palette.info.main,
79
+ background: palette.background.default,
80
+ paper: palette.background.paper,
81
+ textPrimary: palette.text.primary,
82
+ textSecondary: palette.text.secondary,
83
+ divider: palette.divider,
84
+ fontFamily: theme.typography.fontFamily ?? "sans-serif",
85
+ monoFontFamily: theme.typography["monoFontFamily"] ?? '"SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", monospace',
86
+ fontSize: theme.typography.fontSize ?? 14,
87
+ borderRadius: typeof theme.shape.borderRadius === "number" ? theme.shape.borderRadius : 4,
88
+ seriesColors: [
89
+ palette.primary.main,
90
+ palette.secondary.main,
91
+ palette.error.main,
92
+ palette.warning.main,
93
+ palette.success.main,
94
+ palette.info.main
95
+ ]
96
+ };
97
+ }
98
+ function useRendererTheme() {
99
+ const theme = useTheme();
100
+ return useMemo(() => extractThemeValues(theme), [theme]);
101
+ }
102
+
103
+ // libs/ui/src/renderer/mermaid/index.ts
104
+ var MERMAID_PATTERN = /^\s*(?:graph|sequenceDiagram|classDiagram|stateDiagram|flowchart|erDiagram|gantt|pie|journey|gitGraph)\b/;
105
+ function isMermaid(content) {
106
+ return MERMAID_PATTERN.test(content.trim());
107
+ }
108
+ var lazyMermaid = createLazyImport("mermaid", async () => {
109
+ const mod = await runtimeImportWithFallback("mermaid", esmShUrl("mermaid@11"));
110
+ const mermaid = mod["default"] ?? mod;
111
+ return mermaid;
112
+ });
113
+ var MermaidRoot = styled(Box, {
114
+ name: "FrontMcpMermaid",
115
+ slot: "Root"
116
+ })(({ theme }) => ({
117
+ width: "100%",
118
+ display: "flex",
119
+ justifyContent: "center",
120
+ padding: theme.spacing(2),
121
+ "& svg": {
122
+ maxWidth: "100%",
123
+ height: "auto"
124
+ }
125
+ }));
126
+ function getMermaidTheme(tv) {
127
+ return tv.mode === "dark" ? "dark" : "default";
128
+ }
129
+ function getMermaidThemeVariables(tv) {
130
+ return {
131
+ primaryColor: tv.primary,
132
+ secondaryColor: tv.secondary,
133
+ tertiaryColor: tv.info,
134
+ primaryTextColor: tv.textPrimary,
135
+ secondaryTextColor: tv.textSecondary,
136
+ lineColor: tv.divider,
137
+ fontFamily: tv.fontFamily,
138
+ fontSize: `${tv.fontSize}px`
139
+ };
140
+ }
141
+ function MermaidView({ definition, className }) {
142
+ const containerRef = useRef(null);
143
+ const [svg, setSvg] = useState(null);
144
+ const [error, setError] = useState(null);
145
+ const themeValues = useRendererTheme();
146
+ const uniqueId = useId().replace(/:/g, "-");
147
+ useEffect(() => {
148
+ let cancelled = false;
149
+ async function renderDiagram() {
150
+ try {
151
+ const mermaid = lazyMermaid.get() ?? await lazyMermaid.load();
152
+ mermaid.initialize({
153
+ startOnLoad: false,
154
+ theme: getMermaidTheme(themeValues),
155
+ themeVariables: getMermaidThemeVariables(themeValues),
156
+ securityLevel: "strict"
157
+ });
158
+ const result = await mermaid.render(`mermaid-${uniqueId}`, definition);
159
+ if (!cancelled) {
160
+ setSvg(result.svg);
161
+ setError(null);
162
+ }
163
+ } catch (err) {
164
+ if (!cancelled) {
165
+ setError(err instanceof Error ? err.message : String(err));
166
+ setSvg(null);
167
+ }
168
+ }
169
+ }
170
+ renderDiagram();
171
+ return () => {
172
+ cancelled = true;
173
+ };
174
+ }, [definition, themeValues, uniqueId]);
175
+ if (error) {
176
+ return React.createElement(
177
+ Box,
178
+ { className },
179
+ React.createElement(Alert, { severity: "error", sx: { mb: 1 } }, `Mermaid parse error: ${error}`),
180
+ React.createElement(
181
+ "pre",
182
+ { style: { fontFamily: "monospace", whiteSpace: "pre-wrap", fontSize: "0.85em" } },
183
+ definition
184
+ )
185
+ );
186
+ }
187
+ if (!svg) {
188
+ return React.createElement(
189
+ MermaidRoot,
190
+ { className },
191
+ React.createElement(Box, { sx: { color: "text.secondary" } }, "Rendering diagram...")
192
+ );
193
+ }
194
+ return React.createElement(MermaidRoot, {
195
+ ref: containerRef,
196
+ className,
197
+ dangerouslySetInnerHTML: { __html: svg }
198
+ });
199
+ }
200
+ lazyMermaid.load().catch(() => {
201
+ });
202
+ var MermaidRenderer = class {
203
+ type = "mermaid";
204
+ priority = 50;
205
+ canHandle(content) {
206
+ return isMermaid(content);
207
+ }
208
+ render(content, options) {
209
+ return React.createElement(MermaidView, {
210
+ definition: content.trim(),
211
+ className: options?.className ?? "fmcp-mermaid-content"
212
+ });
213
+ }
214
+ };
215
+ var mermaidRenderer = new MermaidRenderer();
216
+ export {
217
+ MermaidRenderer,
218
+ isMermaid,
219
+ mermaidRenderer
220
+ };
@@ -0,0 +1,229 @@
1
+ // libs/ui/src/renderer/pdf/index.ts
2
+ import React, { useState as useState2, useCallback, useMemo } from "react";
3
+ import Box from "@mui/material/Box";
4
+ import IconButton from "@mui/material/IconButton";
5
+ import Typography from "@mui/material/Typography";
6
+ import TextField from "@mui/material/TextField";
7
+ import { styled } from "@mui/material/styles";
8
+
9
+ // libs/ui/src/renderer/common/lazy-import.ts
10
+ var ESM_SH_BASE = "https://esm.sh/";
11
+ function esmShUrl(pkg, options) {
12
+ let url = `${ESM_SH_BASE}${pkg}`;
13
+ if (options?.external?.length) {
14
+ url += `?external=${options.external.join(",")}`;
15
+ }
16
+ return url;
17
+ }
18
+ function runtimeImport(specifier) {
19
+ const dynamicImport = new Function("s", "return import(s)");
20
+ return dynamicImport(specifier);
21
+ }
22
+ async function runtimeImportWithFallback(bareSpecifier, fallbackUrl) {
23
+ try {
24
+ return await runtimeImport(bareSpecifier);
25
+ } catch {
26
+ return runtimeImport(fallbackUrl);
27
+ }
28
+ }
29
+ function createLazyImport(moduleId, importer) {
30
+ let state = { status: "idle" };
31
+ const doImport = importer ?? (async () => {
32
+ const mod = await runtimeImport(moduleId);
33
+ return mod["default"] ?? mod;
34
+ });
35
+ return {
36
+ load() {
37
+ if (state.status === "loaded") return Promise.resolve(state.module);
38
+ if (state.status === "loading") return state.promise;
39
+ if (state.status === "error") {
40
+ state = { status: "idle" };
41
+ }
42
+ const promise = doImport().then(
43
+ (mod) => {
44
+ state = { status: "loaded", module: mod };
45
+ return mod;
46
+ },
47
+ (err) => {
48
+ const error = err instanceof Error ? err : new Error(`Failed to load module "${moduleId}": ${String(err)}`);
49
+ state = { status: "error", error };
50
+ throw error;
51
+ }
52
+ );
53
+ state = { status: "loading", promise };
54
+ return promise;
55
+ },
56
+ get() {
57
+ return state.status === "loaded" ? state.module : void 0;
58
+ },
59
+ getState() {
60
+ return state;
61
+ },
62
+ reset() {
63
+ state = { status: "idle" };
64
+ }
65
+ };
66
+ }
67
+
68
+ // libs/ui/src/renderer/common/use-lazy-module.ts
69
+ import { useState, useEffect } from "react";
70
+ function useLazyModule(lazy) {
71
+ const [, forceUpdate] = useState(0);
72
+ useEffect(() => {
73
+ if (lazy.getState().status === "loaded") {
74
+ forceUpdate((n) => n + 1);
75
+ return;
76
+ }
77
+ lazy.load().then(
78
+ () => forceUpdate((n) => n + 1),
79
+ () => forceUpdate((n) => n + 1)
80
+ );
81
+ }, [lazy]);
82
+ return lazy.get();
83
+ }
84
+
85
+ // libs/ui/src/renderer/pdf/index.ts
86
+ var lazyReactPdf = createLazyImport("react-pdf", async () => {
87
+ const mod = await runtimeImportWithFallback(
88
+ "react-pdf",
89
+ esmShUrl("react-pdf@9", { external: ["react", "react-dom"] })
90
+ );
91
+ const pdfjs = mod["pdfjs"];
92
+ if (pdfjs?.GlobalWorkerOptions) {
93
+ pdfjs.GlobalWorkerOptions.workerSrc = `${ESM_SH_BASE}pdfjs-dist@${pdfjs.version ?? "4"}/build/pdf.worker.min.mjs?raw`;
94
+ }
95
+ return mod;
96
+ });
97
+ function toDataUri(content) {
98
+ if (content.startsWith("data:")) return content;
99
+ if (content.startsWith("%PDF-")) {
100
+ const base64 = typeof btoa === "function" ? btoa(content) : Buffer.from(content).toString("base64");
101
+ return `data:application/pdf;base64,${base64}`;
102
+ }
103
+ return `data:application/pdf;base64,${content}`;
104
+ }
105
+ var PdfRoot = styled(Box, {
106
+ name: "FrontMcpPdf",
107
+ slot: "Root"
108
+ })(({ theme }) => ({
109
+ width: "100%",
110
+ borderRadius: theme.shape.borderRadius,
111
+ overflow: "hidden",
112
+ border: `1px solid ${theme.palette.divider}`
113
+ }));
114
+ var Toolbar = styled(Box, {
115
+ name: "FrontMcpPdf",
116
+ slot: "Toolbar"
117
+ })(({ theme }) => ({
118
+ display: "flex",
119
+ alignItems: "center",
120
+ gap: theme.spacing(1),
121
+ padding: theme.spacing(1, 2),
122
+ borderBottom: `1px solid ${theme.palette.divider}`,
123
+ backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[900] : theme.palette.grey[50]
124
+ }));
125
+ var PageContainer = styled(Box, {
126
+ name: "FrontMcpPdf",
127
+ slot: "PageContainer"
128
+ })({
129
+ display: "flex",
130
+ justifyContent: "center",
131
+ overflow: "auto",
132
+ maxHeight: 700
133
+ });
134
+ function PdfView({ content, className, title }) {
135
+ const [numPages, setNumPages] = useState2(0);
136
+ const [pageNumber, setPageNumber] = useState2(1);
137
+ const [scale, setScale] = useState2(1);
138
+ const reactPdf = useLazyModule(lazyReactPdf);
139
+ const dataUri = useMemo(() => toDataUri(content), [content]);
140
+ const onDocumentLoadSuccess = useCallback(({ numPages: n }) => {
141
+ setNumPages(n);
142
+ }, []);
143
+ const goToPrev = useCallback(() => setPageNumber((p) => Math.max(1, p - 1)), []);
144
+ const goToNext = useCallback(() => setPageNumber((p) => Math.min(numPages, p + 1)), []);
145
+ const zoomIn = useCallback(() => setScale((s) => Math.min(3, s + 0.25)), []);
146
+ const zoomOut = useCallback(() => setScale((s) => Math.max(0.25, s - 0.25)), []);
147
+ if (!reactPdf) {
148
+ return React.createElement("iframe", {
149
+ className: className ?? "fmcp-pdf-content",
150
+ src: dataUri,
151
+ style: { width: "100%", height: "600px", border: "none" },
152
+ title: title ?? "PDF Document"
153
+ });
154
+ }
155
+ const { Document, Page } = reactPdf;
156
+ return React.createElement(
157
+ PdfRoot,
158
+ { className },
159
+ React.createElement(
160
+ Toolbar,
161
+ null,
162
+ React.createElement(
163
+ IconButton,
164
+ { size: "small", onClick: goToPrev, disabled: pageNumber <= 1, "aria-label": "Previous page" },
165
+ "\u25C0"
166
+ ),
167
+ React.createElement(
168
+ Typography,
169
+ { variant: "body2", sx: { minWidth: 80, textAlign: "center" } },
170
+ `${pageNumber} / ${numPages || "..."}`
171
+ ),
172
+ React.createElement(
173
+ IconButton,
174
+ { size: "small", onClick: goToNext, disabled: pageNumber >= numPages, "aria-label": "Next page" },
175
+ "\u25B6"
176
+ ),
177
+ React.createElement(Box, { sx: { flex: 1 } }),
178
+ React.createElement(IconButton, { size: "small", onClick: zoomOut, "aria-label": "Zoom out" }, "\u2212"),
179
+ React.createElement(
180
+ Typography,
181
+ { variant: "body2", sx: { minWidth: 50, textAlign: "center" } },
182
+ `${Math.round(scale * 100)}%`
183
+ ),
184
+ React.createElement(IconButton, { size: "small", onClick: zoomIn, "aria-label": "Zoom in" }, "+"),
185
+ React.createElement(Box, { sx: { flex: 1 } }),
186
+ React.createElement(TextField, {
187
+ size: "small",
188
+ type: "number",
189
+ value: pageNumber,
190
+ onChange: (e) => {
191
+ const n = parseInt(e.target.value, 10);
192
+ if (n >= 1 && n <= numPages) setPageNumber(n);
193
+ },
194
+ sx: { width: 70 },
195
+ slotProps: { htmlInput: { min: 1, max: numPages, "aria-label": "Go to page" } }
196
+ })
197
+ ),
198
+ React.createElement(
199
+ PageContainer,
200
+ null,
201
+ React.createElement(
202
+ Document,
203
+ { file: dataUri, onLoadSuccess: onDocumentLoadSuccess },
204
+ React.createElement(Page, { pageNumber, scale, renderTextLayer: false, renderAnnotationLayer: false })
205
+ )
206
+ )
207
+ );
208
+ }
209
+ lazyReactPdf.load().catch(() => {
210
+ });
211
+ var PdfRenderer = class {
212
+ type = "pdf";
213
+ priority = 90;
214
+ canHandle(content) {
215
+ return content.startsWith("%PDF-") || content.trim().startsWith("JVBER") || /^data:application\/pdf[;,]/.test(content.trim());
216
+ }
217
+ render(content, options) {
218
+ return React.createElement(PdfView, {
219
+ content,
220
+ className: options?.className ?? "fmcp-pdf-content",
221
+ title: options?.toolName ?? "PDF Document"
222
+ });
223
+ }
224
+ };
225
+ var pdfRenderer = new PdfRenderer();
226
+ export {
227
+ PdfRenderer,
228
+ pdfRenderer
229
+ };