@frontmcp/ui 0.12.2 → 1.0.0-beta.1

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,135 @@
1
+ // libs/ui/src/renderer/common/use-renderer-theme.ts
2
+ import { useMemo } from "react";
3
+ import { useTheme } from "@mui/material/styles";
4
+ function extractThemeValues(theme) {
5
+ const palette = theme.palette;
6
+ return {
7
+ mode: palette.mode,
8
+ primary: palette.primary.main,
9
+ secondary: palette.secondary.main,
10
+ error: palette.error.main,
11
+ warning: palette.warning.main,
12
+ success: palette.success.main,
13
+ info: palette.info.main,
14
+ background: palette.background.default,
15
+ paper: palette.background.paper,
16
+ textPrimary: palette.text.primary,
17
+ textSecondary: palette.text.secondary,
18
+ divider: palette.divider,
19
+ fontFamily: theme.typography.fontFamily ?? "sans-serif",
20
+ monoFontFamily: theme.typography["monoFontFamily"] ?? '"SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", monospace',
21
+ fontSize: theme.typography.fontSize ?? 14,
22
+ borderRadius: typeof theme.shape.borderRadius === "number" ? theme.shape.borderRadius : 4,
23
+ seriesColors: [
24
+ palette.primary.main,
25
+ palette.secondary.main,
26
+ palette.error.main,
27
+ palette.warning.main,
28
+ palette.success.main,
29
+ palette.info.main
30
+ ]
31
+ };
32
+ }
33
+ function useRendererTheme() {
34
+ const theme = useTheme();
35
+ return useMemo(() => extractThemeValues(theme), [theme]);
36
+ }
37
+
38
+ // libs/ui/src/renderer/common/inject-stylesheet.ts
39
+ function injectStylesheet(href, id) {
40
+ if (typeof document === "undefined") return;
41
+ if (document.getElementById(id)) return;
42
+ const link = document.createElement("link");
43
+ link.id = id;
44
+ link.rel = "stylesheet";
45
+ link.href = href;
46
+ link.crossOrigin = "anonymous";
47
+ document.head.appendChild(link);
48
+ }
49
+
50
+ // libs/ui/src/renderer/common/lazy-import.ts
51
+ var ESM_SH_BASE = "https://esm.sh/";
52
+ function esmShUrl(pkg, options) {
53
+ let url = `${ESM_SH_BASE}${pkg}`;
54
+ if (options?.external?.length) {
55
+ url += `?external=${options.external.join(",")}`;
56
+ }
57
+ return url;
58
+ }
59
+ function runtimeImport(specifier) {
60
+ const dynamicImport = new Function("s", "return import(s)");
61
+ return dynamicImport(specifier);
62
+ }
63
+ async function runtimeImportWithFallback(bareSpecifier, fallbackUrl) {
64
+ try {
65
+ return await runtimeImport(bareSpecifier);
66
+ } catch {
67
+ return runtimeImport(fallbackUrl);
68
+ }
69
+ }
70
+ function createLazyImport(moduleId, importer) {
71
+ let state = { status: "idle" };
72
+ const doImport = importer ?? (async () => {
73
+ const mod = await runtimeImport(moduleId);
74
+ return mod["default"] ?? mod;
75
+ });
76
+ return {
77
+ load() {
78
+ if (state.status === "loaded") return Promise.resolve(state.module);
79
+ if (state.status === "loading") return state.promise;
80
+ if (state.status === "error") {
81
+ state = { status: "idle" };
82
+ }
83
+ const promise = doImport().then(
84
+ (mod) => {
85
+ state = { status: "loaded", module: mod };
86
+ return mod;
87
+ },
88
+ (err) => {
89
+ const error = err instanceof Error ? err : new Error(`Failed to load module "${moduleId}": ${String(err)}`);
90
+ state = { status: "error", error };
91
+ throw error;
92
+ }
93
+ );
94
+ state = { status: "loading", promise };
95
+ return promise;
96
+ },
97
+ get() {
98
+ return state.status === "loaded" ? state.module : void 0;
99
+ },
100
+ getState() {
101
+ return state;
102
+ },
103
+ reset() {
104
+ state = { status: "idle" };
105
+ }
106
+ };
107
+ }
108
+
109
+ // libs/ui/src/renderer/common/use-lazy-module.ts
110
+ import { useState, useEffect } from "react";
111
+ function useLazyModule(lazy) {
112
+ const [, forceUpdate] = useState(0);
113
+ useEffect(() => {
114
+ if (lazy.getState().status === "loaded") {
115
+ forceUpdate((n) => n + 1);
116
+ return;
117
+ }
118
+ lazy.load().then(
119
+ () => forceUpdate((n) => n + 1),
120
+ () => forceUpdate((n) => n + 1)
121
+ );
122
+ }, [lazy]);
123
+ return lazy.get();
124
+ }
125
+ export {
126
+ ESM_SH_BASE,
127
+ createLazyImport,
128
+ esmShUrl,
129
+ extractThemeValues,
130
+ injectStylesheet,
131
+ runtimeImport,
132
+ runtimeImportWithFallback,
133
+ useLazyModule,
134
+ useRendererTheme
135
+ };
@@ -0,0 +1,193 @@
1
+ // libs/ui/src/renderer/csv/index.ts
2
+ import React, { useState, useMemo, useCallback } from "react";
3
+ import Box from "@mui/material/Box";
4
+ import MuiTable from "@mui/material/Table";
5
+ import TableBody from "@mui/material/TableBody";
6
+ import TableCell from "@mui/material/TableCell";
7
+ import TableContainer from "@mui/material/TableContainer";
8
+ import TableHead from "@mui/material/TableHead";
9
+ import TableRow from "@mui/material/TableRow";
10
+ import TablePagination from "@mui/material/TablePagination";
11
+ import TableSortLabel from "@mui/material/TableSortLabel";
12
+ import TextField from "@mui/material/TextField";
13
+ import { styled } from "@mui/material/styles";
14
+ function detectDelimiter(content) {
15
+ const firstLine = content.split("\n")[0];
16
+ const commas = (firstLine.match(/,/g) ?? []).length;
17
+ const tabs = (firstLine.match(/\t/g) ?? []).length;
18
+ const semicolons = (firstLine.match(/;/g) ?? []).length;
19
+ if (tabs > commas && tabs > semicolons) return " ";
20
+ if (semicolons > commas) return ";";
21
+ return ",";
22
+ }
23
+ function parseCsv(content, delimiter) {
24
+ return content.trim().split("\n").map((line) => line.split(delimiter).map((cell) => cell.trim()));
25
+ }
26
+ var CsvRoot = styled(Box, {
27
+ name: "FrontMcpCsvTable",
28
+ slot: "Root"
29
+ })({
30
+ width: "100%"
31
+ });
32
+ var StyledHeaderCell = styled(TableCell, {
33
+ name: "FrontMcpCsvTable",
34
+ slot: "Header"
35
+ })(({ theme }) => ({
36
+ fontWeight: 600,
37
+ backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[900] : theme.palette.grey[50],
38
+ whiteSpace: "nowrap"
39
+ }));
40
+ var FilterToolbar = styled(Box, {
41
+ name: "FrontMcpCsvTable",
42
+ slot: "Toolbar"
43
+ })(({ theme }) => ({
44
+ padding: theme.spacing(1, 2),
45
+ display: "flex",
46
+ gap: theme.spacing(1)
47
+ }));
48
+ function CsvTableView({ content, className, pageSize = 25 }) {
49
+ const delimiter = useMemo(() => detectDelimiter(content), [content]);
50
+ const allRows = useMemo(() => parseCsv(content, delimiter), [content, delimiter]);
51
+ const headers = allRows[0] ?? [];
52
+ const dataRows = useMemo(() => allRows.slice(1), [allRows]);
53
+ const [page, setPage] = useState(0);
54
+ const [rowsPerPage, setRowsPerPage] = useState(pageSize);
55
+ const [sortCol, setSortCol] = useState(null);
56
+ const [sortDir, setSortDir] = useState("asc");
57
+ const [filter, setFilter] = useState("");
58
+ const filteredRows = useMemo(() => {
59
+ if (!filter) return dataRows;
60
+ const lower = filter.toLowerCase();
61
+ return dataRows.filter((row) => row.some((cell) => cell.toLowerCase().includes(lower)));
62
+ }, [dataRows, filter]);
63
+ const sortedRows = useMemo(() => {
64
+ if (sortCol === null) return filteredRows;
65
+ const sorted = [...filteredRows];
66
+ sorted.sort((a, b) => {
67
+ const va = a[sortCol] ?? "";
68
+ const vb = b[sortCol] ?? "";
69
+ const numA = Number(va);
70
+ const numB = Number(vb);
71
+ if (!isNaN(numA) && !isNaN(numB)) {
72
+ return sortDir === "asc" ? numA - numB : numB - numA;
73
+ }
74
+ return sortDir === "asc" ? va.localeCompare(vb) : vb.localeCompare(va);
75
+ });
76
+ return sorted;
77
+ }, [filteredRows, sortCol, sortDir]);
78
+ const pageRows = useMemo(
79
+ () => sortedRows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage),
80
+ [sortedRows, page, rowsPerPage]
81
+ );
82
+ const handleSort = useCallback((colIndex) => {
83
+ setSortCol((prev) => {
84
+ if (prev === colIndex) {
85
+ setSortDir((d) => d === "asc" ? "desc" : "asc");
86
+ return colIndex;
87
+ }
88
+ setSortDir("asc");
89
+ return colIndex;
90
+ });
91
+ }, []);
92
+ const handleChangePage = useCallback((_, newPage) => setPage(newPage), []);
93
+ const handleChangeRowsPerPage = useCallback((e) => {
94
+ setRowsPerPage(parseInt(e.target.value, 10));
95
+ setPage(0);
96
+ }, []);
97
+ return React.createElement(
98
+ CsvRoot,
99
+ { className },
100
+ React.createElement(
101
+ FilterToolbar,
102
+ null,
103
+ React.createElement(TextField, {
104
+ size: "small",
105
+ placeholder: "Filter rows...",
106
+ value: filter,
107
+ onChange: (e) => {
108
+ setFilter(e.target.value);
109
+ setPage(0);
110
+ },
111
+ sx: { minWidth: 200 }
112
+ })
113
+ ),
114
+ React.createElement(
115
+ TableContainer,
116
+ { sx: { border: 1, borderColor: "divider", borderRadius: 1 } },
117
+ React.createElement(
118
+ MuiTable,
119
+ { size: "small", stickyHeader: true },
120
+ React.createElement(
121
+ TableHead,
122
+ null,
123
+ React.createElement(
124
+ TableRow,
125
+ null,
126
+ headers.map(
127
+ (header, i) => React.createElement(
128
+ StyledHeaderCell,
129
+ { key: i },
130
+ React.createElement(
131
+ TableSortLabel,
132
+ {
133
+ active: sortCol === i,
134
+ direction: sortCol === i ? sortDir : "asc",
135
+ onClick: () => handleSort(i)
136
+ },
137
+ header
138
+ )
139
+ )
140
+ )
141
+ )
142
+ ),
143
+ React.createElement(
144
+ TableBody,
145
+ null,
146
+ pageRows.map(
147
+ (row, ri) => React.createElement(
148
+ TableRow,
149
+ { key: ri, hover: true },
150
+ row.map((cell, ci) => React.createElement(TableCell, { key: ci }, cell))
151
+ )
152
+ )
153
+ )
154
+ )
155
+ ),
156
+ sortedRows.length > rowsPerPage && React.createElement(TablePagination, {
157
+ count: sortedRows.length,
158
+ page,
159
+ rowsPerPage,
160
+ onPageChange: handleChangePage,
161
+ onRowsPerPageChange: handleChangeRowsPerPage,
162
+ rowsPerPageOptions: [10, 25, 50, 100]
163
+ })
164
+ );
165
+ }
166
+ var CsvRenderer = class {
167
+ type = "csv";
168
+ priority = 10;
169
+ canHandle(content) {
170
+ const lines = content.trim().split("\n").slice(0, 5);
171
+ if (lines.length < 2) return false;
172
+ for (const delim of [",", " ", ";"]) {
173
+ const counts = lines.map((line) => line.split(delim).length);
174
+ if (counts[0] > 1 && counts.every((c) => c === counts[0])) return true;
175
+ }
176
+ return false;
177
+ }
178
+ render(content, options) {
179
+ const pageSize = options?.rendererOptions?.["pageSize"];
180
+ return React.createElement(CsvTableView, {
181
+ content,
182
+ className: options?.className ?? "fmcp-csv-table",
183
+ pageSize
184
+ });
185
+ }
186
+ };
187
+ var csvRenderer = new CsvRenderer();
188
+ export {
189
+ CsvRenderer,
190
+ csvRenderer,
191
+ detectDelimiter,
192
+ parseCsv
193
+ };
@@ -0,0 +1,259 @@
1
+ // libs/ui/src/renderer/flow/index.ts
2
+ import React, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
3
+ import Box from "@mui/material/Box";
4
+ import Alert from "@mui/material/Alert";
5
+ import Typography from "@mui/material/Typography";
6
+ import { styled } from "@mui/material/styles";
7
+
8
+ // libs/ui/src/renderer/common/lazy-import.ts
9
+ var ESM_SH_BASE = "https://esm.sh/";
10
+ function esmShUrl(pkg, options) {
11
+ let url = `${ESM_SH_BASE}${pkg}`;
12
+ if (options?.external?.length) {
13
+ url += `?external=${options.external.join(",")}`;
14
+ }
15
+ return url;
16
+ }
17
+ function runtimeImport(specifier) {
18
+ const dynamicImport = new Function("s", "return import(s)");
19
+ return dynamicImport(specifier);
20
+ }
21
+ async function runtimeImportWithFallback(bareSpecifier, fallbackUrl) {
22
+ try {
23
+ return await runtimeImport(bareSpecifier);
24
+ } catch {
25
+ return runtimeImport(fallbackUrl);
26
+ }
27
+ }
28
+ function createLazyImport(moduleId, importer) {
29
+ let state = { status: "idle" };
30
+ const doImport = importer ?? (async () => {
31
+ const mod = await runtimeImport(moduleId);
32
+ return mod["default"] ?? mod;
33
+ });
34
+ return {
35
+ load() {
36
+ if (state.status === "loaded") return Promise.resolve(state.module);
37
+ if (state.status === "loading") return state.promise;
38
+ if (state.status === "error") {
39
+ state = { status: "idle" };
40
+ }
41
+ const promise = doImport().then(
42
+ (mod) => {
43
+ state = { status: "loaded", module: mod };
44
+ return mod;
45
+ },
46
+ (err) => {
47
+ const error = err instanceof Error ? err : new Error(`Failed to load module "${moduleId}": ${String(err)}`);
48
+ state = { status: "error", error };
49
+ throw error;
50
+ }
51
+ );
52
+ state = { status: "loading", promise };
53
+ return promise;
54
+ },
55
+ get() {
56
+ return state.status === "loaded" ? state.module : void 0;
57
+ },
58
+ getState() {
59
+ return state;
60
+ },
61
+ reset() {
62
+ state = { status: "idle" };
63
+ }
64
+ };
65
+ }
66
+
67
+ // libs/ui/src/renderer/common/inject-stylesheet.ts
68
+ function injectStylesheet(href, id) {
69
+ if (typeof document === "undefined") return;
70
+ if (document.getElementById(id)) return;
71
+ const link = document.createElement("link");
72
+ link.id = id;
73
+ link.rel = "stylesheet";
74
+ link.href = href;
75
+ link.crossOrigin = "anonymous";
76
+ document.head.appendChild(link);
77
+ }
78
+
79
+ // libs/ui/src/renderer/common/use-renderer-theme.ts
80
+ import { useMemo } from "react";
81
+ import { useTheme } from "@mui/material/styles";
82
+ function extractThemeValues(theme) {
83
+ const palette = theme.palette;
84
+ return {
85
+ mode: palette.mode,
86
+ primary: palette.primary.main,
87
+ secondary: palette.secondary.main,
88
+ error: palette.error.main,
89
+ warning: palette.warning.main,
90
+ success: palette.success.main,
91
+ info: palette.info.main,
92
+ background: palette.background.default,
93
+ paper: palette.background.paper,
94
+ textPrimary: palette.text.primary,
95
+ textSecondary: palette.text.secondary,
96
+ divider: palette.divider,
97
+ fontFamily: theme.typography.fontFamily ?? "sans-serif",
98
+ monoFontFamily: theme.typography["monoFontFamily"] ?? '"SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", monospace',
99
+ fontSize: theme.typography.fontSize ?? 14,
100
+ borderRadius: typeof theme.shape.borderRadius === "number" ? theme.shape.borderRadius : 4,
101
+ seriesColors: [
102
+ palette.primary.main,
103
+ palette.secondary.main,
104
+ palette.error.main,
105
+ palette.warning.main,
106
+ palette.success.main,
107
+ palette.info.main
108
+ ]
109
+ };
110
+ }
111
+ function useRendererTheme() {
112
+ const theme = useTheme();
113
+ return useMemo(() => extractThemeValues(theme), [theme]);
114
+ }
115
+
116
+ // libs/ui/src/renderer/common/use-lazy-module.ts
117
+ import { useState, useEffect } from "react";
118
+ function useLazyModule(lazy) {
119
+ const [, forceUpdate] = useState(0);
120
+ useEffect(() => {
121
+ if (lazy.getState().status === "loaded") {
122
+ forceUpdate((n) => n + 1);
123
+ return;
124
+ }
125
+ lazy.load().then(
126
+ () => forceUpdate((n) => n + 1),
127
+ () => forceUpdate((n) => n + 1)
128
+ );
129
+ }, [lazy]);
130
+ return lazy.get();
131
+ }
132
+
133
+ // libs/ui/src/renderer/flow/index.ts
134
+ var XYFLOW_CSS_URL = "https://esm.sh/@xyflow/react@12/dist/style.css";
135
+ var XYFLOW_CSS_ID = "fmcp-xyflow-css";
136
+ function isFlow(content) {
137
+ const trimmed = content.trim();
138
+ if (trimmed.charCodeAt(0) !== 123) return false;
139
+ return trimmed.includes('"nodes"') && trimmed.includes('"edges"');
140
+ }
141
+ var lazyXYFlow = createLazyImport("@xyflow/react", async () => {
142
+ const mod = await runtimeImportWithFallback(
143
+ "@xyflow/react",
144
+ esmShUrl("@xyflow/react@12", { external: ["react", "react-dom"] })
145
+ );
146
+ return mod;
147
+ });
148
+ var FlowRoot = styled(Box, {
149
+ name: "FrontMcpFlow",
150
+ slot: "Root"
151
+ })(({ theme }) => ({
152
+ width: "100%",
153
+ borderRadius: theme.shape.borderRadius,
154
+ overflow: "hidden",
155
+ border: `1px solid ${theme.palette.divider}`
156
+ }));
157
+ function FlowView({ config, className }) {
158
+ useEffect2(() => {
159
+ injectStylesheet(XYFLOW_CSS_URL, XYFLOW_CSS_ID);
160
+ }, []);
161
+ const themeValues = useRendererTheme();
162
+ const xyflow = useLazyModule(lazyXYFlow);
163
+ const height = config.height ?? 500;
164
+ const styledNodes = useMemo2(() => {
165
+ return config.nodes.map((node) => ({
166
+ ...node,
167
+ style: {
168
+ background: themeValues.paper,
169
+ color: themeValues.textPrimary,
170
+ border: `1px solid ${themeValues.divider}`,
171
+ borderRadius: themeValues.borderRadius,
172
+ padding: 8,
173
+ fontSize: themeValues.fontSize,
174
+ fontFamily: themeValues.fontFamily,
175
+ ...node.style
176
+ }
177
+ }));
178
+ }, [config.nodes, themeValues]);
179
+ const styledEdges = useMemo2(() => {
180
+ return config.edges.map((edge, i) => ({
181
+ ...edge,
182
+ style: {
183
+ stroke: themeValues.seriesColors[i % themeValues.seriesColors.length],
184
+ strokeWidth: 2,
185
+ ...edge.style
186
+ }
187
+ }));
188
+ }, [config.edges, themeValues]);
189
+ if (!xyflow) {
190
+ return React.createElement(Alert, { severity: "info" }, "Loading flow diagram library...");
191
+ }
192
+ const { ReactFlow, Controls, MiniMap, Background } = xyflow;
193
+ return React.createElement(
194
+ FlowRoot,
195
+ { className },
196
+ config.title && React.createElement(
197
+ Typography,
198
+ { variant: "subtitle1", fontWeight: 600, sx: { p: 1.5, borderBottom: 1, borderColor: "divider" } },
199
+ config.title
200
+ ),
201
+ React.createElement(
202
+ Box,
203
+ { sx: { height } },
204
+ React.createElement(
205
+ ReactFlow,
206
+ {
207
+ nodes: styledNodes,
208
+ edges: styledEdges,
209
+ fitView: config.fitView !== false,
210
+ proOptions: { hideAttribution: true }
211
+ },
212
+ React.createElement(Controls, {
213
+ style: {
214
+ backgroundColor: themeValues.paper,
215
+ borderRadius: themeValues.borderRadius,
216
+ border: `1px solid ${themeValues.divider}`
217
+ }
218
+ }),
219
+ React.createElement(MiniMap, {
220
+ style: {
221
+ backgroundColor: themeValues.background,
222
+ borderRadius: themeValues.borderRadius
223
+ },
224
+ nodeColor: themeValues.primary
225
+ }),
226
+ Background && React.createElement(Background, {
227
+ color: themeValues.divider,
228
+ gap: 16
229
+ })
230
+ )
231
+ )
232
+ );
233
+ }
234
+ lazyXYFlow.load().catch(() => {
235
+ });
236
+ var FlowRenderer = class {
237
+ type = "flow";
238
+ priority = 70;
239
+ canHandle(content) {
240
+ return isFlow(content);
241
+ }
242
+ render(content, options) {
243
+ try {
244
+ const config = JSON.parse(content);
245
+ return React.createElement(FlowView, {
246
+ config,
247
+ className: options?.className ?? "fmcp-flow-content"
248
+ });
249
+ } catch {
250
+ return React.createElement(Alert, { severity: "error" }, "Invalid flow JSON");
251
+ }
252
+ }
253
+ };
254
+ var flowRenderer = new FlowRenderer();
255
+ export {
256
+ FlowRenderer,
257
+ flowRenderer,
258
+ isFlow
259
+ };
@@ -0,0 +1,99 @@
1
+ // libs/ui/src/renderer/html/index.ts
2
+ import React, { useMemo, useState, useEffect } from "react";
3
+ import Box from "@mui/material/Box";
4
+ import { styled } from "@mui/material/styles";
5
+
6
+ // libs/ui/src/renderer/common/lazy-import.ts
7
+ var ESM_SH_BASE = "https://esm.sh/";
8
+ function esmShUrl(pkg, options) {
9
+ let url = `${ESM_SH_BASE}${pkg}`;
10
+ if (options?.external?.length) {
11
+ url += `?external=${options.external.join(",")}`;
12
+ }
13
+ return url;
14
+ }
15
+ function runtimeImport(specifier) {
16
+ const dynamicImport = new Function("s", "return import(s)");
17
+ return dynamicImport(specifier);
18
+ }
19
+ async function runtimeImportWithFallback(bareSpecifier, fallbackUrl) {
20
+ try {
21
+ return await runtimeImport(bareSpecifier);
22
+ } catch {
23
+ return runtimeImport(fallbackUrl);
24
+ }
25
+ }
26
+
27
+ // libs/ui/src/renderer/html/index.ts
28
+ var HtmlRoot = styled(Box, {
29
+ name: "FrontMcpHtml",
30
+ slot: "Root"
31
+ })(({ theme }) => ({
32
+ "& a": { color: theme.palette.primary.main },
33
+ "& table": { borderCollapse: "collapse", width: "100%" },
34
+ "& th, & td": { border: `1px solid ${theme.palette.divider}`, padding: theme.spacing(1) },
35
+ "& pre": {
36
+ backgroundColor: theme.palette.mode === "dark" ? theme.palette.grey[900] : theme.palette.grey[100],
37
+ padding: theme.spacing(1.5),
38
+ borderRadius: theme.shape.borderRadius,
39
+ overflow: "auto"
40
+ }
41
+ }));
42
+ var purifyModule = null;
43
+ var purifyPromise = null;
44
+ function loadDOMPurify() {
45
+ if (purifyModule) return Promise.resolve(purifyModule);
46
+ if (purifyPromise) return purifyPromise;
47
+ purifyPromise = runtimeImportWithFallback("dompurify", esmShUrl("dompurify@3")).then((mod) => {
48
+ purifyModule = mod;
49
+ return purifyModule;
50
+ }).catch(() => {
51
+ purifyModule = null;
52
+ purifyPromise = null;
53
+ return null;
54
+ });
55
+ return purifyPromise;
56
+ }
57
+ function escapeHtml(html) {
58
+ return html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
59
+ }
60
+ function sanitizeSync(html) {
61
+ if (!purifyModule) return escapeHtml(html);
62
+ const sanitize = purifyModule.default?.sanitize ?? purifyModule.sanitize;
63
+ return sanitize ? sanitize(html) : escapeHtml(html);
64
+ }
65
+ loadDOMPurify();
66
+ function HtmlView({ html, className }) {
67
+ const [purifyReady, setPurifyReady] = useState(!!purifyModule);
68
+ useEffect(() => {
69
+ if (!purifyModule) {
70
+ loadDOMPurify().then((mod) => {
71
+ if (mod) setPurifyReady(true);
72
+ });
73
+ }
74
+ }, []);
75
+ const sanitized = useMemo(() => sanitizeSync(html), [html, purifyReady]);
76
+ return React.createElement(HtmlRoot, {
77
+ className,
78
+ dangerouslySetInnerHTML: { __html: sanitized }
79
+ });
80
+ }
81
+ var HtmlRenderer = class {
82
+ type = "html";
83
+ priority = 0;
84
+ canHandle(content) {
85
+ return /^\s*</.test(content) && /<\/\w+>/.test(content);
86
+ }
87
+ render(content, options) {
88
+ return React.createElement(HtmlView, {
89
+ html: content,
90
+ className: options?.className ?? "fmcp-html-content"
91
+ });
92
+ }
93
+ };
94
+ var htmlRenderer = new HtmlRenderer();
95
+ export {
96
+ HtmlRenderer,
97
+ escapeHtml,
98
+ htmlRenderer
99
+ };