@sybilion/uilib 1.3.15 → 1.3.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/esm/components/ui/Chat/Chat.styl.js +1 -1
  2. package/dist/esm/components/ui/Chat/ChatMessage/AgentMessageContent.helpers.js +6 -3
  3. package/dist/esm/components/ui/Chat/ChatMessage/AgentMessageContent.js +2 -1
  4. package/dist/esm/components/ui/Chat/ChatMessage/ChatMessage.js +2 -0
  5. package/dist/esm/components/ui/Chat/ChatMessage/ChatMessage.styl.js +1 -1
  6. package/dist/esm/components/ui/InteractionOverlay/InteractionOverlay.js +3 -3
  7. package/dist/esm/components/ui/InteractionOverlay/InteractionOverlay.styl.js +2 -2
  8. package/dist/esm/components/ui/InteractiveContent/AutolinkUrl.js +34 -0
  9. package/dist/esm/components/ui/InteractiveContent/InteractiveContent.styl.js +2 -2
  10. package/dist/esm/components/ui/Logo/Logo.js +5 -8
  11. package/dist/esm/components/ui/Logo/logo.svg.js +19 -0
  12. package/dist/esm/index.js +2 -0
  13. package/dist/esm/types/src/components/ui/InteractionOverlay/InteractionOverlay.d.ts +2 -1
  14. package/dist/esm/types/src/components/ui/InteractiveContent/AutolinkUrl.d.ts +11 -0
  15. package/dist/esm/types/src/components/ui/InteractiveContent/index.d.ts +1 -0
  16. package/dist/esm/types/src/components/ui/Logo/Logo.d.ts +4 -2
  17. package/dist/esm/types/src/components/ui/Logo/index.d.ts +1 -1
  18. package/package.json +3 -2
  19. package/src/components/ui/Chat/Chat.styl +1 -0
  20. package/src/components/ui/Chat/ChatMessage/AgentMessageContent.helpers.tsx +35 -7
  21. package/src/components/ui/Chat/ChatMessage/ChatMessage.styl +8 -0
  22. package/src/components/ui/InteractionOverlay/InteractionOverlay.styl +45 -14
  23. package/src/components/ui/InteractionOverlay/InteractionOverlay.styl.d.ts +2 -0
  24. package/src/components/ui/InteractionOverlay/InteractionOverlay.tsx +11 -4
  25. package/src/components/ui/InteractiveContent/AutolinkUrl.tsx +53 -0
  26. package/src/components/ui/InteractiveContent/InteractiveContent.styl +60 -9
  27. package/src/components/ui/InteractiveContent/InteractiveContent.styl.d.ts +4 -0
  28. package/src/components/ui/InteractiveContent/index.ts +1 -0
  29. package/src/components/ui/Logo/Logo.tsx +9 -6
  30. package/src/components/ui/Logo/index.ts +1 -1
  31. package/src/{assets → components/ui/Logo}/logo.svg +1 -1
  32. package/src/docs/DocsShell.tsx +2 -2
  33. package/src/docs/config/webpack.config.js +6 -1
  34. 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("a", { href: c.href, target: target, rel: rel, children: c.display })),
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%;-webkit-user-select:text;-moz-user-select:text;user-select:text;width:-moz-fit-content;width:fit-content}.ChatMessage_role-user__u4JPV{align-items:flex-end}.ChatMessage_role-user__u4JPV .ChatMessage_userColumn__cQM6-{align-items:flex-end;display:flex;flex-direction:column;gap:var(--p-2);max-width:100%}.ChatMessage_role-user__u4JPV .ChatMessage_text__Y1XNR{background-color:var(--sb-slate-100);border-radius:var(--p-4);border-bottom-right-radius:0;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}";
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
 
@@ -1,10 +1,10 @@
1
- import { jsx, Fragment } from 'react/jsx-runtime';
1
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
2
2
  import cn from 'classnames';
3
3
  import { useState, useCallback, useEffect } from 'react';
4
4
  import { useIsTouchDevice } from '../../../hooks/useIsTouchDevice.js';
5
5
  import S from './InteractionOverlay.styl.js';
6
6
 
