pxengine 0.1.107 → 0.1.109

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/dist/index.mjs CHANGED
@@ -3130,7 +3130,7 @@ __export(lucide_react_exports, {
3130
3130
  LucideMailX: () => MailX,
3131
3131
  LucideMailbox: () => Mailbox,
3132
3132
  LucideMails: () => Mails,
3133
- LucideMap: () => Map,
3133
+ LucideMap: () => Map2,
3134
3134
  LucideMapPin: () => MapPin,
3135
3135
  LucideMapPinCheck: () => MapPinCheck,
3136
3136
  LucideMapPinCheckInside: () => MapPinCheckInside,
@@ -3922,8 +3922,8 @@ __export(lucide_react_exports, {
3922
3922
  MailboxIcon: () => Mailbox,
3923
3923
  Mails: () => Mails,
3924
3924
  MailsIcon: () => Mails,
3925
- Map: () => Map,
3926
- MapIcon: () => Map,
3925
+ Map: () => Map2,
3926
+ MapIcon: () => Map2,
3927
3927
  MapPin: () => MapPin,
3928
3928
  MapPinCheck: () => MapPinCheck,
3929
3929
  MapPinCheckIcon: () => MapPinCheck,
@@ -6334,7 +6334,7 @@ __export(icons_exports, {
6334
6334
  MailX: () => MailX,
6335
6335
  Mailbox: () => Mailbox,
6336
6336
  Mails: () => Mails,
6337
- Map: () => Map,
6337
+ Map: () => Map2,
6338
6338
  MapPin: () => MapPin,
6339
6339
  MapPinCheck: () => MapPinCheck,
6340
6340
  MapPinCheckInside: () => MapPinCheckInside,
@@ -17149,7 +17149,7 @@ var __iconNode891 = [
17149
17149
  ["path", { d: "M15 5.764v15", key: "1pn4in" }],
17150
17150
  ["path", { d: "M9 3.236v15", key: "1uimfh" }]
17151
17151
  ];
17152
- var Map = createLucideIcon("Map", __iconNode891);
17152
+ var Map2 = createLucideIcon("Map", __iconNode891);
17153
17153
 
17154
17154
  // node_modules/lucide-react/dist/esm/icons/mars-stroke.js
17155
17155
  var __iconNode892 = [
@@ -33164,7 +33164,7 @@ var ChartTooltipContent = React80.forwardRef(
33164
33164
  )
33165
33165
  ] })
33166
33166
  },
33167
- item.dataKey
33167
+ `${item.dataKey ?? index}`
33168
33168
  );
33169
33169
  }) })
33170
33170
  ]
