@deepcitation/deepcitation-js 1.1.27 → 1.1.29

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.
Files changed (82) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +253 -253
  3. package/lib/chunk-2IZXUOQR.js +66 -0
  4. package/lib/chunk-3GR7VKUJ.cjs +1 -0
  5. package/lib/chunk-4FGOHQFP.cjs +66 -0
  6. package/lib/chunk-CFXDRAJL.cjs +1 -0
  7. package/lib/chunk-F2MMVEVC.cjs +1 -0
  8. package/lib/chunk-LSKISWWH.cjs +2 -0
  9. package/lib/chunk-O2XFH626.js +1 -0
  10. package/lib/chunk-QGXCOW3E.js +1 -0
  11. package/lib/chunk-RCHWBA6D.js +2 -0
  12. package/lib/chunk-RQPZSRID.js +1 -0
  13. package/lib/client/index.cjs +1 -0
  14. package/lib/client/{DeepCitation.d.ts → index.d.cts} +159 -3
  15. package/lib/client/index.d.ts +342 -2
  16. package/lib/client/index.js +1 -1
  17. package/lib/index.cjs +1 -0
  18. package/lib/index.d.cts +105 -0
  19. package/lib/index.d.ts +103 -21
  20. package/lib/index.js +1 -20
  21. package/lib/prompts/index.cjs +1 -0
  22. package/lib/prompts/index.d.cts +196 -0
  23. package/lib/prompts/index.d.ts +196 -3
  24. package/lib/prompts/index.js +1 -3
  25. package/lib/react/index.cjs +4 -0
  26. package/lib/react/{types.d.ts → index.d.cts} +173 -22
  27. package/lib/react/index.d.ts +461 -12
  28. package/lib/react/index.js +4 -20
  29. package/lib/types/index.cjs +1 -0
  30. package/lib/types/index.d.cts +96 -0
  31. package/lib/types/index.d.ts +96 -11
  32. package/lib/types/index.js +1 -7
  33. package/lib/utils-CSqRI6NU.d.cts +45 -0
  34. package/lib/{react/utils.d.ts → utils-D_wxy_ni.d.ts} +13 -12
  35. package/package.json +46 -11
  36. package/lib/client/DeepCitation.js +0 -374
  37. package/lib/client/types.d.ts +0 -154
  38. package/lib/client/types.js +0 -1
  39. package/lib/parsing/normalizeCitation.d.ts +0 -5
  40. package/lib/parsing/normalizeCitation.js +0 -198
  41. package/lib/parsing/parseCitation.d.ts +0 -79
  42. package/lib/parsing/parseCitation.js +0 -431
  43. package/lib/parsing/parseWorkAround.d.ts +0 -2
  44. package/lib/parsing/parseWorkAround.js +0 -73
  45. package/lib/prompts/citationPrompts.d.ts +0 -138
  46. package/lib/prompts/citationPrompts.js +0 -168
  47. package/lib/prompts/promptCompression.d.ts +0 -14
  48. package/lib/prompts/promptCompression.js +0 -127
  49. package/lib/prompts/types.d.ts +0 -4
  50. package/lib/prompts/types.js +0 -1
  51. package/lib/react/CitationComponent.d.ts +0 -106
  52. package/lib/react/CitationComponent.js +0 -419
  53. package/lib/react/CitationVariants.d.ts +0 -132
  54. package/lib/react/CitationVariants.js +0 -277
  55. package/lib/react/DiffDisplay.d.ts +0 -10
  56. package/lib/react/DiffDisplay.js +0 -33
  57. package/lib/react/Popover.d.ts +0 -15
  58. package/lib/react/Popover.js +0 -20
  59. package/lib/react/UrlCitationComponent.d.ts +0 -83
  60. package/lib/react/UrlCitationComponent.js +0 -224
  61. package/lib/react/VerificationTabs.d.ts +0 -10
  62. package/lib/react/VerificationTabs.js +0 -36
  63. package/lib/react/icons.d.ts +0 -22
  64. package/lib/react/icons.js +0 -16
  65. package/lib/react/primitives.d.ts +0 -99
  66. package/lib/react/primitives.js +0 -187
  67. package/lib/react/types.js +0 -1
  68. package/lib/react/useSmartDiff.d.ts +0 -16
  69. package/lib/react/useSmartDiff.js +0 -64
  70. package/lib/react/utils.js +0 -88
  71. package/lib/types/boxes.d.ts +0 -11
  72. package/lib/types/boxes.js +0 -1
  73. package/lib/types/citation.d.ts +0 -39
  74. package/lib/types/citation.js +0 -1
  75. package/lib/types/search.d.ts +0 -19
  76. package/lib/types/search.js +0 -1
  77. package/lib/types/verification.d.ts +0 -27
  78. package/lib/types/verification.js +0 -11
  79. package/lib/utils/diff.d.ts +0 -60
  80. package/lib/utils/diff.js +0 -414
  81. package/lib/utils/sha.d.ts +0 -10
  82. package/lib/utils/sha.js +0 -108