7
- function InteractionOverlay({ className, children, }) {
7
+ function InteractionOverlay({ className, children, message = 'Touch to interact', }) {
8
8
  const isTouchDevice = useIsTouchDevice();
9
9
  const [isVisible, setIsVisible] = useState(true);
10
10
  const handleClick = useCallback(() => {
@@ -29,7 +29,7 @@ function InteractionOverlay({ className, children, }) {
29
29
  if (!isTouchDevice) {
30
30
  return jsx(Fragment, { children: children });
31
31
  }
32
- return (jsx("div", { className: cn(S.root, !isVisible && S.hidden, className), onClick: handleClick, children: children }));
32
+ return (jsxs("div", { className: cn(S.root, !isVisible && S.hidden, className), children: [children, jsx("button", { type: "button", className: S.overlay, onClick: handleClick, "aria-label": message, children: jsx("span", { className: S.message, children: message }) })] }));
33
33
  }
34
34
 
35
35
  export { InteractionOverlay };
@@ -1,7 +1,7 @@
1
1
  import styleInject from 'style-inject';
2
2
 
3
- var css_248z = ".InteractionOverlay_root__9FV58{inset:0;opacity:.7;pointer-events:auto;position:relative;transition:opacity .2s ease-out}.InteractionOverlay_root__9FV58:after{content:\"\";height:100%;inset:0;position:absolute;touch-action:manipulation;width:100%;z-index:4}.InteractionOverlay_root__9FV58.InteractionOverlay_hidden__NRlgG{opacity:1;pointer-events:none}";
4
- var S = {"root":"InteractionOverlay_root__9FV58","hidden":"InteractionOverlay_hidden__NRlgG"};
3
+ var css_248z = ".InteractionOverlay_root__9FV58{position:relative}.InteractionOverlay_overlay__Nwawr{background:transparent;border:none;box-shadow:inset 0 0 80px 40px var(--overlay-background-color);cursor:pointer;inset:0;margin:0;padding:0;position:absolute;touch-action:manipulation;transition:box-shadow .2s ease-out;z-index:4}.InteractionOverlay_hidden__NRlgG .InteractionOverlay_overlay__Nwawr{box-shadow:inset 0 0 0 0 var(--overlay-background-color);pointer-events:none}.InteractionOverlay_message__oCuPR{backdrop-filter:blur(10px);background-color:color-mix(in srgb,var(--overlay-background-color) 20%,transparent);border:1px solid color-mix(in srgb,var(--foreground) 14%,transparent);border-radius:9999px;box-shadow:0 0 24px 10px var(--overlay-background-color),0 0 0 1px color-mix(in srgb,var(--overlay-background-color) 40%,transparent);color:var(--foreground);font-size:.875rem;font-weight:500;left:50%;line-height:1.25;padding:var(--p-3) var(--p-5);pointer-events:none;position:absolute;top:50%;transform:translate(-50%,-50%);transition:.2s ease-out;transition-property:transform,opacity;white-space:nowrap;z-index:1}.InteractionOverlay_hidden__NRlgG .InteractionOverlay_message__oCuPR{opacity:0;transform:translate(-50%,-50%) scale(.3)}:root{--overlay-background-color:var(--page-color)}";
4
+ var S = {"root":"InteractionOverlay_root__9FV58","overlay":"InteractionOverlay_overlay__Nwawr","hidden":"InteractionOverlay_hidden__NRlgG","message":"InteractionOverlay_message__oCuPR"};
5
5
  styleInject(css_248z);
6
6
 
7
7
  export { S as default };
@@ -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}.InteractiveContent_root__FHnlY a{color:var(--sb-green-600);text-decoration:underline;text-underline-offset:2px}.InteractiveContent_root__FHnlY a:hover{color:var(--sb-green-700)}.dark .InteractiveContent_root__FHnlY a{color:var(--sb-green-400)}.dark .InteractiveContent_root__FHnlY a:hover{color:var(--sb-green-300)}";
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 };
@@ -1,15 +1,12 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import cn from 'classnames';
3
3
  import S from './Logo.styl.js';
4
+ import LogoMarkSvg from './logo.svg.js';
4
5
 
5
- /**
6
- * Public URL for the Sybilion logo in standalone apps. Copy `@sybilion/uilib/logo.svg`
7
- * to `public/logo.svg` (Sybilion app template README documents postinstall copies).
8
- * Same path as the favicon `<link href>`.
9
- */
10
- const SYBILION_STANDALONE_LOGO_PUBLIC_URL = '/logo.svg';
11
6
  function Logo({ showText = true, size = 'md', className, ...props }) {
12
- return (jsxs("div", { className: cn(S.root, S[size], className), ...props, children: [jsx("img", { src: SYBILION_STANDALONE_LOGO_PUBLIC_URL, alt: showText ? '' : 'Sybilion', className: S.icon, ...(showText ? { 'aria-hidden': true } : {}) }), showText && jsx("span", { className: S.text, children: "Sybilion" })] }));
7
+ return (jsxs("div", { className: cn(S.root, S[size], className), ...props, children: [jsx(LogoMarkSvg, { className: S.icon, ...(showText
8
+ ? { 'aria-hidden': true }
9
+ : { 'aria-label': 'Sybilion', role: 'img' }) }), showText && jsx("span", { className: S.text, children: "Sybilion" })] }));
13
10
  }
14
11
 
15
- export { Logo, SYBILION_STANDALONE_LOGO_PUBLIC_URL };
12
+ export { Logo, LogoMarkSvg as LogoMark };
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+
3
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
4
+ var SvgLogo = function SvgLogo(props) {
5
+ return /*#__PURE__*/React.createElement("svg", _extends({
6
+ xmlns: "http://www.w3.org/2000/svg",
7
+ viewBox: "0 0 24 24",
8
+ fill: "none"
9
+ }, props), /*#__PURE__*/React.createElement("path", {
10
+ fill: "#C259FF",
11
+ d: "M13.43 24.023h-2.836v-2.836h2.836zm-2.835-2.844H5.63v-2.74h4.965Zm10.527-2.74h-2.726v2.74h-4.965v-2.74h4.952v-4.965h2.74zm-15.5 0h-2.74v-4.965h2.74ZM2.87 13.462H.034v-2.836H2.87Zm21.096 0H21.13v-2.836h2.836zM5.617 10.635h-2.74V5.669h2.74zm15.505 0h-2.74V5.669h2.74zM10.588 2.927v2.74H5.623v-2.74Zm2.842 0h4.96v2.74h-4.966v-2.74h-2.83V.09h2.836z",
12
+ style: {
13
+ strokeWidth: 0.13252
14
+ }
15
+ }));
16
+ };
17
+ var LogoMarkSvg = SvgLogo;
18
+
19
+ export { LogoMarkSvg 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';
@@ -118,3 +119,4 @@ export { ChartTooltipContent } from './components/ui/Chart/components/ChartToolt
118
119
  export { ChartLegendContent } from './components/ui/Chart/components/ChartLegendContent.js';
119
120
  export { BaseChartWrapper } from './components/ui/Chart/components/BaseChartWrapper.js';
120
121
  export { default as DialogStyles } from './components/ui/Dialog/Dialog.styl.js';
122
+ export { default as LogoMark } from './components/ui/Logo/logo.svg.js';
@@ -1,6 +1,7 @@
1
1
  interface InteractionOverlayProps {
2
2
  className?: string;
3
3
  children?: React.ReactNode;
4
+ message?: string;
4
5
  }
5
- export declare function InteractionOverlay({ className, children, }: InteractionOverlayProps): import("react/jsx-runtime").JSX.Element;
6
+ export declare function InteractionOverlay({ className, children, message, }: InteractionOverlayProps): import("react/jsx-runtime").JSX.Element;
6
7
  export {};
@@ -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 };
@@ -1 +1,2 @@
1
1
  export { InteractiveContent } from './InteractiveContent';
2
+ export { AutolinkUrl, displayUrlForAutolink } from './AutolinkUrl';
@@ -1,7 +1,9 @@
1
1
  import type { LogoProps } from './Logo.types';
2
+ import LogoMarkSvg from './logo.svg';
3
+ export { LogoMarkSvg as LogoMark };
2
4
  /**
3
- * Public URL for the Sybilion logo in standalone apps. Copy `@sybilion/uilib/logo.svg`
4
- * to `public/logo.svg` (Sybilion app template README documents postinstall copies).
5
+ * Public URL for standalone apps. Copy `@sybilion/uilib/logo.svg` (Logo component asset)
6
+ * to `public/logo.svg` (app template README documents postinstall copies).
5
7
  * Same path as the favicon `<link href>`.
6
8
  */
7
9
  export declare const SYBILION_STANDALONE_LOGO_PUBLIC_URL: "/logo.svg";
@@ -1,2 +1,2 @@
1
- export { Logo } from './Logo';
1
+ export { Logo, LogoMark } from './Logo';
2
2
  export type { LogoProps, LogoSize } from './Logo.types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sybilion/uilib",
3
- "version": "1.3.15",
3
+ "version": "1.3.17",
4
4
  "description": "Sybilion Design System — React UI components (Webpack + Stylus)",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -35,7 +35,7 @@
35
35
  "default": "./dist/esm/hooks/index.js"
36
36
  },
37
37
  "./src/*": "./src/*",
38
- "./logo.svg": "./src/assets/logo.svg"
38
+ "./logo.svg": "./src/components/ui/Logo/logo.svg"
39
39
  },
