@sybilion/uilib 1.3.15 → 1.3.16
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/dist/esm/components/ui/Chat/Chat.styl.js +1 -1
- package/dist/esm/components/ui/Chat/ChatMessage/AgentMessageContent.helpers.js +6 -3
- package/dist/esm/components/ui/Chat/ChatMessage/AgentMessageContent.js +2 -1
- package/dist/esm/components/ui/Chat/ChatMessage/ChatMessage.js +2 -0
- package/dist/esm/components/ui/Chat/ChatMessage/ChatMessage.styl.js +1 -1
- package/dist/esm/components/ui/InteractiveContent/AutolinkUrl.js +34 -0
- package/dist/esm/components/ui/InteractiveContent/InteractiveContent.styl.js +2 -2
- package/dist/esm/index.js +1 -0
- package/dist/esm/types/src/components/ui/InteractiveContent/AutolinkUrl.d.ts +11 -0
- package/dist/esm/types/src/components/ui/InteractiveContent/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/ui/Chat/Chat.styl +1 -0
- package/src/components/ui/Chat/ChatMessage/AgentMessageContent.helpers.tsx +35 -7
- package/src/components/ui/Chat/ChatMessage/ChatMessage.styl +8 -0
- package/src/components/ui/InteractiveContent/AutolinkUrl.tsx +53 -0
- package/src/components/ui/InteractiveContent/InteractiveContent.styl +60 -9
- package/src/components/ui/InteractiveContent/InteractiveContent.styl.d.ts +4 -0
- package/src/components/ui/InteractiveContent/index.ts +1 -0
- package/src/docs/pages/InteractiveContentPage.tsx +2 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import styleInject from 'style-inject';
|
|
2
2
|
|
|
3
|
-
var css_248z = ".Chat_root__IWt99{background-color:var(--background);display:flex;flex-direction:column;height:100%;min-height:0}.Chat_header__ZjwP-{align-items:center;display:flex;flex-shrink:0;min-height:64px;padding:var(--p-2) var(--p-6) 0}.Chat_isEmpty__b4ViB{padding-bottom:170px}";
|
|
3
|
+
var css_248z = ".Chat_root__IWt99{background-color:var(--background);display:flex;flex-direction:column;height:100%;min-height:0}.Chat_header__ZjwP-{align-items:center;display:flex;flex-shrink:0;min-height:64px;padding:var(--p-2) var(--p-6) 0;padding-right:var(--p-12)}.Chat_isEmpty__b4ViB{padding-bottom:170px}";
|
|
4
4
|
var S = {"root":"Chat_root__IWt99","header":"Chat_header__ZjwP-","isEmpty":"Chat_isEmpty__b4ViB"};
|
|
5
5
|
styleInject(css_248z);
|
|
6
6
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { shouldRenderAutolinkPill, AutolinkUrl } from '../../InteractiveContent/AutolinkUrl.js';
|
|
2
3
|
import logger from '../../../../lib/logger.js';
|
|
3
4
|
import S from './ChatMessage.styl.js';
|
|
5
|
+
import S$1 from '../../InteractiveContent/InteractiveContent.styl.js';
|
|
4
6
|
|
|
5
7
|
const injectHeaders = (content) => {
|
|
6
8
|
// Match #, ##, ###, or #### headers at start of line
|
|
@@ -320,7 +322,7 @@ const injectMarkdownLink = (content) => {
|
|
|
320
322
|
const { target, rel } = linkTargetRelForHref(href, undefined);
|
|
321
323
|
const label = matches[1];
|
|
322
324
|
return {
|
|
323
|
-
elem: (jsx("a", { href: href, target: target, rel: rel, children: runFormattingPipeline(label, linkLabelInjectors) })),
|
|
325
|
+
elem: shouldRenderAutolinkPill(label, href) ? (jsx(AutolinkUrl, { href: href, display: label, target: target, rel: rel })) : (jsx("a", { href: href, target: target, rel: rel, className: S$1.textLink, children: runFormattingPipeline(label, linkLabelInjectors) })),
|
|
324
326
|
index: matches.index,
|
|
325
327
|
length: matches[0].length,
|
|
326
328
|
};
|
|
@@ -366,7 +368,7 @@ const injectAutolinkUrl = (content) => {
|
|
|
366
368
|
}
|
|
367
369
|
const { target, rel } = linkTargetRelForHref(c.href, undefined);
|
|
368
370
|
return {
|
|
369
|
-
elem: (jsx(
|
|
371
|
+
elem: (jsx(AutolinkUrl, { href: c.href, display: c.display, target: target, rel: rel })),
|
|
370
372
|
index: c.index,
|
|
371
373
|
length: c.length,
|
|
372
374
|
};
|
|
@@ -393,8 +395,9 @@ const injectAnchor = (content) => {
|
|
|
393
395
|
return null;
|
|
394
396
|
}
|
|
395
397
|
const { target, rel } = linkTargetRelForHref(href, targetRaw || undefined);
|
|
398
|
+
const innerTrimmed = inner.trim();
|
|
396
399
|
return {
|
|
397
|
-
elem: (jsx("a", { href: href, target: target, rel: rel, children: runFormattingPipeline(inner, linkLabelInjectors) })),
|
|
400
|
+
elem: shouldRenderAutolinkPill(innerTrimmed, href) ? (jsx(AutolinkUrl, { href: href, display: innerTrimmed, target: target, rel: rel })) : (jsx("a", { href: href, target: target, rel: rel, className: S$1.textLink, children: runFormattingPipeline(inner, linkLabelInjectors) })),
|
|
398
401
|
index: matches.index,
|
|
399
402
|
length: matches[0].length,
|
|
400
403
|
};
|
|
@@ -2,10 +2,11 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useState, useMemo } from 'react';
|
|
3
3
|
import { Button } from '../../Button/Button.js';
|
|
4
4
|
import { InteractiveContent } from '../../InteractiveContent/InteractiveContent.js';
|
|
5
|
+
import { Presentation } from 'lucide-react';
|
|
6
|
+
import '../../InteractiveContent/InteractiveContent.styl.js';
|
|
5
7
|
import { parseDatasetAppToken } from '../../../../utils/datasetApplicationLink.js';
|
|
6
8
|
import { Scroll } from '@homecode/ui';
|
|
7
9
|
import { PaperPlaneRightIcon } from '@phosphor-icons/react';
|
|
8
|
-
import { Presentation } from 'lucide-react';
|
|
9
10
|
import { convertMarkdownTableToHTML } from './AgentMessageContent.helpers.js';
|
|
10
11
|
import { ChatDatasetApplicationLink } from './ChatDatasetApplicationLink.js';
|
|
11
12
|
import S from './ChatMessage.styl.js';
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import cn from 'classnames';
|
|
3
3
|
import { InteractiveContent } from '../../InteractiveContent/InteractiveContent.js';
|
|
4
|
+
import 'lucide-react';
|
|
5
|
+
import '../../InteractiveContent/InteractiveContent.styl.js';
|
|
4
6
|
import { TextShimmer } from '../../TextShimmer/TextShimmer.js';
|
|
5
7
|
import { MessageRole, GENERATING_DASHBOARD_SYSTEM_TEXT } from '../Chat.types.js';
|
|
6
8
|
import { userTextFileAttachmentsFromMessage } from '../userTextFileAttachments.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import styleInject from 'style-inject';
|
|
2
2
|
|
|
3
|
-
var css_248z = ".ChatMessage_root__6rnsF{background:var(--bg-secondary);display:flex;flex-direction:column;gap:var(--p-1);padding:var(--p-6)}.ChatMessage_text__Y1XNR{color:var(--text-secondary);font-size:var(--text-sm);max-width:100
|
|
3
|
+
var css_248z = ".ChatMessage_root__6rnsF{background:var(--bg-secondary);display:flex;flex-direction:column;gap:var(--p-1);padding:var(--p-6)}.ChatMessage_text__Y1XNR{color:var(--text-secondary);font-size:var(--text-sm);max-width:100%;min-width:0;overflow-wrap:anywhere;-webkit-user-select:text;-moz-user-select:text;user-select:text;width:-moz-fit-content;width:fit-content;word-break:break-word}.ChatMessage_role-user__u4JPV{align-items:flex-end;max-width:100%;min-width:0}.ChatMessage_role-user__u4JPV .ChatMessage_userColumn__cQM6-{align-items:flex-end;display:flex;flex-direction:column;gap:var(--p-2);max-width:100%;min-width:0}.ChatMessage_role-user__u4JPV .ChatMessage_text__Y1XNR{background-color:var(--sb-slate-100);border-radius:var(--p-4);border-bottom-right-radius:0;box-sizing:border-box;overflow:hidden;padding:var(--p-3) var(--p-4);white-space:pre-wrap}.dark .ChatMessage_role-user__u4JPV .ChatMessage_text__Y1XNR{background-color:var(--sb-gray-800)}.ChatMessage_role-system__g13OP{align-items:center}.ChatMessage_role-system__g13OP .ChatMessage_text__Y1XNR{color:var(--muted-foreground);font-size:var(--text-xs);width:100%}.ChatMessage_role-assistant__wketE .ChatMessage_text__Y1XNR{width:100%}.ChatMessage_role-assistant__wketE h3{line-height:2.4}.ChatMessage_role-assistant__wketE h4{font-size:1.1em;font-weight:600;line-height:2.2}.ChatMessage_role-assistant__wketE .ChatMessage_bullet__6vAhq{display:inline-block;margin-left:4px;margin-right:6px}.ChatMessage_role-assistant__wketE .ChatMessage_bullet__6vAhq:before{color:var(--text-secondary);content:\"•\";display:inline-block}.ChatMessage_role-assistant__wketE .ChatMessage_scrollHorizontal__Rms9n{max-width:100%}.ChatMessage_role-assistant__wketE table{border:1px solid var(--border);border-collapse:collapse;border-radius:var(--p-2);border-spacing:0;margin:var(--p-4) 0;overflow:hidden}.ChatMessage_role-assistant__wketE table td,.ChatMessage_role-assistant__wketE table th{border:1px solid var(--border);min-width:100px;padding:var(--p-1)}.ChatMessage_role-assistant__wketE table th{text-align:left}.ChatMessage_role-assistant__wketE ol,.ChatMessage_role-assistant__wketE ul{padding-left:var(--p-4)}.ChatMessage_role-assistant__wketE ul{list-style-type:disc}.ChatMessage_role-assistant__wketE ol{list-style-type:decimal}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T{align-items:center;border:1px dashed var(--sb-slate-300);border-radius:8px;color:var(--foreground);display:inline-flex;font-size:var(--text-xs);gap:6px;margin:1px;max-width:100%;padding:2px 6px 2px 4px;text-decoration:none;vertical-align:middle}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T:hover{background-color:var(--sb-slate-50);border-color:var(--sb-slate-400);border-style:solid}.dark .ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T{border-color:var(--sb-gray-600)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T:hover{background-color:var(--sb-gray-900)}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLinkLabel__PMU7e{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ChatMessage_role-assistant__wketE .ChatMessage_quickReplyWrap__1UFyD{display:inline-block;margin:var(--p-1) var(--p-1) var(--p-1) 0;vertical-align:middle}.ChatMessage_role-assistant__wketE .ChatMessage_downloadButtons__RygM-{display:flex;gap:var(--p-2);margin-top:var(--p-4)}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa{align-items:center;background-color:var(--background);border-radius:var(--p-3);box-shadow:0 0 0 1px var(--border);cursor:pointer;display:flex;gap:var(--p-4);margin-top:var(--p-3);padding:var(--p-3);padding-right:var(--p-4);transition:all .15s;width:-moz-fit-content;width:fit-content}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa:hover{background-color:var(--sb-gray-50);border-color:var(--border)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa{background-color:var(--sb-gray-900);border-color:var(--border)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa:hover{background-color:var(--sb-gray-800)}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardIcon__jkxDJ{align-items:center;border-radius:var(--p-2);display:flex;flex-shrink:0;height:32px;justify-content:center;width:32px}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardContent__PTPwz{display:flex;flex:1;flex-direction:column;min-width:0}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardTitle__K1wqr{font-size:var(--text-base);font-weight:600;line-height:1.4}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardSubtitle__fVeF2{color:var(--muted-foreground);font-size:var(--text-sm);line-height:1.4}";
|
|
4
4
|
var S = {"root":"ChatMessage_root__6rnsF","text":"ChatMessage_text__Y1XNR","role-user":"ChatMessage_role-user__u4JPV","userColumn":"ChatMessage_userColumn__cQM6-","role-system":"ChatMessage_role-system__g13OP","role-assistant":"ChatMessage_role-assistant__wketE","bullet":"ChatMessage_bullet__6vAhq","scrollHorizontal":"ChatMessage_scrollHorizontal__Rms9n","datasetAppLink":"ChatMessage_datasetAppLink__Pxy-T","datasetAppLinkLabel":"ChatMessage_datasetAppLinkLabel__PMU7e","quickReplyWrap":"ChatMessage_quickReplyWrap__1UFyD","downloadButtons":"ChatMessage_downloadButtons__RygM-","downloadCard":"ChatMessage_downloadCard__NsNRa","downloadCardIcon":"ChatMessage_downloadCardIcon__jkxDJ","downloadCardContent":"ChatMessage_downloadCardContent__PTPwz","downloadCardTitle":"ChatMessage_downloadCardTitle__K1wqr","downloadCardSubtitle":"ChatMessage_downloadCardSubtitle__fVeF2"};
|
|
5
5
|
styleInject(css_248z);
|
|
6
6
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { LinkIcon } from 'lucide-react';
|
|
3
|
+
import S from './InteractiveContent.styl.js';
|
|
4
|
+
|
|
5
|
+
function displayUrlForAutolink(display) {
|
|
6
|
+
if (display.startsWith('https://'))
|
|
7
|
+
return display.slice(8);
|
|
8
|
+
if (display.startsWith('http://'))
|
|
9
|
+
return display.slice(7);
|
|
10
|
+
return display;
|
|
11
|
+
}
|
|
12
|
+
function shouldRenderAutolinkPill(label, href) {
|
|
13
|
+
const normalizedLabel = label.trim();
|
|
14
|
+
const normalizedHref = href.trim();
|
|
15
|
+
if (!normalizedLabel || !normalizedHref)
|
|
16
|
+
return false;
|
|
17
|
+
const labelAsHref = normalizeWwwToHttps(normalizedLabel);
|
|
18
|
+
if (labelAsHref === normalizedHref)
|
|
19
|
+
return true;
|
|
20
|
+
return (/^https?:\/\//i.test(normalizedLabel) ||
|
|
21
|
+
/^www\./i.test(normalizedLabel) ||
|
|
22
|
+
normalizedLabel === displayUrlForAutolink(normalizedHref));
|
|
23
|
+
}
|
|
24
|
+
const normalizeWwwToHttps = (raw) => {
|
|
25
|
+
const t = raw.trim();
|
|
26
|
+
if (/^www\./i.test(t))
|
|
27
|
+
return `https://${t}`;
|
|
28
|
+
return t;
|
|
29
|
+
};
|
|
30
|
+
function AutolinkUrl({ href, display, target, rel }) {
|
|
31
|
+
return (jsxs("a", { href: href, target: target, rel: rel, className: S.autolinkUrl, children: [jsx(LinkIcon, { size: 12, "aria-hidden": true, className: S.autolinkUrlIcon }), jsx("span", { className: S.autolinkUrlLabel, title: displayUrlForAutolink(display), children: displayUrlForAutolink(display) })] }));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { AutolinkUrl, S as autolinkStyles, displayUrlForAutolink, shouldRenderAutolinkPill };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import styleInject from 'style-inject';
|
|
2
2
|
|
|
3
|
-
var css_248z = ".InteractiveContent_root__FHnlY strong{font-weight:600}.InteractiveContent_root__FHnlY em{font-style:italic}.
|
|
4
|
-
var S = {"root":"InteractiveContent_root__FHnlY"};
|
|
3
|
+
var css_248z = ".InteractiveContent_root__FHnlY{box-sizing:border-box;display:inline-block;max-width:100%;min-width:0;overflow-wrap:anywhere;word-break:break-word}.InteractiveContent_root__FHnlY strong{font-weight:600}.InteractiveContent_root__FHnlY em{font-style:italic}.InteractiveContent_textLink__Ubh4i{color:var(--sb-green-600);text-decoration:underline;text-underline-offset:2px}.InteractiveContent_textLink__Ubh4i:hover{color:var(--sb-green-700)}.dark .InteractiveContent_textLink__Ubh4i{color:var(--sb-green-400)}.dark .InteractiveContent_textLink__Ubh4i:hover{color:var(--sb-green-300)}.InteractiveContent_autolinkUrl__W0tQH{align-items:center;border-radius:var(--p-2);box-sizing:border-box;color:var(--link-color);display:inline-flex;font-size:var(--text-xs);gap:6px;line-height:1.4;margin:0 1px;max-width:100%;padding:2px 8px 2px 6px;position:relative;text-decoration:none;vertical-align:middle}.InteractiveContent_autolinkUrl__W0tQH:before{background-color:var(--link-color);border-radius:inherit;content:\"\";display:inline-block;height:100%;left:0;opacity:.1;position:absolute;top:0;width:100%}.InteractiveContent_autolinkUrl__W0tQH:hover:before{opacity:.2}.InteractiveContent_autolinkUrlIcon__QoqlQ{flex-shrink:0}.InteractiveContent_autolinkUrlLabel__CcJOG{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}";
|
|
4
|
+
var S = {"root":"InteractiveContent_root__FHnlY","textLink":"InteractiveContent_textLink__Ubh4i","autolinkUrl":"InteractiveContent_autolinkUrl__W0tQH","autolinkUrlIcon":"InteractiveContent_autolinkUrlIcon__QoqlQ","autolinkUrlLabel":"InteractiveContent_autolinkUrlLabel__CcJOG"};
|
|
5
5
|
styleInject(css_248z);
|
|
6
6
|
|
|
7
7
|
export { S as default };
|
package/dist/esm/index.js
CHANGED
|
@@ -47,6 +47,7 @@ export { Image } from './components/ui/Image/Image.js';
|
|
|
47
47
|
export { ImageWithFallback } from './components/ui/ImageWithFallback/ImageWithFallback.js';
|
|
48
48
|
export { Input } from './components/ui/Input/Input.js';
|
|
49
49
|
export { InteractiveContent } from './components/ui/InteractiveContent/InteractiveContent.js';
|
|
50
|
+
export { AutolinkUrl, displayUrlForAutolink } from './components/ui/InteractiveContent/AutolinkUrl.js';
|
|
50
51
|
export { Label } from './components/ui/Label/Label.js';
|
|
51
52
|
export { LabeledInput } from './components/ui/LabeledInput/LabeledInput.js';
|
|
52
53
|
export { AltKeyProvider } from './components/ui/LabelWithId/AltKeyProvider.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import S from './InteractiveContent.styl';
|
|
2
|
+
type AutolinkUrlProps = {
|
|
3
|
+
href: string;
|
|
4
|
+
display: string;
|
|
5
|
+
target?: string;
|
|
6
|
+
rel?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function displayUrlForAutolink(display: string): string;
|
|
9
|
+
export declare function shouldRenderAutolinkPill(label: string, href: string): boolean;
|
|
10
|
+
export declare function AutolinkUrl({ href, display, target, rel }: AutolinkUrlProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export { S as autolinkStyles };
|
package/package.json
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
AutolinkUrl,
|
|
5
|
+
autolinkStyles,
|
|
6
|
+
shouldRenderAutolinkPill,
|
|
7
|
+
} from '#uilib/components/ui/InteractiveContent/AutolinkUrl';
|
|
3
8
|
import logger from '#uilib/lib/logger';
|
|
4
9
|
|
|
5
10
|
import S from './ChatMessage.styl';
|
|
@@ -397,8 +402,15 @@ const injectMarkdownLink: Injector = (content: string) => {
|
|
|
397
402
|
const label = matches[1];
|
|
398
403
|
|
|
399
404
|
return {
|
|
400
|
-
elem: (
|
|
401
|
-
<
|
|
405
|
+
elem: shouldRenderAutolinkPill(label, href) ? (
|
|
406
|
+
<AutolinkUrl href={href} display={label} target={target} rel={rel} />
|
|
407
|
+
) : (
|
|
408
|
+
<a
|
|
409
|
+
href={href}
|
|
410
|
+
target={target}
|
|
411
|
+
rel={rel}
|
|
412
|
+
className={autolinkStyles.textLink}
|
|
413
|
+
>
|
|
402
414
|
{runFormattingPipeline(label, linkLabelInjectors)}
|
|
403
415
|
</a>
|
|
404
416
|
),
|
|
@@ -459,9 +471,12 @@ const injectAutolinkUrl: Injector = (content: string) => {
|
|
|
459
471
|
|
|
460
472
|
return {
|
|
461
473
|
elem: (
|
|
462
|
-
<
|
|
463
|
-
{c.
|
|
464
|
-
|
|
474
|
+
<AutolinkUrl
|
|
475
|
+
href={c.href}
|
|
476
|
+
display={c.display}
|
|
477
|
+
target={target}
|
|
478
|
+
rel={rel}
|
|
479
|
+
/>
|
|
465
480
|
),
|
|
466
481
|
index: c.index,
|
|
467
482
|
length: c.length,
|
|
@@ -500,10 +515,23 @@ const injectAnchor: Injector = (content: string) => {
|
|
|
500
515
|
}
|
|
501
516
|
|
|
502
517
|
const { target, rel } = linkTargetRelForHref(href, targetRaw || undefined);
|
|
518
|
+
const innerTrimmed = inner.trim();
|
|
503
519
|
|
|
504
520
|
return {
|
|
505
|
-
elem: (
|
|
506
|
-
<
|
|
521
|
+
elem: shouldRenderAutolinkPill(innerTrimmed, href) ? (
|
|
522
|
+
<AutolinkUrl
|
|
523
|
+
href={href}
|
|
524
|
+
display={innerTrimmed}
|
|
525
|
+
target={target}
|
|
526
|
+
rel={rel}
|
|
527
|
+
/>
|
|
528
|
+
) : (
|
|
529
|
+
<a
|
|
530
|
+
href={href}
|
|
531
|
+
target={target}
|
|
532
|
+
rel={rel}
|
|
533
|
+
className={autolinkStyles.textLink}
|
|
534
|
+
>
|
|
507
535
|
{runFormattingPipeline(inner, linkLabelInjectors)}
|
|
508
536
|
</a>
|
|
509
537
|
),
|
|
@@ -8,13 +8,18 @@
|
|
|
8
8
|
|
|
9
9
|
.text
|
|
10
10
|
max-width 100%
|
|
11
|
+
min-width 0
|
|
11
12
|
font-size var(--text-sm)
|
|
12
13
|
color var(--text-secondary)
|
|
13
14
|
width fit-content
|
|
14
15
|
user-select text
|
|
16
|
+
overflow-wrap anywhere
|
|
17
|
+
word-break break-word
|
|
15
18
|
|
|
16
19
|
.role-user
|
|
17
20
|
align-items flex-end
|
|
21
|
+
max-width 100%
|
|
22
|
+
min-width 0
|
|
18
23
|
|
|
19
24
|
.userColumn
|
|
20
25
|
display flex
|
|
@@ -22,6 +27,7 @@
|
|
|
22
27
|
align-items flex-end
|
|
23
28
|
gap var(--p-2)
|
|
24
29
|
max-width 100%
|
|
30
|
+
min-width 0
|
|
25
31
|
|
|
26
32
|
.text
|
|
27
33
|
padding var(--p-3) var(--p-4)
|
|
@@ -31,6 +37,8 @@
|
|
|
31
37
|
border-bottom-right-radius 0
|
|
32
38
|
|
|
33
39
|
white-space pre-wrap
|
|
40
|
+
overflow hidden
|
|
41
|
+
box-sizing border-box
|
|
34
42
|
|
|
35
43
|
:global(.dark) &
|
|
36
44
|
background-color var(--sb-gray-800)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { LinkIcon } from 'lucide-react';
|
|
2
|
+
|
|
3
|
+
import S from './InteractiveContent.styl';
|
|
4
|
+
|
|
5
|
+
type AutolinkUrlProps = {
|
|
6
|
+
href: string;
|
|
7
|
+
display: string;
|
|
8
|
+
target?: string;
|
|
9
|
+
rel?: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function displayUrlForAutolink(display: string): string {
|
|
13
|
+
if (display.startsWith('https://')) return display.slice(8);
|
|
14
|
+
if (display.startsWith('http://')) return display.slice(7);
|
|
15
|
+
return display;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function shouldRenderAutolinkPill(label: string, href: string): boolean {
|
|
19
|
+
const normalizedLabel = label.trim();
|
|
20
|
+
const normalizedHref = href.trim();
|
|
21
|
+
if (!normalizedLabel || !normalizedHref) return false;
|
|
22
|
+
|
|
23
|
+
const labelAsHref = normalizeWwwToHttps(normalizedLabel);
|
|
24
|
+
if (labelAsHref === normalizedHref) return true;
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
/^https?:\/\//i.test(normalizedLabel) ||
|
|
28
|
+
/^www\./i.test(normalizedLabel) ||
|
|
29
|
+
normalizedLabel === displayUrlForAutolink(normalizedHref)
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const normalizeWwwToHttps = (raw: string): string => {
|
|
34
|
+
const t = raw.trim();
|
|
35
|
+
if (/^www\./i.test(t)) return `https://${t}`;
|
|
36
|
+
return t;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export function AutolinkUrl({ href, display, target, rel }: AutolinkUrlProps) {
|
|
40
|
+
return (
|
|
41
|
+
<a href={href} target={target} rel={rel} className={S.autolinkUrl}>
|
|
42
|
+
<LinkIcon size={12} aria-hidden className={S.autolinkUrlIcon} />
|
|
43
|
+
<span
|
|
44
|
+
className={S.autolinkUrlLabel}
|
|
45
|
+
title={displayUrlForAutolink(display)}
|
|
46
|
+
>
|
|
47
|
+
{displayUrlForAutolink(display)}
|
|
48
|
+
</span>
|
|
49
|
+
</a>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { S as autolinkStyles };
|
|
@@ -1,20 +1,71 @@
|
|
|
1
1
|
.root
|
|
2
|
+
display inline-block
|
|
3
|
+
max-width 100%
|
|
4
|
+
min-width 0
|
|
5
|
+
box-sizing border-box
|
|
6
|
+
overflow-wrap anywhere
|
|
7
|
+
word-break break-word
|
|
8
|
+
|
|
2
9
|
strong
|
|
3
10
|
font-weight 600
|
|
4
11
|
|
|
5
12
|
em
|
|
6
13
|
font-style italic
|
|
7
14
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
.textLink
|
|
16
|
+
color var(--sb-green-600)
|
|
17
|
+
text-decoration underline
|
|
18
|
+
text-underline-offset 2px
|
|
19
|
+
|
|
20
|
+
&:hover
|
|
21
|
+
color var(--sb-green-700)
|
|
22
|
+
|
|
23
|
+
:global(.dark) &
|
|
24
|
+
color var(--sb-green-400)
|
|
12
25
|
|
|
13
26
|
&:hover
|
|
14
|
-
color var(--sb-green-
|
|
27
|
+
color var(--sb-green-300)
|
|
28
|
+
|
|
29
|
+
.autolinkUrl
|
|
30
|
+
position relative
|
|
31
|
+
display inline-flex
|
|
32
|
+
align-items center
|
|
33
|
+
gap 6px
|
|
34
|
+
|
|
35
|
+
max-width 100%
|
|
36
|
+
box-sizing border-box
|
|
37
|
+
vertical-align middle
|
|
38
|
+
|
|
39
|
+
padding 2px 8px 2px 6px
|
|
40
|
+
margin 0 1px
|
|
41
|
+
|
|
42
|
+
border-radius var(--p-2)
|
|
43
|
+
|
|
44
|
+
color var(--link-color)
|
|
45
|
+
font-size var(--text-xs)
|
|
46
|
+
line-height 1.4
|
|
47
|
+
text-decoration none
|
|
48
|
+
|
|
49
|
+
&::before
|
|
50
|
+
position absolute
|
|
51
|
+
top 0
|
|
52
|
+
left 0
|
|
53
|
+
content ''
|
|
54
|
+
display inline-block
|
|
55
|
+
width 100%
|
|
56
|
+
height 100%
|
|
57
|
+
background-color var(--link-color)
|
|
58
|
+
border-radius inherit
|
|
59
|
+
opacity .1
|
|
60
|
+
|
|
61
|
+
&:hover::before
|
|
62
|
+
opacity .2
|
|
15
63
|
|
|
16
|
-
|
|
17
|
-
|
|
64
|
+
.autolinkUrlIcon
|
|
65
|
+
flex-shrink 0
|
|
18
66
|
|
|
19
|
-
|
|
20
|
-
|
|
67
|
+
.autolinkUrlLabel
|
|
68
|
+
min-width 0
|
|
69
|
+
overflow hidden
|
|
70
|
+
text-overflow ellipsis
|
|
71
|
+
white-space nowrap
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
// This file is automatically generated.
|
|
2
2
|
// Please do not change this file!
|
|
3
3
|
interface CssExports {
|
|
4
|
+
'autolinkUrl': string;
|
|
5
|
+
'autolinkUrlIcon': string;
|
|
6
|
+
'autolinkUrlLabel': string;
|
|
4
7
|
'root': string;
|
|
8
|
+
'textLink': string;
|
|
5
9
|
}
|
|
6
10
|
export const cssExports: CssExports;
|
|
7
11
|
export default cssExports;
|
|
@@ -4,7 +4,8 @@ import { PageContentSection } from '#uilib/components/ui/Page';
|
|
|
4
4
|
import { AppPageHeader } from '../components/AppPageHeader/AppPageHeader';
|
|
5
5
|
import { DocsHeaderActions } from '../docsHeaderActions';
|
|
6
6
|
|
|
7
|
-
const SAMPLE =
|
|
7
|
+
const SAMPLE =
|
|
8
|
+
'Use **bold** and *italic* in formatted text. See https://www.theguardian.com/business/ng-interactive/2026/may/14/us-stock-market-war-inflation-tariffs-trump for context.';
|
|
8
9
|
|
|
9
10
|
export default function InteractiveContentPage() {
|
|
10
11
|
return (
|