@athenaintel/react 0.10.35 → 0.10.37
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 +8 -1
- package/dist/assets/AthenaAssetEmbed.d.ts +4 -1
- package/dist/assets/asset-embed-messages.d.ts +18 -0
- package/dist/assets/use-asset-embed.d.ts +5 -0
- package/dist/index.cjs +95 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +95 -15
- package/dist/index.js.map +1 -1
- package/dist/styles.css +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -160,6 +160,11 @@ function AssetView() {
|
|
|
160
160
|
onCitationClick={({ reference, sourceAssetId }) => {
|
|
161
161
|
console.log('Citation clicked', { reference, sourceAssetId });
|
|
162
162
|
}}
|
|
163
|
+
onCitationAction={({ action, reference }) => {
|
|
164
|
+
if (action === 'open-in-spaces') {
|
|
165
|
+
openAssetInMyApp(reference);
|
|
166
|
+
}
|
|
167
|
+
}}
|
|
163
168
|
/>
|
|
164
169
|
</div>
|
|
165
170
|
</AthenaProvider>
|
|
@@ -167,7 +172,9 @@ function AssetView() {
|
|
|
167
172
|
}
|
|
168
173
|
```
|
|
169
174
|
|
|
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
|
|
175
|
+
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.
|
|
176
|
+
|
|
177
|
+
`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.
|
|
171
178
|
|
|
172
179
|
## Theming
|
|
173
180
|
|
|
@@ -1,5 +1,5 @@
|
|
|
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 } from "./asset-embed-messages";
|
|
3
3
|
export interface AthenaAssetEmbedProps extends Omit<IframeHTMLAttributes<HTMLIFrameElement>, "src" | "onError" | "onLoad"> {
|
|
4
4
|
assetId: string;
|
|
5
5
|
/** Defaults to the native full asset experience. */
|
|
@@ -9,6 +9,9 @@ export interface AthenaAssetEmbedProps extends Omit<IframeHTMLAttributes<HTMLIFr
|
|
|
9
9
|
expiresInSeconds?: number;
|
|
10
10
|
citationBehavior?: AthenaAssetCitationBehavior;
|
|
11
11
|
onCitationClick?: (event: AthenaAssetCitationClickEvent) => void;
|
|
12
|
+
/** Controls the citation popover's actions, including the (+) Open in Spaces button. */
|
|
13
|
+
citationActionBehavior?: AthenaAssetCitationBehavior;
|
|
14
|
+
onCitationAction?: (event: AthenaAssetCitationActionEvent) => void;
|
|
12
15
|
onLoad?: () => void;
|
|
13
16
|
onError?: (error: Error) => void;
|
|
14
17
|
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,6 +30,16 @@ export interface AthenaAssetEmbedConfigEvent {
|
|
|
22
30
|
version: 1;
|
|
23
31
|
token?: string;
|
|
24
32
|
citationBehavior: AthenaAssetCitationBehavior;
|
|
33
|
+
citationActionBehavior?: AthenaAssetCitationBehavior;
|
|
25
34
|
}
|
|
35
|
+
export declare function resolveAthenaAssetCitationBehavior({ citationBehavior, hasCitationClickHandler, }: {
|
|
36
|
+
citationBehavior?: AthenaAssetCitationBehavior;
|
|
37
|
+
hasCitationClickHandler: boolean;
|
|
38
|
+
}): AthenaAssetCitationBehavior;
|
|
39
|
+
export declare function resolveAthenaAssetCitationActionBehavior({ citationActionBehavior, hasCitationActionHandler, }: {
|
|
40
|
+
citationActionBehavior?: AthenaAssetCitationBehavior;
|
|
41
|
+
hasCitationActionHandler: boolean;
|
|
42
|
+
}): AthenaAssetCitationBehavior;
|
|
26
43
|
export declare function isAthenaAssetEmbedReadyEvent(value: unknown): value is AthenaAssetEmbedReadyEvent;
|
|
27
44
|
export declare function isAthenaAssetCitationClickEvent(value: unknown): value is AthenaAssetCitationClickEvent;
|
|
45
|
+
export declare function isAthenaAssetCitationActionEvent(value: unknown): value is AthenaAssetCitationActionEvent;
|
|
@@ -26,6 +26,11 @@ export declare function resolveAssetEmbedUrl({ embedUrl, appUrl, backendUrl, cur
|
|
|
26
26
|
backendUrl?: string | null;
|
|
27
27
|
currentOrigin?: string | null;
|
|
28
28
|
}): string;
|
|
29
|
+
export declare function buildSdkAssetEmbedUrl(embedUrl: string): string;
|
|
30
|
+
export declare function getAssetEmbedAuthContext({ token, apiKey }: {
|
|
31
|
+
token?: string | null;
|
|
32
|
+
apiKey?: string;
|
|
33
|
+
}): string;
|
|
29
34
|
/**
|
|
30
35
|
* Hook to generate an embed URL for rendering an asset in an iframe.
|
|
31
36
|
* Calls the Athena embed token endpoint.
|
package/dist/index.cjs
CHANGED
|
@@ -56254,12 +56254,30 @@ 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";
|
|
56258
|
+
function resolveAthenaAssetCitationBehavior({
|
|
56259
|
+
citationBehavior,
|
|
56260
|
+
hasCitationClickHandler
|
|
56261
|
+
}) {
|
|
56262
|
+
if (citationBehavior === "host" && !hasCitationClickHandler) return "browser";
|
|
56263
|
+
return citationBehavior ?? (hasCitationClickHandler ? "host" : "browser");
|
|
56264
|
+
}
|
|
56265
|
+
function resolveAthenaAssetCitationActionBehavior({
|
|
56266
|
+
citationActionBehavior,
|
|
56267
|
+
hasCitationActionHandler
|
|
56268
|
+
}) {
|
|
56269
|
+
if (citationActionBehavior === "host" && !hasCitationActionHandler) return "browser";
|
|
56270
|
+
return citationActionBehavior ?? (hasCitationActionHandler ? "host" : "browser");
|
|
56271
|
+
}
|
|
56257
56272
|
function isAthenaAssetEmbedReadyEvent(value) {
|
|
56258
56273
|
return typeof value === "object" && value !== null && "type" in value && value.type === ATHENA_ASSET_EMBED_READY_MESSAGE && "version" in value && value.version === 1;
|
|
56259
56274
|
}
|
|
56260
56275
|
function isAthenaAssetCitationClickEvent(value) {
|
|
56261
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";
|
|
56262
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
|
+
}
|
|
56263
56281
|
function buildAssetEmbedRequestBody({
|
|
56264
56282
|
assetId,
|
|
56265
56283
|
readOnly,
|
|
@@ -56356,7 +56374,11 @@ function resolveAssetEmbedUrl({
|
|
|
56356
56374
|
if (!resolvedEmbedUrl.pathname.startsWith("/embed/")) {
|
|
56357
56375
|
return embedUrl;
|
|
56358
56376
|
}
|
|
56359
|
-
const embedAppUrl = resolveEmbedAppUrl({
|
|
56377
|
+
const embedAppUrl = resolveEmbedAppUrl({
|
|
56378
|
+
appUrl,
|
|
56379
|
+
backendUrl,
|
|
56380
|
+
currentOrigin
|
|
56381
|
+
});
|
|
56360
56382
|
if (!embedAppUrl) {
|
|
56361
56383
|
return embedUrl;
|
|
56362
56384
|
}
|
|
@@ -56368,6 +56390,41 @@ function resolveAssetEmbedUrl({
|
|
|
56368
56390
|
return embedUrl;
|
|
56369
56391
|
}
|
|
56370
56392
|
}
|
|
56393
|
+
function buildSdkAssetEmbedUrl(embedUrl) {
|
|
56394
|
+
try {
|
|
56395
|
+
const url = new URL(embedUrl);
|
|
56396
|
+
url.searchParams.set("athena_sdk_bridge", "1");
|
|
56397
|
+
return url.toString();
|
|
56398
|
+
} catch {
|
|
56399
|
+
return embedUrl;
|
|
56400
|
+
}
|
|
56401
|
+
}
|
|
56402
|
+
const getJwtPayload = (token) => {
|
|
56403
|
+
try {
|
|
56404
|
+
const payloadSegment = token.split(".")[1];
|
|
56405
|
+
if (!payloadSegment || typeof atob !== "function") return null;
|
|
56406
|
+
const normalized = payloadSegment.replace(/-/g, "+").replace(/_/g, "/");
|
|
56407
|
+
const payload = JSON.parse(
|
|
56408
|
+
atob(normalized.padEnd(normalized.length + (4 - normalized.length % 4) % 4, "="))
|
|
56409
|
+
);
|
|
56410
|
+
return payload && typeof payload === "object" ? payload : null;
|
|
56411
|
+
} catch {
|
|
56412
|
+
return null;
|
|
56413
|
+
}
|
|
56414
|
+
};
|
|
56415
|
+
function getAssetEmbedAuthContext({ token, apiKey }) {
|
|
56416
|
+
if (!token) return apiKey ? `api-key:${apiKey}` : "anonymous";
|
|
56417
|
+
const payload = getJwtPayload(token);
|
|
56418
|
+
const userId = (payload == null ? void 0 : payload.user_id) ?? (payload == null ? void 0 : payload.sub);
|
|
56419
|
+
if (typeof userId !== "string" || !userId) return `opaque-token:${token}`;
|
|
56420
|
+
return `jwt:${JSON.stringify({
|
|
56421
|
+
issuer: (payload == null ? void 0 : payload.iss) ?? null,
|
|
56422
|
+
userId,
|
|
56423
|
+
activeOrgId: (payload == null ? void 0 : payload.active_org_id) ?? (payload == null ? void 0 : payload.org_id) ?? null,
|
|
56424
|
+
workspaceId: (payload == null ? void 0 : payload.workspace_id) ?? null,
|
|
56425
|
+
orgMemberships: (payload == null ? void 0 : payload.org_id_to_org_member_info) ?? null
|
|
56426
|
+
})}`;
|
|
56427
|
+
}
|
|
56371
56428
|
function useAssetEmbed(assetId, options = {
|
|
56372
56429
|
backendUrl: ""
|
|
56373
56430
|
}) {
|
|
@@ -56386,7 +56443,7 @@ function useAssetEmbed(assetId, options = {
|
|
|
56386
56443
|
const abortRef = React.useRef(null);
|
|
56387
56444
|
const tokenRef = React.useRef(token);
|
|
56388
56445
|
tokenRef.current = token;
|
|
56389
|
-
const
|
|
56446
|
+
const authContext = getAssetEmbedAuthContext({ token, apiKey });
|
|
56390
56447
|
React.useEffect(() => {
|
|
56391
56448
|
var _a2;
|
|
56392
56449
|
if (!assetId || !backendUrl) {
|
|
@@ -56395,7 +56452,6 @@ function useAssetEmbed(assetId, options = {
|
|
|
56395
56452
|
setError(null);
|
|
56396
56453
|
return;
|
|
56397
56454
|
}
|
|
56398
|
-
const authContext = hasToken ? "token" : apiKey ?? "anon";
|
|
56399
56455
|
const cacheKey = `${assetId}:${readOnly}:${displayMode}:${authContext}:${backendUrl}:${appUrl ?? ""}`;
|
|
56400
56456
|
const cached2 = embedCache.get(cacheKey);
|
|
56401
56457
|
if (cached2 && cached2.expiresAt > Date.now() / 1e3) {
|
|
@@ -56411,10 +56467,12 @@ function useAssetEmbed(assetId, options = {
|
|
|
56411
56467
|
abortRef.current = controller;
|
|
56412
56468
|
setIsLoading(true);
|
|
56413
56469
|
setError(null);
|
|
56414
|
-
const headers = {
|
|
56470
|
+
const headers = {
|
|
56471
|
+
"Content-Type": "application/json"
|
|
56472
|
+
};
|
|
56415
56473
|
const currentToken = tokenRef.current;
|
|
56416
56474
|
if (currentToken) {
|
|
56417
|
-
headers
|
|
56475
|
+
headers.Authorization = `Bearer ${currentToken}`;
|
|
56418
56476
|
} else if (apiKey) {
|
|
56419
56477
|
headers["X-API-KEY"] = apiKey;
|
|
56420
56478
|
}
|
|
@@ -56422,7 +56480,12 @@ function useAssetEmbed(assetId, options = {
|
|
|
56422
56480
|
method: "POST",
|
|
56423
56481
|
headers,
|
|
56424
56482
|
body: JSON.stringify(
|
|
56425
|
-
buildAssetEmbedRequestBody({
|
|
56483
|
+
buildAssetEmbedRequestBody({
|
|
56484
|
+
assetId,
|
|
56485
|
+
readOnly,
|
|
56486
|
+
expiresInSeconds,
|
|
56487
|
+
displayMode
|
|
56488
|
+
})
|
|
56426
56489
|
),
|
|
56427
56490
|
signal: controller.signal
|
|
56428
56491
|
}).then(async (res) => {
|
|
@@ -56437,7 +56500,10 @@ function useAssetEmbed(assetId, options = {
|
|
|
56437
56500
|
appUrl,
|
|
56438
56501
|
backendUrl
|
|
56439
56502
|
});
|
|
56440
|
-
embedCache.set(cacheKey, {
|
|
56503
|
+
embedCache.set(cacheKey, {
|
|
56504
|
+
url: resolvedEmbedUrl,
|
|
56505
|
+
expiresAt: data.expires_at
|
|
56506
|
+
});
|
|
56441
56507
|
setEmbedUrl(resolvedEmbedUrl);
|
|
56442
56508
|
setIsLoading(false);
|
|
56443
56509
|
}).catch((err) => {
|
|
@@ -56446,7 +56512,7 @@ function useAssetEmbed(assetId, options = {
|
|
|
56446
56512
|
setIsLoading(false);
|
|
56447
56513
|
});
|
|
56448
56514
|
return () => controller.abort();
|
|
56449
|
-
}, [assetId, readOnly, expiresInSeconds, displayMode, backendUrl, appUrl,
|
|
56515
|
+
}, [assetId, readOnly, expiresInSeconds, displayMode, backendUrl, appUrl, authContext, apiKey]);
|
|
56450
56516
|
return { embedUrl, isLoading, error: error2 };
|
|
56451
56517
|
}
|
|
56452
56518
|
const DEFAULT_STYLE = {
|
|
@@ -56462,6 +56528,8 @@ const AthenaAssetEmbed = ({
|
|
|
56462
56528
|
expiresInSeconds,
|
|
56463
56529
|
citationBehavior,
|
|
56464
56530
|
onCitationClick,
|
|
56531
|
+
citationActionBehavior,
|
|
56532
|
+
onCitationAction,
|
|
56465
56533
|
onLoad,
|
|
56466
56534
|
onError,
|
|
56467
56535
|
loadingFallback,
|
|
@@ -56492,7 +56560,15 @@ const AthenaAssetEmbed = ({
|
|
|
56492
56560
|
return null;
|
|
56493
56561
|
}
|
|
56494
56562
|
}, [embedUrl]);
|
|
56495
|
-
const
|
|
56563
|
+
const iframeSrc = React.useMemo(() => embedUrl ? buildSdkAssetEmbedUrl(embedUrl) : null, [embedUrl]);
|
|
56564
|
+
const effectiveCitationBehavior = resolveAthenaAssetCitationBehavior({
|
|
56565
|
+
citationBehavior,
|
|
56566
|
+
hasCitationClickHandler: !!onCitationClick
|
|
56567
|
+
});
|
|
56568
|
+
const effectiveCitationActionBehavior = resolveAthenaAssetCitationActionBehavior({
|
|
56569
|
+
citationActionBehavior,
|
|
56570
|
+
hasCitationActionHandler: !!onCitationAction
|
|
56571
|
+
});
|
|
56496
56572
|
const sendConfig = React.useCallback(() => {
|
|
56497
56573
|
var _a2, _b;
|
|
56498
56574
|
if (!targetOrigin) return;
|
|
@@ -56501,28 +56577,32 @@ const AthenaAssetEmbed = ({
|
|
|
56501
56577
|
type: ATHENA_ASSET_EMBED_CONFIG_MESSAGE,
|
|
56502
56578
|
version: 1,
|
|
56503
56579
|
...athenaConfig.token ? { token: athenaConfig.token } : {},
|
|
56504
|
-
citationBehavior: effectiveCitationBehavior
|
|
56580
|
+
citationBehavior: effectiveCitationBehavior,
|
|
56581
|
+
citationActionBehavior: effectiveCitationActionBehavior
|
|
56505
56582
|
},
|
|
56506
56583
|
targetOrigin
|
|
56507
56584
|
);
|
|
56508
|
-
}, [athenaConfig, effectiveCitationBehavior, targetOrigin]);
|
|
56585
|
+
}, [athenaConfig, effectiveCitationActionBehavior, effectiveCitationBehavior, targetOrigin]);
|
|
56509
56586
|
React.useEffect(() => {
|
|
56510
56587
|
if (!embedUrl || !targetOrigin) return;
|
|
56511
56588
|
const handleMessage = (event) => {
|
|
56512
56589
|
var _a2;
|
|
56513
|
-
if (event.origin !== targetOrigin || event.source !== ((_a2 = iframeRef.current) == null ? void 0 : _a2.contentWindow))
|
|
56514
|
-
return;
|
|
56590
|
+
if (event.origin !== targetOrigin || event.source !== ((_a2 = iframeRef.current) == null ? void 0 : _a2.contentWindow)) return;
|
|
56515
56591
|
if (isAthenaAssetEmbedReadyEvent(event.data)) {
|
|
56516
56592
|
sendConfig();
|
|
56517
56593
|
return;
|
|
56518
56594
|
}
|
|
56519
56595
|
if (isAthenaAssetCitationClickEvent(event.data)) {
|
|
56520
56596
|
onCitationClick == null ? void 0 : onCitationClick(event.data);
|
|
56597
|
+
return;
|
|
56598
|
+
}
|
|
56599
|
+
if (isAthenaAssetCitationActionEvent(event.data)) {
|
|
56600
|
+
onCitationAction == null ? void 0 : onCitationAction(event.data);
|
|
56521
56601
|
}
|
|
56522
56602
|
};
|
|
56523
56603
|
window.addEventListener("message", handleMessage);
|
|
56524
56604
|
return () => window.removeEventListener("message", handleMessage);
|
|
56525
|
-
}, [embedUrl, onCitationClick, sendConfig, targetOrigin]);
|
|
56605
|
+
}, [embedUrl, onCitationAction, onCitationClick, sendConfig, targetOrigin]);
|
|
56526
56606
|
React.useEffect(() => {
|
|
56527
56607
|
if (!embedUrl) return;
|
|
56528
56608
|
sendConfig();
|
|
@@ -56559,7 +56639,7 @@ const AthenaAssetEmbed = ({
|
|
|
56559
56639
|
{
|
|
56560
56640
|
...iframeProps,
|
|
56561
56641
|
ref: iframeRef,
|
|
56562
|
-
src:
|
|
56642
|
+
src: iframeSrc ?? void 0,
|
|
56563
56643
|
title: title ?? `Athena asset ${assetId}`,
|
|
56564
56644
|
allow,
|
|
56565
56645
|
className: cn("block h-full w-full", className),
|