40
40
  "files": [
41
41
  "assets",
@@ -52,6 +52,7 @@
52
52
  "tests:watch": "jest --watch",
53
53
  "ts": "tsc --noEmit",
54
54
  "dev": "NODE_OPTIONS='--loader ts-node/esm' NODE_ENV=development webpack-dev-server --mode=development --config ./src/docs/config/webpack.config.js --progress",
55
+ "prebuild": "cp src/components/ui/Logo/logo.svg assets/logo.svg",
55
56
  "build": "rollup -c rollup.config.ts --configPlugin @rollup/plugin-typescript",
56
57
  "build:watch": "yarn build --watch",
57
58
  "build:compress": "COMPRESS=true yarn build",
@@ -12,6 +12,7 @@
12
12
  align-items center
13
13
  min-height 64px
14
14
  padding var(--p-2) var(--p-6) 0
15
+ padding-right var(--p-12) // to not overlap with ChatSheet close button
15
16
 
16
17
  .isEmpty
17
18
  padding-bottom 170px // goes under prompt
@@ -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
- <a href={href} target={target} rel={rel}>
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
- <a href={c.href} target={target} rel={rel}>
463
- {c.display}
464
- </a>
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
- <a href={href} target={target} rel={rel}>
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)
@@ -1,19 +1,50 @@
1
1
  .root