@@ -1,224 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { forwardRef, memo, useCallback, useMemo } from "react";
3
- import { classNames, generateCitationInstanceId, generateCitationKey } from "./utils.js";
4
- /**
5
- * Extracts domain from URL for compact display.
6
- */
7
- export function extractDomain(url) {
8
- try {
9
- const urlObj = new URL(url);
10
- return urlObj.hostname.replace(/^www\./, "");
11
- }
12
- catch {
13
- // Fallback for invalid URLs
14
- return url.replace(/^https?:\/\/(www\.)?/, "").split("/")[0];
15
- }
16
- }
17
- /**
18
- * Truncates a string to max length with ellipsis.
19
- */
20
- function truncateString(str, maxLength) {
21
- if (str.length <= maxLength)
22
- return str;
23
- return str.slice(0, maxLength - 1) + "…";
24
- }
25
- /**
26
- * Get path from URL for display.
27
- */
28
- function getUrlPath(url) {
29
- try {
30
- const urlObj = new URL(url);
31
- const path = urlObj.pathname + urlObj.search;
32
- return path === "/" ? "" : path;
33
- }
34
- catch {
35
- return "";
36
- }
37
- }
38
- /**
39
- * Status indicator icons for URL fetch states.
40
- */
41
- const STATUS_ICONS = {
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
- };
56
- /**
57
- * Checks if status is a blocked status.
58
- */
59
- export function isBlockedStatus(status) {
60
- return status.startsWith("blocked_");
61
- }
62
- /**
63
- * Checks if status is an error status.
64
- */
65
- export function isErrorStatus(status) {
66
- return status.startsWith("error_");
67
- }
68
- /**
69
- * Checks if URL was successfully verified.
70
- */
71
- export function isVerifiedStatus(status) {
72
- return status === "verified" || status === "partial";
73
- }
74
- /**
75
- * Default blocked indicator component.
76
- */
77
- const DefaultBlockedIndicator = ({ status, errorMessage }) => {
78
- const statusInfo = STATUS_ICONS[status];
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
- };
81
- /**
82
- * Default favicon component.
83
- */
84
- const DefaultFavicon = ({ url, faviconUrl }) => {
85
- const domain = extractDomain(url);
86
- const src = faviconUrl || `https://www.google.com/s2/favicons?domain=${domain}&sz=16`;
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
- // Hide broken favicon images
89
- e.target.style.display = "none";
90
- } }));
91
- };
92
- /**
93
- * URL Citation Component
94
- *
95
- * Displays a URL citation with compact domain display,
96
- * verification status, and blocked/error indicators.
97
- *
98
- * @example
99
- * ```tsx
100
- * <UrlCitationComponent
101
- * urlMeta={{
102
- * url: "https://example.com/article",
103
- * fetchStatus: "verified",
104
- * }}
105
- * />
106
- * // Renders: [example.com ✓]
107
- *
108
- * <UrlCitationComponent
109
- * urlMeta={{
110
- * url: "https://protected-site.com/page",
111
- * fetchStatus: "blocked_login",
112
- * }}
113
- * />
114
- * // Renders: [protected-site.com 🔒]
115
- * ```
116
- */
117
- export const UrlCitationComponent = forwardRef(({ urlMeta, citation: providedCitation, children, className, variant = "chip", // Default to chip for URLs
118
- showFullUrlOnHover = true, showFavicon = true, showTitle = false, maxDisplayLength = 30, renderBlockedIndicator, onUrlClick, eventHandlers, preventTooltips = false, }, ref) => {
119
- const { url, domain: providedDomain, title, fetchStatus, faviconUrl, errorMessage } = urlMeta;
120
- // Derive citation from URL meta if not provided
121
- const citation = useMemo(() => providedCitation || {
122
- value: url,
123
- fullPhrase: title || url,
124
- }, [providedCitation, url, title]);
125
- const citationKey = useMemo(() => generateCitationKey(citation), [citation]);
126
- const citationInstanceId = useMemo(() => generateCitationInstanceId(citationKey), [citationKey]);
127
- // Compute display text
128
- const domain = useMemo(() => providedDomain || extractDomain(url), [providedDomain, url]);
129
- const path = useMemo(() => getUrlPath(url), [url]);
130
- const displayText = useMemo(() => {
131
- if (showTitle && title) {
132
- return truncateString(title, maxDisplayLength);
133
- }
134
- // Show domain + truncated path
135
- const pathPart = path ? truncateString(path, maxDisplayLength - domain.length - 1) : "";
136
- return pathPart ? `${domain}${pathPart}` : domain;
137
- }, [showTitle, title, domain, path, maxDisplayLength]);
138
- const statusInfo = STATUS_ICONS[fetchStatus];
139
- const isBlocked = isBlockedStatus(fetchStatus);
140
- const isError = isErrorStatus(fetchStatus);
141
- const isVerified = fetchStatus === "verified";
142
- const isPartial = fetchStatus === "partial";
143
- const isPending = fetchStatus === "pending";
144
- const handleClick = useCallback((e) => {
145
- e.preventDefault();
146
- e.stopPropagation();
147
- if (onUrlClick) {
148
- onUrlClick(url, e);
149
- }
150
- else {
151
- // Default: open URL in new tab
152
- window.open(url, "_blank", "noopener,noreferrer");
153
- }
154
- eventHandlers?.onClick?.(citation, citationKey, e);
155
- }, [onUrlClick, url, eventHandlers, citation, citationKey]);
156
- const handleMouseEnter = useCallback(() => {
157
- eventHandlers?.onMouseEnter?.(citation, citationKey);
158
- }, [eventHandlers, citation, citationKey]);
159
- const handleMouseLeave = useCallback(() => {
160
- eventHandlers?.onMouseLeave?.(citation, citationKey);
161
- }, [eventHandlers, citation, citationKey]);
162
- const renderStatusIndicator = () => {
163
- if (isBlocked || isError) {
164
- if (renderBlockedIndicator) {
165
- return renderBlockedIndicator(fetchStatus, errorMessage);
166
- }
167
- return _jsx(DefaultBlockedIndicator, { status: fetchStatus, errorMessage: errorMessage });
168
- }
169
- if (isVerified) {
170
- return (_jsx("span", { className: "text-[0.85em] text-green-600 dark:text-green-500", "aria-hidden": "true", title: "Verified", children: "\u2713" }));
171
- }
172
- if (isPartial) {
173
- return (_jsx("span", { className: "text-[0.85em] text-amber-600 dark:text-amber-500", "aria-hidden": "true", title: "Partial match", children: "~" }));
174
- }
175
- if (isPending) {
176
- return (_jsx("span", { className: "opacity-70", "aria-hidden": "true", children: "\u2026" }));
177
- }
178
- return null;
179
- };
180
- // Choose variant-specific rendering
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, "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
- }
184
- // Inline variant
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, "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
- e.preventDefault();
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", { children: displayText }), renderStatusIndicator()] })] }));
190
- }
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, "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
- });
194
- UrlCitationComponent.displayName = "UrlCitationComponent";
195
- /**
196
- * Memoized version for performance.
197
- */
198
- export const MemoizedUrlCitationComponent = memo(UrlCitationComponent);
199
- /**
200
- * Hook to parse URL and create UrlCitationMeta.
201
- */
202
- export function useUrlMeta(url, fetchStatus = "unknown", additionalMeta) {
203
- return useMemo(() => ({
204
- url,
205
- domain: extractDomain(url),
206
- fetchStatus,
207
- ...additionalMeta,
208
- }), [url, fetchStatus, additionalMeta]);
209
- }
210
- /**
211
- * Compact URL display utilities.
212
- */
213
- export const urlDisplayUtils = {
214
- extractDomain,
215
- truncateString,
216
- getUrlPath,
217
- isBlockedStatus,
218
- isErrorStatus,
219
- isVerifiedStatus,
220
- };
221
- /**
222
- * Status configuration for custom styling.
223
- */
224
- export { STATUS_ICONS };
@@ -1,10 +0,0 @@
1
- import React from "react";
2
- interface VerificationTabsProps {
3
- expected: string;
4
- actual: string;
5
- label?: string;
6
- renderCopyButton?: (text: string, position: "expected" | "found") => React.ReactNode;
7
- emptyText?: string;
8
- }
9
- export declare const VerificationTabs: React.FC<VerificationTabsProps>;
10
- export {};
@@ -1,36 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useState } from "react";
3
- import { useSmartDiff } from "./useSmartDiff.js";
4
- import { classNames } from "./utils.js";
5
- import { CheckIcon } from "./icons.js";
6
- // Sub-component: The individual tab button
7
- const TabButton = ({ isActive, onClick, label }) => (_jsx("button", { onClick: e => {
8
- e.stopPropagation(); // Prevent tooltip from closing or dragging
9
- onClick();
10
- }, className: classNames("dc-tab-button", isActive ? "dc-tab-button--active" : ""), type: "button", children: label }));
11
- export const VerificationTabs = ({ expected, actual, label, renderCopyButton, emptyText = "No text found", }) => {
12
- const { diffResult, isHighVariance, hasDiff } = useSmartDiff(expected, actual);
13
- const [activeTab, setActiveTab] = useState("diff");
14
- useEffect(() => {
15
- if (isHighVariance) {
16
- setActiveTab("found");
17
- }
18
- else {
19
- setActiveTab("diff");
20
- }
21
- }, [isHighVariance, expected, actual]);
22
- const renderFoundContent = () => (_jsx("div", { className: "dc-tab-content dc-tab-content--found", children: actual ? (_jsxs("div", { className: "dc-tab-text-wrapper", children: [renderCopyButton && _jsx("div", { className: "dc-copy-button-wrapper", children: renderCopyButton(actual, "found") }), _jsx("div", { className: "dc-tab-text", children: actual })] })) : (_jsx("span", { className: "dc-tab-empty", children: emptyText })) }));
23
- const isExactMatch = !hasDiff && Boolean(actual) && Boolean(expected);
24
- if (isExactMatch) {
25
- return (_jsxs("div", { className: "dc-verification-tabs dc-verification-tabs--exact", children: [label && _jsx("div", { className: "dc-verification-label", children: label }), _jsxs("div", { className: "dc-exact-match-badge", children: [_jsx(CheckIcon, {}), _jsx("span", { children: "Exact match" })] }), _jsx("div", { className: "dc-exact-match-content", children: renderFoundContent() })] }));
26
- }
27
- return (_jsxs("div", { className: "dc-verification-tabs", children: [label && _jsx("div", { className: "dc-verification-label", children: label }), _jsx("div", { className: "dc-tabs-container", children: _jsxs("div", { className: "dc-tabs-nav", children: [_jsx(TabButton, { label: "Expected", isActive: activeTab === "expected", onClick: () => setActiveTab("expected") }), _jsx(TabButton, { label: "Diff", isActive: activeTab === "diff", onClick: () => setActiveTab("diff") }), _jsx(TabButton, { label: "Found", isActive: activeTab === "found", onClick: () => setActiveTab("found") })] }) }), _jsxs("div", { className: "dc-tabs-content", children: [activeTab === "found" && renderFoundContent(), activeTab === "expected" && (_jsx("div", { className: "dc-tab-content dc-tab-content--expected", children: _jsxs("div", { className: "dc-tab-text-wrapper", children: [renderCopyButton && (_jsx("div", { className: "dc-copy-button-wrapper", children: renderCopyButton(expected, "expected") })), _jsx("div", { className: "dc-tab-text", children: expected })] }) })), activeTab === "diff" && (_jsx("div", { className: "dc-tab-content dc-tab-content--diff", children: !hasDiff ? (_jsxs("div", { className: "dc-exact-match-indicator", children: [_jsx(CheckIcon, {}), _jsx("span", { children: "Exact Match" })] })) : (_jsx("div", { className: "dc-diff-result", children: diffResult.map((block, i) => (_jsx("div", { className: classNames("dc-diff-block", block.type === "added" ? "dc-diff-block--added" : "", block.type === "removed" ? "dc-diff-block--removed" : ""), children: block.parts.map((part, j) => {
28
- if (part.removed) {
29
- return (_jsx("span", { className: "dc-diff-part dc-diff-part--removed", title: "Expected but not found", children: part.value }, j));
30
- }
31
- if (part.added) {
32
- return (_jsx("span", { className: "dc-diff-part dc-diff-part--added", title: "Actually found in source", children: part.value }, j));
33
- }
34
- return (_jsx("span", { className: "dc-diff-part dc-diff-part--unchanged", children: part.value }, j));
35
- }) }, i))) })) }))] })] }));
36
- };
@@ -1,22 +0,0 @@
1
- /**
2
- * DeepCitation icon SVG (no dependencies)
3
- */
4
- export declare const DeepCitationIcon: ({ className }: {
5
- className?: string;
6
- }) => import("react/jsx-runtime").JSX.Element;
7
- /**
8
- * Check icon SVG (no dependencies)
9
- */
10
- export declare const CheckIcon: ({ className }: {
11
- className?: string;
12
- }) => import("react/jsx-runtime").JSX.Element;
13
- /**
14
- * Warning icon SVG (no dependencies)
15
- */
16
- export declare const WarningIcon: ({ className }: {
17
- className?: string;
18
- }) => import("react/jsx-runtime").JSX.Element;
19
- /** Spinner component for loading/pending state */
20
- export declare const SpinnerIcon: ({ className }: {
21
- className?: string;
22
- }) => import("react/jsx-runtime").JSX.Element;
@@ -1,16 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { cn } from "./utils.js";
3
- /**
4
- * DeepCitation icon SVG (no dependencies)
5
- */
6
- export const DeepCitationIcon = ({ className }) => (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "square", shapeRendering: "crispEdges", className: className, children: [_jsx("path", { d: "M7 3 L3 3 L3 21 L7 21" }), _jsx("path", { d: "M17 3 L21 3 L21 21 L17 21" })] }));
7
- /**
8
- * Check icon SVG (no dependencies)
9
- */
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
- /**
12
- * Warning icon SVG (no dependencies)
13
- */
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
- /** Spinner component for loading/pending state */
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" })] }));
@@ -1,99 +0,0 @@
1
- /**
2
- * Citation Primitives - Composable building blocks for citation components
3
- * @packageDocumentation
4
- */
5
- import React, { type ReactNode, type HTMLAttributes, type MouseEvent, type TouchEvent } from "react";
6
- import type { Citation as CitationType, CitationStatus } from "../types/citation.js";
7
- import type { Verification } from "../types/verification.js";
8
- interface CitationContextValue {
9
- citation: CitationType;
10
- citationKey: string;
11
- citationInstanceId: string;
12
- status: CitationStatus;
13
- verification: Verification | null;
14
- config: {
15
- fallbackDisplay: string | null;
16
- pendingContent: ReactNode;
17
- };
18
- }
19
- /** Access citation context. Must be used within Citation.Root. */
20
- export declare function useCitationContext(): CitationContextValue;
21
- /** Safely access citation context (returns null if not in context). */
22
- export declare function useCitationContextSafe(): CitationContextValue | null;
23
- export interface CitationRootProps {
24
- citation: CitationType;
25
- verification?: Verification | null;
26
- children: ReactNode;
27
- fallbackDisplay?: string | null;
28
- pendingContent?: ReactNode;
29
- }
30
- /** Root component that provides citation context to all child primitives. */
31
- export declare const CitationRoot: React.ForwardRefExoticComponent<CitationRootProps & React.HTMLAttributes<HTMLSpanElement> & React.RefAttributes<HTMLSpanElement>>;
32
- export interface CitationTriggerProps extends HTMLAttributes<HTMLSpanElement> {
33
- onCitationClick?: (citation: CitationType, citationKey: string, event: MouseEvent) => void;
34
- onCitationMouseEnter?: (citation: CitationType, citationKey: string) => void;
35
- onCitationMouseLeave?: (citation: CitationType, citationKey: string) => void;
36
- onCitationTouchEnd?: (citation: CitationType, citationKey: string, event: TouchEvent) => void;
37
- isMobile?: boolean;
38
- disableHover?: boolean;
39
- }
40
- /** Interactive trigger component for the citation. */
41
- export declare const CitationTrigger: React.ForwardRefExoticComponent<CitationTriggerProps & React.RefAttributes<HTMLSpanElement>>;
42
- export interface CitationBracketProps extends HTMLAttributes<HTMLSpanElement> {
43
- open?: string;
44
- close?: string;
45
- }
46
- /** Bracket wrapper component for citation content. */
47
- export declare const CitationBracket: React.ForwardRefExoticComponent<CitationBracketProps & React.RefAttributes<HTMLSpanElement>>;
48
- export interface CitationNumberProps extends HTMLAttributes<HTMLSpanElement> {
49
- number?: string | number;
50
- }
51
- /** Displays the citation number. */
52
- export declare const CitationNumber: React.ForwardRefExoticComponent<CitationNumberProps & React.RefAttributes<HTMLSpanElement>>;
53
- export interface CitationKeySpanProps extends HTMLAttributes<HTMLSpanElement> {
54
- keySpan?: string;
55
- separator?: string;
56
- }
57
- /** Displays the citation keySpan (summary text). */
58
- export declare const CitationKeySpan: React.ForwardRefExoticComponent<CitationKeySpanProps & React.RefAttributes<HTMLSpanElement>>;
59
- export interface CitationIndicatorProps extends HTMLAttributes<HTMLSpanElement> {
60
- verifiedIndicator?: ReactNode;
61
- partialIndicator?: ReactNode;
62
- missIndicator?: ReactNode;
63
- pendingIndicator?: ReactNode;
64
- showFor?: Array<"verified" | "partial" | "miss" | "pending">;
65
- }
66
- /** Displays a status indicator based on citation verification state. */
67
- export declare const CitationIndicator: React.ForwardRefExoticComponent<CitationIndicatorProps & React.RefAttributes<HTMLSpanElement>>;
68
- export interface CitationStatusProps {
69
- children: (status: CitationStatus) => ReactNode;
70
- }
71
- /** Render prop component for accessing citation status. */
72
- export declare function CitationStatusComponent({ children }: CitationStatusProps): import("react/jsx-runtime").JSX.Element;
73
- export declare namespace CitationStatusComponent {
74
- var displayName: string;
75
- }
76
- export interface CitationPhraseProps extends HTMLAttributes<HTMLSpanElement> {
77
- maxLength?: number;
78
- truncationSuffix?: string;
79
- }
80
- /** Displays the citation's full phrase with optional truncation. */
81
- export declare const CitationPhrase: React.ForwardRefExoticComponent<CitationPhraseProps & React.RefAttributes<HTMLSpanElement>>;
82
- export interface CitationPageProps extends HTMLAttributes<HTMLSpanElement> {
83
- prefix?: string;
84
- }
85
- /** Displays the citation's page number. */
86
- export declare const CitationPage: React.ForwardRefExoticComponent<CitationPageProps & React.RefAttributes<HTMLSpanElement>>;
87
- /** Citation primitives namespace for composable citation components. */
88
- export declare const Citation: {
89
- readonly Root: React.ForwardRefExoticComponent<CitationRootProps & React.HTMLAttributes<HTMLSpanElement> & React.RefAttributes<HTMLSpanElement>>;
90
- readonly Trigger: React.ForwardRefExoticComponent<CitationTriggerProps & React.RefAttributes<HTMLSpanElement>>;
91
- readonly Bracket: React.ForwardRefExoticComponent<CitationBracketProps & React.RefAttributes<HTMLSpanElement>>;
92
- readonly Number: React.ForwardRefExoticComponent<CitationNumberProps & React.RefAttributes<HTMLSpanElement>>;
93
- readonly KeySpan: React.ForwardRefExoticComponent<CitationKeySpanProps & React.RefAttributes<HTMLSpanElement>>;
94
- readonly Indicator: React.ForwardRefExoticComponent<CitationIndicatorProps & React.RefAttributes<HTMLSpanElement>>;
95
- readonly Status: typeof CitationStatusComponent;
96
- readonly Phrase: React.ForwardRefExoticComponent<CitationPhraseProps & React.RefAttributes<HTMLSpanElement>>;
97
- readonly Page: React.ForwardRefExoticComponent<CitationPageProps & React.RefAttributes<HTMLSpanElement>>;
98
- };
99
- export {};
@@ -1,187 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- /**
3
- * Citation Primitives - Composable building blocks for citation components
4
- * @packageDocumentation
5
- */
6
- import { createContext, useContext, useMemo, useCallback, forwardRef, } from "react";
7
- import { getCitationStatus } from "../parsing/parseCitation.js";
8
- import { generateCitationKey, generateCitationInstanceId, classNames, } from "./utils.js";
9
- const CitationContext = createContext(null);
10
- /** Access citation context. Must be used within Citation.Root. */
11
- export function useCitationContext() {
12
- const context = useContext(CitationContext);
13
- if (!context) {
14
- throw new Error("Citation components must be used within a Citation.Root");
15
- }
16
- return context;
17
- }
18
- /** Safely access citation context (returns null if not in context). */
19
- export function useCitationContextSafe() {
20
- return useContext(CitationContext);
21
- }
22
- /** Root component that provides citation context to all child primitives. */
23
- export const CitationRoot = forwardRef(({ citation, verification = null, children, fallbackDisplay = null, pendingContent = "..", className, ...props }, ref) => {
24
- const citationKey = useMemo(() => generateCitationKey(citation), [citation]);
25
- const citationInstanceId = useMemo(() => generateCitationInstanceId(citationKey), [citationKey]);
26
- const status = getCitationStatus(verification);
27
- const contextValue = useMemo(() => ({
28
- citation,
29
- citationKey,
30
- citationInstanceId,
31
- status,
32
- verification,
33
- config: {
34
- fallbackDisplay,
35
- pendingContent,
36
- },
37
- }), [
38
- citation,
39
- citationKey,
40
- citationInstanceId,
41
- status,
42
- verification,
43
- fallbackDisplay,
44
- pendingContent,
45
- ]);
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 }) }));
47
- });
48
- CitationRoot.displayName = "Citation.Root";
49
- /** Interactive trigger component for the citation. */
50
- export const CitationTrigger = forwardRef(({ children, className, onCitationClick, onCitationMouseEnter, onCitationMouseLeave, onCitationTouchEnd, isMobile = false, disableHover = false, onClick, onMouseEnter, onMouseLeave, onMouseDown, onTouchEnd, ...props }, ref) => {
51
- const { citation, citationKey, status } = useCitationContext();
52
- const handleClick = useCallback((e) => {
53
- e.stopPropagation();
54
- onClick?.(e);
55
- }, [onClick]);
56
- const handleMouseDown = useCallback((e) => {
57
- e.preventDefault();
58
- e.stopPropagation();
59
- onMouseDown?.(e);
60
- onCitationClick?.(citation, citationKey, e);
61
- }, [onMouseDown, onCitationClick, citation, citationKey]);
62
- const handleMouseEnter = useCallback((e) => {
63
- onMouseEnter?.(e);
64
- if (!disableHover) {
65
- onCitationMouseEnter?.(citation, citationKey);
66
- }
67
- }, [onMouseEnter, disableHover, onCitationMouseEnter, citation, citationKey]);
68
- const handleMouseLeave = useCallback((e) => {
69
- onMouseLeave?.(e);
70
- if (!disableHover) {
71
- onCitationMouseLeave?.(citation, citationKey);
72
- }
73
- }, [onMouseLeave, disableHover, onCitationMouseLeave, citation, citationKey]);
74
- const handleTouchEnd = useCallback((e) => {
75
- onTouchEnd?.(e);
76
- if (isMobile) {
77
- e.preventDefault();
78
- e.stopPropagation();
79
- onCitationTouchEnd?.(citation, citationKey, e);
80
- }
81
- }, [onTouchEnd, isMobile, onCitationTouchEnd, citation, citationKey]);
82
- const statusClasses = classNames(status.isVerified &&
83
- !status.isPartialMatch &&
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 }));
86
- });
87
- CitationTrigger.displayName = "Citation.Trigger";
88
- /** Bracket wrapper component for citation content. */
89
- export const CitationBracket = forwardRef(({ children, className, open = "[", close = "]", ...props }, ref) => {
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 })] }));
91
- });
92
- CitationBracket.displayName = "Citation.Bracket";
93
- /** Displays the citation number. */
94
- export const CitationNumber = forwardRef(({ className, number, ...props }, ref) => {
95
- const { citation, config, status } = useCitationContext();
96
- const displayNumber = useMemo(() => {
97
- if (number !== undefined)
98
- return String(number);
99
- return (citation.keySpan?.toString() ||
100
- citation.citationNumber?.toString() ||
101
- config.fallbackDisplay ||
102
- "1");
103
- }, [number, citation, config]);
104
- if (status.isPending) {
105
- return (_jsx("span", { ref: ref, className: classNames("font-medium opacity-60", className), ...props, children: config.pendingContent }));
106
- }
107
- return (_jsx("span", { ref: ref, className: classNames("font-medium", className), ...props, children: displayNumber }));
108
- });
109
- CitationNumber.displayName = "Citation.Number";
110
- /** Displays the citation keySpan (summary text). */
111
- export const CitationKeySpan = forwardRef(({ className, keySpan, separator = " ", ...props }, ref) => {
112
- const { citation } = useCitationContext();
113
- const displayKeySpan = useMemo(() => {
114
- if (keySpan !== undefined)
115
- return keySpan;
116
- return citation.keySpan?.toString() || "";
117
- }, [keySpan, citation]);
118
- if (!displayKeySpan)
119
- return null;
120
- return (_jsxs("span", { ref: ref, className: classNames("italic", className), ...props, children: [displayKeySpan, separator] }));
121
- });
122
- CitationKeySpan.displayName = "Citation.KeySpan";
123
- /** Displays a status indicator based on citation verification state. */
124
- export const CitationIndicator = forwardRef(({ className, verifiedIndicator = "✓", partialIndicator = "*", missIndicator = null, pendingIndicator = null, showFor, ...props }, ref) => {
125
- const { status } = useCitationContext();
126
- const shouldShow = useCallback((state) => {
127
- if (!showFor)
128
- return true;
129
- return showFor.includes(state);
130
- }, [showFor]);
131
- const baseClasses = "inline ml-0.5 text-[0.85em]";
132
- if (status.isPartialMatch && shouldShow("partial")) {
133
- return (_jsx("span", { ref: ref, className: classNames(baseClasses, "text-amber-600 dark:text-amber-500", className), "aria-label": "Partial match", ...props, children: partialIndicator }));
134
- }
135
- if (status.isVerified && !status.isPartialMatch && shouldShow("verified")) {
136
- return (_jsx("span", { ref: ref, className: classNames(baseClasses, "text-green-600 dark:text-green-500", className), "aria-label": "Verified", ...props, children: verifiedIndicator }));
137
- }
138
- if (status.isMiss && shouldShow("miss") && missIndicator) {
139
- return (_jsx("span", { ref: ref, className: classNames(baseClasses, "text-red-500 dark:text-red-400", className), "aria-label": "Not found", ...props, children: missIndicator }));
140
- }
141
- if (status.isPending && shouldShow("pending") && pendingIndicator) {
142
- return (_jsx("span", { ref: ref, className: classNames(baseClasses, "text-gray-400 dark:text-gray-500", className), "aria-label": "Pending", ...props, children: pendingIndicator }));
143
- }
144
- return null;
145
- });
146
- CitationIndicator.displayName = "Citation.Indicator";
147
- /** Render prop component for accessing citation status. */
148
- export function CitationStatusComponent({ children }) {
149
- const { status } = useCitationContext();
150
- return _jsx(_Fragment, { children: children(status) });
151
- }
152
- CitationStatusComponent.displayName = "Citation.Status";
153
- /** Displays the citation's full phrase with optional truncation. */
154
- export const CitationPhrase = forwardRef(({ className, maxLength, truncationSuffix = "...", ...props }, ref) => {
155
- const { citation } = useCitationContext();
156
- const displayPhrase = useMemo(() => {
157
- const phrase = citation.fullPhrase || "";
158
- if (!maxLength || phrase.length <= maxLength)
159
- return phrase;
160
- return phrase.slice(0, maxLength) + truncationSuffix;
161
- }, [citation.fullPhrase, maxLength, truncationSuffix]);
162
- if (!displayPhrase)
163
- return null;
164
- return (_jsx("span", { ref: ref, className: classNames("italic", className), ...props, children: displayPhrase }));
165
- });
166
- CitationPhrase.displayName = "Citation.Phrase";
167
- /** Displays the citation's page number. */
168
- export const CitationPage = forwardRef(({ className, prefix = "", ...props }, ref) => {
169
- const { citation } = useCitationContext();
170
- if (citation.pageNumber === undefined || citation.pageNumber === null) {
171
- return null;
172
- }
173
- return (_jsxs("span", { ref: ref, className: classNames("text-xs text-gray-400 dark:text-gray-500", className), ...props, children: [prefix, citation.pageNumber] }));
174
- });
175
- CitationPage.displayName = "Citation.Page";
176
- /** Citation primitives namespace for composable citation components. */
177
- export const Citation = {
178
- Root: CitationRoot,
179
- Trigger: CitationTrigger,
180
- Bracket: CitationBracket,
181
- Number: CitationNumber,
182
- KeySpan: CitationKeySpan,
183
- Indicator: CitationIndicator,
184
- Status: CitationStatusComponent,
185
- Phrase: CitationPhrase,
186
- Page: CitationPage,
187
- };
@@ -1 +0,0 @@
1
- export {};
@@ -1,16 +0,0 @@
1
- export type DiffBlockType = "modified" | "added" | "removed" | "unchanged";
2
- export interface DiffPart {
3
- value: string;
4
- added?: boolean;
5
- removed?: boolean;
6
- }
7
- export interface DiffBlock {
8
- type: DiffBlockType;
9
- parts: DiffPart[];
10
- }
11
- export declare const useSmartDiff: (expected?: string, actual?: string) => {
12
- diffResult: DiffBlock[];
13
- hasDiff: boolean;
14
- similarity: number;
15
- isHighVariance: boolean;
16
- };