@frontmcp/ui 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.
Files changed (292) hide show
  1. package/bridge/core/bridge-factory.d.ts +1 -0
  2. package/bridge/core/bridge-factory.d.ts.map +1 -1
  3. package/bridge/index.d.ts +1 -1
  4. package/bridge/index.d.ts.map +1 -1
  5. package/bridge/index.js +39 -881
  6. package/bundler/browser-components.d.ts +42 -0
  7. package/bundler/browser-components.d.ts.map +1 -0
  8. package/bundler/bundler.d.ts +78 -4
  9. package/bundler/bundler.d.ts.map +1 -1
  10. package/bundler/index.d.ts +8 -8
  11. package/bundler/index.d.ts.map +1 -1
  12. package/bundler/index.js +1315 -1854
  13. package/bundler/types.d.ts +188 -7
  14. package/bundler/types.d.ts.map +1 -1
  15. package/esm/bridge/{index.js → index.mjs} +40 -877
  16. package/esm/bundler/{index.js → index.mjs} +1391 -1895
  17. package/esm/{index.js → index.mjs} +215 -3091
  18. package/esm/layouts/{index.js → index.mjs} +3 -3
  19. package/esm/package.json +9 -8
  20. package/esm/react/index.mjs +1183 -0
  21. package/esm/renderers/index.mjs +611 -0
  22. package/esm/universal/{index.js → index.mjs} +266 -70
  23. package/index.d.ts +1 -4
  24. package/index.d.ts.map +1 -1
  25. package/index.js +208 -3113
  26. package/layouts/base.d.ts.map +1 -1
  27. package/layouts/index.js +3 -3
  28. package/layouts/presets.d.ts.map +1 -1
  29. package/package.json +9 -8
  30. package/react/Badge.d.ts.map +1 -1
  31. package/react/hooks/context.d.ts.map +1 -1
  32. package/react/index.d.ts +0 -1
  33. package/react/index.d.ts.map +1 -1
  34. package/react/index.js +57 -2001
  35. package/react/types.d.ts.map +1 -1
  36. package/renderers/index.d.ts +9 -4
  37. package/renderers/index.d.ts.map +1 -1
  38. package/renderers/index.js +328 -88
  39. package/renderers/mdx.renderer.d.ts +99 -0
  40. package/renderers/mdx.renderer.d.ts.map +1 -0
  41. package/renderers/react.renderer.d.ts +22 -13
  42. package/renderers/react.renderer.d.ts.map +1 -1
  43. package/renderers/transpiler.d.ts +49 -0
  44. package/renderers/transpiler.d.ts.map +1 -0
  45. package/universal/cached-runtime.d.ts +25 -1
  46. package/universal/cached-runtime.d.ts.map +1 -1
  47. package/universal/index.js +266 -70
  48. package/universal/runtime-builder.d.ts.map +1 -1
  49. package/universal/types.d.ts.map +1 -1
  50. package/web-components/elements/fmcp-input.d.ts.map +1 -1
  51. package/web-components/elements/fmcp-select.d.ts.map +1 -1
  52. package/web-components/index.d.ts +0 -1
  53. package/web-components/index.d.ts.map +1 -1
  54. package/bundler/cache.d.ts +0 -173
  55. package/bundler/cache.d.ts.map +0 -1
  56. package/bundler/file-cache/component-builder.d.ts +0 -167
  57. package/bundler/file-cache/component-builder.d.ts.map +0 -1
  58. package/bundler/file-cache/hash-calculator.d.ts +0 -155
  59. package/bundler/file-cache/hash-calculator.d.ts.map +0 -1
  60. package/bundler/file-cache/index.d.ts +0 -12
  61. package/bundler/file-cache/index.d.ts.map +0 -1
  62. package/bundler/file-cache/storage/filesystem.d.ts +0 -149
  63. package/bundler/file-cache/storage/filesystem.d.ts.map +0 -1
  64. package/bundler/file-cache/storage/index.d.ts +0 -11
  65. package/bundler/file-cache/storage/index.d.ts.map +0 -1
  66. package/bundler/file-cache/storage/interface.d.ts +0 -152
  67. package/bundler/file-cache/storage/interface.d.ts.map +0 -1
  68. package/bundler/file-cache/storage/redis.d.ts +0 -139
  69. package/bundler/file-cache/storage/redis.d.ts.map +0 -1
  70. package/bundler/sandbox/enclave-adapter.d.ts +0 -121
  71. package/bundler/sandbox/enclave-adapter.d.ts.map +0 -1
  72. package/bundler/sandbox/executor.d.ts +0 -14
  73. package/bundler/sandbox/executor.d.ts.map +0 -1
  74. package/bundler/sandbox/policy.d.ts +0 -62
  75. package/bundler/sandbox/policy.d.ts.map +0 -1
  76. package/esm/bridge/adapters/base-adapter.d.ts +0 -104
  77. package/esm/bridge/adapters/base-adapter.d.ts.map +0 -1
  78. package/esm/bridge/adapters/claude.adapter.d.ts +0 -67
  79. package/esm/bridge/adapters/claude.adapter.d.ts.map +0 -1
  80. package/esm/bridge/adapters/ext-apps.adapter.d.ts +0 -143
  81. package/esm/bridge/adapters/ext-apps.adapter.d.ts.map +0 -1
  82. package/esm/bridge/adapters/gemini.adapter.d.ts +0 -64
  83. package/esm/bridge/adapters/gemini.adapter.d.ts.map +0 -1
  84. package/esm/bridge/adapters/generic.adapter.d.ts +0 -56
  85. package/esm/bridge/adapters/generic.adapter.d.ts.map +0 -1
  86. package/esm/bridge/adapters/index.d.ts +0 -26
  87. package/esm/bridge/adapters/index.d.ts.map +0 -1
  88. package/esm/bridge/adapters/openai.adapter.d.ts +0 -65
  89. package/esm/bridge/adapters/openai.adapter.d.ts.map +0 -1
  90. package/esm/bridge/core/adapter-registry.d.ts +0 -122
  91. package/esm/bridge/core/adapter-registry.d.ts.map +0 -1
  92. package/esm/bridge/core/bridge-factory.d.ts +0 -199
  93. package/esm/bridge/core/bridge-factory.d.ts.map +0 -1
  94. package/esm/bridge/core/index.d.ts +0 -10
  95. package/esm/bridge/core/index.d.ts.map +0 -1
  96. package/esm/bridge/index.d.ts +0 -62
  97. package/esm/bridge/index.d.ts.map +0 -1
  98. package/esm/bridge/runtime/iife-generator.d.ts +0 -62
  99. package/esm/bridge/runtime/iife-generator.d.ts.map +0 -1
  100. package/esm/bridge/runtime/index.d.ts +0 -10
  101. package/esm/bridge/runtime/index.d.ts.map +0 -1
  102. package/esm/bridge/types.d.ts +0 -386
  103. package/esm/bridge/types.d.ts.map +0 -1
  104. package/esm/bundler/bundler.d.ts +0 -208
  105. package/esm/bundler/bundler.d.ts.map +0 -1
  106. package/esm/bundler/cache.d.ts +0 -173
  107. package/esm/bundler/cache.d.ts.map +0 -1
  108. package/esm/bundler/file-cache/component-builder.d.ts +0 -167
  109. package/esm/bundler/file-cache/component-builder.d.ts.map +0 -1
  110. package/esm/bundler/file-cache/hash-calculator.d.ts +0 -155
  111. package/esm/bundler/file-cache/hash-calculator.d.ts.map +0 -1
  112. package/esm/bundler/file-cache/index.d.ts +0 -12
  113. package/esm/bundler/file-cache/index.d.ts.map +0 -1
  114. package/esm/bundler/file-cache/storage/filesystem.d.ts +0 -149
  115. package/esm/bundler/file-cache/storage/filesystem.d.ts.map +0 -1
  116. package/esm/bundler/file-cache/storage/index.d.ts +0 -11
  117. package/esm/bundler/file-cache/storage/index.d.ts.map +0 -1
  118. package/esm/bundler/file-cache/storage/interface.d.ts +0 -152
  119. package/esm/bundler/file-cache/storage/interface.d.ts.map +0 -1
  120. package/esm/bundler/file-cache/storage/redis.d.ts +0 -139
  121. package/esm/bundler/file-cache/storage/redis.d.ts.map +0 -1
  122. package/esm/bundler/index.d.ts +0 -43
  123. package/esm/bundler/index.d.ts.map +0 -1
  124. package/esm/bundler/sandbox/enclave-adapter.d.ts +0 -121
  125. package/esm/bundler/sandbox/enclave-adapter.d.ts.map +0 -1
  126. package/esm/bundler/sandbox/executor.d.ts +0 -14
  127. package/esm/bundler/sandbox/executor.d.ts.map +0 -1
  128. package/esm/bundler/sandbox/policy.d.ts +0 -62
  129. package/esm/bundler/sandbox/policy.d.ts.map +0 -1
  130. package/esm/bundler/types.d.ts +0 -702
  131. package/esm/bundler/types.d.ts.map +0 -1
  132. package/esm/components/alert.d.ts +0 -66
  133. package/esm/components/alert.d.ts.map +0 -1
  134. package/esm/components/alert.schema.d.ts +0 -98
  135. package/esm/components/alert.schema.d.ts.map +0 -1
  136. package/esm/components/avatar.d.ts +0 -77
  137. package/esm/components/avatar.d.ts.map +0 -1
  138. package/esm/components/avatar.schema.d.ts +0 -170
  139. package/esm/components/avatar.schema.d.ts.map +0 -1
  140. package/esm/components/badge.d.ts +0 -64
  141. package/esm/components/badge.d.ts.map +0 -1
  142. package/esm/components/badge.schema.d.ts +0 -91
  143. package/esm/components/badge.schema.d.ts.map +0 -1
  144. package/esm/components/button.d.ts +0 -100
  145. package/esm/components/button.d.ts.map +0 -1
  146. package/esm/components/button.schema.d.ts +0 -120
  147. package/esm/components/button.schema.d.ts.map +0 -1
  148. package/esm/components/card.d.ts +0 -53
  149. package/esm/components/card.d.ts.map +0 -1
  150. package/esm/components/card.schema.d.ts +0 -93
  151. package/esm/components/card.schema.d.ts.map +0 -1
  152. package/esm/components/form.d.ts +0 -212
  153. package/esm/components/form.d.ts.map +0 -1
  154. package/esm/components/form.schema.d.ts +0 -365
  155. package/esm/components/form.schema.d.ts.map +0 -1
  156. package/esm/components/index.d.ts +0 -29
  157. package/esm/components/index.d.ts.map +0 -1
  158. package/esm/components/list.d.ts +0 -121
  159. package/esm/components/list.d.ts.map +0 -1
  160. package/esm/components/list.schema.d.ts +0 -129
  161. package/esm/components/list.schema.d.ts.map +0 -1
  162. package/esm/components/modal.d.ts +0 -100
  163. package/esm/components/modal.d.ts.map +0 -1
  164. package/esm/components/modal.schema.d.ts +0 -151
  165. package/esm/components/modal.schema.d.ts.map +0 -1
  166. package/esm/components/table.d.ts +0 -91
  167. package/esm/components/table.d.ts.map +0 -1
  168. package/esm/components/table.schema.d.ts +0 -123
  169. package/esm/components/table.schema.d.ts.map +0 -1
  170. package/esm/index.d.ts +0 -40
  171. package/esm/index.d.ts.map +0 -1
  172. package/esm/layouts/base.d.ts +0 -86
  173. package/esm/layouts/base.d.ts.map +0 -1
  174. package/esm/layouts/index.d.ts +0 -8
  175. package/esm/layouts/index.d.ts.map +0 -1
  176. package/esm/layouts/presets.d.ts +0 -134
  177. package/esm/layouts/presets.d.ts.map +0 -1
  178. package/esm/pages/consent.d.ts +0 -117
  179. package/esm/pages/consent.d.ts.map +0 -1
  180. package/esm/pages/error.d.ts +0 -101
  181. package/esm/pages/error.d.ts.map +0 -1
  182. package/esm/pages/index.d.ts +0 -9
  183. package/esm/pages/index.d.ts.map +0 -1
  184. package/esm/pages/index.js +0 -1036
  185. package/esm/react/Alert.d.ts +0 -101
  186. package/esm/react/Alert.d.ts.map +0 -1
  187. package/esm/react/Badge.d.ts +0 -100
  188. package/esm/react/Badge.d.ts.map +0 -1
  189. package/esm/react/Button.d.ts +0 -108
  190. package/esm/react/Button.d.ts.map +0 -1
  191. package/esm/react/Card.d.ts +0 -103
  192. package/esm/react/Card.d.ts.map +0 -1
  193. package/esm/react/hooks/context.d.ts +0 -179
  194. package/esm/react/hooks/context.d.ts.map +0 -1
  195. package/esm/react/hooks/index.d.ts +0 -42
  196. package/esm/react/hooks/index.d.ts.map +0 -1
  197. package/esm/react/hooks/tools.d.ts +0 -284
  198. package/esm/react/hooks/tools.d.ts.map +0 -1
  199. package/esm/react/index.d.ts +0 -80
  200. package/esm/react/index.d.ts.map +0 -1
  201. package/esm/react/index.js +0 -3124
  202. package/esm/react/types.d.ts +0 -105
  203. package/esm/react/types.d.ts.map +0 -1
  204. package/esm/react/utils.d.ts +0 -43
  205. package/esm/react/utils.d.ts.map +0 -1
  206. package/esm/render/index.d.ts +0 -8
  207. package/esm/render/index.d.ts.map +0 -1
  208. package/esm/render/prerender.d.ts +0 -57
  209. package/esm/render/prerender.d.ts.map +0 -1
  210. package/esm/renderers/index.d.ts +0 -21
  211. package/esm/renderers/index.d.ts.map +0 -1
  212. package/esm/renderers/index.js +0 -381
  213. package/esm/renderers/react.adapter.d.ts +0 -70
  214. package/esm/renderers/react.adapter.d.ts.map +0 -1
  215. package/esm/renderers/react.renderer.d.ts +0 -96
  216. package/esm/renderers/react.renderer.d.ts.map +0 -1
  217. package/esm/universal/UniversalApp.d.ts +0 -108
  218. package/esm/universal/UniversalApp.d.ts.map +0 -1
  219. package/esm/universal/cached-runtime.d.ts +0 -115
  220. package/esm/universal/cached-runtime.d.ts.map +0 -1
  221. package/esm/universal/context.d.ts +0 -122
  222. package/esm/universal/context.d.ts.map +0 -1
  223. package/esm/universal/index.d.ts +0 -57
  224. package/esm/universal/index.d.ts.map +0 -1
  225. package/esm/universal/renderers/html.renderer.d.ts +0 -37
  226. package/esm/universal/renderers/html.renderer.d.ts.map +0 -1
  227. package/esm/universal/renderers/index.d.ts +0 -112
  228. package/esm/universal/renderers/index.d.ts.map +0 -1
  229. package/esm/universal/renderers/markdown.renderer.d.ts +0 -33
  230. package/esm/universal/renderers/markdown.renderer.d.ts.map +0 -1
  231. package/esm/universal/renderers/mdx.renderer.d.ts +0 -38
  232. package/esm/universal/renderers/mdx.renderer.d.ts.map +0 -1
  233. package/esm/universal/renderers/react.renderer.d.ts +0 -46
  234. package/esm/universal/renderers/react.renderer.d.ts.map +0 -1
  235. package/esm/universal/runtime-builder.d.ts +0 -33
  236. package/esm/universal/runtime-builder.d.ts.map +0 -1
  237. package/esm/universal/store.d.ts +0 -135
  238. package/esm/universal/store.d.ts.map +0 -1
  239. package/esm/universal/types.d.ts +0 -199
  240. package/esm/universal/types.d.ts.map +0 -1
  241. package/esm/web-components/core/attribute-parser.d.ts +0 -82
  242. package/esm/web-components/core/attribute-parser.d.ts.map +0 -1
  243. package/esm/web-components/core/base-element.d.ts +0 -197
  244. package/esm/web-components/core/base-element.d.ts.map +0 -1
  245. package/esm/web-components/core/index.d.ts +0 -9
  246. package/esm/web-components/core/index.d.ts.map +0 -1
  247. package/esm/web-components/elements/fmcp-alert.d.ts +0 -46
  248. package/esm/web-components/elements/fmcp-alert.d.ts.map +0 -1
  249. package/esm/web-components/elements/fmcp-badge.d.ts +0 -47
  250. package/esm/web-components/elements/fmcp-badge.d.ts.map +0 -1
  251. package/esm/web-components/elements/fmcp-button.d.ts +0 -117
  252. package/esm/web-components/elements/fmcp-button.d.ts.map +0 -1
  253. package/esm/web-components/elements/fmcp-card.d.ts +0 -53
  254. package/esm/web-components/elements/fmcp-card.d.ts.map +0 -1
  255. package/esm/web-components/elements/fmcp-input.d.ts +0 -96
  256. package/esm/web-components/elements/fmcp-input.d.ts.map +0 -1
  257. package/esm/web-components/elements/fmcp-select.d.ts +0 -100
  258. package/esm/web-components/elements/fmcp-select.d.ts.map +0 -1
  259. package/esm/web-components/elements/index.d.ts +0 -13
  260. package/esm/web-components/elements/index.d.ts.map +0 -1
  261. package/esm/web-components/index.d.ts +0 -50
  262. package/esm/web-components/index.d.ts.map +0 -1
  263. package/esm/web-components/register.d.ts +0 -57
  264. package/esm/web-components/register.d.ts.map +0 -1
  265. package/esm/web-components/types.d.ts +0 -122
  266. package/esm/web-components/types.d.ts.map +0 -1
  267. package/esm/widgets/index.d.ts +0 -8
  268. package/esm/widgets/index.d.ts.map +0 -1
  269. package/esm/widgets/index.js +0 -883
  270. package/esm/widgets/progress.d.ts +0 -133
  271. package/esm/widgets/progress.d.ts.map +0 -1
  272. package/esm/widgets/resource.d.ts +0 -163
  273. package/esm/widgets/resource.d.ts.map +0 -1
  274. package/pages/consent.d.ts +0 -117
  275. package/pages/consent.d.ts.map +0 -1
  276. package/pages/error.d.ts +0 -101
  277. package/pages/error.d.ts.map +0 -1
  278. package/pages/index.d.ts +0 -9
  279. package/pages/index.d.ts.map +0 -1
  280. package/pages/index.js +0 -1065
  281. package/react/utils.d.ts +0 -43
  282. package/react/utils.d.ts.map +0 -1
  283. package/widgets/index.d.ts +0 -8
  284. package/widgets/index.d.ts.map +0 -1
  285. package/widgets/index.js +0 -910
  286. package/widgets/progress.d.ts +0 -133
  287. package/widgets/progress.d.ts.map +0 -1
  288. package/widgets/resource.d.ts +0 -163
  289. package/widgets/resource.d.ts.map +0 -1
  290. /package/esm/components/{index.js → index.mjs} +0 -0
  291. /package/esm/render/{index.js → index.mjs} +0 -0
  292. /package/esm/web-components/{index.js → index.mjs} +0 -0