2
2
  position relative
3
- inset 0
4
- opacity 0.7
5
- transition opacity 200ms ease-out
6
- pointer-events auto
7
3
 
8
- &::after
9
- content ''
10
- position absolute
11
- inset 0
12
- width 100%
13
- height 100%
14
- z-index 4
15
- touch-action manipulation
4
+ .overlay
5
+ position absolute
6
+ inset 0
7
+ z-index 4
8
+ border none
9
+ padding 0
10
+ margin 0
11
+ cursor pointer
12
+ touch-action manipulation
13
+ background transparent
14
+ box-shadow inset 0 0 80px 40px var(--overlay-background-color)
15
+ transition box-shadow 200ms ease-out
16
16
 
17
- &.hidden
18
- opacity 1
17
+ .hidden &
18
+ box-shadow inset 0 0 0 0 var(--overlay-background-color)
19
19
  pointer-events none
20
+
21
+ .message
22
+ position absolute
23
+ top 50%
24
+ left 50%
25
+ transform translate(-50%, -50%)
26
+ pointer-events none
27
+ z-index 1
28
+ font-size 0.875rem
29
+ font-weight 500
30
+ line-height 1.25
31
+ color var(--foreground)
32
+ white-space nowrap
33
+ padding var(--p-3) var(--p-5)
34
+ border-radius 9999px
35
+ border 1px solid unquote('color-mix(in srgb, var(--foreground) 14%, transparent)')
36
+ background-color unquote('color-mix(in srgb, var(--overlay-background-color) 20%, transparent)')
37
+ backdrop-filter blur(10px)
38
+ box-shadow \
39
+ 0 0 24px 10px var(--overlay-background-color), \
40
+ 0 0 0 1px unquote('color-mix(in srgb, var(--overlay-background-color) 40%, transparent)')
41
+ transition 200ms ease-out
42
+ transition-property transform, opacity
43
+
44
+ .hidden &
45
+ transform translate(-50%, -50%) scale(.3)
46
+ opacity 0
47
+
48
+
49
+ :global(:root)
50
+ --overlay-background-color var(--page-color)
@@ -2,6 +2,8 @@
2
2
  // Please do not change this file!
