@mediansh/widget 0.6.0 → 0.8.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.
@@ -0,0 +1,11 @@
1
+ "use client";
2
+ "use client";
3
+ import {
4
+ po
5
+ } from "./chunk-R3S6Y434.js";
6
+ import "./chunk-HLALDSPM.js";
7
+ import "./chunk-77KIJLPP.js";
8
+ export {
9
+ po as Mermaid
10
+ };
11
+ //# sourceMappingURL=mermaid-GHXKKRXX-U6EYEPWB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,11 +1,12 @@
1
1
  "use client";
2
2
  import {
3
3
  cn
4
- } from "./chunk-3KEM4W7J.js";
4
+ } from "./chunk-3ZXE5RBN.js";
5
5
  import {
6
6
  Qs
7
- } from "./chunk-DVQ7V3LR.js";
8
- import "./chunk-W6NPKKCE.js";
7
+ } from "./chunk-R3S6Y434.js";
8
+ import "./chunk-HLALDSPM.js";
9
+ import "./chunk-77KIJLPP.js";
9
10
 
10
11
  // src/next-link-shim.tsx
11
12
  import { forwardRef } from "react";
@@ -117,4 +118,4 @@ function MessageMarkdown({
117
118
  export {
118
119
  MessageMarkdown
119
120
  };
120
- //# sourceMappingURL=message-markdown-LOE74LBE.js.map
121
+ //# sourceMappingURL=message-markdown-KQVNAD42.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/next-link-shim.tsx","../../../apps/web/src/lib/links.ts","../../../apps/web/src/components/ui/message-markdown.tsx"],"sourcesContent":["import { forwardRef, type AnchorHTMLAttributes } from \"react\";\n\n/**\n * Stands in for `next/link` when the widget is bundled for npm, via the\n * `paths` entry in this package's tsconfig. The app links with the\n * framework's router; the package has no router, and the only links that\n * reach it are the ones a reply writes, which an anchor follows the same.\n *\n * The swap is not only a simplification. `next/link` is CommonJS, so bundling\n * it drags in a `require` shim, and Turbopack throws on a dynamic `require`\n * at runtime: an inlined Link white-screens the host page it was supposed to\n * be a guest on.\n *\n * Next-only props are swallowed here so they do not land on a DOM element\n * that has never heard of them.\n */\ntype NextOnlyProps = {\n prefetch?: boolean | null;\n replace?: boolean;\n scroll?: boolean;\n shallow?: boolean;\n passHref?: boolean;\n legacyBehavior?: boolean;\n locale?: string | false;\n};\n\nconst Link = forwardRef<\n HTMLAnchorElement,\n AnchorHTMLAttributes<HTMLAnchorElement> & NextOnlyProps\n>(function Link(\n {\n prefetch: _prefetch,\n replace: _replace,\n scroll: _scroll,\n shallow: _shallow,\n passHref: _passHref,\n legacyBehavior: _legacyBehavior,\n locale: _locale,\n ...props\n },\n ref,\n) {\n return <a ref={ref} {...props} />;\n});\n\nexport default Link;\n","/**\n * Whether an address is one of ours.\n *\n * One rule, in one place, because two things lean on it and they have to\n * agree: a link inside a reply, and a row saying where a call went. Ours\n * open in the tab you are in, the way every other link in the app does.\n * Anything with a host on it leaves, and takes a new tab with it, so\n * following one never costs you a half-written reply.\n *\n * `//` is excluded on purpose. It looks like a path and is a protocol\n * relative URL, which is as external as it gets.\n */\nexport function staysInApp(href: string): boolean {\n return href.startsWith(\"/\") && !href.startsWith(\"//\");\n}\n","import Link from \"next/link\";\nimport { Streamdown, type Components } from \"streamdown\";\n\nimport { staysInApp } from \"@/lib/links\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Markdown, sized for a chat bubble. The agent and the team write it; this\n * renders it the same way in the widget and the inbox, so a reply reads\n * identically on both ends of the conversation.\n *\n * Streamdown underneath, because a reply can be read while it is still being\n * written: half-finished emphasis and an unclosed code fence render as what\n * they are becoming rather than as stray punctuation. Its own code block\n * chrome stays off; a copy button and line numbers are IDE furniture, not\n * chat.\n *\n * Everything stays at the bubble's own text size: a heading the model was\n * told not to write renders as a bold line rather than a headline, so a\n * disobedient reply is merely emphatic instead of enormous.\n *\n * Customer messages never come through here. What a visitor types is quoted\n * verbatim, asterisks and all; markdown is something the house voice writes.\n */\n\n/**\n * What a link wears, wherever it goes.\n *\n * The palette has no colour to spend on one, so the underline is the whole of\n * the signal and has to be worth reading as one: solid, at the text's own\n * weight, close enough under the words to belong to them. Nothing else in a\n * reply is underlined, which is what makes it mean something.\n */\nconst LINK =\n \"font-medium break-all underline decoration-foreground/60 decoration-1 underline-offset-[3px] transition-colors hover:decoration-foreground\";\n\n/** A stray heading becomes a bold line of body text, whatever its rank. */\nconst Flattened: Components[\"h1\"] = ({ children }) => (\n <p className=\"font-semibold\">{children}</p>\n);\n\n/**\n * Headings that are headings.\n *\n * Sized in `em` rather than in steps of the type scale, so they are a\n * proportion of whatever they are set in: the same markdown reads right in\n * the assistant's column and in a card half its size, and neither has to\n * know what the other chose.\n *\n * Two ranks and then a floor. Anything past the second level of an answer in\n * a chat is a list pretending to be an outline, and rendering six sizes\n * would only make that look deliberate.\n */\nconst RANKS: Components = {\n h1: ({ children }) => (\n <p className=\"mt-2 text-[1.25em] leading-tight font-semibold first:mt-0\">\n {children}\n </p>\n ),\n h2: ({ children }) => (\n <p className=\"mt-2 text-[1.1em] leading-snug font-semibold first:mt-0\">\n {children}\n </p>\n ),\n h3: ({ children }) => (\n <p className=\"mt-1 font-semibold first:mt-0\">{children}</p>\n ),\n h4: ({ children }) => <p className=\"font-semibold\">{children}</p>,\n h5: ({ children }) => <p className=\"font-semibold\">{children}</p>,\n h6: ({ children }) => <p className=\"font-semibold\">{children}</p>,\n};\n\nconst FLAT: Components = {\n h1: Flattened,\n h2: Flattened,\n h3: Flattened,\n h4: Flattened,\n h5: Flattened,\n h6: Flattened,\n};\n\nconst COMPONENTS: Components = {\n p: ({ children }) => <p className=\"break-words\">{children}</p>,\n\n /** A link, and whether it leaves. See `lib/links.ts` for the rule. */\n a: ({ children, href }) => {\n const to = href ?? \"\";\n\n return staysInApp(to) ? (\n <Link href={to} className={LINK}>\n {children}\n </Link>\n ) : (\n <a href={to} target=\"_blank\" rel=\"noopener noreferrer\" className={LINK}>\n {children}\n </a>\n );\n },\n\n ul: ({ children }) => (\n <ul className=\"list-disc space-y-1 pl-5\">{children}</ul>\n ),\n ol: ({ children, start }) => (\n <ol start={start} className=\"list-decimal space-y-1 pl-5\">\n {children}\n </ol>\n ),\n\n blockquote: ({ children }) => (\n <blockquote className=\"border-l-2 border-foreground/20 pl-3 text-foreground/80\">\n {children}\n </blockquote>\n ),\n\n // Inline code only. Streamdown's own bg-muted chip vanishes inside a\n // muted bubble, so the chip leans on the text colour instead. Fenced code\n // is left alone: Streamdown's block, with its language header and\n // highlighting, is the proper thing and needs no help.\n inlineCode: ({ children }) => (\n <code className=\"rounded bg-foreground/10 px-1 py-0.5 font-mono text-[0.85em]\">\n {children}\n </code>\n ),\n\n // A table is an object on the page rather than a stripe across it, so it\n // is boxed and it hugs what is in it. `w-fit` is the whole of that: two\n // columns of single digits stay two columns of single digits instead of\n // being stretched over the width of the reply, which is what makes a\n // three-row table read as a spreadsheet somebody dropped in.\n //\n // Every part of it is written down here, including the ones that were\n // being left to Streamdown. Its defaults are sized for a document with a\n // table in it: a grey header band, sm text, px-4 cells. In a thread that\n // is louder than the answer around it.\n table: ({ children }) => (\n <div className=\"w-fit max-w-full overflow-x-auto rounded-lg border\">\n <table className=\"w-full text-left text-xs\">{children}</table>\n </div>\n ),\n thead: ({ children }) => <thead className=\"bg-muted/50\">{children}</thead>,\n // The line under the head belongs to the head. Between rows it belongs to\n // the row above, and the last one has the box's own edge under it already.\n tr: ({ children }) => (\n <tr className=\"[&:not(:last-child)>td]:border-b\">{children}</tr>\n ),\n th: ({ children }) => (\n <th className=\"border-b px-3 py-2 font-medium whitespace-nowrap\">\n {children}\n </th>\n ),\n // Figures line up under each other, and a cell with a paragraph in it sits\n // against the top of its row rather than floating in the middle of one.\n td: ({ children }) => (\n <td className=\"px-3 py-2 align-top tabular-nums\">{children}</td>\n ),\n\n hr: () => <hr className=\"border-foreground/15\" />,\n\n img: ({ src, alt }) => (\n // eslint-disable-next-line @next/next/no-img-element -- arbitrary remote URL, nothing for the optimizer to do.\n <img src={src} alt={alt ?? \"\"} className=\"max-w-full rounded-lg\" />\n ),\n};\n\nexport function MessageMarkdown({\n body,\n className,\n headings = \"flatten\",\n mode = \"streaming\",\n}: {\n body: string;\n className?: string;\n /**\n * What to do with a heading. Flattened by default, which is what a bubble\n * wants: a customer reply that reaches for an H1 should read as emphatic,\n * not as a press release. `keep` is for the places an answer is a document\n * rather than a message, which is the assistant's own column.\n */\n headings?: \"flatten\" | \"keep\";\n /**\n * Streaming is for a reply that is still being written: Streamdown splits\n * it into blocks so a token does not reparse the whole page. Static is\n * for a finished answer shown all at once. Dumping a complete reply in\n * streaming mode is how a palette answer arrives as chunks.\n */\n mode?: \"streaming\" | \"static\";\n}) {\n return (\n <Streamdown\n // The code block brings its own my-4, sized for prose; in a bubble the\n // column's gap is the spacing, so the margin goes.\n className={cn(\n \"flex min-w-0 flex-col gap-2 break-words\",\n \"[&>[data-streamdown=code-block]]:my-0\",\n className,\n )}\n components={{\n ...COMPONENTS,\n ...(headings === \"keep\" ? RANKS : FLAT),\n }}\n controls={false}\n lineNumbers={false}\n mode={mode}\n >\n {body}\n </Streamdown>\n );\n}\n"],"mappings":"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","names":["Link","jsx"]}
1
+ {"version":3,"sources":["../src/next-link-shim.tsx","../../../apps/web/src/lib/links.ts","../../../apps/web/src/components/ui/message-markdown.tsx"],"sourcesContent":["import { forwardRef, type AnchorHTMLAttributes } from \"react\";\n\n/**\n * Stands in for `next/link` when the widget is bundled for npm, via the\n * `paths` entry in this package's tsconfig. The app links with the\n * framework's router; the package has no router, and the only links that\n * reach it are the ones a reply writes, which an anchor follows the same.\n *\n * The swap is not only a simplification. `next/link` is CommonJS, so bundling\n * it drags in a `require` shim, and Turbopack throws on a dynamic `require`\n * at runtime: an inlined Link white-screens the host page it was supposed to\n * be a guest on.\n *\n * Next-only props are swallowed here so they do not land on a DOM element\n * that has never heard of them.\n */\ntype NextOnlyProps = {\n prefetch?: boolean | null;\n replace?: boolean;\n scroll?: boolean;\n shallow?: boolean;\n passHref?: boolean;\n legacyBehavior?: boolean;\n locale?: string | false;\n};\n\nconst Link = forwardRef<\n HTMLAnchorElement,\n AnchorHTMLAttributes<HTMLAnchorElement> & NextOnlyProps\n>(function Link(\n {\n prefetch: _prefetch,\n replace: _replace,\n scroll: _scroll,\n shallow: _shallow,\n passHref: _passHref,\n legacyBehavior: _legacyBehavior,\n locale: _locale,\n ...props\n },\n ref,\n) {\n return <a ref={ref} {...props} />;\n});\n\nexport default Link;\n","/**\n * Whether an address is one of ours.\n *\n * One rule, in one place, because two things lean on it and they have to\n * agree: a link inside a reply, and a row saying where a call went. Ours\n * open in the tab you are in, the way every other link in the app does.\n * Anything with a host on it leaves, and takes a new tab with it, so\n * following one never costs you a half-written reply.\n *\n * `//` is excluded on purpose. It looks like a path and is a protocol\n * relative URL, which is as external as it gets.\n */\nexport function staysInApp(href: string): boolean {\n return href.startsWith(\"/\") && !href.startsWith(\"//\");\n}\n","import Link from \"next/link\";\nimport { Streamdown, type Components } from \"streamdown\";\n\nimport { staysInApp } from \"@/lib/links\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Markdown, sized for a chat bubble. The agent and the team write it; this\n * renders it the same way in the widget and the inbox, so a reply reads\n * identically on both ends of the conversation.\n *\n * Streamdown underneath, because a reply can be read while it is still being\n * written: half-finished emphasis and an unclosed code fence render as what\n * they are becoming rather than as stray punctuation. Its own code block\n * chrome stays off; a copy button and line numbers are IDE furniture, not\n * chat.\n *\n * Everything stays at the bubble's own text size: a heading the model was\n * told not to write renders as a bold line rather than a headline, so a\n * disobedient reply is merely emphatic instead of enormous.\n *\n * Customer messages never come through here. What a visitor types is quoted\n * verbatim, asterisks and all; markdown is something the house voice writes.\n */\n\n/**\n * What a link wears, wherever it goes.\n *\n * The palette has no colour to spend on one, so the underline is the whole of\n * the signal and has to be worth reading as one: solid, at the text's own\n * weight, close enough under the words to belong to them. Nothing else in a\n * reply is underlined, which is what makes it mean something.\n */\nconst LINK =\n \"font-medium break-all underline decoration-foreground/60 decoration-1 underline-offset-[3px] transition-colors hover:decoration-foreground\";\n\n/** A stray heading becomes a bold line of body text, whatever its rank. */\nconst Flattened: Components[\"h1\"] = ({ children }) => (\n <p className=\"font-semibold\">{children}</p>\n);\n\n/**\n * Headings that are headings.\n *\n * Sized in `em` rather than in steps of the type scale, so they are a\n * proportion of whatever they are set in: the same markdown reads right in\n * the assistant's column and in a card half its size, and neither has to\n * know what the other chose.\n *\n * Two ranks and then a floor. Anything past the second level of an answer in\n * a chat is a list pretending to be an outline, and rendering six sizes\n * would only make that look deliberate.\n */\nconst RANKS: Components = {\n h1: ({ children }) => (\n <p className=\"mt-2 text-[1.25em] leading-tight font-semibold first:mt-0\">\n {children}\n </p>\n ),\n h2: ({ children }) => (\n <p className=\"mt-2 text-[1.1em] leading-snug font-semibold first:mt-0\">\n {children}\n </p>\n ),\n h3: ({ children }) => (\n <p className=\"mt-1 font-semibold first:mt-0\">{children}</p>\n ),\n h4: ({ children }) => <p className=\"font-semibold\">{children}</p>,\n h5: ({ children }) => <p className=\"font-semibold\">{children}</p>,\n h6: ({ children }) => <p className=\"font-semibold\">{children}</p>,\n};\n\nconst FLAT: Components = {\n h1: Flattened,\n h2: Flattened,\n h3: Flattened,\n h4: Flattened,\n h5: Flattened,\n h6: Flattened,\n};\n\nconst COMPONENTS: Components = {\n p: ({ children }) => <p className=\"break-words\">{children}</p>,\n\n /** A link, and whether it leaves. See `lib/links.ts` for the rule. */\n a: ({ children, href }) => {\n const to = href ?? \"\";\n\n return staysInApp(to) ? (\n <Link href={to} className={LINK}>\n {children}\n </Link>\n ) : (\n <a href={to} target=\"_blank\" rel=\"noopener noreferrer\" className={LINK}>\n {children}\n </a>\n );\n },\n\n ul: ({ children }) => (\n <ul className=\"list-disc space-y-1 pl-5\">{children}</ul>\n ),\n ol: ({ children, start }) => (\n <ol start={start} className=\"list-decimal space-y-1 pl-5\">\n {children}\n </ol>\n ),\n\n blockquote: ({ children }) => (\n <blockquote className=\"border-l-2 border-foreground/20 pl-3 text-foreground/80\">\n {children}\n </blockquote>\n ),\n\n // Inline code only. Streamdown's own bg-muted chip vanishes inside a\n // muted bubble, so the chip leans on the text colour instead. Fenced code\n // is left alone: Streamdown's block, with its language header and\n // highlighting, is the proper thing and needs no help.\n inlineCode: ({ children }) => (\n <code className=\"rounded bg-foreground/10 px-1 py-0.5 font-mono text-[0.85em]\">\n {children}\n </code>\n ),\n\n // A table is an object on the page rather than a stripe across it, so it\n // is boxed and it hugs what is in it. `w-fit` is the whole of that: two\n // columns of single digits stay two columns of single digits instead of\n // being stretched over the width of the reply, which is what makes a\n // three-row table read as a spreadsheet somebody dropped in.\n //\n // Every part of it is written down here, including the ones that were\n // being left to Streamdown. Its defaults are sized for a document with a\n // table in it: a grey header band, sm text, px-4 cells. In a thread that\n // is louder than the answer around it.\n table: ({ children }) => (\n <div className=\"w-fit max-w-full overflow-x-auto rounded-lg border\">\n <table className=\"w-full text-left text-xs\">{children}</table>\n </div>\n ),\n thead: ({ children }) => <thead className=\"bg-muted/50\">{children}</thead>,\n // The line under the head belongs to the head. Between rows it belongs to\n // the row above, and the last one has the box's own edge under it already.\n tr: ({ children }) => (\n <tr className=\"[&:not(:last-child)>td]:border-b\">{children}</tr>\n ),\n th: ({ children }) => (\n <th className=\"border-b px-3 py-2 font-medium whitespace-nowrap\">\n {children}\n </th>\n ),\n // Figures line up under each other, and a cell with a paragraph in it sits\n // against the top of its row rather than floating in the middle of one.\n td: ({ children }) => (\n <td className=\"px-3 py-2 align-top tabular-nums\">{children}</td>\n ),\n\n hr: () => <hr className=\"border-foreground/15\" />,\n\n img: ({ src, alt }) => (\n // eslint-disable-next-line @next/next/no-img-element -- arbitrary remote URL, nothing for the optimizer to do.\n <img src={src} alt={alt ?? \"\"} className=\"max-w-full rounded-lg\" />\n ),\n};\n\nexport function MessageMarkdown({\n body,\n className,\n headings = \"flatten\",\n mode = \"streaming\",\n}: {\n body: string;\n className?: string;\n /**\n * What to do with a heading. Flattened by default, which is what a bubble\n * wants: a customer reply that reaches for an H1 should read as emphatic,\n * not as a press release. `keep` is for the places an answer is a document\n * rather than a message, which is the assistant's own column.\n */\n headings?: \"flatten\" | \"keep\";\n /**\n * Streaming is for a reply that is still being written: Streamdown splits\n * it into blocks so a token does not reparse the whole page. Static is\n * for a finished answer shown all at once. Dumping a complete reply in\n * streaming mode is how a palette answer arrives as chunks.\n */\n mode?: \"streaming\" | \"static\";\n}) {\n return (\n <Streamdown\n // The code block brings its own my-4, sized for prose; in a bubble the\n // column's gap is the spacing, so the margin goes.\n className={cn(\n \"flex min-w-0 flex-col gap-2 break-words\",\n \"[&>[data-streamdown=code-block]]:my-0\",\n className,\n )}\n components={{\n ...COMPONENTS,\n ...(headings === \"keep\" ? RANKS : FLAT),\n }}\n controls={false}\n lineNumbers={false}\n mode={mode}\n >\n {body}\n </Streamdown>\n );\n}\n"],"mappings":"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","names":["Link","jsx"]}