@deepcitation/deepcitation-js 1.1.11 → 1.1.13
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/lib/prompts/citationPrompts.d.ts +1 -1
- package/lib/prompts/citationPrompts.js +4 -4
- package/lib/react/CitationComponent.d.ts +28 -13
- package/lib/react/CitationComponent.js +31 -22
- package/lib/react/primitives.d.ts +5 -5
- package/lib/react/primitives.js +10 -10
- package/lib/react/styles.css +38 -0
- package/lib/react/types.d.ts +11 -7
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const CITATION_MARKDOWN_SYNTAX_PROMPT = "\nCitation syntax to use within Markdown:\n\u2022 To support any ideas or information that requires a citation from the provided content, use the following citation syntax:\n<cite file_id='file_id' start_page_key='page_number_PAGE_index_INDEX' full_phrase='the verbatim text of the terse phrase inside <file_text />; remember to escape quotes and newlines inside the full_phrase to remain as valid JSON' key_span='the verbatim
|
|
1
|
+
export declare const CITATION_MARKDOWN_SYNTAX_PROMPT = "\nCitation syntax to use within Markdown:\n\u2022 To support any ideas or information that requires a citation from the provided content, use the following citation syntax:\n<cite file_id='file_id' start_page_key='page_number_PAGE_index_INDEX' full_phrase='the verbatim text of the terse phrase inside <file_text />; remember to escape quotes and newlines inside the full_phrase to remain as valid JSON' key_span='the verbatim 1-3 words within full_phrase that best support the citation' line_ids='2-6' reasoning='the terse logic used to conclude the citation' />\n\n\u2022 Very important: for page numbers, only use the page number and page index info from the page_number_PAGE_index_INDEX format (e.g. <page_number_1_index_0>) and never from the contents inside the page.\n\u2022 start_page_key, full_phrase, and line_ids are required for each citation.\n\u2022 Infer line_ids, as we only provide the first, last, and every 5th line. When copying a previous <cite />, use the full info from the previous citation without changing the start_page_key, line_ids, or any other <cite /> attributes.\n\u2022 Use refer to line_ids inclusively, and use a range (or single) for each citation, split multiple sequential line_ids into multiple citations.\n\u2022 These citations will be replaced and displayed in-line as a numeric element (e.g. [1]), the markdown preceding <cite /> should read naturally with only one <cite /> per sentence with rare exceptions for two <cite /> in a sentence. <cite /> often present best at the end of the sentence, and are not grouped at the end of the document.\n\u2022 The full_phrase should be the exact verbatim text of the phrase or paragraph from the source document to support the insight or idea.\n\u2022 We do NOT put the full_phrase inside <cite ...></cite>; we only use full_phrase inside the full_phrase attribute.\n";
|
|
2
2
|
export declare const AV_CITATION_MARKDOWN_SYNTAX_PROMPT = "\n\u2022 To support any ideas or information that requires a citation from the provided content, use the following citation syntax:\n<cite file_id='file_id' full_phrase='the verbatim text of the phrase; remember to escape quotes and newlines inside the full_phrase to remain as valid JSON' timestamps='HH:MM:SS.SSS-HH:MM:SS.SSS' reasoning='the logic connecting the form section requirements to the supporting source citation' />\n\u2022 These citations are displayed in-line or in the relevant list item, and are not grouped at the end of the document.\n";
|
|
3
3
|
export interface WrapSystemPromptOptions {
|
|
4
4
|
/** The original system prompt to wrap with citation instructions */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const CITATION_MARKDOWN_SYNTAX_PROMPT = `
|
|
2
2
|
Citation syntax to use within Markdown:
|
|
3
3
|
• To support any ideas or information that requires a citation from the provided content, use the following citation syntax:
|
|
4
|
-
<cite file_id='file_id' start_page_key='page_number_PAGE_index_INDEX' full_phrase='the verbatim text of the terse phrase inside <file_text />; remember to escape quotes and newlines inside the full_phrase to remain as valid JSON' key_span='the verbatim
|
|
4
|
+
<cite file_id='file_id' start_page_key='page_number_PAGE_index_INDEX' full_phrase='the verbatim text of the terse phrase inside <file_text />; remember to escape quotes and newlines inside the full_phrase to remain as valid JSON' key_span='the verbatim 1-3 words within full_phrase that best support the citation' line_ids='2-6' reasoning='the terse logic used to conclude the citation' />
|
|
5
5
|
|
|
6
6
|
• Very important: for page numbers, only use the page number and page index info from the page_number_PAGE_index_INDEX format (e.g. <page_number_1_index_0>) and never from the contents inside the page.
|
|
7
7
|
• start_page_key, full_phrase, and line_ids are required for each citation.
|
|
@@ -121,11 +121,11 @@ export const CITATION_JSON_OUTPUT_FORMAT = {
|
|
|
121
121
|
},
|
|
122
122
|
fullPhrase: {
|
|
123
123
|
type: "string",
|
|
124
|
-
description: "The verbatim text of the terse phrase inside <file_text /> to support the
|
|
124
|
+
description: "The verbatim text of the terse phrase inside <file_text /> to support the citation (if there is a detected OCR correction, use the corrected text)",
|
|
125
125
|
},
|
|
126
126
|
keySpan: {
|
|
127
127
|
type: "string",
|
|
128
|
-
description: "the verbatim
|
|
128
|
+
description: "the verbatim 1-3 words within fullPhrase that best support the citation",
|
|
129
129
|
},
|
|
130
130
|
lineIds: {
|
|
131
131
|
type: "array",
|
|
@@ -152,7 +152,7 @@ export const CITATION_AV_BASED_JSON_OUTPUT_FORMAT = {
|
|
|
152
152
|
},
|
|
153
153
|
fullPhrase: {
|
|
154
154
|
type: "string",
|
|
155
|
-
description: "The exact verbatim text of the phrase or paragraph from the source document to support the
|
|
155
|
+
description: "The exact verbatim text of the phrase or paragraph from the source document to support the citation (if there is a detected OCR correction, use the verbatim corrected text)",
|
|
156
156
|
},
|
|
157
157
|
timestamps: {
|
|
158
158
|
type: "object",
|
|
@@ -7,33 +7,43 @@ export type { CitationVariant } from "./types.js";
|
|
|
7
7
|
/**
|
|
8
8
|
* Props for the CitationComponent.
|
|
9
9
|
*
|
|
10
|
-
* @example Brackets variant (default) - shows
|
|
10
|
+
* @example Brackets variant (default) - shows keySpan in brackets with blue styling
|
|
11
11
|
* ```tsx
|
|
12
12
|
* <CitationComponent
|
|
13
|
-
* citation={{ citationNumber: 1,
|
|
13
|
+
* citation={{ citationNumber: 1, keySpan: "Revenue grew by 25%" }}
|
|
14
14
|
* verification={verificationResult}
|
|
15
15
|
* />
|
|
16
|
-
* // Renders: [
|
|
16
|
+
* // Renders: [Revenue grew by 25%✓] with blue text
|
|
17
17
|
* ```
|
|
18
18
|
*
|
|
19
|
-
* @example Numeric
|
|
19
|
+
* @example Numeric only - use displayKeySpan=false with brackets variant
|
|
20
20
|
* ```tsx
|
|
21
21
|
* <CitationComponent
|
|
22
|
-
* citation={{ citationNumber: 1,
|
|
22
|
+
* citation={{ citationNumber: 1, keySpan: "25% growth" }}
|
|
23
23
|
* verification={verificationResult}
|
|
24
|
-
*
|
|
24
|
+
* displayKeySpan={false}
|
|
25
25
|
* />
|
|
26
|
-
* // Renders: 1✓
|
|
26
|
+
* // Renders: [1✓]
|
|
27
27
|
* ```
|
|
28
28
|
*
|
|
29
|
-
* @example
|
|
29
|
+
* @example Without brackets - use displayBrackets=false
|
|
30
30
|
* ```tsx
|
|
31
31
|
* <CitationComponent
|
|
32
|
-
* citation={{ citationNumber: 1,
|
|
32
|
+
* citation={{ citationNumber: 1, keySpan: "25% growth" }}
|
|
33
|
+
* verification={verificationResult}
|
|
34
|
+
* displayBrackets={false}
|
|
35
|
+
* />
|
|
36
|
+
* // Renders: 25% growth✓ (no brackets)
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @example Text variant - inherits parent text styling, no truncation
|
|
40
|
+
* ```tsx
|
|
41
|
+
* <CitationComponent
|
|
42
|
+
* citation={{ citationNumber: 1, keySpan: "25% growth" }}
|
|
33
43
|
* verification={verificationResult}
|
|
34
44
|
* variant="text"
|
|
35
45
|
* />
|
|
36
|
-
* // Renders: 25% growth✓
|
|
46
|
+
* // Renders: 25% growth✓ (inherits parent styling)
|
|
37
47
|
* ```
|
|
38
48
|
*
|
|
39
49
|
* @example Minimal variant - no brackets, just text and indicator
|
|
@@ -73,13 +83,18 @@ export interface CitationComponentProps extends BaseCitationProps {
|
|
|
73
83
|
verification?: Verification | null;
|
|
74
84
|
/**
|
|
75
85
|
* Display variant for the citation.
|
|
76
|
-
* - `brackets`: Shows
|
|
77
|
-
* - `
|
|
78
|
-
* - `text`: Shows the value, no text styling, no truncate, shows indicator
|
|
86
|
+
* - `brackets`: Shows keySpan/number in brackets, blue text styling (default)
|
|
87
|
+
* - `text`: Shows the keySpan, inherits parent text styling, no truncation, shows indicator
|
|
79
88
|
* - `minimal`: No brackets, just display text with indicator
|
|
80
89
|
* - `indicator`: Only the status indicator (checkmark/warning), no text
|
|
81
90
|
*/
|
|
82
91
|
variant?: CitationVariant;
|
|
92
|
+
/**
|
|
93
|
+
* Whether to show square brackets around the citation.
|
|
94
|
+
* Only applies to the `brackets` variant.
|
|
95
|
+
* @default true
|
|
96
|
+
*/
|
|
97
|
+
displayBrackets?: boolean;
|
|
83
98
|
/**
|
|
84
99
|
* Event handlers for citation interactions.
|
|
85
100
|
*/
|
|
@@ -136,12 +136,28 @@ const ImageOverlay = ({ src, alt, onClose, }) => {
|
|
|
136
136
|
// Use portal to render at body level, avoiding any parent positioning issues
|
|
137
137
|
return createPortal(_jsx("div", { className: "dc-overlay", onClick: handleBackdropClick, role: "dialog", "aria-modal": "true", "aria-label": "Full size verification image", children: _jsx("div", { className: "dc-overlay-content", onClick: onClose, children: _jsx("img", { src: src, alt: alt, className: "dc-overlay-image", draggable: false }) }) }), document.body);
|
|
138
138
|
};
|
|
139
|
+
/**
|
|
140
|
+
* Diff details for partial/miss verification states.
|
|
141
|
+
* Shows expected vs found text.
|
|
142
|
+
*/
|
|
143
|
+
const DiffDetails = ({ citation, verification, status, }) => {
|
|
144
|
+
const { isMiss, isPartialMatch } = status;
|
|
145
|
+
if (!isMiss && !isPartialMatch)
|
|
146
|
+
return null;
|
|
147
|
+
const expectedText = citation.fullPhrase || citation.keySpan?.toString() || "";
|
|
148
|
+
const actualText = verification?.matchSnippet || "";
|
|
149
|
+
const truncatedExpected = expectedText.length > 100 ? expectedText.slice(0, 100) + "…" : expectedText;
|
|
150
|
+
const truncatedActual = actualText.length > 100 ? actualText.slice(0, 100) + "…" : actualText;
|
|
151
|
+
return (_jsxs("span", { className: "dc-diff-details", children: [truncatedExpected && (_jsxs("span", { className: "dc-status-searched", children: [_jsx("span", { className: "dc-status-label", children: "Expected" }), _jsx("span", { className: "dc-status-text", children: truncatedExpected })] })), isPartialMatch && truncatedActual && (_jsxs("span", { className: "dc-status-searched", children: [_jsx("span", { className: "dc-status-label", children: "Found" }), _jsx("span", { className: "dc-status-text", children: truncatedActual })] })), isMiss && (_jsxs("span", { className: "dc-status-searched", children: [_jsx("span", { className: "dc-status-label", children: "Found" }), _jsx("span", { className: "dc-status-text dc-status-text--miss", children: "Not found in source" })] }))] }));
|
|
152
|
+
};
|
|
139
153
|
/**
|
|
140
154
|
* Default popover content component.
|
|
141
155
|
* Shows verification image if available, otherwise shows text info.
|
|
156
|
+
* For partial/miss states, also displays expected vs found details.
|
|
142
157
|
*/
|
|
143
|
-
const DefaultPopoverContent = ({ verification, status, onImageClick, }) => {
|
|
158
|
+
const DefaultPopoverContent = ({ citation, verification, status, onImageClick, }) => {
|
|
144
159
|
const hasImage = verification?.verificationImageBase64;
|
|
160
|
+
const { isMiss, isPartialMatch } = status;
|
|
145
161
|
const handleImageClick = useCallback((e) => {
|
|
146
162
|
e.preventDefault();
|
|
147
163
|
e.stopPropagation();
|
|
@@ -149,9 +165,9 @@ const DefaultPopoverContent = ({ verification, status, onImageClick, }) => {
|
|
|
149
165
|
onImageClick(verification.verificationImageBase64);
|
|
150
166
|
}
|
|
151
167
|
}, [hasImage, verification?.verificationImageBase64, onImageClick]);
|
|
152
|
-
// If we have a verification image, show
|
|
168
|
+
// If we have a verification image, show image + diff details for partial/miss
|
|
153
169
|
if (hasImage) {
|
|
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" }) }));
|
|
170
|
+
return (_jsxs(_Fragment, { children: [_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" }) }), (isMiss || isPartialMatch) && (_jsx(DiffDetails, { citation: citation, verification: verification, status: status }))] }));
|
|
155
171
|
}
|
|
156
172
|
// No image - show text info
|
|
157
173
|
const statusLabel = getStatusLabel(status);
|
|
@@ -161,7 +177,7 @@ const DefaultPopoverContent = ({ verification, status, onImageClick, }) => {
|
|
|
161
177
|
if (!hasSnippet && !statusLabel) {
|
|
162
178
|
return null;
|
|
163
179
|
}
|
|
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] }))] }));
|
|
180
|
+
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] })), (isMiss || isPartialMatch) && (_jsx(DiffDetails, { citation: citation, verification: verification, status: status }))] }));
|
|
165
181
|
};
|
|
166
182
|
// =============================================================================
|
|
167
183
|
// MAIN COMPONENT
|
|
@@ -182,7 +198,7 @@ const DefaultPopoverContent = ({ verification, status, onImageClick, }) => {
|
|
|
182
198
|
* This means partial matches have blue text (because they were found) but
|
|
183
199
|
* an orange indicator (because they didn't match exactly).
|
|
184
200
|
*/
|
|
185
|
-
export const CitationComponent = forwardRef(({ citation, children, className, displayKeySpan =
|
|
201
|
+
export const CitationComponent = forwardRef(({ citation, children, className, displayKeySpan = true, displayBrackets = true, fallbackDisplay, verification, variant = "brackets", eventHandlers, isMobile = false, renderIndicator, renderContent, popoverPosition = "top", renderPopoverContent, }, ref) => {
|
|
186
202
|
const containerRef = useRef(null);
|
|
187
203
|
const wrapperRef = useRef(null);
|
|
188
204
|
const [expandedImageSrc, setExpandedImageSrc] = useState(null);
|
|
@@ -268,15 +284,11 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
|
|
|
268
284
|
// const { isVerified, isPending } = status;
|
|
269
285
|
const { isMiss, isPartialMatch, isVerified, isPending } = status;
|
|
270
286
|
const displayText = useMemo(() => {
|
|
271
|
-
// For
|
|
272
|
-
|
|
273
|
-
return citation.citationNumber?.toString() ?? "";
|
|
274
|
-
}
|
|
275
|
-
// For text/minimal/brackets, show the value or fullPhrase
|
|
287
|
+
// For text/minimal variants, always show keySpan
|
|
288
|
+
// For brackets variant, show keySpan based on displayKeySpan prop
|
|
276
289
|
return getCitationDisplayText(citation, {
|
|
277
290
|
displayKeySpan: variant === "text" ||
|
|
278
291
|
variant === "minimal" ||
|
|
279
|
-
variant === "brackets" ||
|
|
280
292
|
displayKeySpan,
|
|
281
293
|
fallbackDisplay,
|
|
282
294
|
});
|
|
@@ -309,12 +321,13 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
|
|
|
309
321
|
if (renderIndicator) {
|
|
310
322
|
return renderIndicator(status);
|
|
311
323
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
else if (isPartialMatch) {
|
|
324
|
+
// Check partial match first since isVerified includes isPartialMatch
|
|
325
|
+
if (isPartialMatch) {
|
|
316
326
|
return _jsx(DefaultPartialIndicator, {});
|
|
317
327
|
}
|
|
328
|
+
else if (isVerified) {
|
|
329
|
+
return _jsx(DefaultVerifiedIndicator, {});
|
|
330
|
+
}
|
|
318
331
|
else if (isPending) {
|
|
319
332
|
return (_jsx("span", { className: "dc-indicator dc-indicator--pending", "aria-hidden": "true", children: TWO_DOTS_THINKING_CONTENT }));
|
|
320
333
|
}
|
|
@@ -339,7 +352,7 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
|
|
|
339
352
|
if (variant === "indicator") {
|
|
340
353
|
return (_jsx("span", { className: "dc-citation-text", children: renderStatusIndicator() }));
|
|
341
354
|
}
|
|
342
|
-
// Text variant - no special styling, shows
|
|
355
|
+
// Text variant - no special styling, shows keySpan with indicator
|
|
343
356
|
if (variant === "text") {
|
|
344
357
|
return (_jsxs("span", { className: "dc-citation-text dc-citation-text--plain", children: [displayText, renderStatusIndicator()] }));
|
|
345
358
|
}
|
|
@@ -347,12 +360,8 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
|
|
|
347
360
|
if (variant === "minimal") {
|
|
348
361
|
return (_jsxs("span", { className: "dc-citation-text", children: [displayText, renderStatusIndicator()] }));
|
|
349
362
|
}
|
|
350
|
-
//
|
|
351
|
-
|
|
352
|
-
return (_jsxs("span", { className: "dc-citation-text", children: [displayText, renderStatusIndicator()] }));
|
|
353
|
-
}
|
|
354
|
-
// Brackets variant (default) - value/number in brackets with styling
|
|
355
|
-
return (_jsxs("span", { className: "dc-citation-bracket", "aria-hidden": "true", role: "presentation", children: ["[", _jsxs("span", { className: "dc-citation-text", children: [displayText, renderStatusIndicator()] }), "]"] }));
|
|
363
|
+
// Brackets variant (default) - keySpan/number in brackets with styling
|
|
364
|
+
return (_jsxs("span", { className: "dc-citation-bracket", "aria-hidden": "true", role: "presentation", children: [displayBrackets && "[", _jsxs("span", { className: "dc-citation-text", children: [displayText, renderStatusIndicator()] }), displayBrackets && "]"] }));
|
|
356
365
|
};
|
|
357
366
|
// Determine if popover should be shown
|
|
358
367
|
const isPopoverHidden = popoverPosition === "hidden";
|
|
@@ -55,12 +55,12 @@ export interface CitationNumberProps extends HTMLAttributes<HTMLSpanElement> {
|
|
|
55
55
|
}
|
|
56
56
|
/** Displays the citation number. */
|
|
57
57
|
export declare const CitationNumber: React.ForwardRefExoticComponent<CitationNumberProps & React.RefAttributes<HTMLSpanElement>>;
|
|
58
|
-
export interface
|
|
59
|
-
|
|
58
|
+
export interface CitationKeySpanProps extends HTMLAttributes<HTMLSpanElement> {
|
|
59
|
+
keySpan?: string;
|
|
60
60
|
separator?: string;
|
|
61
61
|
}
|
|
62
|
-
/** Displays the citation
|
|
63
|
-
export declare const
|
|
62
|
+
/** Displays the citation keySpan (summary text). */
|
|
63
|
+
export declare const CitationKeySpan: React.ForwardRefExoticComponent<CitationKeySpanProps & React.RefAttributes<HTMLSpanElement>>;
|
|
64
64
|
export interface CitationIndicatorProps extends HTMLAttributes<HTMLSpanElement> {
|
|
65
65
|
verifiedIndicator?: ReactNode;
|
|
66
66
|
partialIndicator?: ReactNode;
|
|
@@ -95,7 +95,7 @@ export declare const Citation: {
|
|
|
95
95
|
readonly Trigger: React.ForwardRefExoticComponent<CitationTriggerProps & React.RefAttributes<HTMLSpanElement>>;
|
|
96
96
|
readonly Bracket: React.ForwardRefExoticComponent<CitationBracketProps & React.RefAttributes<HTMLSpanElement>>;
|
|
97
97
|
readonly Number: React.ForwardRefExoticComponent<CitationNumberProps & React.RefAttributes<HTMLSpanElement>>;
|
|
98
|
-
readonly
|
|
98
|
+
readonly KeySpan: React.ForwardRefExoticComponent<CitationKeySpanProps & React.RefAttributes<HTMLSpanElement>>;
|
|
99
99
|
readonly Indicator: React.ForwardRefExoticComponent<CitationIndicatorProps & React.RefAttributes<HTMLSpanElement>>;
|
|
100
100
|
readonly Status: typeof CitationStatusComponent;
|
|
101
101
|
readonly Phrase: React.ForwardRefExoticComponent<CitationPhraseProps & React.RefAttributes<HTMLSpanElement>>;
|
package/lib/react/primitives.js
CHANGED
|
@@ -114,21 +114,21 @@ export const CitationNumber = forwardRef(({ className, number, ...props }, ref)
|
|
|
114
114
|
return (_jsx("span", { ref: ref, className: classNames("citation-number", className), ...props, children: displayNumber }));
|
|
115
115
|
});
|
|
116
116
|
CitationNumber.displayName = "Citation.Number";
|
|
117
|
-
/** Displays the citation
|
|
118
|
-
export const
|
|
117
|
+
/** Displays the citation keySpan (summary text). */
|
|
118
|
+
export const CitationKeySpan = forwardRef(({ className, keySpan, separator = " ", ...props }, ref) => {
|
|
119
119
|
const { citation, config } = useCitationContext();
|
|
120
|
-
const
|
|
121
|
-
if (
|
|
122
|
-
return
|
|
120
|
+
const displayKeySpan = useMemo(() => {
|
|
121
|
+
if (keySpan !== undefined)
|
|
122
|
+
return keySpan;
|
|
123
123
|
if (!config.displayKeySpan)
|
|
124
124
|
return "";
|
|
125
125
|
return citation.keySpan?.toString() || "";
|
|
126
|
-
}, [
|
|
127
|
-
if (!
|
|
126
|
+
}, [keySpan, citation, config]);
|
|
127
|
+
if (!displayKeySpan)
|
|
128
128
|
return null;
|
|
129
|
-
return (_jsxs("span", { ref: ref, className: classNames("citation-
|
|
129
|
+
return (_jsxs("span", { ref: ref, className: classNames("citation-key-span", className), ...props, children: [displayKeySpan, separator] }));
|
|
130
130
|
});
|
|
131
|
-
|
|
131
|
+
CitationKeySpan.displayName = "Citation.KeySpan";
|
|
132
132
|
/** Displays a status indicator based on citation verification state. */
|
|
133
133
|
export const CitationIndicator = forwardRef(({ className, verifiedIndicator = "✓", partialIndicator = "*", missIndicator = null, pendingIndicator = null, showFor, ...props }, ref) => {
|
|
134
134
|
const { status } = useCitationContext();
|
|
@@ -187,7 +187,7 @@ export const Citation = {
|
|
|
187
187
|
Trigger: CitationTrigger,
|
|
188
188
|
Bracket: CitationBracket,
|
|
189
189
|
Number: CitationNumber,
|
|
190
|
-
|
|
190
|
+
KeySpan: CitationKeySpan,
|
|
191
191
|
Indicator: CitationIndicator,
|
|
192
192
|
Status: CitationStatusComponent,
|
|
193
193
|
Phrase: CitationPhrase,
|
package/lib/react/styles.css
CHANGED
|
@@ -57,6 +57,27 @@
|
|
|
57
57
|
text-overflow: ellipsis;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/* Text variant - plain styling that inherits from parent */
|
|
61
|
+
.dc-citation-text--plain {
|
|
62
|
+
max-width: none;
|
|
63
|
+
overflow: visible;
|
|
64
|
+
font-family: inherit;
|
|
65
|
+
font-size: inherit;
|
|
66
|
+
line-height: inherit;
|
|
67
|
+
color: inherit;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Text variant container - inherit all styling from parent */
|
|
71
|
+
.dc-citation--text {
|
|
72
|
+
font-family: inherit;
|
|
73
|
+
font-size: inherit;
|
|
74
|
+
line-height: inherit;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.dc-citation--text .dc-citation-text--plain {
|
|
78
|
+
color: inherit;
|
|
79
|
+
}
|
|
80
|
+
|
|
60
81
|
/* Status-specific styles */
|
|
61
82
|
.dc-citation--verified .dc-citation-text {
|
|
62
83
|
color: var(--dc-color-verified, #2563eb);
|
|
@@ -423,6 +444,23 @@
|
|
|
423
444
|
text-overflow: ellipsis;
|
|
424
445
|
}
|
|
425
446
|
|
|
447
|
+
.dc-status-text--miss {
|
|
448
|
+
color: var(--dc-color-warning, #d97706);
|
|
449
|
+
font-style: italic;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/* Diff details container in popover */
|
|
453
|
+
.dc-diff-details {
|
|
454
|
+
display: flex;
|
|
455
|
+
flex-direction: column;
|
|
456
|
+
gap: 0.25rem;
|
|
457
|
+
margin-top: 0.5rem;
|
|
458
|
+
padding-top: 0.5rem;
|
|
459
|
+
border-top: 1px solid var(--dc-border-color, #e2e8f0);
|
|
460
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
461
|
+
font-size: 0.75rem;
|
|
462
|
+
}
|
|
463
|
+
|
|
426
464
|
/* Dark mode support */
|
|
427
465
|
@media (prefers-color-scheme: dark) {
|
|
428
466
|
.dc-status-tooltip {
|
package/lib/react/types.d.ts
CHANGED
|
@@ -4,13 +4,14 @@ import type { SearchState } from "../types/search.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* Available citation display variants.
|
|
6
6
|
*
|
|
7
|
-
* - `brackets`: Shows
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* - `brackets`: Shows keySpan/number in brackets with blue text styling (default).
|
|
8
|
+
* Use displayKeySpan=false for numeric-only display.
|
|
9
|
+
* Use displayBrackets=false to hide the square brackets.
|
|
10
|
+
* - `text`: Shows the keySpan, inherits parent text styling, no truncation, shows indicator
|
|
10
11
|
* - `minimal`: No brackets, just display text with indicator
|
|
11
12
|
* - `indicator`: Only the status indicator (checkmark/warning), no text
|
|
12
13
|
*/
|
|
13
|
-
export type CitationVariant = "brackets" | "
|
|
14
|
+
export type CitationVariant = "brackets" | "text" | "minimal" | "indicator";
|
|
14
15
|
/**
|
|
15
16
|
* URL fetch status for URL citations.
|
|
16
17
|
*/
|
|
@@ -89,9 +90,12 @@ export interface BaseCitationProps {
|
|
|
89
90
|
className?: string;
|
|
90
91
|
/** Class name for controlling inner content width */
|
|
91
92
|
innerWidthClassName?: string;
|
|
92
|
-
/**
|
|
93
|
+
/**
|
|
94
|
+
* When true, displays keySpan text. When false, displays citation number only.
|
|
95
|
+
* @default true
|
|
96
|
+
*/
|
|
93
97
|
displayKeySpan?: boolean;
|
|
94
|
-
/** Fallback display text when citation
|
|
98
|
+
/** Fallback display text when citation keySpan is empty */
|
|
95
99
|
fallbackDisplay?: string | null;
|
|
96
100
|
/** Display variant for the citation */
|
|
97
101
|
variant?: CitationVariant;
|
|
@@ -164,7 +168,7 @@ export interface CitationRenderProps {
|
|
|
164
168
|
citationKey: string;
|
|
165
169
|
/** Display text for the citation */
|
|
166
170
|
displayText: string;
|
|
167
|
-
/** Whether this is a merged
|
|
171
|
+
/** Whether this is a merged keySpan display */
|
|
168
172
|
isMergedDisplay: boolean;
|
|
169
173
|
}
|
|
170
174
|
/**
|