3
3
  interface CssExports {
4
4
  'hidden': string;
5
+ 'message': string;
6
+ 'overlay': string;
5
7
  'root': string;
6
8
  }
7
9
  export const cssExports: CssExports;
@@ -8,11 +8,13 @@ import S from './InteractionOverlay.styl';
8
8
  interface InteractionOverlayProps {
9
9
  className?: string;
10
10
  children?: React.ReactNode;
11
+ message?: string;
11
12
  }
12
13
 
13
14
  export function InteractionOverlay({
14
15
  className,
15
16
  children,
17
+ message = 'Touch to interact',
16
18
  }: InteractionOverlayProps) {
17
19
  const isTouchDevice = useIsTouchDevice();
18
20
  const [isVisible, setIsVisible] = useState(true);
@@ -45,11 +47,16 @@ export function InteractionOverlay({
45
47
  }
46
48
 
47
49
  return (
48
- <div
49
- className={cn(S.root, !isVisible && S.hidden, className)}
50
- onClick={handleClick}
51
- >
50
+ <div className={cn(S.root, !isVisible && S.hidden, className)}>
52
51
  {children}
52
+ <button
53
+ type="button"
54
+ className={S.overlay}
55
+ onClick={handleClick}
56
+ aria-label={message}
57
+ >
58
+ <span className={S.message}>{message}</span>
59
+ </button>
53
60
  </div>
54
61
  );
55
62
  }
@@ -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
- a
9
- color var(--sb-green-600)
10
- text-decoration underline
11
- text-underline-offset 2px
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-700)
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
- :global(.dark) &
17
- color var(--sb-green-400)
64
+ .autolinkUrlIcon
65
+ flex-shrink 0
18
66
 
19
- &:hover
20
- color var(--sb-green-300)
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;
@@ -1 +1,2 @@
1
1
  export { InteractiveContent } from './InteractiveContent';
2
+ export { AutolinkUrl, displayUrlForAutolink } from './AutolinkUrl';
@@ -2,10 +2,13 @@ import cn from 'classnames';
2
2
 
3
3
  import S from './Logo.styl';
4
4
  import type { LogoProps } from './Logo.types';
5
+ import LogoMarkSvg from './logo.svg';
6
+
7
+ export { LogoMarkSvg as LogoMark };
5
8
 
6
9
  /**
7
- * Public URL for the Sybilion logo in standalone apps. Copy `@sybilion/uilib/logo.svg`
8
- * to `public/logo.svg` (Sybilion app template README documents postinstall copies).
10
+ * Public URL for standalone apps. Copy `@sybilion/uilib/logo.svg` (Logo component asset)
11
+ * to `public/logo.svg` (app template README documents postinstall copies).
9
12
  * Same path as the favicon `<link href>`.
10
13
  */
11
14
  export const SYBILION_STANDALONE_LOGO_PUBLIC_URL = '/logo.svg' as const;
