@deepcitation/deepcitation-js 1.1.26 → 1.1.27
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/index.d.ts +0 -1
- package/lib/index.js +0 -2
- package/lib/react/CitationComponent.d.ts +22 -9
- package/lib/react/CitationComponent.js +61 -13
- package/lib/react/CitationVariants.js +54 -61
- package/lib/react/UrlCitationComponent.js +22 -22
- package/lib/react/icons.d.ts +6 -2
- package/lib/react/icons.js +3 -3
- package/lib/react/index.d.ts +3 -2
- package/lib/react/index.js +3 -1
- package/lib/react/primitives.d.ts +0 -2
- package/lib/react/primitives.js +21 -27
- package/lib/react/types.d.ts +46 -14
- package/lib/react/utils.d.ts +7 -6
- package/lib/react/utils.js +14 -15
- package/package.json +20 -3
package/lib/index.d.ts
CHANGED
|
@@ -8,7 +8,6 @@ export { parseCitation, getCitationStatus, getAllCitationsFromLlmOutput, groupCi
|
|
|
8
8
|
export { normalizeCitations, getCitationPageNumber, } from "./parsing/normalizeCitation.js";
|
|
9
9
|
export { isGeminiGarbage, cleanRepeatingLastSentence, } from "./parsing/parseWorkAround.js";
|
|
10
10
|
export type { Citation, CitationStatus, VerifyCitationRequest, VerifyCitationResponse, OutputImageFormat, } from "./types/citation.js";
|
|
11
|
-
export { DeepCitationIcon } from "./react/icons.js";
|
|
12
11
|
export { DEFAULT_OUTPUT_IMAGE_FORMAT } from "./types/citation.js";
|
|
13
12
|
export type { Verification } from "./types/verification.js";
|
|
14
13
|
export { NOT_FOUND_VERIFICATION_INDEX, PENDING_VERIFICATION_INDEX, BLANK_VERIFICATION, } from "./types/verification.js";
|
package/lib/index.js
CHANGED
|
@@ -8,8 +8,6 @@ export { DeepCitation } from "./client/index.js";
|
|
|
8
8
|
export { parseCitation, getCitationStatus, getAllCitationsFromLlmOutput, groupCitationsByAttachmentId, groupCitationsByAttachmentIdObject, } from "./parsing/parseCitation.js";
|
|
9
9
|
export { normalizeCitations, getCitationPageNumber, } from "./parsing/normalizeCitation.js";
|
|
10
10
|
export { isGeminiGarbage, cleanRepeatingLastSentence, } from "./parsing/parseWorkAround.js";
|
|
11
|
-
// Icons
|
|
12
|
-
export { DeepCitationIcon } from "./react/icons.js";
|
|
13
11
|
export { DEFAULT_OUTPUT_IMAGE_FORMAT } from "./types/citation.js";
|
|
14
12
|
export { NOT_FOUND_VERIFICATION_INDEX, PENDING_VERIFICATION_INDEX, BLANK_VERIFICATION, } from "./types/verification.js";
|
|
15
13
|
// Utilities
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { type CitationStatus } from "../types/citation.js";
|
|
3
3
|
import type { Verification } from "../types/verification.js";
|
|
4
|
-
import type { BaseCitationProps, CitationBehaviorConfig, CitationEventHandlers, CitationRenderProps, CitationVariant } from "./types.js";
|
|
5
|
-
export type { CitationVariant } from "./types.js";
|
|
4
|
+
import type { BaseCitationProps, CitationBehaviorConfig, CitationContent, CitationEventHandlers, CitationRenderProps, CitationVariant } from "./types.js";
|
|
5
|
+
export type { CitationVariant, CitationContent } from "./types.js";
|
|
6
6
|
/**
|
|
7
7
|
* Props for the CitationComponent.
|
|
8
8
|
*
|
|
@@ -44,15 +44,28 @@ export interface CitationComponentProps extends BaseCitationProps {
|
|
|
44
44
|
/** Verification result from the DeepCitation API */
|
|
45
45
|
verification?: Verification | null;
|
|
46
46
|
/**
|
|
47
|
-
*
|
|
48
|
-
* - `
|
|
49
|
-
* - `
|
|
50
|
-
* - `
|
|
51
|
-
* - `
|
|
47
|
+
* Visual style variant for the citation.
|
|
48
|
+
* - `chip`: Pill/badge style with background color
|
|
49
|
+
* - `brackets`: [text✓] with square brackets (default)
|
|
50
|
+
* - `text`: Plain text, inherits parent styling
|
|
51
|
+
* - `superscript`: Small raised text like footnotes¹
|
|
52
|
+
* - `minimal`: Compact text with indicator, truncated
|
|
52
53
|
*/
|
|
53
54
|
variant?: CitationVariant;
|
|
54
|
-
/**
|
|
55
|
-
|
|
55
|
+
/**
|
|
56
|
+
* What content to display in the citation.
|
|
57
|
+
* - `keySpan`: Descriptive text (e.g., "Revenue Growth")
|
|
58
|
+
* - `number`: Citation number (e.g., "1", "2", "3")
|
|
59
|
+
* - `indicator`: Only the status icon, no text
|
|
60
|
+
*
|
|
61
|
+
* Defaults based on variant:
|
|
62
|
+
* - `chip` → `keySpan`
|
|
63
|
+
* - `brackets` → `number`
|
|
64
|
+
* - `text` → `keySpan`
|
|
65
|
+
* - `superscript` → `number`
|
|
66
|
+
* - `minimal` → `number`
|
|
67
|
+
*/
|
|
68
|
+
content?: CitationContent;
|
|
56
69
|
/** Event handlers for citation interactions */
|
|
57
70
|
eventHandlers?: CitationEventHandlers;
|
|
58
71
|
/**
|
|
@@ -3,8 +3,40 @@ import { forwardRef, memo, useCallback, useEffect, useMemo, useState, } from "re
|
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
4
|
import { CheckIcon, SpinnerIcon, WarningIcon } from "./icons.js";
|
|
5
5
|
import { Popover, PopoverContent, PopoverTrigger } from "./Popover.js";
|
|
6
|
-
import { cn, generateCitationInstanceId, generateCitationKey,
|
|
6
|
+
import { cn, generateCitationInstanceId, generateCitationKey, } from "./utils.js";
|
|
7
7
|
import { useSmartDiff } from "./useSmartDiff.js";
|
|
8
|
+
/**
|
|
9
|
+
* Get the default content type based on variant.
|
|
10
|
+
*/
|
|
11
|
+
function getDefaultContent(variant) {
|
|
12
|
+
switch (variant) {
|
|
13
|
+
case "chip":
|
|
14
|
+
case "text":
|
|
15
|
+
return "keySpan";
|
|
16
|
+
case "brackets":
|
|
17
|
+
case "superscript":
|
|
18
|
+
case "minimal":
|
|
19
|
+
default:
|
|
20
|
+
return "number";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get display text based on content type and citation data.
|
|
25
|
+
* Returns "1" as fallback if no citation number is available.
|
|
26
|
+
*/
|
|
27
|
+
function getDisplayText(citation, content, fallbackDisplay) {
|
|
28
|
+
if (content === "indicator") {
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
if (content === "keySpan") {
|
|
32
|
+
return (citation.keySpan?.toString() ||
|
|
33
|
+
citation.citationNumber?.toString() ||
|
|
34
|
+
fallbackDisplay ||
|
|
35
|
+
"1");
|
|
36
|
+
}
|
|
37
|
+
// content === "number"
|
|
38
|
+
return citation.citationNumber?.toString() || "1";
|
|
39
|
+
}
|
|
8
40
|
function getStatusLabel(status) {
|
|
9
41
|
if (status.isVerified && !status.isPartialMatch)
|
|
10
42
|
return "Verified";
|
|
@@ -171,7 +203,13 @@ function DiffDetails({ citation, verification, status, }) {
|
|
|
171
203
|
* Use `behaviorConfig.onClick` to completely replace the click behavior,
|
|
172
204
|
* or `eventHandlers.onClick` to add side effects (which disables defaults).
|
|
173
205
|
*/
|
|
174
|
-
export const CitationComponent = forwardRef(({ citation, children, className,
|
|
206
|
+
export const CitationComponent = forwardRef(({ citation, children, className, fallbackDisplay, verification, variant = "brackets", content: contentProp, eventHandlers, behaviorConfig, isMobile = false, renderIndicator, renderContent, popoverPosition = "top", renderPopoverContent, }, ref) => {
|
|
207
|
+
// Resolve content: explicit content prop or default for variant
|
|
208
|
+
const resolvedContent = useMemo(() => {
|
|
209
|
+
if (contentProp)
|
|
210
|
+
return contentProp;
|
|
211
|
+
return getDefaultContent(variant);
|
|
212
|
+
}, [contentProp, variant]);
|
|
175
213
|
const [isHovering, setIsHovering] = useState(false);
|
|
176
214
|
const [expandedImageSrc, setExpandedImageSrc] = useState(null);
|
|
177
215
|
const citationKey = useMemo(() => generateCitationKey(citation), [citation]);
|
|
@@ -180,11 +218,8 @@ export const CitationComponent = forwardRef(({ citation, children, className, hi
|
|
|
180
218
|
const status = useMemo(() => getStatusFromVerification(verification), [verification]);
|
|
181
219
|
const { isMiss, isPartialMatch, isVerified, isPending } = status;
|
|
182
220
|
const displayText = useMemo(() => {
|
|
183
|
-
return
|
|
184
|
-
|
|
185
|
-
fallbackDisplay,
|
|
186
|
-
});
|
|
187
|
-
}, [citation, variant, hideKeySpan, fallbackDisplay]);
|
|
221
|
+
return getDisplayText(citation, resolvedContent, fallbackDisplay);
|
|
222
|
+
}, [citation, resolvedContent, fallbackDisplay]);
|
|
188
223
|
// Behavior context for custom handlers
|
|
189
224
|
const getBehaviorContext = useCallback(() => ({
|
|
190
225
|
citation,
|
|
@@ -276,10 +311,10 @@ export const CitationComponent = forwardRef(({ citation, children, className, hi
|
|
|
276
311
|
eventHandlers?.onTouchEnd?.(citation, citationKey, e);
|
|
277
312
|
}
|
|
278
313
|
}, [eventHandlers, citation, citationKey, isMobile]);
|
|
279
|
-
// Early return for miss with fallback display
|
|
314
|
+
// Early return for miss with fallback display (only when showing keySpan)
|
|
280
315
|
if (fallbackDisplay !== null &&
|
|
281
316
|
fallbackDisplay !== undefined &&
|
|
282
|
-
|
|
317
|
+
resolvedContent === "keySpan" &&
|
|
283
318
|
isMiss) {
|
|
284
319
|
return (_jsx("span", { className: cn("text-gray-400 dark:text-gray-500", className), children: fallbackDisplay }));
|
|
285
320
|
}
|
|
@@ -316,20 +351,33 @@ export const CitationComponent = forwardRef(({ citation, children, className, hi
|
|
|
316
351
|
status,
|
|
317
352
|
citationKey,
|
|
318
353
|
displayText,
|
|
319
|
-
isMergedDisplay:
|
|
354
|
+
isMergedDisplay: resolvedContent === "keySpan",
|
|
320
355
|
});
|
|
321
356
|
}
|
|
322
|
-
|
|
357
|
+
// Content type: indicator only
|
|
358
|
+
if (resolvedContent === "indicator") {
|
|
323
359
|
return _jsx("span", { children: renderStatusIndicator() });
|
|
324
360
|
}
|
|
361
|
+
// Variant: chip (pill/badge style)
|
|
362
|
+
if (variant === "chip") {
|
|
363
|
+
const chipStatusClasses = cn(isVerified && !isPartialMatch && "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400", isPartialMatch && "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400", isMiss && "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400 line-through", isPending && "bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400", !isVerified && !isMiss && !isPending && "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400");
|
|
364
|
+
return (_jsxs("span", { className: cn("inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-sm font-medium", chipStatusClasses), children: [_jsx("span", { className: "max-w-60 overflow-hidden text-ellipsis whitespace-nowrap", children: displayText }), renderStatusIndicator()] }));
|
|
365
|
+
}
|
|
366
|
+
// Variant: superscript (footnote style)
|
|
367
|
+
if (variant === "superscript") {
|
|
368
|
+
const supStatusClasses = cn(isVerified && !isPartialMatch && "text-green-600 dark:text-green-500", isPartialMatch && "text-amber-600 dark:text-amber-500", isMiss && "text-red-500 dark:text-red-400 line-through", isPending && "text-gray-400 dark:text-gray-500", !isVerified && !isMiss && !isPending && "text-blue-600 dark:text-blue-400");
|
|
369
|
+
return (_jsxs("sup", { className: cn("text-xs font-medium transition-colors hover:underline", supStatusClasses), children: ["[", displayText, renderStatusIndicator(), "]"] }));
|
|
370
|
+
}
|
|
371
|
+
// Variant: text (inherits parent styling)
|
|
325
372
|
if (variant === "text") {
|
|
326
373
|
return (_jsxs("span", { className: statusClasses, children: [displayText, renderStatusIndicator()] }));
|
|
327
374
|
}
|
|
375
|
+
// Variant: minimal (compact with truncation)
|
|
328
376
|
if (variant === "minimal") {
|
|
329
377
|
return (_jsxs("span", { className: cn("max-w-80 overflow-hidden text-ellipsis", statusClasses), children: [displayText, renderStatusIndicator()] }));
|
|
330
378
|
}
|
|
331
|
-
// brackets
|
|
332
|
-
return (_jsxs("span", { className: cn("inline-flex items-baseline gap-0.5 whitespace-nowrap", "font-mono text-xs leading-tight", "text-gray-500 dark:text-gray-400", "transition-colors"), "aria-hidden": "true", children: [
|
|
379
|
+
// Variant: brackets (default)
|
|
380
|
+
return (_jsxs("span", { className: cn("inline-flex items-baseline gap-0.5 whitespace-nowrap", "font-mono text-xs leading-tight", "text-gray-500 dark:text-gray-400", "transition-colors"), "aria-hidden": "true", children: ["[", _jsxs("span", { className: cn("max-w-80 overflow-hidden text-ellipsis", statusClasses), children: [displayText, renderStatusIndicator()] }), "]"] }));
|
|
333
381
|
};
|
|
334
382
|
// Popover visibility
|
|
335
383
|
const isPopoverHidden = popoverPosition === "hidden";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { memo, useMemo, useCallback, forwardRef, } from "react";
|
|
3
3
|
import { getCitationStatus } from "../parsing/parseCitation.js";
|
|
4
|
-
import { generateCitationKey, generateCitationInstanceId, getCitationDisplayText,
|
|
4
|
+
import { generateCitationKey, generateCitationInstanceId, getCitationDisplayText, getCitationNumber, classNames, } from "./utils.js";
|
|
5
5
|
const TWO_DOTS_THINKING_CONTENT = "..";
|
|
6
6
|
/**
|
|
7
7
|
* Hook to get common citation data.
|
|
@@ -17,11 +17,11 @@ function useCitationData(citation, verification) {
|
|
|
17
17
|
/**
|
|
18
18
|
* Default verified indicator (checkmark)
|
|
19
19
|
*/
|
|
20
|
-
const DefaultVerifiedIndicator = () => (_jsx("span", { className: "
|
|
20
|
+
const DefaultVerifiedIndicator = () => (_jsx("span", { className: "text-green-600 dark:text-green-500 ml-0.5", "aria-hidden": "true", children: "\u2713" }));
|
|
21
21
|
/**
|
|
22
22
|
* Default partial match indicator (asterisk)
|
|
23
23
|
*/
|
|
24
|
-
const DefaultPartialIndicator = () => (_jsx("span", { className: "
|
|
24
|
+
const DefaultPartialIndicator = () => (_jsx("span", { className: "text-amber-600 dark:text-amber-500 ml-0.5", "aria-hidden": "true", children: "*" }));
|
|
25
25
|
/**
|
|
26
26
|
* Chip/Badge style citation component.
|
|
27
27
|
* Displays citation as a rounded pill/badge.
|
|
@@ -31,16 +31,11 @@ const DefaultPartialIndicator = () => (_jsx("span", { className: "citation-parti
|
|
|
31
31
|
* <ChipCitation citation={citation} verification={found} size="md" />
|
|
32
32
|
* ```
|
|
33
33
|
*/
|
|
34
|
-
export const ChipCitation = forwardRef(({ citation, children, className,
|
|
34
|
+
export const ChipCitation = forwardRef(({ citation, children, className, 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
35
|
const { citationKey, citationInstanceId, status } = useCitationData(citation, verification);
|
|
36
36
|
const { isVerified, isMiss, isPartialMatch, isPending } = status;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
fallbackDisplay,
|
|
40
|
-
}), [citation, hideKeySpan, fallbackDisplay]);
|
|
41
|
-
const keySpanText = useMemo(() => getCitationKeySpanText(citation, {
|
|
42
|
-
hideKeySpan,
|
|
43
|
-
}), [citation, hideKeySpan]);
|
|
37
|
+
// ChipCitation shows keySpan by default
|
|
38
|
+
const displayText = useMemo(() => getCitationDisplayText(citation, { fallbackDisplay }), [citation, fallbackDisplay]);
|
|
44
39
|
const handleClick = useCallback((e) => {
|
|
45
40
|
e.preventDefault();
|
|
46
41
|
e.stopPropagation();
|
|
@@ -53,22 +48,22 @@ export const ChipCitation = forwardRef(({ citation, children, className, hideKey
|
|
|
53
48
|
eventHandlers?.onMouseLeave?.(citation, citationKey);
|
|
54
49
|
}, [eventHandlers, citation, citationKey]);
|
|
55
50
|
const sizeClasses = {
|
|
56
|
-
sm: "
|
|
57
|
-
md: "
|
|
58
|
-
lg: "
|
|
51
|
+
sm: "text-xs px-1.5 py-px",
|
|
52
|
+
md: "text-sm px-2 py-0.5",
|
|
53
|
+
lg: "text-base px-3 py-1",
|
|
59
54
|
};
|
|
60
55
|
// Check partial first since isVerified is true when isPartialMatch is true
|
|
61
56
|
const statusClass = isPartialMatch
|
|
62
|
-
? "
|
|
57
|
+
? "bg-amber-100 text-amber-600 dark:bg-amber-900/30 dark:text-amber-500"
|
|
63
58
|
: isMiss
|
|
64
|
-
? "
|
|
59
|
+
? "bg-red-100 text-red-600 dark:bg-red-900/30 dark:text-red-400 line-through"
|
|
65
60
|
: isVerified
|
|
66
|
-
? "
|
|
61
|
+
? "bg-green-100 text-green-600 dark:bg-green-900/30 dark:text-green-500"
|
|
67
62
|
: isPending
|
|
68
|
-
? "
|
|
69
|
-
: "";
|
|
70
|
-
return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "chip", className: classNames("
|
|
71
|
-
(icon || _jsx("span", { className: "
|
|
63
|
+
? "bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-400"
|
|
64
|
+
: "bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400";
|
|
65
|
+
return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "chip", className: classNames("inline-flex items-center gap-1 rounded-full font-medium cursor-pointer transition-colors hover:brightness-95", 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 &&
|
|
66
|
+
(icon || _jsx("span", { className: "text-[0.9em]", children: "\uD83D\uDCC4" })), _jsx("span", { className: "font-medium", children: displayText }), isPartialMatch && renderPartialIndicator(status), isVerified && !isPartialMatch && renderVerifiedIndicator(status), isPending && (_jsx("span", { className: "opacity-70", children: pendingContent }))] })] }));
|
|
72
67
|
});
|
|
73
68
|
ChipCitation.displayName = "ChipCitation";
|
|
74
69
|
/**
|
|
@@ -81,13 +76,11 @@ ChipCitation.displayName = "ChipCitation";
|
|
|
81
76
|
* // Renders: Text content¹
|
|
82
77
|
* ```
|
|
83
78
|
*/
|
|
84
|
-
export const SuperscriptCitation = forwardRef(({ citation, children, className,
|
|
79
|
+
export const SuperscriptCitation = forwardRef(({ citation, children, className, fallbackDisplay, verification, eventHandlers, isMobile = false, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), hideBrackets = false, }, ref) => {
|
|
85
80
|
const { citationKey, citationInstanceId, status } = useCitationData(citation, verification);
|
|
86
81
|
const { isVerified, isMiss, isPartialMatch, isPending } = status;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
fallbackDisplay,
|
|
90
|
-
}), [citation, hideKeySpan, fallbackDisplay]);
|
|
82
|
+
// SuperscriptCitation shows number by default
|
|
83
|
+
const displayText = useMemo(() => getCitationNumber(citation), [citation]);
|
|
91
84
|
const handleClick = useCallback((e) => {
|
|
92
85
|
e.preventDefault();
|
|
93
86
|
e.stopPropagation();
|
|
@@ -101,15 +94,15 @@ export const SuperscriptCitation = forwardRef(({ citation, children, className,
|
|
|
101
94
|
}, [eventHandlers, citation, citationKey]);
|
|
102
95
|
// Check partial first since isVerified is true when isPartialMatch is true
|
|
103
96
|
const statusClass = isPartialMatch
|
|
104
|
-
? "
|
|
97
|
+
? "text-amber-600 dark:text-amber-500"
|
|
105
98
|
: isMiss
|
|
106
|
-
? "
|
|
99
|
+
? "text-red-500 dark:text-red-400 line-through"
|
|
107
100
|
: isVerified
|
|
108
|
-
? "
|
|
101
|
+
? "text-green-600 dark:text-green-500"
|
|
109
102
|
: isPending
|
|
110
|
-
? "
|
|
111
|
-
: "";
|
|
112
|
-
return (_jsxs(_Fragment, { children: [children, _jsxs("sup", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "superscript", className: classNames("
|
|
103
|
+
? "text-gray-400 dark:text-gray-500"
|
|
104
|
+
: "text-blue-600 dark:text-blue-400";
|
|
105
|
+
return (_jsxs(_Fragment, { children: [children, _jsxs("sup", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "superscript", className: classNames("text-xs cursor-pointer font-medium transition-colors hover:underline", statusClass, className), onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onMouseDown: handleClick, onClick: (e) => e.stopPropagation(), "aria-label": `Citation ${displayText}`, children: [!hideBrackets && "[", displayText, isPartialMatch && renderPartialIndicator(status), isVerified && !isPartialMatch && renderVerifiedIndicator(status), isPending && pendingContent, !hideBrackets && "]"] })] }));
|
|
113
106
|
});
|
|
114
107
|
SuperscriptCitation.displayName = "SuperscriptCitation";
|
|
115
108
|
const FOOTNOTE_SYMBOLS = ["*", "†", "‡", "§", "‖", "¶"];
|
|
@@ -152,15 +145,15 @@ export const FootnoteCitation = forwardRef(({ citation, children, className, fal
|
|
|
152
145
|
}, [eventHandlers, citation, citationKey]);
|
|
153
146
|
// Check partial first since isVerified is true when isPartialMatch is true
|
|
154
147
|
const statusClass = isPartialMatch
|
|
155
|
-
? "
|
|
148
|
+
? "text-amber-600 dark:text-amber-500"
|
|
156
149
|
: isMiss
|
|
157
|
-
? "
|
|
150
|
+
? "text-red-500 dark:text-red-400 line-through"
|
|
158
151
|
: isVerified
|
|
159
|
-
? "
|
|
152
|
+
? "text-green-600 dark:text-green-500"
|
|
160
153
|
: isPending
|
|
161
|
-
? "
|
|
162
|
-
: "";
|
|
163
|
-
return (_jsxs(_Fragment, { children: [children, _jsxs("sup", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "footnote", className: classNames("
|
|
154
|
+
? "text-gray-400 dark:text-gray-500"
|
|
155
|
+
: "text-gray-500 hover:text-blue-600 dark:text-gray-400 dark:hover:text-blue-400";
|
|
156
|
+
return (_jsxs(_Fragment, { children: [children, _jsxs("sup", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "footnote", className: classNames("text-xs cursor-pointer font-normal transition-colors", 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] })] }));
|
|
164
157
|
});
|
|
165
158
|
FootnoteCitation.displayName = "FootnoteCitation";
|
|
166
159
|
/**
|
|
@@ -173,14 +166,11 @@ FootnoteCitation.displayName = "FootnoteCitation";
|
|
|
173
166
|
* // Renders: "quoted text" with subtle underline
|
|
174
167
|
* ```
|
|
175
168
|
*/
|
|
176
|
-
export const InlineCitation = forwardRef(({ citation, children, className,
|
|
177
|
-
fallbackDisplay, verification, eventHandlers, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), underlineStyle = "dotted", }, ref) => {
|
|
169
|
+
export const InlineCitation = forwardRef(({ citation, children, className, fallbackDisplay, verification, eventHandlers, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), underlineStyle = "dotted", }, ref) => {
|
|
178
170
|
const { citationKey, citationInstanceId, status } = useCitationData(citation, verification);
|
|
179
171
|
const { isVerified, isMiss, isPartialMatch, isPending } = status;
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
fallbackDisplay,
|
|
183
|
-
}), [citation, hideKeySpan, fallbackDisplay]);
|
|
172
|
+
// InlineCitation shows keySpan by default
|
|
173
|
+
const displayText = useMemo(() => getCitationDisplayText(citation, { fallbackDisplay }), [citation, fallbackDisplay]);
|
|
184
174
|
const handleClick = useCallback((e) => {
|
|
185
175
|
e.preventDefault();
|
|
186
176
|
e.stopPropagation();
|
|
@@ -194,16 +184,21 @@ fallbackDisplay, verification, eventHandlers, preventTooltips = false, pendingCo
|
|
|
194
184
|
}, [eventHandlers, citation, citationKey]);
|
|
195
185
|
// Check partial first since isVerified is true when isPartialMatch is true
|
|
196
186
|
const statusClass = isPartialMatch
|
|
197
|
-
? "
|
|
187
|
+
? "text-amber-600 dark:text-amber-500"
|
|
198
188
|
: isMiss
|
|
199
|
-
? "
|
|
189
|
+
? "text-red-500 dark:text-red-400 line-through"
|
|
200
190
|
: isVerified
|
|
201
|
-
? "
|
|
191
|
+
? "text-green-600 dark:text-green-500"
|
|
202
192
|
: isPending
|
|
203
|
-
? "
|
|
193
|
+
? "text-gray-400 dark:text-gray-500"
|
|
204
194
|
: "";
|
|
205
|
-
const
|
|
206
|
-
|
|
195
|
+
const underlineClasses = {
|
|
196
|
+
solid: "border-b border-current",
|
|
197
|
+
dotted: "border-b border-dotted border-current",
|
|
198
|
+
dashed: "border-b border-dashed border-current",
|
|
199
|
+
none: "",
|
|
200
|
+
};
|
|
201
|
+
return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "inline", className: classNames("cursor-pointer transition-colors hover:bg-blue-500/5", underlineClasses[underlineStyle], 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: "opacity-70 ml-1", children: pendingContent }))] })] }));
|
|
207
202
|
});
|
|
208
203
|
InlineCitation.displayName = "InlineCitation";
|
|
209
204
|
/**
|
|
@@ -216,13 +211,11 @@ InlineCitation.displayName = "InlineCitation";
|
|
|
216
211
|
* // Renders: 1
|
|
217
212
|
* ```
|
|
218
213
|
*/
|
|
219
|
-
export const MinimalCitation = forwardRef(({ citation, children, className,
|
|
214
|
+
export const MinimalCitation = forwardRef(({ citation, children, className, fallbackDisplay, verification, eventHandlers, preventTooltips = false, pendingContent = TWO_DOTS_THINKING_CONTENT, renderVerifiedIndicator = () => _jsx(DefaultVerifiedIndicator, {}), renderPartialIndicator = () => _jsx(DefaultPartialIndicator, {}), showStatusIndicator = true, }, ref) => {
|
|
220
215
|
const { citationKey, citationInstanceId, status } = useCitationData(citation, verification);
|
|
221
216
|
const { isVerified, isMiss, isPartialMatch, isPending } = status;
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
fallbackDisplay,
|
|
225
|
-
}), [citation, hideKeySpan, fallbackDisplay]);
|
|
217
|
+
// MinimalCitation shows number by default
|
|
218
|
+
const displayText = useMemo(() => getCitationNumber(citation), [citation]);
|
|
226
219
|
const handleClick = useCallback((e) => {
|
|
227
220
|
e.preventDefault();
|
|
228
221
|
e.stopPropagation();
|
|
@@ -236,15 +229,15 @@ export const MinimalCitation = forwardRef(({ citation, children, className, hide
|
|
|
236
229
|
}, [eventHandlers, citation, citationKey]);
|
|
237
230
|
// Check partial first since isVerified is true when isPartialMatch is true
|
|
238
231
|
const statusClass = isPartialMatch
|
|
239
|
-
? "
|
|
232
|
+
? "text-amber-600 dark:text-amber-500"
|
|
240
233
|
: isMiss
|
|
241
|
-
? "
|
|
234
|
+
? "text-red-500 dark:text-red-400 line-through"
|
|
242
235
|
: isVerified
|
|
243
|
-
? "
|
|
236
|
+
? "text-green-600 dark:text-green-500"
|
|
244
237
|
: isPending
|
|
245
|
-
? "
|
|
246
|
-
: "";
|
|
247
|
-
return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "minimal", className: classNames("
|
|
238
|
+
? "text-gray-400 dark:text-gray-500"
|
|
239
|
+
: "text-blue-600 dark:text-blue-400";
|
|
240
|
+
return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-variant": "minimal", className: classNames("cursor-pointer transition-colors hover:underline", 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] }))] })] }));
|
|
248
241
|
});
|
|
249
242
|
MinimalCitation.displayName = "MinimalCitation";
|
|
250
243
|
/**
|
|
@@ -39,19 +39,19 @@ function getUrlPath(url) {
|
|
|
39
39
|
* Status indicator icons for URL fetch states.
|
|
40
40
|
*/
|
|
41
41
|
const STATUS_ICONS = {
|
|
42
|
-
verified: { icon: "✓", label: "Verified", className: "
|
|
43
|
-
partial: { icon: "~", label: "Partial match", className: "
|
|
44
|
-
pending: { icon: "…", label: "Verifying", className: "
|
|
45
|
-
blocked_antibot: { icon: "🛡", label: "Blocked by anti-bot", className: "
|
|
46
|
-
blocked_login: { icon: "🔒", label: "Login required", className: "
|
|
47
|
-
blocked_paywall: { icon: "💳", label: "Paywall", className: "
|
|
48
|
-
blocked_geo: { icon: "🌍", label: "Geo-restricted", className: "
|
|
49
|
-
blocked_rate_limit: { icon: "⏱", label: "Rate limited", className: "
|
|
50
|
-
error_timeout: { icon: "⏰", label: "Timed out", className: "
|
|
51
|
-
error_not_found: { icon: "404", label: "Not found", className: "
|
|
52
|
-
error_server: { icon: "⚠", label: "Server error", className: "
|
|
53
|
-
error_network: { icon: "⚡", label: "Network error", className: "
|
|
54
|
-
unknown: { icon: "?", label: "Unknown status", className: "
|
|
42
|
+
verified: { icon: "✓", label: "Verified", className: "text-green-600 dark:text-green-500" },
|
|
43
|
+
partial: { icon: "~", label: "Partial match", className: "text-amber-600 dark:text-amber-500" },
|
|
44
|
+
pending: { icon: "…", label: "Verifying", className: "text-gray-400 dark:text-gray-500" },
|
|
45
|
+
blocked_antibot: { icon: "🛡", label: "Blocked by anti-bot", className: "text-amber-600 dark:text-amber-500" },
|
|
46
|
+
blocked_login: { icon: "🔒", label: "Login required", className: "text-amber-600 dark:text-amber-500" },
|
|
47
|
+
blocked_paywall: { icon: "💳", label: "Paywall", className: "text-amber-600 dark:text-amber-500" },
|
|
48
|
+
blocked_geo: { icon: "🌍", label: "Geo-restricted", className: "text-amber-600 dark:text-amber-500" },
|
|
49
|
+
blocked_rate_limit: { icon: "⏱", label: "Rate limited", className: "text-amber-600 dark:text-amber-500" },
|
|
50
|
+
error_timeout: { icon: "⏰", label: "Timed out", className: "text-red-500 dark:text-red-400" },
|
|
51
|
+
error_not_found: { icon: "404", label: "Not found", className: "text-red-500 dark:text-red-400" },
|
|
52
|
+
error_server: { icon: "⚠", label: "Server error", className: "text-red-500 dark:text-red-400" },
|
|
53
|
+
error_network: { icon: "⚡", label: "Network error", className: "text-red-500 dark:text-red-400" },
|
|
54
|
+
unknown: { icon: "?", label: "Unknown status", className: "text-gray-400 dark:text-gray-500" },
|
|
55
55
|
};
|
|
56
56
|
/**
|
|
57
57
|
* Checks if status is a blocked status.
|
|
@@ -76,7 +76,7 @@ export function isVerifiedStatus(status) {
|
|
|
76
76
|
*/
|
|
77
77
|
const DefaultBlockedIndicator = ({ status, errorMessage }) => {
|
|
78
78
|
const statusInfo = STATUS_ICONS[status];
|
|
79
|
-
return (_jsx("span", { className: classNames("
|
|
79
|
+
return (_jsx("span", { className: classNames("inline-flex items-center gap-1", statusInfo.className), title: errorMessage || statusInfo.label, "aria-label": statusInfo.label, children: _jsx("span", { className: "text-[0.9em]", "aria-hidden": "true", children: statusInfo.icon }) }));
|
|
80
80
|
};
|
|
81
81
|
/**
|
|
82
82
|
* Default favicon component.
|
|
@@ -84,7 +84,7 @@ const DefaultBlockedIndicator = ({ status, errorMessage }) => {
|
|
|
84
84
|
const DefaultFavicon = ({ url, faviconUrl }) => {
|
|
85
85
|
const domain = extractDomain(url);
|
|
86
86
|
const src = faviconUrl || `https://www.google.com/s2/favicons?domain=${domain}&sz=16`;
|
|
87
|
-
return (_jsx("img", { src: src, alt: "", className: "
|
|
87
|
+
return (_jsx("img", { src: src, alt: "", className: "w-3.5 h-3.5 rounded-sm", width: 14, height: 14, loading: "lazy", onError: e => {
|
|
88
88
|
// Hide broken favicon images
|
|
89
89
|
e.target.style.display = "none";
|
|
90
90
|
} }));
|
|
@@ -167,29 +167,29 @@ showFullUrlOnHover = true, showFavicon = true, showTitle = false, maxDisplayLeng
|
|
|
167
167
|
return _jsx(DefaultBlockedIndicator, { status: fetchStatus, errorMessage: errorMessage });
|
|
168
168
|
}
|
|
169
169
|
if (isVerified) {
|
|
170
|
-
return (_jsx("span", { className: "
|
|
170
|
+
return (_jsx("span", { className: "text-[0.85em] text-green-600 dark:text-green-500", "aria-hidden": "true", title: "Verified", children: "\u2713" }));
|
|
171
171
|
}
|
|
172
172
|
if (isPartial) {
|
|
173
|
-
return (_jsx("span", { className: "
|
|
173
|
+
return (_jsx("span", { className: "text-[0.85em] text-amber-600 dark:text-amber-500", "aria-hidden": "true", title: "Partial match", children: "~" }));
|
|
174
174
|
}
|
|
175
175
|
if (isPending) {
|
|
176
|
-
return (_jsx("span", { className: "
|
|
176
|
+
return (_jsx("span", { className: "opacity-70", "aria-hidden": "true", children: "\u2026" }));
|
|
177
177
|
}
|
|
178
178
|
return null;
|
|
179
179
|
};
|
|
180
180
|
// Choose variant-specific rendering
|
|
181
181
|
if (variant === "chip") {
|
|
182
|
-
return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-url": url, "data-fetch-status": fetchStatus, className: classNames("
|
|
182
|
+
return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-url": url, "data-fetch-status": fetchStatus, "data-variant": "chip", className: classNames("inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-sm cursor-pointer transition-colors no-underline", "bg-blue-100 dark:bg-blue-900/30", statusInfo.className, className), title: showFullUrlOnHover ? url : undefined, onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onMouseDown: handleClick, onClick: e => e.stopPropagation(), role: "link", "aria-label": `Link to ${domain}: ${statusInfo.label}`, children: [showFavicon && _jsx(DefaultFavicon, { url: url, faviconUrl: faviconUrl }), _jsx("span", { className: "max-w-[200px] overflow-hidden text-ellipsis whitespace-nowrap", children: displayText }), renderStatusIndicator()] })] }));
|
|
183
183
|
}
|
|
184
184
|
// Inline variant
|
|
185
185
|
if (variant === "inline") {
|
|
186
|
-
return (_jsxs(_Fragment, { children: [children, _jsxs("a", { ref: ref, href: url, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-fetch-status": fetchStatus, className: classNames("
|
|
186
|
+
return (_jsxs(_Fragment, { children: [children, _jsxs("a", { ref: ref, href: url, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-fetch-status": fetchStatus, "data-variant": "inline", className: classNames("inline-flex items-center gap-1 cursor-pointer transition-colors no-underline border-b border-dotted border-current", statusInfo.className, className), title: showFullUrlOnHover ? url : undefined, onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onClick: e => {
|
|
187
187
|
e.preventDefault();
|
|
188
188
|
handleClick(e);
|
|
189
|
-
}, target: "_blank", rel: "noopener noreferrer", "aria-label": `Link to ${domain}: ${statusInfo.label}`, children: [showFavicon && _jsx(DefaultFavicon, { url: url, faviconUrl: faviconUrl }), _jsx("span", {
|
|
189
|
+
}, target: "_blank", rel: "noopener noreferrer", "aria-label": `Link to ${domain}: ${statusInfo.label}`, children: [showFavicon && _jsx(DefaultFavicon, { url: url, faviconUrl: faviconUrl }), _jsx("span", { children: displayText }), renderStatusIndicator()] })] }));
|
|
190
190
|
}
|
|
191
191
|
// Bracket variant (default for non-URL citations)
|
|
192
|
-
return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-url": url, "data-fetch-status": fetchStatus, className: classNames("
|
|
192
|
+
return (_jsxs(_Fragment, { children: [children, _jsxs("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, "data-url": url, "data-fetch-status": fetchStatus, "data-variant": "bracket", className: classNames("cursor-pointer transition-colors", statusInfo.className, className), title: showFullUrlOnHover ? url : undefined, onMouseEnter: preventTooltips ? undefined : handleMouseEnter, onMouseLeave: preventTooltips ? undefined : handleMouseLeave, onMouseDown: handleClick, onClick: e => e.stopPropagation(), role: "link", "aria-label": `Link to ${domain}: ${statusInfo.label}`, children: ["[", showFavicon && _jsx(DefaultFavicon, { url: url, faviconUrl: faviconUrl }), _jsx("span", { className: "max-w-[200px] overflow-hidden text-ellipsis whitespace-nowrap", children: displayText }), renderStatusIndicator(), "]"] })] }));
|
|
193
193
|
});
|
|
194
194
|
UrlCitationComponent.displayName = "UrlCitationComponent";
|
|
195
195
|
/**
|
package/lib/react/icons.d.ts
CHANGED
|
@@ -7,11 +7,15 @@ export declare const DeepCitationIcon: ({ className }: {
|
|
|
7
7
|
/**
|
|
8
8
|
* Check icon SVG (no dependencies)
|
|
9
9
|
*/
|
|
10
|
-
export declare const CheckIcon: (
|
|
10
|
+
export declare const CheckIcon: ({ className }: {
|
|
11
|
+
className?: string;
|
|
12
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
11
13
|
/**
|
|
12
14
|
* Warning icon SVG (no dependencies)
|
|
13
15
|
*/
|
|
14
|
-
export declare const WarningIcon: (
|
|
16
|
+
export declare const WarningIcon: ({ className }: {
|
|
17
|
+
className?: string;
|
|
18
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
15
19
|
/** Spinner component for loading/pending state */
|
|
16
20
|
export declare const SpinnerIcon: ({ className }: {
|
|
17
21
|
className?: string;
|
package/lib/react/icons.js
CHANGED
|
@@ -7,10 +7,10 @@ export const DeepCitationIcon = ({ className }) => (_jsxs("svg", { xmlns: "http:
|
|
|
7
7
|
/**
|
|
8
8
|
* Check icon SVG (no dependencies)
|
|
9
9
|
*/
|
|
10
|
-
export const CheckIcon = () => (_jsx("svg", { className: "
|
|
10
|
+
export const CheckIcon = ({ className }) => (_jsx("svg", { className: cn("w-[0.7em] h-[0.7em]", className), viewBox: "0 0 256 256", fill: "currentColor", "aria-hidden": "true", children: _jsx("path", { d: "M229.66,66.34 L96,200 L34.34,138.34 L51,121.66 L96,166.69 L213,50 Z", stroke: "currentColor", strokeWidth: "12" }) }));
|
|
11
11
|
/**
|
|
12
12
|
* Warning icon SVG (no dependencies)
|
|
13
13
|
*/
|
|
14
|
-
export const WarningIcon = () => (_jsx("svg", { className: "
|
|
14
|
+
export const WarningIcon = ({ className }) => (_jsx("svg", { className: cn("w-[0.7em] h-[0.7em]", className), viewBox: "0 0 256 256", fill: "currentColor", "aria-hidden": "true", children: _jsx("path", { d: "M236.8,188.09,149.35,36.22h0a24.76,24.76,0,0,0-42.7,0L19.2,188.09a23.51,23.51,0,0,0,0,23.72A24.35,24.35,0,0,0,40.55,224h174.9a24.35,24.35,0,0,0,21.33-12.19A23.51,23.51,0,0,0,236.8,188.09ZM120,104a8,8,0,0,1,16,0v40a8,8,0,0,1-16,0Zm8,88a12,12,0,1,1,12-12A12,12,0,0,1,128,192Z" }) }));
|
|
15
15
|
/** Spinner component for loading/pending state */
|
|
16
|
-
export const SpinnerIcon = ({ className }) => (_jsxs("svg", { className: cn("animate-spin", className), xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24",
|
|
16
|
+
export const SpinnerIcon = ({ className }) => (_jsxs("svg", { className: cn("w-[0.7em] h-[0.7em] animate-spin", className), xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }));
|
package/lib/react/index.d.ts
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @packageDocumentation
|
|
12
12
|
*/
|
|
13
|
-
export type { CitationContentProps, CitationRenderProps, CitationTooltipProps, CitationStyles, CitationStateClasses, CitationCursorClasses, CitationEventHandlers, CitationVariant as CitationVariantType, UrlFetchStatus, UrlCitationMeta, UrlCitationProps, CitationBehaviorConfig, CitationBehaviorContext, CitationBehaviorActions, CitationClickBehavior, CitationHoverBehavior, } from "./types.js";
|
|
13
|
+
export type { CitationContentProps, CitationRenderProps, CitationTooltipProps, CitationStyles, CitationStateClasses, CitationCursorClasses, CitationEventHandlers, CitationVariant as CitationVariantType, CitationContent, UrlFetchStatus, UrlCitationMeta, UrlCitationProps, UrlCitationVariant, CitationBehaviorConfig, CitationBehaviorContext, CitationBehaviorActions, CitationClickBehavior, CitationHoverBehavior, } from "./types.js";
|
|
14
14
|
export { extractDomain, isBlockedStatus, isErrorStatus, isVerifiedStatus, } from "./UrlCitationComponent.js";
|
|
15
|
-
export { generateCitationKey, generateCitationInstanceId, getCitationDisplayText, getCitationKeySpanText, classNames, CITATION_X_PADDING, CITATION_Y_PADDING, } from "./utils.js";
|
|
15
|
+
export { generateCitationKey, generateCitationInstanceId, getCitationDisplayText, getCitationNumber, getCitationKeySpanText, classNames, CITATION_X_PADDING, CITATION_Y_PADDING, } from "./utils.js";
|
|
16
16
|
export { CitationComponent, MemoizedCitationComponent, type CitationVariant, type CitationComponentProps, } from "./CitationComponent.js";
|
|
17
|
+
export { DeepCitationIcon, CheckIcon, SpinnerIcon, WarningIcon, } from "./icons.js";
|
package/lib/react/index.js
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
// URL Utilities - For handling URL citation metadata
|
|
14
14
|
export { extractDomain, isBlockedStatus, isErrorStatus, isVerifiedStatus, } from "./UrlCitationComponent.js";
|
|
15
15
|
// Utilities - For generating citation keys and display text
|
|
16
|
-
export { generateCitationKey, generateCitationInstanceId, getCitationDisplayText, getCitationKeySpanText, classNames, CITATION_X_PADDING, CITATION_Y_PADDING, } from "./utils.js";
|
|
16
|
+
export { generateCitationKey, generateCitationInstanceId, getCitationDisplayText, getCitationNumber, getCitationKeySpanText, classNames, CITATION_X_PADDING, CITATION_Y_PADDING, } from "./utils.js";
|
|
17
17
|
// Components
|
|
18
18
|
export { CitationComponent, MemoizedCitationComponent, } from "./CitationComponent.js";
|
|
19
|
+
// Icons
|
|
20
|
+
export { DeepCitationIcon, CheckIcon, SpinnerIcon, WarningIcon, } from "./icons.js";
|
|
@@ -12,7 +12,6 @@ interface CitationContextValue {
|
|
|
12
12
|
status: CitationStatus;
|
|
13
13
|
verification: Verification | null;
|
|
14
14
|
config: {
|
|
15
|
-
hideKeySpan: boolean;
|
|
16
15
|
fallbackDisplay: string | null;
|
|
17
16
|
pendingContent: ReactNode;
|
|
18
17
|
};
|
|
@@ -25,7 +24,6 @@ export interface CitationRootProps {
|
|
|
25
24
|
citation: CitationType;
|
|
26
25
|
verification?: Verification | null;
|
|
27
26
|
children: ReactNode;
|
|
28
|
-
hideKeySpan?: boolean;
|
|
29
27
|
fallbackDisplay?: string | null;
|
|
30
28
|
pendingContent?: ReactNode;
|
|
31
29
|
}
|
package/lib/react/primitives.js
CHANGED
|
@@ -20,7 +20,7 @@ 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, verification = null, children,
|
|
23
|
+
export const CitationRoot = forwardRef(({ citation, verification = null, children, fallbackDisplay = null, pendingContent = "..", className, ...props }, ref) => {
|
|
24
24
|
const citationKey = useMemo(() => generateCitationKey(citation), [citation]);
|
|
25
25
|
const citationInstanceId = useMemo(() => generateCitationInstanceId(citationKey), [citationKey]);
|
|
26
26
|
const status = getCitationStatus(verification);
|
|
@@ -31,7 +31,6 @@ export const CitationRoot = forwardRef(({ citation, verification = null, childre
|
|
|
31
31
|
status,
|
|
32
32
|
verification,
|
|
33
33
|
config: {
|
|
34
|
-
hideKeySpan,
|
|
35
34
|
fallbackDisplay,
|
|
36
35
|
pendingContent,
|
|
37
36
|
},
|
|
@@ -41,11 +40,10 @@ export const CitationRoot = forwardRef(({ citation, verification = null, childre
|
|
|
41
40
|
citationInstanceId,
|
|
42
41
|
status,
|
|
43
42
|
verification,
|
|
44
|
-
hideKeySpan,
|
|
45
43
|
fallbackDisplay,
|
|
46
44
|
pendingContent,
|
|
47
45
|
]);
|
|
48
|
-
return (_jsx(CitationContext.Provider, { value: contextValue, children: _jsx("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, className: classNames("
|
|
46
|
+
return (_jsx(CitationContext.Provider, { value: contextValue, children: _jsx("span", { ref: ref, "data-citation-id": citationKey, "data-citation-instance": citationInstanceId, className: classNames("inline", className), ...props, children: children }) }));
|
|
49
47
|
});
|
|
50
48
|
CitationRoot.displayName = "Citation.Root";
|
|
51
49
|
/** Interactive trigger component for the citation. */
|
|
@@ -83,13 +81,13 @@ export const CitationTrigger = forwardRef(({ children, className, onCitationClic
|
|
|
83
81
|
}, [onTouchEnd, isMobile, onCitationTouchEnd, citation, citationKey]);
|
|
84
82
|
const statusClasses = classNames(status.isVerified &&
|
|
85
83
|
!status.isPartialMatch &&
|
|
86
|
-
"
|
|
87
|
-
return (_jsx("span", { ref: ref, role: "button", tabIndex: 0, className: classNames("
|
|
84
|
+
"text-green-600 dark:text-green-500", status.isPartialMatch && "text-amber-600 dark:text-amber-500", status.isMiss && "text-red-500 dark:text-red-400 line-through", status.isPending && "text-gray-400 dark:text-gray-500");
|
|
85
|
+
return (_jsx("span", { ref: ref, role: "button", tabIndex: 0, className: classNames("cursor-pointer transition-colors focus-visible:outline-2 focus-visible:outline-blue-500 focus-visible:outline-offset-2 focus-visible:rounded-sm", statusClasses, className), onClick: handleClick, onMouseDown: handleMouseDown, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onTouchEndCapture: isMobile ? handleTouchEnd : undefined, ...props, children: children }));
|
|
88
86
|
});
|
|
89
87
|
CitationTrigger.displayName = "Citation.Trigger";
|
|
90
88
|
/** Bracket wrapper component for citation content. */
|
|
91
89
|
export const CitationBracket = forwardRef(({ children, className, open = "[", close = "]", ...props }, ref) => {
|
|
92
|
-
return (_jsxs("span", { ref: ref, className: classNames("
|
|
90
|
+
return (_jsxs("span", { ref: ref, className: classNames("inline", className), "aria-hidden": "true", ...props, children: [_jsx("span", { className: "inline", children: open }), _jsx("span", { className: "inline", children: children }), _jsx("span", { className: "inline", children: close })] }));
|
|
93
91
|
});
|
|
94
92
|
CitationBracket.displayName = "Citation.Bracket";
|
|
95
93
|
/** Displays the citation number. */
|
|
@@ -98,33 +96,28 @@ export const CitationNumber = forwardRef(({ className, number, ...props }, ref)
|
|
|
98
96
|
const displayNumber = useMemo(() => {
|
|
99
97
|
if (number !== undefined)
|
|
100
98
|
return String(number);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
"");
|
|
106
|
-
}
|
|
107
|
-
return citation.citationNumber?.toString() || "";
|
|
99
|
+
return (citation.keySpan?.toString() ||
|
|
100
|
+
citation.citationNumber?.toString() ||
|
|
101
|
+
config.fallbackDisplay ||
|
|
102
|
+
"1");
|
|
108
103
|
}, [number, citation, config]);
|
|
109
104
|
if (status.isPending) {
|
|
110
|
-
return (_jsx("span", { ref: ref, className: classNames("
|
|
105
|
+
return (_jsx("span", { ref: ref, className: classNames("font-medium opacity-60", className), ...props, children: config.pendingContent }));
|
|
111
106
|
}
|
|
112
|
-
return (_jsx("span", { ref: ref, className: classNames("
|
|
107
|
+
return (_jsx("span", { ref: ref, className: classNames("font-medium", className), ...props, children: displayNumber }));
|
|
113
108
|
});
|
|
114
109
|
CitationNumber.displayName = "Citation.Number";
|
|
115
110
|
/** Displays the citation keySpan (summary text). */
|
|
116
111
|
export const CitationKeySpan = forwardRef(({ className, keySpan, separator = " ", ...props }, ref) => {
|
|
117
|
-
const { citation
|
|
112
|
+
const { citation } = useCitationContext();
|
|
118
113
|
const displayKeySpan = useMemo(() => {
|
|
119
114
|
if (keySpan !== undefined)
|
|
120
115
|
return keySpan;
|
|
121
|
-
if (config.hideKeySpan)
|
|
122
|
-
return "";
|
|
123
116
|
return citation.keySpan?.toString() || "";
|
|
124
|
-
}, [keySpan, citation
|
|
117
|
+
}, [keySpan, citation]);
|
|
125
118
|
if (!displayKeySpan)
|
|
126
119
|
return null;
|
|
127
|
-
return (_jsxs("span", { ref: ref, className: classNames("
|
|
120
|
+
return (_jsxs("span", { ref: ref, className: classNames("italic", className), ...props, children: [displayKeySpan, separator] }));
|
|
128
121
|
});
|
|
129
122
|
CitationKeySpan.displayName = "Citation.KeySpan";
|
|
130
123
|
/** Displays a status indicator based on citation verification state. */
|
|
@@ -135,17 +128,18 @@ export const CitationIndicator = forwardRef(({ className, verifiedIndicator = "
|
|
|
135
128
|
return true;
|
|
136
129
|
return showFor.includes(state);
|
|
137
130
|
}, [showFor]);
|
|
131
|
+
const baseClasses = "inline ml-0.5 text-[0.85em]";
|
|
138
132
|
if (status.isPartialMatch && shouldShow("partial")) {
|
|
139
|
-
return (_jsx("span", { ref: ref, className: classNames("
|
|
133
|
+
return (_jsx("span", { ref: ref, className: classNames(baseClasses, "text-amber-600 dark:text-amber-500", className), "aria-label": "Partial match", ...props, children: partialIndicator }));
|
|
140
134
|
}
|
|
141
135
|
if (status.isVerified && !status.isPartialMatch && shouldShow("verified")) {
|
|
142
|
-
return (_jsx("span", { ref: ref, className: classNames("
|
|
136
|
+
return (_jsx("span", { ref: ref, className: classNames(baseClasses, "text-green-600 dark:text-green-500", className), "aria-label": "Verified", ...props, children: verifiedIndicator }));
|
|
143
137
|
}
|
|
144
138
|
if (status.isMiss && shouldShow("miss") && missIndicator) {
|
|
145
|
-
return (_jsx("span", { ref: ref, className: classNames("
|
|
139
|
+
return (_jsx("span", { ref: ref, className: classNames(baseClasses, "text-red-500 dark:text-red-400", className), "aria-label": "Not found", ...props, children: missIndicator }));
|
|
146
140
|
}
|
|
147
141
|
if (status.isPending && shouldShow("pending") && pendingIndicator) {
|
|
148
|
-
return (_jsx("span", { ref: ref, className: classNames("
|
|
142
|
+
return (_jsx("span", { ref: ref, className: classNames(baseClasses, "text-gray-400 dark:text-gray-500", className), "aria-label": "Pending", ...props, children: pendingIndicator }));
|
|
149
143
|
}
|
|
150
144
|
return null;
|
|
151
145
|
});
|
|
@@ -167,7 +161,7 @@ export const CitationPhrase = forwardRef(({ className, maxLength, truncationSuff
|
|
|
167
161
|
}, [citation.fullPhrase, maxLength, truncationSuffix]);
|
|
168
162
|
if (!displayPhrase)
|
|
169
163
|
return null;
|
|
170
|
-
return (_jsx("span", { ref: ref, className: classNames("
|
|
164
|
+
return (_jsx("span", { ref: ref, className: classNames("italic", className), ...props, children: displayPhrase }));
|
|
171
165
|
});
|
|
172
166
|
CitationPhrase.displayName = "Citation.Phrase";
|
|
173
167
|
/** Displays the citation's page number. */
|
|
@@ -176,7 +170,7 @@ export const CitationPage = forwardRef(({ className, prefix = "", ...props }, re
|
|
|
176
170
|
if (citation.pageNumber === undefined || citation.pageNumber === null) {
|
|
177
171
|
return null;
|
|
178
172
|
}
|
|
179
|
-
return (_jsxs("span", { ref: ref, className: classNames("
|
|
173
|
+
return (_jsxs("span", { ref: ref, className: classNames("text-xs text-gray-400 dark:text-gray-500", className), ...props, children: [prefix, citation.pageNumber] }));
|
|
180
174
|
});
|
|
181
175
|
CitationPage.displayName = "Citation.Page";
|
|
182
176
|
/** Citation primitives namespace for composable citation components. */
|
package/lib/react/types.d.ts
CHANGED
|
@@ -2,16 +2,34 @@ import type { Citation, CitationStatus } from "../types/citation.js";
|
|
|
2
2
|
import type { Verification } from "../types/verification.js";
|
|
3
3
|
import type { SearchStatus } from "../types/search.js";
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Visual style variants for citations.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
7
|
+
* | Variant | Description |
|
|
8
|
+
* |---------------|------------------------------------------------|
|
|
9
|
+
* | `chip` | Pill/badge style with background color |
|
|
10
|
+
* | `brackets` | [text✓] with square brackets (default) |
|
|
11
|
+
* | `text` | Plain text, inherits parent styling |
|
|
12
|
+
* | `superscript` | Small raised text like footnotes¹ |
|
|
13
|
+
* | `minimal` | Compact text with indicator, truncated |
|
|
13
14
|
*/
|
|
14
|
-
export type CitationVariant = "brackets" | "text" | "
|
|
15
|
+
export type CitationVariant = "chip" | "brackets" | "text" | "superscript" | "minimal";
|
|
16
|
+
/**
|
|
17
|
+
* Content to display in the citation.
|
|
18
|
+
*
|
|
19
|
+
* | Content | Description |
|
|
20
|
+
* |---------------|------------------------------------------------|
|
|
21
|
+
* | `keySpan` | Descriptive text (e.g., "Revenue Growth") |
|
|
22
|
+
* | `number` | Citation number (e.g., "1", "2", "3") |
|
|
23
|
+
* | `indicator` | Only the status icon (✓/⚠), no text |
|
|
24
|
+
*
|
|
25
|
+
* Default content per variant:
|
|
26
|
+
* - `chip` → `keySpan`
|
|
27
|
+
* - `brackets` → `number`
|
|
28
|
+
* - `text` → `keySpan`
|
|
29
|
+
* - `superscript` → `number`
|
|
30
|
+
* - `minimal` → `number`
|
|
31
|
+
*/
|
|
32
|
+
export type CitationContent = "keySpan" | "number" | "indicator";
|
|
15
33
|
/**
|
|
16
34
|
* URL fetch status for URL citations.
|
|
17
35
|
*/
|
|
@@ -91,19 +109,33 @@ export interface BaseCitationProps {
|
|
|
91
109
|
/** Class name for controlling inner content width */
|
|
92
110
|
innerWidthClassName?: string;
|
|
93
111
|
/**
|
|
94
|
-
*
|
|
95
|
-
* @default
|
|
112
|
+
* Visual style variant for the citation.
|
|
113
|
+
* @default "brackets"
|
|
114
|
+
*/
|
|
115
|
+
variant?: CitationVariant;
|
|
116
|
+
/**
|
|
117
|
+
* What content to display in the citation.
|
|
118
|
+
* If not specified, defaults based on variant:
|
|
119
|
+
* - `chip` → `keySpan`
|
|
120
|
+
* - `brackets` → `number`
|
|
121
|
+
* - `text` → `keySpan`
|
|
122
|
+
* - `superscript` → `number`
|
|
123
|
+
* - `minimal` → `number`
|
|
96
124
|
*/
|
|
97
|
-
|
|
125
|
+
content?: CitationContent;
|
|
98
126
|
/** Fallback display text when citation keySpan is empty */
|
|
99
127
|
fallbackDisplay?: string | null;
|
|
100
|
-
/** Display variant for the citation */
|
|
101
|
-
variant?: CitationVariant;
|
|
102
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Visual style variants for URL citations.
|
|
131
|
+
*/
|
|
132
|
+
export type UrlCitationVariant = "chip" | "inline" | "bracket";
|
|
103
133
|
/**
|
|
104
134
|
* Props for URL citation component
|
|
105
135
|
*/
|
|
106
|
-
export interface UrlCitationProps extends Omit<BaseCitationProps, "citation"> {
|
|
136
|
+
export interface UrlCitationProps extends Omit<BaseCitationProps, "citation" | "variant"> {
|
|
137
|
+
/** Visual style variant for the URL citation */
|
|
138
|
+
variant?: UrlCitationVariant;
|
|
107
139
|
/** URL metadata including fetch status */
|
|
108
140
|
urlMeta: UrlCitationMeta;
|
|
109
141
|
/** The citation data (optional, will be derived from urlMeta if not provided) */
|
package/lib/react/utils.d.ts
CHANGED
|
@@ -19,18 +19,19 @@ export declare function generateVerificationKey(verification: Verification): str
|
|
|
19
19
|
*/
|
|
20
20
|
export declare function generateCitationInstanceId(citationKey: string): string;
|
|
21
21
|
/**
|
|
22
|
-
* Gets the display text for a citation
|
|
22
|
+
* Gets the display text for a citation (keySpan with fallback to number).
|
|
23
23
|
*/
|
|
24
24
|
export declare function getCitationDisplayText(citation: Citation, options?: {
|
|
25
|
-
hideKeySpan?: boolean;
|
|
26
25
|
fallbackDisplay?: string | null;
|
|
27
26
|
}): string;
|
|
28
27
|
/**
|
|
29
|
-
* Gets the
|
|
28
|
+
* Gets the citation number as a string.
|
|
30
29
|
*/
|
|
31
|
-
export declare function
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
export declare function getCitationNumber(citation: Citation): string;
|
|
31
|
+
/**
|
|
32
|
+
* Gets the keySpan text from a citation.
|
|
33
|
+
*/
|
|
34
|
+
export declare function getCitationKeySpanText(citation: Citation): string;
|
|
34
35
|
/**
|
|
35
36
|
* Joins class names, filtering out falsy values.
|
|
36
37
|
* This is a minimal implementation for the base component.
|
package/lib/react/utils.js
CHANGED
|
@@ -53,26 +53,25 @@ export function generateCitationInstanceId(citationKey) {
|
|
|
53
53
|
return `${citationKey}-${randomSuffix}`;
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* Gets the display text for a citation
|
|
56
|
+
* Gets the display text for a citation (keySpan with fallback to number).
|
|
57
57
|
*/
|
|
58
58
|
export function getCitationDisplayText(citation, options = {}) {
|
|
59
|
-
const {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
"");
|
|
65
|
-
}
|
|
66
|
-
return citation.citationNumber?.toString() || "";
|
|
59
|
+
const { fallbackDisplay } = options;
|
|
60
|
+
return (citation.keySpan?.toString() ||
|
|
61
|
+
citation.citationNumber?.toString() ||
|
|
62
|
+
fallbackDisplay ||
|
|
63
|
+
"1");
|
|
67
64
|
}
|
|
68
65
|
/**
|
|
69
|
-
* Gets the
|
|
66
|
+
* Gets the citation number as a string.
|
|
70
67
|
*/
|
|
71
|
-
export function
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
68
|
+
export function getCitationNumber(citation) {
|
|
69
|
+
return citation.citationNumber?.toString() || "1";
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Gets the keySpan text from a citation.
|
|
73
|
+
*/
|
|
74
|
+
export function getCitationKeySpanText(citation) {
|
|
76
75
|
return citation.keySpan?.toString() || "";
|
|
77
76
|
}
|
|
78
77
|
/**
|
package/package.json
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepcitation/deepcitation-js",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.27",
|
|
4
4
|
"description": "DeepCitation JavaScript SDK for deterministic AI citation verification",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"author": "DeepCitation <opensource@deepcitation.com>",
|
|
9
|
+
"homepage": "https://deepcitation.com",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/deepcitation/deepcitation-js/issues"
|
|
12
|
+
},
|
|
9
13
|
"repository": {
|
|
10
14
|
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/deepcitation/deepcitation-js.git"
|
|
12
|
-
"directory": "packages/deepcitation"
|
|
15
|
+
"url": "git+https://github.com/deepcitation/deepcitation-js.git"
|
|
13
16
|
},
|
|
14
17
|
"main": "./lib/index.js",
|
|
15
18
|
"types": "./lib/index.d.ts",
|
|
@@ -76,10 +79,24 @@
|
|
|
76
79
|
"import": "./lib/index.js",
|
|
77
80
|
"require": "./lib/index.js"
|
|
78
81
|
},
|
|
82
|
+
"./client": {
|
|
83
|
+
"types": "./lib/client/index.d.ts",
|
|
84
|
+
"import": "./lib/client/index.js",
|
|
85
|
+
"require": "./lib/client/index.js"
|
|
86
|
+
},
|
|
87
|
+
"./prompts": {
|
|
88
|
+
"types": "./lib/prompts/index.d.ts",
|
|
89
|
+
"import": "./lib/prompts/index.js",
|
|
90
|
+
"require": "./lib/prompts/index.js"
|
|
91
|
+
},
|
|
79
92
|
"./react": {
|
|
80
93
|
"types": "./lib/react/index.d.ts",
|
|
81
94
|
"import": "./lib/react/index.js",
|
|
82
95
|
"require": "./lib/react/index.js"
|
|
96
|
+
},
|
|
97
|
+
"./types": {
|
|
98
|
+
"types": "./lib/types/index.d.ts",
|
|
99
|
+
"import": "./lib/types/index.js"
|
|
83
100
|
}
|
|
84
101
|
},
|
|
85
102
|
"keywords": [
|