@flamingo-stack/openframe-frontend-core 0.0.296 → 0.0.297
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/README.md +9 -0
- package/dist/{chunk-7RIYT7ZH.js → chunk-2QG57XOJ.js} +1067 -205
- package/dist/chunk-2QG57XOJ.js.map +1 -0
- package/dist/{chunk-WHMATDVP.js → chunk-3JIQVE7T.js} +9 -15
- package/dist/{chunk-WHMATDVP.js.map → chunk-3JIQVE7T.js.map} +1 -1
- package/dist/{chunk-GLLDTKZK.cjs → chunk-4PSQS3SW.cjs} +7 -9
- package/dist/chunk-4PSQS3SW.cjs.map +1 -0
- package/dist/{chunk-OY7OF7E7.js → chunk-4TLE6VLU.js} +30 -24
- package/dist/chunk-4TLE6VLU.js.map +1 -0
- package/dist/{chunk-W6M2FLLT.cjs → chunk-53FUMSZ5.cjs} +40 -46
- package/dist/chunk-53FUMSZ5.cjs.map +1 -0
- package/dist/{chunk-D3LEFMOA.cjs → chunk-54KNMC2R.cjs} +3 -3
- package/dist/{chunk-D3LEFMOA.cjs.map → chunk-54KNMC2R.cjs.map} +1 -1
- package/dist/{chunk-EYEW6PTA.cjs → chunk-6C526VNN.cjs} +358 -118
- package/dist/chunk-6C526VNN.cjs.map +1 -0
- package/dist/{chunk-XREEV72C.cjs → chunk-7OVGB2DQ.cjs} +19 -25
- package/dist/chunk-7OVGB2DQ.cjs.map +1 -0
- package/dist/{chunk-6GCI7JOE.js → chunk-AD6C23QY.js} +8 -7
- package/dist/{chunk-6GCI7JOE.js.map → chunk-AD6C23QY.js.map} +1 -1
- package/dist/chunk-F5OB2YAL.cjs +144 -0
- package/dist/chunk-F5OB2YAL.cjs.map +1 -0
- package/dist/chunk-FBWXMMRB.cjs +2 -0
- package/dist/chunk-FBWXMMRB.cjs.map +1 -0
- package/dist/{chunk-YIGPRLQY.cjs → chunk-FCDQNTDG.cjs} +21 -20
- package/dist/chunk-FCDQNTDG.cjs.map +1 -0
- package/dist/{chunk-IE6OU3WQ.cjs → chunk-FQOTC3UU.cjs} +318 -16
- package/dist/chunk-FQOTC3UU.cjs.map +1 -0
- package/dist/{chunk-QHIXS3W2.cjs → chunk-GUTS7HGA.cjs} +11590 -2105
- package/dist/chunk-GUTS7HGA.cjs.map +1 -0
- package/dist/chunk-GZ4C3XW6.js +2 -0
- package/dist/chunk-GZ4C3XW6.js.map +1 -0
- package/dist/{chunk-5P3B2LZW.js → chunk-IL47XWV5.js} +8 -14
- package/dist/{chunk-5P3B2LZW.js.map → chunk-IL47XWV5.js.map} +1 -1
- package/dist/{chunk-LCNMR277.js → chunk-IZ7JSBFP.js} +1 -1
- package/dist/chunk-IZ7JSBFP.js.map +1 -0
- package/dist/{chunk-EL6QLAWX.js → chunk-JALO4TAZ.js} +357 -55
- package/dist/chunk-JALO4TAZ.js.map +1 -0
- package/dist/{chunk-AQOWFSMB.cjs → chunk-L6PSSIUQ.cjs} +1 -1
- package/dist/chunk-L6PSSIUQ.cjs.map +1 -0
- package/dist/{chunk-MBFWU2EM.js → chunk-L7ULJKG7.js} +6 -10
- package/dist/{chunk-MBFWU2EM.js.map → chunk-L7ULJKG7.js.map} +1 -1
- package/dist/{chunk-K2PFPBMF.js → chunk-PC746XCO.js} +15050 -5565
- package/dist/chunk-PC746XCO.js.map +1 -0
- package/dist/{chunk-3ZXUQQL4.js → chunk-PI4WSYQV.js} +2 -2
- package/dist/{chunk-E4XABBSU.js → chunk-PWQUAVA3.js} +338 -98
- package/dist/chunk-PWQUAVA3.js.map +1 -0
- package/dist/chunk-SA2WPJVO.js +144 -0
- package/dist/chunk-SA2WPJVO.js.map +1 -0
- package/dist/{chunk-X6BV7MB7.cjs → chunk-UNVE2SDJ.cjs} +37 -31
- package/dist/chunk-UNVE2SDJ.cjs.map +1 -0
- package/dist/{chunk-5E2HOSSH.cjs → chunk-WMSTJAZT.cjs} +913 -51
- package/dist/chunk-WMSTJAZT.cjs.map +1 -0
- package/dist/{chunk-ZP4AVIZP.js → chunk-X4DOXQRT.js} +4 -6
- package/dist/{chunk-ZP4AVIZP.js.map → chunk-X4DOXQRT.js.map} +1 -1
- package/dist/{chunk-X647HY3F.cjs → chunk-YBYI62OE.cjs} +33 -37
- package/dist/chunk-YBYI62OE.cjs.map +1 -0
- package/dist/components/case-studies/index.cjs +126 -0
- package/dist/components/case-studies/index.cjs.map +1 -0
- package/dist/components/case-studies/index.d.ts +2 -0
- package/dist/components/case-studies/index.d.ts.map +1 -0
- package/dist/components/case-studies/index.js +126 -0
- package/dist/components/case-studies/index.js.map +1 -0
- package/dist/components/case-studies/share-experience-section.d.ts +48 -0
- package/dist/components/case-studies/share-experience-section.d.ts.map +1 -0
- package/dist/components/chat/index.cjs +8 -18
- package/dist/components/chat/index.cjs.map +1 -1
- package/dist/components/chat/index.js +75 -85
- package/dist/components/contact/index.cjs +8 -15
- package/dist/components/contact/index.cjs.map +1 -1
- package/dist/components/contact/index.js +7 -14
- package/dist/components/docs/doc-viewer.d.ts +39 -2
- package/dist/components/docs/doc-viewer.d.ts.map +1 -1
- package/dist/components/docs/docs-hub-page.d.ts +46 -0
- package/dist/components/docs/docs-hub-page.d.ts.map +1 -0
- package/dist/components/docs/index.cjs +17 -9
- package/dist/components/docs/index.cjs.map +1 -1
- package/dist/components/docs/index.d.ts +4 -0
- package/dist/components/docs/index.d.ts.map +1 -1
- package/dist/components/docs/index.js +16 -8
- package/dist/components/docs/skeletons.d.ts +32 -0
- package/dist/components/docs/skeletons.d.ts.map +1 -0
- package/dist/components/docs/use-docs-resolve-link.d.ts +20 -0
- package/dist/components/docs/use-docs-resolve-link.d.ts.map +1 -0
- package/dist/components/docs/use-document-tree.d.ts.map +1 -1
- package/dist/components/embeds/embed-container.d.ts +37 -0
- package/dist/components/embeds/embed-container.d.ts.map +1 -0
- package/dist/components/embeds/embed-iframe.d.ts.map +1 -1
- package/dist/components/embeds/file-download-card.d.ts +18 -0
- package/dist/components/embeds/file-download-card.d.ts.map +1 -0
- package/dist/components/embeds/index.cjs +38 -15
- package/dist/components/embeds/index.cjs.map +1 -1
- package/dist/components/embeds/index.d.ts +8 -0
- package/dist/components/embeds/index.d.ts.map +1 -1
- package/dist/components/embeds/index.js +40 -17
- package/dist/components/embeds/linkedin-embed-client.d.ts +8 -0
- package/dist/components/embeds/linkedin-embed-client.d.ts.map +1 -0
- package/dist/components/embeds/markdown-image.d.ts +5 -0
- package/dist/components/embeds/markdown-image.d.ts.map +1 -0
- package/dist/components/embeds/reddit-embed-client.d.ts +7 -0
- package/dist/components/embeds/reddit-embed-client.d.ts.map +1 -0
- package/dist/components/embeds/rich-markdown-runtime.d.ts +46 -0
- package/dist/components/embeds/rich-markdown-runtime.d.ts.map +1 -0
- package/dist/components/embeds/twitter-embed-client.d.ts +8 -0
- package/dist/components/embeds/twitter-embed-client.d.ts.map +1 -0
- package/dist/components/faq/index.cjs +9 -16
- package/dist/components/faq/index.cjs.map +1 -1
- package/dist/components/faq/index.js +8 -15
- package/dist/components/features/index.cjs +8 -16
- package/dist/components/features/index.cjs.map +1 -1
- package/dist/components/features/index.js +24 -32
- package/dist/components/index.cjs +257 -452
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +781 -976
- package/dist/components/index.js.map +1 -1
- package/dist/components/layout/page-header.d.ts +78 -0
- package/dist/components/layout/page-header.d.ts.map +1 -0
- package/dist/components/layout/page-layout.d.ts +10 -1
- package/dist/components/layout/page-layout.d.ts.map +1 -1
- package/dist/components/layout/page-with-header.d.ts +67 -0
- package/dist/components/layout/page-with-header.d.ts.map +1 -0
- package/dist/components/layout/title-block.d.ts +17 -1
- package/dist/components/layout/title-block.d.ts.map +1 -1
- package/dist/components/navigation/index.cjs +7 -15
- package/dist/components/navigation/index.cjs.map +1 -1
- package/dist/components/navigation/index.js +9 -17
- package/dist/components/onboarding-guides/index.cjs +35 -36
- package/dist/components/onboarding-guides/index.cjs.map +1 -1
- package/dist/components/onboarding-guides/index.js +13 -14
- package/dist/components/onboarding-guides/index.js.map +1 -1
- package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts +1 -1
- package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts.map +1 -1
- package/dist/components/related-content/index.cjs +9 -16
- package/dist/components/related-content/index.cjs.map +1 -1
- package/dist/components/related-content/index.js +8 -15
- package/dist/components/shared/dev-section/dev-section-page.d.ts +9 -0
- package/dist/components/shared/dev-section/dev-section-page.d.ts.map +1 -1
- package/dist/components/shared/dev-section/dev-section-view.d.ts.map +1 -1
- package/dist/components/shared/dev-section/index.d.ts +1 -1
- package/dist/components/shared/dev-section/index.d.ts.map +1 -1
- package/dist/components/shared/doc-search/use-doc-search.d.ts.map +1 -1
- package/dist/components/shared/legal-document/legal-document-page.d.ts.map +1 -1
- package/dist/components/shared/product-release/release-detail-page.d.ts.map +1 -1
- package/dist/components/tickets/index.cjs +100 -112
- package/dist/components/tickets/index.cjs.map +1 -1
- package/dist/components/tickets/index.js +20 -32
- package/dist/components/tickets/index.js.map +1 -1
- package/dist/components/ui/file-manager/index.cjs +50 -52
- package/dist/components/ui/file-manager/index.cjs.map +1 -1
- package/dist/components/ui/file-manager/index.js +4 -6
- package/dist/components/ui/file-manager/index.js.map +1 -1
- package/dist/components/ui/index.cjs +13 -19
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.d.ts +2 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +133 -139
- package/dist/components/ui/release-changelog-section.d.ts +6 -2
- package/dist/components/ui/release-changelog-section.d.ts.map +1 -1
- package/dist/components/ui/rich-markdown-renderer.d.ts +34 -0
- package/dist/components/ui/rich-markdown-renderer.d.ts.map +1 -0
- package/dist/components/ui/simple-markdown-renderer.d.ts +2 -8
- package/dist/components/ui/simple-markdown-renderer.d.ts.map +1 -1
- package/dist/contexts/chat-runtime-context.d.ts +14 -0
- package/dist/contexts/chat-runtime-context.d.ts.map +1 -1
- package/dist/contexts/index.cjs +3 -3
- package/dist/contexts/index.js +5 -5
- package/dist/embed-shims/index.cjs +3 -3
- package/dist/embed-shims/index.cjs.map +1 -1
- package/dist/embed-shims/index.js +4 -4
- package/dist/hooks/index.cjs +4 -9
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.js +6 -11
- package/dist/index.cjs +14 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +362 -368
- package/dist/types/doc-source.d.ts +31 -1
- package/dist/types/doc-source.d.ts.map +1 -1
- package/dist/utils/index.cjs +4 -0
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/page-header-constants.d.ts +15 -0
- package/dist/utils/page-header-constants.d.ts.map +1 -0
- package/dist/utils/social-embed-cache.d.ts +29 -0
- package/dist/utils/social-embed-cache.d.ts.map +1 -0
- package/package.json +7 -1
- package/src/components/case-studies/index.ts +4 -0
- package/src/components/case-studies/share-experience-section.tsx +185 -0
- package/src/components/chat/embeddable-chat.tsx +1 -1
- package/src/components/docs/doc-viewer.tsx +111 -19
- package/src/components/docs/docs-hub-page.tsx +149 -0
- package/src/components/docs/index.ts +17 -0
- package/src/components/docs/skeletons.tsx +138 -0
- package/src/components/docs/use-docs-resolve-link.ts +52 -0
- package/src/components/docs/use-document-tree.ts +21 -0
- package/src/components/embeds/embed-container.tsx +80 -0
- package/src/components/embeds/embed-iframe.tsx +7 -9
- package/src/components/embeds/file-download-card.tsx +54 -0
- package/src/components/embeds/index.ts +30 -0
- package/src/components/embeds/linkedin-embed-client.tsx +100 -0
- package/src/components/embeds/markdown-image.tsx +88 -0
- package/src/components/embeds/og-link-preview.tsx +13 -13
- package/src/components/embeds/reddit-embed-client.tsx +550 -0
- package/src/components/embeds/rich-markdown-runtime.tsx +79 -0
- package/src/components/embeds/twitter-embed-client.tsx +308 -0
- package/src/components/layout/page-header.tsx +182 -0
- package/src/components/layout/page-layout.tsx +14 -1
- package/src/components/layout/page-with-header.tsx +110 -0
- package/src/components/layout/title-block.tsx +40 -62
- package/src/components/onboarding-guides/onboarding-guide-detail-view.tsx +3 -3
- package/src/components/shared/dev-section/dev-section-page.tsx +9 -1
- package/src/components/shared/dev-section/dev-section-view.tsx +14 -9
- package/src/components/shared/dev-section/index.ts +1 -1
- package/src/components/shared/doc-search/use-doc-search.ts +7 -3
- package/src/components/shared/legal-document/legal-document-page.tsx +2 -2
- package/src/components/shared/product-release/release-detail-page.tsx +6 -4
- package/src/components/ui/index.ts +2 -0
- package/src/components/ui/release-changelog-section.tsx +7 -2
- package/src/components/ui/rich-markdown-renderer.tsx +1203 -0
- package/src/components/ui/simple-markdown-renderer.tsx +7 -11
- package/src/contexts/chat-runtime-context.tsx +14 -0
- package/src/types/doc-source.ts +33 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/page-header-constants.ts +15 -0
- package/src/utils/social-embed-cache.ts +391 -0
- package/dist/chunk-26PKDALD.js +0 -2379
- package/dist/chunk-26PKDALD.js.map +0 -1
- package/dist/chunk-3MCHAFHB.js +0 -89
- package/dist/chunk-3MCHAFHB.js.map +0 -1
- package/dist/chunk-5E2HOSSH.cjs.map +0 -1
- package/dist/chunk-66AANIOC.cjs +0 -619
- package/dist/chunk-66AANIOC.cjs.map +0 -1
- package/dist/chunk-6JINAOI7.cjs +0 -311
- package/dist/chunk-6JINAOI7.cjs.map +0 -1
- package/dist/chunk-7RIYT7ZH.js.map +0 -1
- package/dist/chunk-AQOWFSMB.cjs.map +0 -1
- package/dist/chunk-BOCFIKYS.cjs +0 -3009
- package/dist/chunk-BOCFIKYS.cjs.map +0 -1
- package/dist/chunk-D652TJBQ.js +0 -3009
- package/dist/chunk-D652TJBQ.js.map +0 -1
- package/dist/chunk-E4XABBSU.js.map +0 -1
- package/dist/chunk-EL6QLAWX.js.map +0 -1
- package/dist/chunk-EYEW6PTA.cjs.map +0 -1
- package/dist/chunk-FQJK446R.js +0 -1606
- package/dist/chunk-FQJK446R.js.map +0 -1
- package/dist/chunk-GLLDTKZK.cjs.map +0 -1
- package/dist/chunk-IE6OU3WQ.cjs.map +0 -1
- package/dist/chunk-J54Z3OCR.cjs +0 -1606
- package/dist/chunk-J54Z3OCR.cjs.map +0 -1
- package/dist/chunk-K2PFPBMF.js.map +0 -1
- package/dist/chunk-KXCRGTRN.cjs +0 -2379
- package/dist/chunk-KXCRGTRN.cjs.map +0 -1
- package/dist/chunk-LCNMR277.js.map +0 -1
- package/dist/chunk-LFGGF7OT.cjs +0 -449
- package/dist/chunk-LFGGF7OT.cjs.map +0 -1
- package/dist/chunk-M2OCXTNT.js +0 -311
- package/dist/chunk-M2OCXTNT.js.map +0 -1
- package/dist/chunk-ME4EVDFP.js +0 -619
- package/dist/chunk-ME4EVDFP.js.map +0 -1
- package/dist/chunk-OQ6X7ZOC.js +0 -449
- package/dist/chunk-OQ6X7ZOC.js.map +0 -1
- package/dist/chunk-OY7OF7E7.js.map +0 -1
- package/dist/chunk-POKKCWKF.js +0 -354
- package/dist/chunk-POKKCWKF.js.map +0 -1
- package/dist/chunk-QHIXS3W2.cjs.map +0 -1
- package/dist/chunk-TFSYSWPS.cjs +0 -89
- package/dist/chunk-TFSYSWPS.cjs.map +0 -1
- package/dist/chunk-W6M2FLLT.cjs.map +0 -1
- package/dist/chunk-X647HY3F.cjs.map +0 -1
- package/dist/chunk-X6BV7MB7.cjs.map +0 -1
- package/dist/chunk-XREEV72C.cjs.map +0 -1
- package/dist/chunk-YETA25JW.cjs +0 -354
- package/dist/chunk-YETA25JW.cjs.map +0 -1
- package/dist/chunk-YIGPRLQY.cjs.map +0 -1
- /package/dist/{chunk-3ZXUQQL4.js.map → chunk-PI4WSYQV.js.map} +0 -0
package/dist/chunk-FQJK446R.js
DELETED
|
@@ -1,1606 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import {
|
|
3
|
-
useAutoLimitTags,
|
|
4
|
-
useDebounce
|
|
5
|
-
} from "./chunk-POKKCWKF.js";
|
|
6
|
-
import {
|
|
7
|
-
ClickUpIcon,
|
|
8
|
-
FacebookIcon,
|
|
9
|
-
GitHubIcon,
|
|
10
|
-
HubspotIcon,
|
|
11
|
-
InstagramIcon,
|
|
12
|
-
LinkedInIcon,
|
|
13
|
-
OpenFrameLogo,
|
|
14
|
-
SlackIcon,
|
|
15
|
-
XLogo,
|
|
16
|
-
YouTubeIcon
|
|
17
|
-
} from "./chunk-V4IIBNTA.js";
|
|
18
|
-
import {
|
|
19
|
-
cn,
|
|
20
|
-
getBaseUrl,
|
|
21
|
-
init_cn
|
|
22
|
-
} from "./chunk-XTCBRQN2.js";
|
|
23
|
-
import {
|
|
24
|
-
XmarkCircleIcon
|
|
25
|
-
} from "./chunk-J7AV6H63.js";
|
|
26
|
-
import {
|
|
27
|
-
SearchIcon
|
|
28
|
-
} from "./chunk-6U3IUD57.js";
|
|
29
|
-
|
|
30
|
-
// src/components/ui/hidden-tags-popup.tsx
|
|
31
|
-
import { forwardRef } from "react";
|
|
32
|
-
init_cn();
|
|
33
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
34
|
-
var HiddenTagsPopup = forwardRef(function HiddenTagsPopup2({ items, onRemove, disabled, className, style }, ref) {
|
|
35
|
-
return /* @__PURE__ */ jsx(
|
|
36
|
-
"div",
|
|
37
|
-
{
|
|
38
|
-
ref,
|
|
39
|
-
style,
|
|
40
|
-
className: cn(
|
|
41
|
-
// Base positioning is neutral (left-anchored); consumers override via
|
|
42
|
-
// `style.left` (search-input, tag-search-input) or `className` (autocomplete).
|
|
43
|
-
"absolute top-full left-0 mt-1 z-50 min-w-[200px]",
|
|
44
|
-
"bg-ods-card border border-ods-border rounded-[6px] shadow-lg",
|
|
45
|
-
"animate-in fade-in-0 zoom-in-95 duration-150",
|
|
46
|
-
className
|
|
47
|
-
),
|
|
48
|
-
children: items.map((item) => /* @__PURE__ */ jsxs(
|
|
49
|
-
"div",
|
|
50
|
-
{
|
|
51
|
-
className: cn(
|
|
52
|
-
"flex items-center justify-between gap-3 px-3 h-11 md:h-12",
|
|
53
|
-
"border-b border-ods-border last:border-b-0"
|
|
54
|
-
),
|
|
55
|
-
children: [
|
|
56
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 text-h5 truncate uppercase text-ods-text-primary", title: typeof item.label === "string" ? item.label : void 0, children: item.label }),
|
|
57
|
-
!disabled && onRemove && /* @__PURE__ */ jsx(
|
|
58
|
-
"button",
|
|
59
|
-
{
|
|
60
|
-
type: "button",
|
|
61
|
-
onClick: (e) => {
|
|
62
|
-
e.stopPropagation();
|
|
63
|
-
onRemove(item.value);
|
|
64
|
-
},
|
|
65
|
-
className: "shrink-0 text-ods-text-secondary hover:text-ods-text-primary transition-colors",
|
|
66
|
-
"aria-label": `Remove ${String(item.label)}`,
|
|
67
|
-
children: /* @__PURE__ */ jsx(XmarkCircleIcon, { size: 20 })
|
|
68
|
-
}
|
|
69
|
-
)
|
|
70
|
-
]
|
|
71
|
-
},
|
|
72
|
-
String(item.value)
|
|
73
|
-
))
|
|
74
|
-
}
|
|
75
|
-
);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// src/components/ui/tag.tsx
|
|
79
|
-
import { cva } from "class-variance-authority";
|
|
80
|
-
init_cn();
|
|
81
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
82
|
-
var tagVariants = cva(
|
|
83
|
-
[
|
|
84
|
-
"text-h5 h-8 inline-flex items-center justify-center gap-[var(--spacing-system-xxs)] p-[var(--spacing-system-xsf)] rounded-md",
|
|
85
|
-
"transition-colors duration-150"
|
|
86
|
-
],
|
|
87
|
-
{
|
|
88
|
-
variants: {
|
|
89
|
-
variant: {
|
|
90
|
-
primary: [
|
|
91
|
-
"bg-[var(--ods-open-yellow-base)] text-[var(--ods-system-greys-black)]",
|
|
92
|
-
"hover:bg-[var(--ods-open-yellow-hover)] active:bg-[var(--ods-open-yellow-action)]"
|
|
93
|
-
],
|
|
94
|
-
outline: [
|
|
95
|
-
"bg-[var(--ods-system-greys-black)] text-[var(--ods-system-greys-white)] border border-[var(--ods-system-greys-soft-grey)]",
|
|
96
|
-
"hover:bg-[var(--ods-system-greys-black-hover)] hover:border-[var(--ods-system-greys-soft-grey-hover)]",
|
|
97
|
-
"active:bg-[var(--ods-system-greys-black-action)] active:border-[var(--ods-system-greys-soft-grey-action)]"
|
|
98
|
-
],
|
|
99
|
-
success: [
|
|
100
|
-
"bg-[var(--ods-attention-green-success-secondary)] text-[var(--ods-attention-green-success)]",
|
|
101
|
-
"hover:bg-[#385029] active:bg-[#425a33]"
|
|
102
|
-
],
|
|
103
|
-
warning: [
|
|
104
|
-
"bg-[var(--ods-attention-yellow-warning-secondary)] text-[var(--ods-attention-yellow-warning)]",
|
|
105
|
-
"hover:bg-[#544729] active:bg-[#5e5133]"
|
|
106
|
-
],
|
|
107
|
-
error: [
|
|
108
|
-
"bg-[var(--ods-attention-red-error-secondary)] text-[var(--ods-attention-red-error)]",
|
|
109
|
-
"hover:bg-[#542b2b] active:bg-[#5e3535]"
|
|
110
|
-
],
|
|
111
|
-
critical: [
|
|
112
|
-
"bg-[var(--ods-attention-red-error)] text-[var(--ods-attention-red-error-secondary)]",
|
|
113
|
-
"hover:bg-[var(--ods-attention-red-error-hover)] active:bg-[var(--ods-attention-red-error-action)]"
|
|
114
|
-
],
|
|
115
|
-
grey: [
|
|
116
|
-
"bg-[var(--ods-system-greys-soft-grey)] text-[var(--ods-system-greys-grey)]",
|
|
117
|
-
"hover:bg-[var(--ods-system-greys-soft-grey-hover)] active:bg-[var(--ods-system-greys-soft-grey-action)]"
|
|
118
|
-
],
|
|
119
|
-
// Matches the EntityTagBadges / StatusBadge tag skin (ods-card + ods-border,
|
|
120
|
-
// mono uppercase) so the tag-editor chips render identically to the public
|
|
121
|
-
// tag badges. Used for FilterChipData variant 'tag' (see search-input).
|
|
122
|
-
badge: [
|
|
123
|
-
"bg-ods-card text-ods-text-primary border border-ods-border font-mono uppercase tracking-wide",
|
|
124
|
-
"hover:border-ods-accent transition-colors"
|
|
125
|
-
]
|
|
126
|
-
}
|
|
127
|
-
},
|
|
128
|
-
defaultVariants: {
|
|
129
|
-
variant: "primary"
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
);
|
|
133
|
-
var disabledTagClasses = [
|
|
134
|
-
"bg-[var(--ods-system-greys-soft-grey)] text-[var(--ods-system-greys-grey)]",
|
|
135
|
-
"border-transparent",
|
|
136
|
-
"cursor-not-allowed",
|
|
137
|
-
"pointer-events-none"
|
|
138
|
-
];
|
|
139
|
-
function Tag({
|
|
140
|
-
label,
|
|
141
|
-
variant,
|
|
142
|
-
icon,
|
|
143
|
-
onClose,
|
|
144
|
-
className,
|
|
145
|
-
labelClassName,
|
|
146
|
-
disabled,
|
|
147
|
-
as: Comp = "div",
|
|
148
|
-
...props
|
|
149
|
-
}) {
|
|
150
|
-
return /* @__PURE__ */ jsxs2(
|
|
151
|
-
Comp,
|
|
152
|
-
{
|
|
153
|
-
className: cn(
|
|
154
|
-
tagVariants({ variant }),
|
|
155
|
-
disabled && disabledTagClasses,
|
|
156
|
-
className
|
|
157
|
-
),
|
|
158
|
-
"aria-disabled": disabled || void 0,
|
|
159
|
-
...props,
|
|
160
|
-
children: [
|
|
161
|
-
icon && /* @__PURE__ */ jsx2("span", { className: "flex items-center justify-center size-5 shrink-0", children: icon }),
|
|
162
|
-
/* @__PURE__ */ jsx2("span", { className: cn("truncate", labelClassName), title: typeof label === "string" ? label : void 0, children: label }),
|
|
163
|
-
onClose && /* @__PURE__ */ jsx2(
|
|
164
|
-
"button",
|
|
165
|
-
{
|
|
166
|
-
type: "button",
|
|
167
|
-
disabled,
|
|
168
|
-
onClick: (e) => {
|
|
169
|
-
e.stopPropagation();
|
|
170
|
-
onClose();
|
|
171
|
-
},
|
|
172
|
-
className: cn(
|
|
173
|
-
"flex items-center justify-center size-5 shrink-0 rounded-full opacity-70 transition-opacity",
|
|
174
|
-
disabled ? "cursor-not-allowed" : "hover:opacity-100"
|
|
175
|
-
),
|
|
176
|
-
"aria-label": "Remove",
|
|
177
|
-
children: /* @__PURE__ */ jsx2(XmarkCircleIcon, { className: "size-4" })
|
|
178
|
-
}
|
|
179
|
-
)
|
|
180
|
-
]
|
|
181
|
-
}
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// src/utils/format.ts
|
|
186
|
-
function formatDate(date, options = {
|
|
187
|
-
year: "numeric",
|
|
188
|
-
month: "long",
|
|
189
|
-
day: "numeric"
|
|
190
|
-
}) {
|
|
191
|
-
const dateObj = typeof date === "string" ? new Date(date) : date;
|
|
192
|
-
if (isNaN(dateObj.getTime())) {
|
|
193
|
-
console.warn("Invalid date provided to formatDate:", date);
|
|
194
|
-
return "Invalid Date";
|
|
195
|
-
}
|
|
196
|
-
return dateObj.toLocaleDateString("en-US", options);
|
|
197
|
-
}
|
|
198
|
-
function formatNumber(num) {
|
|
199
|
-
return num.toLocaleString();
|
|
200
|
-
}
|
|
201
|
-
function formatPrice(price, currency = "USD") {
|
|
202
|
-
return new Intl.NumberFormat("en-US", {
|
|
203
|
-
style: "currency",
|
|
204
|
-
currency
|
|
205
|
-
}).format(price);
|
|
206
|
-
}
|
|
207
|
-
function formatBytes(bytes, decimals = 2) {
|
|
208
|
-
if (bytes === 0) return "0 Bytes";
|
|
209
|
-
const k = 1024;
|
|
210
|
-
const dm = decimals < 0 ? 0 : decimals;
|
|
211
|
-
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
212
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
213
|
-
return Number.parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
|
|
214
|
-
}
|
|
215
|
-
function formatBytesShort(bytes) {
|
|
216
|
-
if (bytes === 0) return "0 B";
|
|
217
|
-
const k = 1024;
|
|
218
|
-
const sizes = ["B", "KB", "MB", "GB", "TB"];
|
|
219
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
220
|
-
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
221
|
-
}
|
|
222
|
-
function formatFileSize(bytes) {
|
|
223
|
-
if (bytes === 0) return "0 B";
|
|
224
|
-
const k = 1024;
|
|
225
|
-
const sizes = ["B", "KB", "MB", "GB"];
|
|
226
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
227
|
-
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
|
|
228
|
-
}
|
|
229
|
-
function formatLargeNumber(num) {
|
|
230
|
-
if (num === 0) return "0";
|
|
231
|
-
const isNegative = num < 0;
|
|
232
|
-
const absNum = Math.abs(num);
|
|
233
|
-
let result;
|
|
234
|
-
if (absNum >= 1e9) {
|
|
235
|
-
result = `${Math.floor(absNum / 1e9)}B`;
|
|
236
|
-
} else if (absNum >= 1e6) {
|
|
237
|
-
result = `${Math.floor(absNum / 1e6)}M`;
|
|
238
|
-
} else if (absNum >= 1e3) {
|
|
239
|
-
result = `${Math.floor(absNum / 1e3)}K`;
|
|
240
|
-
} else {
|
|
241
|
-
result = Math.floor(absNum).toString();
|
|
242
|
-
}
|
|
243
|
-
return isNegative ? `-${result}` : result;
|
|
244
|
-
}
|
|
245
|
-
function formatAbbreviatedNumber(n) {
|
|
246
|
-
if (n >= 1e9) {
|
|
247
|
-
const value = n / 1e9;
|
|
248
|
-
return `${Number.isInteger(value) ? value.toFixed(0) : value.toFixed(1)}B`;
|
|
249
|
-
}
|
|
250
|
-
if (n >= 1e6) {
|
|
251
|
-
const value = n / 1e6;
|
|
252
|
-
return `${Number.isInteger(value) ? value.toFixed(0) : value.toFixed(1)}M`;
|
|
253
|
-
}
|
|
254
|
-
if (n >= 1e3) {
|
|
255
|
-
const value = n / 1e3;
|
|
256
|
-
return `${Number.isInteger(value) ? value.toFixed(0) : value.toFixed(1)}K`;
|
|
257
|
-
}
|
|
258
|
-
return n.toLocaleString();
|
|
259
|
-
}
|
|
260
|
-
function getFirstLastInitials(name) {
|
|
261
|
-
if (!name) return "";
|
|
262
|
-
const words = name.trim().split(/\s+/);
|
|
263
|
-
if (words.length === 0 || !words[0]) return "";
|
|
264
|
-
if (words.length === 1) return words[0].charAt(0).toUpperCase();
|
|
265
|
-
return (words[0].charAt(0) + words[words.length - 1].charAt(0)).toUpperCase();
|
|
266
|
-
}
|
|
267
|
-
function nameInitials(name, fallback = "E") {
|
|
268
|
-
const source = typeof name === "string" ? name.trim() : "";
|
|
269
|
-
const words = source.length > 0 ? source.split(/\s+/) : [];
|
|
270
|
-
const letters = words.map((w) => w[0]).filter(Boolean).slice(0, 2).join("");
|
|
271
|
-
return (letters || fallback).toUpperCase();
|
|
272
|
-
}
|
|
273
|
-
function formatDurationMMSS(seconds) {
|
|
274
|
-
if (!seconds) return "";
|
|
275
|
-
const hours = Math.floor(seconds / 3600);
|
|
276
|
-
const minutes = Math.floor(seconds % 3600 / 60);
|
|
277
|
-
const secs = Math.floor(seconds % 60);
|
|
278
|
-
if (hours > 0) {
|
|
279
|
-
return `${hours}:${minutes.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
|
|
280
|
-
}
|
|
281
|
-
return `${minutes}:${secs.toString().padStart(2, "0")}`;
|
|
282
|
-
}
|
|
283
|
-
function formatDurationCompact(seconds) {
|
|
284
|
-
if (!seconds) return "";
|
|
285
|
-
const hours = Math.floor(seconds / 3600);
|
|
286
|
-
const minutes = Math.floor(seconds % 3600 / 60);
|
|
287
|
-
if (hours > 0) {
|
|
288
|
-
return `${hours}h ${minutes}m`;
|
|
289
|
-
}
|
|
290
|
-
return `${minutes} min`;
|
|
291
|
-
}
|
|
292
|
-
function formatTimeWithTimezone(date, timezone) {
|
|
293
|
-
if (!date) return "";
|
|
294
|
-
const dateObj = typeof date === "string" ? new Date(date) : date;
|
|
295
|
-
const timeStr = dateObj.toLocaleTimeString("en-US", {
|
|
296
|
-
hour: "numeric",
|
|
297
|
-
minute: "2-digit",
|
|
298
|
-
hour12: true
|
|
299
|
-
});
|
|
300
|
-
return timezone ? `${timeStr} ${timezone}` : timeStr;
|
|
301
|
-
}
|
|
302
|
-
function formatDurationFromRange(startAt, endAt) {
|
|
303
|
-
if (!startAt || !endAt) return "";
|
|
304
|
-
const start = typeof startAt === "string" ? new Date(startAt) : startAt;
|
|
305
|
-
const end = typeof endAt === "string" ? new Date(endAt) : endAt;
|
|
306
|
-
const durationMs = end.getTime() - start.getTime();
|
|
307
|
-
const minutes = Math.round(durationMs / 6e4);
|
|
308
|
-
if (minutes >= 60) {
|
|
309
|
-
const hours = Math.floor(minutes / 60);
|
|
310
|
-
const mins = minutes % 60;
|
|
311
|
-
return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
|
|
312
|
-
}
|
|
313
|
-
return `${minutes}m`;
|
|
314
|
-
}
|
|
315
|
-
function formatDateUTC(value, options = {}) {
|
|
316
|
-
const { fallback = "N/A", timezone = "UTC" } = options;
|
|
317
|
-
if (value === null || value === void 0 || value === "") return fallback;
|
|
318
|
-
let ms;
|
|
319
|
-
if (typeof value === "number") {
|
|
320
|
-
ms = value;
|
|
321
|
-
} else {
|
|
322
|
-
const n = Number(value);
|
|
323
|
-
if (Number.isFinite(n) && n > 0 && /^-?\d+(\.\d+)?$/.test(value.trim())) {
|
|
324
|
-
ms = n;
|
|
325
|
-
} else {
|
|
326
|
-
ms = Date.parse(value.includes("T") ? value : value + "T00:00:00Z");
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
if (!Number.isFinite(ms)) return fallback;
|
|
330
|
-
return new Date(ms).toLocaleDateString("en-US", {
|
|
331
|
-
year: "numeric",
|
|
332
|
-
month: "short",
|
|
333
|
-
day: "numeric",
|
|
334
|
-
timeZone: timezone === "local" ? void 0 : "UTC"
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
function formatEntryMonthUTC(entryMonth, style = "short") {
|
|
338
|
-
if (!entryMonth) return null;
|
|
339
|
-
return new Date(entryMonth).toLocaleDateString("en-US", { month: style, year: "numeric", timeZone: "UTC" });
|
|
340
|
-
}
|
|
341
|
-
function formatLegalDate(dateInput) {
|
|
342
|
-
return new Intl.DateTimeFormat("en-US", {
|
|
343
|
-
year: "numeric",
|
|
344
|
-
month: "2-digit",
|
|
345
|
-
day: "2-digit"
|
|
346
|
-
}).format(new Date(dateInput));
|
|
347
|
-
}
|
|
348
|
-
function formatCurrency(value) {
|
|
349
|
-
if (value == null) return "N/A";
|
|
350
|
-
return new Intl.NumberFormat("en-US", {
|
|
351
|
-
style: "currency",
|
|
352
|
-
currency: "USD",
|
|
353
|
-
maximumFractionDigits: 0
|
|
354
|
-
}).format(value);
|
|
355
|
-
}
|
|
356
|
-
function formatPercent(value) {
|
|
357
|
-
if (value == null) return "N/A";
|
|
358
|
-
return `${value.toFixed(2)}%`;
|
|
359
|
-
}
|
|
360
|
-
function formatWholeDollars(price, currency = "USD") {
|
|
361
|
-
return new Intl.NumberFormat("en-US", {
|
|
362
|
-
style: "currency",
|
|
363
|
-
currency,
|
|
364
|
-
maximumFractionDigits: 0
|
|
365
|
-
}).format(price);
|
|
366
|
-
}
|
|
367
|
-
function formatCompactMetric(value, format = "number", options) {
|
|
368
|
-
if (value === 0 || value === null || value === void 0) {
|
|
369
|
-
if (format === "currency") return `${options?.prefix || "$"}0`;
|
|
370
|
-
if (format === "percentage") return "0%";
|
|
371
|
-
if (format === "months") return `0 ${options?.suffix || "months"}`;
|
|
372
|
-
return "0";
|
|
373
|
-
}
|
|
374
|
-
const absValue = Math.abs(value);
|
|
375
|
-
const sign = value < 0 ? "-" : "";
|
|
376
|
-
if (format === "currency") {
|
|
377
|
-
const prefix = options?.prefix || "$";
|
|
378
|
-
const compact = (val, divisor, suffix) => {
|
|
379
|
-
const divided = val / divisor;
|
|
380
|
-
const formatted = divided % 1 === 0 ? divided.toFixed(0) : divided.toFixed(1);
|
|
381
|
-
return `${sign}${prefix}${formatted}${suffix}`;
|
|
382
|
-
};
|
|
383
|
-
if (absValue >= 1e9) return compact(absValue, 1e9, "B");
|
|
384
|
-
if (absValue >= 1e6) return compact(absValue, 1e6, "M");
|
|
385
|
-
if (absValue >= 1e3) return `${sign}${prefix}${(absValue / 1e3).toFixed(0)}K`;
|
|
386
|
-
return `${sign}${prefix}${absValue.toLocaleString()}`;
|
|
387
|
-
}
|
|
388
|
-
if (format === "percentage") {
|
|
389
|
-
return `${sign}${absValue}%`;
|
|
390
|
-
}
|
|
391
|
-
if (format === "months") {
|
|
392
|
-
const rounded = Math.round(value * 10) / 10;
|
|
393
|
-
return `${rounded} ${options?.suffix || "months"}`;
|
|
394
|
-
}
|
|
395
|
-
if (absValue >= 1e6) return `${sign}${(absValue / 1e6).toFixed(1)}M`;
|
|
396
|
-
if (absValue >= 1e3) return `${sign}${(absValue / 1e3).toFixed(1)}K`;
|
|
397
|
-
return value.toLocaleString();
|
|
398
|
-
}
|
|
399
|
-
function getTrendColors(direction, polarity = "positive") {
|
|
400
|
-
if (direction === "neutral" || polarity === "neutral") {
|
|
401
|
-
return {
|
|
402
|
-
textClass: "text-ods-text-secondary",
|
|
403
|
-
badgeClass: "bg-ods-border text-ods-text-secondary"
|
|
404
|
-
};
|
|
405
|
-
}
|
|
406
|
-
const isPositiveOutcome = direction === "up" && polarity === "positive" || direction === "down" && polarity === "negative";
|
|
407
|
-
if (isPositiveOutcome) {
|
|
408
|
-
return {
|
|
409
|
-
textClass: "text-ods-success",
|
|
410
|
-
badgeClass: "bg-ods-success-secondary text-ods-success"
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
return {
|
|
414
|
-
textClass: "text-ods-error",
|
|
415
|
-
badgeClass: "bg-ods-error-secondary text-ods-error"
|
|
416
|
-
};
|
|
417
|
-
}
|
|
418
|
-
function formatDateRange(start, end) {
|
|
419
|
-
if (!start || !end) return "";
|
|
420
|
-
const fmt = (s) => {
|
|
421
|
-
const bareMatch = /^(\d{4})-(\d{2})-(\d{2})$/.exec(s);
|
|
422
|
-
const d = bareMatch ? new Date(Number(bareMatch[1]), Number(bareMatch[2]) - 1, Number(bareMatch[3])) : new Date(s);
|
|
423
|
-
if (Number.isNaN(d.getTime())) return s;
|
|
424
|
-
return d.toLocaleDateString(void 0, {
|
|
425
|
-
month: "short",
|
|
426
|
-
day: "numeric",
|
|
427
|
-
year: "numeric"
|
|
428
|
-
});
|
|
429
|
-
};
|
|
430
|
-
return `${fmt(start)} \u2014 ${fmt(end)}`;
|
|
431
|
-
}
|
|
432
|
-
function formatDateTimeAt(dateString) {
|
|
433
|
-
const date = new Date(dateString);
|
|
434
|
-
const dateStr = date.toLocaleDateString("en-US", {
|
|
435
|
-
month: "short",
|
|
436
|
-
day: "numeric",
|
|
437
|
-
year: "numeric"
|
|
438
|
-
});
|
|
439
|
-
const timeStr = date.toLocaleTimeString("en-US", {
|
|
440
|
-
hour: "numeric",
|
|
441
|
-
minute: "2-digit",
|
|
442
|
-
hour12: true
|
|
443
|
-
});
|
|
444
|
-
return `${dateStr} at ${timeStr}`;
|
|
445
|
-
}
|
|
446
|
-
function formatDurationFromMs(ms) {
|
|
447
|
-
if (!ms || isNaN(ms) || ms < 0) return "0ms";
|
|
448
|
-
if (ms < 1e3) return `${ms}ms`;
|
|
449
|
-
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
450
|
-
return `${(ms / 6e4).toFixed(1)}m`;
|
|
451
|
-
}
|
|
452
|
-
function formatDuration(seconds) {
|
|
453
|
-
if (seconds < 60) return `${seconds} seconds`;
|
|
454
|
-
if (seconds < 3600) return `${Math.floor(seconds / 60)} minutes`;
|
|
455
|
-
const hours = Math.floor(seconds / 3600);
|
|
456
|
-
const minutes = Math.floor(seconds % 3600 / 60);
|
|
457
|
-
if (minutes === 0) return `${hours} hour${hours > 1 ? "s" : ""}`;
|
|
458
|
-
return `${hours} hour${hours > 1 ? "s" : ""} ${minutes} minute${minutes > 1 ? "s" : ""}`;
|
|
459
|
-
}
|
|
460
|
-
function formatUnderscoreText(text) {
|
|
461
|
-
return text.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
462
|
-
}
|
|
463
|
-
function stripHtml(html) {
|
|
464
|
-
let noTags = html;
|
|
465
|
-
let prev;
|
|
466
|
-
do {
|
|
467
|
-
prev = noTags;
|
|
468
|
-
noTags = noTags.replace(/<[^<>]*>/g, "");
|
|
469
|
-
} while (noTags !== prev);
|
|
470
|
-
return noTags.replace(/ /g, " ").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/'/g, "'").replace(/'/g, "'").replace(/&/g, "&").replace(/\s+/g, " ").trim();
|
|
471
|
-
}
|
|
472
|
-
function formatClassification(classification) {
|
|
473
|
-
const customMappings = {
|
|
474
|
-
openframe_selected: "OpenFrame Selected"
|
|
475
|
-
};
|
|
476
|
-
return customMappings[classification] || formatUnderscoreText(classification);
|
|
477
|
-
}
|
|
478
|
-
function formatPricingModel(pricingModel) {
|
|
479
|
-
const customMappings = {
|
|
480
|
-
one_time: "One-time Purchase",
|
|
481
|
-
self_hosted: "Self-hosted"
|
|
482
|
-
};
|
|
483
|
-
return customMappings[pricingModel] || formatUnderscoreText(pricingModel);
|
|
484
|
-
}
|
|
485
|
-
function formatBioText(aboutHtml, fallback = "") {
|
|
486
|
-
if (!aboutHtml || !aboutHtml.trim()) return fallback;
|
|
487
|
-
if (aboutHtml.includes("<p")) {
|
|
488
|
-
const paragraphs = aboutHtml.split(/<p[^<>]*>/).slice(1).map((part) => part.split("</p>")[0]).map((text) => stripHtml(text).trim()).filter((text) => text.length > 0);
|
|
489
|
-
if (paragraphs.length > 0) return paragraphs.join(" ");
|
|
490
|
-
}
|
|
491
|
-
return stripHtml(aboutHtml).trim() || fallback;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
// src/utils/image-proxy.ts
|
|
495
|
-
function getProxiedImageUrl(imageUrl, options) {
|
|
496
|
-
if (!imageUrl) return null;
|
|
497
|
-
const proxyPrefix = options?.proxyPrefix;
|
|
498
|
-
const skipDomains = options?.skipDomains ?? [];
|
|
499
|
-
const directHttps = options?.directHttps ?? false;
|
|
500
|
-
if (proxyPrefix && imageUrl.includes(proxyPrefix)) {
|
|
501
|
-
return imageUrl;
|
|
502
|
-
}
|
|
503
|
-
if (!imageUrl.startsWith("http://") && !imageUrl.startsWith("https://")) {
|
|
504
|
-
return imageUrl;
|
|
505
|
-
}
|
|
506
|
-
if (directHttps && imageUrl.startsWith("https://")) {
|
|
507
|
-
return imageUrl;
|
|
508
|
-
}
|
|
509
|
-
if (!proxyPrefix) {
|
|
510
|
-
return imageUrl;
|
|
511
|
-
}
|
|
512
|
-
for (const domain of skipDomains) {
|
|
513
|
-
if (imageUrl.includes(domain)) {
|
|
514
|
-
return imageUrl;
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
return `${proxyPrefix}?url=${encodeURIComponent(imageUrl)}`;
|
|
518
|
-
}
|
|
519
|
-
function urlPathLooksLikeSvg(imageUrl) {
|
|
520
|
-
try {
|
|
521
|
-
return /\.svg$/i.test(new URL(imageUrl).pathname);
|
|
522
|
-
} catch {
|
|
523
|
-
return /\.svg(\?|#|$)/i.test(imageUrl);
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
function shouldProxyImage(imageUrl, proxyPrefix) {
|
|
527
|
-
if (!imageUrl) return false;
|
|
528
|
-
if (!imageUrl.startsWith("http://") && !imageUrl.startsWith("https://")) return false;
|
|
529
|
-
if (proxyPrefix && imageUrl.includes(proxyPrefix)) return false;
|
|
530
|
-
return true;
|
|
531
|
-
}
|
|
532
|
-
function generateImageSizes(_url) {
|
|
533
|
-
return `(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw`;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// src/components/chat/utils/is-cross-origin-url.ts
|
|
537
|
-
function isCrossOriginUrl(url) {
|
|
538
|
-
if (!url) return false;
|
|
539
|
-
if (url.startsWith("/") && !url.startsWith("//")) return false;
|
|
540
|
-
return true;
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
// src/components/chat/utils/decide-new-tab.ts
|
|
544
|
-
function decideNewTab(input) {
|
|
545
|
-
const { href, targetPlatform, openIn, alwaysNewTab, runtimeMode, currentSource } = input;
|
|
546
|
-
if (runtimeMode === "embed") return true;
|
|
547
|
-
if (openIn === "new-tab") return true;
|
|
548
|
-
if (alwaysNewTab === true) return true;
|
|
549
|
-
if (openIn === "same-tab") return false;
|
|
550
|
-
if (targetPlatform !== void 0 && targetPlatform !== null && currentSource) {
|
|
551
|
-
return targetPlatform !== currentSource;
|
|
552
|
-
}
|
|
553
|
-
if (!href) return false;
|
|
554
|
-
return isCrossOriginUrl(href);
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
// src/components/chat/utils/chat-nav-resolution.ts
|
|
558
|
-
var NEW_TAB_FEATURES = "noopener,noreferrer";
|
|
559
|
-
function isModifierClick(e) {
|
|
560
|
-
return e.button !== 0 || !!e.metaKey || !!e.ctrlKey || !!e.shiftKey || !!e.altKey;
|
|
561
|
-
}
|
|
562
|
-
function stripSameOriginToPath(href) {
|
|
563
|
-
if (!href.startsWith("http")) return href;
|
|
564
|
-
try {
|
|
565
|
-
const u = new URL(href);
|
|
566
|
-
return u.pathname + u.search + u.hash;
|
|
567
|
-
} catch {
|
|
568
|
-
return href;
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
function resolveHrefForRuntime(href, runtime) {
|
|
572
|
-
if (runtime.navigation.mode !== "embed") return href;
|
|
573
|
-
if (href.startsWith("http")) return href;
|
|
574
|
-
if (href.startsWith("//")) return href;
|
|
575
|
-
const origin = runtime.navigation.defaultContentOrigin;
|
|
576
|
-
if (!origin) return href;
|
|
577
|
-
return origin.replace(/\/+$/, "") + (href.startsWith("/") ? href : "/" + href);
|
|
578
|
-
}
|
|
579
|
-
function resolveExternalNavigation(args) {
|
|
580
|
-
let abs = args.href;
|
|
581
|
-
if (abs.startsWith("//")) abs = window.location.protocol + abs;
|
|
582
|
-
if (!abs.startsWith("http")) {
|
|
583
|
-
if (args.runtime.navigation.defaultContentOrigin) {
|
|
584
|
-
let origin = args.runtime.navigation.defaultContentOrigin;
|
|
585
|
-
while (origin.endsWith("/")) origin = origin.slice(0, -1);
|
|
586
|
-
abs = origin + (abs.startsWith("/") ? abs : "/" + abs);
|
|
587
|
-
} else if (args.runtime.navigation.mode === "embed" && process.env.NODE_ENV !== "production") {
|
|
588
|
-
console.warn(
|
|
589
|
-
"[chat-nav-resolution] relative href in embed mode with no defaultContentOrigin set on runtime.navigation \u2014 link will resolve against the embedder origin.",
|
|
590
|
-
{ href: abs, targetPlatform: args.targetPlatform }
|
|
591
|
-
);
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
const open = () => {
|
|
595
|
-
if (args.runtime.navigation.openExternal) {
|
|
596
|
-
args.runtime.navigation.openExternal(abs);
|
|
597
|
-
} else {
|
|
598
|
-
window.open(abs, "_blank", NEW_TAB_FEATURES);
|
|
599
|
-
}
|
|
600
|
-
};
|
|
601
|
-
return { href: abs, open };
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
// src/utils/fetch-priority.ts
|
|
605
|
-
import React from "react";
|
|
606
|
-
var REACT_MAJOR = parseInt((React.version || "0").split(".")[0], 10);
|
|
607
|
-
var USE_CAMEL_CASE_FETCH_PRIORITY = REACT_MAJOR >= 19;
|
|
608
|
-
function fetchPriorityProp(priority) {
|
|
609
|
-
const value = priority === void 0 ? "auto" : typeof priority === "boolean" ? priority ? "high" : "low" : priority;
|
|
610
|
-
return USE_CAMEL_CASE_FETCH_PRIORITY ? { fetchPriority: value } : { fetchpriority: value };
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// src/components/layout/page-heading.tsx
|
|
614
|
-
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
615
|
-
var PAGE_HEADING_CLASS = "text-h1 text-ods-text-primary";
|
|
616
|
-
var SECTION_HEADING_CLASS = "text-h2 text-ods-text-primary";
|
|
617
|
-
var DESCRIPTION_CLASS = "mt-6 max-w-[640px] font-['DM_Sans'] text-[16px] md:text-[18px] leading-[24px] md:leading-[28px] text-ods-text-secondary";
|
|
618
|
-
function PageHeading({
|
|
619
|
-
children,
|
|
620
|
-
as: Tag2 = "h1",
|
|
621
|
-
description,
|
|
622
|
-
className,
|
|
623
|
-
descriptionClassName
|
|
624
|
-
}) {
|
|
625
|
-
const headingClass = className ? `${PAGE_HEADING_CLASS} ${className}` : PAGE_HEADING_CLASS;
|
|
626
|
-
const descClass = descriptionClassName ? `${DESCRIPTION_CLASS} ${descriptionClassName}` : DESCRIPTION_CLASS;
|
|
627
|
-
const hasDescription = description != null && description !== "" && typeof description !== "boolean";
|
|
628
|
-
return /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
629
|
-
/* @__PURE__ */ jsx3(Tag2, { className: headingClass, children }),
|
|
630
|
-
hasDescription && /* @__PURE__ */ jsx3("p", { className: descClass, children: description })
|
|
631
|
-
] });
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
// src/components/chat/utils/compact-card-classes.ts
|
|
635
|
-
var COMPACT_CARD_OUTER = "my-1.5 flex items-start gap-3 w-full p-2 rounded-lg border border-ods-border bg-ods-card no-underline transition-colors hover:border-ods-text-secondary/40";
|
|
636
|
-
var COMPACT_CARD_OUTER_STATIC = "my-1.5 flex items-start gap-3 w-full p-2 rounded-lg border border-ods-border bg-ods-card no-underline cursor-default";
|
|
637
|
-
var COMPACT_CARD_SKELETON_OUTER = "my-1.5 flex w-full animate-pulse items-start gap-3 rounded-lg border border-ods-border bg-ods-card p-2";
|
|
638
|
-
var COMPACT_CARD_IMAGE_SLOT = "relative block shrink-0 self-start w-14 h-14 aspect-square overflow-hidden rounded-md bg-ods-bg";
|
|
639
|
-
var COMPACT_CARD_SKELETON_IMAGE_SLOT = "block h-14 w-14 aspect-square shrink-0 self-start rounded-md bg-ods-bg";
|
|
640
|
-
var COMPACT_CARD_ICON_SLOT = "flex h-14 w-14 aspect-square shrink-0 self-start items-center justify-center rounded-md bg-ods-bg text-ods-accent";
|
|
641
|
-
var COMPACT_CARD_TEXT_COL = "flex min-w-0 flex-1 flex-col gap-0.5 min-h-14";
|
|
642
|
-
var COMPACT_CARD_TITLE_ROW = "flex items-center min-w-0 h-5";
|
|
643
|
-
var COMPACT_CARD_META_ROW_BOX = "flex items-center min-w-0 h-4";
|
|
644
|
-
var COMPACT_CARD_TITLE = "truncate text-sm font-semibold leading-5 text-ods-text-primary";
|
|
645
|
-
var COMPACT_CARD_SUBTITLE = "truncate text-[11px] leading-4 text-ods-text-secondary";
|
|
646
|
-
var COMPACT_CARD_SUMMARY = "truncate text-[11px] leading-4 text-ods-text-secondary/80";
|
|
647
|
-
var COMPACT_CARD_META_ROW = "flex items-center gap-1.5 min-w-0 text-[11px] leading-4 text-ods-text-secondary";
|
|
648
|
-
var COMPACT_CARD_ROW_FILLER = "\xA0";
|
|
649
|
-
var SAFE_URL_SCHEMES = ["http:", "https:", "mailto:"];
|
|
650
|
-
function safeHref(url) {
|
|
651
|
-
if (!url) return null;
|
|
652
|
-
if (/[\u0000-\u001f\u007f\u200b-\u200d\u2028\u2029\ufeff]/.test(url)) return null;
|
|
653
|
-
const trimmed = url.trim();
|
|
654
|
-
if (!trimmed) return null;
|
|
655
|
-
if (trimmed.startsWith("/") && !trimmed.startsWith("//")) return trimmed;
|
|
656
|
-
if (trimmed.startsWith("#")) return trimmed;
|
|
657
|
-
if (/^[a-z][a-z0-9+.-]*:$/i.test(trimmed)) return null;
|
|
658
|
-
try {
|
|
659
|
-
const parsed = new URL(trimmed, "https://_safehref_base.invalid");
|
|
660
|
-
if (!SAFE_URL_SCHEMES.includes(parsed.protocol)) return null;
|
|
661
|
-
if ((parsed.protocol === "https:" || parsed.protocol === "http:") && !parsed.hostname) return null;
|
|
662
|
-
return trimmed;
|
|
663
|
-
} catch {
|
|
664
|
-
return null;
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
// src/utils/source-icons.ts
|
|
669
|
-
var SOURCE_ICON_NAMES = {
|
|
670
|
-
// Doc tables
|
|
671
|
-
"openframe-docs": "openframe",
|
|
672
|
-
"data-room-docs": "shield",
|
|
673
|
-
// CMS / programs
|
|
674
|
-
"blog-posts": "newspaper",
|
|
675
|
-
"product-releases": "rocket",
|
|
676
|
-
"case-studies": "briefcase",
|
|
677
|
-
"onboarding-guides": "graduation-cap",
|
|
678
|
-
webinars: "video",
|
|
679
|
-
events: "calendar",
|
|
680
|
-
podcasts: "headphones",
|
|
681
|
-
"customer-interviews": "users",
|
|
682
|
-
// Financials
|
|
683
|
-
"investor-updates": "mail",
|
|
684
|
-
"financial-kpis": "activity",
|
|
685
|
-
"financial-cap-table": "table",
|
|
686
|
-
"financial-pnl": "trending-up",
|
|
687
|
-
"financial-balance-sheet": "dollar-sign",
|
|
688
|
-
"financial-cash-flow": "banknote",
|
|
689
|
-
// ClickUp
|
|
690
|
-
"clickup-roadmap": "clickup",
|
|
691
|
-
"clickup-delivery": "clickup",
|
|
692
|
-
"clickup-tasks-internal": "clickup",
|
|
693
|
-
// GitHub
|
|
694
|
-
"github-commits": "github",
|
|
695
|
-
"github-pull-requests": "github",
|
|
696
|
-
"github-pr-reviews": "github",
|
|
697
|
-
"github-commits-public": "github",
|
|
698
|
-
"github-pull-requests-public": "github",
|
|
699
|
-
"github-pr-reviews-public": "github",
|
|
700
|
-
// HubSpot
|
|
701
|
-
"hubspot-tickets": "hubspot",
|
|
702
|
-
"hubspot-tickets-anon": "hubspot",
|
|
703
|
-
"hubspot-tickets-self": "hubspot",
|
|
704
|
-
// Communications
|
|
705
|
-
"slack-messages": "slack"
|
|
706
|
-
};
|
|
707
|
-
function getSourceIconName(tableId) {
|
|
708
|
-
if (!tableId) return void 0;
|
|
709
|
-
return SOURCE_ICON_NAMES[tableId];
|
|
710
|
-
}
|
|
711
|
-
var SOURCE_LABELS_BY_TABLE = {
|
|
712
|
-
// Doc tables
|
|
713
|
-
"openframe-docs": "OpenFrame Docs",
|
|
714
|
-
"data-room-docs": "Data Room",
|
|
715
|
-
// CMS / programs
|
|
716
|
-
"blog-posts": "Blog Posts",
|
|
717
|
-
"product-releases": "Product Releases",
|
|
718
|
-
"case-studies": "Case Studies",
|
|
719
|
-
"onboarding-guides": "Onboarding Guides",
|
|
720
|
-
webinars: "Webinars",
|
|
721
|
-
events: "Events",
|
|
722
|
-
podcasts: "Podcasts",
|
|
723
|
-
"customer-interviews": "Customer Interviews",
|
|
724
|
-
// Financials
|
|
725
|
-
"investor-updates": "Investor Updates",
|
|
726
|
-
"financial-kpis": "Financial KPIs",
|
|
727
|
-
"financial-cap-table": "Cap Table",
|
|
728
|
-
"financial-pnl": "Profit & Loss",
|
|
729
|
-
"financial-balance-sheet": "Balance Sheet",
|
|
730
|
-
"financial-cash-flow": "Cash Flow",
|
|
731
|
-
// ClickUp
|
|
732
|
-
"clickup-roadmap": "ClickUp Roadmap",
|
|
733
|
-
"clickup-delivery": "ClickUp Delivery",
|
|
734
|
-
"clickup-tasks-internal": "ClickUp Tasks",
|
|
735
|
-
// GitHub
|
|
736
|
-
"github-commits": "GitHub Commits",
|
|
737
|
-
"github-pull-requests": "GitHub Pull Requests",
|
|
738
|
-
"github-pr-reviews": "GitHub PR Reviews",
|
|
739
|
-
"github-commits-public": "OpenFrame Commits",
|
|
740
|
-
"github-pull-requests-public": "OpenFrame Pull Requests",
|
|
741
|
-
"github-pr-reviews-public": "OpenFrame PR Reviews",
|
|
742
|
-
// HubSpot
|
|
743
|
-
"hubspot-tickets": "HubSpot Tickets",
|
|
744
|
-
// Anon + self share the "Tickets" root so the chip vocabulary is
|
|
745
|
-
// uniform across logged-out (everyone's resolved support tickets,
|
|
746
|
-
// anonymized → "Tickets") and logged-in (user-scoped → "My Tickets")
|
|
747
|
-
// surfaces. The full-PII `hubspot-tickets` entry above is product-hub
|
|
748
|
-
// internal only (admin view), kept as "HubSpot Tickets" to flag the
|
|
749
|
-
// distinct scope.
|
|
750
|
-
"hubspot-tickets-anon": "Tickets",
|
|
751
|
-
"hubspot-tickets-self": "My Tickets",
|
|
752
|
-
// Communications
|
|
753
|
-
"slack-messages": "OpenMSP Community"
|
|
754
|
-
};
|
|
755
|
-
function getSourceLabel(tableId) {
|
|
756
|
-
return SOURCE_LABELS_BY_TABLE[tableId] ?? tableId;
|
|
757
|
-
}
|
|
758
|
-
var DEFAULT_DOCUMENT_TYPE_TO_TABLE_ID = {
|
|
759
|
-
// Doc tables
|
|
760
|
-
markdown: "openframe-docs",
|
|
761
|
-
data_room_doc: "data-room-docs",
|
|
762
|
-
// CMS / programs
|
|
763
|
-
blog_post: "blog-posts",
|
|
764
|
-
product_release: "product-releases",
|
|
765
|
-
case_study: "case-studies",
|
|
766
|
-
onboarding_guide: "onboarding-guides",
|
|
767
|
-
webinar: "webinars",
|
|
768
|
-
event: "events",
|
|
769
|
-
podcast: "podcasts",
|
|
770
|
-
customer_interview: "customer-interviews",
|
|
771
|
-
// Financials
|
|
772
|
-
investor_update: "investor-updates",
|
|
773
|
-
financial_kpi: "financial-kpis",
|
|
774
|
-
cap_table: "financial-cap-table",
|
|
775
|
-
profit_loss: "financial-pnl",
|
|
776
|
-
balance_sheet: "financial-balance-sheet",
|
|
777
|
-
cash_flow: "financial-cash-flow",
|
|
778
|
-
// ClickUp
|
|
779
|
-
roadmap_item: "clickup-roadmap",
|
|
780
|
-
delivery_item: "clickup-delivery",
|
|
781
|
-
internal_task: "clickup-tasks-internal",
|
|
782
|
-
// GitHub
|
|
783
|
-
github_commit: "github-commits",
|
|
784
|
-
github_pull_request: "github-pull-requests",
|
|
785
|
-
github_pr_review: "github-pr-reviews",
|
|
786
|
-
github_commit_public: "github-commits-public",
|
|
787
|
-
github_pull_request_public: "github-pull-requests-public",
|
|
788
|
-
github_pr_review_public: "github-pr-reviews-public",
|
|
789
|
-
// HubSpot
|
|
790
|
-
hubspot_ticket: "hubspot-tickets",
|
|
791
|
-
hubspot_ticket_anon: "hubspot-tickets-anon",
|
|
792
|
-
hubspot_ticket_self: "hubspot-tickets-self",
|
|
793
|
-
// Communications
|
|
794
|
-
slack_message: "slack-messages"
|
|
795
|
-
};
|
|
796
|
-
function defaultTableIdForDocumentType(documentType) {
|
|
797
|
-
return DEFAULT_DOCUMENT_TYPE_TO_TABLE_ID[documentType] ?? null;
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
// src/components/chat/utils/icon-registry.ts
|
|
801
|
-
import { createElement } from "react";
|
|
802
|
-
import {
|
|
803
|
-
Activity,
|
|
804
|
-
Banknote,
|
|
805
|
-
Bell,
|
|
806
|
-
BookOpen,
|
|
807
|
-
Box,
|
|
808
|
-
Briefcase,
|
|
809
|
-
Calendar,
|
|
810
|
-
CheckSquare,
|
|
811
|
-
DollarSign,
|
|
812
|
-
Facebook,
|
|
813
|
-
FileText,
|
|
814
|
-
Github,
|
|
815
|
-
Globe,
|
|
816
|
-
GraduationCap,
|
|
817
|
-
Headphones,
|
|
818
|
-
Info,
|
|
819
|
-
Instagram,
|
|
820
|
-
Mail,
|
|
821
|
-
Megaphone,
|
|
822
|
-
MessageCircle,
|
|
823
|
-
MessageSquare,
|
|
824
|
-
Newspaper,
|
|
825
|
-
Package,
|
|
826
|
-
PenSquare,
|
|
827
|
-
Rocket,
|
|
828
|
-
Search,
|
|
829
|
-
Send,
|
|
830
|
-
Shield,
|
|
831
|
-
Star,
|
|
832
|
-
TableProperties,
|
|
833
|
-
TrendingUp,
|
|
834
|
-
Twitter,
|
|
835
|
-
Users,
|
|
836
|
-
Video,
|
|
837
|
-
Youtube
|
|
838
|
-
} from "lucide-react";
|
|
839
|
-
var OpenFrameLogoIcon = ({ className }) => createElement(OpenFrameLogo, { className, upperPathColor: "currentColor" });
|
|
840
|
-
var ICON_REGISTRY = {
|
|
841
|
-
// lucide-react (kebab-case)
|
|
842
|
-
activity: Activity,
|
|
843
|
-
banknote: Banknote,
|
|
844
|
-
bell: Bell,
|
|
845
|
-
"book-open": BookOpen,
|
|
846
|
-
box: Box,
|
|
847
|
-
briefcase: Briefcase,
|
|
848
|
-
calendar: Calendar,
|
|
849
|
-
"check-square": CheckSquare,
|
|
850
|
-
"dollar-sign": DollarSign,
|
|
851
|
-
// For brand-vs-lucide variants the kebab key is the BRAND (most-common
|
|
852
|
-
// social-platform intent); `'<name>-lucide'` carries the lucide outline.
|
|
853
|
-
facebook: FacebookIcon,
|
|
854
|
-
"facebook-lucide": Facebook,
|
|
855
|
-
"file-text": FileText,
|
|
856
|
-
// `'github-lucide'` is the lucide outline glyph (used by
|
|
857
|
-
// `social_platforms.icon_name='Github'`); `'github'` is the brand icon
|
|
858
|
-
// (used by `chat_admin_slash_commands.icon_name='github'`). The PascalCase
|
|
859
|
-
// alias `'Github' → 'github-lucide'` routes the lucide glyph for
|
|
860
|
-
// social-platform DB rows; `'GitHubIcon' → 'github'` keeps brand routing
|
|
861
|
-
// consistent for callers that store the PascalCase component name.
|
|
862
|
-
github: GitHubIcon,
|
|
863
|
-
"github-lucide": Github,
|
|
864
|
-
globe: Globe,
|
|
865
|
-
"graduation-cap": GraduationCap,
|
|
866
|
-
headphones: Headphones,
|
|
867
|
-
info: Info,
|
|
868
|
-
instagram: InstagramIcon,
|
|
869
|
-
"instagram-lucide": Instagram,
|
|
870
|
-
mail: Mail,
|
|
871
|
-
megaphone: Megaphone,
|
|
872
|
-
"message-circle": MessageCircle,
|
|
873
|
-
"message-square": MessageSquare,
|
|
874
|
-
newspaper: Newspaper,
|
|
875
|
-
package: Package,
|
|
876
|
-
"pen-square": PenSquare,
|
|
877
|
-
rocket: Rocket,
|
|
878
|
-
search: Search,
|
|
879
|
-
send: Send,
|
|
880
|
-
shield: Shield,
|
|
881
|
-
star: Star,
|
|
882
|
-
table: TableProperties,
|
|
883
|
-
"trending-up": TrendingUp,
|
|
884
|
-
twitter: Twitter,
|
|
885
|
-
users: Users,
|
|
886
|
-
video: Video,
|
|
887
|
-
youtube: YouTubeIcon,
|
|
888
|
-
"youtube-lucide": Youtube,
|
|
889
|
-
// brand-only icons (no lucide variant in current use)
|
|
890
|
-
slack: SlackIcon,
|
|
891
|
-
clickup: ClickUpIcon,
|
|
892
|
-
hubspot: HubspotIcon,
|
|
893
|
-
linkedin: LinkedInIcon,
|
|
894
|
-
x: XLogo,
|
|
895
|
-
openframe: OpenFrameLogoIcon
|
|
896
|
-
};
|
|
897
|
-
var PASCAL_TO_KEBAB_ALIASES = {
|
|
898
|
-
// Lucide PascalCase names → kebab equivalents
|
|
899
|
-
Activity: "activity",
|
|
900
|
-
Banknote: "banknote",
|
|
901
|
-
Bell: "bell",
|
|
902
|
-
BookOpen: "book-open",
|
|
903
|
-
Box: "box",
|
|
904
|
-
Briefcase: "briefcase",
|
|
905
|
-
Calendar: "calendar",
|
|
906
|
-
CheckSquare: "check-square",
|
|
907
|
-
DollarSign: "dollar-sign",
|
|
908
|
-
// Lucide PascalCase → the `-lucide` kebab variant (kebab default is the
|
|
909
|
-
// brand icon for the social-platform names below).
|
|
910
|
-
Facebook: "facebook-lucide",
|
|
911
|
-
FileText: "file-text",
|
|
912
|
-
Github: "github-lucide",
|
|
913
|
-
Globe: "globe",
|
|
914
|
-
GraduationCap: "graduation-cap",
|
|
915
|
-
Headphones: "headphones",
|
|
916
|
-
Info: "info",
|
|
917
|
-
Instagram: "instagram-lucide",
|
|
918
|
-
Mail: "mail",
|
|
919
|
-
Megaphone: "megaphone",
|
|
920
|
-
MessageCircle: "message-circle",
|
|
921
|
-
MessageSquare: "message-square",
|
|
922
|
-
Newspaper: "newspaper",
|
|
923
|
-
Package: "package",
|
|
924
|
-
PenSquare: "pen-square",
|
|
925
|
-
Rocket: "rocket",
|
|
926
|
-
Search: "search",
|
|
927
|
-
Send: "send",
|
|
928
|
-
Shield: "shield",
|
|
929
|
-
Star: "star",
|
|
930
|
-
TableProperties: "table",
|
|
931
|
-
TrendingUp: "trending-up",
|
|
932
|
-
Twitter: "twitter",
|
|
933
|
-
Users: "users",
|
|
934
|
-
Video: "video",
|
|
935
|
-
Youtube: "youtube-lucide",
|
|
936
|
-
// Brand-icon PascalCase exports → kebab (kebab default is the brand)
|
|
937
|
-
SlackIcon: "slack",
|
|
938
|
-
GitHubIcon: "github",
|
|
939
|
-
ClickUpIcon: "clickup",
|
|
940
|
-
HubspotIcon: "hubspot",
|
|
941
|
-
LinkedInIcon: "linkedin",
|
|
942
|
-
FacebookIcon: "facebook",
|
|
943
|
-
InstagramIcon: "instagram",
|
|
944
|
-
YouTubeIcon: "youtube",
|
|
945
|
-
XLogo: "x",
|
|
946
|
-
OpenFrameLogo: "openframe"
|
|
947
|
-
};
|
|
948
|
-
function normalizeIconKey(key) {
|
|
949
|
-
return PASCAL_TO_KEBAB_ALIASES[key] ?? key;
|
|
950
|
-
}
|
|
951
|
-
function getIconComponent(iconName) {
|
|
952
|
-
if (!iconName) return FileText;
|
|
953
|
-
return ICON_REGISTRY[normalizeIconKey(iconName)] ?? FileText;
|
|
954
|
-
}
|
|
955
|
-
var SIZE_CLASSES = {
|
|
956
|
-
xs: "w-3 h-3",
|
|
957
|
-
// 12px
|
|
958
|
-
sm: "w-4 h-4",
|
|
959
|
-
// 16px
|
|
960
|
-
md: "w-6 h-6",
|
|
961
|
-
// 24px
|
|
962
|
-
lg: "w-8 h-8",
|
|
963
|
-
// 32px
|
|
964
|
-
xl: "w-12 h-12"
|
|
965
|
-
// 48px
|
|
966
|
-
};
|
|
967
|
-
var ICON_COLORS = {
|
|
968
|
-
linkedin: { color: "#0A66C2" },
|
|
969
|
-
facebook: { color: "#1877F2" },
|
|
970
|
-
youtube: { color: "#FF0000" }
|
|
971
|
-
};
|
|
972
|
-
function getDynamicIcon(iconName, size = "md", className) {
|
|
973
|
-
if (!iconName) {
|
|
974
|
-
console.warn("[getDynamicIcon] No iconName provided, using Globe fallback");
|
|
975
|
-
return createElement(Globe, { className: SIZE_CLASSES[size] });
|
|
976
|
-
}
|
|
977
|
-
const sizeClass = SIZE_CLASSES[size];
|
|
978
|
-
const finalClassName = className ? `${sizeClass} ${className}` : sizeClass;
|
|
979
|
-
const canonicalKey = normalizeIconKey(iconName);
|
|
980
|
-
const IconComponent = ICON_REGISTRY[canonicalKey];
|
|
981
|
-
if (IconComponent) {
|
|
982
|
-
const colorConfig = ICON_COLORS[canonicalKey] || {};
|
|
983
|
-
return createElement(IconComponent, { className: finalClassName, ...colorConfig });
|
|
984
|
-
}
|
|
985
|
-
console.error(
|
|
986
|
-
`[getDynamicIcon] Icon NOT found in registry: "${iconName}" (normalized to "${canonicalKey}"). Available icons:`,
|
|
987
|
-
Object.keys(ICON_REGISTRY)
|
|
988
|
-
);
|
|
989
|
-
return createElement(Globe, { className: finalClassName });
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
// src/components/chat/utils/source-row-cta.ts
|
|
993
|
-
import { FileText as FileText2 } from "lucide-react";
|
|
994
|
-
init_cn();
|
|
995
|
-
function sanitizePath(path) {
|
|
996
|
-
return (path || "").replace(/[^a-zA-Z0-9/_\-.]/g, "");
|
|
997
|
-
}
|
|
998
|
-
function sourceRowCtxFromRuntime(runtime, surface = {}) {
|
|
999
|
-
return {
|
|
1000
|
-
currentPlatform: runtime.source ?? null,
|
|
1001
|
-
composeContentUrl: runtime.composeContentUrl,
|
|
1002
|
-
docPlatformTargets: runtime.docPlatformTargets,
|
|
1003
|
-
baseRoute: surface.baseRoute,
|
|
1004
|
-
chipBasePlatform: surface.chipBasePlatform
|
|
1005
|
-
};
|
|
1006
|
-
}
|
|
1007
|
-
function pickSourceIcon(sourceRepo, documentType) {
|
|
1008
|
-
const iconName = sourceRepo ? getSourceIconName(sourceRepo) : void 0;
|
|
1009
|
-
const icon = iconName ? getIconComponent(iconName) : FileText2;
|
|
1010
|
-
const iconLabel = documentType ?? "Source";
|
|
1011
|
-
return { icon, iconLabel };
|
|
1012
|
-
}
|
|
1013
|
-
var DOC_TABLE_TYPES = ["markdown", "data_room_doc"];
|
|
1014
|
-
function shouldFallbackToPathNav(row) {
|
|
1015
|
-
return !!row.documentType && DOC_TABLE_TYPES.includes(row.documentType);
|
|
1016
|
-
}
|
|
1017
|
-
function resolveSourceRowCTA(row, ctx = {}) {
|
|
1018
|
-
const sourceRepo = row.sourceRepo ?? (row.documentType && ctx.tableIdForDocumentType ? ctx.tableIdForDocumentType(row.documentType) : null) ?? null;
|
|
1019
|
-
const { icon, iconLabel } = pickSourceIcon(sourceRepo, row.documentType);
|
|
1020
|
-
let href = null;
|
|
1021
|
-
let targetPlatform = null;
|
|
1022
|
-
const idValue = (row.id ?? "").trim();
|
|
1023
|
-
if (row.path && shouldFallbackToPathNav(row) && !row.externalUrl) {
|
|
1024
|
-
const safePath = sanitizePath(row.path);
|
|
1025
|
-
if (safePath) {
|
|
1026
|
-
const docTarget = row.documentType ? ctx.docPlatformTargets?.[row.documentType] : void 0;
|
|
1027
|
-
if (docTarget) {
|
|
1028
|
-
const seg = docTarget.basePath.split("/").filter(Boolean).join("/");
|
|
1029
|
-
const base = `${getBaseUrl(docTarget.platform)}${seg ? `/${seg}` : ""}/`;
|
|
1030
|
-
href = safeHref(new URL(safePath, base).toString()) ?? null;
|
|
1031
|
-
targetPlatform = docTarget.platform;
|
|
1032
|
-
} else if (ctx.chipBasePlatform) {
|
|
1033
|
-
const base = `${getBaseUrl(ctx.chipBasePlatform)}/knowledge-base/`;
|
|
1034
|
-
href = safeHref(new URL(safePath, base).toString()) ?? null;
|
|
1035
|
-
targetPlatform = ctx.chipBasePlatform;
|
|
1036
|
-
} else if (ctx.baseRoute) {
|
|
1037
|
-
const synthetic = `https://_internal_.local${ctx.baseRoute.startsWith("/") ? ctx.baseRoute : "/" + ctx.baseRoute}/`;
|
|
1038
|
-
const absolute = new URL(safePath, synthetic).toString();
|
|
1039
|
-
href = safeHref(absolute.replace("https://_internal_.local", "")) ?? null;
|
|
1040
|
-
targetPlatform = ctx.currentPlatform ?? null;
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
} else if (ctx.composeContentUrl && row.documentType && row.externalUrl) {
|
|
1044
|
-
const composed = ctx.composeContentUrl({
|
|
1045
|
-
type: row.documentType,
|
|
1046
|
-
identifier: idValue,
|
|
1047
|
-
externalUrl: row.externalUrl,
|
|
1048
|
-
targetPlatform: row.targetPlatform ?? null
|
|
1049
|
-
});
|
|
1050
|
-
href = composed.href ? safeHref(composed.href) ?? null : null;
|
|
1051
|
-
targetPlatform = composed.targetPlatform;
|
|
1052
|
-
} else if (row.externalUrl) {
|
|
1053
|
-
href = safeHref(row.externalUrl) ?? null;
|
|
1054
|
-
targetPlatform = row.targetPlatform ?? null;
|
|
1055
|
-
}
|
|
1056
|
-
const askable = !!(idValue && row.documentType);
|
|
1057
|
-
const chatRef = askable ? {
|
|
1058
|
-
type: row.documentType,
|
|
1059
|
-
...sourceRepo ? { sourceRepo } : {},
|
|
1060
|
-
id: idValue,
|
|
1061
|
-
title: row.title,
|
|
1062
|
-
url: href,
|
|
1063
|
-
targetPlatform,
|
|
1064
|
-
// Carry `path` so a downstream inline card (rendered from this
|
|
1065
|
-
// chatRef on a subsequent turn) gets the same doc-tree-swap
|
|
1066
|
-
// routing the chip already used. Without it, the Ask drill-in
|
|
1067
|
-
// would resolve to a same-tab full-page nav even when an in-app
|
|
1068
|
-
// path is available.
|
|
1069
|
-
...row.path ? { metadata: { path: row.path } } : {}
|
|
1070
|
-
} : null;
|
|
1071
|
-
return { icon, iconLabel, href, targetPlatform, askable, chatRef };
|
|
1072
|
-
}
|
|
1073
|
-
function resolveSourceIcon(input, ctx = {}) {
|
|
1074
|
-
if (!input) return { Icon: FileText2, label: "Source" };
|
|
1075
|
-
const { sourceRepo, documentType } = typeof input === "string" ? { sourceRepo: null, documentType: input } : input;
|
|
1076
|
-
if (!sourceRepo && !documentType) return { Icon: FileText2, label: "Source" };
|
|
1077
|
-
const resolvedRepo = sourceRepo ?? (documentType && ctx.tableIdForDocumentType ? ctx.tableIdForDocumentType(documentType) : null) ?? null;
|
|
1078
|
-
const { icon, iconLabel } = pickSourceIcon(resolvedRepo, documentType);
|
|
1079
|
-
return { Icon: icon, label: iconLabel };
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
// src/utils/content-href.ts
|
|
1083
|
-
var DEFAULT_CONTENT_SUFFIXES = {
|
|
1084
|
-
onboarding_guide: "onboarding-guides",
|
|
1085
|
-
product_release: "releases",
|
|
1086
|
-
blog_post: "blog",
|
|
1087
|
-
case_study: "case-studies",
|
|
1088
|
-
customer_interview: "interviews",
|
|
1089
|
-
investor_update: "investor-updates",
|
|
1090
|
-
webinar: "webinars",
|
|
1091
|
-
podcast: "podcasts",
|
|
1092
|
-
event: "events",
|
|
1093
|
-
// Author profile pages (`/authors/<slug>`) — identified by the profile
|
|
1094
|
-
// slug. Mirrors the hub's `PUBLIC_URL_PATHS.author`, which derives from
|
|
1095
|
-
// `AUTHORS_PATH` in the hub's `lib/utils/breadcrumbs.ts` (the hub-side
|
|
1096
|
-
// SSOT for the segment).
|
|
1097
|
-
author: "authors"
|
|
1098
|
-
};
|
|
1099
|
-
function lastPathSegment(url) {
|
|
1100
|
-
try {
|
|
1101
|
-
const pathname = new URL(url, "https://_.local").pathname;
|
|
1102
|
-
const segs = pathname.split("/").filter(Boolean);
|
|
1103
|
-
return segs.length > 0 ? segs[segs.length - 1] : null;
|
|
1104
|
-
} catch {
|
|
1105
|
-
return null;
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
function makeComposeContentUrl(opts) {
|
|
1109
|
-
const suffixes = opts.suffixes ?? DEFAULT_CONTENT_SUFFIXES;
|
|
1110
|
-
return ({ type, identifier, externalUrl, targetPlatform }) => {
|
|
1111
|
-
const override = opts.overrides && Object.prototype.hasOwnProperty.call(opts.overrides, type) ? opts.overrides[type] : void 0;
|
|
1112
|
-
if (override) return override(identifier);
|
|
1113
|
-
const seg = (Object.prototype.hasOwnProperty.call(suffixes, type) ? suffixes[type] : void 0) ?? type;
|
|
1114
|
-
if (opts.hostedTypes.has(type)) {
|
|
1115
|
-
const recovered = externalUrl ? lastPathSegment(externalUrl) : null;
|
|
1116
|
-
const slug = recovered && recovered !== seg ? recovered : identifier;
|
|
1117
|
-
return { href: `/${seg}/${slug}`, targetPlatform: null };
|
|
1118
|
-
}
|
|
1119
|
-
return externalUrl ? { href: externalUrl, targetPlatform: targetPlatform ?? null } : { href: `${opts.contentOrigin}/${seg}/${identifier}`, targetPlatform: null };
|
|
1120
|
-
};
|
|
1121
|
-
}
|
|
1122
|
-
function buildDefaultHref(basePath, slug) {
|
|
1123
|
-
return { href: `${basePath}/${slug}`, targetPlatform: null };
|
|
1124
|
-
}
|
|
1125
|
-
function resolveContentHref(composeContentUrl, args) {
|
|
1126
|
-
return composeContentUrl ? composeContentUrl({ type: args.type, identifier: args.slug, platforms: args.platforms }) : buildDefaultHref(args.basePath, args.slug);
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
|
-
// src/components/ui/search-input.tsx
|
|
1130
|
-
init_cn();
|
|
1131
|
-
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
1132
|
-
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
|
1133
|
-
import * as React2 from "react";
|
|
1134
|
-
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1135
|
-
var containerStyles = cn(
|
|
1136
|
-
// Layout & spacing — matches lib Input component
|
|
1137
|
-
"flex items-center gap-2 rounded-[6px] border px-3 h-11 md:h-12 cursor-text",
|
|
1138
|
-
"has-[:focus-visible]:outline-none",
|
|
1139
|
-
"group",
|
|
1140
|
-
"transition-colors duration-200",
|
|
1141
|
-
// Theme palette — matches lib Input component
|
|
1142
|
-
"bg-ods-card border-ods-border has-[:focus]:border-ods-accent"
|
|
1143
|
-
);
|
|
1144
|
-
var innerInputStyles = cn(
|
|
1145
|
-
"flex-1 min-w-[60px] bg-transparent border-none outline-none",
|
|
1146
|
-
"text-h4",
|
|
1147
|
-
"text-ods-text-primary placeholder:text-ods-text-secondary",
|
|
1148
|
-
"disabled:cursor-not-allowed",
|
|
1149
|
-
"touch-manipulation"
|
|
1150
|
-
);
|
|
1151
|
-
function chipVariantToTagVariant(variant) {
|
|
1152
|
-
switch (variant) {
|
|
1153
|
-
case "selected":
|
|
1154
|
-
return "primary";
|
|
1155
|
-
// Content tags render with the unified badge skin (ods-card + ods-border,
|
|
1156
|
-
// mono uppercase) — identical to the public EntityTagBadges display.
|
|
1157
|
-
case "tag":
|
|
1158
|
-
return "badge";
|
|
1159
|
-
case "category":
|
|
1160
|
-
case "subcategory":
|
|
1161
|
-
default:
|
|
1162
|
-
return "outline";
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
function SearchInput({
|
|
1166
|
-
placeholder = "Search...",
|
|
1167
|
-
value,
|
|
1168
|
-
defaultValue = "",
|
|
1169
|
-
onChange,
|
|
1170
|
-
onSubmit,
|
|
1171
|
-
results = [],
|
|
1172
|
-
isLoading = false,
|
|
1173
|
-
onResultSelect,
|
|
1174
|
-
debounceMs = 300,
|
|
1175
|
-
renderResult,
|
|
1176
|
-
groupBy,
|
|
1177
|
-
emptyResultsText = "No results found",
|
|
1178
|
-
showDropdown: showDropdownProp,
|
|
1179
|
-
filterChips = [],
|
|
1180
|
-
onFilterRemove,
|
|
1181
|
-
startAdornment,
|
|
1182
|
-
endAdornment,
|
|
1183
|
-
className,
|
|
1184
|
-
dropdownClassName,
|
|
1185
|
-
minQueryLength = 2,
|
|
1186
|
-
limitTags = "auto",
|
|
1187
|
-
getLimitTagsText = (more) => `+${more}`
|
|
1188
|
-
}) {
|
|
1189
|
-
const [internalValue, setInternalValue] = React2.useState(defaultValue);
|
|
1190
|
-
const currentValue = onChange ? value ?? "" : internalValue;
|
|
1191
|
-
const debouncedValue = useDebounce(currentValue, debounceMs);
|
|
1192
|
-
const [isOpen, setIsOpen] = React2.useState(false);
|
|
1193
|
-
const [highlightedIndex, setHighlightedIndex] = React2.useState(-1);
|
|
1194
|
-
const containerRef = React2.useRef(null);
|
|
1195
|
-
const currentPlaceholder = filterChips.length > 0 ? "Add filter..." : placeholder;
|
|
1196
|
-
const {
|
|
1197
|
-
visibleCount: rawVisibleCount,
|
|
1198
|
-
middleRef,
|
|
1199
|
-
measureRef,
|
|
1200
|
-
textMeasureRef,
|
|
1201
|
-
badgeRef,
|
|
1202
|
-
inputRef
|
|
1203
|
-
} = useAutoLimitTags({
|
|
1204
|
-
count: filterChips.length,
|
|
1205
|
-
limitTags,
|
|
1206
|
-
// When chips exist, pass empty placeholder so the hook only reserves input minWidth,
|
|
1207
|
-
// not the full placeholder text width — gives more room for chips on narrow screens
|
|
1208
|
-
placeholder: filterChips.length > 0 ? "" : placeholder
|
|
1209
|
-
});
|
|
1210
|
-
const visibleCount = filterChips.length > 0 ? Math.max(1, rawVisibleCount) : rawVisibleCount;
|
|
1211
|
-
const hiddenTagsRef = React2.useRef(null);
|
|
1212
|
-
const hiddenTagsPopupRef = React2.useRef(null);
|
|
1213
|
-
const [showHiddenTags, setShowHiddenTags] = React2.useState(false);
|
|
1214
|
-
React2.useEffect(() => {
|
|
1215
|
-
if (!showHiddenTags) return;
|
|
1216
|
-
const handleClick = (e) => {
|
|
1217
|
-
const target = e.target;
|
|
1218
|
-
if (!hiddenTagsRef.current?.contains(target) && !hiddenTagsPopupRef.current?.contains(target)) {
|
|
1219
|
-
setShowHiddenTags(false);
|
|
1220
|
-
}
|
|
1221
|
-
};
|
|
1222
|
-
document.addEventListener("mousedown", handleClick);
|
|
1223
|
-
return () => document.removeEventListener("mousedown", handleClick);
|
|
1224
|
-
}, [showHiddenTags]);
|
|
1225
|
-
const hiddenCount = filterChips.length - visibleCount;
|
|
1226
|
-
const visibleChips = filterChips.slice(0, visibleCount);
|
|
1227
|
-
const hiddenChips = filterChips.slice(visibleCount);
|
|
1228
|
-
const { flatResults, groups } = React2.useMemo(() => {
|
|
1229
|
-
if (!groupBy) return { flatResults: results, groups: null };
|
|
1230
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
1231
|
-
for (const r of results) {
|
|
1232
|
-
const key = groupBy(r);
|
|
1233
|
-
const arr = grouped.get(key);
|
|
1234
|
-
if (arr) {
|
|
1235
|
-
arr.push(r);
|
|
1236
|
-
} else {
|
|
1237
|
-
grouped.set(key, [r]);
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
return { flatResults: results, groups: grouped };
|
|
1241
|
-
}, [results, groupBy]);
|
|
1242
|
-
const meetsMinQuery = debouncedValue.length >= minQueryLength;
|
|
1243
|
-
const autoShow = meetsMinQuery;
|
|
1244
|
-
const dropdownVisible = showDropdownProp ?? (isOpen && autoShow);
|
|
1245
|
-
React2.useEffect(() => {
|
|
1246
|
-
setHighlightedIndex(-1);
|
|
1247
|
-
}, [flatResults.length]);
|
|
1248
|
-
const handleChange = (e) => {
|
|
1249
|
-
const newVal = e.target.value;
|
|
1250
|
-
if (onChange) {
|
|
1251
|
-
onChange(newVal);
|
|
1252
|
-
} else {
|
|
1253
|
-
setInternalValue(newVal);
|
|
1254
|
-
}
|
|
1255
|
-
if (!isOpen) setIsOpen(true);
|
|
1256
|
-
setHighlightedIndex(-1);
|
|
1257
|
-
};
|
|
1258
|
-
const handleClear = (e) => {
|
|
1259
|
-
e.stopPropagation();
|
|
1260
|
-
e.preventDefault();
|
|
1261
|
-
if (onChange) {
|
|
1262
|
-
onChange("");
|
|
1263
|
-
} else {
|
|
1264
|
-
setInternalValue("");
|
|
1265
|
-
}
|
|
1266
|
-
inputRef.current?.focus();
|
|
1267
|
-
};
|
|
1268
|
-
const handleResultClick = (result, e) => {
|
|
1269
|
-
onResultSelect?.(
|
|
1270
|
-
result,
|
|
1271
|
-
e ? {
|
|
1272
|
-
metaKey: e.metaKey,
|
|
1273
|
-
ctrlKey: e.ctrlKey,
|
|
1274
|
-
shiftKey: e.shiftKey,
|
|
1275
|
-
altKey: e.altKey,
|
|
1276
|
-
button: e.button
|
|
1277
|
-
} : void 0
|
|
1278
|
-
);
|
|
1279
|
-
setIsOpen(false);
|
|
1280
|
-
};
|
|
1281
|
-
const handleKeyDown = (e) => {
|
|
1282
|
-
switch (e.key) {
|
|
1283
|
-
case "ArrowDown":
|
|
1284
|
-
e.preventDefault();
|
|
1285
|
-
if (!isOpen) setIsOpen(true);
|
|
1286
|
-
setHighlightedIndex(
|
|
1287
|
-
(prev) => prev < flatResults.length - 1 ? prev + 1 : 0
|
|
1288
|
-
);
|
|
1289
|
-
break;
|
|
1290
|
-
case "ArrowUp":
|
|
1291
|
-
e.preventDefault();
|
|
1292
|
-
setHighlightedIndex(
|
|
1293
|
-
(prev) => prev > 0 ? prev - 1 : flatResults.length - 1
|
|
1294
|
-
);
|
|
1295
|
-
break;
|
|
1296
|
-
case "Enter":
|
|
1297
|
-
e.preventDefault();
|
|
1298
|
-
if (highlightedIndex >= 0 && flatResults[highlightedIndex]) {
|
|
1299
|
-
handleResultClick(flatResults[highlightedIndex]);
|
|
1300
|
-
} else {
|
|
1301
|
-
onSubmit?.(currentValue);
|
|
1302
|
-
}
|
|
1303
|
-
break;
|
|
1304
|
-
case "Escape":
|
|
1305
|
-
setIsOpen(false);
|
|
1306
|
-
setHighlightedIndex(-1);
|
|
1307
|
-
break;
|
|
1308
|
-
case "Backspace":
|
|
1309
|
-
if (!currentValue && filterChips.length > 0 && onFilterRemove) {
|
|
1310
|
-
onFilterRemove(filterChips[filterChips.length - 1].id);
|
|
1311
|
-
}
|
|
1312
|
-
break;
|
|
1313
|
-
}
|
|
1314
|
-
};
|
|
1315
|
-
const handleOpenChange = (open) => {
|
|
1316
|
-
setIsOpen(open);
|
|
1317
|
-
};
|
|
1318
|
-
const defaultRenderResult = (result, isHighlighted) => /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-3 w-full min-w-0", children: [
|
|
1319
|
-
result.icon && /* @__PURE__ */ jsx4("span", { className: "flex-shrink-0 text-ods-text-secondary [&_svg]:size-4", children: result.icon }),
|
|
1320
|
-
/* @__PURE__ */ jsxs4("div", { className: "min-w-0 flex-1", children: [
|
|
1321
|
-
/* @__PURE__ */ jsx4("div", { className: cn(
|
|
1322
|
-
"text-sm font-medium leading-5 truncate",
|
|
1323
|
-
isHighlighted ? "text-ods-accent" : "text-ods-text-primary"
|
|
1324
|
-
), title: result.title, children: result.title }),
|
|
1325
|
-
result.description && /* @__PURE__ */ jsx4("div", { className: "text-xs leading-4 text-ods-text-secondary truncate mt-0.5", title: result.description, children: result.description })
|
|
1326
|
-
] }),
|
|
1327
|
-
result.type && /* @__PURE__ */ jsx4("span", { className: "flex-shrink-0 text-[11px] font-medium text-ods-text-muted uppercase tracking-wider", children: result.type })
|
|
1328
|
-
] });
|
|
1329
|
-
const renderRow = (result, index) => {
|
|
1330
|
-
const isHighlighted = index === highlightedIndex;
|
|
1331
|
-
return /* @__PURE__ */ jsx4(
|
|
1332
|
-
"div",
|
|
1333
|
-
{
|
|
1334
|
-
role: "option",
|
|
1335
|
-
"aria-selected": isHighlighted,
|
|
1336
|
-
className: cn(
|
|
1337
|
-
"flex items-center min-h-10 px-3 cursor-pointer transition-colors border-b border-ods-border last:border-b-0",
|
|
1338
|
-
isHighlighted && "bg-ods-bg-hover",
|
|
1339
|
-
!isHighlighted && "hover:bg-ods-bg-hover"
|
|
1340
|
-
),
|
|
1341
|
-
onClick: (e) => handleResultClick(result, e),
|
|
1342
|
-
onMouseEnter: () => setHighlightedIndex(index),
|
|
1343
|
-
children: renderResult ? renderResult(result, isHighlighted) : defaultRenderResult(result, isHighlighted)
|
|
1344
|
-
},
|
|
1345
|
-
result.id
|
|
1346
|
-
);
|
|
1347
|
-
};
|
|
1348
|
-
const renderDropdownContent = () => {
|
|
1349
|
-
if (isLoading) {
|
|
1350
|
-
return /* @__PURE__ */ jsx4("div", { className: "px-4 py-3 text-ods-text-secondary text-[14px]", children: "Loading..." });
|
|
1351
|
-
}
|
|
1352
|
-
if (flatResults.length === 0) {
|
|
1353
|
-
return /* @__PURE__ */ jsx4("div", { className: "px-4 py-3 text-ods-text-secondary text-[14px]", children: emptyResultsText });
|
|
1354
|
-
}
|
|
1355
|
-
if (groups) {
|
|
1356
|
-
let globalIndex = 0;
|
|
1357
|
-
return Array.from(groups.entries()).map(([groupLabel, groupResults]) => /* @__PURE__ */ jsxs4("div", { children: [
|
|
1358
|
-
/* @__PURE__ */ jsx4("div", { className: "px-4 py-2 text-[12px] font-semibold text-ods-text-secondary uppercase tracking-wide bg-ods-bg", children: groupLabel }),
|
|
1359
|
-
groupResults.map((result) => {
|
|
1360
|
-
const idx = globalIndex++;
|
|
1361
|
-
return renderRow(result, idx);
|
|
1362
|
-
})
|
|
1363
|
-
] }, groupLabel));
|
|
1364
|
-
}
|
|
1365
|
-
return flatResults.map((result, index) => renderRow(result, index));
|
|
1366
|
-
};
|
|
1367
|
-
const hasValue = currentValue.length > 0;
|
|
1368
|
-
return /* @__PURE__ */ jsxs4("div", { className: cn("relative", className), ref: containerRef, children: [
|
|
1369
|
-
/* @__PURE__ */ jsxs4(PopoverPrimitive.Root, { open: dropdownVisible, onOpenChange: handleOpenChange, modal: false, children: [
|
|
1370
|
-
/* @__PURE__ */ jsx4(PopoverPrimitive.Anchor, { asChild: true, children: /* @__PURE__ */ jsxs4(
|
|
1371
|
-
"div",
|
|
1372
|
-
{
|
|
1373
|
-
className: cn(
|
|
1374
|
-
containerStyles,
|
|
1375
|
-
"hover:bg-ods-bg-hover hover:border-ods-border-hover active:bg-ods-bg-active active:border-ods-border-active",
|
|
1376
|
-
dropdownVisible && "!border-ods-accent"
|
|
1377
|
-
),
|
|
1378
|
-
onClick: () => {
|
|
1379
|
-
inputRef.current?.focus();
|
|
1380
|
-
setIsOpen(true);
|
|
1381
|
-
},
|
|
1382
|
-
children: [
|
|
1383
|
-
/* @__PURE__ */ jsx4("span", { className: "flex-shrink-0 text-ods-text-secondary transition-colors duration-200 group-has-[:focus]:text-ods-accent [&_svg]:size-4 md:[&_svg]:size-6", children: startAdornment !== void 0 ? startAdornment : /* @__PURE__ */ jsx4(SearchIcon, {}) }),
|
|
1384
|
-
/* @__PURE__ */ jsxs4("div", { ref: middleRef, className: "flex-1 flex items-center gap-2 min-w-0 overflow-hidden", children: [
|
|
1385
|
-
visibleChips.map((chip) => /* @__PURE__ */ jsx4(
|
|
1386
|
-
Tag,
|
|
1387
|
-
{
|
|
1388
|
-
variant: chipVariantToTagVariant(chip.variant),
|
|
1389
|
-
label: chip.label,
|
|
1390
|
-
labelClassName: "truncate max-w-[120px]",
|
|
1391
|
-
onClose: onFilterRemove ? () => onFilterRemove(chip.id) : void 0
|
|
1392
|
-
},
|
|
1393
|
-
chip.id
|
|
1394
|
-
)),
|
|
1395
|
-
hiddenCount > 0 && /* @__PURE__ */ jsx4("div", { ref: hiddenTagsRef, className: "shrink-0", children: /* @__PURE__ */ jsx4(
|
|
1396
|
-
"button",
|
|
1397
|
-
{
|
|
1398
|
-
ref: badgeRef,
|
|
1399
|
-
type: "button",
|
|
1400
|
-
onClick: (e) => {
|
|
1401
|
-
e.stopPropagation();
|
|
1402
|
-
setShowHiddenTags((prev) => !prev);
|
|
1403
|
-
},
|
|
1404
|
-
className: cn(
|
|
1405
|
-
"flex items-center h-8 px-2",
|
|
1406
|
-
"bg-ods-card border border-ods-border rounded-[6px]",
|
|
1407
|
-
"font-mono text-[14px] font-medium leading-5 text-ods-text-secondary uppercase tracking-[-0.28px]",
|
|
1408
|
-
"hover:bg-ods-bg-hover transition-colors cursor-pointer"
|
|
1409
|
-
),
|
|
1410
|
-
"aria-label": `${hiddenCount} more selected filters`,
|
|
1411
|
-
children: getLimitTagsText(hiddenCount)
|
|
1412
|
-
}
|
|
1413
|
-
) }),
|
|
1414
|
-
/* @__PURE__ */ jsx4(
|
|
1415
|
-
"input",
|
|
1416
|
-
{
|
|
1417
|
-
ref: inputRef,
|
|
1418
|
-
type: "text",
|
|
1419
|
-
value: currentValue,
|
|
1420
|
-
onChange: handleChange,
|
|
1421
|
-
onKeyDown: handleKeyDown,
|
|
1422
|
-
onFocus: () => {
|
|
1423
|
-
setIsOpen(true);
|
|
1424
|
-
setShowHiddenTags(false);
|
|
1425
|
-
},
|
|
1426
|
-
placeholder: currentPlaceholder,
|
|
1427
|
-
className: innerInputStyles
|
|
1428
|
-
}
|
|
1429
|
-
)
|
|
1430
|
-
] }),
|
|
1431
|
-
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1 shrink-0 ml-auto", children: [
|
|
1432
|
-
hasValue && /* @__PURE__ */ jsx4(
|
|
1433
|
-
"button",
|
|
1434
|
-
{
|
|
1435
|
-
type: "button",
|
|
1436
|
-
onClick: handleClear,
|
|
1437
|
-
className: "flex items-center justify-center hover:opacity-70 transition-opacity",
|
|
1438
|
-
"aria-label": "Clear search",
|
|
1439
|
-
children: /* @__PURE__ */ jsx4(XmarkCircleIcon, { className: "text-ods-text-secondary", size: 24 })
|
|
1440
|
-
}
|
|
1441
|
-
),
|
|
1442
|
-
endAdornment
|
|
1443
|
-
] })
|
|
1444
|
-
]
|
|
1445
|
-
}
|
|
1446
|
-
) }),
|
|
1447
|
-
/* @__PURE__ */ jsx4(
|
|
1448
|
-
PopoverPrimitive.Content,
|
|
1449
|
-
{
|
|
1450
|
-
className: cn(
|
|
1451
|
-
"z-50 w-[var(--radix-popover-trigger-width)] mt-1",
|
|
1452
|
-
"bg-ods-card border border-ods-border rounded-[6px] overflow-hidden shadow-lg",
|
|
1453
|
-
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1454
|
-
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1455
|
-
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
1456
|
-
"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
|
|
1457
|
-
dropdownClassName
|
|
1458
|
-
),
|
|
1459
|
-
sideOffset: 4,
|
|
1460
|
-
align: "start",
|
|
1461
|
-
onOpenAutoFocus: (e) => {
|
|
1462
|
-
e.preventDefault();
|
|
1463
|
-
inputRef.current?.focus();
|
|
1464
|
-
},
|
|
1465
|
-
onInteractOutside: (e) => {
|
|
1466
|
-
if (containerRef.current?.contains(e.target)) {
|
|
1467
|
-
e.preventDefault();
|
|
1468
|
-
}
|
|
1469
|
-
},
|
|
1470
|
-
children: /* @__PURE__ */ jsxs4(ScrollAreaPrimitive.Root, { className: "overflow-hidden", children: [
|
|
1471
|
-
/* @__PURE__ */ jsx4(ScrollAreaPrimitive.Viewport, { className: "max-h-[320px] w-full", children: /* @__PURE__ */ jsx4("div", { role: "listbox", children: renderDropdownContent() }) }),
|
|
1472
|
-
/* @__PURE__ */ jsx4(ScrollAreaPrimitive.Scrollbar, { className: "hidden", orientation: "vertical", children: /* @__PURE__ */ jsx4(ScrollAreaPrimitive.Thumb, {}) })
|
|
1473
|
-
] })
|
|
1474
|
-
}
|
|
1475
|
-
)
|
|
1476
|
-
] }),
|
|
1477
|
-
showHiddenTags && hiddenCount > 0 && /* @__PURE__ */ jsx4(
|
|
1478
|
-
HiddenTagsPopup,
|
|
1479
|
-
{
|
|
1480
|
-
ref: hiddenTagsPopupRef,
|
|
1481
|
-
items: hiddenChips.map((chip) => ({ label: chip.label, value: chip.id })),
|
|
1482
|
-
style: {
|
|
1483
|
-
left: badgeRef.current ? badgeRef.current.getBoundingClientRect().left - (containerRef.current?.getBoundingClientRect().left ?? 0) : 0
|
|
1484
|
-
},
|
|
1485
|
-
onRemove: (value2) => {
|
|
1486
|
-
onFilterRemove?.(value2);
|
|
1487
|
-
if (hiddenCount <= 1) setShowHiddenTags(false);
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
),
|
|
1491
|
-
/* @__PURE__ */ jsx4(
|
|
1492
|
-
"span",
|
|
1493
|
-
{
|
|
1494
|
-
ref: textMeasureRef,
|
|
1495
|
-
"aria-hidden": "true",
|
|
1496
|
-
className: "fixed -left-[9999px] top-0 pointer-events-none whitespace-nowrap text-ods-text-primary",
|
|
1497
|
-
children: currentPlaceholder
|
|
1498
|
-
}
|
|
1499
|
-
),
|
|
1500
|
-
/* @__PURE__ */ jsx4(
|
|
1501
|
-
"div",
|
|
1502
|
-
{
|
|
1503
|
-
ref: measureRef,
|
|
1504
|
-
"aria-hidden": "true",
|
|
1505
|
-
className: "fixed -left-[9999px] top-0 flex gap-2 pointer-events-none",
|
|
1506
|
-
children: filterChips.map((chip) => /* @__PURE__ */ jsx4(
|
|
1507
|
-
Tag,
|
|
1508
|
-
{
|
|
1509
|
-
variant: chipVariantToTagVariant(chip.variant),
|
|
1510
|
-
label: chip.label,
|
|
1511
|
-
labelClassName: "truncate max-w-[120px]",
|
|
1512
|
-
onClose: () => {
|
|
1513
|
-
}
|
|
1514
|
-
},
|
|
1515
|
-
`m-${chip.id}`
|
|
1516
|
-
))
|
|
1517
|
-
}
|
|
1518
|
-
)
|
|
1519
|
-
] });
|
|
1520
|
-
}
|
|
1521
|
-
|
|
1522
|
-
export {
|
|
1523
|
-
HiddenTagsPopup,
|
|
1524
|
-
tagVariants,
|
|
1525
|
-
Tag,
|
|
1526
|
-
formatDate,
|
|
1527
|
-
formatNumber,
|
|
1528
|
-
formatPrice,
|
|
1529
|
-
formatBytes,
|
|
1530
|
-
formatBytesShort,
|
|
1531
|
-
formatFileSize,
|
|
1532
|
-
formatLargeNumber,
|
|
1533
|
-
formatAbbreviatedNumber,
|
|
1534
|
-
getFirstLastInitials,
|
|
1535
|
-
nameInitials,
|
|
1536
|
-
formatDurationMMSS,
|
|
1537
|
-
formatDurationCompact,
|
|
1538
|
-
formatTimeWithTimezone,
|
|
1539
|
-
formatDurationFromRange,
|
|
1540
|
-
formatDateUTC,
|
|
1541
|
-
formatEntryMonthUTC,
|
|
1542
|
-
formatLegalDate,
|
|
1543
|
-
formatCurrency,
|
|
1544
|
-
formatPercent,
|
|
1545
|
-
formatWholeDollars,
|
|
1546
|
-
formatCompactMetric,
|
|
1547
|
-
getTrendColors,
|
|
1548
|
-
formatDateRange,
|
|
1549
|
-
formatDateTimeAt,
|
|
1550
|
-
formatDurationFromMs,
|
|
1551
|
-
formatDuration,
|
|
1552
|
-
formatUnderscoreText,
|
|
1553
|
-
stripHtml,
|
|
1554
|
-
formatClassification,
|
|
1555
|
-
formatPricingModel,
|
|
1556
|
-
formatBioText,
|
|
1557
|
-
getProxiedImageUrl,
|
|
1558
|
-
urlPathLooksLikeSvg,
|
|
1559
|
-
shouldProxyImage,
|
|
1560
|
-
generateImageSizes,
|
|
1561
|
-
isCrossOriginUrl,
|
|
1562
|
-
decideNewTab,
|
|
1563
|
-
NEW_TAB_FEATURES,
|
|
1564
|
-
isModifierClick,
|
|
1565
|
-
stripSameOriginToPath,
|
|
1566
|
-
resolveHrefForRuntime,
|
|
1567
|
-
resolveExternalNavigation,
|
|
1568
|
-
fetchPriorityProp,
|
|
1569
|
-
PAGE_HEADING_CLASS,
|
|
1570
|
-
SECTION_HEADING_CLASS,
|
|
1571
|
-
PageHeading,
|
|
1572
|
-
COMPACT_CARD_OUTER,
|
|
1573
|
-
COMPACT_CARD_OUTER_STATIC,
|
|
1574
|
-
COMPACT_CARD_SKELETON_OUTER,
|
|
1575
|
-
COMPACT_CARD_IMAGE_SLOT,
|
|
1576
|
-
COMPACT_CARD_SKELETON_IMAGE_SLOT,
|
|
1577
|
-
COMPACT_CARD_ICON_SLOT,
|
|
1578
|
-
COMPACT_CARD_TEXT_COL,
|
|
1579
|
-
COMPACT_CARD_TITLE_ROW,
|
|
1580
|
-
COMPACT_CARD_META_ROW_BOX,
|
|
1581
|
-
COMPACT_CARD_TITLE,
|
|
1582
|
-
COMPACT_CARD_SUBTITLE,
|
|
1583
|
-
COMPACT_CARD_SUMMARY,
|
|
1584
|
-
COMPACT_CARD_META_ROW,
|
|
1585
|
-
COMPACT_CARD_ROW_FILLER,
|
|
1586
|
-
safeHref,
|
|
1587
|
-
SOURCE_ICON_NAMES,
|
|
1588
|
-
getSourceIconName,
|
|
1589
|
-
SOURCE_LABELS_BY_TABLE,
|
|
1590
|
-
getSourceLabel,
|
|
1591
|
-
DEFAULT_DOCUMENT_TYPE_TO_TABLE_ID,
|
|
1592
|
-
defaultTableIdForDocumentType,
|
|
1593
|
-
ICON_REGISTRY,
|
|
1594
|
-
normalizeIconKey,
|
|
1595
|
-
getIconComponent,
|
|
1596
|
-
getDynamicIcon,
|
|
1597
|
-
sourceRowCtxFromRuntime,
|
|
1598
|
-
resolveSourceRowCTA,
|
|
1599
|
-
resolveSourceIcon,
|
|
1600
|
-
DEFAULT_CONTENT_SUFFIXES,
|
|
1601
|
-
makeComposeContentUrl,
|
|
1602
|
-
buildDefaultHref,
|
|
1603
|
-
resolveContentHref,
|
|
1604
|
-
SearchInput
|
|
1605
|
-
};
|
|
1606
|
-
//# sourceMappingURL=chunk-FQJK446R.js.map
|