@seed-ship/mcp-ui-solid 6.21.0 → 6.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +173 -0
- package/README.md +102 -0
- package/dist/components/ChartJSRenderer.cjs +244 -68
- package/dist/components/ChartJSRenderer.cjs.map +1 -1
- package/dist/components/ChartJSRenderer.d.ts +9 -0
- package/dist/components/ChartJSRenderer.d.ts.map +1 -1
- package/dist/components/ChartJSRenderer.js +246 -70
- package/dist/components/ChartJSRenderer.js.map +1 -1
- package/dist/components/ExpandableWrapper.cjs +9 -1
- package/dist/components/ExpandableWrapper.cjs.map +1 -1
- package/dist/components/ExpandableWrapper.d.ts.map +1 -1
- package/dist/components/ExpandableWrapper.js +9 -1
- package/dist/components/ExpandableWrapper.js.map +1 -1
- package/dist/components/LightboxOverlay.cjs +139 -16
- package/dist/components/LightboxOverlay.cjs.map +1 -1
- package/dist/components/LightboxOverlay.d.ts +6 -0
- package/dist/components/LightboxOverlay.d.ts.map +1 -1
- package/dist/components/LightboxOverlay.js +141 -18
- package/dist/components/LightboxOverlay.js.map +1 -1
- package/dist/components/UIResourceRenderer.cjs +15 -5
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts +2 -1
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +15 -5
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/dist/context/MCPUIConfigContext.cjs +2 -1
- package/dist/context/MCPUIConfigContext.cjs.map +1 -1
- package/dist/context/MCPUIConfigContext.d.ts +90 -12
- package/dist/context/MCPUIConfigContext.d.ts.map +1 -1
- package/dist/context/MCPUIConfigContext.js +2 -1
- package/dist/context/MCPUIConfigContext.js.map +1 -1
- package/dist/context/MCPUIMathContext.cjs +19 -0
- package/dist/context/MCPUIMathContext.cjs.map +1 -0
- package/dist/context/MCPUIMathContext.d.ts +18 -0
- package/dist/context/MCPUIMathContext.d.ts.map +1 -0
- package/dist/context/MCPUIMathContext.js +19 -0
- package/dist/context/MCPUIMathContext.js.map +1 -0
- package/dist/context/MCPUIStringsContext.cjs +6 -1
- package/dist/context/MCPUIStringsContext.cjs.map +1 -1
- package/dist/context/MCPUIStringsContext.d.ts +22 -0
- package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
- package/dist/context/MCPUIStringsContext.js +6 -1
- package/dist/context/MCPUIStringsContext.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks.cjs +2 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.js +2 -0
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +8 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/plugins/katex.cjs +23 -0
- package/dist/plugins/katex.cjs.map +1 -0
- package/dist/plugins/katex.d.cts +7 -0
- package/dist/plugins/katex.d.ts +7 -0
- package/dist/plugins/katex.d.ts.map +1 -0
- package/dist/plugins/katex.js +23 -0
- package/dist/plugins/katex.js.map +1 -0
- package/dist/utils/iframe-coep.cjs.map +1 -1
- package/dist/utils/iframe-coep.d.ts +8 -0
- package/dist/utils/iframe-coep.d.ts.map +1 -1
- package/dist/utils/iframe-coep.js.map +1 -1
- package/dist/utils/math-markdown.cjs +240 -0
- package/dist/utils/math-markdown.cjs.map +1 -0
- package/dist/utils/math-markdown.d.ts +16 -0
- package/dist/utils/math-markdown.d.ts.map +1 -0
- package/dist/utils/math-markdown.js +240 -0
- package/dist/utils/math-markdown.js.map +1 -0
- package/dist/utils/pan-zoom.cjs +312 -0
- package/dist/utils/pan-zoom.cjs.map +1 -0
- package/dist/utils/pan-zoom.d.ts +235 -0
- package/dist/utils/pan-zoom.d.ts.map +1 -0
- package/dist/utils/pan-zoom.js +312 -0
- package/dist/utils/pan-zoom.js.map +1 -0
- package/package.json +26 -3
- package/src/components/ChartJSRenderer.tsx +396 -1
- package/src/components/ExpandableWrapper.tsx +26 -0
- package/src/components/LightboxOverlay.tsx +280 -4
- package/src/components/UIResourceRenderer.tsx +24 -3
- package/src/context/MCPUIConfigContext.tsx +92 -12
- package/src/context/MCPUIMathContext.tsx +32 -0
- package/src/context/MCPUIStringsContext.tsx +30 -0
- package/src/hooks/index.ts +13 -0
- package/src/index.ts +20 -0
- package/src/plugins/katex.ts +25 -0
- package/src/utils/iframe-coep.ts +8 -0
- package/src/utils/math-markdown.ts +222 -0
- package/src/utils/pan-zoom.ts +779 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LightboxOverlay.js","sources":["../../src/components/LightboxOverlay.tsx"],"sourcesContent":["/**\n * LightboxOverlay - Fullscreen image viewer\n * Sprint 5: Media Components\n */\n\nimport { Component, Show, createEffect, onCleanup } from 'solid-js'\nimport { Portal } from 'solid-js/web'\nimport type { GalleryImage } from '../types'\nimport { safeUrl } from '../utils/safe-url'\nimport { useMCPUIStrings } from '../context/MCPUIStringsContext'\n\nexport interface LightboxOverlayProps {\n /**\n * Array of images to navigate through\n */\n images: GalleryImage[]\n\n /**\n * Currently selected image index (null when closed)\n */\n selectedIndex: number | null\n\n /**\n * Callback when lightbox should close\n */\n onClose: () => void\n\n /**\n * Callback when navigating to a different image\n */\n onNavigate: (index: number) => void\n}\n\nexport const LightboxOverlay: Component<LightboxOverlayProps> = (props) => {\n const strings = useMCPUIStrings()\n const isOpen = () => props.selectedIndex !== null\n const currentImage = () =>\n props.selectedIndex !== null ? props.images[props.selectedIndex] : null\n const canGoPrev = () => props.selectedIndex !== null && props.selectedIndex > 0\n const canGoNext = () =>\n props.selectedIndex !== null && props.selectedIndex < props.images.length - 1\n\n const handlePrev = () => {\n if (canGoPrev()) {\n props.onNavigate(props.selectedIndex! - 1)\n }\n }\n\n const handleNext = () => {\n if (canGoNext()) {\n props.onNavigate(props.selectedIndex! + 1)\n }\n }\n\n // Keyboard navigation\n createEffect(() => {\n if (!isOpen()) return\n\n const handleKeydown = (e: KeyboardEvent) => {\n switch (e.key) {\n case 'Escape':\n props.onClose()\n break\n case 'ArrowLeft':\n handlePrev()\n break\n case 'ArrowRight':\n handleNext()\n break\n }\n }\n\n document.addEventListener('keydown', handleKeydown)\n document.body.style.overflow = 'hidden'\n\n onCleanup(() => {\n document.removeEventListener('keydown', handleKeydown)\n document.body.style.overflow = ''\n })\n })\n\n return (\n <Show when={isOpen()}>\n <Portal>\n <div\n class=\"fixed inset-0 z-50 bg-black/90 flex items-center justify-center\"\n onClick={props.onClose}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={strings.lightboxLabel}\n >\n {/* Close button */}\n <button\n class=\"absolute top-4 right-4 text-white/80 hover:text-white p-2 rounded-full hover:bg-white/10 transition-colors\"\n onClick={props.onClose}\n aria-label={strings.lightboxClose}\n >\n <svg class=\"w-8 h-8\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n\n {/* Previous button */}\n <Show when={canGoPrev()}>\n <button\n class=\"absolute left-4 top-1/2 -translate-y-1/2 text-white/80 hover:text-white p-2 rounded-full hover:bg-white/10 transition-colors\"\n onClick={(e) => {\n e.stopPropagation()\n handlePrev()\n }}\n aria-label={strings.lightboxPrevious}\n >\n <svg class=\"w-8 h-8\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M15 19l-7-7 7-7\"\n />\n </svg>\n </button>\n </Show>\n\n {/* Next button */}\n <Show when={canGoNext()}>\n <button\n class=\"absolute right-4 top-1/2 -translate-y-1/2 text-white/80 hover:text-white p-2 rounded-full hover:bg-white/10 transition-colors\"\n onClick={(e) => {\n e.stopPropagation()\n handleNext()\n }}\n aria-label={strings.lightboxNext}\n >\n <svg class=\"w-8 h-8\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M9 5l7 7-7 7\"\n />\n </svg>\n </button>\n </Show>\n\n {/* Image */}\n <img\n src={safeUrl(currentImage()?.url ?? '', { allowDataImage: true })}\n alt={currentImage()?.alt || ''}\n srcset={currentImage()?.srcset}\n sizes={currentImage()?.sizes}\n class=\"max-w-[90vw] max-h-[90vh] object-contain\"\n onClick={(e) => e.stopPropagation()}\n />\n\n {/* Caption */}\n <Show when={currentImage()?.caption}>\n <div class=\"absolute bottom-16 left-1/2 -translate-x-1/2 bg-black/60 text-white px-4 py-2 rounded-lg max-w-[80vw] text-center\">\n {currentImage()!.caption}\n </div>\n </Show>\n\n {/* Counter */}\n <div class=\"absolute top-4 left-4 text-white/80 bg-black/40 px-3 py-1 rounded-full text-sm\">\n {(props.selectedIndex ?? 0) + 1} / {props.images.length}\n </div>\n </div>\n </Portal>\n </Show>\n )\n}\n"],"names":["LightboxOverlay","props","strings","useMCPUIStrings","isOpen","selectedIndex","currentImage","images","canGoPrev","canGoNext","length","handlePrev","onNavigate","handleNext","createEffect","handleKeydown","e","key","onClose","document","addEventListener","body","style","overflow","onCleanup","removeEventListener","_$createComponent","Show","when","children","Portal","_el$","_$getNextElement","_tmpl$4","_el$2","firstChild","_el$11","nextSibling","_el$12","_co$3","_$getNextMarker","_el$13","_el$14","_co$4","_el$5","_el$15","_el$16","_co$5","_el$7","_el$9","_el$0","_co$","_el$8","_el$1","_el$10","_co$2","_$addEventListener","_$insert","_el$3","_tmpl$","$$click","stopPropagation","_$effect","_$setAttribute","lightboxPrevious","_$runHydrationEvents","_el$4","_tmpl$2","lightboxNext","caption","_el$6","_tmpl$3","_p$","_v$","lightboxLabel","_v$2","lightboxClose","_v$3","safeUrl","url","allowDataImage","_v$4","alt","_v$5","srcset","_v$6","sizes","t","a","o","i","n","undefined","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LightboxOverlay.js","sources":["../../src/components/LightboxOverlay.tsx"],"sourcesContent":["/**\n * LightboxOverlay - Fullscreen image viewer\n * Sprint 5: Media Components\n *\n * v6.22.0 — zoom & pan. The overlay is a fullscreen `<Portal>`: it OWNS the\n * viewport, nothing scrolls behind it (the effect below locks `body`), so\n * hijacking the wheel here is legitimate in a way it would not be for a\n * component sitting inline in a chat feed. Zoom is therefore always on in the\n * lightbox and needs no host opt-in.\n */\n\nimport { Component, Show, createEffect, createMemo, onCleanup } from 'solid-js'\nimport { Portal } from 'solid-js/web'\nimport type { GalleryImage } from '../types'\nimport { safeUrl } from '../utils/safe-url'\nimport { createPanZoom, type PanZoomPoint } from '../utils/pan-zoom'\nimport { formatMCPUIString, useMCPUIStrings } from '../context/MCPUIStringsContext'\n\n/** Highest magnification of the lightbox — 8× the fitted size. */\nconst MAX_ZOOM = 8\n\n/** Ratio one press of a zoom button (or of `+` / `-`) applies. */\nconst ZOOM_BUTTON_FACTOR = 1.5\n\n/**\n * Scale a double-click jumps to. Deliberately modest: a double-click is a\n * coarse gesture, and the wheel is right there for the rest.\n */\nconst DOUBLE_CLICK_ZOOM = 2\n\nexport interface LightboxOverlayProps {\n /**\n * Array of images to navigate through\n */\n images: GalleryImage[]\n\n /**\n * Currently selected image index (null when closed)\n */\n selectedIndex: number | null\n\n /**\n * Callback when lightbox should close\n */\n onClose: () => void\n\n /**\n * Callback when navigating to a different image\n */\n onNavigate: (index: number) => void\n}\n\nexport const LightboxOverlay: Component<LightboxOverlayProps> = (props) => {\n const strings = useMCPUIStrings()\n let imageRef: HTMLImageElement | undefined\n\n /**\n * The handlers are bound on the BACKDROP, not on the `<img>`: a pan that\n * drags the image out from under the cursor must keep receiving the pointer\n * stream, and a wheel event over the black margin around a portrait image\n * must still zoom. `target` therefore points the maths back at the image,\n * which is the element that actually carries the transform.\n */\n const panZoom = createPanZoom({ min: 1, max: MAX_ZOOM, target: () => imageRef })\n\n const isOpen = () => props.selectedIndex !== null\n const currentImage = () =>\n props.selectedIndex !== null ? props.images[props.selectedIndex] : null\n const canGoPrev = () => props.selectedIndex !== null && props.selectedIndex > 0\n const canGoNext = () =>\n props.selectedIndex !== null && props.selectedIndex < props.images.length - 1\n\n const handlePrev = () => {\n if (canGoPrev()) {\n props.onNavigate(props.selectedIndex! - 1)\n }\n }\n\n const handleNext = () => {\n if (canGoNext()) {\n props.onNavigate(props.selectedIndex! + 1)\n }\n }\n\n /**\n * Identity of the picture on screen, as a VALUE rather than as an object\n * reference — `null` while the overlay is closed.\n *\n * The index alone does not name a picture. A host that replaces `images`\n * under a held `selectedIndex` — a gallery whose list streams in, a refilter,\n * a re-render that rebuilds the array — puts a different photo on screen\n * without the index ever moving. `url` and `srcset` are what the `<img>`\n * below actually resolves, so together with the index they are what \"the\n * displayed image changed\" has to mean. (`sizes` is left out on purpose: it\n * re-picks among the candidates of the SAME picture, so it changes the\n * resolution fetched, never the subject the zoom is framing.)\n *\n * A memo, and a string, so the comparison is by value: `ImageGalleryRenderer`\n * passes `params()?.images || []`, a fresh array on every parent update, and\n * re-reading that must not by itself count as a new picture — it would throw\n * away a zoom the user is in the middle of. The index stays in the key so\n * that navigating between two entries sharing a URL is still the clean slate\n * the arrows promise.\n */\n const displayedImage = createMemo(() => {\n if (props.selectedIndex === null) return null\n const image = props.images[props.selectedIndex]\n return JSON.stringify([props.selectedIndex, image?.url ?? null, image?.srcset ?? null])\n })\n\n /**\n * Every image opens at its fitted size. Without this the transform left over\n * from the previous picture would be applied to the next one — a 6× zoom on\n * a corner of a portrait photo, carried onto a landscape one, shows black.\n * It also settles the \"arrows vs. panning\" question: navigating away is\n * always a clean slate rather than a frame half-belonging to two images.\n *\n * The dependency is `displayedImage()` and not `selectedIndex`, for the same\n * reason: a swapped-out `images` array reaches the user as exactly that black\n * frame — the old picture's scale and offset applied to a new photo — with no\n * navigation to blame it on.\n *\n * `reset()` reads its state through `untrack`, so this effect subscribes to\n * that one memo and never re-runs on its own write. The scale and offset it\n * writes are absent from the memo for the same reason: panning must not\n * reset the pan.\n *\n * `cancelGesture()` comes first, and matters most on the CLOSE (`null`): the\n * pan handlers live on the backdrop, inside the `<Show>` below, but the\n * controller belongs to this component — which `ImageGalleryRenderer` mounts\n * once and never unmounts. Close the overlay with a button still held\n * (Escape mid-drag) and the backdrop is detached before its `pointerup`,\n * which is then delivered to whatever is underneath and never to these\n * handlers. Nothing else would end that gesture: `reset()` only writes the\n * transform, and `onCleanup` belongs to an owner that is still alive. The\n * overlay would reopen stuck at `cursor: grabbing`, with `isPanning()` true\n * and the arrow keys dead behind their pan guards.\n */\n createEffect(() => {\n displayedImage()\n panZoom.cancelGesture()\n panZoom.reset()\n })\n\n /**\n * Is the keystroke going into something the user is typing in?\n *\n * The overlay binds its shortcuts on `document`, so it hears every key in\n * the page — and it does not trap focus, so the host's own composer can keep\n * it while the lightbox is open (`Tab` from the thumbnail that opened the\n * overlay walks on into the host, since the `<Portal>` content is appended\n * after it). The zoom keys are `-`, `+`, `=` and `0`: characters. Calling\n * `preventDefault()` on them without this check silently eats them out of\n * the host's text field — typing a date would zoom the photo instead.\n *\n * `Escape` stays global, as it was before the zoom keys existed: it produces\n * no character, and dismissing the modal is what it is for.\n */\n const isEditableTarget = (target: EventTarget | null): boolean => {\n if (!(target instanceof HTMLElement)) return false\n if (target.isContentEditable) return true\n return ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName)\n }\n\n // Keyboard navigation\n createEffect(() => {\n if (!isOpen()) return\n\n const handleKeydown = (e: KeyboardEvent) => {\n // Ctrl/Cmd + `+` / `-` / `0` is the browser's own page zoom; the overlay\n // must not swallow it.\n const isZoomChord = e.ctrlKey || e.metaKey\n\n // A field the user is typing in owns its keys — all of them but the one\n // that dismisses a modal.\n if (e.key !== 'Escape' && isEditableTarget(e.target)) return\n\n switch (e.key) {\n case 'Escape':\n props.onClose()\n break\n case 'ArrowLeft':\n // Mid-drag the arrows would move the picture the user is holding.\n if (panZoom.isPanning()) break\n handlePrev()\n break\n case 'ArrowRight':\n if (panZoom.isPanning()) break\n handleNext()\n break\n case '+':\n case '=':\n // `=` is `+` unshifted — the key people actually press.\n if (isZoomChord) break\n e.preventDefault()\n panZoom.zoomBy(ZOOM_BUTTON_FACTOR)\n break\n case '-':\n if (isZoomChord) break\n e.preventDefault()\n panZoom.zoomBy(1 / ZOOM_BUTTON_FACTOR)\n break\n case '0':\n if (isZoomChord) break\n e.preventDefault()\n panZoom.reset()\n break\n }\n }\n\n document.addEventListener('keydown', handleKeydown)\n document.body.style.overflow = 'hidden'\n\n onCleanup(() => {\n document.removeEventListener('keydown', handleKeydown)\n document.body.style.overflow = ''\n })\n })\n\n /**\n * Closing on a backdrop click is the behaviour users expect — but a pan\n * releases the pointer over the backdrop as often as not, and the browser\n * then fires a `click` on the common ancestor of the press and the release.\n * `wasDragged()` is exactly that distinction: it stays true from the moment\n * the pointer travelled more than a few pixels until the next `pointerdown`,\n * so the click that closes the overlay is only ever a click that did not move.\n */\n const handleBackdropClick = () => {\n if (panZoom.wasDragged()) return\n props.onClose()\n }\n\n /**\n * The chrome (close, prev/next, the zoom toolbar) sits on top of the pan\n * surface. Pressing a button must not open a gesture: while zoomed\n * `onPointerDown` calls `preventDefault()`, which costs the button its focus,\n * and a hand that shakes on the way to \"next\" would pan the image instead.\n */\n const handlePointerDown = (event: PointerEvent) => {\n const target = event.target\n if (target instanceof Element && target.closest('button')) return\n panZoom.onPointerDown(event)\n }\n\n /**\n * Viewport point of a mouse event, in the space `zoomTo` anchors on: client\n * pixels measured from the image's UNTRANSFORMED top-left corner. That corner\n * is not directly observable — `getBoundingClientRect()` already includes the\n * transform — but with `transform-origin: 0 0` the rendered left edge is\n * exactly `corner + offset`, so subtracting the current offset recovers it\n * whatever the flex centring did.\n *\n * `createPanZoom` computes the same point for the wheel but keeps it private;\n * this is the double-click's copy of it.\n */\n const anchorOf = (event: MouseEvent): PanZoomPoint | undefined => {\n if (!imageRef) return undefined\n const rect = imageRef.getBoundingClientRect()\n const offset = panZoom.offset()\n return {\n x: event.clientX - (rect.left - offset.x),\n y: event.clientY - (rect.top - offset.y),\n }\n }\n\n /** Double-click toggles: in at the spot that was double-clicked, or back out. */\n const handleDoubleClick = (event: MouseEvent) => {\n event.stopPropagation()\n if (panZoom.isZoomed()) {\n panZoom.reset()\n } else {\n panZoom.zoomTo(DOUBLE_CLICK_ZOOM, anchorOf(event))\n }\n }\n\n return (\n <Show when={isOpen()}>\n <Portal>\n <div\n class=\"fixed inset-0 z-50 bg-black/90 flex items-center justify-center\"\n style={panZoom.surfaceStyle()}\n onClick={handleBackdropClick}\n onWheel={panZoom.onWheel}\n onPointerDown={handlePointerDown}\n onPointerMove={panZoom.onPointerMove}\n onPointerUp={panZoom.onPointerUp}\n onPointerCancel={panZoom.onPointerCancel}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={strings.lightboxLabel}\n >\n {/* Close button */}\n <button\n class=\"absolute top-4 right-4 text-white/80 hover:text-white p-2 rounded-full hover:bg-white/10 transition-colors\"\n onClick={props.onClose}\n aria-label={strings.lightboxClose}\n >\n <svg class=\"w-8 h-8\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n\n {/* Previous button */}\n <Show when={canGoPrev()}>\n <button\n class=\"absolute left-4 top-1/2 -translate-y-1/2 text-white/80 hover:text-white p-2 rounded-full hover:bg-white/10 transition-colors\"\n onClick={(e) => {\n e.stopPropagation()\n handlePrev()\n }}\n aria-label={strings.lightboxPrevious}\n >\n <svg class=\"w-8 h-8\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M15 19l-7-7 7-7\"\n />\n </svg>\n </button>\n </Show>\n\n {/* Next button */}\n <Show when={canGoNext()}>\n <button\n class=\"absolute right-4 top-1/2 -translate-y-1/2 text-white/80 hover:text-white p-2 rounded-full hover:bg-white/10 transition-colors\"\n onClick={(e) => {\n e.stopPropagation()\n handleNext()\n }}\n aria-label={strings.lightboxNext}\n >\n <svg class=\"w-8 h-8\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M9 5l7 7-7 7\"\n />\n </svg>\n </button>\n </Show>\n\n {/* Image — `max-w/max-h` fit it, the transform zooms it from there */}\n <img\n ref={imageRef}\n src={safeUrl(currentImage()?.url ?? '', { allowDataImage: true })}\n alt={currentImage()?.alt || ''}\n srcset={currentImage()?.srcset}\n sizes={currentImage()?.sizes}\n class=\"max-w-[90vw] max-h-[90vh] object-contain\"\n style={panZoom.contentStyle()}\n draggable={false}\n onClick={(e) => e.stopPropagation()}\n onDblClick={handleDoubleClick}\n />\n\n {/* Caption */}\n <Show when={currentImage()?.caption}>\n <div class=\"absolute bottom-16 left-1/2 -translate-x-1/2 bg-black/60 text-white px-4 py-2 rounded-lg max-w-[80vw] text-center\">\n {currentImage()!.caption}\n </div>\n </Show>\n\n {/* Counter */}\n <div class=\"absolute top-4 left-4 text-white/80 bg-black/40 px-3 py-1 rounded-full text-sm\">\n {(props.selectedIndex ?? 0) + 1} / {props.images.length}\n </div>\n\n {/* Zoom controls — the pointer-only gestures made reachable by\n keyboard and touch. The wrapper swallows the click so the\n backdrop's close handler never sees it. */}\n <div\n class=\"absolute bottom-4 left-1/2 -translate-x-1/2 flex items-center gap-1 bg-black/50 rounded-full px-2 py-1\"\n onClick={(e) => e.stopPropagation()}\n >\n <button\n class=\"text-white/80 hover:text-white p-2 rounded-full hover:bg-white/10 transition-colors disabled:opacity-40 disabled:hover:bg-transparent\"\n onClick={() => panZoom.zoomBy(1 / ZOOM_BUTTON_FACTOR)}\n disabled={panZoom.scale() <= panZoom.min}\n aria-label={strings.zoomOut}\n title={strings.zoomOut}\n type=\"button\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607zM13.5 10.5h-6\"\n />\n </svg>\n </button>\n\n <span\n class=\"text-white/80 text-xs tabular-nums text-center min-w-[4rem]\"\n aria-live=\"polite\"\n >\n {formatMCPUIString(strings.zoomLevel, { percent: panZoom.percent() })}\n </span>\n\n <button\n class=\"text-white/80 hover:text-white p-2 rounded-full hover:bg-white/10 transition-colors disabled:opacity-40 disabled:hover:bg-transparent\"\n onClick={() => panZoom.zoomBy(ZOOM_BUTTON_FACTOR)}\n disabled={panZoom.scale() >= panZoom.max}\n aria-label={strings.zoomIn}\n title={strings.zoomIn}\n type=\"button\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607zM10.5 7.5v6m3-3h-6\"\n />\n </svg>\n </button>\n\n {/* Only while there is something to reset — at 100% it would be a\n button that does nothing. */}\n <Show when={panZoom.isZoomed()}>\n <button\n class=\"text-white/80 hover:text-white p-2 rounded-full hover:bg-white/10 transition-colors\"\n onClick={() => panZoom.reset()}\n aria-label={strings.zoomReset}\n title={strings.zoomReset}\n type=\"button\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M16.023 9.348h4.992V4.356m0 4.992l-3.181-3.183a8.25 8.25 0 00-13.803 3.7M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7\"\n />\n </svg>\n </button>\n </Show>\n </div>\n </div>\n </Portal>\n </Show>\n )\n}\n"],"names":["MAX_ZOOM","ZOOM_BUTTON_FACTOR","DOUBLE_CLICK_ZOOM","LightboxOverlay","props","strings","useMCPUIStrings","imageRef","panZoom","createPanZoom","min","max","target","isOpen","selectedIndex","currentImage","images","canGoPrev","canGoNext","length","handlePrev","onNavigate","handleNext","displayedImage","createMemo","image","JSON","stringify","url","srcset","createEffect","cancelGesture","reset","isEditableTarget","HTMLElement","isContentEditable","includes","tagName","handleKeydown","e","isZoomChord","ctrlKey","metaKey","key","onClose","isPanning","preventDefault","zoomBy","document","addEventListener","body","style","overflow","onCleanup","removeEventListener","handleBackdropClick","wasDragged","handlePointerDown","event","Element","closest","onPointerDown","anchorOf","undefined","rect","getBoundingClientRect","offset","x","clientX","left","y","clientY","top","handleDoubleClick","stopPropagation","isZoomed","zoomTo","_$createComponent","Show","when","children","Portal","_el$","_$getNextElement","_tmpl$5","_el$2","firstChild","_el$18","nextSibling","_el$19","_co$4","_$getNextMarker","_el$20","_el$21","_co$5","_el$5","_el$22","_el$23","_co$6","_el$7","_el$9","_el$0","_co$","_el$8","_el$1","_el$10","_co$2","_el$11","_el$12","_el$13","_el$14","_el$16","_el$17","_co$3","_$addEventListener","onPointerCancel","onPointerUp","onPointerMove","$$pointerdown","onWheel","$$click","_$insert","_el$3","_tmpl$","_$effect","_$setAttribute","lightboxPrevious","_$runHydrationEvents","_el$4","_tmpl$2","lightboxNext","$$dblclick","_ref$","_$use","caption","_el$6","_tmpl$3","formatMCPUIString","zoomLevel","percent","_el$15","_tmpl$4","_p$","_v$","zoomReset","_v$2","t","_v$3","surfaceStyle","_v$4","lightboxLabel","_v$5","lightboxClose","_v$6","safeUrl","allowDataImage","_v$7","alt","_v$8","_v$9","sizes","_v$0","contentStyle","_v$1","scale","_v$10","zoomOut","_v$11","_v$12","_v$13","zoomIn","_v$14","_$style","a","o","i","n","s","h","r","_$setProperty","d","l","u","c","w","_$delegateEvents"],"mappings":"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"}
|
|
@@ -60,6 +60,8 @@ const RenderContext = require("./RenderContext.cjs");
|
|
|
60
60
|
const useAction = require("../hooks/useAction.cjs");
|
|
61
61
|
const createResponsiveGrid = require("../hooks/createResponsiveGrid.cjs");
|
|
62
62
|
const marked = require("marked");
|
|
63
|
+
const MCPUIMathContext = require("../context/MCPUIMathContext.cjs");
|
|
64
|
+
const mathMarkdown = require("../utils/math-markdown.cjs");
|
|
63
65
|
const formatString = require("../utils/format-string.cjs");
|
|
64
66
|
var _tmpl$ = /* @__PURE__ */ web.template(`<svg class="w-3 h-3 text-gray-500 dark:text-gray-400"fill=none viewBox="0 0 24 24"stroke=currentColor><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">`), _tmpl$2 = /* @__PURE__ */ web.template(`<button data-mcp-ui-action=copy type=button>`), _tmpl$3 = /* @__PURE__ */ web.template(`<svg class="w-3 h-3 text-green-500"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M5 13l4 4L19 7">`), _tmpl$4 = /* @__PURE__ */ web.template(`<div class="p-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"><p class="text-red-500 dark:text-red-400 text-sm">`), _tmpl$5 = /* @__PURE__ */ web.template(`<div class=p-3>`), _tmpl$6 = /* @__PURE__ */ web.template(`<div class="absolute inset-0 flex items-center justify-center"><div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600">`), _tmpl$7 = /* @__PURE__ */ web.template(`<div class="absolute inset-0 flex items-center justify-center p-4"><div class=text-center><p class="text-red-600 dark:text-red-400 text-sm font-medium"></p><p class="text-gray-600 dark:text-gray-400 text-xs mt-1">`), _tmpl$8 = /* @__PURE__ */ web.template(`<h3 class="text-sm font-semibold text-gray-900 dark:text-white mb-3">`), _tmpl$9 = /* @__PURE__ */ web.template(`<div class="w-full h-full p-4"><!$><!/><div class="w-full h-full"role=img><img class="w-full h-auto max-h-[300px] object-contain">`), _tmpl$0 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full min-h-[300px] bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden"><!$><!/><!$><!/><!$><!/><!$><!/>`), _tmpl$1 = /* @__PURE__ */ web.template(`<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">`), _tmpl$10 = /* @__PURE__ */ web.template(`<tr>`), _tmpl$11 = /* @__PURE__ */ web.template(`<td class="px-6 py-4 text-sm text-gray-700 dark:text-gray-200 whitespace-normal break-words leading-relaxed first:pl-6 last:pr-6">`), _tmpl$12 = /* @__PURE__ */ web.template(`<tbody class="bg-white dark:bg-gray-800 relative">`), _tmpl$13 = /* @__PURE__ */ web.template(`<button class="w-full text-left px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">`), _tmpl$14 = /* @__PURE__ */ web.template(`<div class="absolute right-10 top-2 z-10"><button class="opacity-60 hover:opacity-100 px-2 py-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm"aria-haspopup=menu><svg class="w-3 h-3 text-gray-500 dark:text-gray-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 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"></path></svg></button><!$><!/>`), _tmpl$15 = /* @__PURE__ */ web.template(`<span class="ml-2 text-xs font-normal text-gray-400">`), _tmpl$16 = /* @__PURE__ */ web.template(`<h3 class="text-sm font-semibold text-gray-900 dark:text-white mb-3 flex-shrink-0"><!$><!/><!$><!/>`), _tmpl$17 = /* @__PURE__ */ web.template(`<button type=button class="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 text-sm">×`), _tmpl$18 = /* @__PURE__ */ web.template(`<div class="relative mb-3"><span class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 pointer-events-none text-sm">🔍</span><input type=text class="w-full max-w-xs min-w-[200px] pl-8 pr-8 py-1.5 text-sm border border-gray-200 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 focus:border-blue-400 focus:ring-1 focus:ring-blue-400 outline-none"><!$><!/>`), _tmpl$19 = /* @__PURE__ */ web.template(`<p class="text-xs text-gray-500 dark:text-gray-400 mb-2">`), _tmpl$20 = /* @__PURE__ */ web.template(`<div class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><span>`), _tmpl$21 = /* @__PURE__ */ web.template(`<select class="ml-2 px-1 py-0.5 text-xs border border-gray-200 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300"data-mcp-ui-action=page-size>`), _tmpl$22 = /* @__PURE__ */ web.template(`<span class=text-gray-400>`), _tmpl$23 = /* @__PURE__ */ web.template(`<div class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><span><!$><!/>–<!$><!/> / <!$><!/></span><div class="flex items-center gap-2"><button type=button class="px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"data-mcp-ui-action=page-prev><span aria-hidden=true>◀</span></button><span aria-live=polite><!$><!/> / <!$><!/></span><button type=button class="px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"data-mcp-ui-action=page-next><span aria-hidden=true>▶</span></button><!$><!/>`), _tmpl$24 = /* @__PURE__ */ web.template(`<div><!$><!/><div><!$><!/><!$><!/><div role=region tabindex=0><table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700 border-separate border-spacing-0"><thead class="bg-gray-100 dark:bg-gray-900 sticky top-0 z-10"><tr></tr></thead><!$><!/></table></div><!$><!/><!$><!/>`), _tmpl$25 = /* @__PURE__ */ web.template(`<th scope=col class="px-6 py-3 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider border-b border-gray-200 dark:border-gray-700 first:pl-6 last:pr-6 bg-gray-100 dark:bg-gray-900 cursor-pointer select-none hover:bg-gray-200 dark:hover:bg-gray-800 transition-colors"><span class="inline-flex items-center gap-1"><!$><!/><span class="text-[10px] leading-none">`), _tmpl$26 = /* @__PURE__ */ web.template(`<option>`), _tmpl$27 = /* @__PURE__ */ web.template(`<span class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">`), _tmpl$28 = /* @__PURE__ */ web.template(`<div class="mt-3 flex items-center"><span><!$><!/> <!$><!/>%`), _tmpl$29 = /* @__PURE__ */ web.template(`<p class="mt-2 text-xs text-gray-500 dark:text-gray-400">`), _tmpl$30 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4 group"><!$><!/><div class="flex flex-col h-full justify-between"><div><p class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide"></p><div class="mt-2 flex items-baseline"><p class="text-2xl font-semibold text-gray-900 dark:text-white"></p><!$><!/></div></div><!$><!/><!$><!/>`), _tmpl$31 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4 group"><!$><!/><!$><!/>`), _tmpl$32 = /* @__PURE__ */ web.template(`<img class="max-w-full max-h-[400px] object-contain rounded shadow-sm hover:opacity-90 transition-opacity"loading=lazy>`, true, false, false), _tmpl$33 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col"><div class="flex-1 flex items-center justify-center p-4 bg-gray-50 dark:bg-gray-900 min-h-[200px]"></div><div class="p-3 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800"><p class="text-sm text-gray-600 dark:text-gray-400 text-center italic">`), _tmpl$34 = /* @__PURE__ */ web.template(`<a target=_blank rel="noopener noreferrer"class=cursor-zoom-in>`), _tmpl$35 = /* @__PURE__ */ web.template(`<div class="px-4 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900"><h3 class="text-sm font-semibold text-gray-900 dark:text-white">`), _tmpl$36 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col"><!$><!/><iframe class="w-full border-0 flex-1"loading=lazy></iframe><!$><!/>`, true, false, false), _tmpl$37 = /* @__PURE__ */ web.template(`<figcaption class="p-3 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800"><p class="text-sm text-gray-600 dark:text-gray-400 text-center">`), _tmpl$38 = /* @__PURE__ */ web.template(`<figure><div class="flex-1 flex items-center justify-center p-4 bg-gray-50 dark:bg-gray-900 min-h-[200px]"><a target=_blank rel="noopener noreferrer"class="cursor-zoom-in focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 rounded"><img class="max-w-full max-h-[500px] object-contain rounded shadow-sm hover:opacity-95 transition-opacity"loading=lazy></a></div><!$><!/>`, true, false, false), _tmpl$39 = /* @__PURE__ */ web.template(`<p class="text-xs text-gray-500 dark:text-gray-400 truncate">`), _tmpl$40 = /* @__PURE__ */ web.template(`<a target=_blank rel="noopener noreferrer"><div class="p-2 bg-blue-50 dark:bg-blue-900/30 rounded-full text-blue-600 dark:text-blue-400 group-hover:bg-blue-100 dark:group-hover:bg-blue-900/50 shrink-0 transition-colors"aria-hidden=true><svg xmlns=http://www.w3.org/2000/svg class="w-5 h-5"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></div><div class="flex-1 min-w-0"><h4 class="text-sm font-medium text-gray-900 dark:text-white truncate group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"></h4><!$><!/></div><svg xmlns=http://www.w3.org/2000/svg class="w-4 h-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300 shrink-0 transition-colors"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1=10 y1=14 x2=21 y2=3>`), _tmpl$41 = /* @__PURE__ */ web.template(`<div class="inline-flex items-center gap-1.5 px-2 py-1 rounded-md bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 text-xs text-yellow-800 dark:text-yellow-200"role=alert><svg xmlns=http://www.w3.org/2000/svg class="w-3.5 h-3.5"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1=12 y1=9 x2=12 y2=13></line><line x1=12 y1=17 x2=12.01 y2=17></line></svg><span>`), _tmpl$42 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4"><p class="text-sm font-medium text-red-900 dark:text-red-100"></p><p class="text-xs text-red-700 dark:text-red-300 mt-1">`), _tmpl$43 = /* @__PURE__ */ web.template(`<div role=alert class="w-full rounded-lg border border-amber-300 bg-amber-50 px-3 py-2 text-sm text-amber-800 dark:border-amber-700/50 dark:bg-amber-900/20 dark:text-amber-200"><!$><!/> <code class=font-mono>`), _tmpl$44 = /* @__PURE__ */ web.template(`<span aria-hidden=true>`), _tmpl$45 = /* @__PURE__ */ web.template(`<a rel="noopener noreferrer"><!$><!/><!$><!/>`), _tmpl$46 = /* @__PURE__ */ web.template(`<span class="animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full"aria-hidden=true>`), _tmpl$47 = /* @__PURE__ */ web.template(`<button type=button><!$><!/><!$><!/><!$><!/>`), _tmpl$48 = /* @__PURE__ */ web.template(`<p class="text-xs text-red-600 dark:text-red-400 mt-1">`), _tmpl$49 = /* @__PURE__ */ web.template(`<div class=mt-3><p class="text-xs font-medium text-red-700 dark:text-red-300"></p><ul class="mt-1 text-xs text-red-600 dark:text-red-400 list-disc list-inside">`), _tmpl$50 = /* @__PURE__ */ web.template(`<p class="text-xs text-red-500 dark:text-red-500 mt-2">`), _tmpl$51 = /* @__PURE__ */ web.template(`<div class="relative w-full bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 group"><!$><!/><div class="flex items-start gap-3"><div class="p-2 bg-red-100 dark:bg-red-900/40 rounded-full shrink-0"><svg class="w-5 h-5 text-red-600 dark:text-red-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path></svg></div><div class="flex-1 min-w-0"><h4 class="text-sm font-semibold text-red-800 dark:text-red-200"></h4><p class="text-sm text-red-700 dark:text-red-300 mt-1"></p><!$><!/><!$><!/><!$><!/>`), _tmpl$52 = /* @__PURE__ */ web.template(`<li>`), _tmpl$53 = /* @__PURE__ */ web.template(`<div class="px-4 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900"><h3 class="text-sm font-semibold text-gray-900 dark:text-white capitalize">`), _tmpl$54 = /* @__PURE__ */ web.template(`<div class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden"><!$><!/><!$><!/>`), _tmpl$55 = /* @__PURE__ */ web.template(`<div><div class="grid gap-4"data-mcp-ui-grid></div><!$><!/>`), _tmpl$56 = /* @__PURE__ */ web.template(`<div class=min-w-0>`);
|
|
65
67
|
function CopyButton(props) {
|
|
@@ -308,7 +310,7 @@ function ChartRenderer(props) {
|
|
|
308
310
|
}
|
|
309
311
|
const HIGHLIGHT_MARK_CLASS = "bg-yellow-200 dark:bg-[#222F49] text-inherit rounded px-0.5";
|
|
310
312
|
function highlightQuery(html, query) {
|
|
311
|
-
var _a;
|
|
313
|
+
var _a, _b;
|
|
312
314
|
const q = query.trim();
|
|
313
315
|
if (!q) return html;
|
|
314
316
|
if (typeof document === "undefined") return html;
|
|
@@ -319,6 +321,7 @@ function highlightQuery(html, query) {
|
|
|
319
321
|
const walker = document.createTreeWalker(template.content, NodeFilter.SHOW_TEXT);
|
|
320
322
|
const textNodes = [];
|
|
321
323
|
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
324
|
+
if ((_a = node.parentElement) == null ? void 0 : _a.closest("math")) continue;
|
|
322
325
|
textNodes.push(node);
|
|
323
326
|
}
|
|
324
327
|
for (const node of textNodes) {
|
|
@@ -346,7 +349,7 @@ function highlightQuery(html, query) {
|
|
|
346
349
|
if (cursor < text.length) {
|
|
347
350
|
fragment.appendChild(document.createTextNode(text.slice(cursor)));
|
|
348
351
|
}
|
|
349
|
-
(
|
|
352
|
+
(_b = node.parentNode) == null ? void 0 : _b.replaceChild(fragment, node);
|
|
350
353
|
}
|
|
351
354
|
return template.innerHTML;
|
|
352
355
|
}
|
|
@@ -374,7 +377,7 @@ function transformCellCitations(text, ctx) {
|
|
|
374
377
|
});
|
|
375
378
|
});
|
|
376
379
|
}
|
|
377
|
-
function renderCellValue(value, citationCtx) {
|
|
380
|
+
function renderCellValue(value, citationCtx, mathRenderer) {
|
|
378
381
|
if (value === null || value === void 0) {
|
|
379
382
|
return "-";
|
|
380
383
|
}
|
|
@@ -404,6 +407,9 @@ function renderCellValue(value, citationCtx) {
|
|
|
404
407
|
if (strValue.trim() === "") {
|
|
405
408
|
return "-";
|
|
406
409
|
}
|
|
410
|
+
if (mathRenderer && strValue.includes("$")) {
|
|
411
|
+
return mathMarkdown.parseMathMarkdown(strValue, mathRenderer, "cellMarkdown", citationCtx ? (text) => transformCellCitations(text, citationCtx) : void 0);
|
|
412
|
+
}
|
|
407
413
|
const markdownLinkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
408
414
|
if (markdownLinkRegex.test(strValue)) {
|
|
409
415
|
const htmlValue = strValue.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer" class="text-blue-600 dark:text-blue-400 hover:underline">$1</a>');
|
|
@@ -429,6 +435,7 @@ function TableRenderer(props) {
|
|
|
429
435
|
const tableParams = props.component.params;
|
|
430
436
|
let scrollContainerRef;
|
|
431
437
|
const strings = MCPUIStringsContext.useMCPUIStrings();
|
|
438
|
+
const mathRenderer = MCPUIMathContext.useMCPUIMath();
|
|
432
439
|
const citationCtx = tableParams.citationMap ? {
|
|
433
440
|
map: tableParams.citationMap,
|
|
434
441
|
render: tableParams.citationRender,
|
|
@@ -688,7 +695,7 @@ ${dataRows}`;
|
|
|
688
695
|
children: (column) => (() => {
|
|
689
696
|
var _el$27 = web.getNextElement(_tmpl$11);
|
|
690
697
|
web.insert(_el$27, web.createComponent(SafeHtml.SafeHtml, {
|
|
691
|
-
html: () => highlightQuery(renderCellValue(row[column.key], citationCtx), debouncedQuery())
|
|
698
|
+
html: () => highlightQuery(renderCellValue(row[column.key], citationCtx, mathRenderer()), debouncedQuery())
|
|
692
699
|
}));
|
|
693
700
|
return _el$27;
|
|
694
701
|
})()
|
|
@@ -723,7 +730,7 @@ ${dataRows}`;
|
|
|
723
730
|
children: (column) => (() => {
|
|
724
731
|
var _el$30 = web.getNextElement(_tmpl$11);
|
|
725
732
|
web.insert(_el$30, web.createComponent(SafeHtml.SafeHtml, {
|
|
726
|
-
html: () => highlightQuery(renderCellValue(row[column.key], citationCtx), debouncedQuery())
|
|
733
|
+
html: () => highlightQuery(renderCellValue(row[column.key], citationCtx, mathRenderer()), debouncedQuery())
|
|
727
734
|
}));
|
|
728
735
|
return _el$30;
|
|
729
736
|
})()
|
|
@@ -1144,6 +1151,7 @@ function extractImageFromMarkdown(content, fallbackAlt) {
|
|
|
1144
1151
|
}
|
|
1145
1152
|
function TextRenderer(props) {
|
|
1146
1153
|
const strings = MCPUIStringsContext.useMCPUIStrings();
|
|
1154
|
+
const mathRenderer = MCPUIMathContext.useMCPUIMath();
|
|
1147
1155
|
const textParams = props.component.params;
|
|
1148
1156
|
const imageData = solidJs.createMemo(() => {
|
|
1149
1157
|
if (textParams.markdown && textParams.content) {
|
|
@@ -1168,6 +1176,8 @@ function TextRenderer(props) {
|
|
|
1168
1176
|
return escapeHtml.escapeHtml(String(raw));
|
|
1169
1177
|
}
|
|
1170
1178
|
if (textParams.markdown && !imageData()) {
|
|
1179
|
+
const renderMath = mathRenderer();
|
|
1180
|
+
if (renderMath) return mathMarkdown.parseMathMarkdown(String(raw), renderMath, "prose");
|
|
1171
1181
|
return sanitizeHtml.sanitizeHtml(marked.marked.parse(raw, {
|
|
1172
1182
|
async: false
|
|
1173
1183
|
}), sanitizeHtml.SANITIZE_PROFILES.prose);
|