@@ -18,11 +21,11 @@ export function Logo({
18
21
  }: LogoProps) {
19
22
  return (
20
23
  <div className={cn(S.root, S[size], className)} {...props}>
21
- <img
22
- src={SYBILION_STANDALONE_LOGO_PUBLIC_URL}
23
- alt={showText ? '' : 'Sybilion'}
24
+ <LogoMarkSvg
24
25
  className={S.icon}
25
- {...(showText ? { 'aria-hidden': true } : {})}
26
+ {...(showText
27
+ ? { 'aria-hidden': true }
28
+ : { 'aria-label': 'Sybilion', role: 'img' })}
26
29
  />
27
30
  {showText && <span className={S.text}>Sybilion</span>}
28
31
  </div>
@@ -1,5 +1,5 @@
1
1
  // Export main component
2
- export { Logo } from './Logo';
2
+ export { Logo, LogoMark } from './Logo';
3
3
 
4
4
  // Export types that external components might need
5
5
  export type { LogoProps, LogoSize } from './Logo.types';
@@ -1,3 +1,3 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
2
- <path fill="#59f0ff" d="M13.43 24.023h-2.836v-2.836h2.836zm-2.835-2.844H5.63v-2.74h4.965Zm10.527-2.74h-2.726v2.74h-4.965v-2.74h4.952v-4.965h2.74zm-15.5 0h-2.74v-4.965h2.74ZM2.87 13.462H.034v-2.836H2.87Zm21.096 0H21.13v-2.836h2.836zM5.617 10.635h-2.74V5.669h2.74zm15.505 0h-2.74V5.669h2.74zM10.588 2.927v2.74H5.623v-2.74Zm2.842 0h4.96v2.74h-4.966v-2.74h-2.83V.09h2.836z" style="stroke-width:.13252" />
2
+ <path fill="#C259FF" d="M13.43 24.023h-2.836v-2.836h2.836zm-2.835-2.844H5.63v-2.74h4.965Zm10.527-2.74h-2.726v2.74h-4.965v-2.74h4.952v-4.965h2.74zm-15.5 0h-2.74v-4.965h2.74ZM2.87 13.462H.034v-2.836H2.87Zm21.096 0H21.13v-2.836h2.836zM5.617 10.635h-2.74V5.669h2.74zm15.505 0h-2.74V5.669h2.74zM10.588 2.927v2.74H5.623v-2.74Zm2.842 0h4.96v2.74h-4.966v-2.74h-2.83V.09h2.836z" style="stroke-width:.13252" />
3
3
  </svg>
@@ -1,6 +1,7 @@
1
1
  import { Outlet, useLocation, useNavigate } from 'react-router-dom';
2
2
 
3
3
  import { AppHeaderHost } from '#uilib/components/ui/AppHeader';
4
+ import { LogoMark } from '#uilib/components/ui/Logo';
4
5
  import { AppShell, AppShellMainContent } from '#uilib/components/ui/Page';
5
6
  import { PageFooter } from '#uilib/components/ui/Page/PageFooter/PageFooter';
6
7
  import { PageScroll } from '#uilib/components/ui/Page/PageScroll/PageScroll';
@@ -8,7 +9,6 @@ import { SybilionAppHeader } from '#uilib/components/widgets/SybilionAppHeader';
8
9
  import { ThemeToggle } from '#uilib/docs/App/ThemeToggle';
9
10
  import { DocsSidebar } from '#uilib/docs/components/DocsSidebar/DocsSidebar';
10
11
 
11
- import LogoSvg from '../../assets/logo.svg';
12
12
  import S from './DocsShell.styl';
13
13
 
14
14
  export function DocsShell() {
@@ -24,7 +24,7 @@ export function DocsShell() {
24
24
  header={<AppHeaderHost />}
25
25
  footer={
26
26
  <PageFooter
27
- logo={<LogoSvg />}
27
+ logo={<LogoMark />}
28
28
  versionLink="/releases"
29
29
  versionLabel="1.0.0-docs"
30
30
  />
@@ -20,7 +20,7 @@ const FaviconWebpackPlugin = require('favicons-webpack-plugin');
20
20
  const pkg = require('../../../package.json');
21
21
 
22
22
  const themeStyl = pathResolve(paths.src, 'theme.styl');
23
- const logoSvgPath = pathResolve(paths.assets, 'logo.svg');
23
+ const logoSvgPath = pathResolve(paths.src, 'components/ui/Logo/logo.svg');
24
24
 
25
25
  /** GitHub Pages project sites live at /<repo>/; set PUBLIC_PATH=/repo-name/ for production deploy. */
26
26
  function normalizePublicPath(raw) {
@@ -211,6 +211,11 @@ export default (env, argv) => {
211
211
  to: paths.build,
212
212
  noErrorOnMissing: true,
213
213
  },
214
+ {
215
+ from: logoSvgPath,
216
+ to: `${paths.assets}/logo.svg`,
217
+ noErrorOnMissing: true,
218
+ },
214
219
  ],
215
220
  }),
216
221
 
@@ -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 = 'Use **bold** and *italic* in formatted text.';
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 (