@@ -38853,7 +38853,128 @@ var NextStepCard = ({
38853
38853
  };
38854
38854
 
38855
38855
  // src/molecules/generic/PresentationJobCard/PresentationJobCard.tsx
38856
- import { useCallback as useCallback4, useEffect as useEffect6, useRef as useRef5, useState as useState10 } from "react";
38856
+ import { useCallback as useCallback4, useEffect as useEffect7, useRef as useRef6, useState as useState10 } from "react";
38857
+
38858
+ // src/lib/shared-poll.ts
38859
+ import { useEffect as useEffect6, useRef as useRef5 } from "react";
38860
+ var entries = /* @__PURE__ */ new Map();
38861
+ function clearTimer(entry) {
38862
+ if (entry.timer !== null) {
38863
+ clearInterval(entry.timer);
38864
+ entry.timer = null;
38865
+ }
38866
+ entry.controller?.abort();
38867
+ entry.controller = null;
38868
+ }
38869
+ async function runPoll(key) {
38870
+ const entry = entries.get(key);
38871
+ if (!entry || entry.inFlight || entry.stopped) return;
38872
+ entry.inFlight = true;
38873
+ const controller = new AbortController();
38874
+ entry.controller = controller;
38875
+ try {
38876
+ const data = await entry.fetcher(controller.signal);
38877
+ if (entries.get(key) !== entry) return;
38878
+ entry.lastData = data;
38879
+ entry.hasData = true;
38880
+ for (const listener of Array.from(entry.dataListeners)) {
38881
+ try {
38882
+ listener(data);
38883
+ } catch {
38884
+ }
38885
+ }
38886
+ if (!entry.shouldContinue(data)) {
38887
+ entry.stopped = true;
38888
+ clearTimer(entry);
38889
+ }
38890
+ } catch (error) {
38891
+ if (entries.get(key) !== entry) return;
38892
+ for (const listener of Array.from(entry.errorListeners)) {
38893
+ try {
38894
+ listener(error);
38895
+ } catch {
38896
+ }
38897
+ }
38898
+ } finally {
38899
+ entry.inFlight = false;
38900
+ }
38901
+ }
38902
+ function subscribeSharedPoll(config, onData, onError) {
38903
+ const { key, intervalMs, fetcher, shouldContinue } = config;
38904
+ if (!key) return () => {
38905
+ };
38906
+ let entry = entries.get(key);
38907
+ if (!entry) {
38908
+ entry = {
38909
+ intervalMs,
38910
+ fetcher,
38911
+ shouldContinue: shouldContinue ?? (() => true),
38912
+ dataListeners: /* @__PURE__ */ new Set(),
38913
+ errorListeners: /* @__PURE__ */ new Set(),
38914
+ timer: null,
38915
+ controller: null,
38916
+ lastData: void 0,
38917
+ hasData: false,
38918
+ stopped: false,
38919
+ inFlight: false
38920
+ };
38921
+ entries.set(key, entry);
38922
+ }
38923
+ const activeEntry = entry;
38924
+ activeEntry.dataListeners.add(onData);
38925
+ if (onError) activeEntry.errorListeners.add(onError);
38926
+ if (activeEntry.hasData && activeEntry.lastData !== void 0) {
38927
+ try {
38928
+ onData(activeEntry.lastData);
38929
+ } catch {
38930
+ }
38931
+ }
38932
+ if (!activeEntry.stopped && activeEntry.timer === null) {
38933
+ void runPoll(key);
38934
+ activeEntry.timer = setInterval(() => void runPoll(key), activeEntry.intervalMs);
38935
+ }
38936
+ return () => {
38937
+ activeEntry.dataListeners.delete(onData);
38938
+ if (onError) activeEntry.errorListeners.delete(onError);
38939
+ if (activeEntry.dataListeners.size === 0 && activeEntry.errorListeners.size === 0) {
38940
+ clearTimer(activeEntry);
38941
+ entries.delete(key);
38942
+ }
38943
+ };
38944
+ }
38945
+ function stopSharedPoll(key) {
38946
+ const entry = entries.get(key);
38947
+ if (!entry) return;
38948
+ entry.stopped = true;
38949
+ clearTimer(entry);
38950
+ }
38951
+ function useSharedPoll(config, onData, onError) {
38952
+ const fetcherRef = useRef5(config.fetcher);
38953
+ fetcherRef.current = config.fetcher;
38954
+ const shouldContinueRef = useRef5(config.shouldContinue);
38955
+ shouldContinueRef.current = config.shouldContinue;
38956
+ const onDataRef = useRef5(onData);
38957
+ onDataRef.current = onData;
38958
+ const onErrorRef = useRef5(onError);
38959
+ onErrorRef.current = onError;
38960
+ const { key, intervalMs } = config;
38961
+ useEffect6(() => {
38962
+ if (!key) return;
38963
+ const unsubscribe = subscribeSharedPoll(
38964
+ {
38965
+ key,
38966
+ intervalMs,
38967
+ fetcher: (signal) => fetcherRef.current(signal),
38968
+ shouldContinue: (data) => shouldContinueRef.current ? shouldContinueRef.current(data) : true
38969
+ },
38970
+ (data) => onDataRef.current(data),
38971
+ (error) => onErrorRef.current?.(error)
38972
+ );
38973
+ return unsubscribe;
38974
+ }, [key, intervalMs]);
38975
+ }
38976
+
38977
+ // src/molecules/generic/PresentationJobCard/PresentationJobCard.tsx
38857
38978
  import { Fragment as Fragment5, jsx as jsx147, jsxs as jsxs108 } from "react/jsx-runtime";
38858
38979
  var DownloadIcon = () => /* @__PURE__ */ jsxs108("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
38859
38980
  /* @__PURE__ */ jsx147("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
@@ -38980,8 +39101,8 @@ var ExportModal = ({ formats, title, onClose }) => {
38980
39101
  var FullscreenModal = ({ url, title, slideCount, initialSlide = 1, onClose }) => {
38981
39102
  const [currentSlide, setCurrentSlide] = useState10(initialSlide);
38982
39103
  const [iframeReady, setIframeReady] = useState10(false);
38983
- const iframeRef = useRef5(null);
38984
- useEffect6(() => {
39104
+ const iframeRef = useRef6(null);
39105
+ useEffect7(() => {
38985
39106
  const onKey = (e) => {
38986
39107
  if (e.key === "Escape") onClose();
38987
39108
  };
@@ -38999,7 +39120,7 @@ var FullscreenModal = ({ url, title, slideCount, initialSlide = 1, onClose }) =>
38999
39120
  window.removeEventListener("message", onMsg);
39000
39121
  };
39001
39122
  }, [onClose, iframeReady]);
39002
- useEffect6(() => {
39123
+ useEffect7(() => {
39003
39124
  document.body.style.overflow = "hidden";
39004
39125
  return () => {
39005
39126
  document.body.style.overflow = "";
@@ -39110,34 +39231,33 @@ var PresentationJobCard = ({
39110
39231
  const [currentSlide, setCurrentSlide] = useState10(1);
39111
39232
  const [previewScale, setPreviewScale] = useState10(1);
39112
39233
  const [iframeReady, setIframeReady] = useState10(false);
39113
- const intervalRef = useRef5(null);
39114
- const previewRef = useRef5(null);
39115
- const iframeRef = useRef5(null);
39116
- useEffect6(() => {
39234
+ const previewRef = useRef6(null);
39235
+ const iframeRef = useRef6(null);
39236
+ useEffect7(() => {
39117
39237
  setStatus(initialStatus);
39118
39238
  }, [initialStatus]);
39119
39239
  const progressPct = initialProgress?.percentage;
39120
39240
  const progressStep = initialProgress?.current_step;
39121
- useEffect6(() => {
39241
+ useEffect7(() => {
39122
39242
  if (initialProgress) setProgress(initialProgress);
39123
39243
  }, [progressPct, progressStep]);
39124
- useEffect6(() => {
39244
+ useEffect7(() => {
39125
39245
  if (initialError) setError(initialError);
39126
39246
  }, [initialError]);
39127
- useEffect6(() => {
39247
+ useEffect7(() => {
39128
39248
  if (initialSlideCount !== void 0) setSlideCount(initialSlideCount);
39129
39249
  }, [initialSlideCount]);
39130
39250
  const htmlUrl = initialFormats?.html_url;
39131
- useEffect6(() => {
39251
+ useEffect7(() => {
39132
39252
  if (initialFormats) setFormats(initialFormats);
39133
39253
  }, [htmlUrl]);
39134
- useEffect6(() => {
39254
+ useEffect7(() => {
39135
39255
  if (initialTitle) setTitle(initialTitle);
39136
39256
  }, [initialTitle]);
39137
39257
  const updateScale = useCallback4(() => {
39138
39258
  if (previewRef.current) setPreviewScale(previewRef.current.offsetWidth / 1280);
39139
39259
  }, []);
39140
- useEffect6(() => {
39260
+ useEffect7(() => {
39141
39261
  updateScale();
39142
39262
  setIframeReady(false);
39143
39263
  if (typeof ResizeObserver === "undefined") return;
@@ -39145,7 +39265,7 @@ var PresentationJobCard = ({
39145
39265
  if (previewRef.current) ro.observe(previewRef.current);
39146
39266
  return () => ro.disconnect();
39147
39267
  }, [updateScale, formats.html_url]);
39148
- useEffect6(() => {
39268
+ useEffect7(() => {
39149
39269
  const handler = (e) => {
39150
39270
  if (e.data?.type === "slideChanged") {
39151
39271
  setCurrentSlide(e.data.slide);
@@ -39170,66 +39290,59 @@ var PresentationJobCard = ({
39170
39290
  iframe.contentWindow.postMessage({ type: command }, "*");
39171
39291
  };
39172
39292
  const isTerminal = status === "complete" || status === "failed";
39173
- const onCompleteRef = useRef5(onComplete);
39174
- const onFailedRef = useRef5(onFailed);
39175
- const hasNotifiedRef = useRef5(false);
39293
+ const onCompleteRef = useRef6(onComplete);
39294
+ const onFailedRef = useRef6(onFailed);
39295
+ const hasNotifiedRef = useRef6(false);
39176
39296
  onCompleteRef.current = onComplete;
39177
39297
  onFailedRef.current = onFailed;
39178
- useEffect6(() => {
39179
- if (isTerminal || !pollUrl) return;
39180
- const poll = async () => {
39181
- try {
39298
+ useSharedPoll(
39299
+ {
39300
+ key: !isTerminal && pollUrl ? pollUrl : null,
39301
+ intervalMs: 3e3,
39302
+ fetcher: async () => {
39182
39303
  const headers = {};
39183
39304
  if (authToken) {
39184
39305
  headers["Authorization"] = `Bearer ${authToken}`;
39185
39306
  }
39186
39307
  const res = await fetch(pollUrl, { headers });
39187
- if (!res.ok) return;
39188
- const data = await res.json();
39189
- const newStatus = data.status;
39190
- setStatus(newStatus);
39191
- if (data.progress) {
39192
- setProgress(data.progress);
39193
- }
39194
- if (newStatus === "complete" && data.output) {
39195
- const newTitle = data.output.title || initialTitle;
39196
- const newSlideCount = data.output.slide_count || 0;
39197
- const newFormats = data.output.formats || {};
39198
- setTitle(newTitle);
39199
- setSlideCount(newSlideCount);
39200
- setFormats(newFormats);
39201
- if (!hasNotifiedRef.current && onCompleteRef.current) {
39202
- hasNotifiedRef.current = true;
39203
- onCompleteRef.current({
39204
- title: newTitle,
39205
- slide_count: newSlideCount,
39206
- formats: newFormats
39207
- });
39208
- }
39308
+ if (!res.ok) throw new Error(`poll ${res.status}`);
39309
+ return res.json();
39310
+ },
39311
+ shouldContinue: (data) => data.status !== "complete" && data.status !== "failed"
39312
+ },
39313
+ (data) => {
39314
+ const newStatus = data.status;
39315
+ setStatus(newStatus);
39316
+ if (data.progress) {
39317
+ setProgress(data.progress);
39318
+ }
39319
+ if (newStatus === "complete" && data.output) {
39320
+ const newTitle = data.output.title || initialTitle;
39321
+ const newSlideCount = data.output.slide_count || 0;
39322
+ const newFormats = data.output.formats || {};
39323
+ setTitle(newTitle);
39324
+ setSlideCount(newSlideCount);
39325
+ setFormats(newFormats);
39326
+ if (!hasNotifiedRef.current && onCompleteRef.current) {
39327
+ hasNotifiedRef.current = true;
39328
+ onCompleteRef.current({
39329
+ title: newTitle,
39330
+ slide_count: newSlideCount,
39331
+ formats: newFormats
39332
+ });
39209
39333
  }
39210
- if (newStatus === "failed") {
39211
- const errorMsg = data.error || "Job failed";
39212
- setError(errorMsg);
39213
- if (!hasNotifiedRef.current && onFailedRef.current) {
39214
- hasNotifiedRef.current = true;
39215
- onFailedRef.current(errorMsg);
39216
- }
39334
+ }
39335
+ if (newStatus === "failed") {
39336
+ const errorMsg = data.error || "Job failed";
39337
+ setError(errorMsg);
39338
+ if (!hasNotifiedRef.current && onFailedRef.current) {
39339
+ hasNotifiedRef.current = true;
39340
+ onFailedRef.current(errorMsg);
39217
39341
  }
39218
- } catch {
39219
39342
  }
39220
- };
39221
- poll();
39222
- intervalRef.current = setInterval(poll, 3e3);
39223
- return () => {
39224
- if (intervalRef.current) clearInterval(intervalRef.current);
39225
- };
39226
- }, [isTerminal, pollUrl, authToken, initialTitle]);
39227
- useEffect6(() => {
39228
- if (isTerminal && intervalRef.current) {
39229
- clearInterval(intervalRef.current);
39230
- intervalRef.current = null;
39231
39343
  }
39232
- }, [isTerminal]);
39344
+ // Transient fetch errors are ignored — the shared loop retries next tick.
39345
+ );
39233
39346
  const handleShare = async () => {
39234
39347
  const link = shareUrl ?? (typeof window !== "undefined" && _job_id ? `${window.location.origin}/p/${_job_id}` : formats.html_url);
39235
39348
  if (!link) return;
@@ -39501,7 +39614,7 @@ var PresentationJobCard = ({
39501
39614
  };
39502
39615
 
39503
39616
  // src/molecules/generic/ResearchReportJobCard/ResearchReportJobCard.tsx
39504
- import { useCallback as useCallback5, useEffect as useEffect7, useRef as useRef6, useState as useState11 } from "react";
39617
+ import { useCallback as useCallback5, useEffect as useEffect8, useRef as useRef7, useState as useState11 } from "react";
39505
39618
  import { Fragment as Fragment6, jsx as jsx148, jsxs as jsxs109 } from "react/jsx-runtime";
39506
39619
  var DEFAULT_THEME = {
39507
39620
  primary: "#8b5cf6",
@@ -39557,14 +39670,14 @@ function formatTemplateLabel(templateId) {
39557
39670
  return templateId.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
39558
39671
  }
39559
39672
  var FullscreenPreviewModal = ({ url, title, onClose }) => {
39560
- useEffect7(() => {
39673
+ useEffect8(() => {
39561
39674
  const onKey = (e) => {
39562
39675
  if (e.key === "Escape") onClose();
39563
39676
  };
39564
39677
  document.addEventListener("keydown", onKey);
39565
39678
  return () => document.removeEventListener("keydown", onKey);
39566
39679
  }, [onClose]);
39567
- useEffect7(() => {
39680
+ useEffect8(() => {
39568
39681
  document.body.style.overflow = "hidden";
39569
39682
  return () => {
39570
39683
  document.body.style.overflow = "";
@@ -39655,60 +39768,59 @@ var ResearchReportJobCard = (props) => {
39655
39768
  const [approving, setApproving] = useState11(false);
39656
39769
  const [regenerating, setRegenerating] = useState11(false);
39657
39770
  const [approveError, setApproveError] = useState11(null);
39658
- const previewRef = useRef6(null);
39659
- const intervalRef = useRef6(null);
39660
- const onCompleteRef = useRef6(onComplete);
39661
- const onFailedRef = useRef6(onFailed);
39662
- const hasNotifiedRef = useRef6(false);
39771
+ const previewRef = useRef7(null);
39772
+ const onCompleteRef = useRef7(onComplete);
39773
+ const onFailedRef = useRef7(onFailed);
39774
+ const hasNotifiedRef = useRef7(false);
39663
39775
  onCompleteRef.current = onComplete;
39664
39776
  onFailedRef.current = onFailed;
39665
- useEffect7(() => {
39777
+ useEffect8(() => {
39666
39778
  const newStatus = initialStatus ?? (initialHtmlUrl ? "complete" : void 0);
39667
39779
  setStatus(newStatus);
39668
39780
  }, [initialStatus, initialHtmlUrl]);
39669
- useEffect7(() => {
39781
+ useEffect8(() => {
39670
39782
  if (initialTitle) setTitle(initialTitle);
39671
39783
  }, [initialTitle]);
39672
- useEffect7(() => {
39784
+ useEffect8(() => {
39673
39785
  if (initialHtmlUrl) setHtmlUrl(initialHtmlUrl);
39674
39786
  }, [initialHtmlUrl]);
39675
- useEffect7(() => {
39787
+ useEffect8(() => {
39676
39788
  if (initialGenerationMode) setGenerationMode(initialGenerationMode);
39677
39789
  }, [initialGenerationMode]);
39678
- useEffect7(() => {
39790
+ useEffect8(() => {
39679
39791
  if (initialTemplateId) setTemplateId(initialTemplateId);
39680
39792
  }, [initialTemplateId]);
39681
- useEffect7(() => {
39793
+ useEffect8(() => {
39682
39794
  if (initialTemplateVersionId) setTemplateVersionId(initialTemplateVersionId);
39683
39795
  }, [initialTemplateVersionId]);
39684
- useEffect7(() => {
39796
+ useEffect8(() => {
39685
39797
  if (initialReviewStatus) setReviewStatus(initialReviewStatus);
39686
39798
  }, [initialReviewStatus]);
39687
- useEffect7(() => {
39799
+ useEffect8(() => {
39688
39800
  if (initialDepth) setDepth(initialDepth);
39689
39801
  }, [initialDepth]);
39690
- useEffect7(() => {
39802
+ useEffect8(() => {
39691
39803
  if (initialSectionCount !== void 0) setSectionCount(initialSectionCount);
39692
39804
  }, [initialSectionCount]);
39693
- useEffect7(() => {
39805
+ useEffect8(() => {
39694
39806
  if (initialSourceCount !== void 0) setSourceCount(initialSourceCount);
39695
39807
  }, [initialSourceCount]);
39696
- useEffect7(() => {
39808
+ useEffect8(() => {
39697
39809
  if (initialWordCount !== void 0) setWordCount(initialWordCount);
39698
39810
  }, [initialWordCount]);
39699
- useEffect7(() => {
39811
+ useEffect8(() => {
39700
39812
  if (initialSummary) setSummary(initialSummary);
39701
39813
  }, [initialSummary]);
39702
39814
  const themePrimary = initialTheme?.primary;
39703
- useEffect7(() => {
39815
+ useEffect8(() => {
39704
39816
  if (initialTheme) setTheme(initialTheme);
39705
39817
  }, [themePrimary]);
39706
- useEffect7(() => {
39818
+ useEffect8(() => {
39707
39819
  if (initialError) setError(initialError);
39708
39820
  }, [initialError]);
39709
39821
  const progressPct = initialProgress?.percentage;
39710
39822
  const progressStep = initialProgress?.current_step;
39711
- useEffect7(() => {
39823
+ useEffect8(() => {
39712
39824
  if (initialProgress) setProgress(initialProgress);
39713
39825
  }, [progressPct, progressStep]);
39714
39826
  const isTerminal = status === "complete" || status === "failed";
@@ -39719,73 +39831,66 @@ var ResearchReportJobCard = (props) => {
39719
39831
  setPreviewScale(previewRef.current.offsetWidth / 800);
39720
39832
  }
39721
39833
  }, []);
39722
- useEffect7(() => {
39834
+ useEffect8(() => {
39723
39835
  updateScale();
39724
39836
  if (typeof ResizeObserver === "undefined") return;
39725
39837
  const ro = new ResizeObserver(updateScale);
39726
39838
  if (previewRef.current) ro.observe(previewRef.current);
39727
39839
  return () => ro.disconnect();
39728
39840
  }, [updateScale, htmlUrl]);
39729
- useEffect7(() => {
39730
- if (isTerminal || !pollUrl) return;
39731
- const poll = async () => {
39732
- try {
39841
+ useSharedPoll(
39842
+ {
39843
+ key: !isTerminal && pollUrl ? pollUrl : null,
39844
+ intervalMs: 3e3,
39845
+ fetcher: async () => {
39733
39846
  const headers = {};
39734
39847
  if (authToken) {
39735
39848
  headers["Authorization"] = `Bearer ${authToken}`;
39736
39849
  }
39737
39850
  const res = await fetch(pollUrl, { headers });
39738
- if (!res.ok) return;
39739
- const data = await res.json();
39740
- const newStatus = data.status;
39741
- setStatus(newStatus);
39742
- if (data.progress) {
39743
- setProgress(data.progress);
39851
+ if (!res.ok) throw new Error(`poll ${res.status}`);
39852
+ return res.json();
39853
+ },
39854
+ shouldContinue: (data) => data.status !== "complete" && data.status !== "failed"
39855
+ },
39856
+ (data) => {
39857
+ const newStatus = data.status;
39858
+ setStatus(newStatus);
39859
+ if (data.progress) {
39860
+ setProgress(data.progress);
39861
+ }
39862
+ if (newStatus === "complete" && data.output) {
39863
+ const output = data.output;
39864
+ setTitle(output.title || initialTitle);
39865
+ setDepth(output.depth || "");
39866
+ setSectionCount(output.section_count || 0);
39867
+ setSourceCount(output.source_count || 0);
39868
+ setWordCount(output.word_count || 0);
39869
+ setSummary(output.executive_summary || "");
39870
+ setHtmlUrl(output.html_url || "");
39871
+ if (output.generation_mode) setGenerationMode(output.generation_mode);
39872
+ if (output.template_id) setTemplateId(output.template_id);
39873
+ if (output.template_version_id) setTemplateVersionId(output.template_version_id);
39874
+ if (output.review_status) setReviewStatus(output.review_status);
39875
+ if (output.theme) {
39876
+ setTheme(output.theme);
39744
39877
  }
39745
- if (newStatus === "complete" && data.output) {
39746
- const output = data.output;
39747
- setTitle(output.title || initialTitle);
39748
- setDepth(output.depth || "");
39749
- setSectionCount(output.section_count || 0);
39750
- setSourceCount(output.source_count || 0);
39751
- setWordCount(output.word_count || 0);
39752
- setSummary(output.executive_summary || "");
39753
- setHtmlUrl(output.html_url || "");
39754
- if (output.generation_mode) setGenerationMode(output.generation_mode);
39755
- if (output.template_id) setTemplateId(output.template_id);
39756
- if (output.template_version_id) setTemplateVersionId(output.template_version_id);
39757
- if (output.review_status) setReviewStatus(output.review_status);
39758
- if (output.theme) {
39759
- setTheme(output.theme);
39760
- }
39761
- if (!hasNotifiedRef.current && onCompleteRef.current) {
39762
- hasNotifiedRef.current = true;
39763
- onCompleteRef.current(output);
39764
- }
39878
+ if (!hasNotifiedRef.current && onCompleteRef.current) {
39879
+ hasNotifiedRef.current = true;
39880
+ onCompleteRef.current(output);
39765
39881
  }
39766
- if (newStatus === "failed") {
39767
- const errorMsg = data.error || "Job failed";
39768
- setError(errorMsg);
39769
- if (!hasNotifiedRef.current && onFailedRef.current) {
39770
- hasNotifiedRef.current = true;
39771
- onFailedRef.current(errorMsg);
39772
- }
39882
+ }
39883
+ if (newStatus === "failed") {
39884
+ const errorMsg = data.error || "Job failed";
39885
+ setError(errorMsg);
39886
+ if (!hasNotifiedRef.current && onFailedRef.current) {
39887
+ hasNotifiedRef.current = true;
39888
+ onFailedRef.current(errorMsg);
39773
39889
  }
39774
- } catch {
39775
39890
  }
39776
- };
39777
- poll();
39778
- intervalRef.current = setInterval(poll, 3e3);
39779
- return () => {
39780
- if (intervalRef.current) clearInterval(intervalRef.current);
39781
- };
39782
- }, [isTerminal, pollUrl, authToken, initialTitle]);
39783
- useEffect7(() => {
39784
- if (isTerminal && intervalRef.current) {
39785
- clearInterval(intervalRef.current);
39786
- intervalRef.current = null;
39787
39891
  }
39788
- }, [isTerminal]);
39892
+ // Transient fetch errors are ignored — the shared loop retries next tick.
39893
+ );
39789
39894
  const formatWordCount = (count) => {
39790
39895
  if (count >= 1e3) return `${(count / 1e3).toFixed(1)}k`;
39791
39896
  return count.toString();
@@ -40209,7 +40314,7 @@ var ResearchReportJobCard = (props) => {
40209
40314
  };
40210
40315
 
40211
40316
  // src/molecules/generic/WebSearchJobCard/WebSearchJobCard.tsx
40212
- import { useEffect as useEffect8, useRef as useRef7, useState as useState12 } from "react";
40317
+ import { useEffect as useEffect9, useRef as useRef8, useState as useState12 } from "react";
40213
40318
  import { jsx as jsx149, jsxs as jsxs110 } from "react/jsx-runtime";
40214
40319
  var SearchIcon = () => /* @__PURE__ */ jsxs110("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
40215
40320
  /* @__PURE__ */ jsx149("circle", { cx: "11", cy: "11", r: "8" }),
@@ -40246,91 +40351,83 @@ var WebSearchJobCard = ({
40246
40351
  const [results, setResults] = useState12(initialResults || []);
40247
40352
  const [error, setError] = useState12(initialError);
40248
40353
  const [progress, setProgress] = useState12(initialProgress);
40249
- const intervalRef = useRef7(null);
40250
- const onCompleteRef = useRef7(onComplete);
40251
- const onFailedRef = useRef7(onFailed);
40252
- const hasNotifiedRef = useRef7(false);
40354
+ const onCompleteRef = useRef8(onComplete);
40355
+ const onFailedRef = useRef8(onFailed);
40356
+ const hasNotifiedRef = useRef8(false);
40253
40357
  onCompleteRef.current = onComplete;
40254
40358
  onFailedRef.current = onFailed;
40255
- useEffect8(() => {
40359
+ useEffect9(() => {
40256
40360
  setStatus(initialStatus);
40257
40361
  }, [initialStatus]);
40258
- useEffect8(() => {
40362
+ useEffect9(() => {
40259
40363
  if (initialQuery) setQuery(initialQuery);
40260
40364
  }, [initialQuery]);
40261
- useEffect8(() => {
40365
+ useEffect9(() => {
40262
40366
  if (initialTitle && !initialQuery) setQuery(initialTitle);
40263
40367
  }, [initialTitle, initialQuery]);
40264
- useEffect8(() => {
40368
+ useEffect9(() => {
40265
40369
  if (initialResultCount !== void 0) setResultCount(initialResultCount);
40266
40370
  }, [initialResultCount]);
40267
- useEffect8(() => {
40371
+ useEffect9(() => {
40268
40372
  if (initialSearchCount !== void 0) setSearchCount(initialSearchCount);
40269
40373
  }, [initialSearchCount]);
40270
- useEffect8(() => {
40374
+ useEffect9(() => {
40271
40375
  if (initialSummary) setSummary(initialSummary);
40272
40376
  }, [initialSummary]);
40273
- useEffect8(() => {
40377
+ useEffect9(() => {
40274
40378
  if (initialResults) setResults(initialResults);
40275
40379
  }, [initialResults]);
40276
- useEffect8(() => {
40380
+ useEffect9(() => {
40277
40381
  if (initialError) setError(initialError);
40278
40382
  }, [initialError]);
40279
40383
  const progressPct = initialProgress?.percentage;
40280
40384
  const progressStep = initialProgress?.current_step;
40281
- useEffect8(() => {
40385
+ useEffect9(() => {
40282
40386
  if (initialProgress) setProgress(initialProgress);
40283
40387
  }, [progressPct, progressStep]);
40284
40388
  const isTerminal = status === "complete" || status === "failed";
40285
- useEffect8(() => {
40286
- if (isTerminal || !pollUrl) return;
40287
- const poll = async () => {
40288
- try {
40389
+ useSharedPoll(
40390
+ {
40391
+ key: !isTerminal && pollUrl ? pollUrl : null,
40392
+ intervalMs: 3e3,
40393
+ fetcher: async () => {
40289
40394
  const headers = {};
40290
40395
  if (authToken) headers["Authorization"] = `Bearer ${authToken}`;
40291
40396
  const res = await fetch(pollUrl, { headers });
40292
- if (!res.ok) return;
40293
- const data = await res.json();
40294
- const newStatus = data.status;
40295
- setStatus(newStatus);
40296
- if (data.progress) {
40297
- setProgress(data.progress);
40298
- }
40299
- if (newStatus === "complete" && data.output) {
40300
- const output = data.output;
40301
- setQuery(output.query || "");
40302
- setResultCount(output.result_count ?? 0);
40303
- setSearchCount(output.search_count ?? 0);
40304
- setSummary(output.summary || "");
40305
- setResults(output.results || []);
40306
- if (!hasNotifiedRef.current && onCompleteRef.current) {
40307
- hasNotifiedRef.current = true;
40308
- onCompleteRef.current(output);
40309
- }
40397
+ if (!res.ok) throw new Error(`poll ${res.status}`);
40398
+ return res.json();
40399
+ },
40400
+ shouldContinue: (data) => data.status !== "complete" && data.status !== "failed"
40401
+ },
40402
+ (data) => {
40403
+ const newStatus = data.status;
40404
+ setStatus(newStatus);
40405
+ if (data.progress) {
40406
+ setProgress(data.progress);
40407
+ }
40408
+ if (newStatus === "complete" && data.output) {
40409
+ const output = data.output;
40410
+ setQuery(output.query || "");
40411
+ setResultCount(output.result_count ?? 0);
40412
+ setSearchCount(output.search_count ?? 0);
40413
+ setSummary(output.summary || "");
40414
+ setResults(output.results || []);
40415
+ if (!hasNotifiedRef.current && onCompleteRef.current) {
40416
+ hasNotifiedRef.current = true;
40417
+ onCompleteRef.current(output);
40310
40418
  }
40311
- if (newStatus === "failed") {
40312
- const errorMsg = data.error || "Job failed";
40313
- setError(errorMsg);
40314
- if (!hasNotifiedRef.current && onFailedRef.current) {
40315
- hasNotifiedRef.current = true;
40316
- onFailedRef.current(errorMsg);
40317
- }
40419
+ }
40420
+ if (newStatus === "failed") {
40421
+ const errorMsg = data.error || "Job failed";
40422
+ setError(errorMsg);
40423
+ if (!hasNotifiedRef.current && onFailedRef.current) {
40424
+ hasNotifiedRef.current = true;
40425
+ onFailedRef.current(errorMsg);
40318
40426
  }
40319
- } catch {
40320
40427
  }
40321
- };
40322
- poll();
40323
- intervalRef.current = setInterval(poll, 3e3);
40324
- return () => {
40325
- if (intervalRef.current) clearInterval(intervalRef.current);
40326
- };
40327
- }, [isTerminal, pollUrl, authToken]);
40328
- useEffect8(() => {
40329
- if (isTerminal && intervalRef.current) {
40330
- clearInterval(intervalRef.current);
40331
- intervalRef.current = null;
40332
40428
  }
40333
- }, [isTerminal]);
40429
+ // Transient fetch errors are ignored — the shared loop retries next tick.
40430
+ );
40334
40431
  if (status === "pending" || status === "running") {
40335
40432
  const pct = progress?.percentage ?? 0;
40336
40433
  const step = progress?.current_step ?? "Starting web search...";
@@ -40473,7 +40570,7 @@ var WebSearchJobCard = ({
40473
40570
  import React110, { useMemo as useMemo6 } from "react";
40474
40571
 
40475
40572
  // src/molecules/creator-discovery/SearchSpecCard/CustomFieldRenderers.tsx
40476
- import { useState as useState13, useRef as useRef8, useEffect as useEffect9, useMemo as useMemo5 } from "react";
40573
+ import { useState as useState13, useRef as useRef9, useEffect as useEffect10, useMemo as useMemo5 } from "react";
40477
40574
 
40478
40575
  // src/lib/countries.ts
40479
40576
  var countries = [
@@ -40687,8 +40784,8 @@ var CountrySelectEdit = ({
40687
40784
  }) => {
40688
40785
  const [isDropdownOpen, setIsDropdownOpen] = useState13(false);
40689
40786
  const [searchTerm, setSearchTerm] = useState13("");
40690
- const dropdownRef = useRef8(null);
40691
- useEffect9(() => {
40787
+ const dropdownRef = useRef9(null);
40788
+ useEffect10(() => {
40692
40789
  const handleClickOutside = (event) => {
40693
40790
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
40694
40791
  setIsDropdownOpen(false);
@@ -41393,6 +41490,42 @@ SearchSpecCard.displayName = "SearchSpecCard";
41393
41490
  // src/molecules/creator-discovery/MCQCard/MCQCard.tsx
41394
41491
  import React112 from "react";
41395
41492
 
41493
+ // src/lib/auth-provider.ts
41494
+ var _provider = null;
41495
+ var _onUnauthorized = null;
41496
+ function setPxAuthTokenProvider(provider) {
41497
+ _provider = provider;
41498
+ }
41499
+ function setPxUnauthorizedHandler(handler) {
41500
+ _onUnauthorized = handler;
41501
+ }
41502
+ function notifyPxUnauthorized(status) {
41503
+ if (status !== 401) return false;
41504
+ if (_onUnauthorized) {
41505
+ try {
41506
+ _onUnauthorized();
41507
+ } catch {
41508
+ }
41509
+ }
41510
+ return true;
41511
+ }
41512
+ function getPxAuthToken() {
41513
+ if (_provider) {
41514
+ try {
41515
+ const t = _provider();
41516
+ if (t) return t;
41517
+ } catch {
41518
+ }
41519
+ }
41520
+ if (typeof document !== "undefined") {
41521
+ for (const name of ["adminTokenBuilder", "adminToken", "token"]) {
41522
+ const match2 = document.cookie.match(new RegExp(`(?:^|;\\s*)${name}=([^;]*)`));
41523
+ if (match2?.[1]) return match2[1];
41524
+ }
41525
+ }
41526
+ return null;
41527
+ }
41528
+
41396
41529
  // src/molecules/creator-discovery/MCQCard/defaultFetchers.ts
41397
41530
  function getBackendOrigin() {
41398
41531
  if (typeof window === "undefined") return null;
@@ -41408,25 +41541,10 @@ function getBaseUrl() {
41408
41541
  if (backend) return `${backend}/api/custom-agents`;
41409
41542
  return "/api/agents-proxy/custom-agents";
41410
41543
  }
41411
- function getAuthToken() {
41412
- if (typeof window === "undefined") return null;
41413
- try {
41414
- const ls = localStorage.getItem("px_auth_token");
41415
- if (ls) return ls;
41416
- } catch {
41417
- }
41418
- if (typeof document !== "undefined") {
41419
- for (const name of ["adminTokenBuilder", "adminToken", "token"]) {
41420
- const match2 = document.cookie.match(new RegExp(`(?:^|;\\s*)${name}=([^;]*)`));
41421
- if (match2?.[1]) return match2[1];
41422
- }
41423
- }
41424
- return null;
41425
- }
41426
41544
  function buildHeaders() {
41427
41545
  const headers = { "Content-Type": "application/json" };
41428
41546
  if (getBackendOrigin()) {
41429
- const token = getAuthToken();
41547
+ const token = getPxAuthToken();
41430
41548
  if (token) headers["Authorization"] = `Bearer ${token}`;
41431
41549
  }
41432
41550
  return headers;
@@ -41460,6 +41578,7 @@ async function defaultFetchSelections(sessionId) {
41460
41578
  body: "{}"
41461
41579
  }
41462
41580
  );
41581
+ if (res.status === 401) notifyPxUnauthorized(res.status);
41463
41582
  if (!res.ok) return {};
41464
41583
  const data = await res.json();
41465
41584
  const selections = data.selections || {};
@@ -41477,7 +41596,7 @@ async function defaultFetchSelections(sessionId) {
41477
41596
  async function defaultPersistSelection(sessionId, questionKey, value) {
41478
41597
  setLocalSelection(sessionId, questionKey, value);
41479
41598
  try {
41480
- await fetch(
41599
+ const res = await fetch(
41481
41600
  `${getBaseUrl()}/sessions/${sessionId}/mcq-selections`,
41482
41601
  {
41483
41602
  method: "PATCH",
@@ -41485,6 +41604,7 @@ async function defaultPersistSelection(sessionId, questionKey, value) {
41485
41604
  body: JSON.stringify({ question_key: questionKey, value })
41486
41605
  }
41487
41606
  );
41607
+ if (res.status === 401) notifyPxUnauthorized(res.status);
41488
41608
  } catch (err) {
41489
41609
  console.warn("[MCQ persist failed]", err);
41490
41610
  }
@@ -42473,10 +42593,10 @@ var CampaignConceptCard = React114.memo(
42473
42593
  }) });
42474
42594
  }
42475
42595
  if (typeof val === "object") {
42476
- const entries = Object.entries(val);
42477
- if (entries.length === 0)
42596
+ const entries2 = Object.entries(val);
42597
+ if (entries2.length === 0)
42478
42598
  return /* @__PURE__ */ jsx165("span", { className: "text-muted-foreground text-sm", children: "-" });
42479
- return /* @__PURE__ */ jsx165("div", { className: "space-y-2", children: entries.map(([k, v], idx) => /* @__PURE__ */ jsxs125("div", { className: "flex items-center gap-2", children: [
42599
+ return /* @__PURE__ */ jsx165("div", { className: "space-y-2", children: entries2.map(([k, v], idx) => /* @__PURE__ */ jsxs125("div", { className: "flex items-center gap-2", children: [
42480
42600
  /* @__PURE__ */ jsxs125("span", { className: "text-muted-foreground font-medium", children: [
42481
42601
  idx + 1,
42482
42602
  "."
@@ -42734,11 +42854,11 @@ CampaignConceptCard.displayName = "CampaignConceptCard";
42734
42854
  import { useCallback as useCallback9, useState as useState22, memo } from "react";
42735
42855
 
42736
42856
  // src/molecules/creator-discovery/CreatorWidget/CreatorImageList.tsx
42737
- import { useEffect as useEffect10, useState as useState15 } from "react";
42857
+ import { useEffect as useEffect11, useState as useState15 } from "react";
42738
42858
  import { Fragment as Fragment7, jsx as jsx166, jsxs as jsxs126 } from "react/jsx-runtime";
42739
42859
  function useMediaQuery(query) {
42740
42860
  const [matches, setMatches] = useState15(false);
42741
- useEffect10(() => {
42861
+ useEffect11(() => {
42742
42862
  const media = window.matchMedia(query);
42743
42863
  const listener = () => setMatches(media.matches);
42744
42864
  listener();
@@ -42821,7 +42941,7 @@ function CreatorImageList({
42821
42941
  }
42822
42942
 
42823
42943
  // src/molecules/creator-discovery/CreatorWidget/CreatorProgressBar.tsx
42824
- import { useEffect as useEffect11, useState as useState16 } from "react";
42944
+ import { useEffect as useEffect12, useState as useState16 } from "react";
42825
42945
  import { motion as motion2, AnimatePresence as AnimatePresence2 } from "framer-motion";
42826
42946
  import { jsx as jsx167, jsxs as jsxs127 } from "react/jsx-runtime";
42827
42947
  function truncateName(name, maxLength) {
@@ -42830,7 +42950,7 @@ function truncateName(name, maxLength) {
42830
42950
  }
42831
42951
  function ProgressBar({ overallPercentage }) {
42832
42952
  const [showTooltip, setShowTooltip] = useState16(true);
42833
- useEffect11(() => {
42953
+ useEffect12(() => {
42834
42954
  if (overallPercentage && overallPercentage >= 100) {
42835
42955
  setShowTooltip(false);
42836
42956
  }
@@ -42991,7 +43111,7 @@ function CreatorCompactView({
42991
43111
  }
42992
43112
 
42993
43113
  // src/molecules/creator-discovery/CreatorWidget/CreatorExpandedPanel.tsx
42994
- import { useState as useState20, useEffect as useEffect13, useCallback as useCallback7 } from "react";
43114
+ import { useState as useState20, useEffect as useEffect14, useCallback as useCallback7 } from "react";
42995
43115
  import ReactDOM2 from "react-dom";
42996
43116
  import { AnimatePresence as AnimatePresence4, motion as motion5 } from "framer-motion";
42997
43117
 
@@ -43005,26 +43125,11 @@ function getBackendOrigin2() {
43005
43125
  }
43006
43126
  return raw;
43007
43127
  }
43008
- function getAuthToken2() {
43009
- if (typeof window === "undefined") return null;
43010
- try {
43011
- const ls = localStorage.getItem("px_auth_token");
43012
- if (ls) return ls;
43013
- } catch {
43014
- }
43015
- if (typeof document !== "undefined") {
43016
- for (const name of ["adminTokenBuilder", "adminToken", "token"]) {
43017
- const match2 = document.cookie.match(new RegExp(`(?:^|;\\s*)${name}=([^;]*)`));
43018
- if (match2?.[1]) return match2[1];
43019
- }
43020
- }
43021
- return null;
43022
- }
43023
43128
  function buildHeaders2(includeJson = false) {
43024
43129
  const headers = {};
43025
43130
  if (includeJson) headers["Content-Type"] = "application/json";
43026
43131
  if (getBackendOrigin2()) {
43027
- const token = getAuthToken2();
43132
+ const token = getPxAuthToken();
43028
43133
  if (token) headers["Authorization"] = `Bearer ${token}`;
43029
43134
  }
43030
43135
  return headers;
@@ -43034,6 +43139,7 @@ async function defaultFetchVersions(params) {
43034
43139
  const versionParam = params.version ? `&version=${params.version}` : "";
43035
43140
  const url = backend ? `${backend}/api/creators/versions?sessionId=${params.sessionId}${versionParam}&validated=${params.validated}` : `/api/get-creator-versions?sessionId=${params.sessionId}${versionParam}&validated=${params.validated}`;
43036
43141
  const res = await fetch(url, { headers: buildHeaders2() });
43142
+ if (res.status === 401) notifyPxUnauthorized(res.status);
43037
43143
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
43038
43144
  return res.json();
43039
43145
  }
@@ -43041,6 +43147,7 @@ async function defaultFetchStatus(params) {
43041
43147
  const backend = getBackendOrigin2();
43042
43148
  const url = backend ? `${backend}/api/creators/version-status?session_id=${params.sessionId}&version_no=${params.versionNo}` : `/api/get-creator-detail-status?session_id=${params.sessionId}&version_no=${params.versionNo}`;
43043
43149
  const res = await fetch(url, { headers: buildHeaders2() });
43150
+ if (res.status === 401) notifyPxUnauthorized(res.status);
43044
43151
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
43045
43152
  return res.json();
43046
43153
  }
@@ -43056,6 +43163,7 @@ async function defaultFetchCreatorDetails(params) {
43056
43163
  version_no: params.versionNo
43057
43164
  })
43058
43165
  });
43166
+ if (res.status === 401) notifyPxUnauthorized(res.status);
43059
43167
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
43060
43168
  return res.json();
43061
43169
  }
@@ -43964,7 +44072,7 @@ function BrandCollaborationsList({
43964
44072
  }
43965
44073
 
43966
44074
  // src/molecules/creator-discovery/CreatorWidget/CreatorGridView.tsx
43967
- import { useState as useState19, useMemo as useMemo10, useRef as useRef9, useCallback as useCallback6, useEffect as useEffect12 } from "react";
44075
+ import { useState as useState19, useMemo as useMemo10, useRef as useRef10, useCallback as useCallback6, useEffect as useEffect13 } from "react";
43968
44076
  import { motion as motion4 } from "framer-motion";
43969
44077
  import { jsx as jsx175, jsxs as jsxs134 } from "react/jsx-runtime";
43970
44078
  var formatFollowerCount3 = (count) => {
@@ -44016,17 +44124,17 @@ function CreatorGridViewCard({ creator }) {
44016
44124
  const [isExpanded, setIsExpanded] = useState19(false);
44017
44125
  const [showFullDescription, setShowFullDescription] = useState19(false);
44018
44126
  const [isDescriptionOverflowing, setIsDescriptionOverflowing] = useState19(false);
44019
- const descriptionRef = useRef9(null);
44020
- const cardRef = useRef9(null);
44127
+ const descriptionRef = useRef10(null);
44128
+ const cardRef = useRef10(null);
44021
44129
  const checkDescriptionOverflow = useCallback6(() => {
44022
44130
  const el = descriptionRef.current;
44023
44131
  if (!el) return;
44024
44132
  setIsDescriptionOverflowing(el.scrollHeight > el.clientHeight + 1);
44025
44133
  }, []);
44026
- useEffect12(() => {
44134
+ useEffect13(() => {
44027
44135
  checkDescriptionOverflow();
44028
44136
  }, [checkDescriptionOverflow, isExpanded, showFullDescription]);
44029
- useEffect12(() => {
44137
+ useEffect13(() => {
44030
44138
  const onResize = () => checkDescriptionOverflow();
44031
44139
  window.addEventListener("resize", onResize);
44032
44140
  return () => window.removeEventListener("resize", onResize);
@@ -44697,7 +44805,7 @@ function CreatorExpandedPanel({
44697
44805
  setLoading(false);
44698
44806
  }
44699
44807
  }, [creatorIds, sessionId, version, fetcher]);
44700
- useEffect13(() => {
44808
+ useEffect14(() => {
44701
44809
  if (isOpen && creatorIds.length > 0) {
44702
44810
  loadCreators();
44703
44811
  }
@@ -44751,13 +44859,18 @@ function CreatorExpandedPanel({
44751
44859
  }
44752
44860
 
44753
44861
  // src/molecules/creator-discovery/CreatorWidget/useCreatorWidgetPolling.ts
44754
- import { useState as useState21, useEffect as useEffect14, useCallback as useCallback8, useMemo as useMemo11, useRef as useRef10 } from "react";
44862
+ import { useState as useState21, useEffect as useEffect15, useCallback as useCallback8, useMemo as useMemo11, useRef as useRef11 } from "react";
44755
44863
  var DEFAULT_POLLING_CONFIG = {
44756
44864
  pollInterval: 5e3,
44757
44865
  maxDuration: 15 * 60 * 1e3,
44758
44866
  maxErrors: 10,
44759
44867
  secondsPerCreator: 13
44760
44868
  };
44869
+ var formatTime = (seconds) => {
44870
+ if (seconds <= 0) return "to complete";
44871
+ const minutes = Math.floor(seconds / 60);
44872
+ return minutes >= 1 ? `${minutes} min remaining...` : `${seconds} sec remaining...`;
44873
+ };
44761
44874
  function useCreatorWidgetPolling({
44762
44875
  sessionId,
44763
44876
  currentVersion,
@@ -44781,122 +44894,123 @@ function useCreatorWidgetPolling({
44781
44894
  const [statusDetails, setStatusDetails] = useState21();
44782
44895
  const [timeDisplay, setTimeDisplay] = useState21("");
44783
44896
  const [loadingStatus, setLoadingStatus] = useState21(true);
44784
- const remainingTimeRef = useRef10(0);
44897
+ const remainingTimeRef = useRef11(0);
44898
+ const countdownRef = useRef11(null);
44785
44899
  const requestedVersion = selectedVersion ?? currentVersion ?? versionData?.currentVersion;
44786
- const fetchVersionData = useCallback8(async () => {
44787
- if (!sessionId) return;
44788
- if (!versionData) setIsLoadingVersion(true);
44789
- try {
44790
- const data = await fetchVersions({
44791
- sessionId,
44792
- version: requestedVersion,
44793
- validated: isValidationComplete
44794
- });
44795
- if (data.success !== false) {
44900
+ const updateStatus = useCallback8(
44901
+ (status) => {
44902
+ setVersionStatus(status);
44903
+ onStatusChange?.(status);
44904
+ },
44905
+ [onStatusChange]
44906
+ );
44907
+ const versionKey = sessionId ? `creator:versions:${sessionId}:${requestedVersion ?? "latest"}:${isValidationComplete ? 1 : 0}` : null;
44908
+ useSharedPoll(
44909
+ {
44910
+ key: versionKey,
44911
+ intervalMs: config.pollInterval,
44912
+ fetcher: async () => {
44913
+ if (!versionData) setIsLoadingVersion(true);
44914
+ return fetchVersions({
44915
+ sessionId,
44916
+ version: requestedVersion,
44917
+ validated: isValidationComplete
44918
+ });
44919
+ },
44920
+ shouldContinue: (data) => !((data?.totalVersions || 0) > 0)
44921
+ },
44922
+ (data) => {
44923
+ if (data && data.success !== false) {
44796
44924
  setVersionData(data);
44797
44925
  setTotalVersions(data.totalVersions || 0);
44798
44926
  }
44799
- } catch (err) {
44800
- if (err.name !== "AbortError") {
44927
+ setIsLoadingVersion(false);
44928
+ },
44929
+ (err) => {
44930
+ if (err?.name !== "AbortError") {
44801
44931
  console.error("Error fetching creator version:", err);
44802
44932
  }
44803
- } finally {
44804
44933
  setIsLoadingVersion(false);
44805
44934
  }
44806
- }, [sessionId, requestedVersion, isValidationComplete, fetchVersions, versionData]);
44807
- useEffect14(() => {
44808
- fetchVersionData();
44809
- }, [sessionId, requestedVersion, isValidationComplete]);
44810
- useEffect14(() => {
44811
- if (totalVersions > 0 || !sessionId) return;
44812
- const interval = setInterval(() => {
44813
- if (totalVersions === 0) fetchVersionData();
44814
- }, config.pollInterval);
44815
- return () => clearInterval(interval);
44816
- }, [totalVersions, sessionId, fetchVersionData, config.pollInterval]);
44817
- useEffect14(() => {
44818
- if (!selectedVersion && !requestedVersion) return;
44819
- const activeVersion = selectedVersion ?? requestedVersion;
44820
- let isMounted = true;
44821
- let intervalId = null;
44822
- let timerIntervalId = null;
44823
- let elapsed = 0;
44824
- let errorCount = 0;
44935
+ );
44936
+ const activeVersion = selectedVersion ?? requestedVersion;
44937
+ const statusKey = sessionId && activeVersion != null ? `creator:status:${sessionId}:${activeVersion}` : null;
44938
+ const errorCountRef = useRef11(0);
44939
+ const deadlineRef = useRef11(0);
44940
+ const doneRef = useRef11(false);
44941
+ const stopCountdown = useCallback8(() => {
44942
+ if (countdownRef.current) {
44943
+ clearInterval(countdownRef.current);
44944
+ countdownRef.current = null;
44945
+ }
44946
+ setTimeDisplay("");
44947
+ }, []);
44948
+ useEffect15(() => {
44949
+ if (statusKey == null) return;
44825
44950
  setLoadingStatus(true);
44826
44951
  setStatusDetails(void 0);
44827
44952
  setVersionStatus("checking");
44953
+ errorCountRef.current = 0;
44954
+ doneRef.current = false;
44955
+ deadlineRef.current = Date.now() + config.maxDuration;
44828
44956
  const creatorLength2 = versionData?.length || 0;
44829
44957
  remainingTimeRef.current = creatorLength2 > 0 ? creatorLength2 * config.secondsPerCreator : 60;
44830
- const formatTime = (seconds) => {
44831
- if (seconds <= 0) return "to complete";
44832
- const minutes = Math.floor(seconds / 60);
44833
- return minutes >= 1 ? `${minutes} min remaining...` : `${seconds} sec remaining...`;
44834
- };
44835
44958
  setTimeDisplay(formatTime(remainingTimeRef.current));
44836
- timerIntervalId = setInterval(() => {
44959
+ countdownRef.current = setInterval(() => {
44837
44960
  if (remainingTimeRef.current > 0) remainingTimeRef.current -= 1;
44838
44961
  setTimeDisplay(formatTime(remainingTimeRef.current));
44839
44962
  }, 1e3);
44840
- const updateStatus = (status) => {
44841
- setVersionStatus(status);
44842
- onStatusChange?.(status);
44843
- };
44844
- const stopPolling = () => {
44845
- if (intervalId) clearInterval(intervalId);
44846
- if (timerIntervalId) clearInterval(timerIntervalId);
44847
- setTimeDisplay("");
44963
+ return () => {
44964
+ if (countdownRef.current) {
44965
+ clearInterval(countdownRef.current);
44966
+ countdownRef.current = null;
44967
+ }
44848
44968
  };
44849
- const pollStatus = async () => {
44850
- try {
44851
- const data = await fetchStatus({
44852
- sessionId,
44853
- versionNo: activeVersion
44854
- });
44855
- if (!isMounted) return;
44856
- if (data?.status) setStatusDetails(data.status);
44969
+ }, [statusKey]);
44970
+ useSharedPoll(
44971
+ {
44972
+ key: statusKey,
44973
+ intervalMs: config.pollInterval,
44974
+ fetcher: async () => fetchStatus({ sessionId, versionNo: activeVersion }),
44975
+ shouldContinue: (data) => {
44976
+ if (Date.now() >= deadlineRef.current) return false;
44857
44977
  const s = data?.status?.status;
44858
- if (s === "completed" || s === "complete") {
44859
- updateStatus(s);
44860
- setIsValidationComplete(true);
44861
- stopPolling();
44862
- return;
44863
- }
44864
- if (s === "failed") {
44865
- updateStatus("failed");
44866
- stopPolling();
44867
- return;
44868
- }
44869
- errorCount = 0;
44870
- updateStatus(s || "in-progress");
44871
- } catch (err) {
44872
- console.error("Error fetching status:", err);
44873
- errorCount++;
44874
- if (errorCount >= config.maxErrors) {
44875
- console.error(`Polling failed after ${config.maxErrors} consecutive errors`);
44876
- updateStatus("failed");
44877
- setLoadingStatus(false);
44878
- stopPolling();
44879
- return;
44880
- }
44881
- } finally {
44882
- setLoadingStatus(false);
44978
+ return !(s === "completed" || s === "complete" || s === "failed");
44883
44979
  }
44884
- };
44885
- pollStatus();
44886
- intervalId = setInterval(() => {
44887
- elapsed += config.pollInterval;
44888
- if (elapsed >= config.maxDuration) {
44889
- console.warn("Stopped polling after max duration");
44890
- stopPolling();
44980
+ },
44981
+ (data) => {
44982
+ if (data?.status) setStatusDetails(data.status);
44983
+ const s = data?.status?.status;
44984
+ if (s === "completed" || s === "complete") {
44985
+ updateStatus(s);
44986
+ setIsValidationComplete(true);
44987
+ doneRef.current = true;
44988
+ stopCountdown();
44989
+ } else if (s === "failed") {
44990
+ updateStatus("failed");
44991
+ doneRef.current = true;
44992
+ stopCountdown();
44891
44993
  } else {
44892
- pollStatus();
44994
+ errorCountRef.current = 0;
44995
+ updateStatus(s || "in-progress");
44893
44996
  }
44894
- }, config.pollInterval);
44895
- return () => {
44896
- isMounted = false;
44897
- stopPolling();
44898
- };
44899
- }, [selectedVersion, requestedVersion, sessionId]);
44997
+ setLoadingStatus(false);
44998
+ },
44999
+ (err) => {
45000
+ console.error("Error fetching status:", err);
45001
+ errorCountRef.current++;
45002
+ if (errorCountRef.current >= config.maxErrors) {
45003
+ console.error(
45004
+ `Polling failed after ${config.maxErrors} consecutive errors`
45005
+ );
45006
+ updateStatus("failed");
45007
+ doneRef.current = true;
45008
+ stopCountdown();
45009
+ if (statusKey) stopSharedPoll(statusKey);
45010
+ }
45011
+ setLoadingStatus(false);
45012
+ }
45013
+ );
44900
45014
  const versionNumbers = useMemo11(() => {
44901
45015
  if (!totalVersions) return [];
44902
45016
  return Array.from({ length: totalVersions }, (_, i) => i + 1);
@@ -45006,7 +45120,7 @@ function CreatorWidgetInner({
45006
45120
  var CreatorWidget = memo(CreatorWidgetInner);
45007
45121
 
45008
45122
  // src/molecules/analytics/AnalyticsChart.tsx
45009
- import { useEffect as useEffect15, useRef as useRef11, useState as useState23 } from "react";
45123
+ import { useEffect as useEffect16, useRef as useRef12, useState as useState23 } from "react";
45010
45124
  import { jsx as jsx178, jsxs as jsxs137 } from "react/jsx-runtime";
45011
45125
  function getCSSVar(name) {
45012
45126
  if (typeof document === "undefined") return "";
@@ -45123,12 +45237,12 @@ function AnalyticsChart({
45123
45237
  const [fetchedConfig, setFetchedConfig] = useState23(null);
45124
45238
  const [fetching, setFetching] = useState23(false);
45125
45239
  const [fetchError, setFetchError] = useState23(null);
45126
- const containerRef = useRef11(null);
45127
- const chartRef = useRef11(null);
45128
- useEffect15(() => {
45240
+ const containerRef = useRef12(null);
45241
+ const chartRef = useRef12(null);
45242
+ useEffect16(() => {
45129
45243
  setMounted(true);
45130
45244
  }, []);
45131
- useEffect15(() => {
45245
+ useEffect16(() => {
45132
45246
  if (!chartId || configProp) return;
45133
45247
  let cancelled = false;
45134
45248
  setFetching(true);
@@ -45150,7 +45264,7 @@ function AnalyticsChart({
45150
45264
  };
45151
45265
  }, [chartId, apiBase, authToken, configProp]);
45152
45266
  const activeConfig = configProp ?? fetchedConfig;
45153
- useEffect15(() => {
45267
+ useEffect16(() => {
45154
45268
  if (!mounted || !activeConfig || !containerRef.current) return;
45155
45269
  const container = containerRef.current;
45156
45270
  let cancelled = false;
@@ -45170,7 +45284,7 @@ function AnalyticsChart({
45170
45284
  cancelled = true;
45171
45285
  };
45172
45286
  }, [mounted, activeConfig]);
45173
- useEffect15(() => {
45287
+ useEffect16(() => {
45174
45288
  return () => {
45175
45289
  if (chartRef.current) {
45176
45290
  try {
@@ -45181,7 +45295,7 @@ function AnalyticsChart({
45181
45295
  }
45182
45296
  };
45183
45297
  }, []);
45184
- useEffect15(() => {
45298
+ useEffect16(() => {
45185
45299
  if (!mounted || !containerRef.current) return;
45186
45300
  const obs = new ResizeObserver(() => {
45187
45301
  try {
@@ -46884,6 +46998,37 @@ ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
46884
46998
  // src/render/PXEngineRenderer.tsx
46885
46999
  import { jsx as jsx188, jsxs as jsxs140 } from "react/jsx-runtime";
46886
47000
  var MOLECULE_REFS = new Set(Object.values(molecules_exports));
47001
+ var ATOMS_WITH_RENDER = /* @__PURE__ */ new Set([
47002
+ "LayoutAtom",
47003
+ "CardAtom",
47004
+ "TabsAtom",
47005
+ "AccordionAtom",
47006
+ "ScrollAreaAtom",
47007
+ "CarouselAtom",
47008
+ "AspectRatioAtom",
47009
+ "CollapsibleAtom",
47010
+ "TooltipAtom",
47011
+ "PopoverAtom",
47012
+ "DialogAtom",
47013
+ "SheetAtom",
47014
+ "ResizableAtom"
47015
+ ]);
47016
+ var COMPONENT_LOOKUP_CACHE = /* @__PURE__ */ new Map();
47017
+ var resolveComponent = (identifier) => {
47018
+ const cached = COMPONENT_LOOKUP_CACHE.get(identifier);
47019
+ if (cached !== void 0) return cached;
47020
+ const normalized = identifier.split(/[-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
47021
+ const atomName = normalized.endsWith("Atom") ? normalized : `${normalized}Atom`;
47022
+ let Comp = atoms_exports[atomName] || atoms_exports[normalized] || atoms_exports[identifier] || null;
47023
+ if (!Comp) {
47024
+ Comp = molecules_exports[normalized] || molecules_exports[identifier] || null;
47025
+ }
47026
+ if (!Comp && !CONTEXT_DEPENDENT_COMPONENTS.has(normalized)) {
47027
+ Comp = ui_exports[normalized] || ui_exports[identifier] || null;
47028
+ }
47029
+ COMPONENT_LOOKUP_CACHE.set(identifier, Comp);
47030
+ return Comp;
47031
+ };
46887
47032
  var CONTEXT_DEPENDENT_COMPONENTS = /* @__PURE__ */ new Set([
46888
47033
  // Form components - require FormField + FormItem context
46889
47034
  "FormLabel",
@@ -47012,7 +47157,10 @@ var renderContextDependentError = (componentName, normalizedName, key) => {
47012
47157
  key
47013
47158
  );
47014
47159
  };
47160
+ var NORMALIZE_PROPS_CACHE = /* @__PURE__ */ new WeakMap();
47015
47161
  var normalizeProps = (props) => {
47162
+ const cached = NORMALIZE_PROPS_CACHE.get(props);
47163
+ if (cached) return cached;
47016
47164
  const normalized = {};
47017
47165
  const dynamicStyle = {};
47018
47166
  Object.entries(props).forEach(([key, value]) => {
@@ -47072,7 +47220,9 @@ var normalizeProps = (props) => {
47072
47220
  }
47073
47221
  normalized[key] = value;
47074
47222
  });
47075
- return { normalized, dynamicStyle };
47223
+ const result = { normalized, dynamicStyle };
47224
+ NORMALIZE_PROPS_CACHE.set(props, result);
47225
+ return result;
47076
47226
  };
47077
47227
  var FORM_INPUT_ATOM_NAMES = /* @__PURE__ */ new Set([
47078
47228
  "InputAtom",
@@ -47091,13 +47241,13 @@ var FORM_INPUT_ATOM_NAMES = /* @__PURE__ */ new Set([
47091
47241
  "InputOTPAtom",
47092
47242
  "ToggleAtom"
47093
47243
  ]);
47094
- var PXEngineRenderer = ({
47244
+ var PXEngineRenderer = React118.memo(function PXEngineRenderer2({
47095
47245
  schema,
47096
47246
  onAction,
47097
47247
  disabled,
47098
47248
  theme,
47099
47249
  onFormSubmit
47100
- }) => {
47250
+ }) {
47101
47251
  const contextTheme = React118.useContext(WidgetThemeContext);
47102
47252
  const effectiveTheme = theme ?? contextTheme;
47103
47253
  const formValuesRef = React118.useRef({});
@@ -47132,28 +47282,34 @@ var PXEngineRenderer = ({
47132
47282
  } = component;
47133
47283
  const componentName = name || type || componentType;
47134
47284
  if (!componentName || typeof componentName !== "string") return null;
47135
- const rawProps = { ...remainingProps, ...props };
47136
- delete rawProps.key;
47137
- if (disabled !== void 0 && rawProps.disabled === void 0) {
47138
- rawProps.disabled = disabled;
47285
+ const hasRemaining = Object.keys(remainingProps).length > 0;
47286
+ let baseProps = hasRemaining ? { ...remainingProps, ...props } : props;
47287
+ if (baseProps && baseProps.key !== void 0) {
47288
+ const { key: _k, ...rest } = baseProps;
47289
+ baseProps = rest;
47290
+ }
47291
+ const { normalized, dynamicStyle } = normalizeProps(baseProps || {});
47292
+ const finalProps = { ...normalized };
47293
+ if (disabled !== void 0 && finalProps.disabled === void 0) {
47294
+ finalProps.disabled = disabled;
47139
47295
  }
47140
47296
  const normalizedName = componentName.charAt(0).toUpperCase() + componentName.slice(1);
47141
47297
  const earlyAtomName = normalizedName.endsWith("Atom") ? normalizedName : `${normalizedName}Atom`;
47142
47298
  if (onFormSubmit && FORM_INPUT_ATOM_NAMES.has(earlyAtomName)) {
47143
- const fieldKey = rawProps.fieldKey || rawProps.id || id || rawProps.label || componentName;
47299
+ const fieldKey = finalProps.fieldKey || finalProps.id || id || finalProps.label || componentName;
47144
47300
  const storedValue = formValuesRef.current[fieldKey];
47145
47301
  if (storedValue !== void 0) {
47146
- rawProps.defaultValue = storedValue;
47302
+ finalProps.defaultValue = storedValue;
47147
47303
  }
47148
- rawProps.onValueChange = handleInputValueChange;
47149
- rawProps.fieldKey = fieldKey;
47150
- if (id) rawProps.id = id;
47304
+ finalProps.onValueChange = handleInputValueChange;
47305
+ finalProps.fieldKey = fieldKey;
47306
+ if (id) finalProps.id = id;
47151
47307
  }
47152
47308
  if (onFormSubmit && earlyAtomName === "ButtonAtom") {
47153
- const action = rawProps.action || rawProps.buttonAction;
47309
+ const action = finalProps.action || finalProps.buttonAction;
47154
47310
  if (action === "submit") {
47155
- const originalOnAction = rawProps.onAction;
47156
- rawProps.onAction = (evt) => {
47311
+ const originalOnAction = finalProps.onAction;
47312
+ finalProps.onAction = (evt) => {
47157
47313
  const elements = Object.entries(formValuesRef.current).map(
47158
47314
  ([key, value]) => ({
47159
47315
  id: key,
@@ -47169,23 +47325,10 @@ var PXEngineRenderer = ({
47169
47325
  };
47170
47326
  }
47171
47327
  }
47172
- const { normalized: finalProps, dynamicStyle } = normalizeProps(rawProps);
47173
47328
  if (id && !finalProps.id) {
47174
47329
  finalProps.id = id;
47175
47330
  }
47176
47331
  const uniqueKey = id || (index !== void 0 ? `${componentName}-${index}` : `${componentName}-root`);
47177
- const resolveComponent = (identifier) => {
47178
- const normalized = identifier.split(/[-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
47179
- const atomName2 = normalized.endsWith("Atom") ? normalized : `${normalized}Atom`;
47180
- let Comp = atoms_exports[atomName2] || atoms_exports[normalized] || atoms_exports[identifier];
47181
- if (!Comp) {
47182
- Comp = molecules_exports[normalized] || molecules_exports[identifier];
47183
- }
47184
- if (!Comp && !CONTEXT_DEPENDENT_COMPONENTS.has(normalized)) {
47185
- Comp = ui_exports[normalized] || ui_exports[identifier];
47186
- }
47187
- return Comp;
47188
- };
47189
47332
  let TargetComponent = resolveComponent(componentName);
47190
47333
  let resolvedIdentifier = componentName;
47191
47334
  if (!TargetComponent && type && type !== componentName) {
@@ -47210,21 +47353,6 @@ var PXEngineRenderer = ({
47210
47353
  }
47211
47354
  const resolvedNormalized = resolvedIdentifier.charAt(0).toUpperCase() + resolvedIdentifier.slice(1);
47212
47355
  const atomName = resolvedNormalized.endsWith("Atom") ? resolvedNormalized : `${resolvedNormalized}Atom`;
47213
- const ATOMS_WITH_RENDER = /* @__PURE__ */ new Set([
47214
- "LayoutAtom",
47215
- "CardAtom",
47216
- "TabsAtom",
47217
- "AccordionAtom",
47218
- "ScrollAreaAtom",
47219
- "CarouselAtom",
47220
- "AspectRatioAtom",
47221
- "CollapsibleAtom",
47222
- "TooltipAtom",
47223
- "PopoverAtom",
47224
- "DialogAtom",
47225
- "SheetAtom",
47226
- "ResizableAtom"
47227
- ]);
47228
47356
  const isAtomWithRenderProp = ATOMS_WITH_RENDER.has(atomName);
47229
47357
  if (effectiveTheme && finalProps.theme === void 0 && MOLECULE_REFS.has(TargetComponent)) {
47230
47358
  finalProps.theme = effectiveTheme;
@@ -47258,7 +47386,8 @@ var PXEngineRenderer = ({
47258
47386
  }
47259
47387
  };
47260
47388
  return /* @__PURE__ */ jsx188(WidgetThemeContext.Provider, { value: effectiveTheme, children: /* @__PURE__ */ jsx188("div", { className: "px-engine-root relative w-full h-full", children: renderRecursive(root) }) });
47261
- };
47389
+ });
47390
+ PXEngineRenderer.displayName = "PXEngineRenderer";
47262
47391
  export {
47263
47392
  Accordion,
47264
47393
  AccordionAtom,
@@ -47575,7 +47704,11 @@ export {
47575
47704
  formatQAMessage,
47576
47705
  generateFieldsFromData,
47577
47706
  generateFieldsFromPropDefinitions,
47707
+ getPxAuthToken,
47578
47708
  isInputAtom,
47709
+ notifyPxUnauthorized,
47710
+ setPxAuthTokenProvider,
47711
+ setPxUnauthorizedHandler,
47579
47712
  submitWidgetToAgent,
47580
47713
  th,
47581
47714
  useCreatorWidgetPolling,