@xenia-martech/sdk-js 1.2.0-dev.7 → 1.2.0-dev.9
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 +70 -6
- package/dist/{actions-35V37IT0.d.cts → actions--1_9Z8ig.d.cts} +13 -2
- package/dist/{actions-35V37IT0.d.ts → actions--1_9Z8ig.d.ts} +13 -2
- package/dist/{api-0IycTYJR.d.cts → api-DbUxT38T.d.ts} +1 -1
- package/dist/{api-COXWLL5L.d.ts → api-DgzJ5s-k.d.cts} +1 -1
- package/dist/chunk-DPXINHQR.cjs +34 -0
- package/dist/chunk-DPXINHQR.cjs.map +1 -0
- package/dist/chunk-FSJMHXS6.js +432 -0
- package/dist/chunk-FSJMHXS6.js.map +1 -0
- package/dist/chunk-GXJLU3RE.cjs +448 -0
- package/dist/chunk-GXJLU3RE.cjs.map +1 -0
- package/dist/{chunk-2DR5AVPX.cjs → chunk-I5EHLRSR.cjs} +11 -10
- package/dist/chunk-I5EHLRSR.cjs.map +1 -0
- package/dist/{chunk-LW5AEJ6K.js → chunk-MEULT5X6.js} +4 -241
- package/dist/chunk-MEULT5X6.js.map +1 -0
- package/dist/{chunk-GWRDZIVA.js → chunk-NDRRSRTU.js} +4 -3
- package/dist/chunk-NDRRSRTU.js.map +1 -0
- package/dist/chunk-RC46KXDM.js +32 -0
- package/dist/chunk-RC46KXDM.js.map +1 -0
- package/dist/{chunk-RWE2OCQL.cjs → chunk-SU25SELD.cjs} +4 -244
- package/dist/chunk-SU25SELD.cjs.map +1 -0
- package/dist/{chunk-WHGK55JP.cjs → chunk-UUIKUU5W.cjs} +5 -5
- package/dist/{chunk-WHGK55JP.cjs.map → chunk-UUIKUU5W.cjs.map} +1 -1
- package/dist/{chunk-QEYONKWY.js → chunk-UVTFGQR6.js} +3 -3
- package/dist/{chunk-QEYONKWY.js.map → chunk-UVTFGQR6.js.map} +1 -1
- package/dist/{chunk-OMMIRSPK.js → chunk-V4EGU3PM.js} +48 -11
- package/dist/chunk-V4EGU3PM.js.map +1 -0
- package/dist/{chunk-YLMMTKQL.cjs → chunk-WMGCQPHY.cjs} +52 -13
- package/dist/chunk-WMGCQPHY.cjs.map +1 -0
- package/dist/client/index.cjs +26 -10
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +26 -10
- package/dist/client/index.js.map +1 -1
- package/dist/client/react/index.cjs +73 -15
- package/dist/client/react/index.cjs.map +1 -1
- package/dist/client/react/index.d.cts +9 -3
- package/dist/client/react/index.d.ts +9 -3
- package/dist/client/react/index.js +73 -15
- package/dist/client/react/index.js.map +1 -1
- package/dist/cms/contentful.cjs +7 -24
- package/dist/cms/contentful.cjs.map +1 -1
- package/dist/cms/contentful.d.cts +5 -4
- package/dist/cms/contentful.d.ts +5 -4
- package/dist/cms/contentful.js +4 -23
- package/dist/cms/contentful.js.map +1 -1
- package/dist/cms/contentstack.cjs +120 -0
- package/dist/cms/contentstack.cjs.map +1 -0
- package/dist/cms/contentstack.d.cts +41 -0
- package/dist/cms/contentstack.d.ts +41 -0
- package/dist/cms/contentstack.js +117 -0
- package/dist/cms/contentstack.js.map +1 -0
- package/dist/{consent-DRCV0N0d.d.ts → consent-Dtiqzz2B.d.cts} +71 -11
- package/dist/{consent-BgAETCkL.d.cts → consent-byYiDMFr.d.ts} +71 -11
- package/dist/{cookie-names-DU3MtcNG.d.ts → cookie-names-B4hda2rX.d.cts} +1 -1
- package/dist/{cookie-names-DFItnSLK.d.cts → cookie-names-DioZXuV0.d.ts} +1 -1
- package/dist/edge/index.cjs +122 -29
- package/dist/edge/index.cjs.map +1 -1
- package/dist/edge/index.d.cts +42 -6
- package/dist/edge/index.d.ts +42 -6
- package/dist/edge/index.js +92 -9
- package/dist/edge/index.js.map +1 -1
- package/dist/index.cjs +31 -31
- package/dist/index.d.cts +4 -5
- package/dist/index.d.ts +4 -5
- package/dist/index.js +2 -2
- package/dist/next/index.cjs +39 -34
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +2 -3
- package/dist/next/index.d.ts +2 -3
- package/dist/next/index.js +13 -8
- package/dist/next/index.js.map +1 -1
- package/dist/{types-DgVHS4Qw.d.ts → personalize-content-D6xeBI7-.d.cts} +150 -1
- package/dist/{types-DgVHS4Qw.d.cts → personalize-content-D6xeBI7-.d.ts} +150 -1
- package/dist/server/index.cjs +30 -30
- package/dist/server/index.d.cts +5 -6
- package/dist/server/index.d.ts +5 -6
- package/dist/server/index.js +5 -5
- package/dist/xenia-sdk.iife.js +3 -3
- package/dist/xenia-sdk.iife.js.map +1 -1
- package/dist/{xenia-server-Cf24mL0c.d.ts → xenia-server-BcgeUHX4.d.ts} +2 -3
- package/dist/{xenia-server-D-bx14lw.d.cts → xenia-server-lv6LtJZP.d.cts} +2 -3
- package/package.json +14 -1
- package/dist/chunk-2DR5AVPX.cjs.map +0 -1
- package/dist/chunk-BQ5PJCZ7.js +0 -179
- package/dist/chunk-BQ5PJCZ7.js.map +0 -1
- package/dist/chunk-GWRDZIVA.js.map +0 -1
- package/dist/chunk-LW5AEJ6K.js.map +0 -1
- package/dist/chunk-N5M4PI7C.cjs +0 -192
- package/dist/chunk-N5M4PI7C.cjs.map +0 -1
- package/dist/chunk-OMMIRSPK.js.map +0 -1
- package/dist/chunk-RWE2OCQL.cjs.map +0 -1
- package/dist/chunk-YLMMTKQL.cjs.map +0 -1
- package/dist/personalize-content-Cwc2AomC.d.ts +0 -141
- package/dist/personalize-content-CxSdplMV.d.cts +0 -141
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ElementType, ComponentType } from 'react';
|
|
3
|
-
import { E as XeniaClientOptions, D as XeniaClient, w as ResolveResult, u as ResolveBatchResult, J as JsonValue, x as WebhookResponse, R as ResolveBatchItem, g as AnalyticsEventName, T as TrackOptions, P as PagePersonalizeOptions, j as AppliedSwap, s as PageRef, e as XeniaAction, I as InteractionType, q as MessageMountContext, c as MessageComponentRenderer } from '../../actions
|
|
4
|
-
export { A as AnalyticsContext, h as AnalyticsIdentity, i as AnalyticsIngestResponse, k as ClientEvent, l as CmsAdapter, C as ConsentState, m as ContentSwap, n as IdentifyRequest, o as IdentifyResponse, M as MessageCta, f as MessagePlacement, r as MessageRenderContext, b as MessageTemplateFn, t as PersonalizationSwap, v as ResolveOptions, X as XeniaConfig, a as XeniaEvent, F as XeniaMarker, G as createXeniaClient, H as extractContentSwaps, K as parseActions, L as pendingTargets, N as personalizeContent, O as personalizePage, Q as spliceSlots } from '../../actions
|
|
3
|
+
import { E as XeniaClientOptions, D as XeniaClient, w as ResolveResult, u as ResolveBatchResult, J as JsonValue, x as WebhookResponse, R as ResolveBatchItem, g as AnalyticsEventName, T as TrackOptions, P as PagePersonalizeOptions, j as AppliedSwap, s as PageRef, e as XeniaAction, I as InteractionType, q as MessageMountContext, c as MessageComponentRenderer } from '../../actions--1_9Z8ig.cjs';
|
|
4
|
+
export { A as AnalyticsContext, h as AnalyticsIdentity, i as AnalyticsIngestResponse, k as ClientEvent, l as CmsAdapter, C as ConsentState, m as ContentSwap, n as IdentifyRequest, o as IdentifyResponse, M as MessageCta, f as MessagePlacement, r as MessageRenderContext, b as MessageTemplateFn, t as PersonalizationSwap, v as ResolveOptions, X as XeniaConfig, a as XeniaEvent, F as XeniaMarker, G as createXeniaClient, H as extractContentSwaps, K as parseActions, L as pendingTargets, N as personalizeContent, O as personalizePage, Q as spliceSlots } from '../../actions--1_9Z8ig.cjs';
|
|
5
5
|
|
|
6
6
|
interface XeniaProviderProps extends XeniaClientOptions {
|
|
7
7
|
children: ReactNode;
|
|
@@ -240,6 +240,12 @@ interface XeniaDebugPanelProps {
|
|
|
240
240
|
* or closes it, their choice wins for the rest of the session.
|
|
241
241
|
*/
|
|
242
242
|
defaultOpen?: boolean;
|
|
243
|
+
/**
|
|
244
|
+
* Start with the card pinned open: clicks elsewhere on the page and Escape leave it open, and only
|
|
245
|
+
* the Xenia launcher closes it. The card's pin button toggles this; the visitor's choice wins for the
|
|
246
|
+
* rest of the session. Default `false`.
|
|
247
|
+
*/
|
|
248
|
+
keepOpen?: boolean;
|
|
243
249
|
/**
|
|
244
250
|
* Content of your own for the Site tab, beyond `custom` (which the panel shows by itself), from
|
|
245
251
|
* the fields your proxy's `debugInfo` added.
|
|
@@ -255,7 +261,7 @@ declare function debugStatus(entry: DebugEntry): DebugStatus;
|
|
|
255
261
|
* site's own rows (`debugInfo`'s `custom`). Reads the debug cookie `xeniaEdgeProxy({ debug: true })`
|
|
256
262
|
* writes; renders nothing without an entry for this page.
|
|
257
263
|
*/
|
|
258
|
-
declare function XeniaDebugPanel({ prefix, position, defaultOpen, renderExtra }: XeniaDebugPanelProps): react.JSX.Element | null;
|
|
264
|
+
declare function XeniaDebugPanel({ prefix, position, defaultOpen, keepOpen, renderExtra, }: XeniaDebugPanelProps): react.JSX.Element | null;
|
|
259
265
|
|
|
260
266
|
export { AnalyticsEventName, AppliedSwap, InteractionType, JsonValue, MessageComponentRenderer, MessageMountContext, PagePersonalizeOptions, PageRef, ResolveBatchItem, ResolveBatchResult, ResolveResult, TrackOptions, WebhookResponse, XeniaAction, XeniaClient, XeniaClientOptions, XeniaContentProvider, XeniaContext, XeniaDebugPanel, XeniaMessage, XeniaProvider, XeniaTrack, debugStatus, reactMessageComponent, usePersonalization, usePersonalizationResolve, usePersonalizationResolveSlots, usePersonalizationSlots, usePersonalizedContent, usePersonalizedPage, useTrack, useWebhook, useXenia, useXeniaEntry, useXeniaResponse };
|
|
261
267
|
export type { DebugStatus, EntryStatus, UsePersonalizationResolveResult, UsePersonalizationResolveSlotsResult, UsePersonalizationResult, UsePersonalizationSlotsResult, UsePersonalizedContentOptions, UsePersonalizedContentResult, UseWebhookResult, XeniaDebugPanelProps, XeniaMessageComponentProps, XeniaMessageProps, XeniaProviderProps, XeniaTrackProps };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ElementType, ComponentType } from 'react';
|
|
3
|
-
import { E as XeniaClientOptions, D as XeniaClient, w as ResolveResult, u as ResolveBatchResult, J as JsonValue, x as WebhookResponse, R as ResolveBatchItem, g as AnalyticsEventName, T as TrackOptions, P as PagePersonalizeOptions, j as AppliedSwap, s as PageRef, e as XeniaAction, I as InteractionType, q as MessageMountContext, c as MessageComponentRenderer } from '../../actions
|
|
4
|
-
export { A as AnalyticsContext, h as AnalyticsIdentity, i as AnalyticsIngestResponse, k as ClientEvent, l as CmsAdapter, C as ConsentState, m as ContentSwap, n as IdentifyRequest, o as IdentifyResponse, M as MessageCta, f as MessagePlacement, r as MessageRenderContext, b as MessageTemplateFn, t as PersonalizationSwap, v as ResolveOptions, X as XeniaConfig, a as XeniaEvent, F as XeniaMarker, G as createXeniaClient, H as extractContentSwaps, K as parseActions, L as pendingTargets, N as personalizeContent, O as personalizePage, Q as spliceSlots } from '../../actions
|
|
3
|
+
import { E as XeniaClientOptions, D as XeniaClient, w as ResolveResult, u as ResolveBatchResult, J as JsonValue, x as WebhookResponse, R as ResolveBatchItem, g as AnalyticsEventName, T as TrackOptions, P as PagePersonalizeOptions, j as AppliedSwap, s as PageRef, e as XeniaAction, I as InteractionType, q as MessageMountContext, c as MessageComponentRenderer } from '../../actions--1_9Z8ig.js';
|
|
4
|
+
export { A as AnalyticsContext, h as AnalyticsIdentity, i as AnalyticsIngestResponse, k as ClientEvent, l as CmsAdapter, C as ConsentState, m as ContentSwap, n as IdentifyRequest, o as IdentifyResponse, M as MessageCta, f as MessagePlacement, r as MessageRenderContext, b as MessageTemplateFn, t as PersonalizationSwap, v as ResolveOptions, X as XeniaConfig, a as XeniaEvent, F as XeniaMarker, G as createXeniaClient, H as extractContentSwaps, K as parseActions, L as pendingTargets, N as personalizeContent, O as personalizePage, Q as spliceSlots } from '../../actions--1_9Z8ig.js';
|
|
5
5
|
|
|
6
6
|
interface XeniaProviderProps extends XeniaClientOptions {
|
|
7
7
|
children: ReactNode;
|
|
@@ -240,6 +240,12 @@ interface XeniaDebugPanelProps {
|
|
|
240
240
|
* or closes it, their choice wins for the rest of the session.
|
|
241
241
|
*/
|
|
242
242
|
defaultOpen?: boolean;
|
|
243
|
+
/**
|
|
244
|
+
* Start with the card pinned open: clicks elsewhere on the page and Escape leave it open, and only
|
|
245
|
+
* the Xenia launcher closes it. The card's pin button toggles this; the visitor's choice wins for the
|
|
246
|
+
* rest of the session. Default `false`.
|
|
247
|
+
*/
|
|
248
|
+
keepOpen?: boolean;
|
|
243
249
|
/**
|
|
244
250
|
* Content of your own for the Site tab, beyond `custom` (which the panel shows by itself), from
|
|
245
251
|
* the fields your proxy's `debugInfo` added.
|
|
@@ -255,7 +261,7 @@ declare function debugStatus(entry: DebugEntry): DebugStatus;
|
|
|
255
261
|
* site's own rows (`debugInfo`'s `custom`). Reads the debug cookie `xeniaEdgeProxy({ debug: true })`
|
|
256
262
|
* writes; renders nothing without an entry for this page.
|
|
257
263
|
*/
|
|
258
|
-
declare function XeniaDebugPanel({ prefix, position, defaultOpen, renderExtra }: XeniaDebugPanelProps): react.JSX.Element | null;
|
|
264
|
+
declare function XeniaDebugPanel({ prefix, position, defaultOpen, keepOpen, renderExtra, }: XeniaDebugPanelProps): react.JSX.Element | null;
|
|
259
265
|
|
|
260
266
|
export { AnalyticsEventName, AppliedSwap, InteractionType, JsonValue, MessageComponentRenderer, MessageMountContext, PagePersonalizeOptions, PageRef, ResolveBatchItem, ResolveBatchResult, ResolveResult, TrackOptions, WebhookResponse, XeniaAction, XeniaClient, XeniaClientOptions, XeniaContentProvider, XeniaContext, XeniaDebugPanel, XeniaMessage, XeniaProvider, XeniaTrack, debugStatus, reactMessageComponent, usePersonalization, usePersonalizationResolve, usePersonalizationResolveSlots, usePersonalizationSlots, usePersonalizedContent, usePersonalizedPage, useTrack, useWebhook, useXenia, useXeniaEntry, useXeniaResponse };
|
|
261
267
|
export type { DebugStatus, EntryStatus, UsePersonalizationResolveResult, UsePersonalizationResolveSlotsResult, UsePersonalizationResult, UsePersonalizationSlotsResult, UsePersonalizedContentOptions, UsePersonalizedContentResult, UseWebhookResult, XeniaDebugPanelProps, XeniaMessageComponentProps, XeniaMessageProps, XeniaProviderProps, XeniaTrackProps };
|
|
@@ -720,7 +720,7 @@ async function personalizeContent(payload, options) {
|
|
|
720
720
|
const next = apply(target, op, d.decision.field ?? target.marker.field, items, cms);
|
|
721
721
|
report({
|
|
722
722
|
target: target.id,
|
|
723
|
-
kind: "runtime",
|
|
723
|
+
kind: target.local ? "static" : "runtime",
|
|
724
724
|
op,
|
|
725
725
|
entryIds: items.map((e) => cms.entryId(e)).filter((id) => !!id),
|
|
726
726
|
contentKey: d.decision.contentKey,
|
|
@@ -730,20 +730,23 @@ async function personalizeContent(payload, options) {
|
|
|
730
730
|
return next;
|
|
731
731
|
};
|
|
732
732
|
for (let round = 0; ; round++) {
|
|
733
|
-
const pending = walk(frontier, cms, settled, round, report, (t) => {
|
|
733
|
+
const pending = walk(frontier, cms, settled, round, report, options.contentKey, (t) => {
|
|
734
734
|
const d = decided.get(t.id);
|
|
735
735
|
return d ? settle(t, d, round) : void 0;
|
|
736
736
|
});
|
|
737
737
|
if (pending.size === 0) return { content: box.root, applied, complete: true };
|
|
738
|
-
|
|
739
|
-
|
|
738
|
+
const remote = [...pending.values()].filter((p) => !p.local).map((p) => p.id);
|
|
739
|
+
const local = [...pending.values()].flatMap((p) => p.local ? [p.local] : []);
|
|
740
|
+
if (!options.resolve && local.length === 0 || round >= maxRounds) {
|
|
741
|
+
return { content: box.root, applied, complete: !options.resolve && round < maxRounds };
|
|
740
742
|
}
|
|
741
743
|
progress(options, { content: box.root, round, pending: [...pending.keys()] });
|
|
742
744
|
let decisions;
|
|
743
745
|
let entriesById;
|
|
744
746
|
let queried;
|
|
745
747
|
try {
|
|
746
|
-
decisions = await withDeadline(options.resolve(
|
|
748
|
+
decisions = options.resolve && remote.length > 0 ? await withDeadline(options.resolve(remote), deadline) : [];
|
|
749
|
+
decisions = [...decisions, ...local];
|
|
747
750
|
({ entriesById, queried } = await withDeadline(loadReplacements(decisions, cms, options.locale), deadline));
|
|
748
751
|
} catch (error) {
|
|
749
752
|
return { content: box.root, applied, complete: false, error: error === TIMEOUT ? void 0 : error };
|
|
@@ -766,7 +769,7 @@ function progress(options, p) {
|
|
|
766
769
|
} catch {
|
|
767
770
|
}
|
|
768
771
|
}
|
|
769
|
-
function walk(frontier, cms, settled, round, report, reuse) {
|
|
772
|
+
function walk(frontier, cms, settled, round, report, contentKey, reuse) {
|
|
770
773
|
const pending = /* @__PURE__ */ new Map();
|
|
771
774
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
772
775
|
const deferred = /* @__PURE__ */ new WeakSet();
|
|
@@ -777,7 +780,8 @@ function walk(frontier, cms, settled, round, report, reuse) {
|
|
|
777
780
|
if (!value || typeof value !== "object" || deferred.has(value)) continue;
|
|
778
781
|
const id = settled.has(value) ? void 0 : cms.entryId(value);
|
|
779
782
|
const marker = id ? cms.marker(value) : null;
|
|
780
|
-
|
|
783
|
+
const local = id && marker?.kind === "static" && marker.ids?.length && cms.staticVariants(value).length === 0 ? localDecision(id, marker, contentKey) : void 0;
|
|
784
|
+
if (id && marker && (marker.kind === "runtime" || local)) {
|
|
781
785
|
const again = reuse({ id, marker, entry: value, slots: [slot] });
|
|
782
786
|
if (again) {
|
|
783
787
|
queue.push(...again);
|
|
@@ -787,7 +791,7 @@ function walk(frontier, cms, settled, round, report, reuse) {
|
|
|
787
791
|
if (existing) {
|
|
788
792
|
existing.slots.push(slot);
|
|
789
793
|
} else {
|
|
790
|
-
pending.set(id, { id, marker, entry: value, slots: [slot] });
|
|
794
|
+
pending.set(id, { id, marker, entry: value, slots: [slot], ...local ? { local } : {} });
|
|
791
795
|
if (marker.op === "items" && marker.field) {
|
|
792
796
|
const held = cms.getField(value, marker.field);
|
|
793
797
|
if (held && typeof held === "object") deferred.add(held);
|
|
@@ -821,6 +825,16 @@ function walk(frontier, cms, settled, round, report, reuse) {
|
|
|
821
825
|
}
|
|
822
826
|
return pending;
|
|
823
827
|
}
|
|
828
|
+
function localDecision(id, marker, contentKey) {
|
|
829
|
+
return {
|
|
830
|
+
target: id,
|
|
831
|
+
op: marker.op ?? "replace",
|
|
832
|
+
...marker.field ? { field: marker.field } : {},
|
|
833
|
+
ids: marker.ids,
|
|
834
|
+
...marker.ct ? { contentType: marker.ct } : {},
|
|
835
|
+
contentKey
|
|
836
|
+
};
|
|
837
|
+
}
|
|
824
838
|
function apply(target, op, field, items, cms) {
|
|
825
839
|
if (op === "items") {
|
|
826
840
|
if (field) {
|
|
@@ -859,9 +873,11 @@ function children(value) {
|
|
|
859
873
|
}
|
|
860
874
|
async function loadReplacements(decisions, cms, locale) {
|
|
861
875
|
const ids = [...new Set(decisions.flatMap((d) => d.ids ?? []))];
|
|
876
|
+
const types = {};
|
|
877
|
+
for (const d of decisions) if (d.contentType) for (const id of d.ids ?? []) types[id] = d.contentType;
|
|
862
878
|
const queries = decisions.filter((d) => !d.ids && d.query);
|
|
863
879
|
const [fetched, ...results] = await Promise.all([
|
|
864
|
-
ids.length > 0 ? cms.fetchEntries(ids, locale) : Promise.resolve([]),
|
|
880
|
+
ids.length > 0 ? cms.fetchEntries(ids, locale, types) : Promise.resolve([]),
|
|
865
881
|
...queries.map((d) => cms.queryEntries(d.query, locale).catch(() => []))
|
|
866
882
|
]);
|
|
867
883
|
const entriesById = /* @__PURE__ */ new Map();
|
|
@@ -892,7 +908,7 @@ function pendingTargets(payload, adapter, contentKey) {
|
|
|
892
908
|
content = cms.prepare ? cms.prepare(content) : content;
|
|
893
909
|
const root = { parent: { root: content }, key: "root", value: content };
|
|
894
910
|
return [...walk([root], cms, /* @__PURE__ */ new WeakSet(), 0, () => {
|
|
895
|
-
}, () => void 0).keys()];
|
|
911
|
+
}, contentKey, () => void 0).keys()];
|
|
896
912
|
} catch {
|
|
897
913
|
return [];
|
|
898
914
|
}
|
|
@@ -3330,6 +3346,7 @@ function readEntry(prefix) {
|
|
|
3330
3346
|
return readDebugEntries(raw)[location.pathname] ?? null;
|
|
3331
3347
|
}
|
|
3332
3348
|
var OPEN_KEY = "xenia_debug_open";
|
|
3349
|
+
var PIN_KEY = "xenia_debug_pinned";
|
|
3333
3350
|
var TAB_KEY = "xenia_debug_tab";
|
|
3334
3351
|
function Mark({ size }) {
|
|
3335
3352
|
return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 32 20", "aria-hidden": "true", focusable: "false", children: [
|
|
@@ -3344,9 +3361,16 @@ function Id({ value }) {
|
|
|
3344
3361
|
] }) : /* @__PURE__ */ jsx(Fragment, { children: value });
|
|
3345
3362
|
}
|
|
3346
3363
|
var percent = (n) => `${Math.round(n <= 1 ? n * 100 : n)}%`;
|
|
3347
|
-
function XeniaDebugPanel({
|
|
3364
|
+
function XeniaDebugPanel({
|
|
3365
|
+
prefix = DEFAULT_PREFIX,
|
|
3366
|
+
position = "bottom-right",
|
|
3367
|
+
defaultOpen = false,
|
|
3368
|
+
keepOpen = false,
|
|
3369
|
+
renderExtra
|
|
3370
|
+
}) {
|
|
3348
3371
|
const [entry, setEntry] = useState(null);
|
|
3349
3372
|
const [open, setOpen] = useState(false);
|
|
3373
|
+
const [pinned, setPinned] = useState(keepOpen);
|
|
3350
3374
|
const [tab, setTab] = useState("Decision");
|
|
3351
3375
|
const root = useRef(null);
|
|
3352
3376
|
const launcher = useRef(null);
|
|
@@ -3366,31 +3390,39 @@ function XeniaDebugPanel({ prefix = DEFAULT_PREFIX, position = "bottom-right", d
|
|
|
3366
3390
|
try {
|
|
3367
3391
|
const saved = sessionStorage.getItem(OPEN_KEY);
|
|
3368
3392
|
setOpen(saved === null ? defaultOpen : saved === "1");
|
|
3393
|
+
const savedPin = sessionStorage.getItem(PIN_KEY);
|
|
3394
|
+
setPinned(savedPin === null ? keepOpen : savedPin === "1");
|
|
3369
3395
|
const savedTab = sessionStorage.getItem(TAB_KEY);
|
|
3370
3396
|
if (savedTab === "Decision" || savedTab === "Visitor" || savedTab === "Request" || savedTab === "Site") setTab(savedTab);
|
|
3371
3397
|
} catch {
|
|
3372
3398
|
setOpen(defaultOpen);
|
|
3399
|
+
setPinned(keepOpen);
|
|
3373
3400
|
}
|
|
3374
3401
|
const unwatch = watchNavigation(onNavigate);
|
|
3375
3402
|
return () => {
|
|
3376
3403
|
clearTimeout(timer);
|
|
3377
3404
|
unwatch();
|
|
3378
3405
|
};
|
|
3379
|
-
}, [prefix, defaultOpen]);
|
|
3406
|
+
}, [prefix, defaultOpen, keepOpen]);
|
|
3380
3407
|
const toggle = useCallback((next, focusLauncher = false) => {
|
|
3381
3408
|
setOpen(next);
|
|
3382
3409
|
focusOnOpen.current = next;
|
|
3383
3410
|
if (focusLauncher) launcher.current?.focus();
|
|
3384
3411
|
remember(OPEN_KEY, next ? "1" : "0");
|
|
3385
3412
|
}, []);
|
|
3413
|
+
const pin = (next) => {
|
|
3414
|
+
setPinned(next);
|
|
3415
|
+
remember(PIN_KEY, next ? "1" : "0");
|
|
3416
|
+
};
|
|
3386
3417
|
useEffect(() => {
|
|
3387
3418
|
if (!open) return;
|
|
3388
3419
|
if (focusOnOpen.current) card.current?.focus();
|
|
3420
|
+
if (pinned) return;
|
|
3389
3421
|
const onKey = (e) => {
|
|
3390
3422
|
if (e.key === "Escape" && root.current?.contains(document.activeElement)) toggle(false, true);
|
|
3391
3423
|
};
|
|
3392
3424
|
const onDown = (e) => {
|
|
3393
|
-
if (root.current && !root.current.contains(e.target))
|
|
3425
|
+
if (root.current && !root.current.contains(e.target)) setOpen(false);
|
|
3394
3426
|
};
|
|
3395
3427
|
document.addEventListener("keydown", onKey);
|
|
3396
3428
|
document.addEventListener("mousedown", onDown);
|
|
@@ -3398,7 +3430,7 @@ function XeniaDebugPanel({ prefix = DEFAULT_PREFIX, position = "bottom-right", d
|
|
|
3398
3430
|
document.removeEventListener("keydown", onKey);
|
|
3399
3431
|
document.removeEventListener("mousedown", onDown);
|
|
3400
3432
|
};
|
|
3401
|
-
}, [open, toggle]);
|
|
3433
|
+
}, [open, pinned, toggle]);
|
|
3402
3434
|
if (!entry) return null;
|
|
3403
3435
|
const status = debugStatus(entry);
|
|
3404
3436
|
const v = view(entry);
|
|
@@ -3443,7 +3475,28 @@ function XeniaDebugPanel({ prefix = DEFAULT_PREFIX, position = "bottom-right", d
|
|
|
3443
3475
|
typeof v.ms === "number" && v.source === "xenia" ? /* @__PURE__ */ jsxs("span", { className: "xdp-ms", children: [
|
|
3444
3476
|
v.ms,
|
|
3445
3477
|
" ms"
|
|
3446
|
-
] }) : null
|
|
3478
|
+
] }) : null,
|
|
3479
|
+
/* @__PURE__ */ jsx(
|
|
3480
|
+
"button",
|
|
3481
|
+
{
|
|
3482
|
+
type: "button",
|
|
3483
|
+
className: "xdp-pin",
|
|
3484
|
+
"aria-pressed": pinned,
|
|
3485
|
+
"aria-label": "Keep open",
|
|
3486
|
+
title: pinned ? "Pinned: only the Xenia button closes this" : "Keep open: clicks elsewhere won't close it",
|
|
3487
|
+
onClick: () => pin(!pinned),
|
|
3488
|
+
children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx(
|
|
3489
|
+
"path",
|
|
3490
|
+
{
|
|
3491
|
+
d: "M15 3l6 6-3 1-4 4 1 5-2 2-4-4-5 5-1-1 5-5-4-4 2-2 5 1 4-4z",
|
|
3492
|
+
fill: pinned ? "currentColor" : "none",
|
|
3493
|
+
stroke: "currentColor",
|
|
3494
|
+
strokeWidth: "1.8",
|
|
3495
|
+
strokeLinejoin: "round"
|
|
3496
|
+
}
|
|
3497
|
+
) })
|
|
3498
|
+
}
|
|
3499
|
+
)
|
|
3447
3500
|
] }),
|
|
3448
3501
|
/* @__PURE__ */ jsx("code", { className: "xdp-path", title: v.page, children: v.page }),
|
|
3449
3502
|
status === "attention" ? /* @__PURE__ */ jsx("p", { className: "xdp-alert", children: v.source === "timeout" ? "Xenia didn't answer within the time budget." : "The decision failed; the proxy's onError has the cause." }) : null
|
|
@@ -3612,6 +3665,11 @@ var STYLES2 = `
|
|
|
3612
3665
|
code.xdp-chip{font-size:11.5px}
|
|
3613
3666
|
.xdp-chip[data-tone=holdout]{background:var(--xdp-warn-tint);color:var(--xdp-warn);font-weight:600}
|
|
3614
3667
|
.xdp-ms{margin-left:auto;color:var(--xdp-faint)}
|
|
3668
|
+
.xdp-pin{margin-left:auto;width:26px;height:26px;display:grid;place-items:center;border:0;border-radius:7px;background:transparent;color:var(--xdp-faint);cursor:pointer}
|
|
3669
|
+
.xdp-ms + .xdp-pin{margin-left:4px}
|
|
3670
|
+
.xdp-pin:hover{background:var(--xdp-soft);color:var(--xdp-muted)}
|
|
3671
|
+
.xdp-pin[aria-pressed=true]{color:var(--xdp-blue);background:var(--xdp-soft)}
|
|
3672
|
+
.xdp-pin:focus-visible{outline:2px solid var(--xdp-blue);outline-offset:1px}
|
|
3615
3673
|
.xdp-path{display:block;margin-top:8px;font-size:13px;color:var(--xdp-ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
3616
3674
|
.xdp-alert{margin:8px 0 0;padding:8px 10px;border-radius:8px;background:var(--xdp-warn-tint);color:var(--xdp-warn)}
|
|
3617
3675
|
.xdp-tabs{display:flex;gap:4px;padding:0 12px;border-bottom:1px solid var(--xdp-border)}
|