@athenaintel/react 0.10.36 → 0.10.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -150,6 +150,8 @@ Use `AthenaAssetEmbed` to render a native Athena asset without chat, thread hist
150
150
  import { AthenaAssetEmbed, AthenaProvider } from '@athenaintel/react';
151
151
 
152
152
  function AssetView() {
153
+ const [linkedReference, setLinkedReference] = useState(null);
154
+
153
155
  return (
154
156
  <AthenaProvider config={{ token: accessToken }}>
155
157
  <div style={{ height: 800 }}>
@@ -160,14 +162,33 @@ function AssetView() {
160
162
  onCitationClick={({ reference, sourceAssetId }) => {
161
163
  console.log('Citation clicked', { reference, sourceAssetId });
162
164
  }}
165
+ onCitationAction={({ action, reference }) => {
166
+ if (action === 'open-in-spaces') {
167
+ setLinkedReference(reference);
168
+ }
169
+ }}
163
170
  />
171
+ {linkedReference && (
172
+ <AthenaAssetEmbed
173
+ assetId={linkedReference.id}
174
+ reference={linkedReference}
175
+ displayMode="full"
176
+ readOnly
177
+ />
178
+ )}
164
179
  </div>
165
180
  </AthenaProvider>
166
181
  );
167
182
  }
168
183
  ```
169
184
 
170
- When `onCitationClick` is provided, citation navigation is delegated to the host by default. Set `citationBehavior="browser"` to observe the event while preserving Athena's default new-tab navigation, or `citationBehavior="host"` to delegate navigation without providing a callback.
185
+ When `onCitationClick` is provided, citation navigation is delegated to the host by default. Set `citationBehavior="browser"` to observe the event while preserving Athena's default new-tab navigation. Host mode requires `onCitationClick`; without a handler, the SDK safely falls back to browser navigation.
186
+
187
+ `onCitationAction` handles actions initiated from a citation popover. It currently receives `action: 'open-in-spaces'` when the user clicks the (+) button. Providing the handler delegates that action to the host by default. Set `citationActionBehavior="browser"` to observe the event while preserving Athena's default navigation; requesting host mode without a handler safely falls back to browser behavior.
188
+
189
+ Pass the callback's complete `reference` to the linked `AthenaAssetEmbed`, rather than storing only
190
+ `reference.id`. The embed uses the reference anchor to navigate PDFs to the cited page. Updating the
191
+ reference also navigates when the host opens another citation in the same asset.
171
192
 
172
193
  ## Theming
173
194
 
@@ -1,7 +1,9 @@
1
1
  import { type FC, type IframeHTMLAttributes } from "react";
2
- import { type AthenaAssetCitationBehavior, type AthenaAssetCitationClickEvent } from "./asset-embed-messages";
2
+ import { type AthenaAssetCitationActionEvent, type AthenaAssetCitationBehavior, type AthenaAssetCitationClickEvent, type AthenaAssetCitationReference } from "./asset-embed-messages";
3
3
  export interface AthenaAssetEmbedProps extends Omit<IframeHTMLAttributes<HTMLIFrameElement>, "src" | "onError" | "onLoad"> {
4
4
  assetId: string;
5
+ /** Optional citation target to open inside the embedded asset, such as a PDF page. */
6
+ reference?: AthenaAssetCitationReference;
5
7
  /** Defaults to the native full asset experience. */
6
8
  displayMode?: "minimal" | "full";
7
9
  /** Defaults to true. */
@@ -9,6 +11,9 @@ export interface AthenaAssetEmbedProps extends Omit<IframeHTMLAttributes<HTMLIFr
9
11
  expiresInSeconds?: number;
10
12
  citationBehavior?: AthenaAssetCitationBehavior;
11
13
  onCitationClick?: (event: AthenaAssetCitationClickEvent) => void;
14
+ /** Controls the citation popover's actions, including the (+) Open in Spaces button. */
15
+ citationActionBehavior?: AthenaAssetCitationBehavior;
16
+ onCitationAction?: (event: AthenaAssetCitationActionEvent) => void;
12
17
  onLoad?: () => void;
13
18
  onError?: (error: Error) => void;
14
19
  loadingFallback?: React.ReactNode;
@@ -1,7 +1,9 @@
1
1
  export declare const ATHENA_ASSET_EMBED_READY_MESSAGE: "athena:asset-embed-ready";
2
2
  export declare const ATHENA_ASSET_EMBED_CONFIG_MESSAGE: "athena:asset-embed-config";
3
3
  export declare const ATHENA_ASSET_CITATION_CLICK_MESSAGE: "athena:asset-citation-click";
4
+ export declare const ATHENA_ASSET_CITATION_ACTION_MESSAGE: "athena:asset-citation-action";
4
5
  export type AthenaAssetCitationBehavior = "browser" | "host";
6
+ export type AthenaAssetCitationAction = "open-in-spaces";
5
7
  export interface AthenaAssetCitationReference {
6
8
  id: string;
7
9
  anchor?: unknown;
@@ -13,6 +15,12 @@ export interface AthenaAssetCitationClickEvent {
13
15
  sourceAssetId?: string;
14
16
  reference: AthenaAssetCitationReference;
15
17
  }
18
+ export interface AthenaAssetCitationActionEvent {
19
+ type: typeof ATHENA_ASSET_CITATION_ACTION_MESSAGE;
20
+ version: 1;
21
+ action: AthenaAssetCitationAction;
22
+ reference: AthenaAssetCitationReference;
23
+ }
16
24
  export interface AthenaAssetEmbedReadyEvent {
17
25
  type: typeof ATHENA_ASSET_EMBED_READY_MESSAGE;
18
26
  version: 1;
@@ -22,10 +30,16 @@ export interface AthenaAssetEmbedConfigEvent {
22
30
  version: 1;
23
31
  token?: string;
24
32
  citationBehavior: AthenaAssetCitationBehavior;
33
+ citationActionBehavior?: AthenaAssetCitationBehavior;
25
34
  }
26
35
  export declare function resolveAthenaAssetCitationBehavior({ citationBehavior, hasCitationClickHandler, }: {
27
36
  citationBehavior?: AthenaAssetCitationBehavior;
28
37
  hasCitationClickHandler: boolean;
29
38
  }): AthenaAssetCitationBehavior;
39
+ export declare function resolveAthenaAssetCitationActionBehavior({ citationActionBehavior, hasCitationActionHandler, }: {
40
+ citationActionBehavior?: AthenaAssetCitationBehavior;
41
+ hasCitationActionHandler: boolean;
42
+ }): AthenaAssetCitationBehavior;
30
43
  export declare function isAthenaAssetEmbedReadyEvent(value: unknown): value is AthenaAssetEmbedReadyEvent;
31
44
  export declare function isAthenaAssetCitationClickEvent(value: unknown): value is AthenaAssetCitationClickEvent;
45
+ export declare function isAthenaAssetCitationActionEvent(value: unknown): value is AthenaAssetCitationActionEvent;
@@ -1,3 +1,4 @@
1
+ import type { AthenaAssetCitationReference } from './asset-embed-messages';
1
2
  export interface UseAssetEmbedOptions {
2
3
  readOnly?: boolean;
3
4
  expiresInSeconds?: number;
@@ -26,7 +27,7 @@ export declare function resolveAssetEmbedUrl({ embedUrl, appUrl, backendUrl, cur
26
27
  backendUrl?: string | null;
27
28
  currentOrigin?: string | null;
28
29
  }): string;
29
- export declare function buildSdkAssetEmbedUrl(embedUrl: string): string;
30
+ export declare function buildSdkAssetEmbedUrl(embedUrl: string, reference?: AthenaAssetCitationReference): string;
30
31
  export declare function getAssetEmbedAuthContext({ token, apiKey }: {
31
32
  token?: string | null;
32
33
  apiKey?: string;
package/dist/index.cjs CHANGED
@@ -56254,6 +56254,7 @@ const AthenaUserMessage = ({
56254
56254
  const ATHENA_ASSET_EMBED_READY_MESSAGE = "athena:asset-embed-ready";
56255
56255
  const ATHENA_ASSET_EMBED_CONFIG_MESSAGE = "athena:asset-embed-config";
56256
56256
  const ATHENA_ASSET_CITATION_CLICK_MESSAGE = "athena:asset-citation-click";
56257
+ const ATHENA_ASSET_CITATION_ACTION_MESSAGE = "athena:asset-citation-action";
56257
56258
  function resolveAthenaAssetCitationBehavior({
56258
56259
  citationBehavior,
56259
56260
  hasCitationClickHandler
@@ -56261,12 +56262,22 @@ function resolveAthenaAssetCitationBehavior({
56261
56262
  if (citationBehavior === "host" && !hasCitationClickHandler) return "browser";
56262
56263
  return citationBehavior ?? (hasCitationClickHandler ? "host" : "browser");
56263
56264
  }
56265
+ function resolveAthenaAssetCitationActionBehavior({
56266
+ citationActionBehavior,
56267
+ hasCitationActionHandler
56268
+ }) {
56269
+ if (citationActionBehavior === "host" && !hasCitationActionHandler) return "browser";
56270
+ return citationActionBehavior ?? (hasCitationActionHandler ? "host" : "browser");
56271
+ }
56264
56272
  function isAthenaAssetEmbedReadyEvent(value) {
56265
56273
  return typeof value === "object" && value !== null && "type" in value && value.type === ATHENA_ASSET_EMBED_READY_MESSAGE && "version" in value && value.version === 1;
56266
56274
  }
56267
56275
  function isAthenaAssetCitationClickEvent(value) {
56268
56276
  return typeof value === "object" && value !== null && "type" in value && value.type === ATHENA_ASSET_CITATION_CLICK_MESSAGE && "version" in value && value.version === 1 && "reference" in value && typeof value.reference === "object" && value.reference !== null && "id" in value.reference && typeof value.reference.id === "string";
56269
56277
  }
56278
+ function isAthenaAssetCitationActionEvent(value) {
56279
+ return typeof value === "object" && value !== null && "type" in value && value.type === ATHENA_ASSET_CITATION_ACTION_MESSAGE && "version" in value && value.version === 1 && "action" in value && value.action === "open-in-spaces" && "reference" in value && typeof value.reference === "object" && value.reference !== null && "id" in value.reference && typeof value.reference.id === "string";
56280
+ }
56270
56281
  function buildAssetEmbedRequestBody({
56271
56282
  assetId,
56272
56283
  readOnly,
@@ -56379,10 +56390,92 @@ function resolveAssetEmbedUrl({
56379
56390
  return embedUrl;
56380
56391
  }
56381
56392
  }
56382
- function buildSdkAssetEmbedUrl(embedUrl) {
56393
+ function setFiniteNumberParam({ params, key, value }) {
56394
+ if (typeof value === "number" && Number.isFinite(value)) {
56395
+ params.set(key, String(value));
56396
+ }
56397
+ }
56398
+ function appendCitationReferenceParams({
56399
+ params,
56400
+ reference: reference2
56401
+ }) {
56402
+ var _a2;
56403
+ const anchor = reference2 == null ? void 0 : reference2.anchor;
56404
+ if (!anchor || typeof anchor !== "object" || !("type" in anchor) || typeof anchor.type !== "string") {
56405
+ return;
56406
+ }
56407
+ switch (anchor.type) {
56408
+ case "page":
56409
+ params.set("anchor", anchor.type);
56410
+ setFiniteNumberParam({
56411
+ params,
56412
+ key: "page",
56413
+ value: "page" in anchor ? anchor.page : void 0
56414
+ });
56415
+ break;
56416
+ case "page_range":
56417
+ params.set("anchor", anchor.type);
56418
+ setFiniteNumberParam({
56419
+ params,
56420
+ key: "start_page",
56421
+ value: "startPage" in anchor ? anchor.startPage : void 0
56422
+ });
56423
+ setFiniteNumberParam({
56424
+ params,
56425
+ key: "end_page",
56426
+ value: "endPage" in anchor ? anchor.endPage : void 0
56427
+ });
56428
+ break;
56429
+ case "page_rect":
56430
+ params.set("anchor", anchor.type);
56431
+ setFiniteNumberParam({
56432
+ params,
56433
+ key: "page",
56434
+ value: "page" in anchor ? anchor.page : void 0
56435
+ });
56436
+ setFiniteNumberParam({
56437
+ params,
56438
+ key: "x",
56439
+ value: "x" in anchor ? anchor.x : void 0
56440
+ });
56441
+ setFiniteNumberParam({
56442
+ params,
56443
+ key: "y",
56444
+ value: "y" in anchor ? anchor.y : void 0
56445
+ });
56446
+ setFiniteNumberParam({
56447
+ params,
56448
+ key: "width",
56449
+ value: "width" in anchor ? anchor.width : void 0
56450
+ });
56451
+ setFiniteNumberParam({
56452
+ params,
56453
+ key: "height",
56454
+ value: "height" in anchor ? anchor.height : void 0
56455
+ });
56456
+ break;
56457
+ case "page_text":
56458
+ params.set("anchor", anchor.type);
56459
+ setFiniteNumberParam({
56460
+ params,
56461
+ key: "page",
56462
+ value: "page" in anchor ? anchor.page : void 0
56463
+ });
56464
+ if ("text" in anchor && typeof anchor.text === "string") {
56465
+ params.set("text", anchor.text);
56466
+ }
56467
+ break;
56468
+ }
56469
+ const excerpt = (_a2 = reference2.meta) == null ? void 0 : _a2.excerpt;
56470
+ if (typeof excerpt === "string" && excerpt) {
56471
+ params.set("excerpt", excerpt);
56472
+ }
56473
+ }
56474
+ function buildSdkAssetEmbedUrl(embedUrl, reference2) {
56383
56475
  try {
56384
56476
  const url = new URL(embedUrl);
56385
56477
  url.searchParams.set("athena_sdk_bridge", "1");
56478
+ appendCitationReferenceParams({ params: url.searchParams, reference: reference2 });
56386
56479
  return url.toString();
56387
56480
  } catch {
56388
56481
  return embedUrl;
@@ -56512,11 +56605,14 @@ const DEFAULT_STYLE = {
56512
56605
  const AUTH_SYNC_INTERVAL_MS = 6e4;
56513
56606
  const AthenaAssetEmbed = ({
56514
56607
  assetId,
56608
+ reference: reference2,
56515
56609
  displayMode = "full",
56516
56610
  readOnly = true,
56517
56611
  expiresInSeconds,
56518
56612
  citationBehavior,
56519
56613
  onCitationClick,
56614
+ citationActionBehavior,
56615
+ onCitationAction,
56520
56616
  onLoad,
56521
56617
  onError,
56522
56618
  loadingFallback,
@@ -56547,11 +56643,18 @@ const AthenaAssetEmbed = ({
56547
56643
  return null;
56548
56644
  }
56549
56645
  }, [embedUrl]);
56550
- const iframeSrc = React.useMemo(() => embedUrl ? buildSdkAssetEmbedUrl(embedUrl) : null, [embedUrl]);
56646
+ const iframeSrc = React.useMemo(
56647
+ () => embedUrl ? buildSdkAssetEmbedUrl(embedUrl, reference2) : null,
56648
+ [embedUrl, reference2]
56649
+ );
56551
56650
  const effectiveCitationBehavior = resolveAthenaAssetCitationBehavior({
56552
56651
  citationBehavior,
56553
56652
  hasCitationClickHandler: !!onCitationClick
56554
56653
  });
56654
+ const effectiveCitationActionBehavior = resolveAthenaAssetCitationActionBehavior({
56655
+ citationActionBehavior,
56656
+ hasCitationActionHandler: !!onCitationAction
56657
+ });
56555
56658
  const sendConfig = React.useCallback(() => {
56556
56659
  var _a2, _b;
56557
56660
  if (!targetOrigin) return;
@@ -56560,11 +56663,12 @@ const AthenaAssetEmbed = ({
56560
56663
  type: ATHENA_ASSET_EMBED_CONFIG_MESSAGE,
56561
56664
  version: 1,
56562
56665
  ...athenaConfig.token ? { token: athenaConfig.token } : {},
56563
- citationBehavior: effectiveCitationBehavior
56666
+ citationBehavior: effectiveCitationBehavior,
56667
+ citationActionBehavior: effectiveCitationActionBehavior
56564
56668
  },
56565
56669
  targetOrigin
56566
56670
  );
56567
- }, [athenaConfig, effectiveCitationBehavior, targetOrigin]);
56671
+ }, [athenaConfig, effectiveCitationActionBehavior, effectiveCitationBehavior, targetOrigin]);
56568
56672
  React.useEffect(() => {
56569
56673
  if (!embedUrl || !targetOrigin) return;
56570
56674
  const handleMessage = (event) => {
@@ -56576,11 +56680,15 @@ const AthenaAssetEmbed = ({
56576
56680
  }
56577
56681
  if (isAthenaAssetCitationClickEvent(event.data)) {
56578
56682
  onCitationClick == null ? void 0 : onCitationClick(event.data);
56683
+ return;
56684
+ }
56685
+ if (isAthenaAssetCitationActionEvent(event.data)) {
56686
+ onCitationAction == null ? void 0 : onCitationAction(event.data);
56579
56687
  }
56580
56688
  };
56581
56689
  window.addEventListener("message", handleMessage);
56582
56690
  return () => window.removeEventListener("message", handleMessage);
56583
- }, [embedUrl, onCitationClick, sendConfig, targetOrigin]);
56691
+ }, [embedUrl, onCitationAction, onCitationClick, sendConfig, targetOrigin]);
56584
56692
  React.useEffect(() => {
56585
56693
  if (!embedUrl) return;
56586
56694
  sendConfig();