@frontmcp/uipack 0.6.1 → 0.6.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.
- package/CLAUDE.md +88 -105
- package/README.md +1 -0
- package/adapters/index.d.ts +1 -1
- package/adapters/index.d.ts.map +1 -1
- package/adapters/index.js +35 -2
- package/adapters/platform-meta.d.ts +29 -0
- package/adapters/platform-meta.d.ts.map +1 -1
- package/base-template/default-base-template.d.ts +0 -1
- package/base-template/default-base-template.d.ts.map +1 -1
- package/base-template/index.js +32 -37
- package/build/builders/base-builder.d.ts +122 -0
- package/build/builders/base-builder.d.ts.map +1 -0
- package/build/builders/esbuild-config.d.ts +94 -0
- package/build/builders/esbuild-config.d.ts.map +1 -0
- package/build/builders/hybrid-builder.d.ts +93 -0
- package/build/builders/hybrid-builder.d.ts.map +1 -0
- package/build/builders/index.d.ts +17 -0
- package/build/builders/index.d.ts.map +1 -0
- package/build/builders/inline-builder.d.ts +83 -0
- package/build/builders/inline-builder.d.ts.map +1 -0
- package/build/builders/static-builder.d.ts +78 -0
- package/build/builders/static-builder.d.ts.map +1 -0
- package/build/builders/types.d.ts +341 -0
- package/build/builders/types.d.ts.map +1 -0
- package/build/cdn-resources.d.ts +3 -2
- package/build/cdn-resources.d.ts.map +1 -1
- package/build/hybrid-data.d.ts +127 -0
- package/build/hybrid-data.d.ts.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1885 -171
- package/build/ui-components-browser.d.ts +64 -0
- package/build/ui-components-browser.d.ts.map +1 -0
- package/build/widget-manifest.d.ts.map +1 -1
- package/bundler/file-cache/component-builder.d.ts.map +1 -1
- package/bundler/file-cache/storage/redis.d.ts.map +1 -1
- package/bundler/index.js +6 -4
- package/dependency/cdn-registry.d.ts +1 -1
- package/dependency/cdn-registry.d.ts.map +1 -1
- package/dependency/import-map.d.ts.map +1 -1
- package/dependency/index.js +93 -121
- package/dependency/resolver.d.ts.map +1 -1
- package/esm/adapters/{index.js → index.mjs} +34 -2
- package/esm/base-template/{index.js → index.mjs} +32 -37
- package/esm/build/{index.js → index.mjs} +1855 -170
- package/esm/bundler/{index.js → index.mjs} +6 -4
- package/esm/dependency/{index.js → index.mjs} +93 -121
- package/esm/handlebars/{index.js → index.mjs} +0 -1
- package/esm/{index.js → index.mjs} +2516 -830
- package/esm/package.json +7 -6
- package/esm/registry/{index.js → index.mjs} +196 -264
- package/esm/renderers/{index.js → index.mjs} +106 -200
- package/esm/runtime/{index.js → index.mjs} +44 -35
- package/esm/styles/{index.js → index.mjs} +6 -6
- package/esm/theme/{index.js → index.mjs} +90 -42
- package/esm/tool-template/{index.js → index.mjs} +35 -28
- package/esm/typings/{index.js → index.mjs} +157 -1
- package/esm/utils/{index.js → index.mjs} +24 -0
- package/esm/validation/{index.js → index.mjs} +0 -1
- package/handlebars/expression-extractor.d.ts.map +1 -1
- package/handlebars/index.d.ts.map +1 -1
- package/handlebars/index.js +0 -1
- package/index.d.ts +2 -1
- package/index.d.ts.map +1 -1
- package/index.js +2545 -835
- package/package.json +7 -6
- package/preview/claude-preview.d.ts +67 -0
- package/preview/claude-preview.d.ts.map +1 -0
- package/preview/generic-preview.d.ts +67 -0
- package/preview/generic-preview.d.ts.map +1 -0
- package/preview/index.d.ts +36 -0
- package/preview/index.d.ts.map +1 -0
- package/preview/openai-preview.d.ts +70 -0
- package/preview/openai-preview.d.ts.map +1 -0
- package/preview/types.d.ts +185 -0
- package/preview/types.d.ts.map +1 -0
- package/registry/index.js +196 -264
- package/registry/render-template.d.ts.map +1 -1
- package/renderers/index.d.ts +2 -2
- package/renderers/index.d.ts.map +1 -1
- package/renderers/index.js +110 -204
- package/renderers/mdx-client.renderer.d.ts +124 -0
- package/renderers/mdx-client.renderer.d.ts.map +1 -0
- package/renderers/registry.d.ts +2 -2
- package/renderers/registry.d.ts.map +1 -1
- package/renderers/types.d.ts +3 -2
- package/renderers/types.d.ts.map +1 -1
- package/renderers/utils/transpiler.d.ts +8 -27
- package/renderers/utils/transpiler.d.ts.map +1 -1
- package/runtime/index.js +44 -35
- package/runtime/mcp-bridge.d.ts.map +1 -1
- package/runtime/renderer-runtime.d.ts.map +1 -1
- package/runtime/wrapper.d.ts.map +1 -1
- package/styles/index.js +6 -6
- package/styles/variants.d.ts +1 -1
- package/styles/variants.d.ts.map +1 -1
- package/theme/cdn.d.ts.map +1 -1
- package/theme/css-to-theme.d.ts +91 -0
- package/theme/css-to-theme.d.ts.map +1 -0
- package/theme/index.d.ts +2 -1
- package/theme/index.d.ts.map +1 -1
- package/theme/index.js +92 -43
- package/theme/platforms.d.ts +1 -6
- package/theme/platforms.d.ts.map +1 -1
- package/theme/theme.d.ts.map +1 -1
- package/tool-template/builder.d.ts.map +1 -1
- package/tool-template/index.js +35 -28
- package/typings/index.d.ts +4 -4
- package/typings/index.d.ts.map +1 -1
- package/typings/index.js +162 -1
- package/typings/schemas.d.ts +30 -0
- package/typings/schemas.d.ts.map +1 -1
- package/typings/type-fetcher.d.ts +74 -1
- package/typings/type-fetcher.d.ts.map +1 -1
- package/typings/types.d.ts +72 -1
- package/typings/types.d.ts.map +1 -1
- package/utils/escape-html.d.ts +44 -0
- package/utils/escape-html.d.ts.map +1 -1
- package/utils/index.d.ts +1 -1
- package/utils/index.d.ts.map +1 -1
- package/utils/index.js +26 -0
- package/validation/index.js +0 -1
- package/validation/template-validator.d.ts.map +1 -1
- package/esm/adapters/index.d.ts +0 -13
- package/esm/adapters/index.d.ts.map +0 -1
- package/esm/adapters/platform-meta.d.ts +0 -166
- package/esm/adapters/platform-meta.d.ts.map +0 -1
- package/esm/adapters/response-builder.d.ts +0 -108
- package/esm/adapters/response-builder.d.ts.map +0 -1
- package/esm/adapters/serving-mode.d.ts +0 -107
- package/esm/adapters/serving-mode.d.ts.map +0 -1
- package/esm/base-template/bridge.d.ts +0 -90
- package/esm/base-template/bridge.d.ts.map +0 -1
- package/esm/base-template/default-base-template.d.ts +0 -92
- package/esm/base-template/default-base-template.d.ts.map +0 -1
- package/esm/base-template/index.d.ts +0 -15
- package/esm/base-template/index.d.ts.map +0 -1
- package/esm/base-template/polyfills.d.ts +0 -31
- package/esm/base-template/polyfills.d.ts.map +0 -1
- package/esm/base-template/theme-styles.d.ts +0 -74
- package/esm/base-template/theme-styles.d.ts.map +0 -1
- package/esm/bridge-runtime/iife-generator.d.ts +0 -62
- package/esm/bridge-runtime/iife-generator.d.ts.map +0 -1
- package/esm/bridge-runtime/index.d.ts +0 -10
- package/esm/bridge-runtime/index.d.ts.map +0 -1
- package/esm/build/cdn-resources.d.ts +0 -243
- package/esm/build/cdn-resources.d.ts.map +0 -1
- package/esm/build/index.d.ts +0 -295
- package/esm/build/index.d.ts.map +0 -1
- package/esm/build/widget-manifest.d.ts +0 -362
- package/esm/build/widget-manifest.d.ts.map +0 -1
- package/esm/bundler/cache.d.ts +0 -173
- package/esm/bundler/cache.d.ts.map +0 -1
- package/esm/bundler/file-cache/component-builder.d.ts +0 -167
- package/esm/bundler/file-cache/component-builder.d.ts.map +0 -1
- package/esm/bundler/file-cache/hash-calculator.d.ts +0 -155
- package/esm/bundler/file-cache/hash-calculator.d.ts.map +0 -1
- package/esm/bundler/file-cache/index.d.ts +0 -12
- package/esm/bundler/file-cache/index.d.ts.map +0 -1
- package/esm/bundler/file-cache/storage/filesystem.d.ts +0 -149
- package/esm/bundler/file-cache/storage/filesystem.d.ts.map +0 -1
- package/esm/bundler/file-cache/storage/index.d.ts +0 -11
- package/esm/bundler/file-cache/storage/index.d.ts.map +0 -1
- package/esm/bundler/file-cache/storage/interface.d.ts +0 -152
- package/esm/bundler/file-cache/storage/interface.d.ts.map +0 -1
- package/esm/bundler/file-cache/storage/redis.d.ts +0 -139
- package/esm/bundler/file-cache/storage/redis.d.ts.map +0 -1
- package/esm/bundler/index.d.ts +0 -35
- package/esm/bundler/index.d.ts.map +0 -1
- package/esm/bundler/sandbox/enclave-adapter.d.ts +0 -121
- package/esm/bundler/sandbox/enclave-adapter.d.ts.map +0 -1
- package/esm/bundler/sandbox/executor.d.ts +0 -14
- package/esm/bundler/sandbox/executor.d.ts.map +0 -1
- package/esm/bundler/sandbox/policy.d.ts +0 -62
- package/esm/bundler/sandbox/policy.d.ts.map +0 -1
- package/esm/bundler/types.d.ts +0 -702
- package/esm/bundler/types.d.ts.map +0 -1
- package/esm/dependency/cdn-registry.d.ts +0 -98
- package/esm/dependency/cdn-registry.d.ts.map +0 -1
- package/esm/dependency/import-map.d.ts +0 -186
- package/esm/dependency/import-map.d.ts.map +0 -1
- package/esm/dependency/import-parser.d.ts +0 -82
- package/esm/dependency/import-parser.d.ts.map +0 -1
- package/esm/dependency/index.d.ts +0 -17
- package/esm/dependency/index.d.ts.map +0 -1
- package/esm/dependency/resolver.d.ts +0 -164
- package/esm/dependency/resolver.d.ts.map +0 -1
- package/esm/dependency/schemas.d.ts +0 -486
- package/esm/dependency/schemas.d.ts.map +0 -1
- package/esm/dependency/template-loader.d.ts +0 -204
- package/esm/dependency/template-loader.d.ts.map +0 -1
- package/esm/dependency/template-processor.d.ts +0 -118
- package/esm/dependency/template-processor.d.ts.map +0 -1
- package/esm/dependency/types.d.ts +0 -739
- package/esm/dependency/types.d.ts.map +0 -1
- package/esm/handlebars/expression-extractor.d.ts +0 -147
- package/esm/handlebars/expression-extractor.d.ts.map +0 -1
- package/esm/handlebars/helpers.d.ts +0 -339
- package/esm/handlebars/helpers.d.ts.map +0 -1
- package/esm/handlebars/index.d.ts +0 -195
- package/esm/handlebars/index.d.ts.map +0 -1
- package/esm/index.d.ts +0 -50
- package/esm/index.d.ts.map +0 -1
- package/esm/registry/index.d.ts +0 -46
- package/esm/registry/index.d.ts.map +0 -1
- package/esm/registry/render-template.d.ts +0 -91
- package/esm/registry/render-template.d.ts.map +0 -1
- package/esm/registry/tool-ui.registry.d.ts +0 -294
- package/esm/registry/tool-ui.registry.d.ts.map +0 -1
- package/esm/registry/uri-utils.d.ts +0 -56
- package/esm/registry/uri-utils.d.ts.map +0 -1
- package/esm/renderers/cache.d.ts +0 -145
- package/esm/renderers/cache.d.ts.map +0 -1
- package/esm/renderers/html.renderer.d.ts +0 -123
- package/esm/renderers/html.renderer.d.ts.map +0 -1
- package/esm/renderers/index.d.ts +0 -36
- package/esm/renderers/index.d.ts.map +0 -1
- package/esm/renderers/mdx.renderer.d.ts +0 -120
- package/esm/renderers/mdx.renderer.d.ts.map +0 -1
- package/esm/renderers/registry.d.ts +0 -133
- package/esm/renderers/registry.d.ts.map +0 -1
- package/esm/renderers/types.d.ts +0 -342
- package/esm/renderers/types.d.ts.map +0 -1
- package/esm/renderers/utils/detect.d.ts +0 -107
- package/esm/renderers/utils/detect.d.ts.map +0 -1
- package/esm/renderers/utils/hash.d.ts +0 -40
- package/esm/renderers/utils/hash.d.ts.map +0 -1
- package/esm/renderers/utils/index.d.ts +0 -9
- package/esm/renderers/utils/index.d.ts.map +0 -1
- package/esm/renderers/utils/transpiler.d.ts +0 -89
- package/esm/renderers/utils/transpiler.d.ts.map +0 -1
- package/esm/runtime/adapters/html.adapter.d.ts +0 -59
- package/esm/runtime/adapters/html.adapter.d.ts.map +0 -1
- package/esm/runtime/adapters/index.d.ts +0 -26
- package/esm/runtime/adapters/index.d.ts.map +0 -1
- package/esm/runtime/adapters/mdx.adapter.d.ts +0 -73
- package/esm/runtime/adapters/mdx.adapter.d.ts.map +0 -1
- package/esm/runtime/adapters/types.d.ts +0 -95
- package/esm/runtime/adapters/types.d.ts.map +0 -1
- package/esm/runtime/csp.d.ts +0 -48
- package/esm/runtime/csp.d.ts.map +0 -1
- package/esm/runtime/index.d.ts +0 -17
- package/esm/runtime/index.d.ts.map +0 -1
- package/esm/runtime/mcp-bridge.d.ts +0 -101
- package/esm/runtime/mcp-bridge.d.ts.map +0 -1
- package/esm/runtime/renderer-runtime.d.ts +0 -133
- package/esm/runtime/renderer-runtime.d.ts.map +0 -1
- package/esm/runtime/sanitizer.d.ts +0 -172
- package/esm/runtime/sanitizer.d.ts.map +0 -1
- package/esm/runtime/types.d.ts +0 -415
- package/esm/runtime/types.d.ts.map +0 -1
- package/esm/runtime/wrapper.d.ts +0 -421
- package/esm/runtime/wrapper.d.ts.map +0 -1
- package/esm/styles/index.d.ts +0 -8
- package/esm/styles/index.d.ts.map +0 -1
- package/esm/styles/variants.d.ts +0 -51
- package/esm/styles/variants.d.ts.map +0 -1
- package/esm/theme/cdn.d.ts +0 -195
- package/esm/theme/cdn.d.ts.map +0 -1
- package/esm/theme/index.d.ts +0 -18
- package/esm/theme/index.d.ts.map +0 -1
- package/esm/theme/platforms.d.ts +0 -107
- package/esm/theme/platforms.d.ts.map +0 -1
- package/esm/theme/presets/github-openai.d.ts +0 -50
- package/esm/theme/presets/github-openai.d.ts.map +0 -1
- package/esm/theme/presets/index.d.ts +0 -11
- package/esm/theme/presets/index.d.ts.map +0 -1
- package/esm/theme/theme.d.ts +0 -396
- package/esm/theme/theme.d.ts.map +0 -1
- package/esm/tool-template/builder.d.ts +0 -213
- package/esm/tool-template/builder.d.ts.map +0 -1
- package/esm/tool-template/index.d.ts +0 -16
- package/esm/tool-template/index.d.ts.map +0 -1
- package/esm/types/index.d.ts +0 -14
- package/esm/types/index.d.ts.map +0 -1
- package/esm/types/ui-config.d.ts +0 -641
- package/esm/types/ui-config.d.ts.map +0 -1
- package/esm/types/ui-runtime.d.ts +0 -1008
- package/esm/types/ui-runtime.d.ts.map +0 -1
- package/esm/typings/cache/cache-adapter.d.ts +0 -125
- package/esm/typings/cache/cache-adapter.d.ts.map +0 -1
- package/esm/typings/cache/index.d.ts +0 -10
- package/esm/typings/cache/index.d.ts.map +0 -1
- package/esm/typings/cache/memory-cache.d.ts +0 -92
- package/esm/typings/cache/memory-cache.d.ts.map +0 -1
- package/esm/typings/dts-parser.d.ts +0 -90
- package/esm/typings/dts-parser.d.ts.map +0 -1
- package/esm/typings/index.d.ts +0 -48
- package/esm/typings/index.d.ts.map +0 -1
- package/esm/typings/schemas.d.ts +0 -232
- package/esm/typings/schemas.d.ts.map +0 -1
- package/esm/typings/type-fetcher.d.ts +0 -89
- package/esm/typings/type-fetcher.d.ts.map +0 -1
- package/esm/typings/types.d.ts +0 -320
- package/esm/typings/types.d.ts.map +0 -1
- package/esm/utils/escape-html.d.ts +0 -58
- package/esm/utils/escape-html.d.ts.map +0 -1
- package/esm/utils/index.d.ts +0 -10
- package/esm/utils/index.d.ts.map +0 -1
- package/esm/utils/safe-stringify.d.ts +0 -30
- package/esm/utils/safe-stringify.d.ts.map +0 -1
- package/esm/validation/error-box.d.ts +0 -56
- package/esm/validation/error-box.d.ts.map +0 -1
- package/esm/validation/index.d.ts +0 -13
- package/esm/validation/index.d.ts.map +0 -1
- package/esm/validation/schema-paths.d.ts +0 -118
- package/esm/validation/schema-paths.d.ts.map +0 -1
- package/esm/validation/template-validator.d.ts +0 -143
- package/esm/validation/template-validator.d.ts.map +0 -1
- package/esm/validation/wrapper.d.ts +0 -97
- package/esm/validation/wrapper.d.ts.map +0 -1
- package/renderers/mdx.renderer.d.ts +0 -120
- package/renderers/mdx.renderer.d.ts.map +0 -1
- /package/esm/bridge-runtime/{index.js → index.mjs} +0 -0
- /package/esm/types/{index.js → index.mjs} +0 -0
|
@@ -8,13 +8,6 @@ var __export = (target, all) => {
|
|
|
8
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
// libs/uipack/src/utils/safe-stringify.ts
|
|
12
|
-
var init_safe_stringify = __esm({
|
|
13
|
-
"libs/uipack/src/utils/safe-stringify.ts"() {
|
|
14
|
-
"use strict";
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
|
|
18
11
|
// libs/uipack/src/utils/escape-html.ts
|
|
19
12
|
function escapeHtml(str) {
|
|
20
13
|
if (str === null || str === void 0) {
|
|
@@ -26,6 +19,12 @@ function escapeHtml(str) {
|
|
|
26
19
|
function escapeHtmlAttr(str) {
|
|
27
20
|
return str.replace(/&/g, "&").replace(/"/g, """);
|
|
28
21
|
}
|
|
22
|
+
function escapeJsString(str) {
|
|
23
|
+
return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
24
|
+
}
|
|
25
|
+
function escapeScriptClose(jsonString) {
|
|
26
|
+
return jsonString.replace(/<\//g, "<\\/");
|
|
27
|
+
}
|
|
29
28
|
var init_escape_html = __esm({
|
|
30
29
|
"libs/uipack/src/utils/escape-html.ts"() {
|
|
31
30
|
"use strict";
|
|
@@ -36,7 +35,6 @@ var init_escape_html = __esm({
|
|
|
36
35
|
var init_utils = __esm({
|
|
37
36
|
"libs/uipack/src/utils/index.ts"() {
|
|
38
37
|
"use strict";
|
|
39
|
-
init_safe_stringify();
|
|
40
38
|
init_escape_html();
|
|
41
39
|
}
|
|
42
40
|
});
|
|
@@ -267,7 +265,6 @@ var init_helpers = __esm({
|
|
|
267
265
|
// libs/uipack/src/handlebars/expression-extractor.ts
|
|
268
266
|
function extractExpressions(template) {
|
|
269
267
|
const expressions = [];
|
|
270
|
-
const lines = template.split("\n");
|
|
271
268
|
const positionMap = buildPositionMap(template);
|
|
272
269
|
let match;
|
|
273
270
|
EXPRESSION_REGEX.lastIndex = 0;
|
|
@@ -666,7 +663,7 @@ async function calculateComponentHash(options) {
|
|
|
666
663
|
const {
|
|
667
664
|
entryPath,
|
|
668
665
|
baseDir = dirname(entryPath),
|
|
669
|
-
externals = [],
|
|
666
|
+
externals: _externals = [],
|
|
670
667
|
dependencies = {},
|
|
671
668
|
bundleOptions = {},
|
|
672
669
|
maxDepth = 10
|
|
@@ -793,7 +790,7 @@ function getPackagePeerDependencies(packageName, registry = DEFAULT_CDN_REGISTRY
|
|
|
793
790
|
}
|
|
794
791
|
return [];
|
|
795
792
|
}
|
|
796
|
-
function resolveAllDependencies(packageNames,
|
|
793
|
+
function resolveAllDependencies(packageNames, _platform = "unknown", registry = DEFAULT_CDN_REGISTRY) {
|
|
797
794
|
const resolved = /* @__PURE__ */ new Set();
|
|
798
795
|
const queue = [...packageNames];
|
|
799
796
|
while (queue.length > 0) {
|
|
@@ -2708,8 +2705,10 @@ var init_component_builder = __esm({
|
|
|
2708
2705
|
return void 0;
|
|
2709
2706
|
}
|
|
2710
2707
|
try {
|
|
2711
|
-
const
|
|
2712
|
-
const
|
|
2708
|
+
const reactPkg = "react";
|
|
2709
|
+
const reactDomServerPkg = "react-dom/server";
|
|
2710
|
+
const React = await import(reactPkg);
|
|
2711
|
+
const ReactDOMServer = await import(reactDomServerPkg);
|
|
2713
2712
|
const exports = {};
|
|
2714
2713
|
const module = { exports };
|
|
2715
2714
|
if (executeCode) {
|
|
@@ -3582,9 +3581,6 @@ var BRIDGE_SCRIPT_TAGS = {
|
|
|
3582
3581
|
gemini: `<script>${generatePlatformBundle("gemini")}</script>`
|
|
3583
3582
|
};
|
|
3584
3583
|
|
|
3585
|
-
// libs/uipack/src/runtime/mcp-bridge.ts
|
|
3586
|
-
var FRONTMCP_BRIDGE_RUNTIME = BRIDGE_SCRIPT_TAGS.universal;
|
|
3587
|
-
|
|
3588
3584
|
// libs/uipack/src/runtime/csp.ts
|
|
3589
3585
|
var DEFAULT_CDN_DOMAINS = [
|
|
3590
3586
|
"https://cdn.jsdelivr.net",
|
|
@@ -3707,9 +3703,6 @@ var scriptCache = /* @__PURE__ */ new Map();
|
|
|
3707
3703
|
function getCachedScript(url) {
|
|
3708
3704
|
return scriptCache.get(url);
|
|
3709
3705
|
}
|
|
3710
|
-
function isScriptCached(url) {
|
|
3711
|
-
return scriptCache.has(url);
|
|
3712
|
-
}
|
|
3713
3706
|
function buildFontPreconnect() {
|
|
3714
3707
|
return CDN.fonts.preconnect.map((url, i) => `<link rel="preconnect" href="${url}"${i > 0 ? " crossorigin" : ""}>`).join("\n ");
|
|
3715
3708
|
}
|
|
@@ -3742,8 +3735,9 @@ function buildCdnScripts(options = {}) {
|
|
|
3742
3735
|
const scripts = [];
|
|
3743
3736
|
if (inline) {
|
|
3744
3737
|
if (tailwind) {
|
|
3745
|
-
|
|
3746
|
-
|
|
3738
|
+
const cached = getCachedScript(CDN.tailwind);
|
|
3739
|
+
if (cached) {
|
|
3740
|
+
scripts.push(buildInlineScriptTag(cached));
|
|
3747
3741
|
} else {
|
|
3748
3742
|
console.warn(
|
|
3749
3743
|
"[frontmcp/ui] Inline mode requested but Tailwind script not cached. Call fetchAndCacheScripts() first."
|
|
@@ -3751,8 +3745,9 @@ function buildCdnScripts(options = {}) {
|
|
|
3751
3745
|
}
|
|
3752
3746
|
}
|
|
3753
3747
|
if (htmx) {
|
|
3754
|
-
|
|
3755
|
-
|
|
3748
|
+
const cached = getCachedScript(CDN.htmx.url);
|
|
3749
|
+
if (cached) {
|
|
3750
|
+
scripts.push(buildInlineScriptTag(cached));
|
|
3756
3751
|
} else {
|
|
3757
3752
|
console.warn(
|
|
3758
3753
|
"[frontmcp/ui] Inline mode requested but HTMX script not cached. Call fetchAndCacheScripts() first."
|
|
@@ -3760,8 +3755,9 @@ function buildCdnScripts(options = {}) {
|
|
|
3760
3755
|
}
|
|
3761
3756
|
}
|
|
3762
3757
|
if (alpine) {
|
|
3763
|
-
|
|
3764
|
-
|
|
3758
|
+
const cached = getCachedScript(CDN.alpine.url);
|
|
3759
|
+
if (cached) {
|
|
3760
|
+
scripts.push(buildInlineScriptTag(cached));
|
|
3765
3761
|
} else {
|
|
3766
3762
|
console.warn(
|
|
3767
3763
|
"[frontmcp/ui] Inline mode requested but Alpine.js script not cached. Call fetchAndCacheScripts() first."
|
|
@@ -3769,8 +3765,9 @@ function buildCdnScripts(options = {}) {
|
|
|
3769
3765
|
}
|
|
3770
3766
|
}
|
|
3771
3767
|
if (icons) {
|
|
3772
|
-
|
|
3773
|
-
|
|
3768
|
+
const cached = getCachedScript(CDN.icons.url);
|
|
3769
|
+
if (cached) {
|
|
3770
|
+
scripts.push(buildInlineScriptTag(cached));
|
|
3774
3771
|
} else {
|
|
3775
3772
|
console.warn(
|
|
3776
3773
|
"[frontmcp/ui] Inline mode requested but Lucide icons script not cached. Call fetchAndCacheScripts() first."
|
|
@@ -3812,11 +3809,12 @@ var CLAUDE_PLATFORM = {
|
|
|
3812
3809
|
id: "claude",
|
|
3813
3810
|
name: "Claude (Artifacts)",
|
|
3814
3811
|
supportsWidgets: true,
|
|
3812
|
+
// Claude Artifacts support interactive widgets
|
|
3815
3813
|
supportsTailwind: true,
|
|
3816
3814
|
supportsHtmx: false,
|
|
3817
3815
|
// Network blocked, HTMX won't work for API calls
|
|
3818
|
-
networkMode: "
|
|
3819
|
-
scriptStrategy: "
|
|
3816
|
+
networkMode: "limited",
|
|
3817
|
+
scriptStrategy: "cdn",
|
|
3820
3818
|
maxInlineSize: 100 * 1024,
|
|
3821
3819
|
// 100KB limit for artifacts
|
|
3822
3820
|
cspRestrictions: ["script-src 'unsafe-inline'", "connect-src 'none'"],
|
|
@@ -4066,17 +4064,31 @@ function emitColorScale(lines, name, scale) {
|
|
|
4066
4064
|
if (value) lines.push(`--color-${name}-${shade}: ${value};`);
|
|
4067
4065
|
}
|
|
4068
4066
|
}
|
|
4067
|
+
var OPACITY_VARIANTS = [10, 20, 30, 50, 70, 90];
|
|
4068
|
+
function emitColorWithOpacityVariants(lines, name, value) {
|
|
4069
|
+
lines.push(`--color-${name}: ${value};`);
|
|
4070
|
+
for (const opacity of OPACITY_VARIANTS) {
|
|
4071
|
+
lines.push(`--color-${name}-${opacity}: color-mix(in oklch, ${value} ${opacity}%, transparent);`);
|
|
4072
|
+
}
|
|
4073
|
+
}
|
|
4074
|
+
function emitBrandColorWithVariants(lines, name, value) {
|
|
4075
|
+
lines.push(`--color-${name}: ${value};`);
|
|
4076
|
+
lines.push(`--color-${name}-hover: color-mix(in oklch, ${value} 85%, black);`);
|
|
4077
|
+
for (const opacity of OPACITY_VARIANTS) {
|
|
4078
|
+
lines.push(`--color-${name}-${opacity}: color-mix(in oklch, ${value} ${opacity}%, transparent);`);
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4069
4081
|
function buildThemeCss(theme) {
|
|
4070
4082
|
const lines = [];
|
|
4071
4083
|
const semantic = theme.colors.semantic;
|
|
4072
4084
|
if (typeof semantic.primary === "string") {
|
|
4073
|
-
lines
|
|
4085
|
+
emitBrandColorWithVariants(lines, "primary", semantic.primary);
|
|
4074
4086
|
} else if (semantic.primary) {
|
|
4075
4087
|
emitColorScale(lines, "primary", semantic.primary);
|
|
4076
4088
|
}
|
|
4077
4089
|
if (semantic.secondary) {
|
|
4078
4090
|
if (typeof semantic.secondary === "string") {
|
|
4079
|
-
lines
|
|
4091
|
+
emitBrandColorWithVariants(lines, "secondary", semantic.secondary);
|
|
4080
4092
|
} else {
|
|
4081
4093
|
emitColorScale(lines, "secondary", semantic.secondary);
|
|
4082
4094
|
}
|
|
@@ -4095,10 +4107,10 @@ function buildThemeCss(theme) {
|
|
|
4095
4107
|
emitColorScale(lines, "neutral", semantic.neutral);
|
|
4096
4108
|
}
|
|
4097
4109
|
}
|
|
4098
|
-
if (semantic.success) lines
|
|
4099
|
-
if (semantic.warning) lines
|
|
4100
|
-
if (semantic.danger) lines
|
|
4101
|
-
if (semantic.info) lines
|
|
4110
|
+
if (semantic.success) emitColorWithOpacityVariants(lines, "success", semantic.success);
|
|
4111
|
+
if (semantic.warning) emitColorWithOpacityVariants(lines, "warning", semantic.warning);
|
|
4112
|
+
if (semantic.danger) emitColorWithOpacityVariants(lines, "danger", semantic.danger);
|
|
4113
|
+
if (semantic.info) emitColorWithOpacityVariants(lines, "info", semantic.info);
|
|
4102
4114
|
const surface = theme.colors.surface;
|
|
4103
4115
|
if (surface?.background) lines.push(`--color-background: ${surface.background};`);
|
|
4104
4116
|
if (surface?.surface) lines.push(`--color-surface: ${surface.surface};`);
|
|
@@ -4981,35 +4993,25 @@ var ComponentCache = class {
|
|
|
4981
4993
|
};
|
|
4982
4994
|
var componentCache = new ComponentCache();
|
|
4983
4995
|
|
|
4984
|
-
// libs/uipack/src/renderers/mdx.renderer.ts
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4996
|
+
// libs/uipack/src/renderers/mdx-client.renderer.ts
|
|
4997
|
+
init_utils();
|
|
4998
|
+
function buildReactCdnUrls(version = "19") {
|
|
4999
|
+
return {
|
|
5000
|
+
react: `https://esm.sh/react@${version}`,
|
|
5001
|
+
reactDom: `https://esm.sh/react-dom@${version}/client`,
|
|
5002
|
+
jsxRuntime: `https://esm.sh/react@${version}/jsx-runtime`
|
|
5003
|
+
};
|
|
5004
|
+
}
|
|
5005
|
+
var DEFAULT_CDN = {
|
|
5006
|
+
mdx: "https://esm.sh/@mdx-js/mdx@3",
|
|
5007
|
+
...buildReactCdnUrls("19")
|
|
4988
5008
|
};
|
|
4989
|
-
var
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
`;
|
|
4994
|
-
var MdxRenderer = class {
|
|
4995
|
-
type = "mdx";
|
|
4996
|
-
priority = 10;
|
|
4997
|
-
// Between HTML (0) and React (20)
|
|
4998
|
-
/**
|
|
4999
|
-
* Lazy-loaded modules.
|
|
5000
|
-
*/
|
|
5001
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5002
|
-
React = null;
|
|
5003
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5004
|
-
ReactDOMServer = null;
|
|
5005
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5006
|
-
jsxRuntime = null;
|
|
5007
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5008
|
-
mdxEvaluate = null;
|
|
5009
|
+
var MdxClientRenderer = class {
|
|
5010
|
+
type = "mdx-client";
|
|
5011
|
+
priority = 8;
|
|
5012
|
+
// Lower than server-side MDX (10)
|
|
5009
5013
|
/**
|
|
5010
5014
|
* Check if this renderer can handle the given template.
|
|
5011
|
-
*
|
|
5012
|
-
* Accepts strings containing MDX syntax (Markdown + JSX).
|
|
5013
5015
|
*/
|
|
5014
5016
|
canHandle(template) {
|
|
5015
5017
|
if (typeof template !== "string") {
|
|
@@ -5018,11 +5020,9 @@ var MdxRenderer = class {
|
|
|
5018
5020
|
return containsMdxSyntax(template);
|
|
5019
5021
|
}
|
|
5020
5022
|
/**
|
|
5021
|
-
*
|
|
5022
|
-
*
|
|
5023
|
-
*
|
|
5024
|
-
* Note: For MDX, we use evaluate() which combines compile + run,
|
|
5025
|
-
* so this method just returns the source hash for caching purposes.
|
|
5023
|
+
* Prepare MDX template for rendering.
|
|
5024
|
+
* Caches the template hash for deduplication. Actual MDX compilation
|
|
5025
|
+
* happens client-side via CDN-loaded @mdx-js/mdx in the browser.
|
|
5026
5026
|
*/
|
|
5027
5027
|
async transpile(template, _options) {
|
|
5028
5028
|
const hash = hashString(template);
|
|
@@ -5032,7 +5032,6 @@ var MdxRenderer = class {
|
|
|
5032
5032
|
}
|
|
5033
5033
|
const transpileResult = {
|
|
5034
5034
|
code: template,
|
|
5035
|
-
// Store original MDX for evaluate()
|
|
5036
5035
|
hash,
|
|
5037
5036
|
cached: false
|
|
5038
5037
|
};
|
|
@@ -5040,37 +5039,20 @@ var MdxRenderer = class {
|
|
|
5040
5039
|
return transpileResult;
|
|
5041
5040
|
}
|
|
5042
5041
|
/**
|
|
5043
|
-
* Render MDX template to HTML
|
|
5042
|
+
* Render MDX template to HTML with CDN scripts.
|
|
5044
5043
|
*
|
|
5045
|
-
*
|
|
5046
|
-
*
|
|
5044
|
+
* The returned HTML includes:
|
|
5045
|
+
* - A container div for the rendered content
|
|
5046
|
+
* - Script tags that load React and MDX from CDN
|
|
5047
|
+
* - Inline script that compiles and renders the MDX
|
|
5047
5048
|
*/
|
|
5048
5049
|
async render(template, context, options) {
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
const cacheKey = `mdx-component:${templateHash}`;
|
|
5056
|
-
let Content = componentCache.get(cacheKey);
|
|
5057
|
-
if (!Content) {
|
|
5058
|
-
const result = await this.mdxEvaluate(template, {
|
|
5059
|
-
...this.jsxRuntime,
|
|
5060
|
-
Fragment: this.React.Fragment,
|
|
5061
|
-
development: false
|
|
5062
|
-
});
|
|
5063
|
-
Content = result.default;
|
|
5064
|
-
componentCache.set(cacheKey, Content);
|
|
5065
|
-
}
|
|
5066
|
-
const mdxComponents = {
|
|
5067
|
-
// User-provided components from tool config
|
|
5068
|
-
...options?.mdxComponents,
|
|
5069
|
-
// Wrapper that provides context to the content
|
|
5070
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5071
|
-
wrapper: ({ children }) => {
|
|
5072
|
-
return this.React.createElement("div", { className: "mdx-content" }, children);
|
|
5073
|
-
}
|
|
5050
|
+
const containerId = options?.containerId || "mdx-content";
|
|
5051
|
+
const showLoading = options?.showLoading !== false;
|
|
5052
|
+
const loadingMessage = options?.loadingMessage || "Loading...";
|
|
5053
|
+
const cdn = {
|
|
5054
|
+
...DEFAULT_CDN,
|
|
5055
|
+
...options?.cdn
|
|
5074
5056
|
};
|
|
5075
5057
|
const props = {
|
|
5076
5058
|
input: context.input,
|
|
@@ -5078,82 +5060,80 @@ var MdxRenderer = class {
|
|
|
5078
5060
|
structuredContent: context.structuredContent,
|
|
5079
5061
|
helpers: context.helpers
|
|
5080
5062
|
};
|
|
5063
|
+
const reservedProps = /* @__PURE__ */ new Set(["input", "output", "structuredContent", "helpers", "components"]);
|
|
5064
|
+
const outputProps = typeof context.output === "object" && context.output !== null ? Object.fromEntries(Object.entries(context.output).filter(([key]) => !reservedProps.has(key))) : {};
|
|
5081
5065
|
const spreadProps = {
|
|
5082
|
-
...
|
|
5083
|
-
...
|
|
5066
|
+
...outputProps,
|
|
5067
|
+
...props
|
|
5084
5068
|
};
|
|
5085
|
-
const
|
|
5086
|
-
|
|
5087
|
-
|
|
5069
|
+
const escapedMdx = escapeScriptClose(JSON.stringify(template));
|
|
5070
|
+
const escapedProps = escapeScriptClose(JSON.stringify(spreadProps));
|
|
5071
|
+
const safeContainerId = escapeJsString(containerId);
|
|
5072
|
+
const loadingHtml = showLoading ? `<div class="mdx-loading">${escapeHtml(loadingMessage)}</div>` : "";
|
|
5073
|
+
return `
|
|
5074
|
+
<div id="${escapeHtml(containerId)}">${loadingHtml}</div>
|
|
5075
|
+
<script type="module">
|
|
5076
|
+
(async function() {
|
|
5077
|
+
try {
|
|
5078
|
+
// Load dependencies from CDN
|
|
5079
|
+
const [
|
|
5080
|
+
{ evaluate },
|
|
5081
|
+
runtime,
|
|
5082
|
+
React,
|
|
5083
|
+
{ createRoot }
|
|
5084
|
+
] = await Promise.all([
|
|
5085
|
+
import('${cdn.mdx}'),
|
|
5086
|
+
import('${cdn.jsxRuntime}'),
|
|
5087
|
+
import('${cdn.react}'),
|
|
5088
|
+
import('${cdn.reactDom}')
|
|
5089
|
+
]);
|
|
5090
|
+
|
|
5091
|
+
// MDX content and props
|
|
5092
|
+
const mdxSource = ${escapedMdx};
|
|
5093
|
+
const props = ${escapedProps};
|
|
5094
|
+
|
|
5095
|
+
// Compile and evaluate MDX
|
|
5096
|
+
const { default: Content } = await evaluate(mdxSource, {
|
|
5097
|
+
...runtime,
|
|
5098
|
+
Fragment: React.Fragment,
|
|
5099
|
+
development: false
|
|
5088
5100
|
});
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5101
|
+
|
|
5102
|
+
// Render to DOM
|
|
5103
|
+
const container = document.getElementById('${safeContainerId}');
|
|
5104
|
+
if (container) {
|
|
5105
|
+
const root = createRoot(container);
|
|
5106
|
+
root.render(React.createElement(Content, props));
|
|
5093
5107
|
}
|
|
5094
|
-
|
|
5108
|
+
} catch (error) {
|
|
5109
|
+
console.error('[FrontMCP] MDX client rendering failed:', error);
|
|
5110
|
+
const container = document.getElementById('${safeContainerId}');
|
|
5111
|
+
if (container) {
|
|
5112
|
+
container.innerHTML = '<div class="mdx-error">Failed to render MDX content</div>';
|
|
5113
|
+
}
|
|
5114
|
+
}
|
|
5115
|
+
})();
|
|
5116
|
+
</script>
|
|
5117
|
+
`;
|
|
5095
5118
|
}
|
|
5096
5119
|
/**
|
|
5097
|
-
* Get runtime scripts for client
|
|
5120
|
+
* Get runtime scripts - not needed for client renderer since scripts are inline.
|
|
5098
5121
|
*/
|
|
5099
5122
|
getRuntimeScripts(platform) {
|
|
5100
5123
|
if (platform.networkMode === "blocked") {
|
|
5101
5124
|
return {
|
|
5102
5125
|
headScripts: "",
|
|
5103
|
-
inlineScripts:
|
|
5126
|
+
inlineScripts: `console.warn('[FrontMCP] Client-side MDX rendering requires network access. Use @frontmcp/ui for SSR.');`,
|
|
5104
5127
|
isInline: true
|
|
5105
5128
|
};
|
|
5106
5129
|
}
|
|
5107
5130
|
return {
|
|
5108
|
-
headScripts:
|
|
5109
|
-
<script crossorigin src="${REACT_CDN.react}"></script>
|
|
5110
|
-
<script crossorigin src="${REACT_CDN.reactDom}"></script>
|
|
5111
|
-
`,
|
|
5131
|
+
headScripts: "",
|
|
5112
5132
|
isInline: false
|
|
5113
5133
|
};
|
|
5114
5134
|
}
|
|
5115
|
-
/**
|
|
5116
|
-
* Load React and ReactDOMServer modules.
|
|
5117
|
-
*/
|
|
5118
|
-
async loadReact() {
|
|
5119
|
-
if (this.React && this.ReactDOMServer && this.jsxRuntime) {
|
|
5120
|
-
return;
|
|
5121
|
-
}
|
|
5122
|
-
try {
|
|
5123
|
-
const [react, reactDomServer, jsxRuntime] = await Promise.all([
|
|
5124
|
-
import("react"),
|
|
5125
|
-
import("react-dom/server"),
|
|
5126
|
-
import("react/jsx-runtime")
|
|
5127
|
-
]);
|
|
5128
|
-
this.React = react;
|
|
5129
|
-
this.ReactDOMServer = reactDomServer;
|
|
5130
|
-
this.jsxRuntime = jsxRuntime;
|
|
5131
|
-
} catch {
|
|
5132
|
-
throw new Error("React is required for MdxRenderer. Install react and react-dom: npm install react react-dom");
|
|
5133
|
-
}
|
|
5134
|
-
}
|
|
5135
|
-
/**
|
|
5136
|
-
* Load @mdx-js/mdx evaluate function.
|
|
5137
|
-
*
|
|
5138
|
-
* evaluate() is the cleanest way to run MDX - it combines
|
|
5139
|
-
* compile and run in a single step, handling all the runtime
|
|
5140
|
-
* injection automatically.
|
|
5141
|
-
*/
|
|
5142
|
-
async loadMdx() {
|
|
5143
|
-
if (this.mdxEvaluate) {
|
|
5144
|
-
return;
|
|
5145
|
-
}
|
|
5146
|
-
try {
|
|
5147
|
-
const mdx = await import("@mdx-js/mdx");
|
|
5148
|
-
this.mdxEvaluate = mdx.evaluate;
|
|
5149
|
-
} catch {
|
|
5150
|
-
console.warn(
|
|
5151
|
-
"[@frontmcp/ui] @mdx-js/mdx not available. MDX rendering disabled. Install @mdx-js/mdx to enable: npm install @mdx-js/mdx"
|
|
5152
|
-
);
|
|
5153
|
-
}
|
|
5154
|
-
}
|
|
5155
5135
|
};
|
|
5156
|
-
var
|
|
5136
|
+
var mdxClientRenderer = new MdxClientRenderer();
|
|
5157
5137
|
|
|
5158
5138
|
// libs/uipack/src/types/ui-runtime.ts
|
|
5159
5139
|
function isUIType(value) {
|
|
@@ -5223,7 +5203,7 @@ var DEFAULT_RENDERER_ASSETS = {
|
|
|
5223
5203
|
};
|
|
5224
5204
|
|
|
5225
5205
|
// libs/uipack/src/build/cdn-resources.ts
|
|
5226
|
-
var
|
|
5206
|
+
var REACT_CDN = {
|
|
5227
5207
|
url: "https://esm.sh/react@19",
|
|
5228
5208
|
crossorigin: "anonymous"
|
|
5229
5209
|
};
|
|
@@ -5253,8 +5233,9 @@ var CLOUDFLARE_CDN = {
|
|
|
5253
5233
|
* Use this instead of TAILWIND_CDN for Claude Artifacts.
|
|
5254
5234
|
*/
|
|
5255
5235
|
tailwindCss: {
|
|
5256
|
-
url: "https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/
|
|
5257
|
-
|
|
5236
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/tailwindcss-browser/4.1.13/index.global.min.js",
|
|
5237
|
+
integrity: "sha512-TscjjxDy2iXx5s55Ar78c01JDHUug0K5aw4YKId9Yuocjx3ueX/X9PFyH5XNRVWqagx3TtcQWQVBaHAIPFjiFA==",
|
|
5238
|
+
crossorigin: "anonymous"
|
|
5258
5239
|
},
|
|
5259
5240
|
/**
|
|
5260
5241
|
* HTMX for dynamic interactions.
|
|
@@ -5294,7 +5275,7 @@ function getTailwindForPlatform(platform) {
|
|
|
5294
5275
|
if (platform === "openai") {
|
|
5295
5276
|
return buildCDNScriptTag(TAILWIND_CDN);
|
|
5296
5277
|
}
|
|
5297
|
-
return
|
|
5278
|
+
return buildCDNScriptTag(CLOUDFLARE_CDN.tailwindCss);
|
|
5298
5279
|
}
|
|
5299
5280
|
function buildCloudflareStylesheetTag(url) {
|
|
5300
5281
|
return `<link href="${url}" rel="stylesheet">`;
|
|
@@ -5321,13 +5302,13 @@ function getDefaultAssets(uiType, mode = "cdn") {
|
|
|
5321
5302
|
case "react":
|
|
5322
5303
|
return {
|
|
5323
5304
|
...baseAssets,
|
|
5324
|
-
react:
|
|
5305
|
+
react: REACT_CDN,
|
|
5325
5306
|
reactDom: REACT_DOM_CDN
|
|
5326
5307
|
};
|
|
5327
5308
|
case "mdx":
|
|
5328
5309
|
return {
|
|
5329
5310
|
...baseAssets,
|
|
5330
|
-
react:
|
|
5311
|
+
react: REACT_CDN,
|
|
5331
5312
|
reactDom: REACT_DOM_CDN,
|
|
5332
5313
|
mdxRuntime: MDX_RUNTIME_CDN,
|
|
5333
5314
|
markdown: MARKED_CDN
|
|
@@ -5345,7 +5326,7 @@ function getDefaultAssets(uiType, mode = "cdn") {
|
|
|
5345
5326
|
case "auto":
|
|
5346
5327
|
return {
|
|
5347
5328
|
...baseAssets,
|
|
5348
|
-
react:
|
|
5329
|
+
react: REACT_CDN,
|
|
5349
5330
|
reactDom: REACT_DOM_CDN,
|
|
5350
5331
|
markdown: MARKED_CDN,
|
|
5351
5332
|
handlebars: HANDLEBARS_CDN
|
|
@@ -5423,13 +5404,13 @@ function buildCDNInfoForUIType(uiType) {
|
|
|
5423
5404
|
switch (uiType) {
|
|
5424
5405
|
case "react":
|
|
5425
5406
|
return {
|
|
5426
|
-
react:
|
|
5407
|
+
react: REACT_CDN.url,
|
|
5427
5408
|
reactDom: REACT_DOM_CDN.url,
|
|
5428
5409
|
tailwind: TAILWIND_CDN.url
|
|
5429
5410
|
};
|
|
5430
5411
|
case "mdx":
|
|
5431
5412
|
return {
|
|
5432
|
-
react:
|
|
5413
|
+
react: REACT_CDN.url,
|
|
5433
5414
|
reactDom: REACT_DOM_CDN.url,
|
|
5434
5415
|
mdxRuntime: MDX_RUNTIME_CDN.url,
|
|
5435
5416
|
marked: MARKED_CDN.url,
|
|
@@ -5448,7 +5429,7 @@ function buildCDNInfoForUIType(uiType) {
|
|
|
5448
5429
|
case "auto":
|
|
5449
5430
|
default:
|
|
5450
5431
|
return {
|
|
5451
|
-
react:
|
|
5432
|
+
react: REACT_CDN.url,
|
|
5452
5433
|
reactDom: REACT_DOM_CDN.url,
|
|
5453
5434
|
handlebars: HANDLEBARS_CDN.url,
|
|
5454
5435
|
marked: MARKED_CDN.url,
|
|
@@ -5493,9 +5474,6 @@ function detectFormatFromPath(pathOrUrl) {
|
|
|
5493
5474
|
return "html";
|
|
5494
5475
|
}
|
|
5495
5476
|
|
|
5496
|
-
// libs/uipack/src/validation/error-box.ts
|
|
5497
|
-
init_utils();
|
|
5498
|
-
|
|
5499
5477
|
// libs/uipack/src/validation/schema-paths.ts
|
|
5500
5478
|
import { z } from "zod";
|
|
5501
5479
|
function extractSchemaPaths(schema, prefix = "output", options = {}) {
|
|
@@ -6039,7 +6017,7 @@ async function processTemplate(resolved, options) {
|
|
|
6039
6017
|
structuredContent: context.structuredContent,
|
|
6040
6018
|
helpers: defaultHelpers
|
|
6041
6019
|
};
|
|
6042
|
-
const html = await
|
|
6020
|
+
const html = await mdxClientRenderer.render(processedContent, templateContext);
|
|
6043
6021
|
return {
|
|
6044
6022
|
html,
|
|
6045
6023
|
format: "mdx"
|
|
@@ -6165,7 +6143,7 @@ async function generateHash(content) {
|
|
|
6165
6143
|
return Math.abs(hash).toString(16).padStart(8, "0");
|
|
6166
6144
|
}
|
|
6167
6145
|
async function buildToolWidgetManifest(options) {
|
|
6168
|
-
const { toolName, uiConfig, schema, theme, sampleInput, sampleOutput, outputSchema, inputSchema } = options;
|
|
6146
|
+
const { toolName, uiConfig, schema, theme: _theme, sampleInput, sampleOutput, outputSchema, inputSchema } = options;
|
|
6169
6147
|
const uiType = isUIType(uiConfig.uiType) ? uiConfig.uiType : detectUIType(uiConfig.template);
|
|
6170
6148
|
const displayMode = uiConfig.displayMode ?? "inline";
|
|
6171
6149
|
const bundlingMode = uiConfig.bundlingMode ?? "static";
|
|
@@ -6303,7 +6281,7 @@ function ensureRenderersRegistered() {
|
|
|
6303
6281
|
return;
|
|
6304
6282
|
}
|
|
6305
6283
|
if (!rendererRegistry.has("mdx")) {
|
|
6306
|
-
rendererRegistry.register(
|
|
6284
|
+
rendererRegistry.register(mdxClientRenderer);
|
|
6307
6285
|
}
|
|
6308
6286
|
renderersInitialized = true;
|
|
6309
6287
|
}
|
|
@@ -6591,6 +6569,1684 @@ function getPlatformFromClientInfo(clientInfo) {
|
|
|
6591
6569
|
return "unknown";
|
|
6592
6570
|
}
|
|
6593
6571
|
|
|
6572
|
+
// libs/uipack/src/build/hybrid-data.ts
|
|
6573
|
+
var HYBRID_DATA_PLACEHOLDER = "__FRONTMCP_OUTPUT_PLACEHOLDER__";
|
|
6574
|
+
var HYBRID_INPUT_PLACEHOLDER = "__FRONTMCP_INPUT_PLACEHOLDER__";
|
|
6575
|
+
function injectHybridData(shell, data, placeholder = HYBRID_DATA_PLACEHOLDER) {
|
|
6576
|
+
let jsonData;
|
|
6577
|
+
try {
|
|
6578
|
+
jsonData = JSON.stringify(JSON.stringify(data));
|
|
6579
|
+
jsonData = jsonData.slice(1, -1);
|
|
6580
|
+
} catch {
|
|
6581
|
+
jsonData = "null";
|
|
6582
|
+
}
|
|
6583
|
+
return shell.replace(placeholder, jsonData);
|
|
6584
|
+
}
|
|
6585
|
+
function injectHybridDataFull(shell, input, output) {
|
|
6586
|
+
let result = shell;
|
|
6587
|
+
result = injectHybridData(result, output, HYBRID_DATA_PLACEHOLDER);
|
|
6588
|
+
result = injectHybridData(result, input, HYBRID_INPUT_PLACEHOLDER);
|
|
6589
|
+
return result;
|
|
6590
|
+
}
|
|
6591
|
+
function isHybridShell(html, placeholder = HYBRID_DATA_PLACEHOLDER) {
|
|
6592
|
+
return html.includes(placeholder);
|
|
6593
|
+
}
|
|
6594
|
+
function needsInputInjection(html) {
|
|
6595
|
+
return html.includes(HYBRID_INPUT_PLACEHOLDER);
|
|
6596
|
+
}
|
|
6597
|
+
function getHybridPlaceholders(html) {
|
|
6598
|
+
return {
|
|
6599
|
+
hasOutput: html.includes(HYBRID_DATA_PLACEHOLDER),
|
|
6600
|
+
hasInput: html.includes(HYBRID_INPUT_PLACEHOLDER)
|
|
6601
|
+
};
|
|
6602
|
+
}
|
|
6603
|
+
function injectHybridDataWithTrigger(shell, input, output) {
|
|
6604
|
+
let result = injectHybridDataFull(shell, input, output);
|
|
6605
|
+
let outputJson;
|
|
6606
|
+
try {
|
|
6607
|
+
outputJson = JSON.stringify(output);
|
|
6608
|
+
} catch {
|
|
6609
|
+
outputJson = "null";
|
|
6610
|
+
}
|
|
6611
|
+
const triggerScript = `
|
|
6612
|
+
<script>
|
|
6613
|
+
(function() {
|
|
6614
|
+
var data = ${outputJson};
|
|
6615
|
+
|
|
6616
|
+
function triggerUpdate() {
|
|
6617
|
+
if (window.__frontmcp && window.__frontmcp.updateOutput) {
|
|
6618
|
+
window.__frontmcp.updateOutput(data);
|
|
6619
|
+
} else if (window.mcpBridge) {
|
|
6620
|
+
// Trigger via bridge listeners
|
|
6621
|
+
window.dispatchEvent(new CustomEvent('frontmcp:toolResult', { detail: data }));
|
|
6622
|
+
}
|
|
6623
|
+
}
|
|
6624
|
+
|
|
6625
|
+
if (document.readyState === 'loading') {
|
|
6626
|
+
document.addEventListener('DOMContentLoaded', triggerUpdate);
|
|
6627
|
+
} else {
|
|
6628
|
+
// Small delay to ensure store is initialized
|
|
6629
|
+
setTimeout(triggerUpdate, 0);
|
|
6630
|
+
}
|
|
6631
|
+
})();
|
|
6632
|
+
</script>`;
|
|
6633
|
+
result = result.replace("</body>", triggerScript + "\n</body>");
|
|
6634
|
+
return result;
|
|
6635
|
+
}
|
|
6636
|
+
|
|
6637
|
+
// libs/uipack/src/styles/variants.ts
|
|
6638
|
+
var CARD_VARIANTS = {
|
|
6639
|
+
default: "bg-white border border-border rounded-xl shadow-sm",
|
|
6640
|
+
outlined: "bg-transparent border-2 border-border rounded-xl",
|
|
6641
|
+
elevated: "bg-white rounded-xl shadow-lg",
|
|
6642
|
+
filled: "bg-gray-50 rounded-xl",
|
|
6643
|
+
ghost: "bg-transparent"
|
|
6644
|
+
};
|
|
6645
|
+
var CARD_SIZES = {
|
|
6646
|
+
sm: "p-4",
|
|
6647
|
+
md: "p-6",
|
|
6648
|
+
lg: "p-8"
|
|
6649
|
+
};
|
|
6650
|
+
var BADGE_VARIANTS = {
|
|
6651
|
+
default: "bg-gray-100 text-gray-800",
|
|
6652
|
+
primary: "bg-primary/10 text-primary",
|
|
6653
|
+
secondary: "bg-secondary/10 text-secondary",
|
|
6654
|
+
success: "bg-success/10 text-success",
|
|
6655
|
+
warning: "bg-warning/10 text-warning",
|
|
6656
|
+
danger: "bg-danger/10 text-danger",
|
|
6657
|
+
info: "bg-info/10 text-info",
|
|
6658
|
+
outline: "border border-border text-text-primary bg-transparent"
|
|
6659
|
+
};
|
|
6660
|
+
var BADGE_SIZES = {
|
|
6661
|
+
sm: "px-2 py-0.5 text-xs",
|
|
6662
|
+
md: "px-2.5 py-1 text-xs",
|
|
6663
|
+
lg: "px-3 py-1.5 text-sm"
|
|
6664
|
+
};
|
|
6665
|
+
var BADGE_DOT_SIZES = {
|
|
6666
|
+
sm: "w-2 h-2",
|
|
6667
|
+
md: "w-2.5 h-2.5",
|
|
6668
|
+
lg: "w-3 h-3"
|
|
6669
|
+
};
|
|
6670
|
+
var BADGE_DOT_VARIANTS = {
|
|
6671
|
+
default: "bg-gray-400",
|
|
6672
|
+
primary: "bg-primary",
|
|
6673
|
+
secondary: "bg-secondary",
|
|
6674
|
+
success: "bg-success",
|
|
6675
|
+
warning: "bg-warning",
|
|
6676
|
+
danger: "bg-danger",
|
|
6677
|
+
info: "bg-info",
|
|
6678
|
+
outline: "border border-current"
|
|
6679
|
+
};
|
|
6680
|
+
var BUTTON_VARIANTS = {
|
|
6681
|
+
primary: "bg-primary hover:bg-primary/90 text-white shadow-sm",
|
|
6682
|
+
secondary: "bg-secondary hover:bg-secondary/90 text-white shadow-sm",
|
|
6683
|
+
outline: "border-2 border-primary text-primary bg-transparent hover:bg-primary/10",
|
|
6684
|
+
ghost: "text-text-primary hover:bg-gray-100",
|
|
6685
|
+
danger: "bg-danger hover:bg-danger/90 text-white shadow-sm",
|
|
6686
|
+
success: "bg-success hover:bg-success/90 text-white shadow-sm",
|
|
6687
|
+
link: "text-primary hover:text-primary/80 hover:underline"
|
|
6688
|
+
};
|
|
6689
|
+
var BUTTON_SIZES = {
|
|
6690
|
+
xs: "px-2.5 py-1.5 text-xs",
|
|
6691
|
+
sm: "px-3 py-2 text-sm",
|
|
6692
|
+
md: "px-4 py-2.5 text-sm",
|
|
6693
|
+
lg: "px-5 py-3 text-base",
|
|
6694
|
+
xl: "px-6 py-3.5 text-lg"
|
|
6695
|
+
};
|
|
6696
|
+
var BUTTON_ICON_SIZES = {
|
|
6697
|
+
xs: "p-1.5",
|
|
6698
|
+
sm: "p-2",
|
|
6699
|
+
md: "p-2.5",
|
|
6700
|
+
lg: "p-3",
|
|
6701
|
+
xl: "p-4"
|
|
6702
|
+
};
|
|
6703
|
+
var BUTTON_BASE_CLASSES = "cursor-pointer inline-flex items-center justify-center font-medium rounded-lg transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-primary/50 focus:ring-offset-2";
|
|
6704
|
+
var ALERT_VARIANTS = {
|
|
6705
|
+
info: {
|
|
6706
|
+
container: "bg-info/10 border-info/30 text-info",
|
|
6707
|
+
icon: "text-info"
|
|
6708
|
+
},
|
|
6709
|
+
success: {
|
|
6710
|
+
container: "bg-success/10 border-success/30 text-success",
|
|
6711
|
+
icon: "text-success"
|
|
6712
|
+
},
|
|
6713
|
+
warning: {
|
|
6714
|
+
container: "bg-warning/10 border-warning/30 text-warning",
|
|
6715
|
+
icon: "text-warning"
|
|
6716
|
+
},
|
|
6717
|
+
danger: {
|
|
6718
|
+
container: "bg-danger/10 border-danger/30 text-danger",
|
|
6719
|
+
icon: "text-danger"
|
|
6720
|
+
},
|
|
6721
|
+
neutral: {
|
|
6722
|
+
container: "bg-gray-50 border-gray-200 text-gray-800",
|
|
6723
|
+
icon: "text-gray-500"
|
|
6724
|
+
}
|
|
6725
|
+
};
|
|
6726
|
+
var ALERT_BASE_CLASSES = "rounded-lg border p-4";
|
|
6727
|
+
var ALERT_ICONS = {
|
|
6728
|
+
info: `<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6729
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
6730
|
+
</svg>`,
|
|
6731
|
+
success: `<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6732
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
6733
|
+
</svg>`,
|
|
6734
|
+
warning: `<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6735
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
|
|
6736
|
+
</svg>`,
|
|
6737
|
+
danger: `<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6738
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
6739
|
+
</svg>`,
|
|
6740
|
+
neutral: `<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6741
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
6742
|
+
</svg>`
|
|
6743
|
+
};
|
|
6744
|
+
var CLOSE_ICON = `<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6745
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
|
6746
|
+
</svg>`;
|
|
6747
|
+
var LOADING_SPINNER = `<svg class="animate-spin -ml-1 mr-2 h-4 w-4" fill="none" viewBox="0 0 24 24">
|
|
6748
|
+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
6749
|
+
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
6750
|
+
</svg>`;
|
|
6751
|
+
|
|
6752
|
+
// libs/uipack/src/build/ui-components-browser.ts
|
|
6753
|
+
function buildStyleConstants() {
|
|
6754
|
+
return `
|
|
6755
|
+
// Style Constants (from @frontmcp/uipack/styles)
|
|
6756
|
+
var CARD_VARIANTS = ${JSON.stringify(CARD_VARIANTS)};
|
|
6757
|
+
var CARD_SIZES = ${JSON.stringify(CARD_SIZES)};
|
|
6758
|
+
|
|
6759
|
+
var BUTTON_VARIANTS = ${JSON.stringify(BUTTON_VARIANTS)};
|
|
6760
|
+
var BUTTON_SIZES = ${JSON.stringify(BUTTON_SIZES)};
|
|
6761
|
+
var BUTTON_ICON_SIZES = ${JSON.stringify(BUTTON_ICON_SIZES)};
|
|
6762
|
+
var BUTTON_BASE_CLASSES = ${JSON.stringify(BUTTON_BASE_CLASSES)};
|
|
6763
|
+
var LOADING_SPINNER = ${JSON.stringify(LOADING_SPINNER)};
|
|
6764
|
+
|
|
6765
|
+
var BADGE_VARIANTS = ${JSON.stringify(BADGE_VARIANTS)};
|
|
6766
|
+
var BADGE_SIZES = ${JSON.stringify(BADGE_SIZES)};
|
|
6767
|
+
var BADGE_DOT_SIZES = ${JSON.stringify(BADGE_DOT_SIZES)};
|
|
6768
|
+
var BADGE_DOT_VARIANTS = ${JSON.stringify(BADGE_DOT_VARIANTS)};
|
|
6769
|
+
|
|
6770
|
+
var ALERT_VARIANTS = ${JSON.stringify(ALERT_VARIANTS)};
|
|
6771
|
+
var ALERT_BASE_CLASSES = ${JSON.stringify(ALERT_BASE_CLASSES)};
|
|
6772
|
+
var ALERT_ICONS = ${JSON.stringify(ALERT_ICONS)};
|
|
6773
|
+
var CLOSE_ICON = ${JSON.stringify(CLOSE_ICON)};
|
|
6774
|
+
|
|
6775
|
+
// Utility: Join CSS classes, filtering out falsy values
|
|
6776
|
+
function cn() {
|
|
6777
|
+
var result = [];
|
|
6778
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
6779
|
+
if (arguments[i]) result.push(arguments[i]);
|
|
6780
|
+
}
|
|
6781
|
+
return result.join(' ');
|
|
6782
|
+
}
|
|
6783
|
+
`;
|
|
6784
|
+
}
|
|
6785
|
+
function buildCardComponent() {
|
|
6786
|
+
return `
|
|
6787
|
+
// Card Component (matches @frontmcp/ui/react/Card)
|
|
6788
|
+
window.Card = function Card(props) {
|
|
6789
|
+
var title = props.title;
|
|
6790
|
+
var subtitle = props.subtitle;
|
|
6791
|
+
var headerActions = props.headerActions;
|
|
6792
|
+
var footer = props.footer;
|
|
6793
|
+
var variant = props.variant || 'default';
|
|
6794
|
+
var size = props.size || 'md';
|
|
6795
|
+
var className = props.className;
|
|
6796
|
+
var id = props.id;
|
|
6797
|
+
var clickable = props.clickable;
|
|
6798
|
+
var href = props.href;
|
|
6799
|
+
var children = props.children;
|
|
6800
|
+
|
|
6801
|
+
var variantClasses = CARD_VARIANTS[variant] || CARD_VARIANTS.default;
|
|
6802
|
+
var sizeClasses = CARD_SIZES[size] || CARD_SIZES.md;
|
|
6803
|
+
var clickableClasses = clickable ? 'cursor-pointer hover:shadow-md transition-shadow' : '';
|
|
6804
|
+
var allClasses = cn(variantClasses, sizeClasses, clickableClasses, className);
|
|
6805
|
+
|
|
6806
|
+
var hasHeader = title || subtitle || headerActions;
|
|
6807
|
+
|
|
6808
|
+
var headerElement = hasHeader ? React.createElement('div', {
|
|
6809
|
+
className: 'flex items-start justify-between mb-4'
|
|
6810
|
+
}, [
|
|
6811
|
+
React.createElement('div', { key: 'titles' }, [
|
|
6812
|
+
title && React.createElement('h3', {
|
|
6813
|
+
key: 'title',
|
|
6814
|
+
className: 'text-lg font-semibold text-text-primary'
|
|
6815
|
+
}, title),
|
|
6816
|
+
subtitle && React.createElement('p', {
|
|
6817
|
+
key: 'subtitle',
|
|
6818
|
+
className: 'text-sm text-text-secondary mt-1'
|
|
6819
|
+
}, subtitle)
|
|
6820
|
+
]),
|
|
6821
|
+
headerActions && React.createElement('div', {
|
|
6822
|
+
key: 'actions',
|
|
6823
|
+
className: 'flex items-center gap-2'
|
|
6824
|
+
}, headerActions)
|
|
6825
|
+
]) : null;
|
|
6826
|
+
|
|
6827
|
+
var footerElement = footer ? React.createElement('div', {
|
|
6828
|
+
className: 'mt-4 pt-4 border-t border-divider'
|
|
6829
|
+
}, footer) : null;
|
|
6830
|
+
|
|
6831
|
+
var content = React.createElement(React.Fragment, null, [
|
|
6832
|
+
headerElement,
|
|
6833
|
+
children,
|
|
6834
|
+
footerElement
|
|
6835
|
+
]);
|
|
6836
|
+
|
|
6837
|
+
if (href) {
|
|
6838
|
+
return React.createElement('a', {
|
|
6839
|
+
href: href,
|
|
6840
|
+
className: allClasses,
|
|
6841
|
+
id: id
|
|
6842
|
+
}, content);
|
|
6843
|
+
}
|
|
6844
|
+
|
|
6845
|
+
return React.createElement('div', {
|
|
6846
|
+
className: allClasses,
|
|
6847
|
+
id: id
|
|
6848
|
+
}, content);
|
|
6849
|
+
};
|
|
6850
|
+
`;
|
|
6851
|
+
}
|
|
6852
|
+
function buildButtonComponent() {
|
|
6853
|
+
return `
|
|
6854
|
+
// Button Component (matches @frontmcp/ui/react/Button)
|
|
6855
|
+
window.Button = function Button(props) {
|
|
6856
|
+
var variant = props.variant || 'primary';
|
|
6857
|
+
var size = props.size || 'md';
|
|
6858
|
+
var disabled = props.disabled || false;
|
|
6859
|
+
var loading = props.loading || false;
|
|
6860
|
+
var fullWidth = props.fullWidth || false;
|
|
6861
|
+
var iconPosition = props.iconPosition || 'left';
|
|
6862
|
+
var icon = props.icon;
|
|
6863
|
+
var iconOnly = props.iconOnly || false;
|
|
6864
|
+
var type = props.type || 'button';
|
|
6865
|
+
var className = props.className;
|
|
6866
|
+
var onClick = props.onClick;
|
|
6867
|
+
var children = props.children;
|
|
6868
|
+
|
|
6869
|
+
var variantClasses = BUTTON_VARIANTS[variant] || BUTTON_VARIANTS.primary;
|
|
6870
|
+
var sizeClasses = iconOnly
|
|
6871
|
+
? (BUTTON_ICON_SIZES[size] || BUTTON_ICON_SIZES.md)
|
|
6872
|
+
: (BUTTON_SIZES[size] || BUTTON_SIZES.md);
|
|
6873
|
+
|
|
6874
|
+
var disabledClasses = (disabled || loading) ? 'opacity-50 cursor-not-allowed' : '';
|
|
6875
|
+
var widthClasses = fullWidth ? 'w-full' : '';
|
|
6876
|
+
|
|
6877
|
+
var allClasses = cn(BUTTON_BASE_CLASSES, variantClasses, sizeClasses, disabledClasses, widthClasses, className);
|
|
6878
|
+
|
|
6879
|
+
var iconElement = icon ? React.createElement('span', {
|
|
6880
|
+
className: iconPosition === 'left' ? 'mr-2' : 'ml-2'
|
|
6881
|
+
}, icon) : null;
|
|
6882
|
+
|
|
6883
|
+
var loadingSpinner = loading ? React.createElement('span', {
|
|
6884
|
+
className: 'mr-2',
|
|
6885
|
+
dangerouslySetInnerHTML: { __html: LOADING_SPINNER }
|
|
6886
|
+
}) : null;
|
|
6887
|
+
|
|
6888
|
+
return React.createElement('button', {
|
|
6889
|
+
type: type,
|
|
6890
|
+
className: allClasses,
|
|
6891
|
+
disabled: disabled || loading,
|
|
6892
|
+
onClick: onClick
|
|
6893
|
+
}, [
|
|
6894
|
+
loadingSpinner,
|
|
6895
|
+
!loading && icon && iconPosition === 'left' ? iconElement : null,
|
|
6896
|
+
!iconOnly ? children : null,
|
|
6897
|
+
!loading && icon && iconPosition === 'right' ? iconElement : null
|
|
6898
|
+
]);
|
|
6899
|
+
};
|
|
6900
|
+
`;
|
|
6901
|
+
}
|
|
6902
|
+
function buildBadgeComponent() {
|
|
6903
|
+
return `
|
|
6904
|
+
// Badge Component (matches @frontmcp/ui/react/Badge)
|
|
6905
|
+
window.Badge = function Badge(props) {
|
|
6906
|
+
var variant = props.variant || 'default';
|
|
6907
|
+
var size = props.size || 'md';
|
|
6908
|
+
var pill = props.pill || false;
|
|
6909
|
+
var icon = props.icon;
|
|
6910
|
+
var dot = props.dot || false;
|
|
6911
|
+
var className = props.className;
|
|
6912
|
+
var removable = props.removable || false;
|
|
6913
|
+
var onRemove = props.onRemove;
|
|
6914
|
+
var children = props.children;
|
|
6915
|
+
|
|
6916
|
+
// Handle dot badge (status indicator)
|
|
6917
|
+
if (dot) {
|
|
6918
|
+
var dotSizeClasses = BADGE_DOT_SIZES[size] || BADGE_DOT_SIZES.md;
|
|
6919
|
+
var dotVariantClasses = BADGE_DOT_VARIANTS[variant] || BADGE_DOT_VARIANTS.default;
|
|
6920
|
+
var dotClasses = cn('inline-block rounded-full', dotSizeClasses, dotVariantClasses, className);
|
|
6921
|
+
|
|
6922
|
+
var label = typeof children === 'string' ? children : undefined;
|
|
6923
|
+
|
|
6924
|
+
return React.createElement('span', {
|
|
6925
|
+
className: dotClasses,
|
|
6926
|
+
'aria-label': label,
|
|
6927
|
+
title: label
|
|
6928
|
+
});
|
|
6929
|
+
}
|
|
6930
|
+
|
|
6931
|
+
var variantClasses = BADGE_VARIANTS[variant] || BADGE_VARIANTS.default;
|
|
6932
|
+
var sizeClasses = BADGE_SIZES[size] || BADGE_SIZES.md;
|
|
6933
|
+
|
|
6934
|
+
var baseClasses = cn(
|
|
6935
|
+
'inline-flex items-center font-medium',
|
|
6936
|
+
pill ? 'rounded-full' : 'rounded-md',
|
|
6937
|
+
variantClasses,
|
|
6938
|
+
sizeClasses,
|
|
6939
|
+
className
|
|
6940
|
+
);
|
|
6941
|
+
|
|
6942
|
+
var closeButton = removable ? React.createElement('button', {
|
|
6943
|
+
type: 'button',
|
|
6944
|
+
className: 'ml-1.5 -mr-1 hover:opacity-70 transition-opacity',
|
|
6945
|
+
'aria-label': 'Remove',
|
|
6946
|
+
onClick: onRemove
|
|
6947
|
+
}, React.createElement('svg', {
|
|
6948
|
+
className: 'w-3 h-3',
|
|
6949
|
+
fill: 'none',
|
|
6950
|
+
stroke: 'currentColor',
|
|
6951
|
+
viewBox: '0 0 24 24'
|
|
6952
|
+
}, React.createElement('path', {
|
|
6953
|
+
strokeLinecap: 'round',
|
|
6954
|
+
strokeLinejoin: 'round',
|
|
6955
|
+
strokeWidth: '2',
|
|
6956
|
+
d: 'M6 18L18 6M6 6l12 12'
|
|
6957
|
+
}))) : null;
|
|
6958
|
+
|
|
6959
|
+
return React.createElement('span', {
|
|
6960
|
+
className: baseClasses
|
|
6961
|
+
}, [
|
|
6962
|
+
icon ? React.createElement('span', { key: 'icon', className: 'mr-1' }, icon) : null,
|
|
6963
|
+
children,
|
|
6964
|
+
closeButton
|
|
6965
|
+
]);
|
|
6966
|
+
};
|
|
6967
|
+
`;
|
|
6968
|
+
}
|
|
6969
|
+
function buildAlertComponent() {
|
|
6970
|
+
return `
|
|
6971
|
+
// Alert Component (matches @frontmcp/ui/react/Alert)
|
|
6972
|
+
window.Alert = function Alert(props) {
|
|
6973
|
+
var variant = props.variant || 'info';
|
|
6974
|
+
var title = props.title;
|
|
6975
|
+
var icon = props.icon;
|
|
6976
|
+
var showIcon = props.showIcon !== false;
|
|
6977
|
+
var dismissible = props.dismissible || false;
|
|
6978
|
+
var onDismiss = props.onDismiss;
|
|
6979
|
+
var className = props.className;
|
|
6980
|
+
var children = props.children;
|
|
6981
|
+
|
|
6982
|
+
var variantStyles = ALERT_VARIANTS[variant] || ALERT_VARIANTS.info;
|
|
6983
|
+
var allClasses = cn(ALERT_BASE_CLASSES, variantStyles.container, className);
|
|
6984
|
+
|
|
6985
|
+
// Use custom icon or default variant icon
|
|
6986
|
+
var iconContent = icon || (showIcon ? React.createElement('span', {
|
|
6987
|
+
className: cn('flex-shrink-0', variantStyles.icon),
|
|
6988
|
+
dangerouslySetInnerHTML: { __html: ALERT_ICONS[variant] || ALERT_ICONS.info }
|
|
6989
|
+
}) : null);
|
|
6990
|
+
|
|
6991
|
+
var dismissButton = dismissible ? React.createElement('button', {
|
|
6992
|
+
type: 'button',
|
|
6993
|
+
className: 'flex-shrink-0 ml-3 hover:opacity-70 transition-opacity',
|
|
6994
|
+
'aria-label': 'Dismiss',
|
|
6995
|
+
onClick: onDismiss
|
|
6996
|
+
}, React.createElement('span', {
|
|
6997
|
+
dangerouslySetInnerHTML: { __html: CLOSE_ICON }
|
|
6998
|
+
})) : null;
|
|
6999
|
+
|
|
7000
|
+
return React.createElement('div', {
|
|
7001
|
+
className: allClasses,
|
|
7002
|
+
role: 'alert'
|
|
7003
|
+
}, React.createElement('div', {
|
|
7004
|
+
className: 'flex'
|
|
7005
|
+
}, [
|
|
7006
|
+
iconContent ? React.createElement('div', {
|
|
7007
|
+
key: 'icon',
|
|
7008
|
+
className: 'flex-shrink-0 mr-3'
|
|
7009
|
+
}, iconContent) : null,
|
|
7010
|
+
React.createElement('div', {
|
|
7011
|
+
key: 'content',
|
|
7012
|
+
className: 'flex-1'
|
|
7013
|
+
}, [
|
|
7014
|
+
title ? React.createElement('h4', {
|
|
7015
|
+
key: 'title',
|
|
7016
|
+
className: 'font-semibold mb-1'
|
|
7017
|
+
}, title) : null,
|
|
7018
|
+
React.createElement('div', {
|
|
7019
|
+
key: 'body',
|
|
7020
|
+
className: 'text-sm'
|
|
7021
|
+
}, children)
|
|
7022
|
+
]),
|
|
7023
|
+
dismissButton
|
|
7024
|
+
]));
|
|
7025
|
+
};
|
|
7026
|
+
`;
|
|
7027
|
+
}
|
|
7028
|
+
function buildNamespaceExport() {
|
|
7029
|
+
return `
|
|
7030
|
+
// Export to namespace (for require('@frontmcp/ui/react') shim)
|
|
7031
|
+
window.frontmcp_ui_namespaceObject = Object.assign({}, window.React || {}, {
|
|
7032
|
+
// Hooks
|
|
7033
|
+
useToolOutput: window.useToolOutput,
|
|
7034
|
+
useToolInput: window.useToolInput,
|
|
7035
|
+
useMcpBridgeContext: function() { return window.__frontmcp.context; },
|
|
7036
|
+
useMcpBridge: function() { return window.__frontmcp.context; },
|
|
7037
|
+
useCallTool: function() {
|
|
7038
|
+
return function(name, args) {
|
|
7039
|
+
if (window.__frontmcp.context.callTool) {
|
|
7040
|
+
return window.__frontmcp.context.callTool(name, args);
|
|
7041
|
+
}
|
|
7042
|
+
console.warn('[FrontMCP] callTool not available');
|
|
7043
|
+
return Promise.resolve(null);
|
|
7044
|
+
};
|
|
7045
|
+
},
|
|
7046
|
+
useTheme: function() { return window.__frontmcp.theme || 'light'; },
|
|
7047
|
+
useDisplayMode: function() { return window.__frontmcp.displayMode || 'embedded'; },
|
|
7048
|
+
useHostContext: function() { return window.__frontmcp.hostContext || {}; },
|
|
7049
|
+
useCapability: function(cap) { return window.__frontmcp.capabilities?.[cap] || false; },
|
|
7050
|
+
useStructuredContent: function() { return window.__frontmcp.getState().structuredContent; },
|
|
7051
|
+
useToolCalls: function() { return []; },
|
|
7052
|
+
useSendMessage: function() { return function() { return Promise.resolve(); }; },
|
|
7053
|
+
useOpenLink: function() { return function() {}; },
|
|
7054
|
+
|
|
7055
|
+
// Components
|
|
7056
|
+
Card: window.Card,
|
|
7057
|
+
Badge: window.Badge,
|
|
7058
|
+
Button: window.Button,
|
|
7059
|
+
Alert: window.Alert,
|
|
7060
|
+
|
|
7061
|
+
// Re-export React stuff for convenience
|
|
7062
|
+
createElement: React.createElement,
|
|
7063
|
+
Fragment: React.Fragment,
|
|
7064
|
+
useState: React.useState,
|
|
7065
|
+
useEffect: React.useEffect,
|
|
7066
|
+
useCallback: React.useCallback,
|
|
7067
|
+
useMemo: React.useMemo,
|
|
7068
|
+
useRef: React.useRef,
|
|
7069
|
+
useContext: React.useContext
|
|
7070
|
+
});
|
|
7071
|
+
`;
|
|
7072
|
+
}
|
|
7073
|
+
function buildUIComponentsRuntime(options = {}) {
|
|
7074
|
+
const parts = [
|
|
7075
|
+
"// UI Components (Browser-Compatible)",
|
|
7076
|
+
"// Generated from @frontmcp/ui/react components",
|
|
7077
|
+
"(function() {",
|
|
7078
|
+
buildStyleConstants(),
|
|
7079
|
+
buildCardComponent(),
|
|
7080
|
+
buildButtonComponent(),
|
|
7081
|
+
buildBadgeComponent(),
|
|
7082
|
+
buildAlertComponent(),
|
|
7083
|
+
buildNamespaceExport(),
|
|
7084
|
+
"})();"
|
|
7085
|
+
];
|
|
7086
|
+
let script = parts.join("\n");
|
|
7087
|
+
if (options.minify) {
|
|
7088
|
+
script = minifyScript(script);
|
|
7089
|
+
}
|
|
7090
|
+
return script;
|
|
7091
|
+
}
|
|
7092
|
+
function minifyScript(script) {
|
|
7093
|
+
return script.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/[^\n]*$/gm, "").replace(/\n\s*\n/g, "\n").replace(/^\s+/gm, "").trim();
|
|
7094
|
+
}
|
|
7095
|
+
|
|
7096
|
+
// libs/uipack/src/build/builders/base-builder.ts
|
|
7097
|
+
import { transform } from "esbuild";
|
|
7098
|
+
|
|
7099
|
+
// libs/uipack/src/build/builders/esbuild-config.ts
|
|
7100
|
+
var DEFAULT_EXTERNALS = [
|
|
7101
|
+
"react",
|
|
7102
|
+
"react-dom",
|
|
7103
|
+
"react/jsx-runtime",
|
|
7104
|
+
"react/jsx-dev-runtime",
|
|
7105
|
+
"@frontmcp/ui",
|
|
7106
|
+
"@frontmcp/ui/*"
|
|
7107
|
+
];
|
|
7108
|
+
var EXTERNAL_GLOBALS = {
|
|
7109
|
+
"react": "React",
|
|
7110
|
+
"react-dom": "ReactDOM",
|
|
7111
|
+
"react/jsx-runtime": "jsxRuntime",
|
|
7112
|
+
"react/jsx-dev-runtime": "jsxRuntime",
|
|
7113
|
+
"@frontmcp/ui": "FrontMcpUI"
|
|
7114
|
+
};
|
|
7115
|
+
function createTransformConfig(options = {}) {
|
|
7116
|
+
const {
|
|
7117
|
+
format = "esm",
|
|
7118
|
+
target = "es2020",
|
|
7119
|
+
minify = false,
|
|
7120
|
+
jsxImportSource = "react"
|
|
7121
|
+
} = options;
|
|
7122
|
+
return {
|
|
7123
|
+
loader: "tsx",
|
|
7124
|
+
format,
|
|
7125
|
+
target,
|
|
7126
|
+
minify,
|
|
7127
|
+
treeShaking: true,
|
|
7128
|
+
jsx: "automatic",
|
|
7129
|
+
jsxImportSource,
|
|
7130
|
+
sourcemap: options.minify ? false : "inline"
|
|
7131
|
+
};
|
|
7132
|
+
}
|
|
7133
|
+
function createExternalizedConfig(options = {}) {
|
|
7134
|
+
const baseConfig = createTransformConfig({
|
|
7135
|
+
...options,
|
|
7136
|
+
format: "esm"
|
|
7137
|
+
});
|
|
7138
|
+
return {
|
|
7139
|
+
...baseConfig,
|
|
7140
|
+
// Add banner to define external namespace objects
|
|
7141
|
+
banner: createExternalsBanner(options.externals || DEFAULT_EXTERNALS)
|
|
7142
|
+
};
|
|
7143
|
+
}
|
|
7144
|
+
function createExternalsBanner(externals) {
|
|
7145
|
+
const lines = [
|
|
7146
|
+
"// Externalized dependencies - loaded from shell globals"
|
|
7147
|
+
];
|
|
7148
|
+
for (const pkg of externals) {
|
|
7149
|
+
const globalName = EXTERNAL_GLOBALS[pkg];
|
|
7150
|
+
if (globalName) {
|
|
7151
|
+
const safeName = pkg.replace(/[^a-zA-Z0-9]/g, "_");
|
|
7152
|
+
lines.push(`const __external_${safeName} = window.${globalName};`);
|
|
7153
|
+
}
|
|
7154
|
+
}
|
|
7155
|
+
return lines.join("\n");
|
|
7156
|
+
}
|
|
7157
|
+
function createInlineConfig(options = {}) {
|
|
7158
|
+
return createTransformConfig({
|
|
7159
|
+
...options,
|
|
7160
|
+
format: "iife",
|
|
7161
|
+
minify: options.minify ?? true
|
|
7162
|
+
});
|
|
7163
|
+
}
|
|
7164
|
+
var CDN_URLS = {
|
|
7165
|
+
react: "https://esm.sh/react@19",
|
|
7166
|
+
reactDom: "https://esm.sh/react-dom@19",
|
|
7167
|
+
reactJsxRuntime: "https://esm.sh/react@19/jsx-runtime",
|
|
7168
|
+
frontmcpUI: "https://esm.sh/@frontmcp/ui",
|
|
7169
|
+
tailwind: "https://cdn.tailwindcss.com"
|
|
7170
|
+
};
|
|
7171
|
+
var CLOUDFLARE_CDN_URLS = {
|
|
7172
|
+
react: "https://cdnjs.cloudflare.com/ajax/libs/react/19.0.0/umd/react.production.min.js",
|
|
7173
|
+
reactDom: "https://cdnjs.cloudflare.com/ajax/libs/react-dom/19.0.0/umd/react-dom.production.min.js",
|
|
7174
|
+
tailwind: "https://cdn.tailwindcss.com"
|
|
7175
|
+
};
|
|
7176
|
+
function generateCdnScriptTags(useCloudflare = false) {
|
|
7177
|
+
const urls = useCloudflare ? CLOUDFLARE_CDN_URLS : CDN_URLS;
|
|
7178
|
+
if (useCloudflare) {
|
|
7179
|
+
return `
|
|
7180
|
+
<script src="${urls.react}"></script>
|
|
7181
|
+
<script src="${urls.reactDom}"></script>
|
|
7182
|
+
<script src="${urls.tailwind}"></script>
|
|
7183
|
+
`;
|
|
7184
|
+
}
|
|
7185
|
+
return `
|
|
7186
|
+
<script type="importmap">
|
|
7187
|
+
{
|
|
7188
|
+
"imports": {
|
|
7189
|
+
"react": "${CDN_URLS.react}",
|
|
7190
|
+
"react-dom": "${CDN_URLS.reactDom}",
|
|
7191
|
+
"react/jsx-runtime": "${CDN_URLS.reactJsxRuntime}",
|
|
7192
|
+
"@frontmcp/ui": "${CDN_URLS.frontmcpUI}"
|
|
7193
|
+
}
|
|
7194
|
+
}
|
|
7195
|
+
</script>
|
|
7196
|
+
<script src="${CDN_URLS.tailwind}"></script>
|
|
7197
|
+
`;
|
|
7198
|
+
}
|
|
7199
|
+
function generateGlobalsSetupScript() {
|
|
7200
|
+
return `
|
|
7201
|
+
<script type="module">
|
|
7202
|
+
import React from 'react';
|
|
7203
|
+
import ReactDOM from 'react-dom/client';
|
|
7204
|
+
import * as jsxRuntime from 'react/jsx-runtime';
|
|
7205
|
+
|
|
7206
|
+
// Expose as globals for externalized components
|
|
7207
|
+
window.React = React;
|
|
7208
|
+
window.ReactDOM = ReactDOM;
|
|
7209
|
+
window.jsxRuntime = jsxRuntime;
|
|
7210
|
+
|
|
7211
|
+
// Signal that runtime is ready
|
|
7212
|
+
window.__frontmcpRuntimeReady = true;
|
|
7213
|
+
window.dispatchEvent(new CustomEvent('frontmcp:runtime-ready'));
|
|
7214
|
+
</script>
|
|
7215
|
+
`;
|
|
7216
|
+
}
|
|
7217
|
+
|
|
7218
|
+
// libs/uipack/src/build/builders/base-builder.ts
|
|
7219
|
+
init_utils();
|
|
7220
|
+
var BaseBuilder = class {
|
|
7221
|
+
/**
|
|
7222
|
+
* CDN loading mode.
|
|
7223
|
+
*/
|
|
7224
|
+
cdnMode;
|
|
7225
|
+
/**
|
|
7226
|
+
* Whether to minify output.
|
|
7227
|
+
*/
|
|
7228
|
+
minify;
|
|
7229
|
+
/**
|
|
7230
|
+
* Theme configuration.
|
|
7231
|
+
*/
|
|
7232
|
+
theme;
|
|
7233
|
+
/**
|
|
7234
|
+
* Whether to include source maps.
|
|
7235
|
+
*/
|
|
7236
|
+
sourceMaps;
|
|
7237
|
+
constructor(options = {}) {
|
|
7238
|
+
this.cdnMode = options.cdnMode ?? "cdn";
|
|
7239
|
+
this.minify = options.minify ?? false;
|
|
7240
|
+
this.theme = options.theme ? mergeThemes(DEFAULT_THEME, options.theme) : DEFAULT_THEME;
|
|
7241
|
+
this.sourceMaps = options.sourceMaps ?? false;
|
|
7242
|
+
}
|
|
7243
|
+
// ============================================
|
|
7244
|
+
// Template Detection
|
|
7245
|
+
// ============================================
|
|
7246
|
+
/**
|
|
7247
|
+
* Detect the type of a template.
|
|
7248
|
+
*
|
|
7249
|
+
* @param template - Template to detect
|
|
7250
|
+
* @returns Detection result with type and renderer info
|
|
7251
|
+
*/
|
|
7252
|
+
detectTemplate(template) {
|
|
7253
|
+
if (typeof template === "string") {
|
|
7254
|
+
return {
|
|
7255
|
+
type: "html-string",
|
|
7256
|
+
renderer: "html",
|
|
7257
|
+
needsTranspilation: false
|
|
7258
|
+
};
|
|
7259
|
+
}
|
|
7260
|
+
if (typeof template === "function") {
|
|
7261
|
+
const funcStr = template.toString();
|
|
7262
|
+
if (funcStr.includes("jsx") || funcStr.includes("createElement") || funcStr.includes("React") || template.$$typeof) {
|
|
7263
|
+
return {
|
|
7264
|
+
type: "react-component",
|
|
7265
|
+
renderer: "react",
|
|
7266
|
+
needsTranspilation: true
|
|
7267
|
+
};
|
|
7268
|
+
}
|
|
7269
|
+
return {
|
|
7270
|
+
type: "html-function",
|
|
7271
|
+
renderer: "html",
|
|
7272
|
+
needsTranspilation: false
|
|
7273
|
+
};
|
|
7274
|
+
}
|
|
7275
|
+
if (template && typeof template === "object" && template.$$typeof) {
|
|
7276
|
+
return {
|
|
7277
|
+
type: "react-element",
|
|
7278
|
+
renderer: "react",
|
|
7279
|
+
needsTranspilation: true
|
|
7280
|
+
};
|
|
7281
|
+
}
|
|
7282
|
+
return {
|
|
7283
|
+
type: "html-string",
|
|
7284
|
+
renderer: "html",
|
|
7285
|
+
needsTranspilation: false
|
|
7286
|
+
};
|
|
7287
|
+
}
|
|
7288
|
+
// ============================================
|
|
7289
|
+
// Transpilation
|
|
7290
|
+
// ============================================
|
|
7291
|
+
/**
|
|
7292
|
+
* Transpile a component using esbuild.
|
|
7293
|
+
*
|
|
7294
|
+
* @param source - Source code to transpile
|
|
7295
|
+
* @param options - Transpile options
|
|
7296
|
+
* @returns Transpile result
|
|
7297
|
+
*/
|
|
7298
|
+
async transpile(source, options = {}) {
|
|
7299
|
+
const externals = options.externals || DEFAULT_EXTERNALS;
|
|
7300
|
+
const config = options.externals ? createExternalizedConfig(options) : createTransformConfig(options);
|
|
7301
|
+
const result = await transform(source, config);
|
|
7302
|
+
return {
|
|
7303
|
+
code: result.code,
|
|
7304
|
+
map: result.map,
|
|
7305
|
+
size: Buffer.byteLength(result.code, "utf8"),
|
|
7306
|
+
externalizedImports: externals
|
|
7307
|
+
};
|
|
7308
|
+
}
|
|
7309
|
+
/**
|
|
7310
|
+
* Render an HTML template.
|
|
7311
|
+
*
|
|
7312
|
+
* @param template - HTML template (string or function)
|
|
7313
|
+
* @param context - Template context with input/output
|
|
7314
|
+
* @returns Rendered HTML string
|
|
7315
|
+
*/
|
|
7316
|
+
renderHtmlTemplate(template, context) {
|
|
7317
|
+
if (typeof template === "string") {
|
|
7318
|
+
return template;
|
|
7319
|
+
}
|
|
7320
|
+
return template(context);
|
|
7321
|
+
}
|
|
7322
|
+
// ============================================
|
|
7323
|
+
// HTML Generation
|
|
7324
|
+
// ============================================
|
|
7325
|
+
/**
|
|
7326
|
+
* Build the <head> section of the HTML document.
|
|
7327
|
+
*
|
|
7328
|
+
* @param options - Head options
|
|
7329
|
+
* @returns HTML head content
|
|
7330
|
+
*/
|
|
7331
|
+
buildHead(options) {
|
|
7332
|
+
const {
|
|
7333
|
+
title,
|
|
7334
|
+
includeBridge = true,
|
|
7335
|
+
includeCdn = this.cdnMode === "cdn",
|
|
7336
|
+
includeTheme = true,
|
|
7337
|
+
customStyles = ""
|
|
7338
|
+
} = options;
|
|
7339
|
+
const parts = [
|
|
7340
|
+
"<head>",
|
|
7341
|
+
'<meta charset="UTF-8">',
|
|
7342
|
+
'<meta name="viewport" content="width=device-width, initial-scale=1.0">',
|
|
7343
|
+
`<title>${escapeHtml(title)}</title>`
|
|
7344
|
+
];
|
|
7345
|
+
parts.push(buildFontPreconnect());
|
|
7346
|
+
parts.push(buildFontStylesheets({ inter: true }));
|
|
7347
|
+
if (includeTheme) {
|
|
7348
|
+
const themeCss = buildThemeCss(this.theme);
|
|
7349
|
+
const customCss = this.theme.customCss || "";
|
|
7350
|
+
parts.push(`
|
|
7351
|
+
<style type="text/tailwindcss">
|
|
7352
|
+
@theme {
|
|
7353
|
+
${themeCss}
|
|
7354
|
+
}
|
|
7355
|
+
${customCss}
|
|
7356
|
+
</style>
|
|
7357
|
+
`);
|
|
7358
|
+
}
|
|
7359
|
+
if (customStyles) {
|
|
7360
|
+
parts.push(`<style>${customStyles}</style>`);
|
|
7361
|
+
}
|
|
7362
|
+
if (includeCdn) {
|
|
7363
|
+
parts.push('<script src="https://cdn.tailwindcss.com"></script>');
|
|
7364
|
+
}
|
|
7365
|
+
if (includeBridge) {
|
|
7366
|
+
parts.push(BRIDGE_SCRIPT_TAGS.universal);
|
|
7367
|
+
}
|
|
7368
|
+
parts.push("</head>");
|
|
7369
|
+
return parts.join("\n");
|
|
7370
|
+
}
|
|
7371
|
+
/**
|
|
7372
|
+
* Build data injection script.
|
|
7373
|
+
*
|
|
7374
|
+
* @param options - Injection options
|
|
7375
|
+
* @returns Script tag with data injection
|
|
7376
|
+
*/
|
|
7377
|
+
buildDataInjectionScript(options) {
|
|
7378
|
+
const { toolName, input, output, usePlaceholders = false } = options;
|
|
7379
|
+
if (usePlaceholders) {
|
|
7380
|
+
return `
|
|
7381
|
+
<script>
|
|
7382
|
+
window.__mcpToolName = ${JSON.stringify(toolName)};
|
|
7383
|
+
window.__mcpToolInput = JSON.parse("${HYBRID_INPUT_PLACEHOLDER}");
|
|
7384
|
+
window.__mcpToolOutput = JSON.parse("${HYBRID_DATA_PLACEHOLDER}");
|
|
7385
|
+
window.__mcpStructuredContent = window.__mcpToolOutput;
|
|
7386
|
+
</script>
|
|
7387
|
+
`;
|
|
7388
|
+
}
|
|
7389
|
+
return `
|
|
7390
|
+
<script>
|
|
7391
|
+
window.__mcpToolName = ${JSON.stringify(toolName)};
|
|
7392
|
+
window.__mcpToolInput = ${JSON.stringify(input ?? {})};
|
|
7393
|
+
window.__mcpToolOutput = ${JSON.stringify(output ?? {})};
|
|
7394
|
+
window.__mcpStructuredContent = window.__mcpToolOutput;
|
|
7395
|
+
</script>
|
|
7396
|
+
`;
|
|
7397
|
+
}
|
|
7398
|
+
/**
|
|
7399
|
+
* Wrap content in a complete HTML document.
|
|
7400
|
+
*
|
|
7401
|
+
* @param options - Wrap options
|
|
7402
|
+
* @returns Complete HTML document
|
|
7403
|
+
*/
|
|
7404
|
+
wrapInHtmlDocument(options) {
|
|
7405
|
+
const { head, body, bodyClass = "" } = options;
|
|
7406
|
+
return `<!DOCTYPE html>
|
|
7407
|
+
<html lang="en">
|
|
7408
|
+
${head}
|
|
7409
|
+
<body${bodyClass ? ` class="${bodyClass}"` : ""}>
|
|
7410
|
+
${body}
|
|
7411
|
+
</body>
|
|
7412
|
+
</html>`;
|
|
7413
|
+
}
|
|
7414
|
+
// ============================================
|
|
7415
|
+
// Utility Methods
|
|
7416
|
+
// ============================================
|
|
7417
|
+
/**
|
|
7418
|
+
* Calculate content hash.
|
|
7419
|
+
*
|
|
7420
|
+
* @param content - Content to hash
|
|
7421
|
+
* @returns Hash string
|
|
7422
|
+
*/
|
|
7423
|
+
async calculateHash(content) {
|
|
7424
|
+
if (typeof crypto !== "undefined" && crypto.subtle) {
|
|
7425
|
+
const encoder = new TextEncoder();
|
|
7426
|
+
const data = encoder.encode(content);
|
|
7427
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
7428
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
7429
|
+
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 16);
|
|
7430
|
+
}
|
|
7431
|
+
let hash = 0;
|
|
7432
|
+
for (let i = 0; i < content.length; i++) {
|
|
7433
|
+
const char = content.charCodeAt(i);
|
|
7434
|
+
hash = (hash << 5) - hash + char;
|
|
7435
|
+
hash = hash & hash;
|
|
7436
|
+
}
|
|
7437
|
+
return Math.abs(hash).toString(16).padStart(8, "0");
|
|
7438
|
+
}
|
|
7439
|
+
/**
|
|
7440
|
+
* Estimate gzipped size.
|
|
7441
|
+
*
|
|
7442
|
+
* @param content - Content to estimate
|
|
7443
|
+
* @returns Estimated gzipped size in bytes
|
|
7444
|
+
*/
|
|
7445
|
+
estimateGzipSize(content) {
|
|
7446
|
+
return Math.round(Buffer.byteLength(content, "utf8") * 0.25);
|
|
7447
|
+
}
|
|
7448
|
+
/**
|
|
7449
|
+
* Create template context.
|
|
7450
|
+
*
|
|
7451
|
+
* @param input - Tool input
|
|
7452
|
+
* @param output - Tool output
|
|
7453
|
+
* @returns Template context
|
|
7454
|
+
*/
|
|
7455
|
+
createContext(input, output) {
|
|
7456
|
+
return {
|
|
7457
|
+
input,
|
|
7458
|
+
output,
|
|
7459
|
+
helpers: {
|
|
7460
|
+
escapeHtml,
|
|
7461
|
+
formatDate: (date, format) => {
|
|
7462
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
7463
|
+
if (isNaN(d.getTime())) return String(date);
|
|
7464
|
+
if (format === "iso") return d.toISOString();
|
|
7465
|
+
if (format === "time") return d.toLocaleTimeString();
|
|
7466
|
+
if (format === "datetime") return d.toLocaleString();
|
|
7467
|
+
return d.toLocaleDateString();
|
|
7468
|
+
},
|
|
7469
|
+
formatCurrency: (amount, currency = "USD") => {
|
|
7470
|
+
return new Intl.NumberFormat("en-US", { style: "currency", currency }).format(amount);
|
|
7471
|
+
},
|
|
7472
|
+
uniqueId: (prefix = "mcp") => {
|
|
7473
|
+
return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;
|
|
7474
|
+
},
|
|
7475
|
+
jsonEmbed: (data) => {
|
|
7476
|
+
const json2 = JSON.stringify(data);
|
|
7477
|
+
if (json2 === void 0) return "undefined";
|
|
7478
|
+
return json2.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/'/g, "\\u0027");
|
|
7479
|
+
}
|
|
7480
|
+
}
|
|
7481
|
+
};
|
|
7482
|
+
}
|
|
7483
|
+
};
|
|
7484
|
+
|
|
7485
|
+
// libs/uipack/src/build/builders/static-builder.ts
|
|
7486
|
+
var StaticBuilder = class extends BaseBuilder {
|
|
7487
|
+
mode = "static";
|
|
7488
|
+
constructor(options = {}) {
|
|
7489
|
+
super(options);
|
|
7490
|
+
}
|
|
7491
|
+
/**
|
|
7492
|
+
* Build a static HTML shell with placeholders.
|
|
7493
|
+
*
|
|
7494
|
+
* @param options - Build options
|
|
7495
|
+
* @returns Static build result
|
|
7496
|
+
*/
|
|
7497
|
+
async build(options) {
|
|
7498
|
+
const startTime = Date.now();
|
|
7499
|
+
const { template, toolName, title = `${toolName} Widget` } = options;
|
|
7500
|
+
const detection = this.detectTemplate(template.template);
|
|
7501
|
+
let bodyContent;
|
|
7502
|
+
if (detection.renderer === "html") {
|
|
7503
|
+
const context = this.createContext(
|
|
7504
|
+
options.sampleInput ?? {},
|
|
7505
|
+
options.sampleOutput ?? {}
|
|
7506
|
+
);
|
|
7507
|
+
if (typeof template.template === "function") {
|
|
7508
|
+
bodyContent = template.template(context);
|
|
7509
|
+
} else {
|
|
7510
|
+
bodyContent = template.template;
|
|
7511
|
+
}
|
|
7512
|
+
bodyContent = `
|
|
7513
|
+
<div id="frontmcp-widget-root">
|
|
7514
|
+
${bodyContent}
|
|
7515
|
+
</div>
|
|
7516
|
+
`;
|
|
7517
|
+
} else {
|
|
7518
|
+
bodyContent = this.buildReactShell(template, toolName);
|
|
7519
|
+
}
|
|
7520
|
+
const head = this.buildHead({
|
|
7521
|
+
title,
|
|
7522
|
+
includeBridge: true,
|
|
7523
|
+
includeCdn: this.cdnMode === "cdn",
|
|
7524
|
+
includeTheme: true
|
|
7525
|
+
});
|
|
7526
|
+
const dataScript = this.buildDataInjectionScript({
|
|
7527
|
+
toolName,
|
|
7528
|
+
usePlaceholders: true
|
|
7529
|
+
});
|
|
7530
|
+
let additionalScripts = "";
|
|
7531
|
+
if (detection.renderer === "react") {
|
|
7532
|
+
additionalScripts = this.cdnMode === "cdn" ? generateCdnScriptTags(false) + generateGlobalsSetupScript() : this.buildInlineReactRuntime();
|
|
7533
|
+
}
|
|
7534
|
+
const body = `
|
|
7535
|
+
${dataScript}
|
|
7536
|
+
${additionalScripts}
|
|
7537
|
+
${bodyContent}
|
|
7538
|
+
`;
|
|
7539
|
+
const html = this.wrapInHtmlDocument({
|
|
7540
|
+
head,
|
|
7541
|
+
body,
|
|
7542
|
+
bodyClass: "antialiased"
|
|
7543
|
+
});
|
|
7544
|
+
const finalHtml = this.minify ? this.minifyHtml(html) : html;
|
|
7545
|
+
const hash = await this.calculateHash(finalHtml);
|
|
7546
|
+
const size = Buffer.byteLength(finalHtml, "utf8");
|
|
7547
|
+
const gzipSize = this.estimateGzipSize(finalHtml);
|
|
7548
|
+
return {
|
|
7549
|
+
mode: "static",
|
|
7550
|
+
html: finalHtml,
|
|
7551
|
+
hash,
|
|
7552
|
+
size,
|
|
7553
|
+
gzipSize,
|
|
7554
|
+
placeholders: {
|
|
7555
|
+
hasOutput: finalHtml.includes(HYBRID_DATA_PLACEHOLDER),
|
|
7556
|
+
hasInput: finalHtml.includes(HYBRID_INPUT_PLACEHOLDER)
|
|
7557
|
+
},
|
|
7558
|
+
rendererType: detection.renderer,
|
|
7559
|
+
buildTime: new Date(startTime).toISOString()
|
|
7560
|
+
};
|
|
7561
|
+
}
|
|
7562
|
+
/**
|
|
7563
|
+
* Inject data into a pre-built shell.
|
|
7564
|
+
*
|
|
7565
|
+
* @param shell - HTML shell with placeholders
|
|
7566
|
+
* @param input - Tool input data
|
|
7567
|
+
* @param output - Tool output data
|
|
7568
|
+
* @returns HTML with data injected
|
|
7569
|
+
*/
|
|
7570
|
+
injectData(shell, input, output) {
|
|
7571
|
+
return injectHybridDataFull(shell, input, output);
|
|
7572
|
+
}
|
|
7573
|
+
// ============================================
|
|
7574
|
+
// Private Methods
|
|
7575
|
+
// ============================================
|
|
7576
|
+
/**
|
|
7577
|
+
* Build React rendering shell.
|
|
7578
|
+
*
|
|
7579
|
+
* Creates a client-side React rendering setup that:
|
|
7580
|
+
* 1. Waits for runtime to be ready
|
|
7581
|
+
* 2. Loads component code
|
|
7582
|
+
* 3. Renders into #root with data from window.__mcpToolOutput
|
|
7583
|
+
*/
|
|
7584
|
+
buildReactShell(template, _toolName) {
|
|
7585
|
+
const _componentName = this.getComponentName(template.template);
|
|
7586
|
+
return `
|
|
7587
|
+
<div id="frontmcp-widget-root">
|
|
7588
|
+
<div id="root" class="min-h-[200px]">
|
|
7589
|
+
<div class="flex items-center justify-center p-4">
|
|
7590
|
+
<div class="text-center text-gray-500">
|
|
7591
|
+
<svg class="animate-spin mx-auto mb-2" style="width: 1.5rem; height: 1.5rem; color: #9ca3af;" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
7592
|
+
<circle style="opacity: 0.25;" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
7593
|
+
<path style="opacity: 0.75;" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
7594
|
+
</svg>
|
|
7595
|
+
<p class="text-sm">Loading...</p>
|
|
7596
|
+
</div>
|
|
7597
|
+
</div>
|
|
7598
|
+
</div>
|
|
7599
|
+
</div>
|
|
7600
|
+
|
|
7601
|
+
<script type="module">
|
|
7602
|
+
// Wait for React runtime to be ready
|
|
7603
|
+
function waitForRuntime() {
|
|
7604
|
+
return new Promise((resolve) => {
|
|
7605
|
+
if (window.__frontmcpRuntimeReady) {
|
|
7606
|
+
resolve();
|
|
7607
|
+
} else {
|
|
7608
|
+
window.addEventListener('frontmcp:runtime-ready', resolve, { once: true });
|
|
7609
|
+
}
|
|
7610
|
+
});
|
|
7611
|
+
}
|
|
7612
|
+
|
|
7613
|
+
async function renderWidget() {
|
|
7614
|
+
await waitForRuntime();
|
|
7615
|
+
|
|
7616
|
+
const React = window.React;
|
|
7617
|
+
const ReactDOM = window.ReactDOM;
|
|
7618
|
+
|
|
7619
|
+
// Get data from injected globals
|
|
7620
|
+
const input = window.__mcpToolInput || {};
|
|
7621
|
+
const output = window.__mcpToolOutput || {};
|
|
7622
|
+
|
|
7623
|
+
// Create simple widget component
|
|
7624
|
+
function Widget() {
|
|
7625
|
+
const [data, setData] = React.useState({ input, output });
|
|
7626
|
+
|
|
7627
|
+
React.useEffect(() => {
|
|
7628
|
+
// Subscribe to data updates via bridge
|
|
7629
|
+
const handleUpdate = (event) => {
|
|
7630
|
+
if (event.detail) {
|
|
7631
|
+
setData((prev) => ({ ...prev, output: event.detail }));
|
|
7632
|
+
}
|
|
7633
|
+
};
|
|
7634
|
+
window.addEventListener('frontmcp:toolResult', handleUpdate);
|
|
7635
|
+
return () => window.removeEventListener('frontmcp:toolResult', handleUpdate);
|
|
7636
|
+
}, []);
|
|
7637
|
+
|
|
7638
|
+
return React.createElement('div', {
|
|
7639
|
+
className: 'p-4',
|
|
7640
|
+
dangerouslySetInnerHTML: {
|
|
7641
|
+
__html: '<pre>' + JSON.stringify(data.output, null, 2) + '</pre>'
|
|
7642
|
+
}
|
|
7643
|
+
});
|
|
7644
|
+
}
|
|
7645
|
+
|
|
7646
|
+
// Render
|
|
7647
|
+
const root = ReactDOM.createRoot(document.getElementById('root'));
|
|
7648
|
+
root.render(React.createElement(Widget));
|
|
7649
|
+
}
|
|
7650
|
+
|
|
7651
|
+
renderWidget().catch(console.error);
|
|
7652
|
+
</script>
|
|
7653
|
+
`;
|
|
7654
|
+
}
|
|
7655
|
+
/**
|
|
7656
|
+
* Build inline React runtime (for offline mode).
|
|
7657
|
+
*/
|
|
7658
|
+
buildInlineReactRuntime() {
|
|
7659
|
+
return `
|
|
7660
|
+
<script>
|
|
7661
|
+
// Inline React runtime would be bundled here
|
|
7662
|
+
console.warn('[FrontMCP] Inline React runtime not yet implemented');
|
|
7663
|
+
</script>
|
|
7664
|
+
`;
|
|
7665
|
+
}
|
|
7666
|
+
/**
|
|
7667
|
+
* Get component name from template.
|
|
7668
|
+
*/
|
|
7669
|
+
getComponentName(template) {
|
|
7670
|
+
if (typeof template === "function") {
|
|
7671
|
+
return template.name || "Widget";
|
|
7672
|
+
}
|
|
7673
|
+
return "Widget";
|
|
7674
|
+
}
|
|
7675
|
+
/**
|
|
7676
|
+
* Simple HTML minification.
|
|
7677
|
+
*/
|
|
7678
|
+
minifyHtml(html) {
|
|
7679
|
+
return html.replace(/>\s+</g, "><").replace(/\s{2,}/g, " ").trim();
|
|
7680
|
+
}
|
|
7681
|
+
};
|
|
7682
|
+
|
|
7683
|
+
// libs/uipack/src/build/builders/hybrid-builder.ts
|
|
7684
|
+
var HybridBuilder = class extends BaseBuilder {
|
|
7685
|
+
mode = "hybrid";
|
|
7686
|
+
/**
|
|
7687
|
+
* Cached vendor shell.
|
|
7688
|
+
*/
|
|
7689
|
+
vendorShellCache = null;
|
|
7690
|
+
constructor(options = {}) {
|
|
7691
|
+
super(options);
|
|
7692
|
+
}
|
|
7693
|
+
/**
|
|
7694
|
+
* Build a hybrid result with vendor shell and component chunk.
|
|
7695
|
+
*
|
|
7696
|
+
* @param options - Build options
|
|
7697
|
+
* @returns Hybrid build result
|
|
7698
|
+
*/
|
|
7699
|
+
async build(options) {
|
|
7700
|
+
const startTime = Date.now();
|
|
7701
|
+
const { template, toolName } = options;
|
|
7702
|
+
const vendorShell = await this.buildVendorShell();
|
|
7703
|
+
const componentChunk = await this.buildComponentChunk(template.template);
|
|
7704
|
+
const shellResourceUri = `resource://widget/${toolName}/shell`;
|
|
7705
|
+
const combinedHash = await this.calculateHash(vendorShell + componentChunk);
|
|
7706
|
+
const shellSize = Buffer.byteLength(vendorShell, "utf8");
|
|
7707
|
+
const componentSize = Buffer.byteLength(componentChunk, "utf8");
|
|
7708
|
+
const detection = this.detectTemplate(template.template);
|
|
7709
|
+
return {
|
|
7710
|
+
mode: "hybrid",
|
|
7711
|
+
vendorShell,
|
|
7712
|
+
componentChunk,
|
|
7713
|
+
shellResourceUri,
|
|
7714
|
+
hash: combinedHash,
|
|
7715
|
+
shellSize,
|
|
7716
|
+
componentSize,
|
|
7717
|
+
rendererType: detection.renderer,
|
|
7718
|
+
buildTime: new Date(startTime).toISOString()
|
|
7719
|
+
};
|
|
7720
|
+
}
|
|
7721
|
+
/**
|
|
7722
|
+
* Build the vendor shell (shared across all tools).
|
|
7723
|
+
*
|
|
7724
|
+
* The vendor shell contains:
|
|
7725
|
+
* - React/ReactDOM from CDN
|
|
7726
|
+
* - FrontMCP Bridge runtime
|
|
7727
|
+
* - Theme CSS and fonts
|
|
7728
|
+
* - Component injection point
|
|
7729
|
+
*
|
|
7730
|
+
* @returns Vendor shell HTML
|
|
7731
|
+
*/
|
|
7732
|
+
async buildVendorShell() {
|
|
7733
|
+
if (this.vendorShellCache) {
|
|
7734
|
+
return this.vendorShellCache;
|
|
7735
|
+
}
|
|
7736
|
+
const head = this.buildHead({
|
|
7737
|
+
title: "FrontMCP Widget",
|
|
7738
|
+
includeBridge: true,
|
|
7739
|
+
includeCdn: this.cdnMode === "cdn",
|
|
7740
|
+
includeTheme: true
|
|
7741
|
+
});
|
|
7742
|
+
const cdnScripts = this.cdnMode === "cdn" ? generateCdnScriptTags(false) + generateGlobalsSetupScript() : "";
|
|
7743
|
+
const body = `
|
|
7744
|
+
<script>
|
|
7745
|
+
window.__mcpToolName = '';
|
|
7746
|
+
window.__mcpToolInput = {};
|
|
7747
|
+
window.__mcpToolOutput = {};
|
|
7748
|
+
window.__mcpStructuredContent = {};
|
|
7749
|
+
</script>
|
|
7750
|
+
${cdnScripts}
|
|
7751
|
+
<div id="frontmcp-widget-root">
|
|
7752
|
+
<div id="root" class="min-h-[200px]">
|
|
7753
|
+
<!-- Component will be injected here -->
|
|
7754
|
+
<div class="flex items-center justify-center p-4">
|
|
7755
|
+
<div class="text-center text-gray-500">
|
|
7756
|
+
<svg class="animate-spin mx-auto mb-2" style="width: 1.5rem; height: 1.5rem; color: #9ca3af;" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
7757
|
+
<circle style="opacity: 0.25;" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
7758
|
+
<path style="opacity: 0.75;" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
7759
|
+
</svg>
|
|
7760
|
+
<p class="text-sm">Loading component...</p>
|
|
7761
|
+
</div>
|
|
7762
|
+
</div>
|
|
7763
|
+
</div>
|
|
7764
|
+
</div>
|
|
7765
|
+
|
|
7766
|
+
<!-- Component injection script -->
|
|
7767
|
+
<script type="module">
|
|
7768
|
+
// Wait for component code to be injected
|
|
7769
|
+
window.__frontmcpInjectComponent = async function(componentCode) {
|
|
7770
|
+
try {
|
|
7771
|
+
// Wait for runtime
|
|
7772
|
+
if (!window.__frontmcpRuntimeReady) {
|
|
7773
|
+
await new Promise((resolve) => {
|
|
7774
|
+
window.addEventListener('frontmcp:runtime-ready', resolve, { once: true });
|
|
7775
|
+
});
|
|
7776
|
+
}
|
|
7777
|
+
|
|
7778
|
+
// Execute component code
|
|
7779
|
+
const blob = new Blob([componentCode], { type: 'application/javascript' });
|
|
7780
|
+
const url = URL.createObjectURL(blob);
|
|
7781
|
+
const module = await import(url);
|
|
7782
|
+
URL.revokeObjectURL(url);
|
|
7783
|
+
|
|
7784
|
+
// Render component
|
|
7785
|
+
const React = window.React;
|
|
7786
|
+
const ReactDOM = window.ReactDOM;
|
|
7787
|
+
const Component = module.default || module.Widget || module.Component;
|
|
7788
|
+
|
|
7789
|
+
if (Component) {
|
|
7790
|
+
const root = ReactDOM.createRoot(document.getElementById('root'));
|
|
7791
|
+
root.render(React.createElement(Component, {
|
|
7792
|
+
input: window.__mcpToolInput,
|
|
7793
|
+
output: window.__mcpToolOutput,
|
|
7794
|
+
}));
|
|
7795
|
+
}
|
|
7796
|
+
} catch (error) {
|
|
7797
|
+
console.error('[FrontMCP] Component injection failed:', error);
|
|
7798
|
+
document.getElementById('root').innerHTML =
|
|
7799
|
+
'<div class="p-4 text-red-500">Component failed to load</div>';
|
|
7800
|
+
}
|
|
7801
|
+
};
|
|
7802
|
+
|
|
7803
|
+
// Listen for component via bridge
|
|
7804
|
+
if (window.FrontMcpBridge) {
|
|
7805
|
+
const checkForComponent = () => {
|
|
7806
|
+
const meta = window.FrontMcpBridge.getToolResponseMetadata?.() || {};
|
|
7807
|
+
const componentCode = meta['ui/component'] || meta['openai/component'];
|
|
7808
|
+
if (componentCode) {
|
|
7809
|
+
window.__frontmcpInjectComponent(componentCode);
|
|
7810
|
+
}
|
|
7811
|
+
};
|
|
7812
|
+
|
|
7813
|
+
if (window.FrontMcpBridge.onToolResponseMetadata) {
|
|
7814
|
+
window.FrontMcpBridge.onToolResponseMetadata((meta) => {
|
|
7815
|
+
const componentCode = meta['ui/component'] || meta['openai/component'];
|
|
7816
|
+
if (componentCode) {
|
|
7817
|
+
window.__frontmcpInjectComponent(componentCode);
|
|
7818
|
+
}
|
|
7819
|
+
});
|
|
7820
|
+
}
|
|
7821
|
+
|
|
7822
|
+
// Check immediately in case data is already available
|
|
7823
|
+
checkForComponent();
|
|
7824
|
+
}
|
|
7825
|
+
</script>
|
|
7826
|
+
`;
|
|
7827
|
+
const html = this.wrapInHtmlDocument({
|
|
7828
|
+
head,
|
|
7829
|
+
body,
|
|
7830
|
+
bodyClass: "antialiased"
|
|
7831
|
+
});
|
|
7832
|
+
this.vendorShellCache = html;
|
|
7833
|
+
return html;
|
|
7834
|
+
}
|
|
7835
|
+
/**
|
|
7836
|
+
* Build a component chunk for a specific template.
|
|
7837
|
+
*
|
|
7838
|
+
* The component chunk is transpiled with externalized dependencies
|
|
7839
|
+
* (React, etc.) that are provided by the vendor shell.
|
|
7840
|
+
*
|
|
7841
|
+
* @param template - Component template
|
|
7842
|
+
* @returns Transpiled component code
|
|
7843
|
+
*/
|
|
7844
|
+
async buildComponentChunk(template) {
|
|
7845
|
+
const detection = this.detectTemplate(template);
|
|
7846
|
+
if (detection.renderer === "html") {
|
|
7847
|
+
return this.wrapHtmlAsComponent(template);
|
|
7848
|
+
}
|
|
7849
|
+
if (typeof template === "function") {
|
|
7850
|
+
return this.transpileReactComponent(template);
|
|
7851
|
+
}
|
|
7852
|
+
return `
|
|
7853
|
+
// Externalized React component
|
|
7854
|
+
const React = window.React;
|
|
7855
|
+
|
|
7856
|
+
export default function Widget({ input, output }) {
|
|
7857
|
+
return React.createElement('div', {
|
|
7858
|
+
className: 'p-4',
|
|
7859
|
+
}, React.createElement('pre', null, JSON.stringify(output, null, 2)));
|
|
7860
|
+
}
|
|
7861
|
+
`;
|
|
7862
|
+
}
|
|
7863
|
+
/**
|
|
7864
|
+
* Combine shell and component for Claude/inline delivery.
|
|
7865
|
+
*
|
|
7866
|
+
* @param shell - Vendor shell HTML
|
|
7867
|
+
* @param component - Component chunk code
|
|
7868
|
+
* @param input - Tool input data
|
|
7869
|
+
* @param output - Tool output data
|
|
7870
|
+
* @returns Complete HTML with embedded component and data
|
|
7871
|
+
*/
|
|
7872
|
+
combineForInline(shell, component, input, output) {
|
|
7873
|
+
let result = shell.replace("window.__mcpToolInput = {};", `window.__mcpToolInput = ${JSON.stringify(input)};`).replace("window.__mcpToolOutput = {};", `window.__mcpToolOutput = ${JSON.stringify(output)};`).replace("window.__mcpStructuredContent = {};", `window.__mcpStructuredContent = ${JSON.stringify(output)};`);
|
|
7874
|
+
const componentInjection = `
|
|
7875
|
+
<script type="module">
|
|
7876
|
+
(async function() {
|
|
7877
|
+
// Wait for runtime
|
|
7878
|
+
if (!window.__frontmcpRuntimeReady) {
|
|
7879
|
+
await new Promise((resolve) => {
|
|
7880
|
+
window.addEventListener('frontmcp:runtime-ready', resolve, { once: true });
|
|
7881
|
+
});
|
|
7882
|
+
}
|
|
7883
|
+
|
|
7884
|
+
// Execute component
|
|
7885
|
+
${component}
|
|
7886
|
+
|
|
7887
|
+
// Render
|
|
7888
|
+
const React = window.React;
|
|
7889
|
+
const ReactDOM = window.ReactDOM;
|
|
7890
|
+
const Component = typeof Widget !== 'undefined' ? Widget : (typeof exports !== 'undefined' ? exports.default : null);
|
|
7891
|
+
|
|
7892
|
+
if (Component) {
|
|
7893
|
+
const root = ReactDOM.createRoot(document.getElementById('root'));
|
|
7894
|
+
root.render(React.createElement(Component, {
|
|
7895
|
+
input: window.__mcpToolInput,
|
|
7896
|
+
output: window.__mcpToolOutput,
|
|
7897
|
+
}));
|
|
7898
|
+
}
|
|
7899
|
+
})();
|
|
7900
|
+
</script>
|
|
7901
|
+
`;
|
|
7902
|
+
result = result.replace("</body>", componentInjection + "\n</body>");
|
|
7903
|
+
return result;
|
|
7904
|
+
}
|
|
7905
|
+
// ============================================
|
|
7906
|
+
// Private Methods
|
|
7907
|
+
// ============================================
|
|
7908
|
+
/**
|
|
7909
|
+
* Wrap HTML template as a React component.
|
|
7910
|
+
*/
|
|
7911
|
+
wrapHtmlAsComponent(template) {
|
|
7912
|
+
if (typeof template === "string") {
|
|
7913
|
+
return `
|
|
7914
|
+
// HTML template wrapped as component
|
|
7915
|
+
const React = window.React;
|
|
7916
|
+
|
|
7917
|
+
export default function Widget({ input, output }) {
|
|
7918
|
+
return React.createElement('div', {
|
|
7919
|
+
dangerouslySetInnerHTML: { __html: ${JSON.stringify(template)} }
|
|
7920
|
+
});
|
|
7921
|
+
}
|
|
7922
|
+
`;
|
|
7923
|
+
}
|
|
7924
|
+
return `
|
|
7925
|
+
// HTML function template wrapped as component
|
|
7926
|
+
const React = window.React;
|
|
7927
|
+
|
|
7928
|
+
export default function Widget({ input, output }) {
|
|
7929
|
+
const html = (${template.toString()})({ input, output, helpers: {} });
|
|
7930
|
+
return React.createElement('div', {
|
|
7931
|
+
dangerouslySetInnerHTML: { __html: html }
|
|
7932
|
+
});
|
|
7933
|
+
}
|
|
7934
|
+
`;
|
|
7935
|
+
}
|
|
7936
|
+
/**
|
|
7937
|
+
* Transpile a React component function.
|
|
7938
|
+
*/
|
|
7939
|
+
async transpileReactComponent(component) {
|
|
7940
|
+
const funcString = component.toString();
|
|
7941
|
+
const componentName = component.name || "Widget";
|
|
7942
|
+
const source = `
|
|
7943
|
+
// Externalized React component
|
|
7944
|
+
const React = window.React;
|
|
7945
|
+
|
|
7946
|
+
const ${componentName} = ${funcString};
|
|
7947
|
+
|
|
7948
|
+
export default ${componentName};
|
|
7949
|
+
export { ${componentName} as Widget, ${componentName} as Component };
|
|
7950
|
+
`;
|
|
7951
|
+
try {
|
|
7952
|
+
const result = await this.transpile(source, {
|
|
7953
|
+
externals: DEFAULT_EXTERNALS,
|
|
7954
|
+
format: "esm",
|
|
7955
|
+
minify: this.minify
|
|
7956
|
+
});
|
|
7957
|
+
return result.code;
|
|
7958
|
+
} catch (error) {
|
|
7959
|
+
console.warn("[HybridBuilder] Transpilation failed, using source directly:", error);
|
|
7960
|
+
return source;
|
|
7961
|
+
}
|
|
7962
|
+
}
|
|
7963
|
+
};
|
|
7964
|
+
|
|
7965
|
+
// libs/uipack/src/build/builders/inline-builder.ts
|
|
7966
|
+
var InlineBuilder = class extends BaseBuilder {
|
|
7967
|
+
mode = "inline";
|
|
7968
|
+
constructor(options = {}) {
|
|
7969
|
+
super(options);
|
|
7970
|
+
}
|
|
7971
|
+
/**
|
|
7972
|
+
* Build an inline result with loader and full widget generator.
|
|
7973
|
+
*
|
|
7974
|
+
* @param options - Build options
|
|
7975
|
+
* @returns Inline build result
|
|
7976
|
+
*/
|
|
7977
|
+
async build(options) {
|
|
7978
|
+
const startTime = Date.now();
|
|
7979
|
+
const { template, toolName } = options;
|
|
7980
|
+
const loaderShell = this.buildLoader(toolName);
|
|
7981
|
+
const buildFullWidget = async (input, output) => {
|
|
7982
|
+
return this.buildFullWidget(template.template, input, output);
|
|
7983
|
+
};
|
|
7984
|
+
const hash = await this.calculateHash(loaderShell);
|
|
7985
|
+
const loaderSize = Buffer.byteLength(loaderShell, "utf8");
|
|
7986
|
+
const detection = this.detectTemplate(template.template);
|
|
7987
|
+
return {
|
|
7988
|
+
mode: "inline",
|
|
7989
|
+
loaderShell,
|
|
7990
|
+
buildFullWidget,
|
|
7991
|
+
hash,
|
|
7992
|
+
loaderSize,
|
|
7993
|
+
rendererType: detection.renderer,
|
|
7994
|
+
buildTime: new Date(startTime).toISOString()
|
|
7995
|
+
};
|
|
7996
|
+
}
|
|
7997
|
+
/**
|
|
7998
|
+
* Build the minimal loader shell.
|
|
7999
|
+
*
|
|
8000
|
+
* The loader contains:
|
|
8001
|
+
* - FrontMCP Bridge runtime
|
|
8002
|
+
* - Loading indicator
|
|
8003
|
+
* - Injector script that replaces document on tool response
|
|
8004
|
+
*
|
|
8005
|
+
* @param toolName - Name of the tool
|
|
8006
|
+
* @returns Loader HTML
|
|
8007
|
+
*/
|
|
8008
|
+
buildLoader(toolName) {
|
|
8009
|
+
const head = this.buildHead({
|
|
8010
|
+
title: `${toolName} Widget`,
|
|
8011
|
+
includeBridge: true,
|
|
8012
|
+
includeCdn: this.cdnMode === "cdn",
|
|
8013
|
+
includeTheme: true
|
|
8014
|
+
});
|
|
8015
|
+
const body = `
|
|
8016
|
+
<script>
|
|
8017
|
+
window.__mcpToolName = ${JSON.stringify(toolName)};
|
|
8018
|
+
window.__mcpLeanShell = true;
|
|
8019
|
+
</script>
|
|
8020
|
+
|
|
8021
|
+
<div id="frontmcp-widget-root" class="flex items-center justify-center min-h-[200px] p-4">
|
|
8022
|
+
<div class="text-center text-gray-500">
|
|
8023
|
+
<svg class="animate-spin mx-auto mb-2" style="width: 1.5rem; height: 1.5rem; color: #9ca3af;" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
8024
|
+
<circle style="opacity: 0.25;" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
8025
|
+
<path style="opacity: 0.75;" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
8026
|
+
</svg>
|
|
8027
|
+
<p class="text-sm">Loading widget...</p>
|
|
8028
|
+
</div>
|
|
8029
|
+
</div>
|
|
8030
|
+
|
|
8031
|
+
<!-- Injector script -->
|
|
8032
|
+
<script>
|
|
8033
|
+
(function() {
|
|
8034
|
+
var injected = false;
|
|
8035
|
+
|
|
8036
|
+
function injectWidget(metadata) {
|
|
8037
|
+
if (injected) return;
|
|
8038
|
+
|
|
8039
|
+
var html = null;
|
|
8040
|
+
if (metadata) {
|
|
8041
|
+
html = metadata['ui/html'] || metadata['openai/html'] || metadata.html;
|
|
8042
|
+
}
|
|
8043
|
+
|
|
8044
|
+
if (html && typeof html === 'string') {
|
|
8045
|
+
injected = true;
|
|
8046
|
+
console.log('[FrontMCP] Inline shell: Injecting widget HTML (' + html.length + ' chars)');
|
|
8047
|
+
document.open();
|
|
8048
|
+
document.write(html);
|
|
8049
|
+
document.close();
|
|
8050
|
+
return true;
|
|
8051
|
+
}
|
|
8052
|
+
return false;
|
|
8053
|
+
}
|
|
8054
|
+
|
|
8055
|
+
function subscribeAndInject() {
|
|
8056
|
+
var bridge = window.FrontMcpBridge;
|
|
8057
|
+
if (!bridge) {
|
|
8058
|
+
console.warn('[FrontMCP] Inline shell: Bridge not found');
|
|
8059
|
+
return;
|
|
8060
|
+
}
|
|
8061
|
+
|
|
8062
|
+
// Check if data already available
|
|
8063
|
+
if (typeof bridge.getToolResponseMetadata === 'function') {
|
|
8064
|
+
var existing = bridge.getToolResponseMetadata();
|
|
8065
|
+
if (existing && injectWidget(existing)) {
|
|
8066
|
+
return;
|
|
8067
|
+
}
|
|
8068
|
+
}
|
|
8069
|
+
|
|
8070
|
+
// Subscribe to metadata changes
|
|
8071
|
+
if (typeof bridge.onToolResponseMetadata === 'function') {
|
|
8072
|
+
console.log('[FrontMCP] Inline shell: Subscribing to tool response metadata');
|
|
8073
|
+
bridge.onToolResponseMetadata(function(metadata) {
|
|
8074
|
+
console.log('[FrontMCP] Inline shell: Received tool response metadata');
|
|
8075
|
+
injectWidget(metadata);
|
|
8076
|
+
});
|
|
8077
|
+
}
|
|
8078
|
+
}
|
|
8079
|
+
|
|
8080
|
+
// Wait for bridge:ready event
|
|
8081
|
+
window.addEventListener('bridge:ready', function() {
|
|
8082
|
+
console.log('[FrontMCP] Inline shell: Bridge ready, setting up injector');
|
|
8083
|
+
subscribeAndInject();
|
|
8084
|
+
});
|
|
8085
|
+
|
|
8086
|
+
// Also try immediately in case bridge is already ready
|
|
8087
|
+
if (window.FrontMcpBridge && window.FrontMcpBridge.initialized) {
|
|
8088
|
+
subscribeAndInject();
|
|
8089
|
+
}
|
|
8090
|
+
|
|
8091
|
+
// Fallback: poll for bridge
|
|
8092
|
+
var attempts = 0;
|
|
8093
|
+
var interval = setInterval(function() {
|
|
8094
|
+
attempts++;
|
|
8095
|
+
if (window.FrontMcpBridge) {
|
|
8096
|
+
clearInterval(interval);
|
|
8097
|
+
if (!injected) {
|
|
8098
|
+
subscribeAndInject();
|
|
8099
|
+
}
|
|
8100
|
+
} else if (attempts >= 100) {
|
|
8101
|
+
clearInterval(interval);
|
|
8102
|
+
console.warn('[FrontMCP] Inline shell: Timeout waiting for bridge');
|
|
8103
|
+
}
|
|
8104
|
+
}, 100);
|
|
8105
|
+
})();
|
|
8106
|
+
</script>
|
|
8107
|
+
|
|
8108
|
+
<style>
|
|
8109
|
+
@keyframes spin {
|
|
8110
|
+
from { transform: rotate(0deg); }
|
|
8111
|
+
to { transform: rotate(360deg); }
|
|
8112
|
+
}
|
|
8113
|
+
.animate-spin {
|
|
8114
|
+
animation: spin 1s linear infinite;
|
|
8115
|
+
}
|
|
8116
|
+
</style>
|
|
8117
|
+
`;
|
|
8118
|
+
return this.wrapInHtmlDocument({
|
|
8119
|
+
head,
|
|
8120
|
+
body,
|
|
8121
|
+
bodyClass: "antialiased"
|
|
8122
|
+
});
|
|
8123
|
+
}
|
|
8124
|
+
/**
|
|
8125
|
+
* Build full widget HTML with embedded data.
|
|
8126
|
+
*
|
|
8127
|
+
* @param template - Component template
|
|
8128
|
+
* @param input - Tool input data
|
|
8129
|
+
* @param output - Tool output data
|
|
8130
|
+
* @returns Complete HTML with all dependencies and data
|
|
8131
|
+
*/
|
|
8132
|
+
async buildFullWidget(template, input, output) {
|
|
8133
|
+
const detection = this.detectTemplate(template);
|
|
8134
|
+
const head = this.buildHead({
|
|
8135
|
+
title: "FrontMCP Widget",
|
|
8136
|
+
includeBridge: true,
|
|
8137
|
+
includeCdn: this.cdnMode === "cdn",
|
|
8138
|
+
includeTheme: true
|
|
8139
|
+
});
|
|
8140
|
+
const dataScript = this.buildDataInjectionScript({
|
|
8141
|
+
toolName: "widget",
|
|
8142
|
+
input,
|
|
8143
|
+
output,
|
|
8144
|
+
usePlaceholders: false
|
|
8145
|
+
});
|
|
8146
|
+
let content;
|
|
8147
|
+
if (detection.renderer === "html") {
|
|
8148
|
+
const context = this.createContext(input, output);
|
|
8149
|
+
if (typeof template === "function") {
|
|
8150
|
+
content = template(context);
|
|
8151
|
+
} else {
|
|
8152
|
+
content = template;
|
|
8153
|
+
}
|
|
8154
|
+
content = `
|
|
8155
|
+
<div id="frontmcp-widget-root">
|
|
8156
|
+
${content}
|
|
8157
|
+
</div>
|
|
8158
|
+
`;
|
|
8159
|
+
} else {
|
|
8160
|
+
content = this.buildReactContent(template, input, output);
|
|
8161
|
+
}
|
|
8162
|
+
const body = `
|
|
8163
|
+
${dataScript}
|
|
8164
|
+
${detection.renderer === "react" ? this.buildReactScripts() : ""}
|
|
8165
|
+
${content}
|
|
8166
|
+
`;
|
|
8167
|
+
const html = this.wrapInHtmlDocument({
|
|
8168
|
+
head,
|
|
8169
|
+
body,
|
|
8170
|
+
bodyClass: "antialiased"
|
|
8171
|
+
});
|
|
8172
|
+
return this.minify ? this.minifyHtml(html) : html;
|
|
8173
|
+
}
|
|
8174
|
+
// ============================================
|
|
8175
|
+
// Private Methods
|
|
8176
|
+
// ============================================
|
|
8177
|
+
/**
|
|
8178
|
+
* Build React scripts for client-side rendering.
|
|
8179
|
+
*/
|
|
8180
|
+
buildReactScripts() {
|
|
8181
|
+
if (this.cdnMode === "cdn") {
|
|
8182
|
+
return generateCdnScriptTags(false) + generateGlobalsSetupScript();
|
|
8183
|
+
}
|
|
8184
|
+
return `
|
|
8185
|
+
<script>
|
|
8186
|
+
console.warn('[FrontMCP] Inline React runtime not yet implemented');
|
|
8187
|
+
</script>
|
|
8188
|
+
`;
|
|
8189
|
+
}
|
|
8190
|
+
/**
|
|
8191
|
+
* Build React content with client-side rendering.
|
|
8192
|
+
*/
|
|
8193
|
+
buildReactContent(_template, _input, _output) {
|
|
8194
|
+
return `
|
|
8195
|
+
<div id="frontmcp-widget-root">
|
|
8196
|
+
<div id="root" class="min-h-[200px]">
|
|
8197
|
+
<div class="flex items-center justify-center p-4">
|
|
8198
|
+
<div class="text-center text-gray-500">
|
|
8199
|
+
<p class="text-sm">Initializing...</p>
|
|
8200
|
+
</div>
|
|
8201
|
+
</div>
|
|
8202
|
+
</div>
|
|
8203
|
+
</div>
|
|
8204
|
+
|
|
8205
|
+
<script type="module">
|
|
8206
|
+
// Wait for runtime
|
|
8207
|
+
function waitForRuntime() {
|
|
8208
|
+
return new Promise((resolve) => {
|
|
8209
|
+
if (window.__frontmcpRuntimeReady) {
|
|
8210
|
+
resolve();
|
|
8211
|
+
} else {
|
|
8212
|
+
window.addEventListener('frontmcp:runtime-ready', resolve, { once: true });
|
|
8213
|
+
}
|
|
8214
|
+
});
|
|
8215
|
+
}
|
|
8216
|
+
|
|
8217
|
+
async function renderWidget() {
|
|
8218
|
+
await waitForRuntime();
|
|
8219
|
+
|
|
8220
|
+
const React = window.React;
|
|
8221
|
+
const ReactDOM = window.ReactDOM;
|
|
8222
|
+
|
|
8223
|
+
const input = window.__mcpToolInput || {};
|
|
8224
|
+
const output = window.__mcpToolOutput || {};
|
|
8225
|
+
|
|
8226
|
+
function Widget() {
|
|
8227
|
+
return React.createElement('div', {
|
|
8228
|
+
className: 'p-4',
|
|
8229
|
+
}, React.createElement('pre', {
|
|
8230
|
+
className: 'bg-gray-100 p-2 rounded overflow-auto',
|
|
8231
|
+
}, JSON.stringify(output, null, 2)));
|
|
8232
|
+
}
|
|
8233
|
+
|
|
8234
|
+
const root = ReactDOM.createRoot(document.getElementById('root'));
|
|
8235
|
+
root.render(React.createElement(Widget));
|
|
8236
|
+
}
|
|
8237
|
+
|
|
8238
|
+
renderWidget().catch(console.error);
|
|
8239
|
+
</script>
|
|
8240
|
+
`;
|
|
8241
|
+
}
|
|
8242
|
+
/**
|
|
8243
|
+
* Simple HTML minification.
|
|
8244
|
+
*/
|
|
8245
|
+
minifyHtml(html) {
|
|
8246
|
+
return html.replace(/>\s+</g, "><").replace(/\s{2,}/g, " ").trim();
|
|
8247
|
+
}
|
|
8248
|
+
};
|
|
8249
|
+
|
|
6594
8250
|
// libs/uipack/src/build/index.ts
|
|
6595
8251
|
async function buildToolUI(options) {
|
|
6596
8252
|
const startTime = Date.now();
|
|
@@ -6738,49 +8394,78 @@ async function buildToolUIMulti(options) {
|
|
|
6738
8394
|
};
|
|
6739
8395
|
}
|
|
6740
8396
|
export {
|
|
8397
|
+
BaseBuilder,
|
|
8398
|
+
CDN_URLS,
|
|
6741
8399
|
CLAUDE_PLATFORM,
|
|
6742
8400
|
CLOUDFLARE_CDN,
|
|
8401
|
+
CLOUDFLARE_CDN_URLS,
|
|
6743
8402
|
DEFAULT_CSP_BY_TYPE,
|
|
8403
|
+
DEFAULT_EXTERNALS,
|
|
6744
8404
|
DEFAULT_RENDERER_ASSETS,
|
|
6745
8405
|
DEFAULT_THEME,
|
|
8406
|
+
EXTERNAL_GLOBALS,
|
|
6746
8407
|
HANDLEBARS_CDN,
|
|
8408
|
+
HYBRID_DATA_PLACEHOLDER,
|
|
8409
|
+
HYBRID_INPUT_PLACEHOLDER,
|
|
8410
|
+
HybridBuilder,
|
|
8411
|
+
InlineBuilder,
|
|
6747
8412
|
MARKED_CDN,
|
|
6748
8413
|
MDX_RUNTIME_CDN,
|
|
6749
8414
|
OPENAI_PLATFORM,
|
|
6750
|
-
|
|
8415
|
+
REACT_CDN,
|
|
6751
8416
|
REACT_DOM_CDN,
|
|
8417
|
+
StaticBuilder,
|
|
6752
8418
|
TAILWIND_CDN,
|
|
6753
8419
|
batchBuildWidgets,
|
|
8420
|
+
buildAlertComponent,
|
|
8421
|
+
buildBadgeComponent,
|
|
8422
|
+
buildButtonComponent,
|
|
6754
8423
|
buildCDNInfoForUIType,
|
|
6755
8424
|
buildCDNScriptTag,
|
|
6756
8425
|
buildCSPForType,
|
|
6757
8426
|
buildCSPMetaContent,
|
|
8427
|
+
buildCardComponent,
|
|
6758
8428
|
buildCloudflareScriptTag,
|
|
6759
8429
|
buildCloudflareStylesheetTag,
|
|
6760
8430
|
buildFileComponent,
|
|
6761
8431
|
buildFileComponents,
|
|
8432
|
+
buildNamespaceExport,
|
|
6762
8433
|
buildScriptsForUIType,
|
|
6763
8434
|
buildStaticWidget,
|
|
8435
|
+
buildStyleConstants,
|
|
6764
8436
|
buildTailwindScriptTag,
|
|
6765
8437
|
buildToolResponseMeta,
|
|
6766
8438
|
buildToolUI,
|
|
6767
8439
|
buildToolUIMulti,
|
|
6768
8440
|
buildToolWidgetManifest,
|
|
8441
|
+
buildUIComponentsRuntime,
|
|
8442
|
+
createExternalizedConfig,
|
|
8443
|
+
createExternalsBanner,
|
|
8444
|
+
createInlineConfig,
|
|
6769
8445
|
createTemplateHelpers,
|
|
8446
|
+
createTransformConfig,
|
|
6770
8447
|
detectUIType,
|
|
8448
|
+
generateCdnScriptTags,
|
|
8449
|
+
generateGlobalsSetupScript,
|
|
6771
8450
|
getCachedFileComponent,
|
|
6772
8451
|
getDefaultAssets,
|
|
8452
|
+
getHybridPlaceholders,
|
|
6773
8453
|
getOutputModeForClient,
|
|
6774
8454
|
getPlatformFromClientInfo,
|
|
6775
8455
|
getRendererAssets,
|
|
6776
8456
|
getTailwindForPlatform,
|
|
6777
8457
|
getURLsToPreFetch,
|
|
6778
8458
|
hasInlineScripts,
|
|
8459
|
+
injectHybridData,
|
|
8460
|
+
injectHybridDataFull,
|
|
8461
|
+
injectHybridDataWithTrigger,
|
|
6779
8462
|
isBundlingMode,
|
|
6780
8463
|
isDisplayMode,
|
|
6781
8464
|
isFilePathTemplate,
|
|
8465
|
+
isHybridShell,
|
|
6782
8466
|
isOutputMode,
|
|
6783
8467
|
isResourceMode,
|
|
6784
8468
|
isUIType,
|
|
6785
|
-
needsFileComponentRebuild
|
|
8469
|
+
needsFileComponentRebuild,
|
|
8470
|
+
needsInputInjection
|
|
6786
8471
|
};
|