@epam/ai-dial-quotations 1.1.0-dev.405 → 1.1.0-dev.413

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.
@@ -3,11 +3,11 @@ import { useCitationCard } from '../utils/useCitationCard';
3
3
  export type CitationCardHook = ReturnType<typeof useCitationCard>;
4
4
  /** Provider that supplies `CitationCardHook` state to a citation subtree. */
5
5
  export declare const CitationCardProvider: import('react').Provider<{
6
- openPopup: (sourceUrl: string) => void;
6
+ openPopup: (groupKey: string) => void;
7
7
  closePopup: () => void;
8
- setActiveIndex: (sourceUrl: string, index: number) => void;
9
- isOpen: (sourceUrl: string) => boolean;
10
- getActiveIndex: (sourceUrl: string) => number;
8
+ setActiveIndex: (groupKey: string, index: number) => void;
9
+ isOpen: (groupKey: string) => boolean;
10
+ getActiveIndex: (groupKey: string) => number;
11
11
  } | null>;
12
12
  /** Returns the nearest `CitationCardHook` from context. Throws when used outside a `CitationCardProvider`. */
13
13
  export declare const useCitationCardContext: () => CitationCardHook;
@@ -16,25 +16,32 @@ export interface UseCitationMarkdownComponentsCallbacks {
16
16
  };
17
17
  }
18
18
  /**
19
- * Builds react-markdown component overrides that inject citation markers into
20
- * rendered paragraph text at the character offsets stored in each annotation
19
+ * Builds react-markdown component overrides that inject citation markers
20
+ * into rendered assistant message content: a `cit` element override for
21
+ * `<cit data-id="…">` tags (rendered as real elements once `rehype-raw` and
22
+ * the host's `rehype-sanitize` allowlist parse them — see
23
+ * `MarkdownRenderer`'s `baseRehypePlugins`), and `p`/`li` overrides that
24
+ * inject markers at the character offsets of every other annotation
21
25
  * group's primary selector.
22
26
  *
23
- * The `p` and `li` component overrides are stable references — they only
24
- * change when `groups` transitions between empty and non-empty. Citation card
25
- * open/close state is provided via `CitationCardContext` so that state changes
26
- * do not recreate the component functions, preventing ReactMarkdown from
27
- * unmounting and remounting the paragraph subtree on every interaction.
27
+ * Citation card open/close state is provided via `CitationCardContext` so
28
+ * that state changes do not recreate the component functions, preventing
29
+ * ReactMarkdown from unmounting and remounting the paragraph subtree on
30
+ * every interaction.
28
31
  *
29
- * Returns both the pre-processed content string (with sentinel placeholders
30
- * injected at the right offsets) and the `Components` map to pass to the
31
- * markdown renderer.
32
+ * Returns both the pre-processed content string and the `Components` map to
33
+ * pass to the markdown renderer. While `isStreaming` is true, complete
34
+ * supported `<cit data-id="…"></cit>` elements are hidden from
35
+ * `processedContent`; incomplete or otherwise unsupported `cit` markup is
36
+ * escaped and remains visible as literal text. Citation pills for supported
37
+ * `<cit>` elements only appear once the message has finished streaming,
38
+ * matching every other citation family.
32
39
  *
33
40
  * `isCompactTypography` drops the paragraph class one type-scale step, matching
34
41
  * `COMPACT_MARKDOWN_CLASS_NAMES` so cited and uncited paragraphs stay the same
35
42
  * size.
36
43
  */
