@epam/ai-dial-quotations 1.1.0-dev.99 → 1.2.0-dev.1

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.
@@ -20,8 +20,6 @@ export interface CitationCardLabels {
20
20
  }
21
21
  /** Color overrides for `CitationCard`, applied as CSS custom properties with app theme fallbacks. */
22
22
  export interface CitationCardColors {
23
- /** Card border color. Fallback: `--stroke-primary`. */
24
- cardBorder?: string;
25
23
  /** Card background color. Fallback: `--bg-layer-raised`. */
26
24
  cardBackground?: string;
27
25
  /** Quoted excerpt text color. Fallback: `--text-secondary`. */
@@ -41,6 +39,8 @@ export interface CitationCardTypography {
41
39
  titleClassName?: string;
42
40
  /** CSS class applied to the quoted excerpt. Defaults to `'dial-small-text'`. */
43
41
  quoteClassName?: string;
42
+ /** CSS class applied to bold spans inside the quoted excerpt. Defaults to `'dial-small-semi-text'` — the semibold step matching the default `quoteClassName`. */
43
+ quoteStrongClassName?: string;
44
44
  /** CSS class applied to the pagination switcher text. Defaults to `'dial-tiny-text'`. */
45
45
  switcherClassName?: string;
46
46
  }
@@ -71,6 +71,4 @@ export interface CitationCardProps {
71
71
  }
72
72
  /** Popup card displaying a citation's title, quoted excerpt, and navigation controls. */
73
73
  export declare const CitationCard: FC<CitationCardProps>;
74
- declare const _default: import('react').NamedExoticComponent<CitationCardProps>;
75
- export default _default;
76
74
  //# sourceMappingURL=CitationCard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CitationCard.d.ts","sourceRoot":"","sources":["../../../src/components/CitationCard/CitationCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAc5D,OAAO,EAAE,EAAE,EAAQ,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAG/E,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,gBAAgB,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,2GAA2G;IAC3G,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/D,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qGAAqG;AACrG,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,oEAAoE;AACpE,MAAM,WAAW,sBAAsB;IACrC,qFAAqF;IACrF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sFAAsF;IACtF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,KAAK,EAAE,eAAe,CAAC;IACvB,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC7C,2EAA2E;IAC3E,eAAe,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAClD,wEAAwE;IACxE,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,4BAA4B;IAC5B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,2CAA2C;IAC3C,UAAU,CAAC,EAAE,sBAAsB,CAAC;IACpC,gCAAgC;IAChC,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC7B;AAED,yFAAyF;AACzF,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAmI9C,CAAC;;AAEF,wBAAkC"}
1
+ {"version":3,"file":"CitationCard.d.ts","sourceRoot":"","sources":["../../../src/components/CitationCard/CitationCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAe5D,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAG/E,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,gBAAgB,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,2GAA2G;IAC3G,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/D,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qGAAqG;AACrG,MAAM,WAAW,kBAAkB;IACjC,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,oEAAoE;AACpE,MAAM,WAAW,sBAAsB;IACrC,qFAAqF;IACrF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sFAAsF;IACtF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iKAAiK;IACjK,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,KAAK,EAAE,eAAe,CAAC;IACvB,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC7C,2EAA2E;IAC3E,eAAe,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAClD,wEAAwE;IACxE,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,4BAA4B;IAC5B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,2CAA2C;IAC3C,UAAU,CAAC,EAAE,sBAAsB,CAAC;IACpC,gCAAgC;IAChC,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC7B;AAED,yFAAyF;AACzF,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAqJ9C,CAAC"}
@@ -24,9 +24,9 @@ export interface CitationDropdownProps {
24
24
  markerLabels: CitationMarkerLabels;
25
25
  /** Optional typography overrides forwarded to the card. */
26
26
  cardTypography?: CitationCardTypography;
27
+ /** Typography class forwarded to the marker's label text. Defaults to `'dial-caption-text'`. */
28
+ markerLabelClassName?: string;
27
29
  }
28
30
  /** Combines `CitationMarker` and `CitationCard` into a tooltip-based dropdown. Requires a `CitationCardProvider` ancestor. */
29
31
  export declare const CitationDropdown: FC<CitationDropdownProps>;
30
- declare const _default: import('react').NamedExoticComponent<CitationDropdownProps>;
31
- export default _default;
32
32
  //# sourceMappingURL=CitationDropdown.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CitationDropdown.d.ts","sourceRoot":"","sources":["../../../src/components/CitationDropdown/CitationDropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,EAAE,EAAE,EAAQ,SAAS,EAAwB,MAAM,OAAO,CAAC;AAElE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,kCAAkC,CAAC;AAE1C,kDAAkD;AAClD,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,KAAK,EAAE,eAAe,CAAC;IACvB;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC7C,uEAAuE;IACvE,eAAe,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAClD,wDAAwD;IACxD,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,uFAAuF;IACvF,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,+CAA+C;IAC/C,UAAU,EAAE,kBAAkB,CAAC;IAC/B,yDAAyD;IACzD,YAAY,EAAE,oBAAoB,CAAC;IACnC,2DAA2D;IAC3D,cAAc,CAAC,EAAE,sBAAsB,CAAC;CACzC;AAED,8HAA8H;AAC9H,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CA6DtD,CAAC;;AAEF,wBAAsC"}
1
+ {"version":3,"file":"CitationDropdown.d.ts","sourceRoot":"","sources":["../../../src/components/CitationDropdown/CitationDropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAG5D,OAAO,EAAE,EAAE,EAAE,SAAS,EAAwB,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,kCAAkC,CAAC;AAG1C,kDAAkD;AAClD,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,KAAK,EAAE,eAAe,CAAC;IACvB;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC7C,uEAAuE;IACvE,eAAe,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAClD,wDAAwD;IACxD,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,uFAAuF;IACvF,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,+CAA+C;IAC/C,UAAU,EAAE,kBAAkB,CAAC;IAC/B,yDAAyD;IACzD,YAAY,EAAE,oBAAoB,CAAC;IACnC,2DAA2D;IAC3D,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,gGAAgG;IAChG,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,8HAA8H;AAC9H,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CAuEtD,CAAC"}
@@ -20,9 +20,9 @@ export interface CitationMarkerProps {
20
20
  icon?: ReactNode;
21
21
  /** User-visible strings. */
22
22
  labels: CitationMarkerLabels;
23
+ /** Typography class applied to the marker's label text. Defaults to `'dial-caption-text'`. */
24
+ labelClassName?: string;
23
25
  }
24
26
  /** Inline button that opens the citation popup for a source group. */
25
27
  export declare const CitationMarker: FC<CitationMarkerProps>;
26
- declare const _default: import('react').NamedExoticComponent<CitationMarkerProps>;
27
- export default _default;
28
28
  //# sourceMappingURL=CitationMarker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CitationMarker.d.ts","sourceRoot":"","sources":["../../../src/components/CitationMarker/CitationMarker.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAQ,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5C,iDAAiD;AACjD,MAAM,WAAW,oBAAoB;IACnC,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,gDAAgD;AAChD,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,eAAe,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,mEAAmE;IACnE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,4BAA4B;IAC5B,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED,sEAAsE;AACtE,eAAO,MAAM,cAAc,EAAE,EAAE,CAAC,mBAAmB,CAuBlD,CAAC;;AAEF,wBAAoC"}
1
+ {"version":3,"file":"CitationMarker.d.ts","sourceRoot":"","sources":["../../../src/components/CitationMarker/CitationMarker.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtC,iDAAiD;AACjD,MAAM,WAAW,oBAAoB;IACnC,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,gDAAgD;AAChD,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,eAAe,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,mEAAmE;IACnE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,4BAA4B;IAC5B,MAAM,EAAE,oBAAoB,CAAC;IAC7B,8FAA8F;IAC9F,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,sEAAsE;AACtE,eAAO,MAAM,cAAc,EAAE,EAAE,CAAC,mBAAmB,CAwBlD,CAAC"}
@@ -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;
@@ -0,0 +1,48 @@
1
+ import { Annotation } from '@epam/ai-dial-chat-shared';
2
+ import { Components } from 'react-markdown';
3
+ import { CitationCardLabels } from '../../components/CitationCard/CitationCard';
4
+ import { CitationMarkerLabels } from '../../components/CitationMarker/CitationMarker';
5
+ import { AnnotationGroup } from '../../utils/group-annotations-by-source';
6
+ /** Host-supplied callbacks and label builder consumed by `useCitationMarkdownComponents`. */
7
+ export interface UseCitationMarkdownComponentsCallbacks {
8
+ /** Called when a citation marker's preview action is invoked, with the clicked annotation and its group. */
9
+ onPreview(annotation: Annotation, group: AnnotationGroup): void;
10
+ /** Called when a citation marker's open-in-browser action is invoked. */
11
+ onOpenInBrowser(annotation: Annotation): void;
12
+ /** Builds the translated label bundles used by a given citation group's card and marker. */
13
+ buildLabels(group: AnnotationGroup): {
14
+ cardLabels: CitationCardLabels;
15
+ markerLabels: CitationMarkerLabels;
16
+ };
17
+ }
18
+ /**
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
25
+ * group's primary selector.
26
+ *
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.
31
+ *
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.
39
+ *
40
+ * `isCompactTypography` drops the paragraph class one type-scale step, matching
41
+ * `COMPACT_MARKDOWN_CLASS_NAMES` so cited and uncited paragraphs stay the same
42
+ * size.
43
+ */
44
+ export declare const useCitationMarkdownComponents: (content: string, groups: AnnotationGroup[], callbacks: UseCitationMarkdownComponentsCallbacks, isStreaming?: boolean, isCompactTypography?: boolean) => {
45
+ processedContent: string;
46
+ markdownComponents: Components;
47
+ };
48
+ //# sourceMappingURL=useCitationMarkdownComponents.d.ts.map
@@ -0,0 +1 @@
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.css CHANGED
@@ -1,2 +1,2 @@
1
- ._card_18wh9_1{border-color:var(--cc-card-border,var(--stroke-primary,#6b7280));background:var(--cc-card-bg,var(--bg-layer-raised,#fcfcfc))}._quote_18wh9_6{color:var(--cc-quote-text,var(--text-secondary,#6b7280))}._title_18wh9_10{color:var(--cc-title-text,var(--text-primary,#161b2d))}._switcher_18wh9_14{color:var(--cc-switcher-text,var(--text-secondary,#6b7280))}._sourceName_18wh9_18{color:var(--cc-source-name-text,var(--text-primary,#161b2d))}
1
+ ._card_1kph1_1{background:var(--cc-card-bg,var(--bg-layer-raised,#fcfcfc))}._quote_1kph1_5{color:var(--cc-quote-text,var(--text-secondary,#57647a))}._title_1kph1_9{color:var(--cc-title-text,var(--text-primary,#161b2d))}._switcher_1kph1_13{color:var(--cc-switcher-text,var(--text-secondary,#57647a))}._sourceName_1kph1_17{color:var(--cc-source-name-text,var(--text-primary,#161b2d))}._content_xzs0h_1>svg{fill:var(--cc-card-bg,var(--bg-layer-raised,#fcfcfc));stroke:#0000}
2
2
  /*$vite$:1*/
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { CitationCard } from './components/CitationCard/CitationCard';
2
- export type { CitationCardLabels, CitationCardProps, CitationCardTypography, } from './components/CitationCard/CitationCard';
2
+ export type { CitationCardColors, CitationCardLabels, CitationCardProps, CitationCardTypography, } from './components/CitationCard/CitationCard';
3
3
  export { CitationMarker } from './components/CitationMarker/CitationMarker';
4
4
  export type { CitationMarkerLabels, CitationMarkerProps, } from './components/CitationMarker/CitationMarker';
5
5
  export { CitationDropdown } from './components/CitationDropdown/CitationDropdown';
@@ -8,11 +8,13 @@ export { CitationCardProvider, useCitationCardContext, } from './context/Citatio
8
8
  export type { CitationCardHook } from './context/CitationCardContext';
9
9
  export { useAnnotations } from './utils/useAnnotations';
10
10
  export { useCitationCard } from './utils/useCitationCard';
11
- export { groupAnnotationsBySource } from './utils/group-annotations-by-source';
11
+ export { useCitationMarkdownComponents } from './hooks/useCitationMarkdownComponents/useCitationMarkdownComponents';
12
+ export type { UseCitationMarkdownComponentsCallbacks } from './hooks/useCitationMarkdownComponents/useCitationMarkdownComponents';
13
+ export { gatherSameSourceAnnotations, groupAnnotations, groupAnnotationsByCitId, groupAnnotationsBySource, } from './utils/group-annotations-by-source';
12
14
  export type { AnnotationGroup } from './utils/group-annotations-by-source';
13
- export { annotationsToPdfHighlights, annotationHighlightId, normalizeRawAnnotations, resolveMessageAnnotations, } from './utils/annotation';
14
- export type { AttachmentResource } from './utils/annotation';
15
- export { injectCitationSentinels, replaceSentinelsInChildren, } from './utils/citation-injection';
15
+ export { annotationHighlightId, annotationsToPdfHighlights, annotationToOfficeHighlightLocations, getAnnotationPdfPage, isDocxRangeSelector, isExcelRcRangeSelector, isPptxRangeSelector, resolveMessageAnnotations, } from './utils/annotation';
16
+ export type { DocxOfficeHighlightLocation, ExcelOfficeHighlightLocation, OfficeHighlightLocation, PptxOfficeHighlightLocation, } from './models/office-highlight';
17
+ export { injectCitationSentinels, replaceSentinelsInChildren, stripCitTagsWhileStreaming, } from './utils/citation-injection';
16
18
  export { isReferenceOnlyAttachment, parsePdfPageReference, getReferenceAttachmentGroups, } from './utils/reference-attachment';
17
19
  export type { PdfPageReference } from './utils/reference-attachment';
18
20
  //# 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;AAG1D,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;AAC5B,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,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,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,2BAA2B,EAC3B,gBAAgB,EAChB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAE3E,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,oCAAoC,EACpC,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,2BAA2B,CAAC;AAEnC,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,244 +1,307 @@
1
- import { MIMEType as e, MarkdownRenderer as t, buildCssVars as n, mergeClasses as r } from "@epam/ai-dial-chat-shared";
2
- import { DialEllipsisTooltip as i, DialTooltip as a, ElementSize as o, GhostIconButton as s, NeutralButton as c, PrimaryButton as l } from "@epam/ai-dial-ui-kit";
3
- import { IconChevronLeft as u, IconChevronRight as d } from "@tabler/icons-react";
4
- import { createContext as f, memo as p, useCallback as m, useContext as h, useMemo as g, useState as _ } from "react";
5
- import { jsx as v, jsxs as y } from "react/jsx-runtime";
6
- var b = {
7
- card: "_card_18wh9_1",
8
- quote: "_quote_18wh9_6",
9
- title: "_title_18wh9_10",
10
- switcher: "_switcher_18wh9_14",
11
- sourceName: "_sourceName_18wh9_18"
12
- }, x = ({ group: a, activeIndex: c, onIndexChange: f, onPreview: p, onOpenInBrowser: m, headerIcon: h, labels: g, typography: _, colors: x }) => {
13
- let S = a.annotations.length, C = a.annotations[c] ?? a.primaryAnnotation, w = S > 1, T = a.annotations.some((e) => e.body?.title), E = a.primaryAnnotation.body?.source?.attachment?.type, D = p == null || E === e.HTML || E === e.XHTML, O = _?.sourceNameClassName ?? "dial-tiny-text", k = _?.titleClassName ?? "dial-body-semi-text", A = _?.quoteClassName ?? "dial-small-text", j = _?.switcherClassName ?? "dial-tiny-text", M = n({
14
- "--cc-card-border": x?.cardBorder,
1
+ import { MIMEType as e, MarkdownRenderer as t, buildCssVars as n, isAnnotationSelector as r, mergeClasses as i, normalizePersistedHtmlTagAttachmentType as a, normalizeRawAnnotations as o } from "@epam/ai-dial-chat-shared";
2
+ import { DIAL_KIT_ICON_STROKE as s, ElementSize as c, EllipsisTooltip as l, GhostIconButton as u, NeutralButton as d, PrimaryButton as f, Tooltip as p } from "@epam/ai-dial-ui-kit";
3
+ import { IconChevronLeft as m, IconChevronRight as h } from "@tabler/icons-react";
4
+ import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
5
+ import { createContext as y, useCallback as b, useContext as x, useMemo as S, useState as C } from "react";
6
+ var w = {
7
+ card: "_card_1kph1_1",
8
+ quote: "_quote_1kph1_5",
9
+ title: "_title_1kph1_9",
10
+ switcher: "_switcher_1kph1_13",
11
+ sourceName: "_sourceName_1kph1_17"
12
+ }, T = ({ group: r, activeIndex: a, onIndexChange: o, onPreview: d, onOpenInBrowser: p, headerIcon: g, labels: y, typography: b, colors: x }) => {
13
+ let S = r.annotations.length, C = r.annotations[a] ?? r.primaryAnnotation, T = S > 1, E = r.primaryAnnotation.body?.source?.attachment?.type, D = d == null || E === e.HTML || E === e.XHTML, O = b?.sourceNameClassName ?? "dial-tiny-text", k = b?.titleClassName ?? "dial-body-semi-text", A = b?.quoteClassName ?? "dial-small-text", j = b?.quoteStrongClassName ?? "dial-small-semi-text", M = b?.switcherClassName ?? "dial-tiny-text", N = n({
15
14
  "--cc-card-bg": x?.cardBackground,
16
15
  "--cc-quote-text": x?.quoteText,
17
16
  "--cc-title-text": x?.titleText,
18
17
  "--cc-switcher-text": x?.switcherText,
19
18
  "--cc-source-name-text": x?.sourceNameText
20
19
  });
21
- return /* @__PURE__ */ y("div", {
20
+ return /* @__PURE__ */ v("div", {
22
21
  role: "dialog",
23
22
  "aria-modal": "true",
24
- "aria-label": g.ariaLabel,
25
- style: M,
26
- className: r("flex w-[400px] flex-col gap-3 rounded-lg border p-4 shadow-lg", b.card),
23
+ "aria-label": y.ariaLabel,
24
+ style: N,
25
+ className: i("flex w-[400px] flex-col gap-3 rounded-lg p-4 shadow-lg", w.card),
27
26
  children: [
28
- /* @__PURE__ */ y("div", {
27
+ /* @__PURE__ */ v("div", {
29
28
  className: "flex items-center justify-between gap-2",
30
- children: [/* @__PURE__ */ y("div", {
29
+ children: [/* @__PURE__ */ v("div", {
31
30
  className: "flex min-w-0 items-center gap-1",
32
- children: [h, /* @__PURE__ */ v(i, {
33
- text: a.sourceName,
34
- className: r(O, "min-w-0", b.sourceName)
31
+ children: [g, /* @__PURE__ */ _(l, {
32
+ text: r.sourceName,
33
+ className: i(O, "min-w-0", w.sourceName)
35
34
  })]
36
- }), w && /* @__PURE__ */ y("div", {
35
+ }), T && /* @__PURE__ */ v("div", {
37
36
  className: "flex shrink-0 items-center gap-1",
38
37
  children: [
39
- /* @__PURE__ */ v(s, {
40
- icon: /* @__PURE__ */ v(u, {
38
+ /* @__PURE__ */ _(u, {
39
+ icon: /* @__PURE__ */ _(m, {
41
40
  size: 14,
42
- className: "rtl:scale-x-[-1]"
41
+ className: "rtl:scale-x-[-1]",
42
+ stroke: s
43
43
  }),
44
- size: o.Small,
45
- "aria-label": g.previousCitation,
46
- onClick: () => f((c - 1 + S) % S)
44
+ size: c.Small,
45
+ "aria-label": y.previousCitation,
46
+ onClick: () => o((a - 1 + S) % S)
47
47
  }),
48
- /* @__PURE__ */ v("span", {
49
- className: r(j, b.switcher),
50
- children: g.formatSwitcherText(c + 1, S)
48
+ /* @__PURE__ */ _("span", {
49
+ className: i(M, w.switcher),
50
+ children: y.formatSwitcherText(a + 1, S)
51
51
  }),
52
- /* @__PURE__ */ v(s, {
53
- icon: /* @__PURE__ */ v(d, {
52
+ /* @__PURE__ */ _(u, {
53
+ icon: /* @__PURE__ */ _(h, {
54
54
  size: 14,
55
- className: "rtl:scale-x-[-1]"
55
+ className: "rtl:scale-x-[-1]",
56
+ stroke: s
56
57
  }),
57
- size: o.Small,
58
- "aria-label": g.nextCitation,
59
- onClick: () => f((c + 1) % S)
58
+ size: c.Small,
59
+ "aria-label": y.nextCitation,
60
+ onClick: () => o((a + 1) % S)
60
61
  })
61
62
  ]
62
63
  })]
63
64
  }),
64
- (C.body?.title || C.body?.quote || w) && /* @__PURE__ */ y("div", {
65
+ (C.body?.title || C.body?.quote || T) && /* @__PURE__ */ v("div", {
65
66
  className: "flex flex-col gap-3",
66
- children: [(C.body?.title || w && T) && /* @__PURE__ */ v("p", {
67
- className: r(k, b.title, w && T && "min-h-[1lh]"),
68
- children: C.body?.title
69
- }), (C.body?.quote || w) && /* @__PURE__ */ v("div", {
70
- className: r(w && "min-h-[3lh]"),
71
- children: C.body?.quote && /* @__PURE__ */ v(t, {
67
+ children: [C.body?.title && /* @__PURE__ */ _("p", {
68
+ className: i(k, w.title, "break-words"),
69
+ children: C.body.title
70
+ }), (C.body?.quote || T) && /* @__PURE__ */ _("div", {
71
+ className: i(A, w.quote, "line-clamp-6 break-words", T && "min-h-[3lh]"),
72
+ children: C.body?.quote && /* @__PURE__ */ _(t, {
72
73
  content: C.body.quote,
73
- classNames: { p: r(A, "line-clamp-6", b.quote) }
74
+ classNames: {
75
+ p: i(A, w.quote),
76
+ ul: i(A, "ps-3"),
77
+ ol: i(A, "ps-3"),
78
+ strong: j
79
+ }
74
80
  })
75
81
  })]
76
82
  }),
77
- /* @__PURE__ */ y("div", {
83
+ /* @__PURE__ */ v("div", {
78
84
  className: "flex justify-start gap-2",
79
- children: [p && /* @__PURE__ */ v(l, {
80
- label: g.preview,
81
- size: o.Small,
85
+ children: [d && /* @__PURE__ */ _(f, {
86
+ label: y.preview,
87
+ size: c.Small,
88
+ onClick: () => d(C)
89
+ }), /* @__PURE__ */ _(f, {
90
+ label: D ? y.openInBrowser : y.download,
91
+ size: c.Small,
82
92
  onClick: () => p(C)
83
- }), /* @__PURE__ */ v(l, {
84
- label: D ? g.openInBrowser : g.download,
85
- size: o.Small,
86
- onClick: () => m(C)
87
93
  })]
88
94
  })
89
95
  ]
90
96
  });
91
- };
92
- p(x);
93
- //#endregion
94
- //#region src/components/CitationMarker/CitationMarker.tsx
95
- var S = ({ annotationCount: e, onOpen: t, icon: n, labels: r }) => {
96
- let i = /* @__PURE__ */ y("span", {
97
+ }, E = ({ annotationCount: e, onOpen: t, icon: n, labels: r, labelClassName: i = "dial-caption-text" }) => {
98
+ let a = /* @__PURE__ */ v("span", {
97
99
  className: "flex items-center gap-1",
98
- children: [n, /* @__PURE__ */ v("span", {
99
- className: "dial-caption-text",
100
+ children: [n, /* @__PURE__ */ _("span", {
101
+ className: i,
100
102
  children: e > 1 ? r.labelWithOverflow : r.label
101
103
  })]
102
104
  });
103
- return /* @__PURE__ */ v(c, {
104
- size: o.Small,
105
- label: i,
105
+ return /* @__PURE__ */ _(d, {
106
+ size: c.Small,
107
+ label: a,
106
108
  "aria-label": r.ariaLabel,
107
109
  onClick: t
108
110
  });
109
- };
110
- p(S);
111
- //#endregion
112
- //#region src/context/CitationCardContext.tsx
113
- var C = f(null), w = C.Provider, T = () => {
114
- let e = h(C);
111
+ }, D = y(null), O = D.Provider, k = () => {
112
+ let e = x(D);
115
113
  if (e == null) throw Error("useCitationCardContext must be used within a CitationCardProvider");
116
114
  return e;
117
- }, E = ({ group: e, onPreview: t, onOpenInBrowser: n, icon: r, headerIcon: i, cardLabels: o, markerLabels: s, cardTypography: c }) => {
118
- let l = T(), u = l.isOpen(e.sourceUrl), d = l.getActiveIndex(e.sourceUrl);
119
- return /* @__PURE__ */ v(a, {
120
- open: u,
121
- onOpenChange: m((e) => {
122
- e || l.closePopup();
123
- }, [l]),
124
- placement: "bottom-end",
115
+ }, A = { content: "_content_xzs0h_1" }, j = ({ group: e, onPreview: t, onOpenInBrowser: n, icon: r, headerIcon: a, cardLabels: o, markerLabels: s, cardTypography: c, markerLabelClassName: l }) => {
116
+ let u = k(), d = u.isOpen(e.groupKey), f = u.getActiveIndex(e.groupKey), m = b((e) => {
117
+ e || u.closePopup();
118
+ }, [u]), h = S(() => t ? (e) => {
119
+ t(e), u.closePopup();
120
+ } : void 0, [t, u]);
121
+ return /* @__PURE__ */ _(p, {
122
+ open: d,
123
+ onOpenChange: m,
125
124
  triggerClassName: "ms-1 inline-flex align-middle",
126
- contentClassName: "!p-0 !bg-transparent !border-0 !shadow-none !max-w-none !rounded-none",
127
- tooltip: /* @__PURE__ */ v(x, {
125
+ contentClassName: i("!p-0 !bg-transparent !border-0 !shadow-none !max-w-none !rounded-none", A.content),
126
+ tooltip: /* @__PURE__ */ _(T, {
128
127
  group: e,
129
- activeIndex: d,
130
- onIndexChange: (t) => l.setActiveIndex(e.sourceUrl, t),
131
- onPreview: g(() => t ? (e) => {
132
- t(e), l.closePopup();
133
- } : void 0, [t, l]),
128
+ activeIndex: f,
129
+ onIndexChange: (t) => u.setActiveIndex(e.groupKey, t),
130
+ onPreview: h,
134
131
  onOpenInBrowser: n,
135
- headerIcon: i,
132
+ headerIcon: a,
136
133
  labels: o,
137
134
  typography: c
138
135
  }),
139
- children: /* @__PURE__ */ v(S, {
136
+ children: /* @__PURE__ */ _(E, {
140
137
  sourceName: e.sourceName,
141
138
  annotationCount: e.annotations.length,
142
- onOpen: () => l.openPopup(e.sourceUrl),
139
+ onOpen: () => u.openPopup(e.groupKey),
143
140
  icon: r,
144
- labels: s
141
+ labels: s,
142
+ labelClassName: l
145
143
  })
146
144
  });
147
- };
148
- p(E);
149
- //#endregion
150
- //#region src/utils/annotation.ts
151
- var D = {
145
+ }, M = {
152
146
  backgroundColor: "transparent",
153
- borderColor: "#124ACE",
147
+ borderColor: "var(--stroke-accent, #1D4ED8)",
154
148
  borderWidth: "2px",
155
149
  opacity: .5,
156
150
  hoverOpacity: .5
157
- }, O = (e) => e.flatMap((e, t) => {
158
- let n = e.body?.selector;
159
- if (n == null) return [];
160
- let r = (Array.isArray(n) ? n : [n]).flatMap((e) => {
161
- if (e.type !== "pdf_bbox") return [];
162
- let { page: t, x1: n, y1: r, x2: i, y2: a } = e;
163
- return [{
164
- page: t,
165
- x1: n,
166
- y1: r,
167
- x2: i,
168
- y2: a
169
- }];
170
- });
171
- return r.length === 0 ? [] : [{
172
- id: String(e.index ?? t),
173
- bboxes: r,
174
- style: D
175
- }];
176
- }), k = (e, t) => String(e.index ?? t), A = (e) => typeof e == "number" ? e : null, j = (e) => {
177
- if (typeof e != "object" || !e) return null;
178
- let t = e;
179
- if (t.type !== "pdf_region") return null;
180
- let n = t.bbox;
181
- if (typeof n != "object" || !n) return null;
182
- let r = n, i = A(r.left), a = A(r.top), o = A(r.width), s = A(r.height);
183
- return i === null || a === null || o === null || s === null ? null : {
184
- type: "pdf_bbox",
185
- page: A(t.page) ?? 1,
151
+ }, N = (e) => {
152
+ if (typeof e != "object" || !e) return;
153
+ let t = e, { lt: n, wh: r } = t;
154
+ if (Array.isArray(n) && Array.isArray(r) && n.length >= 2 && r.length >= 2) {
155
+ let [e, t] = n, [i, a] = r;
156
+ if (typeof e == "number" && typeof t == "number" && typeof i == "number" && typeof a == "number") return {
157
+ x1: e,
158
+ y1: t,
159
+ x2: e + i,
160
+ y2: t + a
161
+ };
162
+ }
163
+ let { left: i, top: a, width: o, height: s } = t;
164
+ if (typeof i == "number" && typeof a == "number" && typeof o == "number" && typeof s == "number") return {
186
165
  x1: i,
187
166
  y1: a,
188
167
  x2: i + o,
189
168
  y2: a + s
190
169
  };
191
- }, M = (t, n) => t.flatMap((t) => {
192
- if (typeof t != "object" || !t) return [];
193
- let r = t, i = r.target;
194
- if (typeof i != "object" || !i) return [];
195
- let a = i, o = a.source;
196
- if (typeof o != "object" || !o) return [];
197
- let s = A(o.attachment_index);
198
- if (s === null) return [];
199
- let c = n.find((e) => e.index === s);
200
- if (c?.url == null) return [];
201
- let l = j(a.selector);
202
- if (l === null) return [];
203
- 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;
204
- return [{
205
- index: A(r.index) ?? void 0,
206
- body: {
207
- title: f,
208
- quote: p,
209
- source: {
210
- type: "attachment",
211
- attachment: {
212
- type: c.type ?? e.PDF,
213
- url: c.url,
214
- title: c.title
215
- }
216
- },
217
- selector: l
218
- }
170
+ }, P = (e) => {
171
+ if (!r(e)) return;
172
+ let t = e, n;
173
+ if (t.type === "pdf_bbox") {
174
+ let { x1: e, y1: r, x2: i, y2: a } = t;
175
+ typeof e == "number" && typeof r == "number" && typeof i == "number" && typeof a == "number" && (n = {
176
+ x1: e,
177
+ y1: r,
178
+ x2: i,
179
+ y2: a
180
+ });
181
+ } else t.type === "pdf_region" && (n = N(t.bbox));
182
+ if (n == null) return;
183
+ let i = t.page;
184
+ if (!(typeof i != "number" || !Number.isInteger(i) || i < 1) && [
185
+ n.x1,
186
+ n.y1,
187
+ n.x2,
188
+ n.y2
189
+ ].every(Number.isFinite)) return {
190
+ page: i,
191
+ x1: n.x1,
192
+ y1: n.y1,
193
+ x2: n.x2,
194
+ y2: n.y2
195
+ };
196
+ }, ee = (e) => e.flatMap((e, t) => {
197
+ let n = e.body?.selector;
198
+ if (n == null) return [];
199
+ let i = (Array.isArray(n) ? n : [n]).flatMap((e) => {
200
+ if (!r(e)) return [];
201
+ let t = P(e);
202
+ return t == null ? [] : [t];
203
+ });
204
+ return i.length === 0 ? [] : [{
205
+ id: String(e.index ?? t),
206
+ bboxes: i,
207
+ style: M
219
208
  }];
220
- }), N = (e) => {
209
+ }), te = (e, t) => String(e.index ?? t), ne = (e) => {
210
+ let t = e.body?.selector;
211
+ if (t == null) return;
212
+ let n = Array.isArray(t) ? t : [t];
213
+ for (let e of n) {
214
+ if (!r(e)) continue;
215
+ let t = P(e);
216
+ if (t != null) return t.page;
217
+ }
218
+ }, F = (e) => {
221
219
  let t = e.custom_content?.annotations;
222
- if (t?.length) return t.filter((e) => e != null && e.body?.source?.attachment?.url != null);
220
+ if (t?.length) return t.filter((e) => e != null && e.body?.source?.attachment?.url != null).map(a);
223
221
  let n = e.custom_fields;
224
222
  if (typeof n != "object" || !n) return [];
225
223
  let r = n.annotations;
226
- return !Array.isArray(r) || r.length === 0 ? [] : M(r, e.custom_content?.attachments ?? []);
227
- }, P = (e, t) => g(() => t ? [] : N(e), [t, e]), F = {
228
- openGroupSourceUrl: null,
224
+ return !Array.isArray(r) || r.length === 0 ? [] : o(r, e.custom_content?.attachments ?? []).map(a);
225
+ }, I = (e) => {
226
+ if (e.type !== "docx_text_range") return !1;
227
+ let t = e;
228
+ return typeof t.story == "string" && Array.isArray(t.path) && t.path.every((e) => typeof e == "number") && typeof t.start == "number" && typeof t.end == "number" && typeof t.text == "string";
229
+ }, L = (e) => {
230
+ if (e.type !== "pptx_text_range") return !1;
231
+ let t = e;
232
+ return typeof t.slide == "number" && typeof t.shape_id == "string" && typeof t.start == "number" && typeof t.end == "number" && typeof t.text == "string";
233
+ }, R = (e) => typeof e == "object" && !!e && typeof e.row == "number" && typeof e.col == "number", z = (e) => {
234
+ if (e.type !== "excel_rc_range") return !1;
235
+ let t = e;
236
+ return typeof t.sheet == "string" && R(t.start) && (t.end === void 0 || t.end === null || R(t.end));
237
+ }, re = (e) => {
238
+ let { story: t, path: n, start: r, end: i, text: a } = e;
239
+ if (!(!n.every((e) => Number.isInteger(e)) || !Number.isInteger(r) || !Number.isInteger(i) || r < 0 || i < r)) return {
240
+ type: "docx_text_range",
241
+ story: t,
242
+ path: n,
243
+ start: r,
244
+ endExclusive: i,
245
+ text: a
246
+ };
247
+ }, ie = (e) => {
248
+ let { slide: t, shape_id: n, start: r, end: i, text: a } = e;
249
+ if (!(!Number.isInteger(t) || t < 1 || !Number.isInteger(r) || !Number.isInteger(i) || r < 0 || i < r)) return {
250
+ type: "pptx_text_range",
251
+ slide: t,
252
+ shapeId: n,
253
+ start: r,
254
+ endExclusive: i,
255
+ text: a
256
+ };
257
+ }, ae = (e) => {
258
+ let { sheet: t, start: n, end: r } = e;
259
+ if (!(t.length === 0 || !Number.isInteger(n.row) || !Number.isInteger(n.col) || n.row < 1 || n.col < 1)) {
260
+ if (r == null) return {
261
+ type: "excel_rc_range",
262
+ sheet: t,
263
+ start: n
264
+ };
265
+ if (!(!Number.isInteger(r.row) || !Number.isInteger(r.col) || r.row !== n.row || r.col < n.col)) return {
266
+ type: "excel_rc_range",
267
+ sheet: t,
268
+ start: n,
269
+ end: r
270
+ };
271
+ }
272
+ }, oe = (e) => {
273
+ let t = e.body?.selector;
274
+ return t == null ? [] : (Array.isArray(t) ? t : [t]).flatMap((e) => {
275
+ if (!r(e)) return [];
276
+ if (I(e)) {
277
+ let t = re(e);
278
+ return t ? [t] : [];
279
+ }
280
+ if (L(e)) {
281
+ let t = ie(e);
282
+ return t ? [t] : [];
283
+ }
284
+ if (z(e)) {
285
+ let t = ae(e);
286
+ return t ? [t] : [];
287
+ }
288
+ return [];
289
+ });
290
+ }, se = (e, t) => S(() => t ? [] : F(e), [t, e]), ce = {
291
+ openGroupKey: null,
229
292
  activeIndexByGroup: {}
230
- }, I = () => {
231
- let [e, t] = _(F), n = m((e) => {
293
+ }, le = () => {
294
+ let [e, t] = C(ce), n = b((e) => {
232
295
  t((t) => ({
233
296
  ...t,
234
- openGroupSourceUrl: e
297
+ openGroupKey: e
235
298
  }));
236
- }, []), r = m(() => {
299
+ }, []), r = b(() => {
237
300
  t((e) => ({
238
301
  ...e,
239
- openGroupSourceUrl: null
302
+ openGroupKey: null
240
303
  }));
241
- }, []), i = m((e, n) => {
304
+ }, []), i = b((e, n) => {
242
305
  t((t) => ({
243
306
  ...t,
244
307
  activeIndexByGroup: {
@@ -247,11 +310,11 @@ var D = {
247
310
  }
248
311
  }));
249
312
  }, []);
250
- return g(() => ({
313
+ return S(() => ({
251
314
  openPopup: n,
252
315
  closePopup: r,
253
316
  setActiveIndex: i,
254
- isOpen: (t) => e.openGroupSourceUrl === t,
317
+ isOpen: (t) => e.openGroupKey === t,
255
318
  getActiveIndex: (t) => e.activeIndexByGroup[t] ?? 0
256
319
  }), [
257
320
  n,
@@ -259,64 +322,151 @@ var D = {
259
322
  i,
260
323
  e
261
324
  ]);
262
- }, L = (e) => {
325
+ }, ue = /⟦C(\d+)⟧/g, B = (e, t) => {
326
+ let n = t.map((e, t) => ({
327
+ g: e,
328
+ idx: t
329
+ })).filter(({ g: e }) => e.primaryAnnotation.target?.selector?.type !== "html_tag").map(({ g: t, idx: n }) => {
330
+ let r = t.primaryAnnotation.target?.selector, i = typeof r == "object" && r && "type" in r && r.type === "text_character_range" ? r.end : e.length;
331
+ return {
332
+ idx: n,
333
+ pos: Math.min(i, e.length)
334
+ };
335
+ }).sort((e, t) => t.pos - e.pos), r = e;
336
+ for (let { idx: e, pos: t } of n) r = `${r.slice(0, t)}⟦C${e}⟧${r.slice(t)}`;
337
+ return r;
338
+ }, V = /<cit\s+data-id=(?:"[^"]+"|'[^']+')\s*>\s*<\/cit>/g, H = /^<cit\s+data-id=(?:"[^"]+"|'[^']+')\s*>\s*<\/cit>$/, de = /<cit\s+data-id=(?:"[^"]+"|'[^']+')\s*>\s*<\/cit>|<\/?cit\b[^>]*>|<\/?cit\b[^>]*$/gi, fe = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"), U = (e) => e.replace(de, (e) => H.test(e) ? e : fe(e)), W = (e) => U(e).replace(V, ""), G = (e, t) => {
339
+ if (typeof e == "string") {
340
+ let n = e.split(ue);
341
+ if (n.length === 1) return e;
342
+ let r = [];
343
+ return n.forEach((e, n) => {
344
+ n % 2 == 1 ? r.push(t(parseInt(e, 10))) : e && r.push(e);
345
+ }), r;
346
+ }
347
+ return Array.isArray(e) ? e.flatMap((e) => {
348
+ let n = G(e, t);
349
+ return Array.isArray(n) ? n : [n];
350
+ }) : e;
351
+ }, pe = (e) => {
352
+ let t = e.primaryAnnotation.target?.selector;
353
+ return t?.type === "html_tag" ? t.id : void 0;
354
+ }, me = (e, t) => /* @__PURE__ */ v(g, { children: [
355
+ e == null ? "<cit>" : `<cit data-id="${e}">`,
356
+ t,
357
+ "</cit>"
358
+ ] }), he = (e, t, n, r = !1, a = !1) => {
359
+ let { onPreview: o, onOpenInBrowser: s, buildLabels: c } = n, l = S(() => r ? W(e) : U(t.length > 0 ? B(e, t) : e), [
360
+ e,
361
+ t,
362
+ r
363
+ ]), u = l.includes("<cit");
364
+ return {
365
+ processedContent: l,
366
+ markdownComponents: S(() => {
367
+ let e = /* @__PURE__ */ new Map();
368
+ for (let n of t) {
369
+ let t = pe(n);
370
+ t != null && e.set(t, n);
371
+ }
372
+ let n = (e) => {
373
+ let { cardLabels: t, markerLabels: n } = c(e);
374
+ return /* @__PURE__ */ _(j, {
375
+ group: e,
376
+ onPreview: (t) => o(t, e),
377
+ onOpenInBrowser: s,
378
+ cardLabels: t,
379
+ markerLabels: n
380
+ }, `citation-${e.groupKey}`);
381
+ }, r = (e) => {
382
+ let r = t[e];
383
+ return r ? n(r) : null;
384
+ }, l = { cit: (t) => {
385
+ let r = t["data-id"] == null ? void 0 : e.get(t["data-id"]);
386
+ return r ? n(r) : me(t["data-id"], t.children);
387
+ } };
388
+ return t.length === 0 ? u ? l : {} : {
389
+ ...l,
390
+ p: ({ children: e, ...t }) => /* @__PURE__ */ _("p", {
391
+ ...t,
392
+ className: i(a ? "dial-small-paragraph-text" : "dial-body-paragraph-text", "mb-3 [overflow-wrap:anywhere] [text-wrap:pretty] last:mb-0"),
393
+ children: G(e, r)
394
+ }),
395
+ li: ({ children: e, ...t }) => /* @__PURE__ */ _("li", {
396
+ ...t,
397
+ className: "mb-1.5 last:mb-0",
398
+ children: G(e, r)
399
+ })
400
+ };
401
+ }, [
402
+ t,
403
+ o,
404
+ s,
405
+ c,
406
+ a,
407
+ u
408
+ ])
409
+ };
410
+ }, K = (e) => {
263
411
  try {
264
412
  return decodeURIComponent(e);
265
413
  } catch {
266
414
  return e;
267
415
  }
268
- }, R = (e) => {
416
+ }, ge = (e) => {
269
417
  try {
270
418
  let t = new URL(e);
271
- return t.pathname.split("/").map((e) => L(e)).filter(Boolean).at(-1) ?? t.hostname;
419
+ return t.pathname.split("/").map((e) => K(e)).filter(Boolean).at(-1) ?? t.hostname;
272
420
  } catch {
273
- return e.split("/").map((e) => L(e)).filter(Boolean).at(-1) ?? e;
421
+ return e.split("/").map((e) => K(e)).filter(Boolean).at(-1) ?? e;
274
422
  }
275
- }, z = (e) => {
423
+ }, q = (e, t) => e.body?.source?.attachment?.title ?? ge(t), J = (e) => {
424
+ let t = e.target?.selector;
425
+ return t?.type === "html_tag" ? t : void 0;
426
+ }, _e = (e) => J(e) != null, Y = (e) => {
276
427
  let t = /* @__PURE__ */ new Map();
277
428
  for (let n of e) {
429
+ if (_e(n)) continue;
278
430
  let e = n.body?.source?.attachment?.url;
279
431
  if (e == null) continue;
280
432
  let r = t.get(e);
281
433
  r ? r.annotations.push(n) : t.set(e, {
434
+ groupKey: e,
282
435
  sourceUrl: e,
283
- sourceName: n.body?.source?.attachment?.title ?? R(e),
436
+ sourceName: q(n, e),
284
437
  annotations: [n],
285
438
  primaryAnnotation: n
286
439
  });
287
440
  }
288
441
  return Array.from(t.values());
289
- }, B = /⟦C(\d+)⟧/g, V = (e, t) => {
290
- let n = t.map((t, n) => {
291
- let r = t.primaryAnnotation.target?.selector, i = typeof r == "object" && r && "type" in r && r.type === "text_character_range" ? r.end : e.length;
292
- return {
293
- idx: n,
294
- pos: Math.min(i, e.length)
295
- };
296
- }).sort((e, t) => t.pos - e.pos), r = e;
297
- for (let { idx: e, pos: t } of n) r = `${r.slice(0, t)}⟦C${e}⟧${r.slice(t)}`;
298
- return r;
299
- }, H = (e, t) => {
300
- if (typeof e == "string") {
301
- let n = e.split(B);
302
- if (n.length === 1) return e;
303
- let r = [];
304
- return n.forEach((e, n) => {
305
- n % 2 == 1 ? r.push(t(parseInt(e, 10))) : e && r.push(e);
306
- }), r;
442
+ }, X = (e) => {
443
+ let t = /* @__PURE__ */ new Map();
444
+ for (let n of e) {
445
+ let e = J(n)?.id;
446
+ if (e == null) continue;
447
+ let r = n.body?.source?.attachment?.url;
448
+ if (r == null) continue;
449
+ let i = t.get(e);
450
+ i ? i.annotations.push(n) : t.set(e, {
451
+ groupKey: `cit:${e}`,
452
+ sourceUrl: r,
453
+ sourceName: q(n, r),
454
+ annotations: [n],
455
+ primaryAnnotation: n
456
+ });
307
457
  }
308
- return Array.isArray(e) ? e.flatMap((e) => {
309
- let n = H(e, t);
310
- return Array.isArray(n) ? n : [n];
311
- }) : e;
312
- }, U = (e) => e.url == null && e.reference_url != null, W = /^(.*\.pdf)(?:#page=(\d+))?$/i, G = (e) => {
313
- let t = W.exec(e);
458
+ return Array.from(t.values());
459
+ }, ve = (e) => [...X(e), ...Y(e)], Z = (e, t) => {
460
+ let n = e.body?.source?.attachment?.url;
461
+ return n == null || !t.includes(e) ? [e] : t.filter((e) => e.body?.source?.attachment?.url === n);
462
+ }, Q = (e) => e.url == null && e.reference_url != null, ye = /^(.*\.pdf)(?:#page=(\d+))?$/i, $ = (e) => {
463
+ let t = ye.exec(e);
314
464
  return t ? {
315
465
  baseUrl: t[1],
316
466
  page: t[2] == null ? null : Number(t[2])
317
467
  } : null;
318
- }, K = (t) => z((t ?? []).filter(U).map((t) => {
319
- let n = t.reference_url, r = G(n) != null;
468
+ }, be = (t) => Y((t ?? []).filter(Q).map((t) => {
469
+ let n = t.reference_url, r = $(n) != null;
320
470
  return { body: {
321
471
  quote: t.data,
322
472
  source: {
@@ -330,4 +480,4 @@ var D = {
330
480
  } };
331
481
  }));
332
482
  //#endregion
333
- export { x as CitationCard, w as CitationCardProvider, E as CitationDropdown, S as CitationMarker, k as annotationHighlightId, O as annotationsToPdfHighlights, K as getReferenceAttachmentGroups, z as groupAnnotationsBySource, V as injectCitationSentinels, U as isReferenceOnlyAttachment, M as normalizeRawAnnotations, G as parsePdfPageReference, H as replaceSentinelsInChildren, N as resolveMessageAnnotations, P as useAnnotations, I as useCitationCard, T as useCitationCardContext };
483
+ export { T as CitationCard, O as CitationCardProvider, j as CitationDropdown, E as CitationMarker, te as annotationHighlightId, oe as annotationToOfficeHighlightLocations, ee as annotationsToPdfHighlights, Z as gatherSameSourceAnnotations, ne as getAnnotationPdfPage, be as getReferenceAttachmentGroups, ve as groupAnnotations, X as groupAnnotationsByCitId, Y as groupAnnotationsBySource, B as injectCitationSentinels, I as isDocxRangeSelector, z as isExcelRcRangeSelector, L as isPptxRangeSelector, Q as isReferenceOnlyAttachment, $ as parsePdfPageReference, G as replaceSentinelsInChildren, F as resolveMessageAnnotations, W as stripCitTagsWhileStreaming, se as useAnnotations, le as useCitationCard, k as useCitationCardContext, he as useCitationMarkdownComponents };
@@ -0,0 +1,62 @@
1
+ import { ExcelCellAddress } from '@epam/ai-dial-chat-shared';
2
+ /**
3
+ * A validated, normalised DOCX character-range location. `endExclusive` is
4
+ * the wire's `end` copied through unchanged — confirmed exclusive on the
5
+ * wire, unlike `TextCharacterRangeSelector`'s inclusive `end` (see the
6
+ * `annotation.ts` normaliser and `design.md` D3 for the evidence).
7
+ */
8
+ export interface DocxOfficeHighlightLocation {
9
+ /** Discriminates this location within `OfficeHighlightLocation`. Mirrors the wire selector's `type`. */
10
+ type: 'docx_text_range';
11
+ /** Name of the DOCX story the range lives in, as an opaque string (only `'body'` is confirmed upstream). */
12
+ story: string;
13
+ /** Source-tree element indices identifying the paragraph, matched element-wise. */
14
+ path: number[];
15
+ /** Zero-based start character offset. */
16
+ start: number;
17
+ /** Zero-based exclusive end character offset. */
18
+ endExclusive: number;
19
+ /** The cited text, expected to equal the text resolved over `[start, endExclusive)`. */
20
+ text: string;
21
+ }
22
+ /**
23
+ * A validated, normalised PPTX character-range location. `endExclusive` is
24
+ * the wire's `end` copied through unchanged — confirmed exclusive on the
25
+ * wire (see `design.md` D3).
26
+ */
27
+ export interface PptxOfficeHighlightLocation {
28
+ /** Discriminates this location within `OfficeHighlightLocation`. Mirrors the wire selector's `type`. */
29
+ type: 'pptx_text_range';
30
+ /** 1-based slide number. */
31
+ slide: number;
32
+ /** Shape identifier, compared as a string against the run's own shape id. */
33
+ shapeId: string;
34
+ /** Zero-based start character offset. */
35
+ start: number;
36
+ /** Zero-based exclusive end character offset. */
37
+ endExclusive: number;
38
+ /** The cited text, expected to equal the text resolved over `[start, endExclusive)`. */
39
+ text: string;
40
+ }
41
+ /** A validated, normalised XLSX cell or same-row cell-range location. */
42
+ export interface ExcelOfficeHighlightLocation {
43
+ /** Discriminates this location within `OfficeHighlightLocation`. Mirrors the wire selector's `type`. */
44
+ type: 'excel_rc_range';
45
+ /** Sheet name, matched exactly against the workbook's own sheet names. */
46
+ sheet: string;
47
+ /** First cell of the range. */
48
+ start: ExcelCellAddress;
49
+ /** Last (inclusive) cell of the range, on the same row as `start`. Omitted for a single cell. */
50
+ end?: ExcelCellAddress;
51
+ }
52
+ /**
53
+ * A validated, normalised Office document highlight location, produced by
54
+ * `annotationToOfficeHighlightLocations`. Intentionally not the
55
+ * `@epam/ai-dial-attachment-canvas` `OoxmlHighlightLocation` shape — this lib
56
+ * must not depend on `attachment-canvas` (that lib's own test already
57
+ * depends on this one, via `annotationsToPdfHighlights`, and a lib-to-lib
58
+ * cycle is not permitted). `libs/chat-hooks`, which already depends on both,
59
+ * maps this into `OoxmlHighlight`/`OoxmlHighlightLocation`.
60
+ */
61
+ export type OfficeHighlightLocation = DocxOfficeHighlightLocation | PptxOfficeHighlightLocation | ExcelOfficeHighlightLocation;
62
+ //# sourceMappingURL=office-highlight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"office-highlight.d.ts","sourceRoot":"","sources":["../../src/models/office-highlight.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE;;;;;GAKG;AACH,MAAM,WAAW,2BAA2B;IAC1C,wGAAwG;IACxG,IAAI,EAAE,iBAAiB,CAAC;IACxB,4GAA4G;IAC5G,KAAK,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,YAAY,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C,wGAAwG;IACxG,IAAI,EAAE,iBAAiB,CAAC;IACxB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,YAAY,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;CACd;AAED,yEAAyE;AACzE,MAAM,WAAW,4BAA4B;IAC3C,wGAAwG;IACxG,IAAI,EAAE,gBAAgB,CAAC;IACvB,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,KAAK,EAAE,gBAAgB,CAAC;IACxB,iGAAiG;IACjG,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,uBAAuB,GAC/B,2BAA2B,GAC3B,2BAA2B,GAC3B,4BAA4B,CAAC"}
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.99",
4
+ "version": "1.2.0-dev.1",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "main": "./index.js",
@@ -9,18 +9,22 @@
9
9
  "types": "./index.d.ts",
10
10
  "exports": {
11
11
  "./package.json": "./package.json",
12
+ "./styles.css": "./index.css",
12
13
  ".": {
13
14
  "types": "./index.d.ts",
14
15
  "import": "./index.js",
15
16
  "default": "./index.js"
16
17
  }
17
18
  },
19
+ "dependencies": {
20
+ "@tabler/icons-react": "^3.44.0",
21
+ "react-markdown": "^10.1.0",
22
+ "@epam/pdf-highlighter-kit": "^0.0.19"
23
+ },
18
24
  "peerDependencies": {
19
- "react": "^19.0.0",
20
- "@tabler/icons-react": "^3.0.0",
21
- "@epam/ai-dial-chat-shared": "1.1.0-dev.99",
22
- "@epam/ai-dial-ui-kit": "^0.13.0-dev.26",
23
- "@epam/pdf-highlighter-kit": ">=0.0.14"
25
+ "react": "^19.2.8",
26
+ "@epam/ai-dial-chat-shared": "1.2.0-dev.1",
27
+ "@epam/ai-dial-ui-kit": "^0.14.2"
24
28
  },
25
29
  "repository": {
26
30
  "type": "git",
@@ -1,27 +1,23 @@
1
- import { Annotation, AttachmentResource, Message, MessageAttachment } from '@epam/ai-dial-chat-shared';
1
+ import { Annotation, AnnotationSelector, DocxRangeSelector, ExcelRcRangeSelector, Message, PptxRangeSelector } from '@epam/ai-dial-chat-shared';
2
2
  import { InputHighlightData } from '@epam/pdf-highlighter-kit';
3
+ import { OfficeHighlightLocation } from '../models/office-highlight';
3
4
  /**
4
5
  * Maps a list of annotations to `InputHighlightData` entries for the PDF viewer.
5
- * Annotations whose `body.selector` contains no `pdf_bbox` selectors are skipped.
6
- * The highlight `id` is `annotation.index` when present, otherwise the position
7
- * in the input array.
6
+ * Recognizes `pdf_bbox` selectors and both `pdf_region` coordinate forms
7
+ * (`lt`/`wh` and legacy `left`/`top`/`width`/`height`); annotations whose
8
+ * `body.selector` contains none of these are skipped. The highlight `id` is
9
+ * `annotation.index` when present, otherwise the position in the input array.
8
10
  */
9
11
  export declare const annotationsToPdfHighlights: (annotations: Annotation[]) => InputHighlightData[];
10
12
  /** Returns a stable string ID for a given annotation, matching the IDs produced by `annotationsToPdfHighlights`. */
11
13
  export declare const annotationHighlightId: (annotation: Annotation, fallbackIndex: number) => string;
12
14
  /**
13
- * Normalizes raw annotations from the API wire format (stored in
14
- * `message.custom_fields.annotations`) to the internal `Annotation` model.
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.
20
- *
21
- * Annotations whose attachment index cannot be resolved or whose selector
22
- * is not a recognised PDF region are omitted from the result.
15
+ * Returns the first positive integer PDF page in the annotation's body selectors,
16
+ * or `undefined` when none exists. Recognizes `pdf_bbox` selectors and both
17
+ * `pdf_region` coordinate forms; a page is returned only for a selector whose
18
+ * geometry also validates (see `readPdfSelectorBox`).
23
19
  */
24
- export declare const normalizeRawAnnotations: (rawAnnotations: unknown[], attachments: MessageAttachment[]) => Annotation[];
20
+ export declare const getAnnotationPdfPage: (annotation: Annotation) => number | undefined;
25
21
  /**
26
22
  * Resolves the annotation list for a message regardless of how it was loaded.
27
23
  *
@@ -30,5 +26,26 @@ export declare const normalizeRawAnnotations: (rawAnnotations: unknown[], attach
30
26
  * normalises those entries using the message's `custom_content.attachments`.
31
27
  */
32
28
  export declare const resolveMessageAnnotations: (message: Message) => Annotation[];
33
- export type { AttachmentResource };
29
+ /**
30
+ * Returns whether `selector` is a `docx_text_range` selector carrying every
31
+ * field the shape requires — a `_range`-suffixed selector missing any field
32
+ * (or with a wrongly-typed one) does not match.
33
+ */
34
+ export declare const isDocxRangeSelector: (selector: AnnotationSelector) => selector is DocxRangeSelector;
35
+ /**
36
+ * Returns whether `selector` is a `pptx_text_range` selector carrying every
37
+ * field the shape requires.
38
+ */
39
+ export declare const isPptxRangeSelector: (selector: AnnotationSelector) => selector is PptxRangeSelector;
40
+ /**
41
+ * Returns whether `selector` is an `excel_rc_range` selector carrying every
42
+ * field the shape requires. `end` may be a cell address, `null`, or absent.
43
+ */
44
+ export declare const isExcelRcRangeSelector: (selector: AnnotationSelector) => selector is ExcelRcRangeSelector;
45
+ /**
46
+ * Converts an annotation's `body.selector` (scalar or array) to validated
47
+ * `OfficeHighlightLocation` entries, skipping any selector that is not a
48
+ * recognised Office range or that fails validation — never throwing.
49
+ */
50
+ export declare const annotationToOfficeHighlightLocations: (annotation: Annotation) => OfficeHighlightLocation[];
34
51
  //# sourceMappingURL=annotation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"annotation.d.ts","sourceRoot":"","sources":["../../src/utils/annotation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,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;AAGF,YAAY,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"annotation.d.ts","sourceRoot":"","sources":["../../src/utils/annotation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,OAAO,EACP,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAMnC,OAAO,KAAK,EAGV,kBAAkB,EACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAqG1E;;;;;;GAMG;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;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAC/B,YAAY,UAAU,KACrB,MAAM,GAAG,SAWX,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GAAI,SAAS,OAAO,KAAG,UAAU,EAoBtE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,UAAU,kBAAkB,KAC3B,QAAQ,IAAI,iBAWd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC9B,UAAU,kBAAkB,KAC3B,QAAQ,IAAI,iBAUd,CAAC;AAUF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GACjC,UAAU,kBAAkB,KAC3B,QAAQ,IAAI,oBAQd,CAAC;AA8FF;;;;GAIG;AACH,eAAO,MAAM,oCAAoC,GAC/C,YAAY,UAAU,KACrB,uBAAuB,EAsBzB,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,35 @@ 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[];
44
+ /**
45
+ * Returns every annotation in `annotations` whose `body.source.attachment.url`
46
+ * equals `clicked`'s, in their original order — gathering across the whole
47
+ * list rather than one `cit`-id group, so annotations behind other markers
48
+ * citing the same file are included too. Keys on URL, never on the display
49
+ * title, since two different files can share a title. Returns `[clicked]`
50
+ * when `clicked` is not itself present in `annotations` (identified by
51
+ * reference identity) or has no source URL.
52
+ */
53
+ export declare const gatherSameSourceAnnotations: (clicked: Annotation, annotations: Annotation[]) => Annotation[];
18
54
  //# 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;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,GACtC,SAAS,UAAU,EACnB,aAAa,UAAU,EAAE,KACxB,UAAU,EAKZ,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"}