@deepcitation/deepcitation-js 1.1.13 → 1.1.15
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { type ReactNode } from "react";
|
|
2
2
|
import { type CitationStatus } from "../types/citation.js";
|
|
3
3
|
import type { Verification } from "../types/verification.js";
|
|
4
|
-
import type { BaseCitationProps, CitationEventHandlers, CitationRenderProps, CitationVariant } from "./types.js";
|
|
4
|
+
import type { BaseCitationProps, CitationBehaviorConfig, CitationEventHandlers, CitationRenderProps, CitationVariant } from "./types.js";
|
|
5
5
|
import "./styles.css";
|
|
6
6
|
export type { CitationVariant } from "./types.js";
|
|
7
7
|
/**
|
|
@@ -74,6 +74,30 @@ export type { CitationVariant } from "./types.js";
|
|
|
74
74
|
* popoverPosition="hidden"
|
|
75
75
|
* />
|
|
76
76
|
* ```
|
|
77
|
+
*
|
|
78
|
+
* @example Custom click behavior (replaces default)
|
|
79
|
+
* ```tsx
|
|
80
|
+
* <CitationComponent
|
|
81
|
+
* citation={citation}
|
|
82
|
+
* verification={verificationResult}
|
|
83
|
+
* behaviorConfig={{
|
|
84
|
+
* onClick: (context, event) => {
|
|
85
|
+
* if (context.hasImage) {
|
|
86
|
+
* return { setImageExpanded: true };
|
|
87
|
+
* }
|
|
88
|
+
* }
|
|
89
|
+
* }}
|
|
90
|
+
* />
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @example Disable all click behavior
|
|
94
|
+
* ```tsx
|
|
95
|
+
* <CitationComponent
|
|
96
|
+
* citation={citation}
|
|
97
|
+
* verification={verificationResult}
|
|
98
|
+
* behaviorConfig={{ onClick: () => false }}
|
|
99
|
+
* />
|
|
100
|
+
* ```
|
|
77
101
|
*/
|
|
78
102
|
export interface CitationComponentProps extends BaseCitationProps {
|
|
79
103
|
/**
|
|
@@ -97,8 +121,22 @@ export interface CitationComponentProps extends BaseCitationProps {
|
|
|
97
121
|
displayBrackets?: boolean;
|
|
98
122
|
/**
|
|
99
123
|
* Event handlers for citation interactions.
|
|
124
|
+
* These are always called regardless of behaviorConfig settings.
|
|
100
125
|
*/
|
|
101
126
|
eventHandlers?: CitationEventHandlers;
|
|
127
|
+
/**
|
|
128
|
+
* Configuration for customizing default click/hover behaviors.
|
|
129
|
+
* Use this to disable or extend the built-in behaviors.
|
|
130
|
+
*
|
|
131
|
+
* Default behaviors:
|
|
132
|
+
* - Hover: Shows zoom-in cursor when popover is pinned and has image
|
|
133
|
+
* - Click 1: Pins the popover open (stays visible without hover)
|
|
134
|
+
* - Click 2: Opens full-size image overlay (if image available)
|
|
135
|
+
* - Click 3: Closes image and unpins popover
|
|
136
|
+
*
|
|
137
|
+
* @see CitationBehaviorConfig for all options
|
|
138
|
+
*/
|
|
139
|
+
behaviorConfig?: CitationBehaviorConfig;
|
|
102
140
|
/**
|
|
103
141
|
* Enable mobile touch handlers.
|
|
104
142
|
* @default false
|
|
@@ -198,7 +198,7 @@ const DefaultPopoverContent = ({ citation, verification, status, onImageClick, }
|
|
|
198
198
|
* This means partial matches have blue text (because they were found) but
|
|
199
199
|
* an orange indicator (because they didn't match exactly).
|
|
200
200
|
*/
|
|
201
|
-
export const CitationComponent = forwardRef(({ citation, children, className, displayKeySpan = true, displayBrackets = true, fallbackDisplay, verification, variant = "brackets", eventHandlers, isMobile = false, renderIndicator, renderContent, popoverPosition = "top", renderPopoverContent, }, ref) => {
|
|
201
|
+
export const CitationComponent = forwardRef(({ citation, children, className, displayKeySpan = true, displayBrackets = true, fallbackDisplay, verification, variant = "brackets", eventHandlers, behaviorConfig, isMobile = false, renderIndicator, renderContent, popoverPosition = "top", renderPopoverContent, }, ref) => {
|
|
202
202
|
const containerRef = useRef(null);
|
|
203
203
|
const wrapperRef = useRef(null);
|
|
204
204
|
const [expandedImageSrc, setExpandedImageSrc] = useState(null);
|
|
@@ -247,10 +247,52 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
|
|
|
247
247
|
}, [isTooltipExpanded]);
|
|
248
248
|
const citationKey = useMemo(() => generateCitationKey(citation), [citation]);
|
|
249
249
|
const citationInstanceId = useMemo(() => generateCitationInstanceId(citationKey), [citationKey]);
|
|
250
|
+
// Create behavior context for custom handlers
|
|
251
|
+
const getBehaviorContext = useCallback(() => ({
|
|
252
|
+
citation,
|
|
253
|
+
citationKey,
|
|
254
|
+
verification: verification ?? null,
|
|
255
|
+
isTooltipExpanded,
|
|
256
|
+
isImageExpanded: !!expandedImageSrc,
|
|
257
|
+
hasImage: !!verification?.verificationImageBase64,
|
|
258
|
+
}), [citation, citationKey, verification, isTooltipExpanded, expandedImageSrc]);
|
|
259
|
+
// Apply behavior actions from custom handler
|
|
260
|
+
const applyBehaviorActions = useCallback((actions) => {
|
|
261
|
+
if (actions.setTooltipExpanded !== undefined) {
|
|
262
|
+
setIsTooltipExpanded(actions.setTooltipExpanded);
|
|
263
|
+
}
|
|
264
|
+
if (actions.setImageExpanded !== undefined) {
|
|
265
|
+
if (typeof actions.setImageExpanded === "string") {
|
|
266
|
+
setExpandedImageSrc(actions.setImageExpanded);
|
|
267
|
+
}
|
|
268
|
+
else if (actions.setImageExpanded === true && verification?.verificationImageBase64) {
|
|
269
|
+
setExpandedImageSrc(verification.verificationImageBase64);
|
|
270
|
+
}
|
|
271
|
+
else if (actions.setImageExpanded === false) {
|
|
272
|
+
setExpandedImageSrc(null);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (actions.setPhrasesExpanded !== undefined) {
|
|
276
|
+
setIsPhrasesExpanded(actions.setPhrasesExpanded);
|
|
277
|
+
}
|
|
278
|
+
}, [verification?.verificationImageBase64]);
|
|
250
279
|
const handleToggleTooltip = useCallback((e) => {
|
|
251
280
|
e.preventDefault();
|
|
252
281
|
e.stopPropagation();
|
|
253
|
-
|
|
282
|
+
const context = getBehaviorContext();
|
|
283
|
+
// If custom onClick handler is provided, it REPLACES default behavior
|
|
284
|
+
if (behaviorConfig?.onClick) {
|
|
285
|
+
const result = behaviorConfig.onClick(context, e);
|
|
286
|
+
// If custom handler returns actions, apply them
|
|
287
|
+
if (result && typeof result === "object") {
|
|
288
|
+
applyBehaviorActions(result);
|
|
289
|
+
}
|
|
290
|
+
// If returns false or void, no state changes
|
|
291
|
+
// Always call eventHandlers.onClick regardless of custom behavior
|
|
292
|
+
eventHandlers?.onClick?.(citation, citationKey, e);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
// Default click behavior (only runs when no custom onClick is provided)
|
|
254
296
|
if (verification?.verificationImageBase64) {
|
|
255
297
|
if (expandedImageSrc) {
|
|
256
298
|
// Image is open - close it and unpin
|
|
@@ -262,7 +304,7 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
|
|
|
262
304
|
setExpandedImageSrc(verification.verificationImageBase64);
|
|
263
305
|
}
|
|
264
306
|
else {
|
|
265
|
-
// First click -
|
|
307
|
+
// First click - pin the popover open
|
|
266
308
|
setIsTooltipExpanded(true);
|
|
267
309
|
}
|
|
268
310
|
}
|
|
@@ -274,11 +316,14 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
|
|
|
274
316
|
eventHandlers?.onClick?.(citation, citationKey, e);
|
|
275
317
|
}, [
|
|
276
318
|
eventHandlers,
|
|
319
|
+
behaviorConfig,
|
|
277
320
|
citation,
|
|
278
321
|
citationKey,
|
|
279
322
|
verification?.verificationImageBase64,
|
|
280
323
|
expandedImageSrc,
|
|
281
324
|
isTooltipExpanded,
|
|
325
|
+
getBehaviorContext,
|
|
326
|
+
applyBehaviorActions,
|
|
282
327
|
]);
|
|
283
328
|
const status = getCitationStatus(verification ?? null);
|
|
284
329
|
// const { isVerified, isPending } = status;
|
|
@@ -297,11 +342,19 @@ export const CitationComponent = forwardRef(({ citation, children, className, di
|
|
|
297
342
|
const foundStatusClass = useMemo(() => getFoundStatusClass(status), [status]);
|
|
298
343
|
// Event handlers
|
|
299
344
|
const handleMouseEnter = useCallback(() => {
|
|
345
|
+
// Call custom onHover.onEnter handler (if provided)
|
|
346
|
+
if (behaviorConfig?.onHover?.onEnter) {
|
|
347
|
+
behaviorConfig.onHover.onEnter(getBehaviorContext());
|
|
348
|
+
}
|
|
300
349
|
eventHandlers?.onMouseEnter?.(citation, citationKey);
|
|
301
|
-
}, [eventHandlers, citation, citationKey]);
|
|
350
|
+
}, [eventHandlers, behaviorConfig, citation, citationKey, getBehaviorContext]);
|
|
302
351
|
const handleMouseLeave = useCallback(() => {
|
|
352
|
+
// Call custom onHover.onLeave handler (if provided)
|
|
353
|
+
if (behaviorConfig?.onHover?.onLeave) {
|
|
354
|
+
behaviorConfig.onHover.onLeave(getBehaviorContext());
|
|
355
|
+
}
|
|
303
356
|
eventHandlers?.onMouseLeave?.(citation, citationKey);
|
|
304
|
-
}, [eventHandlers, citation, citationKey]);
|
|
357
|
+
}, [eventHandlers, behaviorConfig, citation, citationKey, getBehaviorContext]);
|
|
305
358
|
const handleTouchEnd = useCallback((e) => {
|
|
306
359
|
if (isMobile) {
|
|
307
360
|
e.preventDefault();
|
package/lib/react/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @packageDocumentation
|
|
12
12
|
*/
|
|
13
|
-
export type { CitationContentProps, CitationRenderProps, CitationTooltipProps, CitationStyles, CitationStateClasses, CitationCursorClasses, CitationEventHandlers, CitationVariant as CitationVariantType, UrlFetchStatus, UrlCitationMeta, UrlCitationProps, } from "./types.js";
|
|
13
|
+
export type { CitationContentProps, CitationRenderProps, CitationTooltipProps, CitationStyles, CitationStateClasses, CitationCursorClasses, CitationEventHandlers, CitationVariant as CitationVariantType, UrlFetchStatus, UrlCitationMeta, UrlCitationProps, CitationBehaviorConfig, CitationBehaviorContext, CitationBehaviorActions, CitationClickBehavior, CitationHoverBehavior, } from "./types.js";
|
|
14
14
|
export { extractDomain, isBlockedStatus, isErrorStatus, isVerifiedStatus, } from "./UrlCitationComponent.js";
|
|
15
15
|
export { generateCitationKey, generateCitationInstanceId, getCitationDisplayText, getCitationKeySpanText, classNames, CITATION_X_PADDING, CITATION_Y_PADDING, } from "./utils.js";
|
|
16
16
|
export { CitationComponent, MemoizedCitationComponent, type CitationVariant, type CitationComponentProps, } from "./CitationComponent.js";
|
package/lib/react/types.d.ts
CHANGED
|
@@ -184,6 +184,94 @@ export interface CitationEventHandlers {
|
|
|
184
184
|
/** Called on touch end (mobile) */
|
|
185
185
|
onTouchEnd?: (citation: Citation, citationKey: string, event: React.TouchEvent) => void;
|
|
186
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Context provided to behavior handlers for making decisions.
|
|
189
|
+
*/
|
|
190
|
+
export interface CitationBehaviorContext {
|
|
191
|
+
/** The citation data */
|
|
192
|
+
citation: Citation;
|
|
193
|
+
/** Unique key for this citation */
|
|
194
|
+
citationKey: string;
|
|
195
|
+
/** Verification result if available */
|
|
196
|
+
verification: Verification | null;
|
|
197
|
+
/** Whether the popover is currently pinned open */
|
|
198
|
+
isTooltipExpanded: boolean;
|
|
199
|
+
/** Whether the full-size image overlay is currently open */
|
|
200
|
+
isImageExpanded: boolean;
|
|
201
|
+
/** Whether a verification image is available */
|
|
202
|
+
hasImage: boolean;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Actions that can be performed by the citation component.
|
|
206
|
+
* These are returned by behavior handlers to control component state.
|
|
207
|
+
*/
|
|
208
|
+
export interface CitationBehaviorActions {
|
|
209
|
+
/** Pin or unpin the popover (keeps it visible without hover) */
|
|
210
|
+
setTooltipExpanded?: boolean;
|
|
211
|
+
/** Open or close the full-size image overlay */
|
|
212
|
+
setImageExpanded?: boolean | string;
|
|
213
|
+
/** Expand or collapse the search phrases list (for miss/partial states) */
|
|
214
|
+
setPhrasesExpanded?: boolean;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Configuration for click behavior.
|
|
218
|
+
* Return actions to perform, or `false` to prevent default behavior.
|
|
219
|
+
*/
|
|
220
|
+
export type CitationClickBehavior = (context: CitationBehaviorContext, event: React.MouseEvent | React.TouchEvent) => CitationBehaviorActions | false | void;
|
|
221
|
+
/**
|
|
222
|
+
* Configuration for hover behavior.
|
|
223
|
+
*/
|
|
224
|
+
export interface CitationHoverBehavior {
|
|
225
|
+
/** Called when mouse enters the citation */
|
|
226
|
+
onEnter?: (context: CitationBehaviorContext) => void;
|
|
227
|
+
/** Called when mouse leaves the citation */
|
|
228
|
+
onLeave?: (context: CitationBehaviorContext) => void;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Configuration for customizing default citation behaviors.
|
|
232
|
+
*
|
|
233
|
+
* When you provide `onClick` or `onHover`, they REPLACE the corresponding default behaviors.
|
|
234
|
+
* Use `eventHandlers` for side effects that should run alongside defaults.
|
|
235
|
+
*
|
|
236
|
+
* @example Custom click behavior (replaces default)
|
|
237
|
+
* ```tsx
|
|
238
|
+
* <CitationComponent
|
|
239
|
+
* citation={citation}
|
|
240
|
+
* verification={verification}
|
|
241
|
+
* behaviorConfig={{
|
|
242
|
+
* onClick: (context, event) => {
|
|
243
|
+
* if (context.hasImage) {
|
|
244
|
+
* return { setImageExpanded: true };
|
|
245
|
+
* }
|
|
246
|
+
* }
|
|
247
|
+
* }}
|
|
248
|
+
* />
|
|
249
|
+
* ```
|
|
250
|
+
*
|
|
251
|
+
* @example Disable click behavior entirely
|
|
252
|
+
* ```tsx
|
|
253
|
+
* <CitationComponent
|
|
254
|
+
* citation={citation}
|
|
255
|
+
* verification={verification}
|
|
256
|
+
* behaviorConfig={{ onClick: () => false }}
|
|
257
|
+
* />
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
export interface CitationBehaviorConfig {
|
|
261
|
+
/**
|
|
262
|
+
* Custom click behavior handler. When provided, REPLACES the default click behavior.
|
|
263
|
+
*
|
|
264
|
+
* Return values:
|
|
265
|
+
* - `CitationBehaviorActions`: Apply specific state changes
|
|
266
|
+
* - `false`: Prevent any state changes
|
|
267
|
+
* - `void`/`undefined`: No state changes
|
|
268
|
+
*/
|
|
269
|
+
onClick?: CitationClickBehavior;
|
|
270
|
+
/**
|
|
271
|
+
* Custom hover behavior handlers. When provided, REPLACE the default hover behavior.
|
|
272
|
+
*/
|
|
273
|
+
onHover?: CitationHoverBehavior;
|
|
274
|
+
}
|
|
187
275
|
/**
|
|
188
276
|
* Props for the tooltip wrapper component
|
|
189
277
|
*/
|