37
- export declare const useCitationMarkdownComponents: (content: string, groups: AnnotationGroup[], callbacks: UseCitationMarkdownComponentsCallbacks, isCompactTypography?: boolean) => {
44
+ export declare const useCitationMarkdownComponents: (content: string, groups: AnnotationGroup[], callbacks: UseCitationMarkdownComponentsCallbacks, isStreaming?: boolean, isCompactTypography?: boolean) => {
38
45
  processedContent: string;
39
46
  markdownComponents: Components;
40
47
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useCitationMarkdownComponents.d.ts","sourceRoot":"","sources":["../../../src/hooks/useCitationMarkdownComponents/useCitationMarkdownComponents.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAErF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gDAAgD,CAAC;AAK3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAE/E,6FAA6F;AAC7F,MAAM,WAAW,sCAAsC;IACrD,4GAA4G;IAC5G,SAAS,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAChE,yEAAyE;IACzE,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9C,4FAA4F;IAC5F,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG;QACnC,UAAU,EAAE,kBAAkB,CAAC;QAC/B,YAAY,EAAE,oBAAoB,CAAC;KACpC,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,6BAA6B,GACxC,SAAS,MAAM,EACf,QAAQ,eAAe,EAAE,EACzB,WAAW,sCAAsC,EACjD,6BAA2B,KAC1B;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,UAAU,CAAA;CAsD5D,CAAC"}
1
+ {"version":3,"file":"useCitationMarkdownComponents.d.ts","sourceRoot":"","sources":["../../../src/hooks/useCitationMarkdownComponents/useCitationMarkdownComponents.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAErF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gDAAgD,CAAC;AAO3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAE/E,6FAA6F;AAC7F,MAAM,WAAW,sCAAsC;IACrD,4GAA4G;IAC5G,SAAS,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAChE,yEAAyE;IACzE,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9C,4FAA4F;IAC5F,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG;QACnC,UAAU,EAAE,kBAAkB,CAAC;QAC/B,YAAY,EAAE,oBAAoB,CAAC;KACpC,CAAC;CACH;AA2BD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,6BAA6B,GACxC,SAAS,MAAM,EACf,QAAQ,eAAe,EAAE,EACzB,WAAW,sCAAsC,EACjD,qBAAmB,EACnB,6BAA2B,KAC1B;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,UAAU,CAAA;CA8F5D,CAAC"}
package/index.d.ts CHANGED
@@ -10,10 +10,10 @@ export { useAnnotations } from './utils/useAnnotations';
10
10
  export { useCitationCard } from './utils/useCitationCard';
11
11
  export { useCitationMarkdownComponents } from './hooks/useCitationMarkdownComponents/useCitationMarkdownComponents';
12
12
  export type { UseCitationMarkdownComponentsCallbacks } from './hooks/useCitationMarkdownComponents/useCitationMarkdownComponents';
13
- export { groupAnnotationsBySource } from './utils/group-annotations-by-source';
13
+ export { groupAnnotations, groupAnnotationsByCitId, groupAnnotationsBySource, } from './utils/group-annotations-by-source';
14
14
  export type { AnnotationGroup } from './utils/group-annotations-by-source';
15
15
  export { annotationsToPdfHighlights, annotationHighlightId, normalizeRawAnnotations, resolveMessageAnnotations, } from './utils/annotation';
16
- export { injectCitationSentinels, replaceSentinelsInChildren, } from './utils/citation-injection';
16
+ export { injectCitationSentinels, replaceSentinelsInChildren, stripCitTagsWhileStreaming, } from './utils/citation-injection';
17
17
  export { isReferenceOnlyAttachment, parsePdfPageReference, getReferenceAttachmentGroups, } from './utils/reference-attachment';
18
18
  export type { PdfPageReference } from './utils/reference-attachment';
19
19
  //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AACtE,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAC5E,YAAY,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,4CAA4C,CAAC;AAEpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AAClF,YAAY,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AAG5F,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,+BAA+B,CAAC;AACvC,YAAY,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGtE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,6BAA6B,EAAE,MAAM,qEAAqE,CAAC;AACpH,YAAY,EAAE,sCAAsC,EAAE,MAAM,qEAAqE,CAAC;AAGlI,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAE3E,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,8BAA8B,CAAC;AACtC,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AACtE,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAC5E,YAAY,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,4CAA4C,CAAC;AAEpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AAClF,YAAY,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AAG5F,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,+BAA+B,CAAC;AACvC,YAAY,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGtE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,6BAA6B,EAAE,MAAM,qEAAqE,CAAC;AACpH,YAAY,EAAE,sCAAsC,EAAE,MAAM,qEAAqE,CAAC;AAGlI,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAE3E,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,8BAA8B,CAAC;AACtC,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC"}
package/index.js CHANGED
@@ -1,166 +1,175 @@
1
- import { MIMEType as e, MarkdownRenderer as t, buildCssVars as n, mergeClasses as r } from "@epam/ai-dial-chat-shared";
2
- import { DIAL_KIT_ICON_STROKE as i, ElementSize as a, EllipsisTooltip as o, GhostIconButton as s, NeutralButton as c, PrimaryButton as l, Tooltip as u } from "@epam/ai-dial-ui-kit";
3
- import { IconChevronLeft as d, IconChevronRight as f } from "@tabler/icons-react";
4
- import { createContext as p, memo as m, useCallback as h, useContext as g, useMemo as _, useState as v } from "react";
5
- import { jsx as y, jsxs as b } from "react/jsx-runtime";
6
- var x = {
1
+ import { MIMEType as e, MarkdownRenderer as t, buildCssVars as n, inferMimeTypeFromPath as r, mergeClasses as i } from "@epam/ai-dial-chat-shared";
2
+ import { DIAL_KIT_ICON_STROKE as a, ElementSize as o, EllipsisTooltip as s, GhostIconButton as c, NeutralButton as l, PrimaryButton as u, Tooltip as d } from "@epam/ai-dial-ui-kit";
3
+ import { IconChevronLeft as f, IconChevronRight as p } from "@tabler/icons-react";
4
+ import { createContext as m, memo as h, useCallback as g, useContext as _, useMemo as v, useState as y } from "react";
5
+ import { Fragment as b, jsx as x, jsxs as S } from "react/jsx-runtime";
6
+ var C = {
7
7
  card: "_card_1kph1_1",
8
8
  quote: "_quote_1kph1_5",
9
9
  title: "_title_1kph1_9",
10
10
  switcher: "_switcher_1kph1_13",
11
11
  sourceName: "_sourceName_1kph1_17"
12
- }, S = ({ group: c, activeIndex: u, onIndexChange: p, onPreview: m, onOpenInBrowser: h, headerIcon: g, labels: _, typography: v, colors: S }) => {
13
- let C = c.annotations.length, w = c.annotations[u] ?? c.primaryAnnotation, T = C > 1, E = c.primaryAnnotation.body?.source?.attachment?.type, D = m == null || E === e.HTML || E === e.XHTML, O = v?.sourceNameClassName ?? "dial-tiny-text", k = v?.titleClassName ?? "dial-body-semi-text", A = v?.quoteClassName ?? "dial-small-text", j = v?.quoteStrongClassName ?? "dial-small-semi-text", M = v?.switcherClassName ?? "dial-tiny-text", N = n({
14
- "--cc-card-bg": S?.cardBackground,
15
- "--cc-quote-text": S?.quoteText,
16
- "--cc-title-text": S?.titleText,
17
- "--cc-switcher-text": S?.switcherText,
18
- "--cc-source-name-text": S?.sourceNameText
12
+ }, w = ({ group: r, activeIndex: l, onIndexChange: d, onPreview: m, onOpenInBrowser: h, headerIcon: g, labels: _, typography: v, colors: y }) => {
13
+ let b = r.annotations.length, w = r.annotations[l] ?? r.primaryAnnotation, T = b > 1, E = r.primaryAnnotation.body?.source?.attachment?.type, D = m == null || E === e.HTML || E === e.XHTML, O = v?.sourceNameClassName ?? "dial-tiny-text", k = v?.titleClassName ?? "dial-body-semi-text", A = v?.quoteClassName ?? "dial-small-text", j = v?.quoteStrongClassName ?? "dial-small-semi-text", M = v?.switcherClassName ?? "dial-tiny-text", N = n({
14
+ "--cc-card-bg": y?.cardBackground,
15
+ "--cc-quote-text": y?.quoteText,
16
+ "--cc-title-text": y?.titleText,
17
+ "--cc-switcher-text": y?.switcherText,
18
+ "--cc-source-name-text": y?.sourceNameText
19
19
  });
20
- return /* @__PURE__ */ b("div", {
20
+ return /* @__PURE__ */ S("div", {
21
21
  role: "dialog",
22
22
  "aria-modal": "true",
23
23
  "aria-label": _.ariaLabel,
24
24
  style: N,
25
- className: r("flex w-[400px] flex-col gap-3 rounded-lg p-4 shadow-lg", x.card),
25
+ className: i("flex w-[400px] flex-col gap-3 rounded-lg p-4 shadow-lg", C.card),
26
26
  children: [
27
- /* @__PURE__ */ b("div", {
27
+ /* @__PURE__ */ S("div", {
28
28
  className: "flex items-center justify-between gap-2",
29
- children: [/* @__PURE__ */ b("div", {
29
+ children: [/* @__PURE__ */ S("div", {
30
30
  className: "flex min-w-0 items-center gap-1",
31
- children: [g, /* @__PURE__ */ y(o, {
32
- text: c.sourceName,
33
- className: r(O, "min-w-0", x.sourceName)
31
+ children: [g, /* @__PURE__ */ x(s, {
32
+ text: r.sourceName,
33
+ className: i(O, "min-w-0", C.sourceName)
34
34
  })]
35
- }), T && /* @__PURE__ */ b("div", {
35
+ }), T && /* @__PURE__ */ S("div", {
36
36
  className: "flex shrink-0 items-center gap-1",
37
37
  children: [
38
- /* @__PURE__ */ y(s, {
39
- icon: /* @__PURE__ */ y(d, {
38
+ /* @__PURE__ */ x(c, {
39
+ icon: /* @__PURE__ */ x(f, {
40
40
  size: 14,
41
41
  className: "rtl:scale-x-[-1]",
42
- stroke: i
42
+ stroke: a
43
43
  }),
44
- size: a.Small,
44
+ size: o.Small,
45
45
  "aria-label": _.previousCitation,
46
- onClick: () => p((u - 1 + C) % C)
46
+ onClick: () => d((l - 1 + b) % b)
47
47
  }),
48
- /* @__PURE__ */ y("span", {
49
- className: r(M, x.switcher),
50
- children: _.formatSwitcherText(u + 1, C)
48
+ /* @__PURE__ */ x("span", {
49
+ className: i(M, C.switcher),
50
+ children: _.formatSwitcherText(l + 1, b)
51
51
  }),
52
- /* @__PURE__ */ y(s, {
53
- icon: /* @__PURE__ */ y(f, {
52
+ /* @__PURE__ */ x(c, {
53
+ icon: /* @__PURE__ */ x(p, {
54
54
  size: 14,
55
55
  className: "rtl:scale-x-[-1]",
56
- stroke: i
56
+ stroke: a
57
57
  }),
58
- size: a.Small,
58
+ size: o.Small,
59
59
  "aria-label": _.nextCitation,
60
- onClick: () => p((u + 1) % C)
60
+ onClick: () => d((l + 1) % b)
61
61
  })
62
62
  ]
63
63
  })]
64
64
  }),
65
- (w.body?.title || w.body?.quote || T) && /* @__PURE__ */ b("div", {
65
+ (w.body?.title || w.body?.quote || T) && /* @__PURE__ */ S("div", {
66
66
  className: "flex flex-col gap-3",
67
- children: [w.body?.title && /* @__PURE__ */ y("p", {
68
- className: r(k, x.title, "break-words"),
67
+ children: [w.body?.title && /* @__PURE__ */ x("p", {
68
+ className: i(k, C.title, "break-words"),
69
69
  children: w.body.title
70
- }), (w.body?.quote || T) && /* @__PURE__ */ y("div", {
71
- className: r(A, x.quote, "line-clamp-6 break-words", T && "min-h-[3lh]"),
72
- children: w.body?.quote && /* @__PURE__ */ y(t, {
70
+ }), (w.body?.quote || T) && /* @__PURE__ */ x("div", {
71
+ className: i(A, C.quote, "line-clamp-6 break-words", T && "min-h-[3lh]"),
72
+ children: w.body?.quote && /* @__PURE__ */ x(t, {
73
73
  content: w.body.quote,
74
74
  classNames: {
75
- p: r(A, x.quote),
76
- ul: r(A, "ps-3"),
77
- ol: r(A, "ps-3"),
75
+ p: i(A, C.quote),
76
+ ul: i(A, "ps-3"),
77
+ ol: i(A, "ps-3"),
78
78
  strong: j
79
79
  }
80
80
  })
81
81
  })]
82
82
  }),
83
- /* @__PURE__ */ b("div", {
83
+ /* @__PURE__ */ S("div", {
84
84
  className: "flex justify-start gap-2",
85
- children: [m && /* @__PURE__ */ y(l, {
85
+ children: [m && /* @__PURE__ */ x(u, {
86
86
  label: _.preview,
87
- size: a.Small,
87
+ size: o.Small,
88
88
  onClick: () => m(w)
89
- }), /* @__PURE__ */ y(l, {
89
+ }), /* @__PURE__ */ x(u, {
90
90
  label: D ? _.openInBrowser : _.download,
91
- size: a.Small,
91
+ size: o.Small,
92
92
  onClick: () => h(w)
93
93
  })]
94
94
  })
95
95
  ]
96
96
  });
97
97
  };
98
- m(S);
98
+ h(w);
99
99
  //#endregion
100
100
  //#region src/components/CitationMarker/CitationMarker.tsx
101
- var C = ({ annotationCount: e, onOpen: t, icon: n, labels: r, labelClassName: i = "dial-caption-text" }) => {
102
- let o = /* @__PURE__ */ b("span", {
101
+ var T = ({ annotationCount: e, onOpen: t, icon: n, labels: r, labelClassName: i = "dial-caption-text" }) => {
102
+ let a = /* @__PURE__ */ S("span", {
103
103
  className: "flex items-center gap-1",
104
- children: [n, /* @__PURE__ */ y("span", {
104
+ children: [n, /* @__PURE__ */ x("span", {
105
105
  className: i,
106
106
  children: e > 1 ? r.labelWithOverflow : r.label
107
107
  })]
108
108
  });
109
- return /* @__PURE__ */ y(c, {
110
- size: a.Small,
111
- label: o,
109
+ return /* @__PURE__ */ x(l, {
110
+ size: o.Small,
111
+ label: a,
112
112
  "aria-label": r.ariaLabel,
113
113
  onClick: t
114
114
  });
115
115
  };
116
- m(C);
116
+ h(T);
117
117
  //#endregion
118
118
  //#region src/context/CitationCardContext.tsx
119
- var w = p(null), T = w.Provider, E = () => {
120
- let e = g(w);
119
+ var E = m(null), D = E.Provider, O = () => {
120
+ let e = _(E);
121
121
  if (e == null) throw Error("useCitationCardContext must be used within a CitationCardProvider");
122
122
  return e;
123
- }, D = { content: "_content_xzs0h_1" }, O = ({ group: e, onPreview: t, onOpenInBrowser: n, icon: i, headerIcon: a, cardLabels: o, markerLabels: s, cardTypography: c, markerLabelClassName: l }) => {
124
- let d = E(), f = d.isOpen(e.sourceUrl), p = d.getActiveIndex(e.sourceUrl), m = h((e) => {
125
- e || d.closePopup();
126
- }, [d]), g = _(() => t ? (e) => {
127
- t(e), d.closePopup();
128
- } : void 0, [t, d]);
129
- return /* @__PURE__ */ y(u, {
123
+ }, k = { content: "_content_xzs0h_1" }, A = ({ group: e, onPreview: t, onOpenInBrowser: n, icon: r, headerIcon: a, cardLabels: o, markerLabels: s, cardTypography: c, markerLabelClassName: l }) => {
124
+ let u = O(), f = u.isOpen(e.groupKey), p = u.getActiveIndex(e.groupKey), m = g((e) => {
125
+ e || u.closePopup();
126
+ }, [u]), h = v(() => t ? (e) => {
127
+ t(e), u.closePopup();
128
+ } : void 0, [t, u]);
129
+ return /* @__PURE__ */ x(d, {
130
130
  open: f,
131
131
  onOpenChange: m,
132
132
  triggerClassName: "ms-1 inline-flex align-middle",
133
- contentClassName: r("!p-0 !bg-transparent !border-0 !shadow-none !max-w-none !rounded-none", D.content),
134
- tooltip: /* @__PURE__ */ y(S, {
133
+ contentClassName: i("!p-0 !bg-transparent !border-0 !shadow-none !max-w-none !rounded-none", k.content),
134
+ tooltip: /* @__PURE__ */ x(w, {
135
135
  group: e,
136
136
  activeIndex: p,
137
- onIndexChange: (t) => d.setActiveIndex(e.sourceUrl, t),
138
- onPreview: g,
137
+ onIndexChange: (t) => u.setActiveIndex(e.groupKey, t),
138
+ onPreview: h,
139
139
  onOpenInBrowser: n,
140
140
  headerIcon: a,
141
141
  labels: o,
142
142
  typography: c
143
143
  }),
144
- children: /* @__PURE__ */ y(C, {
144
+ children: /* @__PURE__ */ x(T, {
145
145
  sourceName: e.sourceName,
146
146
  annotationCount: e.annotations.length,
147
- onOpen: () => d.openPopup(e.sourceUrl),
148
- icon: i,
147
+ onOpen: () => u.openPopup(e.groupKey),
148
+ icon: r,
149
149
  labels: s,
150
150
  labelClassName: l
151
151
  })
152
152
  });
153
153
  };
154
- m(O);
154
+ h(A);
155
155
  //#endregion
156
156
  //#region src/utils/annotation.ts
157
- var k = {
157
+ var j = {
158
158
  backgroundColor: "transparent",
159
159
  borderColor: "var(--stroke-accent, #1D4ED8)",
160
160
  borderWidth: "2px",
161
161
  opacity: .5,
162
162
  hoverOpacity: .5
163
- }, A = (e) => e.flatMap((e, t) => {
163
+ }, M = {
164
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
165
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
166
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
167
+ }, N = (e) => {
168
+ let t = r(e);
169
+ if (t != null) return t;
170
+ let n = e.split(/[?#]/)[0], i = n.lastIndexOf(".");
171
+ if (i !== -1) return M[n.slice(i + 1).toLowerCase()];
172
+ }, P = (e) => e.flatMap((e, t) => {
164
173
  let n = e.body?.selector;
165
174
  if (n == null) return [];
166
175
  let r = (Array.isArray(n) ? n : [n]).flatMap((e) => {
@@ -177,74 +186,133 @@ var k = {
177
186
  return r.length === 0 ? [] : [{
178
187
  id: String(e.index ?? t),
179
188
  bboxes: r,
180
- style: k
189
+ style: j
181
190
  }];
182
- }), j = (e, t) => String(e.index ?? t), M = (e) => typeof e == "number" ? e : null, N = (e) => {
191
+ }), F = (e, t) => String(e.index ?? t), I = (e) => typeof e == "number" ? e : null, L = (e) => {
183
192
  if (typeof e != "object" || !e) return null;
184
193
  let t = e;
185
194
  if (t.type !== "pdf_region") return null;
186
195
  let n = t.bbox;
187
196
  if (typeof n != "object" || !n) return null;
188
- let r = n, i = M(r.left), a = M(r.top), o = M(r.width), s = M(r.height);
197
+ let r = n, i = I(r.left), a = I(r.top), o = I(r.width), s = I(r.height);
189
198
  return i === null || a === null || o === null || s === null ? null : {
190
199
  type: "pdf_bbox",
191
- page: M(t.page) ?? 1,
200
+ page: I(t.page) ?? 1,
192
201
  x1: i,
193
202
  y1: a,
194
203
  x2: i + o,
195
204
  y2: a + s
196
205
  };
197
- }, P = (t, n) => t.flatMap((t) => {
198
- if (typeof t != "object" || !t) return [];
199
- let r = t, i = r.target;
200
- if (typeof i != "object" || !i) return [];
201
- let a = i, o = a.source;
202
- if (typeof o != "object" || !o) return [];
203
- let s = M(o.attachment_index);
204
- if (s === null) return [];
205
- let c = n.find((e) => e.index === s);
206
- if (c?.url == null) return [];
207
- let l = N(a.selector);
208
- if (l === null) return [];
209
- let u = r.body, d = typeof u == "object" && u ? u : {}, f = typeof d.title == "string" ? d.title : void 0, p = typeof d.quote == "string" ? d.quote : void 0;
210
- return [{
211
- index: M(r.index) ?? void 0,
206
+ }, ee = (t, n) => {
207
+ let r = t.target;
208
+ if (typeof r != "object" || !r) return null;
209
+ let i = r, a = i.source;
210
+ if (typeof a != "object" || !a) return null;
211
+ let o = I(a.attachment_index);
212
+ if (o === null) return null;
213
+ let s = n.find((e) => e.index === o);
214
+ if (s?.url == null) return null;
215
+ let c = L(i.selector);
216
+ if (c === null) return null;
217
+ let l = t.body, u = typeof l == "object" && l ? l : {}, d = typeof u.title == "string" ? u.title : void 0, f = typeof u.quote == "string" ? u.quote : void 0;
218
+ return {
219
+ index: I(t.index) ?? void 0,
212
220
  body: {
213
- title: f,
214
- quote: p,
221
+ title: d,
222
+ quote: f,
215
223
  source: {
216
224
  type: "attachment",
217
225
  attachment: {
218
- type: c.type ?? e.PDF,
219
- url: c.url,
220
- title: c.title
226
+ type: s.type ?? e.PDF,
227
+ url: s.url,
228
+ title: s.title
221
229
  }
222
230
  },
223
- selector: l
231
+ selector: c
224
232
  }
225
- }];
226
- }), F = (e) => {
233
+ };
234
+ }, te = (t) => {
235
+ let n = t.target;
236
+ if (typeof n != "object" || !n) return null;
237
+ let r = n.selector;
238
+ if (typeof r != "object" || !r) return null;
239
+ let i = r;
240
+ if (i.type !== "html_tag" || typeof i.tag != "string" || typeof i.id != "string") return null;
241
+ let a = {
242
+ type: "html_tag",
243
+ tag: i.tag,
244
+ id: i.id
245
+ }, o = t.body;
246
+ if (typeof o != "object" || !o) return null;
247
+ let s = o, c = s.source;
248
+ if (typeof c != "object" || !c) return null;
249
+ let l = c;
250
+ if (l.type !== "attachment") return null;
251
+ let u = l.url;
252
+ if (typeof u != "string") return null;
253
+ let d = typeof s.title == "string" ? s.title : void 0, f = typeof s.quote == "string" ? s.quote : void 0;
254
+ return {
255
+ target: { selector: a },
256
+ body: {
257
+ title: d,
258
+ quote: f,
259
+ source: {
260
+ type: "attachment",
261
+ attachment: {
262
+ type: N(u) ?? e.PDF,
263
+ url: u,
264
+ title: d
265
+ }
266
+ }
267
+ }
268
+ };
269
+ }, R = (e) => {
270
+ if (e.target?.selector?.type !== "html_tag") return e;
271
+ let t = e.body?.source?.attachment;
272
+ if (t?.url == null) return e;
273
+ let n = N(t.url);
274
+ return n == null || n === t.type ? e : {
275
+ ...e,
276
+ body: {
277
+ ...e.body,
278
+ source: {
279
+ ...e.body?.source,
280
+ type: "attachment",
281
+ attachment: {
282
+ ...t,
283
+ type: n
284
+ }
285
+ }
286
+ }
287
+ };
288
+ }, z = (e, t) => e.flatMap((e) => {
289
+ if (typeof e != "object" || !e) return [];
290
+ let n = e, r = te(n);
291
+ if (r) return [r];
292
+ let i = ee(n, t);
293
+ return i ? [i] : [];
294
+ }), B = (e) => {
227
295
  let t = e.custom_content?.annotations;
228
- if (t?.length) return t.filter((e) => e != null && e.body?.source?.attachment?.url != null);
296
+ if (t?.length) return t.filter((e) => e != null && e.body?.source?.attachment?.url != null).map(R);
229
297
  let n = e.custom_fields;
230
298
  if (typeof n != "object" || !n) return [];
231
299
  let r = n.annotations;
232
- return !Array.isArray(r) || r.length === 0 ? [] : P(r, e.custom_content?.attachments ?? []);
233
- }, I = (e, t) => _(() => t ? [] : F(e), [t, e]), L = {
234
- openGroupSourceUrl: null,
300
+ return !Array.isArray(r) || r.length === 0 ? [] : z(r, e.custom_content?.attachments ?? []).map(R);
301
+ }, ne = (e, t) => v(() => t ? [] : B(e), [t, e]), re = {
302
+ openGroupKey: null,
235
303
  activeIndexByGroup: {}
236
- }, R = () => {
237
- let [e, t] = v(L), n = h((e) => {
304
+ }, ie = () => {
305
+ let [e, t] = y(re), n = g((e) => {
238
306
  t((t) => ({
239
307
  ...t,
240
- openGroupSourceUrl: e
308
+ openGroupKey: e
241
309
  }));
242
- }, []), r = h(() => {
310
+ }, []), r = g(() => {
243
311
  t((e) => ({
244
312
  ...e,
245
- openGroupSourceUrl: null
313
+ openGroupKey: null
246
314
  }));
247
- }, []), i = h((e, n) => {
315
+ }, []), i = g((e, n) => {
248
316
  t((t) => ({
249
317
  ...t,
250
318
  activeIndexByGroup: {
@@ -253,11 +321,11 @@ var k = {
253
321
  }
254
322
  }));
255
323
  }, []);
256
- return _(() => ({
324
+ return v(() => ({
257
325
  openPopup: n,
258
326
  closePopup: r,
259
327
  setActiveIndex: i,
260
- isOpen: (t) => e.openGroupSourceUrl === t,
328
+ isOpen: (t) => e.openGroupKey === t,
261
329
  getActiveIndex: (t) => e.activeIndexByGroup[t] ?? 0
262
330
  }), [
263
331
  n,
@@ -265,8 +333,11 @@ var k = {
265
333
  i,
266
334
  e
267
335
  ]);
268
- }, z = /⟦C(\d+)⟧/g, B = (e, t) => {
269
- let n = t.map((t, n) => {
336
+ }, ae = /⟦C(\d+)⟧/g, V = (e, t) => {
337
+ let n = t.map((e, t) => ({
338
+ g: e,
339
+ idx: t
340
+ })).filter(({ g: e }) => e.primaryAnnotation.target?.selector?.type !== "html_tag").map(({ g: t, idx: n }) => {
270
341
  let r = t.primaryAnnotation.target?.selector, i = typeof r == "object" && r && "type" in r && r.type === "text_character_range" ? r.end : e.length;
271
342
  return {
272
343
  idx: n,
@@ -275,9 +346,9 @@ var k = {
275
346
  }).sort((e, t) => t.pos - e.pos), r = e;
276
347
  for (let { idx: e, pos: t } of n) r = `${r.slice(0, t)}⟦C${e}⟧${r.slice(t)}`;
277
348
  return r;
278
- }, V = (e, t) => {
349
+ }, oe = /<cit\s+data-id=(?:"[^"]+"|'[^']+')\s*>\s*<\/cit>/g, se = /^<cit\s+data-id=(?:"[^"]+"|'[^']+')\s*>\s*<\/cit>$/, H = /<cit\s+data-id=(?:"[^"]+"|'[^']+')\s*>\s*<\/cit>|<\/?cit\b[^>]*>|<\/?cit\b[^>]*$/gi, U = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"), W = (e) => e.replace(H, (e) => se.test(e) ? e : U(e)), G = (e) => W(e).replace(oe, ""), K = (e, t) => {
279
350
  if (typeof e == "string") {
280
- let n = e.split(z);
351
+ let n = e.split(ae);
281
352
  if (n.length === 1) return e;
282
353
  let r = [];
283
354
  return n.forEach((e, n) => {
@@ -285,82 +356,125 @@ var k = {
285
356
  }), r;
286
357
  }
287
358
  return Array.isArray(e) ? e.flatMap((e) => {
288
- let n = V(e, t);
359
+ let n = K(e, t);
289
360
  return Array.isArray(n) ? n : [n];
290
361
  }) : e;
291
- }, H = (e, t, n, i = !1) => {
292
- let { onPreview: a, onOpenInBrowser: o, buildLabels: s } = n;
362
+ }, ce = (e) => {
363
+ let t = e.primaryAnnotation.target?.selector;
364
+ return t?.type === "html_tag" ? t.id : void 0;
365
+ }, le = (e, t) => /* @__PURE__ */ S(b, { children: [
366
+ e == null ? "<cit>" : `<cit data-id="${e}">`,
367
+ t,
368
+ "</cit>"
369
+ ] }), ue = (e, t, n, r = !1, a = !1) => {
370
+ let { onPreview: o, onOpenInBrowser: s, buildLabels: c } = n, l = v(() => r ? G(e) : W(t.length > 0 ? V(e, t) : e), [
371
+ e,
372
+ t,
373
+ r
374
+ ]), u = l.includes("<cit");
293
375
  return {
294
- processedContent: _(() => t.length > 0 ? B(e, t) : e, [e, t]),
295
- markdownComponents: _(() => {
296
- if (t.length === 0) return {};
297
- let e = (e) => {
298
- let n = t[e];
299
- if (!n) return null;
300
- let { cardLabels: r, markerLabels: i } = s(n);
301
- return /* @__PURE__ */ y(O, {
302
- group: n,
303
- onPreview: (e) => a(e, n),
304
- onOpenInBrowser: o,
305
- cardLabels: r,
306
- markerLabels: i
307
- }, `citation-${n.sourceUrl}`);
308
- };
309
- return {
310
- p: ({ children: t, ...n }) => /* @__PURE__ */ y("p", {
311
- ...n,
312
- className: r(i ? "dial-small-paragraph-text" : "dial-body-paragraph-text", "mb-3 [overflow-wrap:anywhere] [text-wrap:pretty] last:mb-0"),
313
- children: V(t, e)
376
+ processedContent: l,
377
+ markdownComponents: v(() => {
378
+ let e = /* @__PURE__ */ new Map();
379
+ for (let n of t) {
380
+ let t = ce(n);
381
+ t != null && e.set(t, n);
382
+ }
383
+ let n = (e) => {
384
+ let { cardLabels: t, markerLabels: n } = c(e);
385
+ return /* @__PURE__ */ x(A, {
386
+ group: e,
387
+ onPreview: (t) => o(t, e),
388
+ onOpenInBrowser: s,
389
+ cardLabels: t,
390
+ markerLabels: n
391
+ }, `citation-${e.groupKey}`);
392
+ }, r = (e) => {
393
+ let r = t[e];
394
+ return r ? n(r) : null;
395
+ }, l = { cit: (t) => {
396
+ let r = t["data-id"] == null ? void 0 : e.get(t["data-id"]);
397
+ return r ? n(r) : le(t["data-id"], t.children);
398
+ } };
399
+ return t.length === 0 ? u ? l : {} : {
400
+ ...l,
401
+ p: ({ children: e, ...t }) => /* @__PURE__ */ x("p", {
402
+ ...t,
403
+ className: i(a ? "dial-small-paragraph-text" : "dial-body-paragraph-text", "mb-3 [overflow-wrap:anywhere] [text-wrap:pretty] last:mb-0"),
404
+ children: K(e, r)
314
405
  }),
315
- li: ({ children: t, ...n }) => /* @__PURE__ */ y("li", {
316
- ...n,
406
+ li: ({ children: e, ...t }) => /* @__PURE__ */ x("li", {
407
+ ...t,
317
408
  className: "mb-1.5 last:mb-0",
318
- children: V(t, e)
409
+ children: K(e, r)
319
410
  })
320
411
  };
321
412
  }, [
322
413
  t,
323
- a,
324
414
  o,
325
415
  s,
326
- i
416
+ c,
417
+ a,
418
+ u
327
419
  ])
328
420
  };
329
- }, U = (e) => {
421
+ }, q = (e) => {
330
422
  try {
331
423
  return decodeURIComponent(e);
332
424
  } catch {
333
425
  return e;
334
426
  }
335
- }, W = (e) => {
427
+ }, de = (e) => {
336
428
  try {
337
429
  let t = new URL(e);
338
- return t.pathname.split("/").map((e) => U(e)).filter(Boolean).at(-1) ?? t.hostname;
430
+ return t.pathname.split("/").map((e) => q(e)).filter(Boolean).at(-1) ?? t.hostname;
339
431
  } catch {
340
- return e.split("/").map((e) => U(e)).filter(Boolean).at(-1) ?? e;
432
+ return e.split("/").map((e) => q(e)).filter(Boolean).at(-1) ?? e;
341
433
  }
342
- }, G = (e) => {
434
+ }, J = (e, t) => e.body?.source?.attachment?.title ?? de(t), Y = (e) => {
435
+ let t = e.target?.selector;
436
+ return t?.type === "html_tag" ? t : void 0;
437
+ }, fe = (e) => Y(e) != null, X = (e) => {
343
438
  let t = /* @__PURE__ */ new Map();
344
439
  for (let n of e) {
440
+ if (fe(n)) continue;
345
441
  let e = n.body?.source?.attachment?.url;
346
442
  if (e == null) continue;
347
443
  let r = t.get(e);
348
444
  r ? r.annotations.push(n) : t.set(e, {
445
+ groupKey: e,
349
446
  sourceUrl: e,
350
- sourceName: n.body?.source?.attachment?.title ?? W(e),
447
+ sourceName: J(n, e),
448
+ annotations: [n],
449
+ primaryAnnotation: n
450
+ });
451
+ }
452
+ return Array.from(t.values());
453
+ }, Z = (e) => {
454
+ let t = /* @__PURE__ */ new Map();
455
+ for (let n of e) {
456
+ let e = Y(n)?.id;
457
+ if (e == null) continue;
458
+ let r = n.body?.source?.attachment?.url;
459
+ if (r == null) continue;
460
+ let i = t.get(e);
461
+ i ? i.annotations.push(n) : t.set(e, {
462
+ groupKey: `cit:${e}`,
463
+ sourceUrl: r,
464
+ sourceName: J(n, r),
351
465
  annotations: [n],
352
466
  primaryAnnotation: n
353
467
  });
354
468
  }
355
469
  return Array.from(t.values());
356
- }, K = (e) => e.url == null && e.reference_url != null, q = /^(.*\.pdf)(?:#page=(\d+))?$/i, J = (e) => {
357
- let t = q.exec(e);
470
+ }, pe = (e) => [...Z(e), ...X(e)], Q = (e) => e.url == null && e.reference_url != null, me = /^(.*\.pdf)(?:#page=(\d+))?$/i, $ = (e) => {
471
+ let t = me.exec(e);
358
472
  return t ? {
359
473
  baseUrl: t[1],
360
474
  page: t[2] == null ? null : Number(t[2])
361
475
  } : null;
362
- }, Y = (t) => G((t ?? []).filter(K).map((t) => {
363
- let n = t.reference_url, r = J(n) != null;
476
+ }, he = (t) => X((t ?? []).filter(Q).map((t) => {
477
+ let n = t.reference_url, r = $(n) != null;
364
478
  return { body: {
365
479
  quote: t.data,
366
480
  source: {
@@ -374,4 +488,4 @@ var k = {
374
488
  } };
375
489
  }));
376
490
  //#endregion
377
- export { S as CitationCard, T as CitationCardProvider, O as CitationDropdown, C as CitationMarker, j as annotationHighlightId, A as annotationsToPdfHighlights, Y as getReferenceAttachmentGroups, G as groupAnnotationsBySource, B as injectCitationSentinels, K as isReferenceOnlyAttachment, P as normalizeRawAnnotations, J as parsePdfPageReference, V as replaceSentinelsInChildren, F as resolveMessageAnnotations, I as useAnnotations, R as useCitationCard, E as useCitationCardContext, H as useCitationMarkdownComponents };
491
+ export { w as CitationCard, D as CitationCardProvider, A as CitationDropdown, T as CitationMarker, F as annotationHighlightId, P as annotationsToPdfHighlights, he as getReferenceAttachmentGroups, pe as groupAnnotations, Z as groupAnnotationsByCitId, X as groupAnnotationsBySource, V as injectCitationSentinels, Q as isReferenceOnlyAttachment, z as normalizeRawAnnotations, $ as parsePdfPageReference, K as replaceSentinelsInChildren, B as resolveMessageAnnotations, G as stripCitTagsWhileStreaming, ne as useAnnotations, ie as useCitationCard, O as useCitationCardContext, ue as useCitationMarkdownComponents };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@epam/ai-dial-quotations",
3
3
  "description": "Citation and annotation components, hooks, and utilities for AI DIAL conversations",
4
- "version": "1.1.0-dev.405",
4
+ "version": "1.1.0-dev.413",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "main": "./index.js",
@@ -19,7 +19,7 @@
19
19
  "react": "^19.0.0",
20
20
  "react-markdown": "^10.1.0",
21
21
  "@tabler/icons-react": "^3.0.0",
22
- "@epam/ai-dial-chat-shared": "1.1.0-dev.405",
22
+ "@epam/ai-dial-chat-shared": "1.1.0-dev.413",
23
23
  "@epam/ai-dial-ui-kit": "*",
24
24
  "@epam/pdf-highlighter-kit": ">=0.0.14"
25
25
  },
@@ -13,13 +13,17 @@ export declare const annotationHighlightId: (annotation: Annotation, fallbackInd
13
13
  * Normalizes raw annotations from the API wire format (stored in
14
14
  * `message.custom_fields.annotations`) to the internal `Annotation` model.
15
15
  *
16
- * The API format uses `target.source.attachment_index` (integer) and a
17
- * `pdf_region` selector with `{ left, top, width, height }` coordinates.
18
- * The internal model uses `body.source.attachment.url` (resolved URL) and a
19
- * `pdf_bbox` selector with `{ x1, y1, x2, y2 }` coordinates.
16
+ * Recognizes two wire shapes:
17
+ * - `target.source.attachment_index` (integer) + a `pdf_region` selector
18
+ * with `{ left, top, width, height }` coordinates, resolved against
19
+ * `attachments` and converted to `body.source.attachment.url` + a
20
+ * `pdf_bbox` selector with `{ x1, y1, x2, y2 }` coordinates.
21
+ * - `target.selector` of type `html_tag` (`{ tag, id }`) with a flat
22
+ * `body.source = { type: 'attachment', url }` — normalized to
23
+ * `body.source.attachment.url`/`.title` directly, with no attachment-list
24
+ * lookup and no `index`.
20
25
  *
21
- * Annotations whose attachment index cannot be resolved or whose selector
22
- * is not a recognised PDF region are omitted from the result.
26
+ * Annotations matching neither shape are omitted from the result.
23
27
  */
24
28
  export declare const normalizeRawAnnotations: (rawAnnotations: unknown[], attachments: MessageAttachment[]) => Annotation[];
25
29
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"annotation.d.ts","sourceRoot":"","sources":["../../src/utils/annotation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,OAAO,EACP,iBAAiB,EAElB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAEV,kBAAkB,EACnB,MAAM,2BAA2B,CAAC;AAUnC;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,GACrC,aAAa,UAAU,EAAE,KACxB,kBAAkB,EAoBjB,CAAC;AAEL,oHAAoH;AACpH,eAAO,MAAM,qBAAqB,GAChC,YAAY,UAAU,EACtB,eAAe,MAAM,KACpB,MAAmD,CAAC;AA+BvD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,uBAAuB,GAClC,gBAAgB,OAAO,EAAE,EACzB,aAAa,iBAAiB,EAAE,KAC/B,UAAU,EAmDT,CAAC;AAEL;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GAAI,SAAS,OAAO,KAAG,UAAU,EAkBtE,CAAC"}
1
+ {"version":3,"file":"annotation.d.ts","sourceRoot":"","sources":["../../src/utils/annotation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EAEV,OAAO,EACP,iBAAiB,EAElB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAEV,kBAAkB,EACnB,MAAM,2BAA2B,CAAC;AA2BnC;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,GACrC,aAAa,UAAU,EAAE,KACxB,kBAAkB,EAoBjB,CAAC;AAEL,oHAAoH;AACpH,eAAO,MAAM,qBAAqB,GAChC,YAAY,UAAU,EACtB,eAAe,MAAM,KACpB,MAAmD,CAAC;AAyKvD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,uBAAuB,GAClC,gBAAgB,OAAO,EAAE,EACzB,aAAa,iBAAiB,EAAE,KAC/B,UAAU,EAeT,CAAC;AAEL;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GAAI,SAAS,OAAO,KAAG,UAAU,EAoBtE,CAAC"}
@@ -2,10 +2,26 @@ import { ReactNode } from 'react';
2
2
  import { AnnotationGroup } from './group-annotations-by-source';
3
3
  /**
4
4
  * Inserts sentinel strings into `content` at the `end` character offsets of
5
- * each annotation group's primary selector. Offsets are processed in
6
- * descending order so earlier insertions do not shift later ones.
5
+ * each non-`html_tag` annotation group's primary selector (descending order
6
+ * so earlier insertions don't shift later ones). Sentinel indices are the
7
+ * group's position in the original flat `groups` array, so a caller doing
8
+ * `groups[idx]` still resolves correctly even though `html_tag` groups are
9
+ * skipped here — those render as real `<cit>` elements instead (see
10
+ * `useCitationMarkdownComponents`'s `cit` component override).
7
11
  */
8
12
  export declare const injectCitationSentinels: (content: string, groups: AnnotationGroup[]) => string;
13
+ /**
14
+ * Leaves the one supported paired citation element parseable as HTML and
15
+ * escapes every other `cit` shape so Markdown renders the original markup as
16
+ * visible text. Unsupported markup is never interpreted as a citation.
17
+ */
18
+ export declare const escapeUnsupportedCitTags: (content: string) => string;
19
+ /**
20
+ * Hides supported paired citation elements while the message is streaming.
21
+ * Every other `cit` shape is escaped and remains visible as ordinary text,
22
+ * preventing an incomplete opening tag from swallowing the streamed suffix.
23
+ */
24
+ export declare const stripCitTagsWhileStreaming: (content: string) => string;
9
25
  /**
10
26
  * Recursively walks a React child tree and replaces sentinel strings with
11
27
  * the result of `renderMarker(idx)`. Handles string children, arrays, and
@@ -1 +1 @@
1
- {"version":3,"file":"citation-injection.d.ts","sourceRoot":"","sources":["../../src/utils/citation-injection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAUrE;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAClC,SAAS,MAAM,EACf,QAAQ,eAAe,EAAE,KACxB,MAoBF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,GACrC,UAAU,SAAS,EACnB,cAAc,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,KACvC,SA0BF,CAAC"}
1
+ {"version":3,"file":"citation-injection.d.ts","sourceRoot":"","sources":["../../src/utils/citation-injection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAUrE;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,GAClC,SAAS,MAAM,EACf,QAAQ,eAAe,EAAE,KACxB,MAwBF,CAAC;AAmBF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GAAI,SAAS,MAAM,KAAG,MAGxD,CAAC;AAEJ;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,GAAI,SAAS,MAAM,KAAG,MAE5D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,GACrC,UAAU,SAAS,EACnB,cAAc,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,KACvC,SA0BF,CAAC"}
@@ -1,7 +1,14 @@
1
1
  import { Annotation } from '@epam/ai-dial-chat-shared';
2
- /** A set of annotations that all cite the same source document. */
2
+ /** A set of annotations rendered behind one inline citation marker. */
3
3
  export interface AnnotationGroup {
4
- /** The attachment URL shared by all annotations in this group. */
4
+ /**
5
+ * This group's identity — used for open/active-index popup state and
6
+ * React keys. Equals `sourceUrl` for a `groupAnnotationsBySource` group;
7
+ * equals `` `cit:${id}` `` for a `groupAnnotationsByCitId` group, so two
8
+ * cit ids citing the same document never share popup state.
9
+ */
10
+ groupKey: string;
11
+ /** The cited attachment's URL — used for Preview/Download. */
5
12
  sourceUrl: string;
6
13
  /**
7
14
  * Human-readable name derived from the URL: the last non-empty path segment
@@ -13,6 +20,25 @@ export interface AnnotationGroup {
13
20
  /** The first annotation in the group — used for the inline citation marker position. */
14
21
  primaryAnnotation: Annotation;
15
22
  }
16
- /** Groups annotations by their source attachment URL. Annotations without a `body.source.attachment.url` are excluded. */
23
+ /**
24
+ * Groups annotations by their source attachment URL. Annotations without a
25
+ * `body.source.attachment.url` are excluded, as are `html_tag`-selector
26
+ * annotations — those are grouped by tag id instead, see
27
+ * `groupAnnotationsByCitId`.
28
+ */
17
29
  export declare const groupAnnotationsBySource: (annotations: Annotation[]) => AnnotationGroup[];
30
+ /**
31
+ * Groups `html_tag`-selector annotations by `target.selector.id`, one group
32
+ * per distinct tag id — never collapsing two different ids that cite the
33
+ * same source document into one group. Annotations without
34
+ * `target.selector.id` or without `body.source.attachment.url` are excluded.
35
+ */
36
+ export declare const groupAnnotationsByCitId: (annotations: Annotation[]) => AnnotationGroup[];
37
+ /**
38
+ * Partitions annotations by selector type and groups each family with its
39
+ * own algorithm: `html_tag` annotations via `groupAnnotationsByCitId`, every
40
+ * other annotation via `groupAnnotationsBySource`. Lets a host render
41
+ * citations without branching on selector type itself.
42
+ */
43
+ export declare const groupAnnotations: (annotations: Annotation[]) => AnnotationGroup[];
18
44
  //# sourceMappingURL=group-annotations-by-source.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"group-annotations-by-source.d.ts","sourceRoot":"","sources":["../../src/utils/group-annotations-by-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,mEAAmE;AACnE,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,wFAAwF;IACxF,iBAAiB,EAAE,UAAU,CAAC;CAC/B;AA2BD,0HAA0H;AAC1H,eAAO,MAAM,wBAAwB,GACnC,aAAa,UAAU,EAAE,KACxB,eAAe,EAsBjB,CAAC"}
1
+ {"version":3,"file":"group-annotations-by-source.d.ts","sourceRoot":"","sources":["../../src/utils/group-annotations-by-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,2BAA2B,CAAC;AAE7E,uEAAuE;AACvE,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,wFAAwF;IACxF,iBAAiB,EAAE,UAAU,CAAC;CAC/B;AAkDD;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,GACnC,aAAa,UAAU,EAAE,KACxB,eAAe,EAuBjB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAClC,aAAa,UAAU,EAAE,KACxB,eAAe,EAwBjB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAC3B,aAAa,UAAU,EAAE,KACxB,eAAe,EAGjB,CAAC"}
@@ -1,12 +1,15 @@
1
1
  /**
2
2
  * Manages open/close state and per-group active annotation index for citation
3
- * cards within a single assistant message.
3
+ * cards within a single assistant message. State is keyed by
4
+ * `AnnotationGroup.groupKey`, not `sourceUrl` — two groups can share a
5
+ * `sourceUrl` (e.g. two `cit`-id groups citing the same document) while
6
+ * having independent popup/switcher state.
4
7
  */
5
8
  export declare const useCitationCard: () => {
6
- openPopup: (sourceUrl: string) => void;
9
+ openPopup: (groupKey: string) => void;
7
10
  closePopup: () => void;
8
- setActiveIndex: (sourceUrl: string, index: number) => void;
9
- isOpen: (sourceUrl: string) => boolean;
10
- getActiveIndex: (sourceUrl: string) => number;
11
+ setActiveIndex: (groupKey: string, index: number) => void;
12
+ isOpen: (groupKey: string) => boolean;
13
+ getActiveIndex: (groupKey: string) => number;
11
14
  };
12
15
  //# sourceMappingURL=useCitationCard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useCitationCard.d.ts","sourceRoot":"","sources":["../../src/utils/useCitationCard.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,eAAO,MAAM,eAAe;2BAGgB,MAAM;;gCAQD,MAAM,SAAS,MAAM;wBAY5C,MAAM;gCACE,MAAM;CAKvC,CAAC"}
1
+ {"version":3,"file":"useCitationCard.d.ts","sourceRoot":"","sources":["../../src/utils/useCitationCard.ts"],"names":[],"mappings":"AAcA;;;;;;GAMG;AACH,eAAO,MAAM,eAAe;0BAGe,MAAM;;+BAQD,MAAM,SAAS,MAAM;uBAY5C,MAAM;+BACE,MAAM;CAKtC,CAAC"}