package/index.js CHANGED
@@ -43,7 +43,7 @@ __export(index_exports, {
43
43
  AvatarSpacingSchema: () => AvatarSpacingSchema,
44
44
  AvatarStatusSchema: () => AvatarStatusSchema,
45
45
  AvatarWithTextOptionsSchema: () => AvatarWithTextOptionsSchema,
46
- BRIDGE_SCRIPT_TAGS: () => BRIDGE_SCRIPT_TAGS,
46
+ BRIDGE_SCRIPT_TAGS: () => import_uipack.BRIDGE_SCRIPT_TAGS,
47
47
  Badge: () => Badge,
48
48
  BadgeGroupOptionsSchema: () => BadgeGroupOptionsSchema,
49
49
  BadgeOptionsSchema: () => BadgeOptionsSchema,
@@ -107,7 +107,7 @@ __export(index_exports, {
107
107
  TextareaResizeSchema: () => TextareaResizeSchema,
108
108
  ToastOptionsSchema: () => ToastOptionsSchema,
109
109
  ToastPositionSchema: () => ToastPositionSchema,
110
- UNIVERSAL_BRIDGE_SCRIPT: () => UNIVERSAL_BRIDGE_SCRIPT,
110
+ UNIVERSAL_BRIDGE_SCRIPT: () => import_uipack.UNIVERSAL_BRIDGE_SCRIPT,
111
111
  actionList: () => actionList,
112
112
  activeBadge: () => activeBadge,
113
113
  alert: () => alert,
@@ -121,22 +121,15 @@ __export(index_exports, {
121
121
  badgeGroup: () => badgeGroup,
122
122
  baseLayout: () => baseLayout,
123
123
  betaBadge: () => betaBadge,
124
- buildHydrationScript: () => buildHydrationScript,
125
124
  busyDot: () => busyDot,
126
125
  button: () => button,
127
126
  buttonGroup: () => buttonGroup,
128
127
  card: () => card,
129
128
  cardGroup: () => cardGroup,
130
129
  checkbox: () => checkbox,
131
- circularProgress: () => circularProgress,
132
- codePreview: () => codePreview,
133
130
  confirmModal: () => confirmModal,
134
- consentDeniedPage: () => consentDeniedPage,
135
131
  consentLayout: () => consentLayout,
136
132
  consentLayoutBuilder: () => consentLayoutBuilder,
137
- consentPage: () => consentPage,
138
- consentSuccessPage: () => consentSuccessPage,
139
- contentSkeleton: () => contentSkeleton,
140
133
  createBridge: () => createBridge,
141
134
  createLayoutBuilder: () => createLayoutBuilder,
142
135
  createReactAdapter: () => createReactAdapter,
@@ -149,45 +142,33 @@ __export(index_exports, {
149
142
  errorBadge: () => errorBadge,
150
143
  errorLayout: () => errorLayout,
151
144
  errorLayoutBuilder: () => errorLayoutBuilder,
152
- errorPage: () => errorPage,
153
145
  escapeHtml: () => import_utils2.escapeHtml,
154
146
  featureList: () => featureList,
155
- forbiddenPage: () => forbiddenPage,
156
147
  form: () => form,
157
148
  formActions: () => formActions,
158
149
  formRow: () => formRow,
159
150
  formSection: () => formSection,
160
- generateBridgeIIFE: () => generateBridgeIIFE,
161
- generatePlatformBundle: () => generatePlatformBundle,
151
+ generateBridgeIIFE: () => import_uipack.generateBridgeIIFE,
152
+ generatePlatformBundle: () => import_uipack.generatePlatformBundle,
162
153
  ghostButton: () => ghostButton,
163
154
  hiddenInput: () => hiddenInput,
164
- imagePreview: () => imagePreview,
165
155
  inactiveBadge: () => inactiveBadge,
166
156
  infoAlert: () => infoAlert,
167
157
  input: () => input,
168
- isBrowser: () => isBrowser,
169
- isReactAvailable: () => isReactAvailable,
170
- isServer: () => isServer,
171
158
  linkButton: () => linkButton,
172
159
  loadReactAdapter: () => loadReactAdapter,
173
160
  loadingLayout: () => loadingLayout,
174
- maintenancePage: () => maintenancePage,
175
161
  modal: () => modal,
176
162
  modalTrigger: () => modalTrigger,
177
163
  newBadge: () => newBadge,
178
- notFoundPage: () => notFoundPage,
179
- oauthErrorPage: () => oauthErrorPage,
180
164
  offlineDot: () => offlineDot,
181
- offlinePage: () => offlinePage,
182
165
  onlineDot: () => onlineDot,
183
166
  outlineButton: () => outlineButton,
184
167
  pagination: () => pagination,
185
168
  pendingBadge: () => pendingBadge,
186
169
  permissionList: () => permissionList,
187
170
  primaryButton: () => primaryButton,
188
- progressBar: () => progressBar,
189
171
  radioGroup: () => radioGroup,
190
- rateLimitPage: () => rateLimitPage,
191
172
  reactRenderer: () => reactRenderer,
192
173
  registerAdapter: () => registerAdapter,
193
174
  registerAllComponents: () => registerAllComponents,
@@ -205,26 +186,14 @@ __export(index_exports, {
205
186
  renderButtonSync: () => renderButtonSync,
206
187
  renderCard: () => renderCard,
207
188
  renderCardSync: () => renderCardSync,
208
- renderChildrenToString: () => renderChildrenToString,
209
- renderToString: () => renderToString,
210
- renderToStringSync: () => renderToStringSync,
211
- resourceItem: () => resourceItem,
212
- resourceList: () => resourceList,
213
- resourceWidget: () => resourceWidget,
214
189
  secondaryButton: () => secondaryButton,
215
190
  select: () => select,
216
- serverErrorPage: () => serverErrorPage,
217
- sessionExpiredPage: () => sessionExpiredPage,
218
- skeleton: () => skeleton,
219
- statusIndicator: () => statusIndicator,
220
- stepProgress: () => stepProgress,
221
191
  successAlert: () => successAlert,
222
192
  successLayout: () => successLayout,
223
193
  table: () => table,
224
194
  textarea: () => textarea,
225
195
  toast: () => toast,
226
196
  toastContainer: () => toastContainer,
227
- unauthorizedPage: () => unauthorizedPage,
228
197
  useCallTool: () => useCallTool,
229
198
  useCapability: () => useCapability,
230
199
  useDisplayMode: () => useDisplayMode,
@@ -947,7 +916,7 @@ function getAlignmentClasses(alignment) {
947
916
  };
948
917
  return alignMap[alignment];
949
918
  }
950
- function getBackgroundClasses(background, theme) {
919
+ function getBackgroundClasses(background) {
951
920
  switch (background) {
952
921
  case "gradient":
953
922
  return "bg-gradient-to-br from-primary to-secondary";
@@ -992,7 +961,7 @@ function buildBodyAttrs(attrs) {
992
961
  function baseLayout(content, options) {
993
962
  const {
994
963
  title,
995
- pageType = "custom",
964
+ pageType: _pageType = "custom",
996
965
  size = "md",
997
966
  alignment = "center",
998
967
  background = "solid",
@@ -1029,7 +998,7 @@ function baseLayout(content, options) {
1029
998
  </style>` : "";
1030
999
  const sizeClass = getSizeClass(size);
1031
1000
  const alignmentClasses = getAlignmentClasses(alignment);
1032
- const backgroundClasses = getBackgroundClasses(background, theme);
1001
+ const backgroundClasses = getBackgroundClasses(background);
1033
1002
  const allBodyClasses = [backgroundClasses, "font-sans antialiased", bodyClass].filter(Boolean).join(" ");
1034
1003
  const metaTags = buildMetaTags(options);
1035
1004
  const bodyAttrStr = buildBodyAttrs(bodyAttrs);
@@ -2896,926 +2865,6 @@ var errorLayoutBuilder = createLayoutBuilder({
2896
2865
  background: "solid"
2897
2866
  });
2898
2867
 
2899
- // libs/ui/src/pages/consent.ts
2900
- function consentPage(options) {
2901
- const {
2902
- client,
2903
- user,
2904
- permissions,
2905
- approveUrl,
2906
- denyUrl,
2907
- csrfToken,
2908
- state,
2909
- redirectUri,
2910
- responseType,
2911
- nonce,
2912
- codeChallenge,
2913
- codeChallengeMethod,
2914
- error,
2915
- layout = {},
2916
- warningMessage,
2917
- allowScopeSelection = false,
2918
- approveText = "Allow",
2919
- denyText = "Deny"
2920
- } = options;
2921
- const errorAlert = error ? alert(error, { variant: "danger", dismissible: true }) : "";
2922
- const unverifiedWarning = !client.verified ? alert(warningMessage || "This application has not been verified. Only authorize applications you trust.", {
2923
- variant: "warning",
2924
- title: "Unverified Application"
2925
- }) : "";
2926
- const clientHeader = `
2927
- <div class="text-center mb-6">
2928
- ${client.icon ? `<img src="${(0, import_utils2.escapeHtml)(client.icon)}" alt="${(0, import_utils2.escapeHtml)(
2929
- client.name
2930
- )}" class="w-16 h-16 rounded-xl mx-auto mb-4 shadow-md">` : `<div class="inline-flex items-center justify-center w-16 h-16 rounded-xl bg-gradient-to-br from-primary to-secondary text-white font-bold text-2xl mx-auto mb-4 shadow-md">
2931
- ${(0, import_utils2.escapeHtml)(client.name.charAt(0).toUpperCase())}
2932
- </div>`}
2933
- <h1 class="text-xl font-bold text-text-primary">
2934
- ${client.verified ? `<span class="inline-flex items-center gap-1">
2935
- ${(0, import_utils2.escapeHtml)(client.name)}
2936
- <svg class="w-5 h-5 text-primary" fill="currentColor" viewBox="0 0 20 20">
2937
- <path fill-rule="evenodd" d="M6.267 3.455a3.066 3.066 0 001.745-.723 3.066 3.066 0 013.976 0 3.066 3.066 0 001.745.723 3.066 3.066 0 012.812 2.812c.051.643.304 1.254.723 1.745a3.066 3.066 0 010 3.976 3.066 3.066 0 00-.723 1.745 3.066 3.066 0 01-2.812 2.812 3.066 3.066 0 00-1.745.723 3.066 3.066 0 01-3.976 0 3.066 3.066 0 00-1.745-.723 3.066 3.066 0 01-2.812-2.812 3.066 3.066 0 00-.723-1.745 3.066 3.066 0 010-3.976 3.066 3.066 0 00.723-1.745 3.066 3.066 0 012.812-2.812zm7.44 5.252a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
2938
- </svg>
2939
- </span>` : (0, import_utils2.escapeHtml)(client.name)}
2940
- </h1>
2941
- <p class="text-text-secondary mt-1">wants to access your account</p>
2942
- </div>
2943
- `;
2944
- const userSection = user ? `
2945
- <div class="flex items-center gap-3 p-4 bg-gray-50 rounded-lg mb-6">
2946
- ${user.avatar ? `<img src="${(0, import_utils2.escapeHtml)(user.avatar)}" class="w-12 h-12 rounded-full">` : `<div class="w-12 h-12 rounded-full bg-primary text-white flex items-center justify-center font-semibold text-lg">
2947
- ${(0, import_utils2.escapeHtml)((user.name || user.email || "U").charAt(0).toUpperCase())}
2948
- </div>`}
2949
- <div class="flex-1 min-w-0">
2950
- ${user.name ? `<div class="font-medium text-text-primary truncate">${(0, import_utils2.escapeHtml)(user.name)}</div>` : ""}
2951
- ${user.email ? `<div class="text-sm text-text-secondary truncate">${(0, import_utils2.escapeHtml)(user.email)}</div>` : ""}
2952
- </div>
2953
- <a href="/login?prompt=select_account" class="text-sm text-primary hover:text-primary/80">
2954
- Switch account
2955
- </a>
2956
- </div>
2957
- ` : "";
2958
- const permissionsSection = `
2959
- <div class="mb-6">
2960
- <h3 class="font-medium text-text-primary mb-3">This will allow ${(0, import_utils2.escapeHtml)(client.name)} to:</h3>
2961
- ${permissionList(permissions, {
2962
- checkable: allowScopeSelection,
2963
- inputName: "scope"
2964
- })}
2965
- </div>
2966
- `;
2967
- const hiddenFields = [
2968
- csrfToken ? csrfInput(csrfToken) : "",
2969
- state ? hiddenInput("state", state) : "",
2970
- redirectUri ? hiddenInput("redirect_uri", redirectUri) : "",
2971
- responseType ? hiddenInput("response_type", responseType) : "",
2972
- nonce ? hiddenInput("nonce", nonce) : "",
2973
- codeChallenge ? hiddenInput("code_challenge", codeChallenge) : "",
2974
- codeChallengeMethod ? hiddenInput("code_challenge_method", codeChallengeMethod) : "",
2975
- hiddenInput("client_id", client.clientId),
2976
- // Include all scopes if not selectable
2977
- !allowScopeSelection ? permissions.map((p) => hiddenInput("scope[]", p.scope)).join("\n") : ""
2978
- ].filter(Boolean).join("\n");
2979
- const actionsHtml = `
2980
- <div class="flex gap-3 pt-4">
2981
- <form action="${(0, import_utils2.escapeHtml)(denyUrl || approveUrl)}" method="post" class="flex-1">
2982
- ${hiddenFields}
2983
- <input type="hidden" name="action" value="deny">
2984
- ${outlineButton(denyText, { type: "submit", fullWidth: true })}
2985
- </form>
2986
- <form action="${(0, import_utils2.escapeHtml)(approveUrl)}" method="post" class="flex-1">
2987
- ${hiddenFields}
2988
- <input type="hidden" name="action" value="approve">
2989
- ${primaryButton(approveText, { type: "submit", fullWidth: true })}
2990
- </form>
2991
- </div>
2992
- `;
2993
- const linksHtml = client.privacyUrl || client.termsUrl || client.websiteUrl ? `
2994
- <div class="text-center text-xs text-text-secondary mt-6 space-x-3">
2995
- ${client.websiteUrl ? `<a href="${(0, import_utils2.escapeHtml)(
2996
- client.websiteUrl
2997
- )}" target="_blank" rel="noopener" class="hover:text-primary">Website</a>` : ""}
2998
- ${client.privacyUrl ? `<a href="${(0, import_utils2.escapeHtml)(
2999
- client.privacyUrl
3000
- )}" target="_blank" rel="noopener" class="hover:text-primary">Privacy Policy</a>` : ""}
3001
- ${client.termsUrl ? `<a href="${(0, import_utils2.escapeHtml)(
3002
- client.termsUrl
3003
- )}" target="_blank" rel="noopener" class="hover:text-primary">Terms of Service</a>` : ""}
3004
- </div>
3005
- ` : "";
3006
- const content = `
3007
- ${errorAlert}
3008
- ${unverifiedWarning}
3009
- ${clientHeader}
3010
- ${userSection}
3011
- ${permissionsSection}
3012
- ${actionsHtml}
3013
- ${linksHtml}
3014
- `;
3015
- return consentLayout(content, {
3016
- title: `Authorize ${client.name}`,
3017
- clientName: client.name,
3018
- clientIcon: client.icon,
3019
- userInfo: user,
3020
- ...layout
3021
- });
3022
- }
3023
- function consentSuccessPage(options) {
3024
- const { client, redirectUrl, autoRedirectDelay = 3e3, layout = {} } = options;
3025
- const redirectScript = redirectUrl && autoRedirectDelay > 0 ? `
3026
- <script>
3027
- setTimeout(() => {
3028
- window.location.href = '${(0, import_utils2.escapeHtml)(redirectUrl)}';
3029
- }, ${autoRedirectDelay});
3030
- </script>
3031
- ` : "";
3032
- const content = `
3033
- <div class="text-center">
3034
- <div class="inline-flex items-center justify-center w-16 h-16 rounded-full bg-success/10 mb-6">
3035
- <svg class="w-8 h-8 text-success" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3036
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
3037
- </svg>
3038
- </div>
3039
- <h1 class="text-2xl font-bold text-text-primary mb-2">Authorization Successful</h1>
3040
- <p class="text-text-secondary mb-4">
3041
- You have authorized <strong>${(0, import_utils2.escapeHtml)(client.name)}</strong> to access your account.
3042
- </p>
3043
- ${redirectUrl ? `<p class="text-sm text-text-secondary">Redirecting you back to ${(0, import_utils2.escapeHtml)(client.name)}...</p>` : ""}
3044
- </div>
3045
- ${redirectScript}
3046
- `;
3047
- return consentLayout(content, {
3048
- title: "Authorization Successful",
3049
- clientName: client.name,
3050
- clientIcon: client.icon,
3051
- ...layout
3052
- });
3053
- }
3054
- function consentDeniedPage(options) {
3055
- const { client, redirectUrl, layout = {} } = options;
3056
- const content = `
3057
- <div class="text-center">
3058
- <div class="inline-flex items-center justify-center w-16 h-16 rounded-full bg-gray-100 mb-6">
3059
- <svg class="w-8 h-8 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3060
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
3061
- </svg>
3062
- </div>
3063
- <h1 class="text-2xl font-bold text-text-primary mb-2">Authorization Denied</h1>
3064
- <p class="text-text-secondary mb-6">
3065
- You denied <strong>${(0, import_utils2.escapeHtml)(client.name)}</strong> access to your account.
3066
- </p>
3067
- ${redirectUrl ? `
3068
- <a href="${(0, import_utils2.escapeHtml)(
3069
- redirectUrl
3070
- )}" class="inline-block px-6 py-3 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg transition-colors">
3071
- Return to ${(0, import_utils2.escapeHtml)(client.name)}
3072
- </a>
3073
- ` : ""}
3074
- </div>
3075
- `;
3076
- return consentLayout(content, {
3077
- title: "Authorization Denied",
3078
- clientName: client.name,
3079
- clientIcon: client.icon,
3080
- ...layout
3081
- });
3082
- }
3083
-
3084
- // libs/ui/src/pages/error.ts
3085
- function errorPage(options) {
3086
- const {
3087
- code,
3088
- title = "Something went wrong",
3089
- message,
3090
- details,
3091
- showStack = false,
3092
- stack,
3093
- showRetry = true,
3094
- retryUrl,
3095
- showHome = true,
3096
- homeUrl = "/",
3097
- showBack = false,
3098
- actions,
3099
- layout = {},
3100
- requestId
3101
- } = options;
3102
- const detailsHtml = details || showStack && stack ? `
3103
- <div class="mt-8 text-left">
3104
- ${details ? `
3105
- <div class="p-4 bg-gray-50 rounded-lg text-sm text-text-secondary mb-4">
3106
- <strong class="text-text-primary">Details:</strong>
3107
- <p class="mt-1">${(0, import_utils2.escapeHtml)(details)}</p>
3108
- </div>
3109
- ` : ""}
3110
- ${showStack && stack ? `
3111
- <details class="p-4 bg-gray-900 rounded-lg text-sm">
3112
- <summary class="text-gray-300 cursor-pointer hover:text-white">Stack Trace</summary>
3113
- <pre class="mt-2 text-xs text-gray-400 overflow-x-auto whitespace-pre-wrap">${(0, import_utils2.escapeHtml)(stack)}</pre>
3114
- </details>
3115
- ` : ""}
3116
- </div>
3117
- ` : "";
3118
- const requestIdHtml = requestId ? `
3119
- <p class="text-xs text-text-secondary mt-6">
3120
- Request ID: <code class="px-1.5 py-0.5 bg-gray-100 rounded text-xs">${(0, import_utils2.escapeHtml)(requestId)}</code>
3121
- </p>
3122
- ` : "";
3123
- const content = `
3124
- ${detailsHtml}
3125
- ${actions || ""}
3126
- ${requestIdHtml}
3127
- `;
3128
- return errorLayout(content, {
3129
- title: `${code ? `Error ${code} - ` : ""}${title}`,
3130
- errorCode: code?.toString(),
3131
- errorTitle: title,
3132
- errorMessage: message,
3133
- showRetry,
3134
- retryUrl,
3135
- showHome,
3136
- homeUrl,
3137
- ...layout
3138
- });
3139
- }
3140
- function notFoundPage(options = {}) {
3141
- return errorPage({
3142
- code: 404,
3143
- title: "Page Not Found",
3144
- message: "The page you're looking for doesn't exist or has been moved.",
3145
- showRetry: false,
3146
- ...options
3147
- });
3148
- }
3149
- function forbiddenPage(options = {}) {
3150
- return errorPage({
3151
- code: 403,
3152
- title: "Access Denied",
3153
- message: "You don't have permission to access this resource.",
3154
- showRetry: false,
3155
- ...options
3156
- });
3157
- }
3158
- function unauthorizedPage(options = {}) {
3159
- const { loginUrl = "/login", ...rest } = options;
3160
- return errorPage({
3161
- code: 401,
3162
- title: "Authentication Required",
3163
- message: "Please sign in to access this resource.",
3164
- showRetry: false,
3165
- showHome: false,
3166
- actions: `
3167
- <div class="flex justify-center mt-8">
3168
- <a href="${(0, import_utils2.escapeHtml)(
3169
- loginUrl
3170
- )}" class="px-6 py-3 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg transition-colors">
3171
- Sign In
3172
- </a>
3173
- </div>
3174
- `,
3175
- ...rest
3176
- });
3177
- }
3178
- function serverErrorPage(options = {}) {
3179
- return errorPage({
3180
- code: 500,
3181
- title: "Server Error",
3182
- message: "We're having trouble processing your request. Please try again later.",
3183
- showRetry: true,
3184
- ...options
3185
- });
3186
- }
3187
- function maintenancePage(options = {}) {
3188
- const { estimatedTime, ...rest } = options;
3189
- const timeMessage = estimatedTime ? `We expect to be back by ${(0, import_utils2.escapeHtml)(estimatedTime)}.` : "We'll be back shortly.";
3190
- return errorPage({
3191
- code: 503,
3192
- title: "Under Maintenance",
3193
- message: `We're currently performing scheduled maintenance. ${timeMessage}`,
3194
- showRetry: true,
3195
- showHome: false,
3196
- ...rest
3197
- });
3198
- }
3199
- function rateLimitPage(options = {}) {
3200
- const { retryAfter, ...rest } = options;
3201
- const retryMessage = retryAfter ? `Please wait ${retryAfter} seconds before trying again.` : "Please wait a moment before trying again.";
3202
- return errorPage({
3203
- code: 429,
3204
- title: "Too Many Requests",
3205
- message: `You've made too many requests. ${retryMessage}`,
3206
- showRetry: true,
3207
- showHome: true,
3208
- ...rest
3209
- });
3210
- }
3211
- function offlinePage(options = {}) {
3212
- return errorPage({
3213
- title: "You're Offline",
3214
- message: "Please check your internet connection and try again.",
3215
- showRetry: true,
3216
- showHome: false,
3217
- ...options,
3218
- layout: {
3219
- ...options.layout
3220
- }
3221
- });
3222
- }
3223
- function sessionExpiredPage(options = {}) {
3224
- const { loginUrl = "/login", ...rest } = options;
3225
- return errorPage({
3226
- title: "Session Expired",
3227
- message: "Your session has expired. Please sign in again to continue.",
3228
- showRetry: false,
3229
- showHome: false,
3230
- actions: `
3231
- <div class="flex justify-center mt-8">
3232
- <a href="${(0, import_utils2.escapeHtml)(
3233
- loginUrl
3234
- )}" class="px-6 py-3 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg transition-colors">
3235
- Sign In Again
3236
- </a>
3237
- </div>
3238
- `,
3239
- ...rest
3240
- });
3241
- }
3242
- function oauthErrorPage(options) {
3243
- const { errorCode, errorDescription, redirectUri, clientName, ...rest } = options;
3244
- const errorMessages = {
3245
- invalid_request: {
3246
- title: "Invalid Request",
3247
- message: "The authorization request is missing required parameters or is malformed."
3248
- },
3249
- unauthorized_client: {
3250
- title: "Unauthorized Client",
3251
- message: "The client is not authorized to request an authorization code."
3252
- },
3253
- access_denied: {
3254
- title: "Access Denied",
3255
- message: "The resource owner denied the authorization request."
3256
- },
3257
- unsupported_response_type: {
3258
- title: "Unsupported Response Type",
3259
- message: "The authorization server does not support the requested response type."
3260
- },
3261
- invalid_scope: {
3262
- title: "Invalid Scope",
3263
- message: "The requested scope is invalid, unknown, or malformed."
3264
- },
3265
- server_error: {
3266
- title: "Server Error",
3267
- message: "The authorization server encountered an unexpected error."
3268
- },
3269
- temporarily_unavailable: {
3270
- title: "Temporarily Unavailable",
3271
- message: "The authorization server is temporarily unavailable. Please try again later."
3272
- }
3273
- };
3274
- const errorInfo = errorCode && errorMessages[errorCode] ? errorMessages[errorCode] : { title: "Authorization Error", message: errorDescription || "An error occurred during authorization." };
3275
- const clientMessage = clientName ? ` while connecting to ${(0, import_utils2.escapeHtml)(clientName)}` : "";
3276
- const redirectAction = redirectUri ? `
3277
- <a href="${(0, import_utils2.escapeHtml)(
3278
- redirectUri
3279
- )}" class="px-6 py-3 bg-gray-100 hover:bg-gray-200 text-text-primary font-medium rounded-lg transition-colors">
3280
- Return to ${clientName ? (0, import_utils2.escapeHtml)(clientName) : "Application"}
3281
- </a>
3282
- ` : "";
3283
- return errorPage({
3284
- title: errorInfo.title,
3285
- message: `${errorInfo.message}${clientMessage}`,
3286
- details: errorCode && errorDescription ? `Error: ${errorCode}
3287
- ${errorDescription}` : void 0,
3288
- showRetry: errorCode === "server_error" || errorCode === "temporarily_unavailable",
3289
- showHome: true,
3290
- actions: redirectAction ? `<div class="flex justify-center gap-4 mt-8">${redirectAction}</div>` : void 0,
3291
- ...rest
3292
- });
3293
- }
3294
-
3295
- // libs/ui/src/widgets/resource.ts
3296
- var resourceIcons = {
3297
- document: `<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3298
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
3299
- </svg>`,
3300
- image: `<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3301
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/>
3302
- </svg>`,
3303
- code: `<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3304
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"/>
3305
- </svg>`,
3306
- data: `<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3307
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4"/>
3308
- </svg>`,
3309
- file: `<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3310
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"/>
3311
- </svg>`,
3312
- link: `<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3313
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/>
3314
- </svg>`,
3315
- user: `<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3316
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
3317
- </svg>`,
3318
- event: `<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3319
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
3320
- </svg>`,
3321
- message: `<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3322
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"/>
3323
- </svg>`,
3324
- task: `<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3325
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"/>
3326
- </svg>`,
3327
- custom: `<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3328
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"/>
3329
- </svg>`
3330
- };
3331
- function formatFileSize(bytes) {
3332
- if (bytes === 0) return "0 B";
3333
- const k = 1024;
3334
- const sizes = ["B", "KB", "MB", "GB", "TB"];
3335
- const i = Math.floor(Math.log(bytes) / Math.log(k));
3336
- return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
3337
- }
3338
- function formatDate(date) {
3339
- const d = typeof date === "string" ? new Date(date) : date;
3340
- return d.toLocaleDateString("en-US", {
3341
- year: "numeric",
3342
- month: "short",
3343
- day: "numeric"
3344
- });
3345
- }
3346
- function resourceWidget(options) {
3347
- const {
3348
- type,
3349
- title,
3350
- description,
3351
- icon,
3352
- thumbnail,
3353
- url,
3354
- meta,
3355
- status,
3356
- actions = [],
3357
- className = "",
3358
- cardOptions = {}
3359
- } = options;
3360
- const iconHtml = thumbnail ? `<div class="w-16 h-16 rounded-lg overflow-hidden bg-gray-100 flex-shrink-0">
3361
- <img src="${(0, import_utils2.escapeHtml)(thumbnail)}" alt="${(0, import_utils2.escapeHtml)(title)}" class="w-full h-full object-cover">
3362
- </div>` : `<div class="w-16 h-16 rounded-lg bg-gray-100 flex items-center justify-center flex-shrink-0 text-gray-400">
3363
- ${icon || resourceIcons[type]}
3364
- </div>`;
3365
- const statusHtml = status ? badge(status.label, { variant: status.variant, size: "sm" }) : "";
3366
- const metaItems = [];
3367
- if (meta?.size) {
3368
- metaItems.push(formatFileSize(meta.size));
3369
- }
3370
- if (meta?.mimeType) {
3371
- metaItems.push(meta.mimeType);
3372
- }
3373
- if (meta?.updatedAt) {
3374
- metaItems.push(`Updated ${formatDate(meta.updatedAt)}`);
3375
- } else if (meta?.createdAt) {
3376
- metaItems.push(`Created ${formatDate(meta.createdAt)}`);
3377
- }
3378
- if (meta?.author) {
3379
- metaItems.push(`by ${meta.author}`);
3380
- }
3381
- const metaHtml = metaItems.length > 0 ? `<div class="text-xs text-text-secondary mt-1">${metaItems.join(" \u2022 ")}</div>` : "";
3382
- const tagsHtml = meta?.tags && meta.tags.length > 0 ? `<div class="flex flex-wrap gap-1 mt-2">
3383
- ${meta.tags.map((tag) => badge(tag, { variant: "default", size: "sm" })).join("")}
3384
- </div>` : "";
3385
- const actionsHtml = actions.length > 0 ? `<div class="flex gap-2 mt-4">
3386
- ${actions.map((action) => {
3387
- const variantMap = {
3388
- primary: "primary",
3389
- secondary: "secondary",
3390
- danger: "danger",
3391
- ghost: "ghost"
3392
- };
3393
- const variant = action.variant ? variantMap[action.variant] : "ghost";
3394
- const htmxAttrs = [];
3395
- if (action.htmx) {
3396
- if (action.htmx.get) htmxAttrs.push(`hx-get="${(0, import_utils2.escapeHtml)(action.htmx.get)}"`);
3397
- if (action.htmx.post) htmxAttrs.push(`hx-post="${(0, import_utils2.escapeHtml)(action.htmx.post)}"`);
3398
- if (action.htmx.delete) htmxAttrs.push(`hx-delete="${(0, import_utils2.escapeHtml)(action.htmx.delete)}"`);
3399
- if (action.htmx.target) htmxAttrs.push(`hx-target="${(0, import_utils2.escapeHtml)(action.htmx.target)}"`);
3400
- if (action.htmx.swap) htmxAttrs.push(`hx-swap="${(0, import_utils2.escapeHtml)(action.htmx.swap)}"`);
3401
- if (action.htmx.confirm) htmxAttrs.push(`hx-confirm="${(0, import_utils2.escapeHtml)(action.htmx.confirm)}"`);
3402
- }
3403
- return button(action.label, {
3404
- variant,
3405
- size: "sm",
3406
- href: action.href,
3407
- disabled: action.disabled,
3408
- iconBefore: action.icon
3409
- });
3410
- }).join("")}
3411
- </div>` : "";
3412
- const content = `
3413
- <div class="flex gap-4">
3414
- ${iconHtml}
3415
- <div class="flex-1 min-w-0">
3416
- <div class="flex items-start justify-between gap-2">
3417
- <div class="min-w-0">
3418
- ${url ? `<a href="${(0, import_utils2.escapeHtml)(
3419
- url
3420
- )}" class="font-semibold text-text-primary hover:text-primary truncate block">${(0, import_utils2.escapeHtml)(
3421
- title
3422
- )}</a>` : `<h3 class="font-semibold text-text-primary truncate">${(0, import_utils2.escapeHtml)(title)}</h3>`}
3423
- ${description ? `<p class="text-sm text-text-secondary mt-0.5 line-clamp-2">${(0, import_utils2.escapeHtml)(description)}</p>` : ""}
3424
- ${metaHtml}
3425
- ${tagsHtml}
3426
- </div>
3427
- ${statusHtml}
3428
- </div>
3429
- ${actionsHtml}
3430
- </div>
3431
- </div>
3432
- `;
3433
- return card(content, {
3434
- variant: "default",
3435
- size: "md",
3436
- className: `resource-widget resource-${type} ${className}`,
3437
- ...cardOptions
3438
- });
3439
- }
3440
- function resourceList(options) {
3441
- const {
3442
- resources,
3443
- title,
3444
- emptyMessage = "No resources found",
3445
- layout = "list",
3446
- columns = 2,
3447
- className = "",
3448
- showLoadMore = false,
3449
- loadMoreUrl
3450
- } = options;
3451
- const titleHtml = title ? `<h2 class="text-lg font-semibold text-text-primary mb-4">${(0, import_utils2.escapeHtml)(title)}</h2>` : "";
3452
- if (resources.length === 0) {
3453
- return `<div class="${className}">
3454
- ${titleHtml}
3455
- <div class="text-center py-12 text-text-secondary">
3456
- <svg class="w-12 h-12 mx-auto mb-4 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3457
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"/>
3458
- </svg>
3459
- <p>${(0, import_utils2.escapeHtml)(emptyMessage)}</p>
3460
- </div>
3461
- </div>`;
3462
- }
3463
- const layoutClasses = layout === "grid" ? `grid grid-cols-1 md:grid-cols-${columns} gap-4` : "space-y-4";
3464
- const resourcesHtml = resources.map((r) => resourceWidget(r)).join("\n");
3465
- const loadMoreHtml = showLoadMore && loadMoreUrl ? `<div class="text-center mt-6">
3466
- ${button("Load More", {
3467
- variant: "outline",
3468
- href: loadMoreUrl
3469
- })}
3470
- </div>` : "";
3471
- return `<div class="resource-list ${className}">
3472
- ${titleHtml}
3473
- <div class="${layoutClasses}">
3474
- ${resourcesHtml}
3475
- </div>
3476
- ${loadMoreHtml}
3477
- </div>`;
3478
- }
3479
- function resourceItem(options) {
3480
- const { type, title, description, icon, url, meta, status } = options;
3481
- const iconHtml = `<div class="w-10 h-10 rounded-lg bg-gray-100 flex items-center justify-center flex-shrink-0 text-gray-400">
3482
- ${icon || resourceIcons[type]}
3483
- </div>`;
3484
- const statusHtml = status ? badge(status.label, { variant: status.variant, size: "sm" }) : "";
3485
- const metaText = meta?.size ? formatFileSize(meta.size) : "";
3486
- const titleElement = url ? `<a href="${(0, import_utils2.escapeHtml)(url)}" class="font-medium text-text-primary hover:text-primary">${(0, import_utils2.escapeHtml)(title)}</a>` : `<span class="font-medium text-text-primary">${(0, import_utils2.escapeHtml)(title)}</span>`;
3487
- return `<div class="flex items-center gap-3 p-3 rounded-lg hover:bg-gray-50 transition-colors">
3488
- ${iconHtml}
3489
- <div class="flex-1 min-w-0">
3490
- <div class="flex items-center gap-2">
3491
- ${titleElement}
3492
- ${statusHtml}
3493
- </div>
3494
- ${description || metaText ? `<p class="text-sm text-text-secondary truncate">${(0, import_utils2.escapeHtml)(description || metaText)}</p>` : ""}
3495
- </div>
3496
- </div>`;
3497
- }
3498
- function codePreview(options) {
3499
- const {
3500
- code,
3501
- language = "text",
3502
- filename,
3503
- lineNumbers = true,
3504
- maxHeight = "400px",
3505
- showCopy = true,
3506
- className = ""
3507
- } = options;
3508
- const lines = code.split("\n");
3509
- const lineNumbersHtml = lineNumbers ? `<div class="text-right select-none pr-4 text-gray-500">
3510
- ${lines.map((_, i) => `<div>${i + 1}</div>`).join("")}
3511
- </div>` : "";
3512
- const copyScript = showCopy ? `<script>
3513
- function copyCode(btn, code) {
3514
- navigator.clipboard.writeText(code).then(() => {
3515
- const original = btn.innerHTML;
3516
- btn.innerHTML = '<svg class="w-4 h-4 text-success" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>';
3517
- setTimeout(() => btn.innerHTML = original, 2000);
3518
- });
3519
- }
3520
- </script>` : "";
3521
- const copyButton = showCopy ? `<button
3522
- type="button"
3523
- onclick="copyCode(this, ${(0, import_utils2.escapeHtml)(JSON.stringify(code))})"
3524
- class="p-1.5 rounded hover:bg-gray-700 transition-colors"
3525
- title="Copy code"
3526
- >
3527
- <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3528
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/>
3529
- </svg>
3530
- </button>` : "";
3531
- return `<div class="code-preview rounded-lg overflow-hidden ${className}">
3532
- ${filename || showCopy ? `
3533
- <div class="flex items-center justify-between px-4 py-2 bg-gray-800 border-b border-gray-700">
3534
- ${filename ? `<span class="text-sm text-gray-300">${(0, import_utils2.escapeHtml)(filename)}</span>` : "<span></span>"}
3535
- <div class="flex items-center gap-2">
3536
- ${language ? `<span class="text-xs text-gray-500">${(0, import_utils2.escapeHtml)(language)}</span>` : ""}
3537
- ${copyButton}
3538
- </div>
3539
- </div>
3540
- ` : ""}
3541
- <div class="bg-gray-900 p-4 overflow-auto" style="max-height: ${maxHeight}">
3542
- <div class="flex text-sm font-mono">
3543
- ${lineNumbersHtml}
3544
- <pre class="flex-1 text-gray-100"><code>${(0, import_utils2.escapeHtml)(code)}</code></pre>
3545
- </div>
3546
- </div>
3547
- ${copyScript}
3548
- </div>`;
3549
- }
3550
- function imagePreview(options) {
3551
- const { src, alt, caption, maxHeight = "400px", clickable = true, className = "" } = options;
3552
- const imageHtml = `<img
3553
- src="${(0, import_utils2.escapeHtml)(src)}"
3554
- alt="${(0, import_utils2.escapeHtml)(alt)}"
3555
- class="max-w-full h-auto rounded-lg"
3556
- style="max-height: ${maxHeight}"
3557
- >`;
3558
- const captionHtml = caption ? `<p class="text-sm text-text-secondary mt-2 text-center">${(0, import_utils2.escapeHtml)(caption)}</p>` : "";
3559
- const content = clickable ? `<a href="${(0, import_utils2.escapeHtml)(src)}" target="_blank" rel="noopener" class="block">${imageHtml}</a>` : imageHtml;
3560
- return `<div class="image-preview ${className}">
3561
- ${content}
3562
- ${captionHtml}
3563
- </div>`;
3564
- }
3565
-
3566
- // libs/ui/src/widgets/progress.ts
3567
- function progressBar(options) {
3568
- const {
3569
- value,
3570
- showLabel = true,
3571
- labelPosition = "outside",
3572
- size = "md",
3573
- variant = "primary",
3574
- animated = false,
3575
- className = "",
3576
- label
3577
- } = options;
3578
- const clampedValue = Math.min(100, Math.max(0, value));
3579
- const sizeClasses = {
3580
- sm: "h-1.5",
3581
- md: "h-2.5",
3582
- lg: "h-4"
3583
- };
3584
- const variantClasses = {
3585
- primary: "bg-primary",
3586
- success: "bg-success",
3587
- warning: "bg-warning",
3588
- danger: "bg-danger",
3589
- info: "bg-blue-500"
3590
- };
3591
- const animatedClass = animated ? "bg-stripes animate-stripes" : "";
3592
- const displayLabel = label || `${Math.round(clampedValue)}%`;
3593
- const insideLabel = labelPosition === "inside" && size === "lg" && clampedValue > 10 ? `<span class="absolute inset-0 flex items-center justify-center text-xs font-medium text-white">${(0, import_utils2.escapeHtml)(
3594
- displayLabel
3595
- )}</span>` : "";
3596
- const outsideLabel = showLabel && labelPosition === "outside" ? `<div class="flex justify-between mb-1">
3597
- <span class="text-sm font-medium text-text-primary">${label ? (0, import_utils2.escapeHtml)(label) : "Progress"}</span>
3598
- <span class="text-sm text-text-secondary">${Math.round(clampedValue)}%</span>
3599
- </div>` : "";
3600
- return `<div class="progress-bar ${className}">
3601
- ${outsideLabel}
3602
- <div class="relative w-full ${sizeClasses[size]} bg-gray-200 rounded-full overflow-hidden">
3603
- <div
3604
- class="${variantClasses[variant]} ${sizeClasses[size]} ${animatedClass} rounded-full transition-all duration-300"
3605
- style="width: ${clampedValue}%"
3606
- role="progressbar"
3607
- aria-valuenow="${clampedValue}"
3608
- aria-valuemin="0"
3609
- aria-valuemax="100"
3610
- ></div>
3611
- ${insideLabel}
3612
- </div>
3613
- </div>
3614
- ${animated ? `<style>
3615
- .bg-stripes {
3616
- background-image: linear-gradient(
3617
- 45deg,
3618
- rgba(255,255,255,0.15) 25%,
3619
- transparent 25%,
3620
- transparent 50%,
3621
- rgba(255,255,255,0.15) 50%,
3622
- rgba(255,255,255,0.15) 75%,
3623
- transparent 75%,
3624
- transparent
3625
- );
3626
- background-size: 1rem 1rem;
3627
- }
3628
- @keyframes stripes {
3629
- from { background-position: 1rem 0; }
3630
- to { background-position: 0 0; }
3631
- }
3632
- .animate-stripes {
3633
- animation: stripes 1s linear infinite;
3634
- }
3635
- </style>` : ""}`;
3636
- }
3637
- function stepProgress(options) {
3638
- const { steps, orientation = "horizontal", connector = "line", className = "" } = options;
3639
- const getStepIcon = (step, index) => {
3640
- if (step.icon) return step.icon;
3641
- if (step.status === "completed") {
3642
- return `<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
3643
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
3644
- </svg>`;
3645
- }
3646
- return `<span class="font-medium">${index + 1}</span>`;
3647
- };
3648
- const getStepClasses = (status) => {
3649
- switch (status) {
3650
- case "completed":
3651
- return {
3652
- circle: "bg-success text-white",
3653
- text: "text-text-primary"
3654
- };
3655
- case "current":
3656
- return {
3657
- circle: "bg-primary text-white ring-4 ring-primary/20",
3658
- text: "text-primary font-medium"
3659
- };
3660
- case "upcoming":
3661
- default:
3662
- return {
3663
- circle: "bg-gray-200 text-gray-500",
3664
- text: "text-text-secondary"
3665
- };
3666
- }
3667
- };
3668
- if (orientation === "vertical") {
3669
- const stepsHtml2 = steps.map((step, index) => {
3670
- const classes = getStepClasses(step.status);
3671
- const isLast = index === steps.length - 1;
3672
- const connectorHtml = !isLast && connector !== "none" ? `<div class="ml-5 w-0.5 h-8 ${connector === "dashed" ? "border-l-2 border-dashed border-gray-300" : "bg-gray-200"} ${step.status === "completed" ? "bg-success" : ""}"></div>` : "";
3673
- const stepContent = `
3674
- <div class="flex items-start gap-4">
3675
- <div class="w-10 h-10 rounded-full ${classes.circle} flex items-center justify-center flex-shrink-0">
3676
- ${getStepIcon(step, index)}
3677
- </div>
3678
- <div class="pt-2">
3679
- <div class="${classes.text}">${(0, import_utils2.escapeHtml)(step.label)}</div>
3680
- ${step.description ? `<p class="text-sm text-text-secondary mt-0.5">${(0, import_utils2.escapeHtml)(step.description)}</p>` : ""}
3681
- </div>
3682
- </div>
3683
- ${connectorHtml}
3684
- `;
3685
- return step.href && step.status === "completed" ? `<a href="${(0, import_utils2.escapeHtml)(step.href)}" class="block hover:opacity-80">${stepContent}</a>` : `<div>${stepContent}</div>`;
3686
- }).join("\n");
3687
- return `<div class="step-progress ${className}">${stepsHtml2}</div>`;
3688
- }
3689
- const stepsHtml = steps.map((step, index) => {
3690
- const classes = getStepClasses(step.status);
3691
- const isLast = index === steps.length - 1;
3692
- const connectorHtml = !isLast && connector !== "none" ? `<div class="flex-1 h-0.5 mx-2 ${connector === "dashed" ? "border-t-2 border-dashed border-gray-300" : "bg-gray-200"} ${step.status === "completed" ? "bg-success" : ""}"></div>` : "";
3693
- const stepHtml = `
3694
- <div class="flex flex-col items-center">
3695
- <div class="w-10 h-10 rounded-full ${classes.circle} flex items-center justify-center">
3696
- ${getStepIcon(step, index)}
3697
- </div>
3698
- <div class="mt-2 text-center">
3699
- <div class="${classes.text} text-sm">${(0, import_utils2.escapeHtml)(step.label)}</div>
3700
- ${step.description ? `<p class="text-xs text-text-secondary mt-0.5 max-w-[120px]">${(0, import_utils2.escapeHtml)(step.description)}</p>` : ""}
3701
- </div>
3702
- </div>
3703
- `;
3704
- const clickableStep = step.href && step.status === "completed" ? `<a href="${(0, import_utils2.escapeHtml)(step.href)}" class="hover:opacity-80">${stepHtml}</a>` : stepHtml;
3705
- return `${clickableStep}${connectorHtml}`;
3706
- }).join("\n");
3707
- return `<div class="step-progress flex items-start ${className}">${stepsHtml}</div>`;
3708
- }
3709
- function circularProgress(options) {
3710
- const { value, size = 80, strokeWidth = 8, variant = "primary", showLabel = true, label, className = "" } = options;
3711
- const clampedValue = Math.min(100, Math.max(0, value));
3712
- const radius = (size - strokeWidth) / 2;
3713
- const circumference = radius * 2 * Math.PI;
3714
- const offset = circumference - clampedValue / 100 * circumference;
3715
- const variantColors = {
3716
- primary: "text-primary",
3717
- success: "text-success",
3718
- warning: "text-warning",
3719
- danger: "text-danger"
3720
- };
3721
- const displayLabel = label || `${Math.round(clampedValue)}%`;
3722
- return `<div class="circular-progress inline-flex items-center justify-center ${className}" style="width: ${size}px; height: ${size}px;">
3723
- <svg class="transform -rotate-90" width="${size}" height="${size}">
3724
- <!-- Background circle -->
3725
- <circle
3726
- cx="${size / 2}"
3727
- cy="${size / 2}"
3728
- r="${radius}"
3729
- fill="none"
3730
- stroke="currentColor"
3731
- stroke-width="${strokeWidth}"
3732
- class="text-gray-200"
3733
- />
3734
- <!-- Progress circle -->
3735
- <circle
3736
- cx="${size / 2}"
3737
- cy="${size / 2}"
3738
- r="${radius}"
3739
- fill="none"
3740
- stroke="currentColor"
3741
- stroke-width="${strokeWidth}"
3742
- stroke-linecap="round"
3743
- class="${variantColors[variant]}"
3744
- style="stroke-dasharray: ${circumference}; stroke-dashoffset: ${offset}; transition: stroke-dashoffset 0.3s ease;"
3745
- />
3746
- </svg>
3747
- ${showLabel ? `<span class="absolute text-sm font-semibold text-text-primary">${(0, import_utils2.escapeHtml)(displayLabel)}</span>` : ""}
3748
- </div>`;
3749
- }
3750
- function statusIndicator(options) {
3751
- const { status, label, size = "md", pulse = false, className = "" } = options;
3752
- const sizeClasses = {
3753
- sm: { dot: "w-2 h-2", text: "text-xs" },
3754
- md: { dot: "w-2.5 h-2.5", text: "text-sm" },
3755
- lg: { dot: "w-3 h-3", text: "text-base" }
3756
- };
3757
- const statusClasses = {
3758
- online: { color: "bg-success", label: "Online" },
3759
- offline: { color: "bg-gray-400", label: "Offline" },
3760
- busy: { color: "bg-danger", label: "Busy" },
3761
- away: { color: "bg-warning", label: "Away" },
3762
- loading: { color: "bg-blue-500", label: "Loading" },
3763
- error: { color: "bg-danger", label: "Error" },
3764
- success: { color: "bg-success", label: "Success" }
3765
- };
3766
- const statusInfo = statusClasses[status];
3767
- const sizeInfo = sizeClasses[size];
3768
- const displayLabel = label || statusInfo.label;
3769
- const pulseHtml = pulse || status === "loading" ? `<span class="absolute ${sizeInfo.dot} ${statusInfo.color} rounded-full animate-ping opacity-75"></span>` : "";
3770
- return `<div class="status-indicator inline-flex items-center gap-2 ${className}">
3771
- <span class="relative flex">
3772
- ${pulseHtml}
3773
- <span class="relative ${sizeInfo.dot} ${statusInfo.color} rounded-full"></span>
3774
- </span>
3775
- ${displayLabel ? `<span class="${sizeInfo.text} text-text-secondary">${(0, import_utils2.escapeHtml)(displayLabel)}</span>` : ""}
3776
- </div>`;
3777
- }
3778
- function skeleton(options = {}) {
3779
- const { type = "text", width, height, lines = 3, animated = true, className = "" } = options;
3780
- const animateClass = animated ? "animate-pulse" : "";
3781
- const baseClass = `bg-gray-200 ${animateClass}`;
3782
- switch (type) {
3783
- case "circle":
3784
- return `<div class="${baseClass} rounded-full ${className}" style="width: ${width || "40px"}; height: ${height || "40px"}"></div>`;
3785
- case "rect":
3786
- return `<div class="${baseClass} rounded ${className}" style="width: ${width || "100%"}; height: ${height || "100px"}"></div>`;
3787
- case "card":
3788
- return `<div class="${animateClass} space-y-4 ${className}">
3789
- <div class="bg-gray-200 rounded h-40"></div>
3790
- <div class="space-y-2">
3791
- <div class="bg-gray-200 h-4 rounded w-3/4"></div>
3792
- <div class="bg-gray-200 h-4 rounded w-1/2"></div>
3793
- </div>
3794
- </div>`;
3795
- case "text":
3796
- default: {
3797
- const linesHtml = Array(lines).fill(0).map((_, i) => {
3798
- const lineWidth = i === lines - 1 ? "60%" : i === 0 ? "90%" : "80%";
3799
- return `<div class="bg-gray-200 h-4 rounded" style="width: ${lineWidth}"></div>`;
3800
- }).join("\n");
3801
- return `<div class="${animateClass} space-y-2 ${className}" style="width: ${width || "100%"}">
3802
- ${linesHtml}
3803
- </div>`;
3804
- }
3805
- }
3806
- }
3807
- function contentSkeleton(options = {}) {
3808
- const { animated = true, className = "" } = options;
3809
- const animateClass = animated ? "animate-pulse" : "";
3810
- return `<div class="${animateClass} flex gap-4 ${className}">
3811
- <div class="bg-gray-200 rounded-full w-12 h-12 flex-shrink-0"></div>
3812
- <div class="flex-1 space-y-2 py-1">
3813
- <div class="bg-gray-200 h-4 rounded w-3/4"></div>
3814
- <div class="bg-gray-200 h-4 rounded w-1/2"></div>
3815
- </div>
3816
- </div>`;
3817
- }
3818
-
3819
2868
  // libs/ui/src/bridge/core/adapter-registry.ts
3820
2869
  var AdapterRegistry = class {
3821
2870
  _adapters = /* @__PURE__ */ new Map();
@@ -4180,50 +3229,50 @@ var FrontMcpBridge = class {
4180
3229
  * Get current theme.
4181
3230
  */
4182
3231
  getTheme() {
4183
- this._ensureInitialized();
4184
- return this._adapter.getTheme();
3232
+ const adapter = this._ensureInitialized();
3233
+ return adapter.getTheme();
4185
3234
  }
4186
3235
  /**
4187
3236
  * Get current display mode.
4188
3237
  */
4189
3238
  getDisplayMode() {
4190
- this._ensureInitialized();
4191
- return this._adapter.getDisplayMode();
3239
+ const adapter = this._ensureInitialized();
3240
+ return adapter.getDisplayMode();
4192
3241
  }
4193
3242
  /**
4194
3243
  * Get tool input arguments.
4195
3244
  */
4196
3245
  getToolInput() {
4197
- this._ensureInitialized();
4198
- return this._adapter.getToolInput();
3246
+ const adapter = this._ensureInitialized();
3247
+ return adapter.getToolInput();
4199
3248
  }
4200
3249
  /**
4201
3250
  * Get tool output/result.
4202
3251
  */
4203
3252
  getToolOutput() {
4204
- this._ensureInitialized();
4205
- return this._adapter.getToolOutput();
3253
+ const adapter = this._ensureInitialized();
3254
+ return adapter.getToolOutput();
4206
3255
  }
4207
3256
  /**
4208
3257
  * Get structured content (parsed output).
4209
3258
  */
4210
3259
  getStructuredContent() {
4211
- this._ensureInitialized();
4212
- return this._adapter.getStructuredContent();
3260
+ const adapter = this._ensureInitialized();
3261
+ return adapter.getStructuredContent();
4213
3262
  }
4214
3263
  /**
4215
3264
  * Get persisted widget state.
4216
3265
  */
4217
3266
  getWidgetState() {
4218
- this._ensureInitialized();
4219
- return this._adapter.getWidgetState();
3267
+ const adapter = this._ensureInitialized();
3268
+ return adapter.getWidgetState();
4220
3269
  }
4221
3270
  /**
4222
3271
  * Get full host context.
4223
3272
  */
4224
3273
  getHostContext() {
4225
- this._ensureInitialized();
4226
- return this._adapter.getHostContext();
3274
+ const adapter = this._ensureInitialized();
3275
+ return adapter.getHostContext();
4227
3276
  }
4228
3277
  // ============================================
4229
3278
  // Actions (delegate to adapter)
@@ -4234,2026 +3283,134 @@ var FrontMcpBridge = class {
4234
3283
  * @param args - Tool arguments
4235
3284
  */
4236
3285
  async callTool(name, args) {
4237
- this._ensureInitialized();
3286
+ const adapter = this._ensureInitialized();
4238
3287
  if (!this.hasCapability("canCallTools")) {
4239
3288
  throw new Error("Tool calls are not supported by the current adapter");
4240
3289
  }
4241
- return this._adapter.callTool(name, args);
3290
+ return adapter.callTool(name, args);
4242
3291
  }
4243
3292
  /**
4244
3293
  * Send a follow-up message to the conversation.
4245
3294
  * @param content - Message content
4246
3295
  */
4247
3296
  async sendMessage(content) {
4248
- this._ensureInitialized();
3297
+ const adapter = this._ensureInitialized();
4249
3298
  if (!this.hasCapability("canSendMessages")) {
4250
3299
  throw new Error("Sending messages is not supported by the current adapter");
4251
3300
  }
4252
- return this._adapter.sendMessage(content);
3301
+ return adapter.sendMessage(content);
4253
3302
  }
4254
3303
  /**
4255
3304
  * Open an external link.
4256
3305
  * @param url - URL to open
4257
3306
  */
4258
3307
  async openLink(url) {
4259
- this._ensureInitialized();
4260
- return this._adapter.openLink(url);
3308
+ const adapter = this._ensureInitialized();
3309
+ return adapter.openLink(url);
4261
3310
  }
4262
3311
  /**
4263
3312
  * Request a display mode change.
4264
3313
  * @param mode - Desired display mode
4265
3314
  */
4266
3315
  async requestDisplayMode(mode) {
4267
- this._ensureInitialized();
4268
- return this._adapter.requestDisplayMode(mode);
3316
+ const adapter = this._ensureInitialized();
3317
+ return adapter.requestDisplayMode(mode);
4269
3318
  }
4270
3319
  /**
4271
3320
  * Request widget close.
4272
3321
  */
4273
3322
  async requestClose() {
4274
- this._ensureInitialized();
4275
- return this._adapter.requestClose();
3323
+ const adapter = this._ensureInitialized();
3324
+ return adapter.requestClose();
4276
3325
  }
4277
3326
  /**
4278
3327
  * Set widget state (persisted across sessions).
4279
3328
  * @param state - State object to persist
4280
3329
  */
4281
- setWidgetState(state) {
4282
- this._ensureInitialized();
4283
- this._adapter.setWidgetState(state);
4284
- }
4285
- // ============================================
4286
- // Events (delegate to adapter)
4287
- // ============================================
4288
- /**
4289
- * Subscribe to host context changes.
4290
- * @param callback - Called when context changes
4291
- * @returns Unsubscribe function
4292
- */
4293
- onContextChange(callback) {
4294
- this._ensureInitialized();
4295
- return this._adapter.onContextChange(callback);
4296
- }
4297
- /**
4298
- * Subscribe to tool result updates.
4299
- * @param callback - Called when tool result is received
4300
- * @returns Unsubscribe function
4301
- */
4302
- onToolResult(callback) {
4303
- this._ensureInitialized();
4304
- return this._adapter.onToolResult(callback);
4305
- }
4306
- // ============================================
4307
- // Private Helpers
4308
- // ============================================
4309
- /**
4310
- * Ensure the bridge is initialized before operations.
4311
- */
4312
- _ensureInitialized() {
4313
- if (!this._initialized || !this._adapter) {
4314
- throw new Error("FrontMcpBridge is not initialized. Call initialize() first.");
4315
- }
4316
- }
4317
- /**
4318
- * Wrap a promise with a timeout.
4319
- */
4320
- _withTimeout(promise, ms) {
4321
- return new Promise((resolve, reject) => {
4322
- const timer = setTimeout(() => {
4323
- reject(new Error(`Operation timed out after ${ms}ms`));
4324
- }, ms);
4325
- promise.then((result) => {
4326
- clearTimeout(timer);
4327
- resolve(result);
4328
- }).catch((error) => {
4329
- clearTimeout(timer);
4330
- reject(error);
4331
- });
4332
- });
4333
- }
4334
- /**
4335
- * Emit a bridge event via CustomEvent.
4336
- */
4337
- _emitEvent(type, payload) {
4338
- if (typeof window !== "undefined" && typeof CustomEvent !== "undefined") {
4339
- try {
4340
- const event = new CustomEvent(type, { detail: payload });
4341
- window.dispatchEvent(event);
4342
- } catch {
4343
- }
4344
- }
4345
- }
4346
- /**
4347
- * Log debug message if debugging is enabled.
4348
- */
4349
- _log(message) {
4350
- if (this._config.debug) {
4351
- console.log(`[FrontMcpBridge] ${message}`);
4352
- }
4353
- }
4354
- };
4355
- async function createBridge(config, registry) {
4356
- const bridge = new FrontMcpBridge(config, registry);
4357
- await bridge.initialize();
4358
- return bridge;
4359
- }
4360
-
4361
- // libs/ui/src/bridge/adapters/base-adapter.ts
4362
- var DEFAULT_CAPABILITIES = {
4363
- canCallTools: false,
4364
- canSendMessages: false,
4365
- canOpenLinks: false,
4366
- canPersistState: true,
4367
- // localStorage fallback
4368
- hasNetworkAccess: true,
4369
- supportsDisplayModes: false,
4370
- supportsTheme: true
4371
- };
4372
- var DEFAULT_SAFE_AREA = {
4373
- top: 0,
4374
- bottom: 0,
4375
- left: 0,
4376
- right: 0
4377
- };
4378
- var BaseAdapter = class {
4379
- _capabilities = { ...DEFAULT_CAPABILITIES };
4380
- _hostContext;
4381
- _widgetState = {};
4382
- _toolInput = {};
4383
- _toolOutput = void 0;
4384
- _structuredContent = void 0;
4385
- _initialized = false;
4386
- _contextListeners = /* @__PURE__ */ new Set();
4387
- _toolResultListeners = /* @__PURE__ */ new Set();
4388
- constructor() {
4389
- this._hostContext = this._createDefaultHostContext();
4390
- }
4391
- get capabilities() {
4392
- return this._capabilities;
4393
- }
4394
- async initialize() {
4395
- if (this._initialized) return;
4396
- this._loadWidgetState();
4397
- this._readInjectedData();
4398
- this._initialized = true;
4399
- }
4400
- dispose() {
4401
- this._contextListeners.clear();
4402
- this._toolResultListeners.clear();
4403
- this._initialized = false;
4404
- }
4405
- // ============================================
4406
- // Data Access
4407
- // ============================================
4408
- getTheme() {
4409
- return this._hostContext.theme;
4410
- }
4411
- getDisplayMode() {
4412
- return this._hostContext.displayMode;
4413
- }
4414
- getUserAgent() {
4415
- return this._hostContext.userAgent;
4416
- }
4417
- getLocale() {
4418
- return this._hostContext.locale;
4419
- }
4420
- getToolInput() {
4421
- return this._toolInput;
4422
- }
4423
- getToolOutput() {
4424
- return this._toolOutput;
4425
- }
4426
- getStructuredContent() {
4427
- return this._structuredContent;
4428
- }
4429
- getWidgetState() {
4430
- return this._widgetState;
4431
- }
4432
- getSafeArea() {
4433
- return this._hostContext.safeArea;
4434
- }
4435
- getViewport() {
4436
- return this._hostContext.viewport;
4437
- }
4438
- getHostContext() {
4439
- return { ...this._hostContext };
4440
- }
4441
- // ============================================
4442
- // Actions (override in subclasses for real functionality)
4443
- // ============================================
4444
- async callTool(_name, _args) {
4445
- if (!this._capabilities.canCallTools) {
4446
- throw new Error(`Tool calls are not supported by ${this.name} adapter`);
4447
- }
4448
- throw new Error("callTool not implemented");
4449
- }
4450
- async sendMessage(_content) {
4451
- if (!this._capabilities.canSendMessages) {
4452
- throw new Error(`Sending messages is not supported by ${this.name} adapter`);
4453
- }
4454
- throw new Error("sendMessage not implemented");
4455
- }
4456
- async openLink(url) {
4457
- if (!this._capabilities.canOpenLinks) {
4458
- if (typeof window !== "undefined") {
4459
- window.open(url, "_blank", "noopener,noreferrer");
4460
- return;
4461
- }
4462
- throw new Error(`Opening links is not supported by ${this.name} adapter`);
4463
- }
4464
- throw new Error("openLink not implemented");
4465
- }
4466
- async requestDisplayMode(_mode) {
4467
- if (!this._capabilities.supportsDisplayModes) {
4468
- return;
4469
- }
4470
- throw new Error("requestDisplayMode not implemented");
4471
- }
4472
- async requestClose() {
4473
- }
4474
- setWidgetState(state) {
4475
- this._widgetState = { ...this._widgetState, ...state };
4476
- this._persistWidgetState();
4477
- }
4478
- // ============================================
4479
- // Events
4480
- // ============================================
4481
- onContextChange(callback) {
4482
- this._contextListeners.add(callback);
4483
- return () => {
4484
- this._contextListeners.delete(callback);
4485
- };
4486
- }
4487
- onToolResult(callback) {
4488
- this._toolResultListeners.add(callback);
4489
- return () => {
4490
- this._toolResultListeners.delete(callback);
4491
- };
4492
- }
4493
- // ============================================
4494
- // Protected Helpers
4495
- // ============================================
4496
- /**
4497
- * Create default host context from environment detection.
4498
- */
4499
- _createDefaultHostContext() {
4500
- return {
4501
- theme: this._detectTheme(),
4502
- displayMode: "inline",
4503
- locale: this._detectLocale(),
4504
- userAgent: this._detectUserAgent(),
4505
- safeArea: DEFAULT_SAFE_AREA,
4506
- viewport: this._detectViewport()
4507
- };
4508
- }
4509
- /**
4510
- * Detect theme from CSS media query.
4511
- */
4512
- _detectTheme() {
4513
- if (typeof window !== "undefined" && window.matchMedia) {
4514
- return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
4515
- }
4516
- return "light";
4517
- }
4518
- /**
4519
- * Detect locale from navigator.
4520
- */
4521
- _detectLocale() {
4522
- if (typeof navigator !== "undefined") {
4523
- return navigator.language || "en-US";
4524
- }
4525
- return "en-US";
4526
- }
4527
- /**
4528
- * Detect user agent capabilities.
4529
- */
4530
- _detectUserAgent() {
4531
- if (typeof navigator === "undefined") {
4532
- return { type: "web", hover: true, touch: false };
4533
- }
4534
- const ua = navigator.userAgent || "";
4535
- const isMobile = /iPhone|iPad|iPod|Android/i.test(ua);
4536
- const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
4537
- const hasHover = typeof window !== "undefined" && window.matchMedia && window.matchMedia("(hover: hover)").matches;
4538
- return {
4539
- type: isMobile ? "mobile" : "web",
4540
- hover: hasHover !== false,
4541
- touch: hasTouch
4542
- };
4543
- }
4544
- /**
4545
- * Detect viewport dimensions.
4546
- */
4547
- _detectViewport() {
4548
- if (typeof window !== "undefined") {
4549
- return {
4550
- width: window.innerWidth,
4551
- height: window.innerHeight
4552
- };
4553
- }
4554
- return void 0;
4555
- }
4556
- /**
4557
- * Read injected tool data from window globals.
4558
- */
4559
- _readInjectedData() {
4560
- if (typeof window === "undefined") return;
4561
- const win = window;
4562
- if (win.__mcpToolInput) {
4563
- this._toolInput = win.__mcpToolInput;
4564
- }
4565
- if (win.__mcpToolOutput) {
4566
- this._toolOutput = win.__mcpToolOutput;
4567
- }
4568
- if (win.__mcpStructuredContent) {
4569
- this._structuredContent = win.__mcpStructuredContent;
4570
- }
4571
- if (win.__mcpHostContext) {
4572
- this._hostContext = { ...this._hostContext, ...win.__mcpHostContext };
4573
- }
4574
- }
4575
- /**
4576
- * Load widget state from localStorage.
4577
- */
4578
- _loadWidgetState() {
4579
- if (typeof localStorage === "undefined") return;
4580
- try {
4581
- const key = this._getStateKey();
4582
- const stored = localStorage.getItem(key);
4583
- if (stored) {
4584
- this._widgetState = JSON.parse(stored);
4585
- }
4586
- } catch {
4587
- }
4588
- }
4589
- /**
4590
- * Persist widget state to localStorage.
4591
- */
4592
- _persistWidgetState() {
4593
- if (typeof localStorage === "undefined") return;
4594
- try {
4595
- const key = this._getStateKey();
4596
- localStorage.setItem(key, JSON.stringify(this._widgetState));
4597
- } catch {
4598
- }
4599
- }
4600
- /**
4601
- * Get localStorage key for widget state.
4602
- */
4603
- _getStateKey() {
4604
- if (typeof window !== "undefined") {
4605
- const toolName = window.__mcpToolName || "unknown";
4606
- return `frontmcp:widget:${toolName}`;
4607
- }
4608
- return "frontmcp:widget:unknown";
4609
- }
4610
- /**
4611
- * Notify context change listeners.
4612
- */
4613
- _notifyContextChange(changes) {
4614
- this._hostContext = { ...this._hostContext, ...changes };
4615
- this._contextListeners.forEach((cb) => {
4616
- try {
4617
- cb(changes);
4618
- } catch (e) {
4619
- console.error("[FrontMcpBridge] Context change listener error:", e);
4620
- }
4621
- });
4622
- }
4623
- /**
4624
- * Notify tool result listeners.
4625
- */
4626
- _notifyToolResult(result) {
4627
- this._toolOutput = result;
4628
- this._toolResultListeners.forEach((cb) => {
4629
- try {
4630
- cb(result);
4631
- } catch (e) {
4632
- console.error("[FrontMcpBridge] Tool result listener error:", e);
4633
- }
4634
- });
4635
- }
4636
- };
4637
-
4638
- // libs/ui/src/bridge/adapters/openai.adapter.ts
4639
- var OpenAIAdapter = class extends BaseAdapter {
4640
- id = "openai";
4641
- name = "OpenAI ChatGPT";
4642
- priority = 100;
4643
- // Highest priority
4644
- _openai;
4645
- _unsubscribeContext;
4646
- _unsubscribeToolResult;
4647
- constructor() {
4648
- super();
4649
- this._capabilities = {
4650
- ...DEFAULT_CAPABILITIES,
4651
- canCallTools: true,
4652
- canSendMessages: true,
4653
- canOpenLinks: true,
4654
- canPersistState: true,
4655
- hasNetworkAccess: true,
4656
- supportsDisplayModes: true,
4657
- supportsTheme: true
4658
- };
4659
- }
4660
- /**
4661
- * Check if OpenAI Apps SDK is available.
4662
- */
4663
- canHandle() {
4664
- if (typeof window === "undefined") return false;
4665
- const win = window;
4666
- return Boolean(win.openai?.canvas);
4667
- }
4668
- /**
4669
- * Initialize the OpenAI adapter.
4670
- */
4671
- async initialize() {
4672
- if (this._initialized) return;
4673
- this._openai = window.openai;
4674
- await super.initialize();
4675
- this._syncContextFromSDK();
4676
- if (this._openai?.canvas?.onContextChange) {
4677
- this._unsubscribeContext = this._openai.canvas.onContextChange((changes) => {
4678
- this._notifyContextChange(changes);
4679
- });
4680
- }
4681
- if (this._openai?.canvas?.onToolResult) {
4682
- this._unsubscribeToolResult = this._openai.canvas.onToolResult((result) => {
4683
- this._notifyToolResult(result);
4684
- });
4685
- }
4686
- }
4687
- /**
4688
- * Dispose adapter resources.
4689
- */
4690
- dispose() {
4691
- if (this._unsubscribeContext) {
4692
- this._unsubscribeContext();
4693
- this._unsubscribeContext = void 0;
4694
- }
4695
- if (this._unsubscribeToolResult) {
4696
- this._unsubscribeToolResult();
4697
- this._unsubscribeToolResult = void 0;
4698
- }
4699
- this._openai = void 0;
4700
- super.dispose();
4701
- }
4702
- // ============================================
4703
- // Data Access (override with SDK calls)
4704
- // ============================================
4705
- getTheme() {
4706
- if (this._openai?.canvas?.getTheme) {
4707
- const theme = this._openai.canvas.getTheme();
4708
- return theme === "dark" ? "dark" : "light";
4709
- }
4710
- return super.getTheme();
4711
- }
4712
- getDisplayMode() {
4713
- if (this._openai?.canvas?.getDisplayMode) {
4714
- const mode = this._openai.canvas.getDisplayMode();
4715
- if (mode === "fullscreen" || mode === "pip" || mode === "carousel") {
4716
- return mode;
4717
- }
4718
- return "inline";
4719
- }
4720
- return super.getDisplayMode();
4721
- }
4722
- // ============================================
4723
- // Actions (proxy to SDK)
4724
- // ============================================
4725
- async callTool(name, args) {
4726
- if (!this._openai?.canvas?.callServerTool) {
4727
- throw new Error("callServerTool not available in OpenAI SDK");
4728
- }
4729
- return this._openai.canvas.callServerTool(name, args);
4730
- }
4731
- async sendMessage(content) {
4732
- if (!this._openai?.canvas?.sendMessage) {
4733
- throw new Error("sendMessage not available in OpenAI SDK");
4734
- }
4735
- await this._openai.canvas.sendMessage(content);
4736
- }
4737
- async openLink(url) {
4738
- if (!this._openai?.canvas?.openLink) {
4739
- return super.openLink(url);
4740
- }
4741
- await this._openai.canvas.openLink(url);
4742
- }
4743
- async requestDisplayMode(mode) {
4744
- if (!this._openai?.canvas?.setDisplayMode) {
4745
- return super.requestDisplayMode(mode);
4746
- }
4747
- await this._openai.canvas.setDisplayMode(mode);
4748
- this._hostContext = { ...this._hostContext, displayMode: mode };
4749
- }
4750
- async requestClose() {
4751
- if (this._openai?.canvas?.close) {
4752
- await this._openai.canvas.close();
4753
- }
4754
- }
4755
- // ============================================
4756
- // Private Helpers
4757
- // ============================================
4758
- /**
4759
- * Sync context from OpenAI SDK.
4760
- */
4761
- _syncContextFromSDK() {
4762
- if (!this._openai?.canvas) return;
4763
- if (this._openai.canvas.getTheme) {
4764
- const theme = this._openai.canvas.getTheme();
4765
- this._hostContext.theme = theme === "dark" ? "dark" : "light";
4766
- }
4767
- if (this._openai.canvas.getDisplayMode) {
4768
- const mode = this._openai.canvas.getDisplayMode();
4769
- if (mode === "fullscreen" || mode === "pip" || mode === "carousel" || mode === "inline") {
4770
- this._hostContext.displayMode = mode;
4771
- }
4772
- }
4773
- if (this._openai.canvas.getContext) {
4774
- const ctx = this._openai.canvas.getContext();
4775
- if (ctx) {
4776
- this._hostContext = { ...this._hostContext, ...ctx };
4777
- }
4778
- }
4779
- }
4780
- };
4781
- function createOpenAIAdapter() {
4782
- return new OpenAIAdapter();
4783
- }
4784
-
4785
- // libs/ui/src/bridge/adapters/ext-apps.adapter.ts
4786
- var ExtAppsAdapter = class extends BaseAdapter {
4787
- id = "ext-apps";
4788
- name = "ext-apps (SEP-1865)";
4789
- priority = 80;
4790
- // High priority, but below OpenAI native
4791
- _config;
4792
- _messageListener;
4793
- _pendingRequests = /* @__PURE__ */ new Map();
4794
- _requestId = 0;
4795
- _trustedOrigin;
4796
- _hostCapabilities = {};
4797
- constructor(config) {
4798
- super();
4799
- this._config = config || {};
4800
- this._capabilities = {
4801
- ...DEFAULT_CAPABILITIES,
4802
- canPersistState: true,
4803
- hasNetworkAccess: true,
4804
- // ext-apps usually allows network
4805
- supportsTheme: true
4806
- };
4807
- }
4808
- /**
4809
- * Check if we're in an iframe (potential ext-apps context).
4810
- */
4811
- canHandle() {
4812
- if (typeof window === "undefined") return false;
4813
- const inIframe = window.parent !== window;
4814
- if (!inIframe) return false;
4815
- const win = window;
4816
- if (win.openai?.canvas) return false;
4817
- if (win.__mcpPlatform === "ext-apps") return true;
4818
- return true;
4819
- }
4820
- /**
4821
- * Initialize the ext-apps adapter with protocol handshake.
4822
- */
4823
- async initialize() {
4824
- if (this._initialized) return;
4825
- this._setupMessageListener();
4826
- await super.initialize();
4827
- await this._performHandshake();
4828
- this._initialized = true;
4829
- }
4830
- /**
4831
- * Dispose adapter resources.
4832
- */
4833
- dispose() {
4834
- if (this._messageListener && typeof window !== "undefined") {
4835
- window.removeEventListener("message", this._messageListener);
4836
- this._messageListener = void 0;
4837
- }
4838
- for (const [id, pending] of this._pendingRequests) {
4839
- clearTimeout(pending.timeout);
4840
- pending.reject(new Error("Adapter disposed"));
4841
- }
4842
- this._pendingRequests.clear();
4843
- super.dispose();
4844
- }
4845
- // ============================================
4846
- // Actions (via JSON-RPC)
4847
- // ============================================
4848
- async callTool(name, args) {
4849
- if (!this._hostCapabilities.serverToolProxy) {
4850
- throw new Error("Server tool proxy not supported by host");
4851
- }
4852
- return this._sendRequest("ui/callServerTool", {
4853
- name,
4854
- arguments: args
4855
- });
4856
- }
4857
- async sendMessage(content) {
4858
- await this._sendRequest("ui/message", { content });
4859
- }
4860
- async openLink(url) {
4861
- if (!this._hostCapabilities.openLink) {
4862
- return super.openLink(url);
4863
- }
4864
- await this._sendRequest("ui/openLink", { url });
4865
- }
4866
- async requestDisplayMode(mode) {
4867
- await this._sendRequest("ui/setDisplayMode", { mode });
4868
- this._hostContext = { ...this._hostContext, displayMode: mode };
4869
- }
4870
- async requestClose() {
4871
- await this._sendRequest("ui/close", {});
4872
- }
4873
- // ============================================
4874
- // Private: Message Handling
4875
- // ============================================
4876
- /**
4877
- * Setup postMessage listener for incoming messages.
4878
- */
4879
- _setupMessageListener() {
4880
- if (typeof window === "undefined") return;
4881
- this._messageListener = (event) => {
4882
- this._handleMessage(event);
4883
- };
4884
- window.addEventListener("message", this._messageListener);
4885
- }
4886
- /**
4887
- * Handle incoming postMessage events.
4888
- */
4889
- _handleMessage(event) {
4890
- if (!this._isOriginTrusted(event.origin)) {
4891
- return;
4892
- }
4893
- const data = event.data;
4894
- if (!data || typeof data !== "object") return;
4895
- if (data.jsonrpc !== "2.0") return;
4896
- if ("id" in data && (data.result !== void 0 || data.error !== void 0)) {
4897
- this._handleResponse(data);
4898
- return;
4899
- }
4900
- if ("method" in data && !("id" in data)) {
4901
- this._handleNotification(data);
4902
- return;
4903
- }
4904
- }
4905
- /**
4906
- * Handle JSON-RPC response.
4907
- */
4908
- _handleResponse(response) {
4909
- const pending = this._pendingRequests.get(response.id);
4910
- if (!pending) return;
4911
- clearTimeout(pending.timeout);
4912
- this._pendingRequests.delete(response.id);
4913
- if (response.error) {
4914
- pending.reject(new Error(`${response.error.message} (code: ${response.error.code})`));
4915
- } else {
4916
- pending.resolve(response.result);
4917
- }
4918
- }
4919
- /**
4920
- * Handle JSON-RPC notification from host.
4921
- */
4922
- _handleNotification(notification) {
4923
- switch (notification.method) {
4924
- case "ui/notifications/tool-input":
4925
- this._handleToolInput(notification.params);
4926
- break;
4927
- case "ui/notifications/tool-input-partial":
4928
- this._handleToolInputPartial(notification.params);
4929
- break;
4930
- case "ui/notifications/tool-result":
4931
- this._handleToolResult(notification.params);
4932
- break;
4933
- case "ui/notifications/host-context-changed":
4934
- this._handleHostContextChange(notification.params);
4935
- break;
4936
- case "ui/notifications/initialized":
4937
- break;
4938
- case "ui/notifications/cancelled":
4939
- this._handleCancelled(notification.params);
4940
- break;
4941
- }
4942
- }
4943
- /**
4944
- * Handle tool input notification.
4945
- */
4946
- _handleToolInput(params) {
4947
- this._toolInput = params.arguments || {};
4948
- this._emitBridgeEvent("tool:input", { arguments: this._toolInput });
4949
- }
4950
- /**
4951
- * Handle partial tool input (streaming).
4952
- */
4953
- _handleToolInputPartial(params) {
4954
- this._toolInput = { ...this._toolInput, ...params.arguments };
4955
- this._emitBridgeEvent("tool:input-partial", { arguments: this._toolInput });
4956
- }
4957
- /**
4958
- * Handle tool result notification.
4959
- */
4960
- _handleToolResult(params) {
4961
- this._toolOutput = params.content;
4962
- this._structuredContent = params.structuredContent;
4963
- this._notifyToolResult(params.content);
4964
- this._emitBridgeEvent("tool:result", {
4965
- content: params.content,
4966
- structuredContent: params.structuredContent
4967
- });
4968
- }
4969
- /**
4970
- * Handle host context change notification.
4971
- */
4972
- _handleHostContextChange(params) {
4973
- const changes = {};
4974
- if (params.theme !== void 0) {
4975
- changes.theme = params.theme;
4976
- }
4977
- if (params.displayMode !== void 0) {
4978
- changes.displayMode = params.displayMode;
4979
- }
4980
- if (params.viewport !== void 0) {
4981
- changes.viewport = params.viewport;
4982
- }
4983
- if (params.locale !== void 0) {
4984
- changes.locale = params.locale;
4985
- }
4986
- if (params.timezone !== void 0) {
4987
- changes.timezone = params.timezone;
4988
- }
4989
- this._notifyContextChange(changes);
4990
- }
4991
- /**
4992
- * Handle cancellation notification.
4993
- */
4994
- _handleCancelled(params) {
4995
- const reason = params?.reason;
4996
- this._emitBridgeEvent("tool:cancelled", { reason });
4997
- }
4998
- // ============================================
4999
- // Private: JSON-RPC Transport
5000
- // ============================================
5001
- /**
5002
- * Send a JSON-RPC request to the host.
5003
- */
5004
- _sendRequest(method, params) {
5005
- return new Promise((resolve, reject) => {
5006
- const id = ++this._requestId;
5007
- const timeout = this._config.options?.initTimeout || 1e4;
5008
- const request = {
5009
- jsonrpc: "2.0",
5010
- id,
5011
- method,
5012
- params
5013
- };
5014
- const timeoutHandle = setTimeout(() => {
5015
- this._pendingRequests.delete(id);
5016
- reject(new Error(`Request ${method} timed out after ${timeout}ms`));
5017
- }, timeout);
5018
- this._pendingRequests.set(id, {
5019
- resolve,
5020
- reject,
5021
- timeout: timeoutHandle
5022
- });
5023
- this._postMessage(request);
5024
- });
5025
- }
5026
- /**
5027
- * Send a JSON-RPC notification (no response expected).
5028
- */
5029
- _sendNotification(method, params) {
5030
- const notification = {
5031
- jsonrpc: "2.0",
5032
- method,
5033
- params
5034
- };
5035
- this._postMessage(notification);
5036
- }
5037
- /**
5038
- * Post a message to the parent window.
5039
- */
5040
- _postMessage(message) {
5041
- if (typeof window === "undefined") return;
5042
- const targetOrigin = this._trustedOrigin || "*";
5043
- window.parent.postMessage(message, targetOrigin);
5044
- }
5045
- // ============================================
5046
- // Private: Handshake
5047
- // ============================================
5048
- /**
5049
- * Perform the ui/initialize handshake with the host.
5050
- */
5051
- async _performHandshake() {
5052
- const params = {
5053
- appInfo: {
5054
- name: this._config.options?.appName || "FrontMCP Widget",
5055
- version: this._config.options?.appVersion || "1.0.0"
5056
- },
5057
- appCapabilities: {
5058
- tools: {
5059
- listChanged: false
5060
- }
5061
- },
5062
- protocolVersion: this._config.options?.protocolVersion || "2024-11-05"
5063
- };
5064
- try {
5065
- const result = await this._sendRequest("ui/initialize", params);
5066
- this._hostCapabilities = result.hostCapabilities || {};
5067
- this._capabilities = {
5068
- ...this._capabilities,
5069
- canCallTools: Boolean(this._hostCapabilities.serverToolProxy),
5070
- canSendMessages: true,
5071
- canOpenLinks: Boolean(this._hostCapabilities.openLink),
5072
- supportsDisplayModes: true
5073
- };
5074
- if (result.hostContext) {
5075
- this._hostContext = {
5076
- ...this._hostContext,
5077
- ...result.hostContext
5078
- };
5079
- }
5080
- if (!this._config.options?.trustedOrigins?.length) {
5081
- }
5082
- } catch (error) {
5083
- throw new Error(`ext-apps handshake failed: ${error}`);
5084
- }
5085
- }
5086
- // ============================================
5087
- // Private: Origin Security
5088
- // ============================================
5089
- /**
5090
- * Check if an origin is trusted.
5091
- * Uses trust-on-first-use if no explicit origins configured.
5092
- */
5093
- _isOriginTrusted(origin) {
5094
- const trustedOrigins = this._config.options?.trustedOrigins;
5095
- if (trustedOrigins && trustedOrigins.length > 0) {
5096
- return trustedOrigins.includes(origin);
5097
- }
5098
- if (!this._trustedOrigin) {
5099
- this._trustedOrigin = origin;
5100
- return true;
5101
- }
5102
- return this._trustedOrigin === origin;
5103
- }
5104
- // ============================================
5105
- // Private: Events
5106
- // ============================================
5107
- /**
5108
- * Emit a bridge event via CustomEvent.
5109
- */
5110
- _emitBridgeEvent(type, detail) {
5111
- if (typeof window !== "undefined" && typeof CustomEvent !== "undefined") {
5112
- try {
5113
- const event = new CustomEvent(type, { detail });
5114
- window.dispatchEvent(event);
5115
- } catch {
5116
- }
5117
- }
5118
- }
5119
- };
5120
- function createExtAppsAdapter(config) {
5121
- return new ExtAppsAdapter(config);
5122
- }
5123
-
5124
- // libs/ui/src/bridge/adapters/claude.adapter.ts
5125
- var ClaudeAdapter = class extends BaseAdapter {
5126
- id = "claude";
5127
- name = "Claude (Anthropic)";
5128
- priority = 60;
5129
- constructor() {
5130
- super();
5131
- this._capabilities = {
5132
- ...DEFAULT_CAPABILITIES,
5133
- canCallTools: false,
5134
- // Claude artifacts can't call tools
5135
- canSendMessages: false,
5136
- // Can't send messages back to conversation
5137
- canOpenLinks: true,
5138
- // Can open links via window.open
5139
- canPersistState: true,
5140
- // localStorage works
5141
- hasNetworkAccess: false,
5142
- // Network is blocked
5143
- supportsDisplayModes: false,
5144
- // No display mode control
5145
- supportsTheme: true
5146
- // Can detect system theme
5147
- };
5148
- }
5149
- /**
5150
- * Check if we're running in a Claude artifact/widget context.
5151
- */
5152
- canHandle() {
5153
- if (typeof window === "undefined") return false;
5154
- const win = window;
5155
- if (win.__mcpPlatform === "claude") return true;
5156
- if (win.claude) return true;
5157
- if (win.__claudeArtifact) return true;
5158
- if (typeof location !== "undefined") {
5159
- const href = location.href;
5160
- if (href.includes("claude.ai") || href.includes("anthropic.com")) {
5161
- return true;
5162
- }
5163
- }
5164
- return false;
5165
- }
5166
- /**
5167
- * Initialize the Claude adapter.
5168
- */
5169
- async initialize() {
5170
- if (this._initialized) return;
5171
- await super.initialize();
5172
- this._setupThemeListener();
5173
- }
5174
- /**
5175
- * Open a link in a new tab.
5176
- * This is one of the few actions available in Claude artifacts.
5177
- */
5178
- async openLink(url) {
5179
- if (typeof window !== "undefined") {
5180
- window.open(url, "_blank", "noopener,noreferrer");
5181
- }
5182
- }
5183
- /**
5184
- * Request display mode change (no-op for Claude).
5185
- */
5186
- async requestDisplayMode(_mode) {
5187
- }
5188
- /**
5189
- * Request close (no-op for Claude).
5190
- */
5191
- async requestClose() {
5192
- }
5193
- // ============================================
5194
- // Private Helpers
5195
- // ============================================
5196
- /**
5197
- * Setup listener for system theme changes.
5198
- */
5199
- _setupThemeListener() {
5200
- if (typeof window === "undefined" || !window.matchMedia) return;
5201
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
5202
- const handleChange = (e) => {
5203
- const newTheme = e.matches ? "dark" : "light";
5204
- if (newTheme !== this._hostContext.theme) {
5205
- this._notifyContextChange({ theme: newTheme });
5206
- }
5207
- };
5208
- if (mediaQuery.addEventListener) {
5209
- mediaQuery.addEventListener("change", handleChange);
5210
- } else if (mediaQuery.addListener) {
5211
- mediaQuery.addListener(handleChange);
5212
- }
5213
- }
5214
- };
5215
- function createClaudeAdapter() {
5216
- return new ClaudeAdapter();
5217
- }
5218
-
5219
- // libs/ui/src/bridge/adapters/gemini.adapter.ts
5220
- var GeminiAdapter = class extends BaseAdapter {
5221
- id = "gemini";
5222
- name = "Google Gemini";
5223
- priority = 40;
5224
- _gemini;
5225
- constructor() {
5226
- super();
5227
- this._capabilities = {
5228
- ...DEFAULT_CAPABILITIES,
5229
- canCallTools: false,
5230
- // May be enabled if SDK supports it
5231
- canSendMessages: false,
5232
- // May be enabled if SDK supports it
5233
- canOpenLinks: true,
5234
- canPersistState: true,
5235
- hasNetworkAccess: true,
5236
- supportsDisplayModes: false,
5237
- supportsTheme: true
5238
- };
5239
- }
5240
- /**
5241
- * Check if we're running in a Gemini context.
5242
- */
5243
- canHandle() {
5244
- if (typeof window === "undefined") return false;
5245
- const win = window;
5246
- if (win.__mcpPlatform === "gemini") return true;
5247
- if (win.gemini) return true;
5248
- if (typeof location !== "undefined") {
5249
- const href = location.href;
5250
- if (href.includes("gemini.google.com") || href.includes("bard.google.com")) {
5251
- return true;
5252
- }
5253
- }
5254
- return false;
5255
- }
5256
- /**
5257
- * Initialize the Gemini adapter.
5258
- */
5259
- async initialize() {
5260
- if (this._initialized) return;
5261
- const win = window;
5262
- this._gemini = win.gemini;
5263
- if (this._gemini?.ui) {
5264
- if (this._gemini.ui.sendMessage) {
5265
- this._capabilities = { ...this._capabilities, canSendMessages: true };
5266
- }
5267
- }
5268
- await super.initialize();
5269
- this._setupThemeListener();
5270
- }
5271
- /**
5272
- * Get current theme.
5273
- */
5274
- getTheme() {
5275
- if (this._gemini?.ui?.getTheme) {
5276
- const theme = this._gemini.ui.getTheme();
5277
- return theme === "dark" ? "dark" : "light";
5278
- }
5279
- return super.getTheme();
5280
- }
5281
- /**
5282
- * Send a message (if supported by SDK).
5283
- */
5284
- async sendMessage(content) {
5285
- if (this._gemini?.ui?.sendMessage) {
5286
- await this._gemini.ui.sendMessage(content);
5287
- return;
5288
- }
5289
- throw new Error("Sending messages is not supported by Gemini adapter");
5290
- }
5291
- /**
5292
- * Open a link.
5293
- */
5294
- async openLink(url) {
5295
- if (this._gemini?.ui?.openLink) {
5296
- await this._gemini.ui.openLink(url);
5297
- return;
5298
- }
5299
- return super.openLink(url);
5300
- }
5301
- // ============================================
5302
- // Private Helpers
5303
- // ============================================
5304
- /**
5305
- * Setup listener for system theme changes.
5306
- */
5307
- _setupThemeListener() {
5308
- if (typeof window === "undefined" || !window.matchMedia) return;
5309
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
5310
- const handleChange = (e) => {
5311
- if (!this._gemini?.ui?.getTheme) {
5312
- const newTheme = e.matches ? "dark" : "light";
5313
- if (newTheme !== this._hostContext.theme) {
5314
- this._notifyContextChange({ theme: newTheme });
5315
- }
5316
- }
5317
- };
5318
- if (mediaQuery.addEventListener) {
5319
- mediaQuery.addEventListener("change", handleChange);
5320
- } else if (mediaQuery.addListener) {
5321
- mediaQuery.addListener(handleChange);
5322
- }
5323
- }
5324
- };
5325
- function createGeminiAdapter() {
5326
- return new GeminiAdapter();
5327
- }
5328
-
5329
- // libs/ui/src/bridge/adapters/generic.adapter.ts
5330
- var GenericAdapter = class extends BaseAdapter {
5331
- id = "generic";
5332
- name = "Generic Web";
5333
- priority = 0;
5334
- // Lowest priority - fallback only
5335
- constructor() {
5336
- super();
5337
- this._capabilities = {
5338
- ...DEFAULT_CAPABILITIES,
5339
- canCallTools: false,
5340
- canSendMessages: false,
5341
- canOpenLinks: true,
5342
- // window.open works
5343
- canPersistState: true,
5344
- // localStorage works
5345
- hasNetworkAccess: true,
5346
- // Assume network available
5347
- supportsDisplayModes: false,
5348
- supportsTheme: true
5349
- // System theme detection
5350
- };
5351
- }
5352
- /**
5353
- * Generic adapter can always handle the environment.
5354
- * It serves as the fallback when no other adapter matches.
5355
- */
5356
- canHandle() {
5357
- return typeof window !== "undefined";
5358
- }
5359
- /**
5360
- * Initialize the generic adapter.
5361
- */
5362
- async initialize() {
5363
- if (this._initialized) return;
5364
- await super.initialize();
5365
- this._setupThemeListener();
5366
- }
5367
- /**
5368
- * Open a link using window.open.
5369
- */
5370
- async openLink(url) {
5371
- if (typeof window !== "undefined") {
5372
- window.open(url, "_blank", "noopener,noreferrer");
5373
- }
5374
- }
5375
- // ============================================
5376
- // Private Helpers
5377
- // ============================================
5378
- /**
5379
- * Setup listener for system theme changes.
5380
- */
5381
- _setupThemeListener() {
5382
- if (typeof window === "undefined" || !window.matchMedia) return;
5383
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
5384
- const handleChange = (e) => {
5385
- const newTheme = e.matches ? "dark" : "light";
5386
- if (newTheme !== this._hostContext.theme) {
5387
- this._notifyContextChange({ theme: newTheme });
5388
- }
5389
- };
5390
- if (mediaQuery.addEventListener) {
5391
- mediaQuery.addEventListener("change", handleChange);
5392
- } else if (mediaQuery.addListener) {
5393
- mediaQuery.addListener(handleChange);
5394
- }
5395
- }
5396
- };
5397
- function createGenericAdapter() {
5398
- return new GenericAdapter();
5399
- }
5400
-
5401
- // libs/ui/src/bridge/adapters/index.ts
5402
- function registerBuiltInAdapters() {
5403
- defaultRegistry.register("openai", createOpenAIAdapter);
5404
- defaultRegistry.register("ext-apps", createExtAppsAdapter);
5405
- defaultRegistry.register("claude", createClaudeAdapter);
5406
- defaultRegistry.register("gemini", createGeminiAdapter);
5407
- defaultRegistry.register("generic", createGenericAdapter);
5408
- }
5409
- registerBuiltInAdapters();
5410
-
5411
- // libs/ui/src/bridge/runtime/iife-generator.ts
5412
- function generateBridgeIIFE(options = {}) {
5413
- const { debug = false, trustedOrigins = [], minify = false } = options;
5414
- const adapters = options.adapters || ["openai", "ext-apps", "claude", "gemini", "generic"];
5415
- const parts = [];
5416
- parts.push("(function() {");
5417
- parts.push('"use strict";');
5418
- parts.push("");
5419
- if (debug) {
5420
- parts.push('function log(msg) { console.log("[FrontMcpBridge] " + msg); }');
5421
- } else {
5422
- parts.push("function log() {}");
5423
- }
5424
- parts.push("");
5425
- parts.push("var DEFAULT_SAFE_AREA = { top: 0, bottom: 0, left: 0, right: 0 };");
5426
- parts.push("");
5427
- parts.push(generateContextDetection());
5428
- parts.push("");
5429
- parts.push(generateBaseCapabilities());
5430
- parts.push("");
5431
- if (adapters.includes("openai")) {
5432
- parts.push(generateOpenAIAdapter());
5433
- parts.push("");
5434
- }
5435
- if (adapters.includes("ext-apps")) {
5436
- parts.push(generateExtAppsAdapter(trustedOrigins));
5437
- parts.push("");
5438
- }
5439
- if (adapters.includes("claude")) {
5440
- parts.push(generateClaudeAdapter());
5441
- parts.push("");
5442
- }
5443
- if (adapters.includes("gemini")) {
5444
- parts.push(generateGeminiAdapter());
5445
- parts.push("");
5446
- }
5447
- if (adapters.includes("generic")) {
5448
- parts.push(generateGenericAdapter());
5449
- parts.push("");
5450
- }
5451
- parts.push(generatePlatformDetection(adapters));
5452
- parts.push("");
5453
- parts.push(generateBridgeClass());
5454
- parts.push("");
5455
- parts.push("var bridge = new FrontMcpBridge();");
5456
- parts.push("bridge.initialize().then(function() {");
5457
- parts.push(' log("Bridge initialized with adapter: " + bridge.adapterId);');
5458
- parts.push(' window.dispatchEvent(new CustomEvent("bridge:ready", { detail: { adapter: bridge.adapterId } }));');
5459
- parts.push("}).catch(function(err) {");
5460
- parts.push(' console.error("[FrontMcpBridge] Init failed:", err);');
5461
- parts.push(' window.dispatchEvent(new CustomEvent("bridge:error", { detail: { error: err } }));');
5462
- parts.push("});");
5463
- parts.push("");
5464
- parts.push("window.FrontMcpBridge = bridge;");
5465
- parts.push("})();");
5466
- const code = parts.join("\n");
5467
- if (minify) {
5468
- return minifyJS(code);
5469
- }
5470
- return code;
5471
- }
5472
- function generateContextDetection() {
5473
- return `
5474
- function detectTheme() {
5475
- if (typeof window !== 'undefined' && window.matchMedia) {
5476
- return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
5477
- }
5478
- return 'light';
5479
- }
5480
-
5481
- function detectLocale() {
5482
- if (typeof navigator !== 'undefined') {
5483
- return navigator.language || 'en-US';
5484
- }
5485
- return 'en-US';
5486
- }
5487
-
5488
- function detectUserAgent() {
5489
- if (typeof navigator === 'undefined') {
5490
- return { type: 'web', hover: true, touch: false };
5491
- }
5492
- var ua = navigator.userAgent || '';
5493
- var isMobile = /iPhone|iPad|iPod|Android/i.test(ua);
5494
- var hasTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
5495
- var hasHover = window.matchMedia && window.matchMedia('(hover: hover)').matches;
5496
- return { type: isMobile ? 'mobile' : 'web', hover: hasHover !== false, touch: hasTouch };
5497
- }
5498
-
5499
- function detectViewport() {
5500
- if (typeof window !== 'undefined') {
5501
- return { width: window.innerWidth, height: window.innerHeight };
5502
- }
5503
- return undefined;
5504
- }
5505
-
5506
- function readInjectedData() {
5507
- var data = { toolInput: {}, toolOutput: undefined, structuredContent: undefined };
5508
- if (typeof window !== 'undefined') {
5509
- if (window.__mcpToolInput) data.toolInput = window.__mcpToolInput;
5510
- if (window.__mcpToolOutput) data.toolOutput = window.__mcpToolOutput;
5511
- if (window.__mcpStructuredContent) data.structuredContent = window.__mcpStructuredContent;
5512
- }
5513
- return data;
5514
- }
5515
- `.trim();
5516
- }
5517
- function generateBaseCapabilities() {
5518
- return `
5519
- var DEFAULT_CAPABILITIES = {
5520
- canCallTools: false,
5521
- canSendMessages: false,
5522
- canOpenLinks: false,
5523
- canPersistState: true,
5524
- hasNetworkAccess: true,
5525
- supportsDisplayModes: false,
5526
- supportsTheme: true
5527
- };
5528
- `.trim();
5529
- }
5530
- function generateOpenAIAdapter() {
5531
- return `
5532
- var OpenAIAdapter = {
5533
- id: 'openai',
5534
- name: 'OpenAI ChatGPT',
5535
- priority: 100,
5536
- capabilities: Object.assign({}, DEFAULT_CAPABILITIES, {
5537
- canCallTools: true,
5538
- canSendMessages: true,
5539
- canOpenLinks: true,
5540
- supportsDisplayModes: true
5541
- }),
5542
- canHandle: function() {
5543
- if (typeof window === 'undefined') return false;
5544
- // Check for window.openai.callTool (the actual OpenAI SDK API)
5545
- if (window.openai && typeof window.openai.callTool === 'function') return true;
5546
- // Also check if we're being injected with tool metadata (OpenAI injects toolOutput)
5547
- if (window.openai && (window.openai.toolOutput !== undefined || window.openai.toolInput !== undefined)) return true;
5548
- return false;
5549
- },
5550
- initialize: function(context) {
5551
- var sdk = window.openai;
5552
- context.sdk = sdk;
5553
- // OpenAI SDK exposes theme and displayMode directly as properties
5554
- if (sdk.theme) {
5555
- context.hostContext.theme = sdk.theme;
5556
- }
5557
- if (sdk.displayMode) {
5558
- context.hostContext.displayMode = sdk.displayMode;
5559
- }
5560
- // Note: OpenAI SDK does not have an onContextChange equivalent
5561
- return Promise.resolve();
5562
- },
5563
- callTool: function(context, name, args) {
5564
- return context.sdk.callTool(name, args);
5565
- },
5566
- sendMessage: function(context, content) {
5567
- if (typeof context.sdk.sendFollowUpMessage === 'function') {
5568
- return context.sdk.sendFollowUpMessage(content);
5569
- }
5570
- return Promise.reject(new Error('Messages not supported'));
5571
- },
5572
- openLink: function(context, url) {
5573
- window.open(url, '_blank', 'noopener,noreferrer');
5574
- return Promise.resolve();
5575
- },
5576
- requestDisplayMode: function(context, mode) {
5577
- return Promise.resolve();
5578
- },
5579
- requestClose: function(context) {
5580
- return Promise.resolve();
5581
- }
5582
- };
5583
- `.trim();
5584
- }
5585
- function generateExtAppsAdapter(trustedOrigins) {
5586
- const originsArray = trustedOrigins.length > 0 ? JSON.stringify(trustedOrigins) : "[]";
5587
- return `
5588
- var ExtAppsAdapter = {
5589
- id: 'ext-apps',
5590
- name: 'ext-apps (SEP-1865)',
5591
- priority: 80,
5592
- capabilities: Object.assign({}, DEFAULT_CAPABILITIES, { canPersistState: true, hasNetworkAccess: true }),
5593
- trustedOrigins: ${originsArray},
5594
- trustedOrigin: null,
5595
- pendingRequests: {},
5596
- requestId: 0,
5597
- hostCapabilities: {},
5598
- canHandle: function() {
5599
- if (typeof window === 'undefined') return false;
5600
- if (window.parent === window) return false;
5601
- // Check for OpenAI SDK (window.openai.callTool) - defer to OpenAIAdapter
5602
- if (window.openai && typeof window.openai.callTool === 'function') return false;
5603
- if (window.__mcpPlatform === 'ext-apps') return true;
5604
- return true;
5605
- },
5606
- initialize: function(context) {
5607
- var self = this;
5608
- context.extApps = this;
5609
-
5610
- window.addEventListener('message', function(event) {
5611
- self.handleMessage(context, event);
5612
- });
5613
-
5614
- return self.performHandshake(context);
5615
- },
5616
- handleMessage: function(context, event) {
5617
- if (!this.isOriginTrusted(event.origin)) return;
5618
- var data = event.data;
5619
- if (!data || typeof data !== 'object' || data.jsonrpc !== '2.0') return;
5620
-
5621
- if ('id' in data && (data.result !== undefined || data.error !== undefined)) {
5622
- var pending = this.pendingRequests[data.id];
5623
- if (pending) {
5624
- clearTimeout(pending.timeout);
5625
- delete this.pendingRequests[data.id];
5626
- if (data.error) {
5627
- pending.reject(new Error(data.error.message + ' (code: ' + data.error.code + ')'));
5628
- } else {
5629
- pending.resolve(data.result);
5630
- }
5631
- }
5632
- return;
5633
- }
5634
-
5635
- if ('method' in data && !('id' in data)) {
5636
- this.handleNotification(context, data);
5637
- }
5638
- },
5639
- handleNotification: function(context, notification) {
5640
- var params = notification.params || {};
5641
- switch (notification.method) {
5642
- case 'ui/notifications/tool-input':
5643
- context.toolInput = params.arguments || {};
5644
- window.dispatchEvent(new CustomEvent('tool:input', { detail: { arguments: context.toolInput } }));
5645
- break;
5646
- case 'ui/notifications/tool-result':
5647
- context.toolOutput = params.content;
5648
- context.structuredContent = params.structuredContent;
5649
- context.notifyToolResult(params.content);
5650
- window.dispatchEvent(new CustomEvent('tool:result', { detail: params }));
5651
- break;
5652
- case 'ui/notifications/host-context-changed':
5653
- Object.assign(context.hostContext, params);
5654
- context.notifyContextChange(params);
5655
- break;
5656
- }
5657
- },
5658
- isOriginTrusted: function(origin) {
5659
- if (this.trustedOrigins.length > 0) {
5660
- return this.trustedOrigins.indexOf(origin) !== -1;
5661
- }
5662
- // When no trusted origins configured, only trust first message in iframe context
5663
- // This helps mitigate race conditions where a malicious iframe could establish trust
5664
- if (!this.trustedOrigin) {
5665
- if (window.parent !== window && origin) {
5666
- this.trustedOrigin = origin;
5667
- return true;
5668
- }
5669
- return false;
5670
- }
5671
- return this.trustedOrigin === origin;
5672
- },
5673
- sendRequest: function(method, params) {
5674
- var self = this;
5675
- return new Promise(function(resolve, reject) {
5676
- // Security: Require trusted origin before sending requests to prevent message leaks
5677
- if (!self.trustedOrigin && self.trustedOrigins.length === 0) {
5678
- reject(new Error('Cannot send request: no trusted origin established'));
5679
- return;
5680
- }
5681
-
5682
- var id = ++self.requestId;
5683
- var timeout = setTimeout(function() {
5684
- delete self.pendingRequests[id];
5685
- reject(new Error('Request ' + method + ' timed out'));
5686
- }, 10000);
5687
-
5688
- self.pendingRequests[id] = { resolve: resolve, reject: reject, timeout: timeout };
5689
-
5690
- var targetOrigin = self.trustedOrigin || self.trustedOrigins[0];
5691
- window.parent.postMessage({ jsonrpc: '2.0', id: id, method: method, params: params }, targetOrigin);
5692
- });
5693
- },
5694
- performHandshake: function(context) {
5695
- var self = this;
5696
- var params = {
5697
- appInfo: { name: 'FrontMCP Widget', version: '1.0.0' },
5698
- appCapabilities: { tools: { listChanged: false } },
5699
- protocolVersion: '2024-11-05'
5700
- };
5701
-
5702
- return this.sendRequest('ui/initialize', params).then(function(result) {
5703
- self.hostCapabilities = result.hostCapabilities || {};
5704
- self.capabilities = Object.assign({}, self.capabilities, {
5705
- canCallTools: Boolean(self.hostCapabilities.serverToolProxy),
5706
- canSendMessages: true,
5707
- canOpenLinks: Boolean(self.hostCapabilities.openLink),
5708
- supportsDisplayModes: true
5709
- });
5710
- if (result.hostContext) {
5711
- Object.assign(context.hostContext, result.hostContext);
5712
- }
5713
- });
5714
- },
5715
- callTool: function(context, name, args) {
5716
- if (!this.hostCapabilities.serverToolProxy) {
5717
- return Promise.reject(new Error('Server tool proxy not supported'));
5718
- }
5719
- return this.sendRequest('ui/callServerTool', { name: name, arguments: args });
5720
- },
5721
- sendMessage: function(context, content) {
5722
- return this.sendRequest('ui/message', { content: content });
5723
- },
5724
- openLink: function(context, url) {
5725
- if (!this.hostCapabilities.openLink) {
5726
- window.open(url, '_blank', 'noopener,noreferrer');
5727
- return Promise.resolve();
5728
- }
5729
- return this.sendRequest('ui/openLink', { url: url });
5730
- },
5731
- requestDisplayMode: function(context, mode) {
5732
- return this.sendRequest('ui/setDisplayMode', { mode: mode });
5733
- },
5734
- requestClose: function(context) {
5735
- return this.sendRequest('ui/close', {});
5736
- }
5737
- };
5738
- `.trim();
5739
- }
5740
- function generateClaudeAdapter() {
5741
- return `
5742
- var ClaudeAdapter = {
5743
- id: 'claude',
5744
- name: 'Claude (Anthropic)',
5745
- priority: 60,
5746
- capabilities: Object.assign({}, DEFAULT_CAPABILITIES, {
5747
- canCallTools: false,
5748
- canSendMessages: false,
5749
- canOpenLinks: true,
5750
- hasNetworkAccess: false,
5751
- supportsDisplayModes: false
5752
- }),
5753
- canHandle: function() {
5754
- if (typeof window === 'undefined') return false;
5755
- if (window.__mcpPlatform === 'claude') return true;
5756
- if (window.claude) return true;
5757
- if (window.__claudeArtifact) return true;
5758
- if (typeof location !== 'undefined') {
5759
- var href = location.href;
5760
- if (href.indexOf('claude.ai') !== -1 || href.indexOf('anthropic.com') !== -1) return true;
5761
- }
5762
- return false;
5763
- },
5764
- initialize: function(context) {
5765
- return Promise.resolve();
5766
- },
5767
- callTool: function() {
5768
- return Promise.reject(new Error('Tool calls not supported in Claude'));
5769
- },
5770
- sendMessage: function() {
5771
- return Promise.reject(new Error('Messages not supported in Claude'));
5772
- },
5773
- openLink: function(context, url) {
5774
- window.open(url, '_blank', 'noopener,noreferrer');
5775
- return Promise.resolve();
5776
- },
5777
- requestDisplayMode: function() {
5778
- return Promise.resolve();
5779
- },
5780
- requestClose: function() {
5781
- return Promise.resolve();
5782
- }
5783
- };
5784
- `.trim();
5785
- }
5786
- function generateGeminiAdapter() {
5787
- return `
5788
- var GeminiAdapter = {
5789
- id: 'gemini',
5790
- name: 'Google Gemini',
5791
- priority: 40,
5792
- capabilities: Object.assign({}, DEFAULT_CAPABILITIES, {
5793
- canOpenLinks: true,
5794
- hasNetworkAccess: true
5795
- }),
5796
- canHandle: function() {
5797
- if (typeof window === 'undefined') return false;
5798
- if (window.__mcpPlatform === 'gemini') return true;
5799
- if (window.gemini) return true;
5800
- if (typeof location !== 'undefined') {
5801
- var href = location.href;
5802
- if (href.indexOf('gemini.google.com') !== -1 || href.indexOf('bard.google.com') !== -1) return true;
5803
- }
5804
- return false;
5805
- },
5806
- initialize: function(context) {
5807
- if (window.gemini && window.gemini.ui && window.gemini.ui.getTheme) {
5808
- context.hostContext.theme = window.gemini.ui.getTheme() === 'dark' ? 'dark' : 'light';
5809
- }
5810
- return Promise.resolve();
5811
- },
5812
- callTool: function() {
5813
- return Promise.reject(new Error('Tool calls not supported in Gemini'));
5814
- },
5815
- sendMessage: function(context, content) {
5816
- if (window.gemini && window.gemini.ui && window.gemini.ui.sendMessage) {
5817
- return window.gemini.ui.sendMessage(content);
5818
- }
5819
- return Promise.reject(new Error('Messages not supported in Gemini'));
5820
- },
5821
- openLink: function(context, url) {
5822
- if (window.gemini && window.gemini.ui && window.gemini.ui.openLink) {
5823
- return window.gemini.ui.openLink(url);
5824
- }
5825
- window.open(url, '_blank', 'noopener,noreferrer');
5826
- return Promise.resolve();
5827
- },
5828
- requestDisplayMode: function() {
5829
- return Promise.resolve();
5830
- },
5831
- requestClose: function() {
5832
- return Promise.resolve();
3330
+ setWidgetState(state) {
3331
+ const adapter = this._ensureInitialized();
3332
+ adapter.setWidgetState(state);
5833
3333
  }
5834
- };
5835
- `.trim();
5836
- }
5837
- function generateGenericAdapter() {
5838
- return `
5839
- var GenericAdapter = {
5840
- id: 'generic',
5841
- name: 'Generic Web',
5842
- priority: 0,
5843
- capabilities: Object.assign({}, DEFAULT_CAPABILITIES, {
5844
- canOpenLinks: true,
5845
- hasNetworkAccess: true
5846
- }),
5847
- canHandle: function() {
5848
- return typeof window !== 'undefined';
5849
- },
5850
- initialize: function(context) {
5851
- return Promise.resolve();
5852
- },
5853
- callTool: function() {
5854
- return Promise.reject(new Error('Tool calls not supported'));
5855
- },
5856
- sendMessage: function() {
5857
- return Promise.reject(new Error('Messages not supported'));
5858
- },
5859
- openLink: function(context, url) {
5860
- window.open(url, '_blank', 'noopener,noreferrer');
5861
- return Promise.resolve();
5862
- },
5863
- requestDisplayMode: function() {
5864
- return Promise.resolve();
5865
- },
5866
- requestClose: function() {
5867
- return Promise.resolve();
3334
+ // ============================================
3335
+ // Events (delegate to adapter)
3336
+ // ============================================
3337
+ /**
3338
+ * Subscribe to host context changes.
3339
+ * @param callback - Called when context changes
3340
+ * @returns Unsubscribe function
3341
+ */
3342
+ onContextChange(callback) {
3343
+ const adapter = this._ensureInitialized();
3344
+ return adapter.onContextChange(callback);
5868
3345
  }
5869
- };
5870
- `.trim();
5871
- }
5872
- function generatePlatformDetection(adapters) {
5873
- const adapterVars = adapters.map((a) => {
5874
- switch (a) {
5875
- case "openai":
5876
- return "OpenAIAdapter";
5877
- case "ext-apps":
5878
- return "ExtAppsAdapter";
5879
- case "claude":
5880
- return "ClaudeAdapter";
5881
- case "gemini":
5882
- return "GeminiAdapter";
5883
- case "generic":
5884
- return "GenericAdapter";
5885
- default:
5886
- return "";
5887
- }
5888
- }).filter(Boolean);
5889
- return `
5890
- var ADAPTERS = [${adapterVars.join(", ")}].sort(function(a, b) { return b.priority - a.priority; });
5891
-
5892
- function detectPlatform() {
5893
- for (var i = 0; i < ADAPTERS.length; i++) {
5894
- if (ADAPTERS[i].canHandle()) {
5895
- log('Detected platform: ' + ADAPTERS[i].id);
5896
- return ADAPTERS[i];
5897
- }
3346
+ /**
3347
+ * Subscribe to tool result updates.
3348
+ * @param callback - Called when tool result is received
3349
+ * @returns Unsubscribe function
3350
+ */
3351
+ onToolResult(callback) {
3352
+ const adapter = this._ensureInitialized();
3353
+ return adapter.onToolResult(callback);
5898
3354
  }
5899
- log('No platform detected, using generic');
5900
- return GenericAdapter;
5901
- }
5902
- `.trim();
5903
- }
5904
- function generateBridgeClass() {
5905
- return `
5906
- function FrontMcpBridge() {
5907
- this._adapter = null;
5908
- this._initialized = false;
5909
- this._context = {
5910
- hostContext: {
5911
- theme: detectTheme(),
5912
- displayMode: 'inline',
5913
- locale: detectLocale(),
5914
- userAgent: detectUserAgent(),
5915
- safeArea: DEFAULT_SAFE_AREA,
5916
- viewport: detectViewport()
5917
- },
5918
- toolInput: {},
5919
- toolOutput: undefined,
5920
- structuredContent: undefined,
5921
- widgetState: {},
5922
- contextListeners: [],
5923
- toolResultListeners: [],
5924
- notifyContextChange: function(changes) {
5925
- Object.assign(this.hostContext, changes);
5926
- for (var i = 0; i < this.contextListeners.length; i++) {
5927
- try { this.contextListeners[i](changes); } catch(e) {}
5928
- }
5929
- },
5930
- notifyToolResult: function(result) {
5931
- this.toolOutput = result;
5932
- for (var i = 0; i < this.toolResultListeners.length; i++) {
5933
- try { this.toolResultListeners[i](result); } catch(e) {}
5934
- }
3355
+ // ============================================
3356
+ // Private Helpers
3357
+ // ============================================
3358
+ /**
3359
+ * Ensure the bridge is initialized before operations.
3360
+ * Returns the adapter for type-safe access.
3361
+ */
3362
+ _ensureInitialized() {
3363
+ if (!this._initialized || !this._adapter) {
3364
+ throw new Error("FrontMcpBridge is not initialized. Call initialize() first.");
5935
3365
  }
5936
- };
5937
-
5938
- var injected = readInjectedData();
5939
- this._context.toolInput = injected.toolInput;
5940
- this._context.toolOutput = injected.toolOutput;
5941
- this._context.structuredContent = injected.structuredContent;
5942
-
5943
- this._loadWidgetState();
5944
- }
5945
-
5946
- FrontMcpBridge.prototype._loadWidgetState = function() {
5947
- try {
5948
- var key = 'frontmcp:widget:' + (window.__mcpToolName || 'unknown');
5949
- var stored = localStorage.getItem(key);
5950
- if (stored) this._context.widgetState = JSON.parse(stored);
5951
- } catch(e) {}
5952
- };
5953
-
5954
- FrontMcpBridge.prototype._saveWidgetState = function() {
5955
- try {
5956
- var key = 'frontmcp:widget:' + (window.__mcpToolName || 'unknown');
5957
- localStorage.setItem(key, JSON.stringify(this._context.widgetState));
5958
- } catch(e) {}
5959
- };
5960
-
5961
- FrontMcpBridge.prototype.initialize = function() {
5962
- if (this._initialized) return Promise.resolve();
5963
- var self = this;
5964
- this._adapter = detectPlatform();
5965
- return this._adapter.initialize(this._context).then(function() {
5966
- self._initialized = true;
5967
- // Set up the data-tool-call click handler after initialization
5968
- self._setupDataToolCallHandler();
5969
- });
5970
- };
5971
-
5972
- Object.defineProperty(FrontMcpBridge.prototype, 'initialized', { get: function() { return this._initialized; } });
5973
- Object.defineProperty(FrontMcpBridge.prototype, 'adapterId', { get: function() { return this._adapter ? this._adapter.id : undefined; } });
5974
- Object.defineProperty(FrontMcpBridge.prototype, 'capabilities', { get: function() { return this._adapter ? this._adapter.capabilities : DEFAULT_CAPABILITIES; } });
5975
-
5976
- FrontMcpBridge.prototype.getTheme = function() { return this._context.hostContext.theme; };
5977
- FrontMcpBridge.prototype.getDisplayMode = function() { return this._context.hostContext.displayMode; };
5978
- FrontMcpBridge.prototype.getToolInput = function() { return this._context.toolInput; };
5979
- FrontMcpBridge.prototype.getToolOutput = function() { return this._context.toolOutput; };
5980
- FrontMcpBridge.prototype.getStructuredContent = function() { return this._context.structuredContent; };
5981
- FrontMcpBridge.prototype.getWidgetState = function() { return this._context.widgetState; };
5982
- FrontMcpBridge.prototype.getHostContext = function() { return Object.assign({}, this._context.hostContext); };
5983
- FrontMcpBridge.prototype.hasCapability = function(cap) { return this._adapter && this._adapter.capabilities[cap] === true; };
5984
-
5985
- // Get tool response metadata (platform-agnostic)
5986
- // Used by inline mode widgets to detect when ui/html arrives
5987
- FrontMcpBridge.prototype.getToolResponseMetadata = function() {
5988
- // OpenAI injects toolResponseMetadata for widget-producing tools
5989
- if (typeof window !== 'undefined' && window.openai && window.openai.toolResponseMetadata) {
5990
- return window.openai.toolResponseMetadata;
5991
- }
5992
- // Claude (future support)
5993
- if (typeof window !== 'undefined' && window.claude && window.claude.toolResponseMetadata) {
5994
- return window.claude.toolResponseMetadata;
5995
- }
5996
- // FrontMCP direct injection (for testing/ext-apps)
5997
- if (typeof window !== 'undefined' && window.__mcpToolResponseMetadata) {
5998
- return window.__mcpToolResponseMetadata;
5999
- }
6000
- return null;
6001
- };
6002
-
6003
- // Subscribe to tool response metadata changes (for inline mode injection)
6004
- FrontMcpBridge.prototype.onToolResponseMetadata = function(callback) {
6005
- var self = this;
6006
- var called = false;
6007
-
6008
- // Check if already available
6009
- var existing = self.getToolResponseMetadata();
6010
- if (existing) {
6011
- called = true;
6012
- callback(existing);
3366
+ return this._adapter;
6013
3367
  }
6014
-
6015
- // Set up property interceptors for OpenAI
6016
- if (typeof window !== 'undefined') {
6017
- // OpenAI: Intercept toolResponseMetadata assignment
6018
- if (!window.__frontmcpMetadataIntercepted) {
6019
- window.__frontmcpMetadataIntercepted = true;
6020
- window.__frontmcpMetadataCallbacks = [];
6021
-
6022
- // Create openai object if it doesn't exist
6023
- if (!window.openai) window.openai = {};
6024
-
6025
- var originalMetadata = window.openai.toolResponseMetadata;
6026
- Object.defineProperty(window.openai, 'toolResponseMetadata', {
6027
- get: function() { return originalMetadata; },
6028
- set: function(val) {
6029
- originalMetadata = val;
6030
- log('toolResponseMetadata set, notifying ' + window.__frontmcpMetadataCallbacks.length + ' listeners');
6031
- for (var i = 0; i < window.__frontmcpMetadataCallbacks.length; i++) {
6032
- try { window.__frontmcpMetadataCallbacks[i](val); } catch(e) {}
6033
- }
6034
- },
6035
- configurable: true
3368
+ /**
3369
+ * Wrap a promise with a timeout.
3370
+ */
3371
+ _withTimeout(promise, ms) {
3372
+ return new Promise((resolve, reject) => {
3373
+ const timer = setTimeout(() => {
3374
+ reject(new Error(`Operation timed out after ${ms}ms`));
3375
+ }, ms);
3376
+ promise.then((result) => {
3377
+ clearTimeout(timer);
3378
+ resolve(result);
3379
+ }).catch((error) => {
3380
+ clearTimeout(timer);
3381
+ reject(error);
6036
3382
  });
6037
- }
6038
-
6039
- // Register callback wrapper (store reference for unsubscribe)
6040
- var wrapper = function(metadata) {
6041
- if (!called) {
6042
- called = true;
6043
- callback(metadata);
6044
- }
6045
- };
6046
- window.__frontmcpMetadataCallbacks.push(wrapper);
6047
-
6048
- // Return unsubscribe function that removes the wrapper (not the original callback)
6049
- return function() {
6050
- if (window.__frontmcpMetadataCallbacks) {
6051
- var idx = window.__frontmcpMetadataCallbacks.indexOf(wrapper);
6052
- if (idx !== -1) window.__frontmcpMetadataCallbacks.splice(idx, 1);
6053
- }
6054
- };
6055
- }
6056
-
6057
- // Return no-op unsubscribe for non-window environments
6058
- return function() {};
6059
- };
6060
-
6061
- FrontMcpBridge.prototype.callTool = function(name, args) {
6062
- // Priority 1: Direct OpenAI SDK call (most reliable in OpenAI iframe)
6063
- // This bypasses adapter abstraction for maximum compatibility
6064
- if (typeof window !== 'undefined' && window.openai && typeof window.openai.callTool === 'function') {
6065
- log('callTool: Using OpenAI SDK directly');
6066
- return window.openai.callTool(name, args);
6067
- }
6068
-
6069
- // Priority 2: Use adapter (if initialized and supports tool calls)
6070
- if (this._adapter && this._adapter.capabilities && this._adapter.capabilities.canCallTools) {
6071
- log('callTool: Using adapter ' + this._adapter.id);
6072
- return this._adapter.callTool(this._context, name, args);
6073
- }
6074
-
6075
- // Not initialized or no tool support
6076
- if (!this._adapter) {
6077
- return Promise.reject(new Error('Bridge not initialized. Wait for bridge:ready event.'));
3383
+ });
6078
3384
  }
6079
- return Promise.reject(new Error('Tool calls not supported on this platform (' + this._adapter.id + ')'));
6080
- };
6081
-
6082
- FrontMcpBridge.prototype.sendMessage = function(content) {
6083
- if (!this._adapter) return Promise.reject(new Error('Not initialized'));
6084
- return this._adapter.sendMessage(this._context, content);
6085
- };
6086
-
6087
- FrontMcpBridge.prototype.openLink = function(url) {
6088
- if (!this._adapter) return Promise.reject(new Error('Not initialized'));
6089
- return this._adapter.openLink(this._context, url);
6090
- };
6091
-
6092
- FrontMcpBridge.prototype.requestDisplayMode = function(mode) {
6093
- if (!this._adapter) return Promise.reject(new Error('Not initialized'));
6094
- var self = this;
6095
- return this._adapter.requestDisplayMode(this._context, mode).then(function() {
6096
- self._context.hostContext.displayMode = mode;
6097
- });
6098
- };
6099
-
6100
- FrontMcpBridge.prototype.requestClose = function() {
6101
- if (!this._adapter) return Promise.reject(new Error('Not initialized'));
6102
- return this._adapter.requestClose(this._context);
6103
- };
6104
-
6105
- FrontMcpBridge.prototype.setWidgetState = function(state) {
6106
- Object.assign(this._context.widgetState, state);
6107
- this._saveWidgetState();
6108
- };
6109
-
6110
- FrontMcpBridge.prototype.onContextChange = function(callback) {
6111
- var listeners = this._context.contextListeners;
6112
- listeners.push(callback);
6113
- return function() {
6114
- var idx = listeners.indexOf(callback);
6115
- if (idx !== -1) listeners.splice(idx, 1);
6116
- };
6117
- };
6118
-
6119
- FrontMcpBridge.prototype.onToolResult = function(callback) {
6120
- var listeners = this._context.toolResultListeners;
6121
- listeners.push(callback);
6122
- return function() {
6123
- var idx = listeners.indexOf(callback);
6124
- if (idx !== -1) listeners.splice(idx, 1);
6125
- };
6126
- };
6127
-
6128
- // ==================== data-tool-call Click Handler ====================
6129
-
6130
- FrontMcpBridge.prototype._setupDataToolCallHandler = function() {
6131
- var self = this;
6132
-
6133
- document.addEventListener('click', function(e) {
6134
- // Find the closest element with data-tool-call attribute
6135
- var target = e.target;
6136
- while (target && target !== document) {
6137
- if (target.hasAttribute && target.hasAttribute('data-tool-call')) {
6138
- var toolName = target.getAttribute('data-tool-call');
6139
- var argsAttr = target.getAttribute('data-tool-args');
6140
- var args = {};
6141
-
6142
- try {
6143
- if (argsAttr) {
6144
- args = JSON.parse(argsAttr);
6145
- }
6146
- } catch (parseErr) {
6147
- console.error('[frontmcp] Failed to parse data-tool-args:', parseErr);
6148
- }
6149
-
6150
- log('data-tool-call clicked: ' + toolName);
6151
-
6152
- // Show loading state - save original content first
6153
- var originalContent = target.innerHTML;
6154
- var originalDisabled = target.disabled;
6155
- target.disabled = true;
6156
- target.classList.add('opacity-50', 'cursor-not-allowed');
6157
-
6158
- // Add spinner for buttons
6159
- var spinner = '<svg class="animate-spin -ml-1 mr-2 h-4 w-4 inline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><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></svg>';
6160
- if (target.tagName === 'BUTTON') {
6161
- target.innerHTML = spinner + 'Loading...';
6162
- }
6163
-
6164
- // Helper to reset button state
6165
- function resetButton() {
6166
- target.innerHTML = originalContent;
6167
- target.disabled = originalDisabled;
6168
- target.classList.remove('opacity-50', 'cursor-not-allowed');
6169
- }
6170
-
6171
- // Determine how to call the tool
6172
- var toolCallPromise;
6173
-
6174
- // Priority 1: Direct OpenAI SDK call (bypasses adapter abstraction)
6175
- if (typeof window !== 'undefined' && window.openai && typeof window.openai.callTool === 'function') {
6176
- log('Using OpenAI SDK directly for tool call');
6177
- toolCallPromise = window.openai.callTool(toolName, args);
6178
- }
6179
- // Priority 2: Use adapter (if it supports tool calls)
6180
- else if (self.hasCapability('canCallTools')) {
6181
- log('Using adapter for tool call');
6182
- toolCallPromise = self.callTool(toolName, args);
6183
- }
6184
- // No tool call capability
6185
- else {
6186
- console.error('[frontmcp] Tool calls not supported on this platform (' + self.adapterId + ')');
6187
- resetButton();
6188
- target.dispatchEvent(new CustomEvent('tool:error', {
6189
- detail: { name: toolName, args: args, error: 'Tool calls not supported on this platform' },
6190
- bubbles: true
6191
- }));
6192
- e.preventDefault();
6193
- return;
6194
- }
6195
-
6196
- // Handle the tool call result
6197
- toolCallPromise.then(function(result) {
6198
- log('Tool call succeeded: ' + toolName);
6199
- resetButton();
6200
-
6201
- // Update bridge state to trigger widget re-render
6202
- // React isn't hydrated in OpenAI iframe, so useState doesn't work
6203
- // Instead, we use the bridge's reactive state system
6204
- if (result && window.__frontmcp && window.__frontmcp.bridge && typeof window.__frontmcp.bridge.setWidgetState === 'function') {
6205
- var newData = result.structuredContent || result;
6206
- log('Updating bridge state with new data');
6207
- window.__frontmcp.bridge.setWidgetState(newData);
6208
- }
6209
-
6210
- // Dispatch success event
6211
- target.dispatchEvent(new CustomEvent('tool:success', {
6212
- detail: { name: toolName, args: args, result: result },
6213
- bubbles: true
6214
- }));
6215
- }).catch(function(err) {
6216
- console.error('[frontmcp] Tool call failed: ' + toolName, err);
6217
- resetButton();
6218
- // Dispatch error event
6219
- target.dispatchEvent(new CustomEvent('tool:error', {
6220
- detail: { name: toolName, args: args, error: err.message || err },
6221
- bubbles: true
6222
- }));
6223
- });
6224
-
6225
- // Prevent default behavior (e.g., form submission)
6226
- e.preventDefault();
6227
- return;
3385
+ /**
3386
+ * Emit a bridge event via CustomEvent.
3387
+ */
3388
+ _emitEvent(type, payload) {
3389
+ if (typeof window !== "undefined" && typeof CustomEvent !== "undefined") {
3390
+ try {
3391
+ const event = new CustomEvent(type, { detail: payload });
3392
+ window.dispatchEvent(event);
3393
+ } catch {
6228
3394
  }
6229
- target = target.parentElement;
6230
3395
  }
6231
- }, true); // Use capture phase to handle before React handlers
3396
+ }
3397
+ /**
3398
+ * Log debug message if debugging is enabled.
3399
+ */
3400
+ _log(message) {
3401
+ if (this._config.debug) {
3402
+ console.log(`[FrontMcpBridge] ${message}`);
3403
+ }
3404
+ }
6232
3405
  };
6233
- `.trim();
6234
- }
6235
- function minifyJS(code) {
6236
- return code.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "").replace(/\s+/g, " ").replace(/\s*([{};,:()[\]])\s*/g, "$1").replace(/;\}/g, "}").trim();
6237
- }
6238
- function generatePlatformBundle(platform, options = {}) {
6239
- const platformAdapters = {
6240
- chatgpt: ["openai", "generic"],
6241
- claude: ["claude", "generic"],
6242
- gemini: ["gemini", "generic"],
6243
- universal: ["openai", "ext-apps", "claude", "gemini", "generic"]
6244
- };
6245
- return generateBridgeIIFE({
6246
- ...options,
6247
- adapters: platformAdapters[platform]
6248
- });
3406
+ async function createBridge(config, registry) {
3407
+ const bridge = new FrontMcpBridge(config, registry);
3408
+ await bridge.initialize();
3409
+ return bridge;
6249
3410
  }
6250
- var UNIVERSAL_BRIDGE_SCRIPT = generateBridgeIIFE();
6251
- var BRIDGE_SCRIPT_TAGS = {
6252
- universal: `<script>${UNIVERSAL_BRIDGE_SCRIPT}</script>`,
6253
- chatgpt: `<script>${generatePlatformBundle("chatgpt")}</script>`,
6254
- claude: `<script>${generatePlatformBundle("claude")}</script>`,
6255
- gemini: `<script>${generatePlatformBundle("gemini")}</script>`
6256
- };
3411
+
3412
+ // libs/ui/src/bridge/runtime/index.ts
3413
+ var import_uipack = require("@frontmcp/uipack");
6257
3414
 
6258
3415
  // libs/ui/src/web-components/core/base-element.ts
6259
3416
  var import_validation2 = require("@frontmcp/uipack/validation");
@@ -7331,15 +4488,6 @@ function renderToStringSync(element) {
7331
4488
  const ReactDOMServer = require("react-dom/server");
7332
4489
  return ReactDOMServer.renderToStaticMarkup(element);
7333
4490
  }
7334
- function isReactAvailable() {
7335
- try {
7336
- require("react");
7337
- require("react-dom/server");
7338
- return true;
7339
- } catch {
7340
- return false;
7341
- }
7342
- }
7343
4491
 
7344
4492
  // libs/ui/src/react/Card.tsx
7345
4493
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -7902,51 +5050,19 @@ function useOpenLink() {
7902
5050
  );
7903
5051
  }
7904
5052
 
7905
- // libs/ui/src/react/utils.ts
7906
- var import_utils3 = require("@frontmcp/uipack/utils");
7907
- var cachedReactDOMServer = null;
7908
- function getReactDOMServer() {
7909
- if (!cachedReactDOMServer) {
7910
- try {
7911
- cachedReactDOMServer = require("react-dom/server");
7912
- } catch {
7913
- return null;
7914
- }
7915
- }
7916
- return cachedReactDOMServer;
5053
+ // libs/ui/src/renderers/react.renderer.ts
5054
+ var import_renderers = require("@frontmcp/uipack/renderers");
5055
+ var VALID_JS_IDENTIFIER = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
5056
+ function isValidComponentName(name) {
5057
+ return VALID_JS_IDENTIFIER.test(name);
7917
5058
  }
7918
- function renderChildrenToString(children) {
7919
- if (children == null) {
7920
- return "";
7921
- }
7922
- if (typeof children === "string") {
7923
- return (0, import_utils3.escapeHtml)(children);
7924
- }
7925
- if (typeof children === "number") {
7926
- return String(children);
7927
- }
7928
- if (typeof children === "boolean") {
7929
- return "";
7930
- }
7931
- try {
7932
- const server = getReactDOMServer();
7933
- if (server) {
7934
- return server.renderToStaticMarkup(children);
7935
- }
7936
- return String(children);
7937
- } catch {
7938
- return String(children);
5059
+ function sanitizeComponentName(name) {
5060
+ if (isValidComponentName(name)) {
5061
+ return name;
7939
5062
  }
5063
+ const sanitized = name.replace(/[^a-zA-Z0-9_$]/g, "_").replace(/^[0-9]/, "_$&");
5064
+ return sanitized || "Component";
7940
5065
  }
7941
- function isBrowser() {
7942
- return typeof window !== "undefined";
7943
- }
7944
- function isServer() {
7945
- return typeof window === "undefined";
7946
- }
7947
-
7948
- // libs/ui/src/renderers/react.renderer.ts
7949
- var import_renderers = require("@frontmcp/uipack/renderers");
7950
5066
  var REACT_CDN = {
7951
5067
  react: "https://esm.sh/react@19",
7952
5068
  reactDom: "https://esm.sh/react-dom@19/client"
@@ -7960,13 +5076,6 @@ var ReactRenderer = class {
7960
5076
  type = "react";
7961
5077
  priority = 20;
7962
5078
  // Higher priority than HTML
7963
- /**
7964
- * Lazy-loaded React modules.
7965
- */
7966
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7967
- React = null;
7968
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7969
- ReactDOMServer = null;
7970
5079
  /**
7971
5080
  * Check if this renderer can handle the given template.
7972
5081
  *
@@ -8007,46 +5116,109 @@ var ReactRenderer = class {
8007
5116
  throw new Error("Invalid template type for ReactRenderer");
8008
5117
  }
8009
5118
  /**
8010
- * Render the template to HTML string using react-dom/server.
5119
+ * Render the template to HTML for client-side rendering.
5120
+ *
5121
+ * Unlike SSR, this method generates HTML that will be rendered
5122
+ * client-side by React in the browser. No server-side React required.
5123
+ *
5124
+ * The generated HTML includes:
5125
+ * - A container div for the React root
5126
+ * - The component code (transpiled if needed)
5127
+ * - Props embedded as a data attribute
5128
+ * - A render script that initializes the component
8011
5129
  */
8012
- async render(template, context, options) {
8013
- await this.loadReact();
8014
- let Component;
5130
+ async render(template, context, _options) {
5131
+ const props = {
5132
+ input: context.input,
5133
+ output: context.output,
5134
+ structuredContent: context.structuredContent,
5135
+ helpers: context.helpers
5136
+ };
5137
+ const escapedProps = JSON.stringify(props).replace(/&/g, "&amp;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
5138
+ const rootId = `frontmcp-react-${(0, import_renderers.hashString)(Date.now().toString()).slice(0, 8)}`;
5139
+ let componentCode;
5140
+ let componentName;
8015
5141
  if (typeof template === "function") {
8016
- Component = template;
5142
+ const rawName = template.name || "Component";
5143
+ componentName = sanitizeComponentName(rawName);
5144
+ componentCode = `
5145
+ // Component should be registered via window.__frontmcp_components['${componentName}']
5146
+ (function() {
5147
+ if (!window.__frontmcp_components || !window.__frontmcp_components['${componentName}']) {
5148
+ console.error('[FrontMCP] Component "${componentName}" not registered. Use buildHydrationScript() to register components.');
5149
+ }
5150
+ })();
5151
+ `;
8017
5152
  } else if (typeof template === "string") {
8018
5153
  const transpiled = await this.transpile(template);
8019
- const cached = import_renderers.transpileCache.getByKey(`exec:${transpiled.hash}`);
8020
- if (cached) {
8021
- Component = cached.code;
8022
- } else {
8023
- Component = await (0, import_renderers.executeTranspiledCode)(transpiled.code, {
8024
- // Provide any additional MDX components if specified
8025
- ...options?.mdxComponents
8026
- });
8027
- import_renderers.transpileCache.setByKey(`exec:${transpiled.hash}`, {
8028
- code: Component,
8029
- hash: transpiled.hash,
8030
- cached: false
8031
- });
8032
- }
5154
+ const match = transpiled.code.match(/function\s+(\w+)/);
5155
+ const rawName = match?.[1] || "Widget";
5156
+ componentName = sanitizeComponentName(rawName);
5157
+ componentCode = transpiled.code;
8033
5158
  } else {
8034
5159
  throw new Error("Invalid template type for ReactRenderer");
8035
5160
  }
8036
- const props = {
8037
- input: context.input,
8038
- output: context.output,
8039
- structuredContent: context.structuredContent,
8040
- helpers: context.helpers
5161
+ const html = `
5162
+ <div id="${rootId}" data-frontmcp-react data-component="${componentName}" data-props='${escapedProps}'>
5163
+ <div class="flex items-center justify-center p-4 text-gray-500">
5164
+ <svg class="animate-spin h-5 w-5 mr-2" viewBox="0 0 24 24">
5165
+ <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"></circle>
5166
+ <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>
5167
+ </svg>
5168
+ Loading...
5169
+ </div>
5170
+ </div>
5171
+ <script type="module">
5172
+ (function() {
5173
+ ${componentCode}
5174
+
5175
+ // Wait for React to be available
5176
+ function waitForReact(callback, maxAttempts) {
5177
+ var attempts = 0;
5178
+ var check = function() {
5179
+ if (typeof React !== 'undefined' && typeof ReactDOM !== 'undefined') {
5180
+ callback();
5181
+ } else if (attempts < maxAttempts) {
5182
+ attempts++;
5183
+ setTimeout(check, 50);
5184
+ } else {
5185
+ console.error('[FrontMCP] React not loaded after ' + maxAttempts + ' attempts');
5186
+ }
8041
5187
  };
8042
- const element = this.React.createElement(Component, props);
8043
- const html = this.ReactDOMServer.renderToString(element);
8044
- if (options?.hydrate) {
8045
- const componentName = Component.name || "Component";
8046
- const escapedProps = JSON.stringify(props).replace(/&/g, "&amp;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
8047
- return `<div data-hydrate="${componentName}" data-props='${escapedProps}'>${html}</div>`;
5188
+ check();
5189
+ }
5190
+
5191
+ waitForReact(function() {
5192
+ try {
5193
+ var root = document.getElementById('${rootId}');
5194
+ if (!root) return;
5195
+
5196
+ var propsJson = root.getAttribute('data-props');
5197
+ var props = propsJson ? JSON.parse(propsJson.replace(/&amp;/g, '&').replace(/&#39;/g, "'").replace(/&lt;/g, '<').replace(/&gt;/g, '>')) : {};
5198
+
5199
+ // Get the component
5200
+ var Component = ${componentName};
5201
+
5202
+ // Check if it's registered globally
5203
+ if (typeof Component === 'undefined' && window.__frontmcp_components) {
5204
+ Component = window.__frontmcp_components['${componentName}'];
5205
+ }
5206
+
5207
+ if (typeof Component === 'function') {
5208
+ var element = React.createElement(Component, props);
5209
+ var reactRoot = ReactDOM.createRoot(root);
5210
+ reactRoot.render(element);
5211
+ } else {
5212
+ console.error('[FrontMCP] Component "${componentName}" not found');
5213
+ }
5214
+ } catch (err) {
5215
+ console.error('[FrontMCP] React render error:', err);
8048
5216
  }
8049
- return html;
5217
+ }, 100);
5218
+ })();
5219
+ </script>
5220
+ `;
5221
+ return html.trim();
8050
5222
  }
8051
5223
  /**
8052
5224
  * Get runtime scripts for client-side functionality.
@@ -8067,54 +5239,8 @@ var ReactRenderer = class {
8067
5239
  isInline: false
8068
5240
  };
8069
5241
  }
8070
- /**
8071
- * Load React and ReactDOMServer modules.
8072
- */
8073
- async loadReact() {
8074
- if (this.React && this.ReactDOMServer) {
8075
- return;
8076
- }
8077
- try {
8078
- this.React = await import("react");
8079
- this.ReactDOMServer = await import("react-dom/server");
8080
- } catch {
8081
- throw new Error("React is required for ReactRenderer. Install react and react-dom: npm install react react-dom");
8082
- }
8083
- }
8084
5242
  };
8085
5243
  var reactRenderer = new ReactRenderer();
8086
- function buildHydrationScript() {
8087
- return `
8088
- <script>
8089
- (function() {
8090
- // Wait for React to be available
8091
- if (typeof React === 'undefined' || typeof ReactDOM === 'undefined') {
8092
- console.warn('[FrontMCP] React not available for hydration');
8093
- return;
8094
- }
8095
-
8096
- // Find all elements marked for hydration
8097
- document.querySelectorAll('[data-hydrate]').forEach(function(root) {
8098
- var componentName = root.getAttribute('data-hydrate');
8099
- var propsJson = root.getAttribute('data-props');
8100
- var props = propsJson ? JSON.parse(propsJson) : {};
8101
-
8102
- // Look for the component in the global scope
8103
- if (window.__frontmcp_components && window.__frontmcp_components[componentName]) {
8104
- try {
8105
- ReactDOM.hydrateRoot(root, React.createElement(
8106
- window.__frontmcp_components[componentName],
8107
- props
8108
- ));
8109
- } catch (e) {
8110
- console.error('[FrontMCP] Hydration failed for', componentName, e);
8111
- }
8112
- }
8113
- });
8114
- })();
8115
- </script>
8116
- `;
8117
- }
8118
5244
 
8119
5245
  // libs/ui/src/renderers/react.adapter.ts
8120
5246
  var mountedRoots = /* @__PURE__ */ new WeakMap();
@@ -8404,22 +5530,15 @@ async function loadReactAdapter() {
8404
5530
  badgeGroup,
8405
5531
  baseLayout,
8406
5532
  betaBadge,
8407
- buildHydrationScript,
8408
5533
  busyDot,
8409
5534
  button,
8410
5535
  buttonGroup,
8411
5536
  card,
8412
5537
  cardGroup,
8413
5538
  checkbox,
8414
- circularProgress,
8415
- codePreview,
8416
5539
  confirmModal,
8417
- consentDeniedPage,
8418
5540
  consentLayout,
8419
5541
  consentLayoutBuilder,
8420
- consentPage,
8421
- consentSuccessPage,
8422
- contentSkeleton,
8423
5542
  createBridge,
8424
5543
  createLayoutBuilder,
8425
5544
  createReactAdapter,
@@ -8432,10 +5551,8 @@ async function loadReactAdapter() {
8432
5551
  errorBadge,
8433
5552
  errorLayout,
8434
5553
  errorLayoutBuilder,
8435
- errorPage,
8436
5554
  escapeHtml,
8437
5555
  featureList,
8438
- forbiddenPage,
8439
5556
  form,
8440
5557
  formActions,
8441
5558
  formRow,
@@ -8444,33 +5561,23 @@ async function loadReactAdapter() {
8444
5561
  generatePlatformBundle,
8445
5562
  ghostButton,
8446
5563
  hiddenInput,
8447
- imagePreview,
8448
5564
  inactiveBadge,
8449
5565
  infoAlert,
8450
5566
  input,
8451
- isBrowser,
8452
- isReactAvailable,
8453
- isServer,
8454
5567
  linkButton,
8455
5568
  loadReactAdapter,
8456
5569
  loadingLayout,
8457
- maintenancePage,
8458
5570
  modal,
8459
5571
  modalTrigger,
8460
5572
  newBadge,
8461
- notFoundPage,
8462
- oauthErrorPage,
8463
5573
  offlineDot,
8464
- offlinePage,
8465
5574
  onlineDot,
8466
5575
  outlineButton,
8467
5576
  pagination,
8468
5577
  pendingBadge,
8469
5578
  permissionList,
8470
5579
  primaryButton,
8471
- progressBar,
8472
5580
  radioGroup,
8473
- rateLimitPage,
8474
5581
  reactRenderer,
8475
5582
  registerAdapter,
8476
5583
  registerAllComponents,
@@ -8488,26 +5595,14 @@ async function loadReactAdapter() {
8488
5595
  renderButtonSync,
8489
5596
  renderCard,
8490
5597
  renderCardSync,
8491
- renderChildrenToString,
8492
- renderToString,
8493
- renderToStringSync,
8494
- resourceItem,
8495
- resourceList,
8496
- resourceWidget,
8497
5598
  secondaryButton,
8498
5599
  select,
8499
- serverErrorPage,
8500
- sessionExpiredPage,
8501
- skeleton,
8502
- statusIndicator,
8503
- stepProgress,
8504
5600
  successAlert,
8505
5601
  successLayout,
8506
5602
  table,
8507
5603
  textarea,
8508
5604
  toast,
8509
5605
  toastContainer,
8510
- unauthorizedPage,
8511
5606
  useCallTool,
8512
5607
  useCapability,
8513
5608
  useDisplayMode,