@deepcitation/deepcitation-js 1.0.9 → 1.1.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.
package/README.md CHANGED
@@ -107,7 +107,7 @@ function Response({ citations, verifications }) {
107
107
  Revenue grew by
108
108
  <CitationComponent
109
109
  citation={citations["1"]}
110
- foundCitation={verifications["1"]}
110
+ verification={verifications["1"]}
111
111
  />
112
112
  this quarter.
113
113
  </p>
@@ -163,7 +163,7 @@ import {
163
163
  ```typescript
164
164
  import type {
165
165
  Citation,
166
- FoundHighlightLocation,
166
+ Verification,
167
167
  SearchState,
168
168
  SearchStatus,
169
169
  } from "@deepcitation/deepcitation-js";
@@ -154,7 +154,7 @@ export declare class DeepCitation {
154
154
  * const citations = getAllCitationsFromLlmOutput(llmResponse);
155
155
  * const verified = await dc.verifyCitations(fileId, citations);
156
156
  *
157
- * for (const [key, result] of Object.entries(verified.foundHighlights)) {
157
+ * for (const [key, result] of Object.entries(verified.verifications)) {
158
158
  * console.log(key, result.searchState?.status);
159
159
  * // "found", "partial_text_found", "not_found", etc.
160
160
  * }
@@ -175,7 +175,7 @@ export declare class DeepCitation {
175
175
  * fileDataParts, // From prepareFiles()
176
176
  * });
177
177
  *
178
- * for (const [key, result] of Object.entries(result.foundHighlights)) {
178
+ * for (const [key, result] of Object.entries(result.verifications)) {
179
179
  * console.log(key, result.searchState?.status);
180
180
  * }
181
181
  * ```
@@ -237,13 +237,19 @@ export class DeepCitation {
237
237
  return { fileDataParts: [], deepTextPromptPortion: [] };
238
238
  }
239
239
  // Upload all files in parallel
240
- const uploadPromises = files.map(({ file, filename, fileId }) => this.uploadFile(file, { filename, fileId }));
241
- const results = await Promise.all(uploadPromises);
242
- // Extract file data parts and file deep texts
243
- const fileDataParts = results.map((result) => ({
240
+ const uploadPromises = files.map(({ file, filename, fileId }) => this.uploadFile(file, { filename, fileId }).then((result) => ({
241
+ result,
242
+ filename,
243
+ })));
244
+ const uploadResults = await Promise.all(uploadPromises);
245
+ // Extract file data parts with deepTextPromptPortion included (single source of truth)
246
+ const fileDataParts = uploadResults.map(({ result, filename }) => ({
244
247
  fileId: result.fileId,
248
+ deepTextPromptPortion: result.deepTextPromptPortion,
249
+ filename: filename || result.metadata?.filename,
245
250
  }));
246
- const deepTextPromptPortion = results.map((result) => result.deepTextPromptPortion);
251
+ // Also return separate array for backwards compatibility (deprecated)
252
+ const deepTextPromptPortion = fileDataParts.map((part) => part.deepTextPromptPortion);
247
253
  return { fileDataParts, deepTextPromptPortion };
248
254
  }
249
255
  /**
@@ -261,7 +267,7 @@ export class DeepCitation {
261
267
  * const citations = getAllCitationsFromLlmOutput(llmResponse);
262
268
  * const verified = await dc.verifyCitations(fileId, citations);
263
269
  *
264
- * for (const [key, result] of Object.entries(verified.foundHighlights)) {
270
+ * for (const [key, result] of Object.entries(verified.verifications)) {
265
271
  * console.log(key, result.searchState?.status);
266
272
  * // "found", "partial_text_found", "not_found", etc.
267
273
  * }
@@ -328,7 +334,7 @@ export class DeepCitation {
328
334
  * fileDataParts, // From prepareFiles()
329
335
  * });
330
336
  *
331
- * for (const [key, result] of Object.entries(result.foundHighlights)) {
337
+ * for (const [key, result] of Object.entries(result.verifications)) {
332
338
  * console.log(key, result.searchState?.status);
333
339
  * }
334
340
  * ```
@@ -340,7 +346,7 @@ export class DeepCitation {
340
346
  citations = getAllCitationsFromLlmOutput(llmOutput);
341
347
  // If no citations found, return empty result
342
348
  if (Object.keys(citations).length === 0) {
343
- return { foundHighlights: {} };
349
+ return { verifications: {} };
344
350
  }
345
351
  // Group citations by fileId
346
352
  const citationsByFile = new Map();
@@ -361,8 +367,8 @@ export class DeepCitation {
361
367
  const results = await Promise.all(verificationPromises);
362
368
  const allHighlights = {};
363
369
  for (const result of results) {
364
- Object.assign(allHighlights, result.foundHighlights);
370
+ Object.assign(allHighlights, result.verifications);
365
371
  }
366
- return { foundHighlights: allHighlights };
372
+ return { verifications: allHighlights };
367
373
  }
368
374
  }
@@ -1,4 +1,4 @@
1
- import type { Citation, FoundHighlightLocation } from "../types/index.js";
1
+ import type { Citation, Verification } from "../types/index.js";
2
2
  /**
3
3
  * Configuration options for the DeepCitation client
4
4
  */
@@ -51,7 +51,7 @@ export interface UploadFileOptions {
51
51
  */
52
52
  export interface VerifyCitationsResponse {
53
53
  /** Map of citation keys to their verification results */
54
- foundHighlights: Record<string, FoundHighlightLocation>;
54
+ verifications: Record<string, Verification>;
55
55
  }
56
56
  /**
57
57
  * Options for citation verification
@@ -81,14 +81,22 @@ export interface FileInput {
81
81
  export interface FileDataPart {
82
82
  /** The file ID assigned by DeepCitation */
83
83
  fileId: string;
84
+ /** The formatted text content for LLM prompts (with page markers and line IDs) */
85
+ deepTextPromptPortion: string;
86
+ /** Optional filename for display purposes */
87
+ filename?: string;
84
88
  }
85
89
  /**
86
90
  * Result from prepareFiles
87
91
  */
88
92
  export interface PrepareFilesResult {
89
- /** Array of file references for verification */
93
+ /** Array of file references for verification (includes deepTextPromptPortion for each file) */
90
94
  fileDataParts: FileDataPart[];
91
- /** Array of formatted text content for LLM prompts (with page markers and line IDs) */
95
+ /**
96
+ * Array of formatted text content for LLM prompts (with page markers and line IDs).
97
+ * @deprecated Use fileDataParts[].deepTextPromptPortion instead for single source of truth.
98
+ * This is kept for backwards compatibility but will be removed in a future version.
99
+ */
92
100
  deepTextPromptPortion: string[];
93
101
  }
94
102
  /**
package/lib/index.d.ts CHANGED
@@ -9,8 +9,8 @@ export { normalizeCitations, getCitationPageNumber, } from "./parsing/normalizeC
9
9
  export { isGeminiGarbage, cleanRepeatingLastSentence, } from "./parsing/parseWorkAround.js";
10
10
  export type { Citation, CitationStatus, VerifyCitationRequest, VerifyCitationResponse, OutputImageFormat, } from "./types/citation.js";
11
11
  export { DEFAULT_OUTPUT_IMAGE_FORMAT } from "./types/citation.js";
12
- export type { FoundHighlightLocation } from "./types/foundHighlight.js";
13
- export { NOT_FOUND_HIGHLIGHT_INDEX, PENDING_HIGHLIGHT_INDEX, BLANK_HIGHLIGHT_LOCATION, deterministicIdFromHighlightLocation, } from "./types/foundHighlight.js";
12
+ export type { Verification } from "./types/verification.js";
13
+ export { NOT_FOUND_VERIFICATION_INDEX, PENDING_VERIFICATION_INDEX, BLANK_VERIFICATION, deterministicIdFromVerification, } from "./types/verification.js";
14
14
  export type { SearchState, SearchStatus, SearchMethod, SearchAttempt, } from "./types/search.js";
15
15
  export type { ScreenBox, PdfSpaceItem, IVertex } from "./types/boxes.js";
16
16
  export { sha1Hash } from "./utils/sha.js";
package/lib/index.js CHANGED
@@ -9,7 +9,7 @@ export { parseCitation, getCitationStatus, getAllCitationsFromLlmOutput, groupCi
9
9
  export { normalizeCitations, getCitationPageNumber, } from "./parsing/normalizeCitation.js";
10
10
  export { isGeminiGarbage, cleanRepeatingLastSentence, } from "./parsing/parseWorkAround.js";
11
11
  export { DEFAULT_OUTPUT_IMAGE_FORMAT } from "./types/citation.js";
12
- export { NOT_FOUND_HIGHLIGHT_INDEX, PENDING_HIGHLIGHT_INDEX, BLANK_HIGHLIGHT_LOCATION, deterministicIdFromHighlightLocation, } from "./types/foundHighlight.js";
12
+ export { NOT_FOUND_VERIFICATION_INDEX, PENDING_VERIFICATION_INDEX, BLANK_VERIFICATION, deterministicIdFromVerification, } from "./types/verification.js";
13
13
  // Utilities
14
14
  export { sha1Hash } from "./utils/sha.js";
15
15
  export { generateCitationKey } from "./react/utils.js";
@@ -1,12 +1,12 @@
1
- import { type FoundHighlightLocation } from "../types/foundHighlight.js";
1
+ import { type Verification } from "../types/verification.js";
2
2
  import { type Citation, type CitationStatus } from "../types/citation.js";
3
3
  /**
4
4
  * Calculates the verification status of a citation based on the found highlight and search state.
5
5
  *
6
- * @param foundHighlight - The found highlight location, or null/undefined if not found
6
+ * @param verification - The found highlight location, or null/undefined if not found
7
7
  * @returns An object containing boolean flags for verification status
8
8
  */
9
- export declare function getCitationStatus(foundHighlight: FoundHighlightLocation | null | undefined): CitationStatus;
9
+ export declare function getCitationStatus(verification: Verification | null | undefined): CitationStatus;
10
10
  export declare const parseCitation: (fragment: string, mdAttachmentId?: string | null, citationCounterRef?: any | null, isVerbose?: boolean) => {
11
11
  beforeCite: string;
12
12
  afterCite: string;
@@ -48,11 +48,11 @@ function parseLineIds(lineIdsString) {
48
48
  /**
49
49
  * Calculates the verification status of a citation based on the found highlight and search state.
50
50
  *
51
- * @param foundHighlight - The found highlight location, or null/undefined if not found
51
+ * @param verification - The found highlight location, or null/undefined if not found
52
52
  * @returns An object containing boolean flags for verification status
53
53
  */
54
- export function getCitationStatus(foundHighlight) {
55
- const searchState = foundHighlight?.searchState;
54
+ export function getCitationStatus(verification) {
55
+ const searchState = verification?.searchState;
56
56
  const isMiss = searchState?.status === "not_found";
57
57
  const isFullMatchWithMissedValue = searchState?.status === "found_phrase_missed_value";
58
58
  const isFoundValueMissedFullMatch = searchState?.status === "found_value_only";
@@ -1,6 +1,6 @@
1
1
  import React, { type ReactNode } from "react";
2
2
  import { type CitationStatus } from "../types/citation.js";
3
- import type { FoundHighlightLocation } from "../types/foundHighlight.js";
3
+ import type { Verification } from "../types/verification.js";
4
4
  import type { BaseCitationProps, CitationEventHandlers, CitationRenderProps, CitationVariant } from "./types.js";
5
5
  import "./styles.css";
6
6
  export type { CitationVariant } from "./types.js";
@@ -11,7 +11,7 @@ export type { CitationVariant } from "./types.js";
11
11
  * ```tsx
12
12
  * <CitationComponent
13
13
  * citation={{ citationNumber: 1, fullPhrase: "Revenue grew by 25%" }}
14
- * foundCitation={verificationResult}
14
+ * verification={verificationResult}
15
15
  * />
16
16
  * // Renders: [1✓] with blue text
17
17
  * ```
@@ -20,7 +20,7 @@ export type { CitationVariant } from "./types.js";
20
20
  * ```tsx
21
21
  * <CitationComponent
22
22
  * citation={{ citationNumber: 1, value: "25% growth" }}
23
- * foundCitation={verificationResult}
23
+ * verification={verificationResult}
24
24
  * variant="numeric"
25
25
  * />
26
26
  * // Renders: 1✓
@@ -30,7 +30,7 @@ export type { CitationVariant } from "./types.js";
30
30
  * ```tsx
31
31
  * <CitationComponent
32
32
  * citation={{ citationNumber: 1, value: "25% growth" }}
33
- * foundCitation={verificationResult}
33
+ * verification={verificationResult}
34
34
  * variant="text"
35
35
  * />
36
36
  * // Renders: 25% growth✓
@@ -40,7 +40,7 @@ export type { CitationVariant } from "./types.js";
40
40
  * ```tsx
41
41
  * <CitationComponent
42
42
  * citation={citation}
43
- * foundCitation={verificationResult}
43
+ * verification={verificationResult}
44
44
  * variant="minimal"
45
45
  * />
46
46
  * // Renders: Revenue grew...✓
@@ -50,7 +50,7 @@ export type { CitationVariant } from "./types.js";
50
50
  * ```tsx
51
51
  * <CitationComponent
52
52
  * citation={citation}
53
- * foundCitation={verificationResult}
53
+ * verification={verificationResult}
54
54
  * variant="indicator"
55
55
  * />
56
56
  * // Renders: ✓
@@ -60,7 +60,7 @@ export type { CitationVariant } from "./types.js";
60
60
  * ```tsx
61
61
  * <CitationComponent
62
62
  * citation={citation}
63
- * foundCitation={verificationResult}
63
+ * verification={verificationResult}
64
64
  * popoverPosition="hidden"
65
65
  * />
66
66
  * ```
@@ -70,7 +70,7 @@ export interface CitationComponentProps extends BaseCitationProps {
70
70
  * Verification result from the DeepCitation API.
71
71
  * Contains match snippet, page number, and verification image.
72
72
  */
73
- foundCitation?: FoundHighlightLocation | null;
73
+ verification?: Verification | null;
74
74
  /**
75
75
  * Display variant for the citation.
76
76
  * - `brackets`: Shows value/number in brackets, blue text styling (default)
@@ -110,7 +110,7 @@ export interface CitationComponentProps extends BaseCitationProps {
110
110
  */
111
111
  renderPopoverContent?: (props: {
112
112
  citation: BaseCitationProps["citation"];
113
- foundCitation: FoundHighlightLocation | null;
113
+ verification: Verification | null;
114
114
  status: CitationStatus;
115
115
  }) => ReactNode;
116
116
  }
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState, } from "react";
3
3
  import { createPortal } from "react-dom";
4
4
  import { CheckIcon, WarningIcon } from "./icons.js";
5
- import { classNames, generateCitationInstanceId, generateCitationKey, getCitationDisplayText } from "./utils.js";
5
+ import { classNames, generateCitationInstanceId, generateCitationKey, getCitationDisplayText, } from "./utils.js";
6
6
  import { getCitationStatus } from "../parsing/parseCitation.js";
7
7
  import "./styles.css";
8
8
  const TWO_DOTS_THINKING_CONTENT = "..";
@@ -74,13 +74,13 @@ function getFoundStatusClass(status) {
74
74
  * Status tooltip content for miss/partial states.
75
75
  * Shows explanation when hovering over citations with issues.
76
76
  */
77
- const StatusTooltipContent = ({ citation, status, foundCitation, isExpanded, onToggleExpand, }) => {
77
+ const StatusTooltipContent = ({ citation, status, verification, isExpanded, onToggleExpand, }) => {
78
78
  const { isMiss, isPartialMatch } = status;
79
79
  if (!isMiss && !isPartialMatch)
80
80
  return null;
81
- // Get search attempts from foundCitation
82
- const searchAttempts = foundCitation?.searchState?.searchAttempts;
83
- const failedAttempts = searchAttempts?.filter(a => !a.success) || [];
81
+ // Get search attempts from verification
82
+ const searchAttempts = verification?.searchState?.searchAttempts;
83
+ const failedAttempts = searchAttempts?.filter((a) => !a.success) || [];
84
84
  // Collect all unique phrases tried
85
85
  const allPhrases = [];
86
86
  const seenPhrases = new Set();
@@ -105,8 +105,10 @@ const StatusTooltipContent = ({ citation, status, foundCitation, isExpanded, onT
105
105
  }
106
106
  if (isPartialMatch) {
107
107
  const expectedText = citation.fullPhrase || citation.value || "";
108
- const actualText = foundCitation?.matchSnippet || "";
109
- const truncatedExpected = expectedText.length > 100 ? expectedText.slice(0, 100) + "…" : expectedText;
108
+ const actualText = verification?.matchSnippet || "";
109
+ const truncatedExpected = expectedText.length > 100
110
+ ? expectedText.slice(0, 100) + "…"
111
+ : expectedText;
110
112
  const truncatedActual = actualText.length > 100 ? actualText.slice(0, 100) + "…" : actualText;
111
113
  return (_jsxs("span", { className: "dc-status-tooltip", role: "tooltip", children: [_jsxs("span", { className: "dc-status-header dc-status-header--partial", children: [_jsx(WarningIcon, {}), _jsx("span", { children: "Partial match" })] }), _jsx("span", { className: "dc-status-description", children: "Text differs from citation." }), truncatedExpected && (_jsxs("span", { className: "dc-status-searched", children: [_jsx("span", { className: "dc-status-label", children: "Expected" }), _jsx("span", { className: "dc-status-text", children: truncatedExpected })] })), truncatedActual && (_jsxs("span", { className: "dc-status-searched", children: [_jsx("span", { className: "dc-status-label", children: "Found" }), _jsx("span", { className: "dc-status-text", children: truncatedActual })] }))] }));
112
114
  }
@@ -116,7 +118,7 @@ const StatusTooltipContent = ({ citation, status, foundCitation, isExpanded, onT
116
118
  * Full-size image overlay component.
117
119
  * Uses portal to render at document body level.
118
120
  */
119
- const ImageOverlay = ({ src, alt, onClose }) => {
121
+ const ImageOverlay = ({ src, alt, onClose, }) => {
120
122
  const handleBackdropClick = useCallback((e) => {
121
123
  if (e.target === e.currentTarget) {
122
124
  onClose();
@@ -138,28 +140,28 @@ const ImageOverlay = ({ src, alt, onClose }) => {
138
140
  * Default popover content component.
139
141
  * Shows verification image if available, otherwise shows text info.
140
142
  */
141
- const DefaultPopoverContent = ({ foundCitation, status, onImageClick, }) => {
142
- const hasImage = foundCitation?.verificationImageBase64;
143
+ const DefaultPopoverContent = ({ verification, status, onImageClick, }) => {
144
+ const hasImage = verification?.verificationImageBase64;
143
145
  const handleImageClick = useCallback((e) => {
144
146
  e.preventDefault();
145
147
  e.stopPropagation();
146
148
  if (hasImage && onImageClick) {
147
- onImageClick(foundCitation.verificationImageBase64);
149
+ onImageClick(verification.verificationImageBase64);
148
150
  }
149
- }, [hasImage, foundCitation?.verificationImageBase64, onImageClick]);
151
+ }, [hasImage, verification?.verificationImageBase64, onImageClick]);
150
152
  // If we have a verification image, show only the image
151
153
  if (hasImage) {
152
- return (_jsx("button", { type: "button", className: "dc-popover-image-button", onClick: handleImageClick, "aria-label": "Click to view full size", children: _jsx("img", { src: foundCitation.verificationImageBase64, alt: "Citation verification", className: "dc-popover-image", loading: "lazy" }) }));
154
+ return (_jsx("button", { type: "button", className: "dc-popover-image-button", onClick: handleImageClick, "aria-label": "Click to view full size", children: _jsx("img", { src: verification.verificationImageBase64, alt: "Citation verification", className: "dc-popover-image", loading: "lazy" }) }));
153
155
  }
154
156
  // No image - show text info
155
157
  const statusLabel = getStatusLabel(status);
156
158
  const statusClass = getPopoverStatusClass(status);
157
- const hasSnippet = foundCitation?.matchSnippet;
158
- const pageNumber = foundCitation?.pageNumber;
159
+ const hasSnippet = verification?.matchSnippet;
160
+ const pageNumber = verification?.pageNumber;
159
161
  if (!hasSnippet && !statusLabel) {
160
162
  return null;
161
163
  }
162
- return (_jsxs(_Fragment, { children: [statusLabel && _jsx("span", { className: classNames("dc-popover-status", statusClass), children: statusLabel }), hasSnippet && _jsxs("span", { className: "dc-popover-snippet", children: ["\"", foundCitation.matchSnippet, "\""] }), pageNumber && pageNumber > 0 && _jsxs("span", { className: "dc-popover-page", children: ["Page ", pageNumber] })] }));
164
+ return (_jsxs(_Fragment, { children: [statusLabel && (_jsx("span", { className: classNames("dc-popover-status", statusClass), children: statusLabel })), hasSnippet && (_jsxs("span", { className: "dc-popover-snippet", children: ["\"", verification.matchSnippet, "\""] })), pageNumber && pageNumber > 0 && (_jsxs("span", { className: "dc-popover-page", children: ["Page ", pageNumber] }))] }));
163
165
  };
164
166
  // =============================================================================
165
167
  // MAIN COMPONENT
@@ -180,7 +182,7 @@ const DefaultPopoverContent = ({ foundCitation, status, onImageClick, }) => {
180
182
  * This means partial matches have blue text (because they were found) but
181
183
  * an orange indicator (because they didn't match exactly).
182
184
  */
183
- export const CitationComponent = forwardRef(({ citation, children, className, displayCitationValue = false, fallbackDisplay, foundCitation, variant = "brackets", eventHandlers, isMobile = false, renderIndicator, renderContent, popoverPosition = "top", renderPopoverContent, }, ref) => {
185
+ export const CitationComponent = forwardRef(({ citation, children, className, displayCitationValue = false, fallbackDisplay, verification, variant = "brackets", eventHandlers, isMobile = false, renderIndicator, renderContent, popoverPosition = "top", renderPopoverContent, }, ref) => {
184
186
  const containerRef = useRef(null);
185
187
  const wrapperRef = useRef(null);
186
188
  const [expandedImageSrc, setExpandedImageSrc] = useState(null);
@@ -195,14 +197,15 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
195
197
  const handleTogglePhrases = useCallback((e) => {
196
198
  e?.preventDefault();
197
199
  e?.stopPropagation();
198
- setIsPhrasesExpanded(prev => !prev);
200
+ setIsPhrasesExpanded((prev) => !prev);
199
201
  }, []);
200
202
  // Handle click outside to close expanded tooltip
201
203
  useEffect(() => {
202
204
  if (!isTooltipExpanded)
203
205
  return;
204
206
  const handleClickOutside = (event) => {
205
- if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
207
+ if (wrapperRef.current &&
208
+ !wrapperRef.current.contains(event.target)) {
206
209
  setIsTooltipExpanded(false);
207
210
  }
208
211
  };
@@ -232,7 +235,7 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
232
235
  e.preventDefault();
233
236
  e.stopPropagation();
234
237
  // If we have a verification image
235
- if (foundCitation?.verificationImageBase64) {
238
+ if (verification?.verificationImageBase64) {
236
239
  if (expandedImageSrc) {
237
240
  // Image is open - close it and unpin
238
241
  setExpandedImageSrc(null);
@@ -240,7 +243,7 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
240
243
  }
241
244
  else if (isTooltipExpanded) {
242
245
  // Already pinned - second click expands image
243
- setExpandedImageSrc(foundCitation.verificationImageBase64);
246
+ setExpandedImageSrc(verification.verificationImageBase64);
244
247
  }
245
248
  else {
246
249
  // First click - just pin the popover open
@@ -249,19 +252,19 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
249
252
  }
250
253
  else {
251
254
  // No image - toggle phrases expansion for miss/partial tooltips
252
- setIsTooltipExpanded(prev => !prev);
253
- setIsPhrasesExpanded(prev => !prev);
255
+ setIsTooltipExpanded((prev) => !prev);
256
+ setIsPhrasesExpanded((prev) => !prev);
254
257
  }
255
258
  eventHandlers?.onClick?.(citation, citationKey, e);
256
259
  }, [
257
260
  eventHandlers,
258
261
  citation,
259
262
  citationKey,
260
- foundCitation?.verificationImageBase64,
263
+ verification?.verificationImageBase64,
261
264
  expandedImageSrc,
262
265
  isTooltipExpanded,
263
266
  ]);
264
- const status = getCitationStatus(foundCitation ?? null);
267
+ const status = getCitationStatus(verification ?? null);
265
268
  // const { isVerified, isPending } = status;
266
269
  const { isMiss, isPartialMatch, isVerified, isPending } = status;
267
270
  const displayText = useMemo(() => {
@@ -271,7 +274,10 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
271
274
  }
272
275
  // For text/minimal/brackets, show the value or fullPhrase
273
276
  return getCitationDisplayText(citation, {
274
- displayCitationValue: variant === "text" || variant === "minimal" || variant === "brackets" || displayCitationValue,
277
+ displayCitationValue: variant === "text" ||
278
+ variant === "minimal" ||
279
+ variant === "brackets" ||
280
+ displayCitationValue,
275
281
  fallbackDisplay,
276
282
  });
277
283
  }, [citation, variant, displayCitationValue, fallbackDisplay]);
@@ -292,8 +298,11 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
292
298
  }
293
299
  }, [eventHandlers, citation, citationKey, isMobile]);
294
300
  // Early return for miss with fallback display
295
- if (fallbackDisplay !== null && fallbackDisplay !== undefined && displayCitationValue && isMiss) {
296
- return _jsx("span", { className: classNames("dc-citation-fallback", className), children: fallbackDisplay });
301
+ if (fallbackDisplay !== null &&
302
+ fallbackDisplay !== undefined &&
303
+ displayCitationValue &&
304
+ isMiss) {
305
+ return (_jsx("span", { className: classNames("dc-citation-fallback", className), children: fallbackDisplay }));
297
306
  }
298
307
  // Render the appropriate indicator based on match quality
299
308
  const renderStatusIndicator = () => {
@@ -323,12 +332,14 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
323
332
  status,
324
333
  citationKey,
325
334
  displayText,
326
- isMergedDisplay: variant === "text" || variant === "brackets" || displayCitationValue,
335
+ isMergedDisplay: variant === "text" ||
336
+ variant === "brackets" ||
337
+ displayCitationValue,
327
338
  });
328
339
  }
329
340
  // Indicator-only variant - just the checkmark/warning
330
341
  if (variant === "indicator") {
331
- return _jsx("span", { className: "dc-citation-text", children: renderStatusIndicator() });
342
+ return (_jsx("span", { className: "dc-citation-text", children: renderStatusIndicator() }));
332
343
  }
333
344
  // Text variant - no special styling, shows value with indicator
334
345
  if (variant === "text") {
@@ -347,23 +358,30 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
347
358
  };
348
359
  // Determine if popover should be shown
349
360
  const isPopoverHidden = popoverPosition === "hidden";
350
- const shouldShowPopover = !isPopoverHidden && foundCitation && (foundCitation.verificationImageBase64 || foundCitation.matchSnippet);
361
+ const shouldShowPopover = !isPopoverHidden &&
362
+ verification &&
363
+ (verification.verificationImageBase64 || verification.matchSnippet);
351
364
  // Determine if status tooltip should be shown (miss/partial without full verification)
352
365
  const shouldShowStatusTooltip = !isPopoverHidden && (isMiss || isPartialMatch) && !shouldShowPopover;
353
366
  // Popover content - determine position class (only "top" or "bottom" add classes)
354
367
  const popoverPositionClass = popoverPosition === "bottom" ? "dc-popover--bottom" : "";
355
- const popoverContent = shouldShowPopover ? (_jsx("span", { className: classNames("dc-popover", popoverPositionClass), children: renderPopoverContent ? (renderPopoverContent({ citation, foundCitation: foundCitation ?? null, status })) : (_jsx(DefaultPopoverContent, { citation: citation, foundCitation: foundCitation ?? null, status: status, onImageClick: handleImageClick })) })) : null;
368
+ const popoverContent = shouldShowPopover ? (_jsx("span", { className: classNames("dc-popover", popoverPositionClass), children: renderPopoverContent ? (renderPopoverContent({
369
+ citation,
370
+ verification: verification ?? null,
371
+ status,
372
+ })) : (_jsx(DefaultPopoverContent, { citation: citation, verification: verification ?? null, status: status, onImageClick: handleImageClick })) })) : null;
356
373
  // Status tooltip for miss/partial explanations
357
- const statusTooltipContent = shouldShowStatusTooltip ? (_jsx(StatusTooltipContent, { citation: citation, status: status, foundCitation: foundCitation ?? null, isExpanded: isPhrasesExpanded, onToggleExpand: handleTogglePhrases })) : null;
358
- const citationTrigger = (_jsx("span", { ref: node => {
359
- containerRef.current = node;
374
+ const statusTooltipContent = shouldShowStatusTooltip ? (_jsx(StatusTooltipContent, { citation: citation, status: status, verification: verification ?? null, isExpanded: isPhrasesExpanded, onToggleExpand: handleTogglePhrases })) : null;
375
+ const citationTrigger = (_jsx("span", { ref: (node) => {
376
+ containerRef.current =
377
+ node;
360
378
  if (typeof ref === "function") {
361
379
  ref(node);
362
380
  }
363
381
  else if (ref) {
364
382
  ref.current = node;
365
383
  }
366
- }, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-tooltip-expanded": isTooltipExpanded, "data-has-image": !!foundCitation?.verificationImageBase64, className: classNames("dc-citation", `dc-citation--${variant}`, foundStatusClass, className), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onClick: handleToggleTooltip, onTouchEndCapture: isMobile ? handleTouchEnd : undefined, "aria-label": displayText ? `[${displayText}]` : undefined, "aria-expanded": isTooltipExpanded, children: renderCitationContent() }));
384
+ }, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-tooltip-expanded": isTooltipExpanded, "data-has-image": !!verification?.verificationImageBase64, className: classNames("dc-citation", `dc-citation--${variant}`, foundStatusClass, className), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onClick: handleToggleTooltip, onTouchEndCapture: isMobile ? handleTouchEnd : undefined, "aria-label": displayText ? `[${displayText}]` : undefined, "aria-expanded": isTooltipExpanded, children: renderCitationContent() }));
367
385
  // Image overlay for full-size view
368
386
  const imageOverlay = expandedImageSrc ? (_jsx(ImageOverlay, { src: expandedImageSrc, alt: "Citation verification - full size", onClose: handleCloseOverlay })) : null;
369
387
  // Wrap with popover or status tooltip if needed
@@ -1,6 +1,6 @@
1
1
  import React, { type ReactNode } from "react";
2
2
  import type { CitationStatus } from "../types/citation.js";
3
- import type { FoundHighlightLocation } from "../types/foundHighlight.js";
3
+ import type { Verification } from "../types/verification.js";
4
4
  import type { SearchState } from "../types/search.js";
5
5
  import type { BaseCitationProps, CitationVariant as CitationVariantType, CitationEventHandlers } from "./types.js";
6
6
  /**
@@ -8,7 +8,7 @@ import type { BaseCitationProps, CitationVariant as CitationVariantType, Citatio
8
8
  */
9
9
  export interface CitationVariantProps extends BaseCitationProps {
10
10
  /** Found citation highlight location data */
11
- foundCitation?: FoundHighlightLocation | null;
11
+ verification?: Verification | null;
12
12
  /** Current search state for the citation */
13
13
  searchState?: SearchState | null;
14
14
  /** Event handlers */
@@ -38,7 +38,7 @@ export interface ChipCitationProps extends CitationVariantProps {
38
38
  *
39
39
  * @example
40
40
  * ```tsx
41
- * <ChipCitation citation={citation} foundCitation={found} size="md" />
41
+ * <ChipCitation citation={citation} verification={found} size="md" />
42
42
  * ```
43
43
  */
44
44
  export declare const ChipCitation: React.ForwardRefExoticComponent<ChipCitationProps & React.RefAttributes<HTMLSpanElement>>;
@@ -52,7 +52,7 @@ export interface SuperscriptCitationProps extends CitationVariantProps {
52
52
  *
53
53
  * @example
54
54
  * ```tsx
55
- * <SuperscriptCitation citation={citation} foundCitation={found} />
55
+ * <SuperscriptCitation citation={citation} verification={found} />
56
56
  * // Renders: Text content¹
57
57
  * ```
58
58
  */
@@ -1,17 +1,17 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { memo, useMemo, useCallback, forwardRef } from "react";
2
+ import { memo, useMemo, useCallback, forwardRef, } from "react";
3
3
  import { getCitationStatus } from "../parsing/parseCitation.js";
4
4
  import { generateCitationKey, generateCitationInstanceId, getCitationDisplayText, getCitationValueText, classNames, } from "./utils.js";
5
5
  const TWO_DOTS_THINKING_CONTENT = "..";
6
6
  /**
7
7
  * Hook to get common citation data.
8
- * NOTE: Status is not memoized because foundCitation may be mutated in place.
8
+ * NOTE: Status is not memoized because verification may be mutated in place.
9
9
  */
10
- function useCitationData(citation, foundCitation) {
10
+ function useCitationData(citation, verification) {
11
11
  const citationKey = useMemo(() => generateCitationKey(citation), [citation]);
12
12
  const citationInstanceId = useMemo(() => generateCitationInstanceId(citationKey), [citationKey]);
13
13
  // Don't memoize - object reference as dependency causes stale values on mutation
14
- const status = getCitationStatus(foundCitation ?? null);
14
+ const status = getCitationStatus(verification ?? null);
15
15
  return { citationKey, citationInstanceId, status };
16
16
  }
17
17
  /**
@@ -28,11 +28,11 @@ const DefaultPartialIndicator = () => (_jsx("span", { className: "citation-parti
28
28
  *
29
29
  * @example
30
30
  * ```tsx
31
- * <ChipCitation citation={citation} foundCitation={found} size="md" />
31
+ * <ChipCitation citation={citation} verification={found} size="md" />
32
32
  * ```
33
33
  */
34
- export const ChipCitation = forwardRef(({ citation, children, className, displayCitationValue = false, fallbackDisplay, foundCitation, eventHandlers, isMobile = false, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), size = "md", showIcon = false, icon, }, ref) => {
35
- const { citationKey, citationInstanceId, status } = useCitationData(citation, foundCitation);
34
+ export const ChipCitation = forwardRef(({ citation, children, className, displayCitationValue = false, fallbackDisplay, verification, eventHandlers, isMobile = false, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), size = "md", showIcon = false, icon, }, ref) => {
35
+ const { citationKey, citationInstanceId, status } = useCitationData(citation, verification);
36
36
  const { isVerified, isMiss, isPartialMatch, isPending } = status;
37
37
  const displayText = useMemo(() => getCitationDisplayText(citation, {
38
38
  displayCitationValue,
@@ -67,7 +67,8 @@ export const ChipCitation = forwardRef(({ citation, children, className, display
67
67
  : isPending
68
68
  ? "citation-chip--pending"
69
69
  : "";
70
- return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "chip", className: classNames("citation-chip", sizeClasses[size], statusClass, className), onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onMouseDown: handleClick, onClick: e => e.stopPropagation(), "aria-label": displayText ? `Citation: ${displayText}` : undefined, children: [showIcon && (icon || _jsx("span", { className: "citation-chip__icon", children: "\uD83D\uDCC4" })), valueText && !displayCitationValue && _jsx("span", { className: "citation-chip__value", children: valueText }), _jsx("span", { className: "citation-chip__text", children: displayText }), isPartialMatch && renderPartialIndicator(status), isVerified && !isPartialMatch && renderVerifiedIndicator(status), isPending && _jsx("span", { className: "citation-chip__pending", children: pendingContent })] })] }));
70
+ return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "chip", className: classNames("citation-chip", sizeClasses[size], statusClass, className), onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onMouseDown: handleClick, onClick: (e) => e.stopPropagation(), "aria-label": displayText ? `Citation: ${displayText}` : undefined, children: [showIcon &&
71
+ (icon || _jsx("span", { className: "citation-chip__icon", children: "\uD83D\uDCC4" })), valueText && !displayCitationValue && (_jsx("span", { className: "citation-chip__value", children: valueText })), _jsx("span", { className: "citation-chip__text", children: displayText }), isPartialMatch && renderPartialIndicator(status), isVerified && !isPartialMatch && renderVerifiedIndicator(status), isPending && (_jsx("span", { className: "citation-chip__pending", children: pendingContent }))] })] }));
71
72
  });
72
73
  ChipCitation.displayName = "ChipCitation";
73
74
  /**
@@ -76,12 +77,12 @@ ChipCitation.displayName = "ChipCitation";
76
77
  *
77
78
  * @example
78
79
  * ```tsx
79
- * <SuperscriptCitation citation={citation} foundCitation={found} />
80
+ * <SuperscriptCitation citation={citation} verification={found} />
80
81
  * // Renders: Text content¹
81
82
  * ```
82
83
  */
83
- export const SuperscriptCitation = forwardRef(({ citation, children, className, displayCitationValue = false, fallbackDisplay, foundCitation, eventHandlers, isMobile = false, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), showBrackets = false, }, ref) => {
84
- const { citationKey, citationInstanceId, status } = useCitationData(citation, foundCitation);
84
+ export const SuperscriptCitation = forwardRef(({ citation, children, className, displayCitationValue = false, fallbackDisplay, verification, eventHandlers, isMobile = false, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), showBrackets = false, }, ref) => {
85
+ const { citationKey, citationInstanceId, status } = useCitationData(citation, verification);
85
86
  const { isVerified, isMiss, isPartialMatch, isPending } = status;
86
87
  const displayText = useMemo(() => getCitationDisplayText(citation, {
87
88
  displayCitationValue,
@@ -108,7 +109,7 @@ export const SuperscriptCitation = forwardRef(({ citation, children, className,
108
109
  : isPending
109
110
  ? "citation-superscript--pending"
110
111
  : "";
111
- return (_jsxs(_Fragment, { children: [children, _jsxs("sup", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "superscript", className: classNames("citation-superscript", statusClass, className), onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onMouseDown: handleClick, onClick: e => e.stopPropagation(), "aria-label": `Citation ${displayText}`, children: [showBrackets && "[", displayText, isPartialMatch && renderPartialIndicator(status), isVerified && !isPartialMatch && renderVerifiedIndicator(status), isPending && pendingContent, showBrackets && "]"] })] }));
112
+ return (_jsxs(_Fragment, { children: [children, _jsxs("sup", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "superscript", className: classNames("citation-superscript", statusClass, className), onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onMouseDown: handleClick, onClick: (e) => e.stopPropagation(), "aria-label": `Citation ${displayText}`, children: [showBrackets && "[", displayText, isPartialMatch && renderPartialIndicator(status), isVerified && !isPartialMatch && renderVerifiedIndicator(status), isPending && pendingContent, showBrackets && "]"] })] }));
112
113
  });
113
114
  SuperscriptCitation.displayName = "SuperscriptCitation";
114
115
  const FOOTNOTE_SYMBOLS = ["*", "†", "‡", "§", "‖", "¶"];
@@ -122,8 +123,8 @@ const FOOTNOTE_SYMBOLS = ["*", "†", "‡", "§", "‖", "¶"];
122
123
  * // Renders: Text content*
123
124
  * ```
124
125
  */
125
- export const FootnoteCitation = forwardRef(({ citation, children, className, fallbackDisplay, foundCitation, eventHandlers, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), symbolStyle = "number", customSymbol, }, ref) => {
126
- const { citationKey, citationInstanceId, status } = useCitationData(citation, foundCitation);
126
+ export const FootnoteCitation = forwardRef(({ citation, children, className, fallbackDisplay, verification, eventHandlers, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), symbolStyle = "number", customSymbol, }, ref) => {
127
+ const { citationKey, citationInstanceId, status } = useCitationData(citation, verification);
127
128
  const { isVerified, isMiss, isPartialMatch, isPending } = status;
128
129
  const displaySymbol = useMemo(() => {
129
130
  if (symbolStyle === "custom" && customSymbol)
@@ -159,7 +160,7 @@ export const FootnoteCitation = forwardRef(({ citation, children, className, fal
159
160
  : isPending
160
161
  ? "citation-footnote--pending"
161
162
  : "";
162
- return (_jsxs(_Fragment, { children: [children, _jsxs("sup", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "footnote", className: classNames("citation-footnote", statusClass, className), onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onMouseDown: handleClick, onClick: e => e.stopPropagation(), "aria-label": `Footnote ${displaySymbol}`, children: [displaySymbol, isPartialMatch && renderPartialIndicator(status), isVerified && !isPartialMatch && renderVerifiedIndicator(status), isPending && pendingContent] })] }));
163
+ return (_jsxs(_Fragment, { children: [children, _jsxs("sup", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "footnote", className: classNames("citation-footnote", statusClass, className), onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onMouseDown: handleClick, onClick: (e) => e.stopPropagation(), "aria-label": `Footnote ${displaySymbol}`, children: [displaySymbol, isPartialMatch && renderPartialIndicator(status), isVerified && !isPartialMatch && renderVerifiedIndicator(status), isPending && pendingContent] })] }));
163
164
  });
164
165
  FootnoteCitation.displayName = "FootnoteCitation";
165
166
  /**
@@ -173,8 +174,8 @@ FootnoteCitation.displayName = "FootnoteCitation";
173
174
  * ```
174
175
  */
175
176
  export const InlineCitation = forwardRef(({ citation, children, className, displayCitationValue = true, // Default to merged for inline
176
- fallbackDisplay, foundCitation, eventHandlers, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), underlineStyle = "dotted", }, ref) => {
177
- const { citationKey, citationInstanceId, status } = useCitationData(citation, foundCitation);
177
+ fallbackDisplay, verification, eventHandlers, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), underlineStyle = "dotted", }, ref) => {
178
+ const { citationKey, citationInstanceId, status } = useCitationData(citation, verification);
178
179
  const { isVerified, isMiss, isPartialMatch, isPending } = status;
179
180
  const displayText = useMemo(() => getCitationDisplayText(citation, {
180
181
  displayCitationValue,
@@ -202,7 +203,7 @@ fallbackDisplay, foundCitation, eventHandlers, preventTooltips = false, pendingC
202
203
  ? "citation-inline--pending"
203
204
  : "";
204
205
  const underlineClass = `citation-inline--underline-${underlineStyle}`;
205
- return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "inline", className: classNames("citation-inline", underlineClass, statusClass, className), onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onMouseDown: handleClick, onClick: e => e.stopPropagation(), "aria-label": `Citation: ${displayText}`, children: [displayText, isPartialMatch && renderPartialIndicator(status), isVerified && !isPartialMatch && renderVerifiedIndicator(status), isPending && _jsx("span", { className: "citation-inline__pending", children: pendingContent })] })] }));
206
+ return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "inline", className: classNames("citation-inline", underlineClass, statusClass, className), onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onMouseDown: handleClick, onClick: (e) => e.stopPropagation(), "aria-label": `Citation: ${displayText}`, children: [displayText, isPartialMatch && renderPartialIndicator(status), isVerified && !isPartialMatch && renderVerifiedIndicator(status), isPending && (_jsx("span", { className: "citation-inline__pending", children: pendingContent }))] })] }));
206
207
  });
207
208
  InlineCitation.displayName = "InlineCitation";
208
209
  /**
@@ -215,8 +216,8 @@ InlineCitation.displayName = "InlineCitation";
215
216
  * // Renders: 1
216
217
  * ```
217
218
  */
218
- export const MinimalCitation = forwardRef(({ citation, children, className, displayCitationValue = false, fallbackDisplay, foundCitation, eventHandlers, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), showStatusIndicator = true, }, ref) => {
219
- const { citationKey, citationInstanceId, status } = useCitationData(citation, foundCitation);
219
+ export const MinimalCitation = forwardRef(({ citation, children, className, displayCitationValue = false, fallbackDisplay, verification, eventHandlers, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), showStatusIndicator = true, }, ref) => {
220
+ const { citationKey, citationInstanceId, status } = useCitationData(citation, verification);
220
221
  const { isVerified, isMiss, isPartialMatch, isPending } = status;
221
222
  const displayText = useMemo(() => getCitationDisplayText(citation, {
222
223
  displayCitationValue,
@@ -243,7 +244,7 @@ export const MinimalCitation = forwardRef(({ citation, children, className, disp
243
244
  : isPending
244
245
  ? "citation-minimal--pending"
245
246
  : "";
246
- return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "minimal", className: classNames("citation-minimal", statusClass, className), onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onMouseDown: handleClick, onClick: e => e.stopPropagation(), "aria-label": `Citation ${displayText}`, children: [displayText, showStatusIndicator && (_jsxs(_Fragment, { children: [isPartialMatch && renderPartialIndicator(status), isVerified && !isPartialMatch && renderVerifiedIndicator(status), isPending && pendingContent] }))] })] }));
247
+ return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "minimal", className: classNames("citation-minimal", statusClass, className), onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onMouseDown: handleClick, onClick: (e) => e.stopPropagation(), "aria-label": `Citation ${displayText}`, children: [displayText, showStatusIndicator && (_jsxs(_Fragment, { children: [isPartialMatch && renderPartialIndicator(status), isVerified && !isPartialMatch && renderVerifiedIndicator(status), isPending && pendingContent] }))] })] }));
247
248
  });
248
249
  MinimalCitation.displayName = "MinimalCitation";
249
250
  /**
@@ -259,7 +260,7 @@ export const CitationVariantFactory = forwardRef(({ variant = "bracket", chipPro
259
260
  case "chip":
260
261
  return _jsx(ChipCitation, { ref: ref, ...props, ...chipProps });
261
262
  case "superscript":
262
- return _jsx(SuperscriptCitation, { ref: ref, ...props, ...superscriptProps });
263
+ return (_jsx(SuperscriptCitation, { ref: ref, ...props, ...superscriptProps }));
263
264
  case "footnote":
264
265
  return _jsx(FootnoteCitation, { ref: ref, ...props, ...footnoteProps });
265
266
  case "inline":
@@ -4,14 +4,14 @@
4
4
  */
5
5
  import React, { type ReactNode, type HTMLAttributes, type MouseEvent, type TouchEvent } from "react";
6
6
  import type { Citation as CitationType, CitationStatus } from "../types/citation.js";
7
- import type { FoundHighlightLocation } from "../types/foundHighlight.js";
7
+ import type { Verification } from "../types/verification.js";
8
8
  import type { SearchState } from "../types/search.js";
9
9
  interface CitationContextValue {
10
10
  citation: CitationType;
11
11
  citationKey: string;
12
12
  citationInstanceId: string;
13
13
  status: CitationStatus;
14
- foundCitation: FoundHighlightLocation | null;
14
+ verification: Verification | null;
15
15
  searchState: SearchState | null;
16
16
  config: {
17
17
  displayCitationValue: boolean;
@@ -25,7 +25,7 @@ export declare function useCitationContext(): CitationContextValue;
25
25
  export declare function useCitationContextSafe(): CitationContextValue | null;
26
26
  export interface CitationRootProps {
27
27
  citation: CitationType;
28
- foundCitation?: FoundHighlightLocation | null;
28
+ verification?: Verification | null;
29
29
  searchState?: SearchState | null;
30
30
  children: ReactNode;
31
31
  displayCitationValue?: boolean;
@@ -5,7 +5,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
5
5
  */
6
6
  import { createContext, useContext, useMemo, useCallback, forwardRef, } from "react";
7
7
  import { getCitationStatus } from "../parsing/parseCitation.js";
8
- import { generateCitationKey, generateCitationInstanceId, classNames } from "./utils.js";
8
+ import { generateCitationKey, generateCitationInstanceId, classNames, } from "./utils.js";
9
9
  const CitationContext = createContext(null);
10
10
  /** Access citation context. Must be used within Citation.Root. */
11
11
  export function useCitationContext() {
@@ -20,16 +20,16 @@ export function useCitationContextSafe() {
20
20
  return useContext(CitationContext);
21
21
  }
22
22
  /** Root component that provides citation context to all child primitives. */
23
- export const CitationRoot = forwardRef(({ citation, foundCitation = null, searchState = null, children, displayCitationValue = false, fallbackDisplay = null, pendingContent = "..", className, ...props }, ref) => {
23
+ export const CitationRoot = forwardRef(({ citation, verification = null, searchState = null, children, displayCitationValue = false, fallbackDisplay = null, pendingContent = "..", className, ...props }, ref) => {
24
24
  const citationKey = useMemo(() => generateCitationKey(citation), [citation]);
25
25
  const citationInstanceId = useMemo(() => generateCitationInstanceId(citationKey), [citationKey]);
26
- const status = getCitationStatus(foundCitation);
26
+ const status = getCitationStatus(verification);
27
27
  const contextValue = useMemo(() => ({
28
28
  citation,
29
29
  citationKey,
30
30
  citationInstanceId,
31
31
  status,
32
- foundCitation,
32
+ verification,
33
33
  searchState,
34
34
  config: {
35
35
  displayCitationValue,
@@ -41,7 +41,7 @@ export const CitationRoot = forwardRef(({ citation, foundCitation = null, search
41
41
  citationKey,
42
42
  citationInstanceId,
43
43
  status,
44
- foundCitation,
44
+ verification,
45
45
  searchState,
46
46
  displayCitationValue,
47
47
  fallbackDisplay,
@@ -83,7 +83,9 @@ export const CitationTrigger = forwardRef(({ children, className, onCitationClic
83
83
  onCitationTouchEnd?.(citation, citationKey, e);
84
84
  }
85
85
  }, [onTouchEnd, isMobile, onCitationTouchEnd, citation, citationKey]);
86
- const statusClasses = classNames(status.isVerified && !status.isPartialMatch && "citation-trigger--verified", status.isPartialMatch && "citation-trigger--partial", status.isMiss && "citation-trigger--miss", status.isPending && "citation-trigger--pending");
86
+ const statusClasses = classNames(status.isVerified &&
87
+ !status.isPartialMatch &&
88
+ "citation-trigger--verified", status.isPartialMatch && "citation-trigger--partial", status.isMiss && "citation-trigger--miss", status.isPending && "citation-trigger--pending");
87
89
  return (_jsx("span", { ref: ref, role: "button", tabIndex: 0, className: classNames("citation-trigger", statusClasses, className), onClick: handleClick, onMouseDown: handleMouseDown, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onTouchEndCapture: isMobile ? handleTouchEnd : undefined, ...props, children: children }));
88
90
  });
89
91
  CitationTrigger.displayName = "Citation.Trigger";
@@ -99,7 +101,10 @@ export const CitationNumber = forwardRef(({ className, number, ...props }, ref)
99
101
  if (number !== undefined)
100
102
  return String(number);
101
103
  if (config.displayCitationValue) {
102
- return citation.value || citation.citationNumber?.toString() || config.fallbackDisplay || "";
104
+ return (citation.value ||
105
+ citation.citationNumber?.toString() ||
106
+ config.fallbackDisplay ||
107
+ "");
103
108
  }
104
109
  return citation.citationNumber?.toString() || "";
105
110
  }, [number, citation, config]);
@@ -1,5 +1,5 @@
1
1
  import type { Citation, CitationStatus } from "../types/citation.js";
2
- import type { FoundHighlightLocation } from "../types/foundHighlight.js";
2
+ import type { Verification } from "../types/verification.js";
3
3
  import type { SearchState } from "../types/search.js";
4
4
  /**
5
5
  * Available citation display variants.
@@ -130,7 +130,7 @@ export interface CitationContentProps extends BaseCitationProps {
130
130
  /** Unique instance ID for this citation render */
131
131
  citationInstanceId: string;
132
132
  /** Found citation highlight data */
133
- foundCitation: FoundHighlightLocation | null | undefined;
133
+ verification: Verification | null | undefined;
134
134
  /** Current search state */
135
135
  searchState: SearchState | undefined | null;
136
136
  /** Actual page number where citation was found */
@@ -186,7 +186,7 @@ export interface CitationEventHandlers {
186
186
  export interface CitationTooltipProps {
187
187
  children: React.ReactNode;
188
188
  citation: Citation;
189
- foundHighlight?: FoundHighlightLocation | null;
189
+ verification?: Verification | null;
190
190
  searchState?: SearchState | null;
191
191
  shouldShowTooltip: boolean;
192
192
  }
@@ -1,10 +1,10 @@
1
1
  import { type ScreenBox } from "./boxes.js";
2
- import { type FoundHighlightLocation } from "./foundHighlight.js";
2
+ import { type Verification } from "./verification.js";
3
3
  export type OutputImageFormat = "jpeg" | "png" | "avif" | undefined | null;
4
4
  export declare const DEFAULT_OUTPUT_IMAGE_FORMAT: "avif";
5
5
  export interface VerifyCitationResponse {
6
- foundHighlights: {
7
- [key: string]: FoundHighlightLocation;
6
+ verifications: {
7
+ [key: string]: Verification;
8
8
  };
9
9
  }
10
10
  export interface VerifyCitationRequest {
@@ -21,11 +21,11 @@ export interface Citation {
21
21
  keySpan?: string | null;
22
22
  value?: string | null;
23
23
  startPageKey?: string | null;
24
- pageNumber?: number | null;
25
24
  lineIds?: number[] | null;
26
25
  reasoning?: string | null;
27
26
  selection?: ScreenBox | null;
28
27
  citationNumber?: number;
28
+ pageNumber?: number | null;
29
29
  timestamps?: {
30
30
  endTime?: string;
31
31
  startTime?: string;
@@ -5,7 +5,7 @@
5
5
  */
6
6
  export type { Citation, CitationStatus, VerifyCitationRequest, VerifyCitationResponse, OutputImageFormat, } from "./citation.js";
7
7
  export { DEFAULT_OUTPUT_IMAGE_FORMAT } from "./citation.js";
8
- export type { FoundHighlightLocation } from "./foundHighlight.js";
9
- export { NOT_FOUND_HIGHLIGHT_INDEX, PENDING_HIGHLIGHT_INDEX, BLANK_HIGHLIGHT_LOCATION, deterministicIdFromHighlightLocation, } from "./foundHighlight.js";
8
+ export type { Verification } from "./verification.js";
9
+ export { NOT_FOUND_VERIFICATION_INDEX, PENDING_VERIFICATION_INDEX, BLANK_VERIFICATION, deterministicIdFromVerification, } from "./verification.js";
10
10
  export type { SearchState, SearchStatus } from "./search.js";
11
11
  export type { ScreenBox, PdfSpaceItem, IVertex } from "./boxes.js";
@@ -4,4 +4,4 @@
4
4
  * @packageDocumentation
5
5
  */
6
6
  export { DEFAULT_OUTPUT_IMAGE_FORMAT } from "./citation.js";
7
- export { NOT_FOUND_HIGHLIGHT_INDEX, PENDING_HIGHLIGHT_INDEX, BLANK_HIGHLIGHT_LOCATION, deterministicIdFromHighlightLocation, } from "./foundHighlight.js";
7
+ export { NOT_FOUND_VERIFICATION_INDEX, PENDING_VERIFICATION_INDEX, BLANK_VERIFICATION, deterministicIdFromVerification, } from "./verification.js";
@@ -1,11 +1,11 @@
1
1
  import { type Citation } from "./citation.js";
2
2
  import { type SearchState } from "./search.js";
3
3
  import { type PdfSpaceItem } from "./boxes.js";
4
- export declare const NOT_FOUND_HIGHLIGHT_INDEX = -1;
5
- export declare const PENDING_HIGHLIGHT_INDEX = -2;
6
- export declare const BLANK_HIGHLIGHT_LOCATION: FoundHighlightLocation;
7
- export declare function deterministicIdFromHighlightLocation(highlightLocation: FoundHighlightLocation): string;
8
- export interface FoundHighlightLocation {
4
+ export declare const NOT_FOUND_VERIFICATION_INDEX = -1;
5
+ export declare const PENDING_VERIFICATION_INDEX = -2;
6
+ export declare const BLANK_VERIFICATION: Verification;
7
+ export declare function deterministicIdFromVerification(verification: Verification): string;
8
+ export interface Verification {
9
9
  regex?: RegExp | null;
10
10
  lowerCaseSearchTerm: string | null;
11
11
  label?: string | null;
@@ -0,0 +1,23 @@
1
+ import { sha1Hash } from "../utils/sha.js";
2
+ export const NOT_FOUND_VERIFICATION_INDEX = -1;
3
+ export const PENDING_VERIFICATION_INDEX = -2;
4
+ export const BLANK_VERIFICATION = {
5
+ pageNumber: NOT_FOUND_VERIFICATION_INDEX,
6
+ regex: null,
7
+ lowerCaseSearchTerm: null,
8
+ attachmentId: null,
9
+ matchSnippet: null,
10
+ source: null,
11
+ citation: {
12
+ fileId: undefined,
13
+ startPageKey: null,
14
+ fullPhrase: null,
15
+ keySpan: null,
16
+ lineIds: null,
17
+ reasoning: null,
18
+ pageNumber: NOT_FOUND_VERIFICATION_INDEX,
19
+ },
20
+ };
21
+ export function deterministicIdFromVerification(verification) {
22
+ return sha1Hash(`${verification.lowerCaseSearchTerm}-${verification.attachmentId}-${verification.pageNumber}-${verification.hitIndexWithinPage}-${verification.matchSnippet}-${verification?.hitIndexWithinPage}`);
23
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepcitation/deepcitation-js",
3
- "version": "1.0.9",
3
+ "version": "1.1.1",
4
4
  "description": "DeepCitation JavaScript SDK for deterministic AI citation verification",
5
5
  "type": "module",
6
6
  "private": false,
@@ -1,22 +0,0 @@
1
- import { sha1Hash } from "../utils/sha.js";
2
- export const NOT_FOUND_HIGHLIGHT_INDEX = -1;
3
- export const PENDING_HIGHLIGHT_INDEX = -2;
4
- export const BLANK_HIGHLIGHT_LOCATION = {
5
- pageNumber: NOT_FOUND_HIGHLIGHT_INDEX,
6
- regex: null,
7
- lowerCaseSearchTerm: null,
8
- attachmentId: null,
9
- matchSnippet: null,
10
- source: null,
11
- citation: {
12
- startPageKey: null,
13
- lineIds: null,
14
- pageNumber: NOT_FOUND_HIGHLIGHT_INDEX,
15
- fileId: undefined,
16
- fullPhrase: null,
17
- value: null,
18
- },
19
- };
20
- export function deterministicIdFromHighlightLocation(highlightLocation) {
21
- return sha1Hash(`${highlightLocation.lowerCaseSearchTerm}-${highlightLocation.attachmentId}-${highlightLocation.pageNumber}-${highlightLocation.hitIndexWithinPage}-${highlightLocation.matchSnippet}-${highlightLocation?.hitIndexWithinPage}`);
22
- }