pxengine 0.1.108 → 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.cjs CHANGED
@@ -347,7 +347,9 @@ __export(index_exports, {
347
347
  generateFieldsFromPropDefinitions: () => generateFieldsFromPropDefinitions,
348
348
  getPxAuthToken: () => getPxAuthToken,
349
349
  isInputAtom: () => isInputAtom,
350
+ notifyPxUnauthorized: () => notifyPxUnauthorized,
350
351
  setPxAuthTokenProvider: () => setPxAuthTokenProvider,
352
+ setPxUnauthorizedHandler: () => setPxUnauthorizedHandler,
351
353
  submitWidgetToAgent: () => submitWidgetToAgent,
352
354
  th: () => th,
353
355
  useCreatorWidgetPolling: () => useCreatorWidgetPolling,
@@ -357,7 +359,7 @@ __export(index_exports, {
357
359
  module.exports = __toCommonJS(index_exports);
358
360
 
359
361
  // src/render/PXEngineRenderer.tsx
360
- var import_react96 = __toESM(require("react"), 1);
362
+ var import_react97 = __toESM(require("react"), 1);
361
363
 
362
364
  // src/atoms/index.ts
363
365
  var atoms_exports = {};
@@ -39183,7 +39185,128 @@ var NextStepCard = ({
39183
39185
  };
39184
39186
 
39185
39187
  // src/molecules/generic/PresentationJobCard/PresentationJobCard.tsx
39188
+ var import_react78 = require("react");
39189
+
39190
+ // src/lib/shared-poll.ts
39186
39191
  var import_react77 = require("react");
39192
+ var entries = /* @__PURE__ */ new Map();
39193
+ function clearTimer(entry) {
39194
+ if (entry.timer !== null) {
39195
+ clearInterval(entry.timer);
39196
+ entry.timer = null;
39197
+ }
39198
+ entry.controller?.abort();
39199
+ entry.controller = null;
39200
+ }
39201
+ async function runPoll(key) {
39202
+ const entry = entries.get(key);
39203
+ if (!entry || entry.inFlight || entry.stopped) return;
39204
+ entry.inFlight = true;
39205
+ const controller = new AbortController();
39206
+ entry.controller = controller;
39207
+ try {
39208
+ const data = await entry.fetcher(controller.signal);
39209
+ if (entries.get(key) !== entry) return;
39210
+ entry.lastData = data;
39211
+ entry.hasData = true;
39212
+ for (const listener of Array.from(entry.dataListeners)) {
39213
+ try {
39214
+ listener(data);
39215
+ } catch {
39216
+ }
39217
+ }
39218
+ if (!entry.shouldContinue(data)) {
39219
+ entry.stopped = true;
39220
+ clearTimer(entry);
39221
+ }
39222
+ } catch (error) {
39223
+ if (entries.get(key) !== entry) return;
39224
+ for (const listener of Array.from(entry.errorListeners)) {
39225
+ try {
39226
+ listener(error);
39227
+ } catch {
39228
+ }
39229
+ }
39230
+ } finally {
39231
+ entry.inFlight = false;
39232
+ }
39233
+ }
39234
+ function subscribeSharedPoll(config, onData, onError) {
39235
+ const { key, intervalMs, fetcher, shouldContinue } = config;
39236
+ if (!key) return () => {
39237
+ };
39238
+ let entry = entries.get(key);
39239
+ if (!entry) {
39240
+ entry = {
39241
+ intervalMs,
39242
+ fetcher,
39243
+ shouldContinue: shouldContinue ?? (() => true),
39244
+ dataListeners: /* @__PURE__ */ new Set(),
39245
+ errorListeners: /* @__PURE__ */ new Set(),
39246
+ timer: null,
39247
+ controller: null,
39248
+ lastData: void 0,
39249
+ hasData: false,
39250
+ stopped: false,
39251
+ inFlight: false
39252
+ };
39253
+ entries.set(key, entry);
39254
+ }
39255
+ const activeEntry = entry;
39256
+ activeEntry.dataListeners.add(onData);
39257
+ if (onError) activeEntry.errorListeners.add(onError);
39258
+ if (activeEntry.hasData && activeEntry.lastData !== void 0) {
39259
+ try {
39260
+ onData(activeEntry.lastData);
39261
+ } catch {
39262
+ }
39263
+ }
39264
+ if (!activeEntry.stopped && activeEntry.timer === null) {
39265
+ void runPoll(key);
39266
+ activeEntry.timer = setInterval(() => void runPoll(key), activeEntry.intervalMs);
39267
+ }
39268
+ return () => {
39269
+ activeEntry.dataListeners.delete(onData);
39270
+ if (onError) activeEntry.errorListeners.delete(onError);
39271
+ if (activeEntry.dataListeners.size === 0 && activeEntry.errorListeners.size === 0) {
39272
+ clearTimer(activeEntry);
39273
+ entries.delete(key);
39274
+ }
39275
+ };
39276
+ }
39277
+ function stopSharedPoll(key) {
39278
+ const entry = entries.get(key);
39279
+ if (!entry) return;
39280
+ entry.stopped = true;
39281
+ clearTimer(entry);
39282
+ }
39283
+ function useSharedPoll(config, onData, onError) {
39284
+ const fetcherRef = (0, import_react77.useRef)(config.fetcher);
39285
+ fetcherRef.current = config.fetcher;
39286
+ const shouldContinueRef = (0, import_react77.useRef)(config.shouldContinue);
39287
+ shouldContinueRef.current = config.shouldContinue;
39288
+ const onDataRef = (0, import_react77.useRef)(onData);
39289
+ onDataRef.current = onData;
39290
+ const onErrorRef = (0, import_react77.useRef)(onError);
39291
+ onErrorRef.current = onError;
39292
+ const { key, intervalMs } = config;
39293
+ (0, import_react77.useEffect)(() => {
39294
+ if (!key) return;
39295
+ const unsubscribe = subscribeSharedPoll(
39296
+ {
39297
+ key,
39298
+ intervalMs,
39299
+ fetcher: (signal) => fetcherRef.current(signal),
39300
+ shouldContinue: (data) => shouldContinueRef.current ? shouldContinueRef.current(data) : true
39301
+ },
39302
+ (data) => onDataRef.current(data),
39303
+ (error) => onErrorRef.current?.(error)
39304
+ );
39305
+ return unsubscribe;
39306
+ }, [key, intervalMs]);
39307
+ }
39308
+
39309
+ // src/molecules/generic/PresentationJobCard/PresentationJobCard.tsx
39187
39310
  var import_jsx_runtime147 = require("react/jsx-runtime");
39188
39311
  var DownloadIcon = () => /* @__PURE__ */ (0, import_jsx_runtime147.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
39189
39312
  /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
@@ -39240,7 +39363,7 @@ var FORMATS = [
39240
39363
  var ExportModal = ({ formats, title, onClose }) => {
39241
39364
  const available = FORMATS.filter((f) => (formats ?? {})[f.key]);
39242
39365
  const filename = (title ?? "").replace(/[^a-z0-9]/gi, "-").toLowerCase();
39243
- const [downloadingKey, setDownloadingKey] = (0, import_react77.useState)(null);
39366
+ const [downloadingKey, setDownloadingKey] = (0, import_react78.useState)(null);
39244
39367
  const handleDownload = async (fmtKey, url, ext) => {
39245
39368
  if (downloadingKey) return;
39246
39369
  const downloadName = `${filename}${ext}`;
@@ -39308,10 +39431,10 @@ var ExportModal = ({ formats, title, onClose }) => {
39308
39431
  ] });
39309
39432
  };
39310
39433
  var FullscreenModal = ({ url, title, slideCount, initialSlide = 1, onClose }) => {
39311
- const [currentSlide, setCurrentSlide] = (0, import_react77.useState)(initialSlide);
39312
- const [iframeReady, setIframeReady] = (0, import_react77.useState)(false);
39313
- const iframeRef = (0, import_react77.useRef)(null);
39314
- (0, import_react77.useEffect)(() => {
39434
+ const [currentSlide, setCurrentSlide] = (0, import_react78.useState)(initialSlide);
39435
+ const [iframeReady, setIframeReady] = (0, import_react78.useState)(false);
39436
+ const iframeRef = (0, import_react78.useRef)(null);
39437
+ (0, import_react78.useEffect)(() => {
39315
39438
  const onKey = (e) => {
39316
39439
  if (e.key === "Escape") onClose();
39317
39440
  };
@@ -39329,7 +39452,7 @@ var FullscreenModal = ({ url, title, slideCount, initialSlide = 1, onClose }) =>
39329
39452
  window.removeEventListener("message", onMsg);
39330
39453
  };
39331
39454
  }, [onClose, iframeReady]);
39332
- (0, import_react77.useEffect)(() => {
39455
+ (0, import_react78.useEffect)(() => {
39333
39456
  document.body.style.overflow = "hidden";
39334
39457
  return () => {
39335
39458
  document.body.style.overflow = "";
@@ -39428,46 +39551,45 @@ var PresentationJobCard = ({
39428
39551
  }) => {
39429
39552
  const t = th(theme);
39430
39553
  const accentGradient = theme?.gradient;
39431
- const [status, setStatus] = (0, import_react77.useState)(initialStatus);
39432
- const [title, setTitle] = (0, import_react77.useState)(initialTitle);
39433
- const [slideCount, setSlideCount] = (0, import_react77.useState)(initialSlideCount ?? 0);
39434
- const [formats, setFormats] = (0, import_react77.useState)(initialFormats);
39435
- const [error, setError] = (0, import_react77.useState)(initialError);
39436
- const [progress, setProgress] = (0, import_react77.useState)(initialProgress);
39437
- const [showExport, setShowExport] = (0, import_react77.useState)(false);
39438
- const [showFullscreen, setShowFullscreen] = (0, import_react77.useState)(false);
39439
- const [copied, setCopied] = (0, import_react77.useState)(false);
39440
- const [currentSlide, setCurrentSlide] = (0, import_react77.useState)(1);
39441
- const [previewScale, setPreviewScale] = (0, import_react77.useState)(1);
39442
- const [iframeReady, setIframeReady] = (0, import_react77.useState)(false);
39443
- const intervalRef = (0, import_react77.useRef)(null);
39444
- const previewRef = (0, import_react77.useRef)(null);
39445
- const iframeRef = (0, import_react77.useRef)(null);
39446
- (0, import_react77.useEffect)(() => {
39554
+ const [status, setStatus] = (0, import_react78.useState)(initialStatus);
39555
+ const [title, setTitle] = (0, import_react78.useState)(initialTitle);
39556
+ const [slideCount, setSlideCount] = (0, import_react78.useState)(initialSlideCount ?? 0);
39557
+ const [formats, setFormats] = (0, import_react78.useState)(initialFormats);
39558
+ const [error, setError] = (0, import_react78.useState)(initialError);
39559
+ const [progress, setProgress] = (0, import_react78.useState)(initialProgress);
39560
+ const [showExport, setShowExport] = (0, import_react78.useState)(false);
39561
+ const [showFullscreen, setShowFullscreen] = (0, import_react78.useState)(false);
39562
+ const [copied, setCopied] = (0, import_react78.useState)(false);
39563
+ const [currentSlide, setCurrentSlide] = (0, import_react78.useState)(1);
39564
+ const [previewScale, setPreviewScale] = (0, import_react78.useState)(1);
39565
+ const [iframeReady, setIframeReady] = (0, import_react78.useState)(false);
39566
+ const previewRef = (0, import_react78.useRef)(null);
39567
+ const iframeRef = (0, import_react78.useRef)(null);
39568
+ (0, import_react78.useEffect)(() => {
39447
39569
  setStatus(initialStatus);
39448
39570
  }, [initialStatus]);
39449
39571
  const progressPct = initialProgress?.percentage;
39450
39572
  const progressStep = initialProgress?.current_step;
39451
- (0, import_react77.useEffect)(() => {
39573
+ (0, import_react78.useEffect)(() => {
39452
39574
  if (initialProgress) setProgress(initialProgress);
39453
39575
  }, [progressPct, progressStep]);
39454
- (0, import_react77.useEffect)(() => {
39576
+ (0, import_react78.useEffect)(() => {
39455
39577
  if (initialError) setError(initialError);
39456
39578
  }, [initialError]);
39457
- (0, import_react77.useEffect)(() => {
39579
+ (0, import_react78.useEffect)(() => {
39458
39580
  if (initialSlideCount !== void 0) setSlideCount(initialSlideCount);
39459
39581
  }, [initialSlideCount]);
39460
39582
  const htmlUrl = initialFormats?.html_url;
39461
- (0, import_react77.useEffect)(() => {
39583
+ (0, import_react78.useEffect)(() => {
39462
39584
  if (initialFormats) setFormats(initialFormats);
39463
39585
  }, [htmlUrl]);
39464
- (0, import_react77.useEffect)(() => {
39586
+ (0, import_react78.useEffect)(() => {
39465
39587
  if (initialTitle) setTitle(initialTitle);
39466
39588
  }, [initialTitle]);
39467
- const updateScale = (0, import_react77.useCallback)(() => {
39589
+ const updateScale = (0, import_react78.useCallback)(() => {
39468
39590
  if (previewRef.current) setPreviewScale(previewRef.current.offsetWidth / 1280);
39469
39591
  }, []);
39470
- (0, import_react77.useEffect)(() => {
39592
+ (0, import_react78.useEffect)(() => {
39471
39593
  updateScale();
39472
39594
  setIframeReady(false);
39473
39595
  if (typeof ResizeObserver === "undefined") return;
@@ -39475,7 +39597,7 @@ var PresentationJobCard = ({
39475
39597
  if (previewRef.current) ro.observe(previewRef.current);
39476
39598
  return () => ro.disconnect();
39477
39599
  }, [updateScale, formats.html_url]);
39478
- (0, import_react77.useEffect)(() => {
39600
+ (0, import_react78.useEffect)(() => {
39479
39601
  const handler = (e) => {
39480
39602
  if (e.data?.type === "slideChanged") {
39481
39603
  setCurrentSlide(e.data.slide);
@@ -39500,66 +39622,59 @@ var PresentationJobCard = ({
39500
39622
  iframe.contentWindow.postMessage({ type: command }, "*");
39501
39623
  };
39502
39624
  const isTerminal = status === "complete" || status === "failed";
39503
- const onCompleteRef = (0, import_react77.useRef)(onComplete);
39504
- const onFailedRef = (0, import_react77.useRef)(onFailed);
39505
- const hasNotifiedRef = (0, import_react77.useRef)(false);
39625
+ const onCompleteRef = (0, import_react78.useRef)(onComplete);
39626
+ const onFailedRef = (0, import_react78.useRef)(onFailed);
39627
+ const hasNotifiedRef = (0, import_react78.useRef)(false);
39506
39628
  onCompleteRef.current = onComplete;
39507
39629
  onFailedRef.current = onFailed;
39508
- (0, import_react77.useEffect)(() => {
39509
- if (isTerminal || !pollUrl) return;
39510
- const poll = async () => {
39511
- try {
39630
+ useSharedPoll(
39631
+ {
39632
+ key: !isTerminal && pollUrl ? pollUrl : null,
39633
+ intervalMs: 3e3,
39634
+ fetcher: async () => {
39512
39635
  const headers = {};
39513
39636
  if (authToken) {
39514
39637
  headers["Authorization"] = `Bearer ${authToken}`;
39515
39638
  }
39516
39639
  const res = await fetch(pollUrl, { headers });
39517
- if (!res.ok) return;
39518
- const data = await res.json();
39519
- const newStatus = data.status;
39520
- setStatus(newStatus);
39521
- if (data.progress) {
39522
- setProgress(data.progress);
39523
- }
39524
- if (newStatus === "complete" && data.output) {
39525
- const newTitle = data.output.title || initialTitle;
39526
- const newSlideCount = data.output.slide_count || 0;
39527
- const newFormats = data.output.formats || {};
39528
- setTitle(newTitle);
39529
- setSlideCount(newSlideCount);
39530
- setFormats(newFormats);
39531
- if (!hasNotifiedRef.current && onCompleteRef.current) {
39532
- hasNotifiedRef.current = true;
39533
- onCompleteRef.current({
39534
- title: newTitle,
39535
- slide_count: newSlideCount,
39536
- formats: newFormats
39537
- });
39538
- }
39640
+ if (!res.ok) throw new Error(`poll ${res.status}`);
39641
+ return res.json();
39642
+ },
39643
+ shouldContinue: (data) => data.status !== "complete" && data.status !== "failed"
39644
+ },
39645
+ (data) => {
39646
+ const newStatus = data.status;
39647
+ setStatus(newStatus);
39648
+ if (data.progress) {
39649
+ setProgress(data.progress);
39650
+ }
39651
+ if (newStatus === "complete" && data.output) {
39652
+ const newTitle = data.output.title || initialTitle;
39653
+ const newSlideCount = data.output.slide_count || 0;
39654
+ const newFormats = data.output.formats || {};
39655
+ setTitle(newTitle);
39656
+ setSlideCount(newSlideCount);
39657
+ setFormats(newFormats);
39658
+ if (!hasNotifiedRef.current && onCompleteRef.current) {
39659
+ hasNotifiedRef.current = true;
39660
+ onCompleteRef.current({
39661
+ title: newTitle,
39662
+ slide_count: newSlideCount,
39663
+ formats: newFormats
39664
+ });
39539
39665
  }
39540
- if (newStatus === "failed") {
39541
- const errorMsg = data.error || "Job failed";
39542
- setError(errorMsg);
39543
- if (!hasNotifiedRef.current && onFailedRef.current) {
39544
- hasNotifiedRef.current = true;
39545
- onFailedRef.current(errorMsg);
39546
- }
39666
+ }
39667
+ if (newStatus === "failed") {
39668
+ const errorMsg = data.error || "Job failed";
39669
+ setError(errorMsg);
39670
+ if (!hasNotifiedRef.current && onFailedRef.current) {
39671
+ hasNotifiedRef.current = true;
39672
+ onFailedRef.current(errorMsg);
39547
39673
  }
39548
- } catch {
39549
39674
  }
39550
- };
39551
- poll();
39552
- intervalRef.current = setInterval(poll, 3e3);
39553
- return () => {
39554
- if (intervalRef.current) clearInterval(intervalRef.current);
39555
- };
39556
- }, [isTerminal, pollUrl, authToken, initialTitle]);
39557
- (0, import_react77.useEffect)(() => {
39558
- if (isTerminal && intervalRef.current) {
39559
- clearInterval(intervalRef.current);
39560
- intervalRef.current = null;
39561
39675
  }
39562
- }, [isTerminal]);
39676
+ // Transient fetch errors are ignored — the shared loop retries next tick.
39677
+ );
39563
39678
  const handleShare = async () => {
39564
39679
  const link = shareUrl ?? (typeof window !== "undefined" && _job_id ? `${window.location.origin}/p/${_job_id}` : formats.html_url);
39565
39680
  if (!link) return;
@@ -39831,7 +39946,7 @@ var PresentationJobCard = ({
39831
39946
  };
39832
39947
 
39833
39948
  // src/molecules/generic/ResearchReportJobCard/ResearchReportJobCard.tsx
39834
- var import_react78 = require("react");
39949
+ var import_react79 = require("react");
39835
39950
  var import_jsx_runtime148 = require("react/jsx-runtime");
39836
39951
  var DEFAULT_THEME = {
39837
39952
  primary: "#8b5cf6",
@@ -39887,14 +40002,14 @@ function formatTemplateLabel(templateId) {
39887
40002
  return templateId.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
39888
40003
  }
39889
40004
  var FullscreenPreviewModal = ({ url, title, onClose }) => {
39890
- (0, import_react78.useEffect)(() => {
40005
+ (0, import_react79.useEffect)(() => {
39891
40006
  const onKey = (e) => {
39892
40007
  if (e.key === "Escape") onClose();
39893
40008
  };
39894
40009
  document.addEventListener("keydown", onKey);
39895
40010
  return () => document.removeEventListener("keydown", onKey);
39896
40011
  }, [onClose]);
39897
- (0, import_react78.useEffect)(() => {
40012
+ (0, import_react79.useEffect)(() => {
39898
40013
  document.body.style.overflow = "hidden";
39899
40014
  return () => {
39900
40015
  document.body.style.overflow = "";
@@ -39960,162 +40075,154 @@ var ResearchReportJobCard = (props) => {
39960
40075
  compact = false
39961
40076
  } = props;
39962
40077
  const inferredStatus = initialStatus ?? (initialHtmlUrl ? "complete" : void 0);
39963
- const [status, setStatus] = (0, import_react78.useState)(inferredStatus);
39964
- const [title, setTitle] = (0, import_react78.useState)(initialTitle);
39965
- const [depth, setDepth] = (0, import_react78.useState)(initialDepth || "");
39966
- const [sectionCount, setSectionCount] = (0, import_react78.useState)(initialSectionCount ?? 0);
39967
- const [sourceCount, setSourceCount] = (0, import_react78.useState)(initialSourceCount ?? 0);
39968
- const [wordCount, setWordCount] = (0, import_react78.useState)(initialWordCount ?? 0);
39969
- const [summary, setSummary] = (0, import_react78.useState)(initialSummary || "");
39970
- const [htmlUrl, setHtmlUrl] = (0, import_react78.useState)(initialHtmlUrl || "");
39971
- const [generationMode, setGenerationMode] = (0, import_react78.useState)(
40078
+ const [status, setStatus] = (0, import_react79.useState)(inferredStatus);
40079
+ const [title, setTitle] = (0, import_react79.useState)(initialTitle);
40080
+ const [depth, setDepth] = (0, import_react79.useState)(initialDepth || "");
40081
+ const [sectionCount, setSectionCount] = (0, import_react79.useState)(initialSectionCount ?? 0);
40082
+ const [sourceCount, setSourceCount] = (0, import_react79.useState)(initialSourceCount ?? 0);
40083
+ const [wordCount, setWordCount] = (0, import_react79.useState)(initialWordCount ?? 0);
40084
+ const [summary, setSummary] = (0, import_react79.useState)(initialSummary || "");
40085
+ const [htmlUrl, setHtmlUrl] = (0, import_react79.useState)(initialHtmlUrl || "");
40086
+ const [generationMode, setGenerationMode] = (0, import_react79.useState)(
39972
40087
  initialGenerationMode || (initialHtmlUrl ? "template" : "")
39973
40088
  );
39974
- const [templateId, setTemplateId] = (0, import_react78.useState)(initialTemplateId || "");
39975
- const [templateVersionId, setTemplateVersionId] = (0, import_react78.useState)(initialTemplateVersionId || "");
39976
- const [reviewStatus, setReviewStatus] = (0, import_react78.useState)(
40089
+ const [templateId, setTemplateId] = (0, import_react79.useState)(initialTemplateId || "");
40090
+ const [templateVersionId, setTemplateVersionId] = (0, import_react79.useState)(initialTemplateVersionId || "");
40091
+ const [reviewStatus, setReviewStatus] = (0, import_react79.useState)(
39977
40092
  initialReviewStatus || (initialHtmlUrl ? "pending_review" : "")
39978
40093
  );
39979
- const [theme, setTheme] = (0, import_react78.useState)(initialTheme || DEFAULT_THEME);
39980
- const [error, setError] = (0, import_react78.useState)(initialError);
39981
- const [progress, setProgress] = (0, import_react78.useState)(initialProgress);
39982
- const [showPreview, setShowPreview] = (0, import_react78.useState)(false);
39983
- const [previewScale, setPreviewScale] = (0, import_react78.useState)(1);
39984
- const [copied, setCopied] = (0, import_react78.useState)(false);
39985
- const [approving, setApproving] = (0, import_react78.useState)(false);
39986
- const [regenerating, setRegenerating] = (0, import_react78.useState)(false);
39987
- const [approveError, setApproveError] = (0, import_react78.useState)(null);
39988
- const previewRef = (0, import_react78.useRef)(null);
39989
- const intervalRef = (0, import_react78.useRef)(null);
39990
- const onCompleteRef = (0, import_react78.useRef)(onComplete);
39991
- const onFailedRef = (0, import_react78.useRef)(onFailed);
39992
- const hasNotifiedRef = (0, import_react78.useRef)(false);
40094
+ const [theme, setTheme] = (0, import_react79.useState)(initialTheme || DEFAULT_THEME);
40095
+ const [error, setError] = (0, import_react79.useState)(initialError);
40096
+ const [progress, setProgress] = (0, import_react79.useState)(initialProgress);
40097
+ const [showPreview, setShowPreview] = (0, import_react79.useState)(false);
40098
+ const [previewScale, setPreviewScale] = (0, import_react79.useState)(1);
40099
+ const [copied, setCopied] = (0, import_react79.useState)(false);
40100
+ const [approving, setApproving] = (0, import_react79.useState)(false);
40101
+ const [regenerating, setRegenerating] = (0, import_react79.useState)(false);
40102
+ const [approveError, setApproveError] = (0, import_react79.useState)(null);
40103
+ const previewRef = (0, import_react79.useRef)(null);
40104
+ const onCompleteRef = (0, import_react79.useRef)(onComplete);
40105
+ const onFailedRef = (0, import_react79.useRef)(onFailed);
40106
+ const hasNotifiedRef = (0, import_react79.useRef)(false);
39993
40107
  onCompleteRef.current = onComplete;
39994
40108
  onFailedRef.current = onFailed;
39995
- (0, import_react78.useEffect)(() => {
40109
+ (0, import_react79.useEffect)(() => {
39996
40110
  const newStatus = initialStatus ?? (initialHtmlUrl ? "complete" : void 0);
39997
40111
  setStatus(newStatus);
39998
40112
  }, [initialStatus, initialHtmlUrl]);
39999
- (0, import_react78.useEffect)(() => {
40113
+ (0, import_react79.useEffect)(() => {
40000
40114
  if (initialTitle) setTitle(initialTitle);
40001
40115
  }, [initialTitle]);
40002
- (0, import_react78.useEffect)(() => {
40116
+ (0, import_react79.useEffect)(() => {
40003
40117
  if (initialHtmlUrl) setHtmlUrl(initialHtmlUrl);
40004
40118
  }, [initialHtmlUrl]);
40005
- (0, import_react78.useEffect)(() => {
40119
+ (0, import_react79.useEffect)(() => {
40006
40120
  if (initialGenerationMode) setGenerationMode(initialGenerationMode);
40007
40121
  }, [initialGenerationMode]);
40008
- (0, import_react78.useEffect)(() => {
40122
+ (0, import_react79.useEffect)(() => {
40009
40123
  if (initialTemplateId) setTemplateId(initialTemplateId);
40010
40124
  }, [initialTemplateId]);
40011
- (0, import_react78.useEffect)(() => {
40125
+ (0, import_react79.useEffect)(() => {
40012
40126
  if (initialTemplateVersionId) setTemplateVersionId(initialTemplateVersionId);
40013
40127
  }, [initialTemplateVersionId]);
40014
- (0, import_react78.useEffect)(() => {
40128
+ (0, import_react79.useEffect)(() => {
40015
40129
  if (initialReviewStatus) setReviewStatus(initialReviewStatus);
40016
40130
  }, [initialReviewStatus]);
40017
- (0, import_react78.useEffect)(() => {
40131
+ (0, import_react79.useEffect)(() => {
40018
40132
  if (initialDepth) setDepth(initialDepth);
40019
40133
  }, [initialDepth]);
40020
- (0, import_react78.useEffect)(() => {
40134
+ (0, import_react79.useEffect)(() => {
40021
40135
  if (initialSectionCount !== void 0) setSectionCount(initialSectionCount);
40022
40136
  }, [initialSectionCount]);
40023
- (0, import_react78.useEffect)(() => {
40137
+ (0, import_react79.useEffect)(() => {
40024
40138
  if (initialSourceCount !== void 0) setSourceCount(initialSourceCount);
40025
40139
  }, [initialSourceCount]);
40026
- (0, import_react78.useEffect)(() => {
40140
+ (0, import_react79.useEffect)(() => {
40027
40141
  if (initialWordCount !== void 0) setWordCount(initialWordCount);
40028
40142
  }, [initialWordCount]);
40029
- (0, import_react78.useEffect)(() => {
40143
+ (0, import_react79.useEffect)(() => {
40030
40144
  if (initialSummary) setSummary(initialSummary);
40031
40145
  }, [initialSummary]);
40032
40146
  const themePrimary = initialTheme?.primary;
40033
- (0, import_react78.useEffect)(() => {
40147
+ (0, import_react79.useEffect)(() => {
40034
40148
  if (initialTheme) setTheme(initialTheme);
40035
40149
  }, [themePrimary]);
40036
- (0, import_react78.useEffect)(() => {
40150
+ (0, import_react79.useEffect)(() => {
40037
40151
  if (initialError) setError(initialError);
40038
40152
  }, [initialError]);
40039
40153
  const progressPct = initialProgress?.percentage;
40040
40154
  const progressStep = initialProgress?.current_step;
40041
- (0, import_react78.useEffect)(() => {
40155
+ (0, import_react79.useEffect)(() => {
40042
40156
  if (initialProgress) setProgress(initialProgress);
40043
40157
  }, [progressPct, progressStep]);
40044
40158
  const isTerminal = status === "complete" || status === "failed";
40045
40159
  const primaryColor = theme?.primary || DEFAULT_THEME.primary;
40046
40160
  const hasHTML = Boolean(htmlUrl);
40047
- const updateScale = (0, import_react78.useCallback)(() => {
40161
+ const updateScale = (0, import_react79.useCallback)(() => {
40048
40162
  if (previewRef.current) {
40049
40163
  setPreviewScale(previewRef.current.offsetWidth / 800);
40050
40164
  }
40051
40165
  }, []);
40052
- (0, import_react78.useEffect)(() => {
40166
+ (0, import_react79.useEffect)(() => {
40053
40167
  updateScale();
40054
40168
  if (typeof ResizeObserver === "undefined") return;
40055
40169
  const ro = new ResizeObserver(updateScale);
40056
40170
  if (previewRef.current) ro.observe(previewRef.current);
40057
40171
  return () => ro.disconnect();
40058
40172
  }, [updateScale, htmlUrl]);
40059
- (0, import_react78.useEffect)(() => {
40060
- if (isTerminal || !pollUrl) return;
40061
- const poll = async () => {
40062
- try {
40173
+ useSharedPoll(
40174
+ {
40175
+ key: !isTerminal && pollUrl ? pollUrl : null,
40176
+ intervalMs: 3e3,
40177
+ fetcher: async () => {
40063
40178
  const headers = {};
40064
40179
  if (authToken) {
40065
40180
  headers["Authorization"] = `Bearer ${authToken}`;
40066
40181
  }
40067
40182
  const res = await fetch(pollUrl, { headers });
40068
- if (!res.ok) return;
40069
- const data = await res.json();
40070
- const newStatus = data.status;
40071
- setStatus(newStatus);
40072
- if (data.progress) {
40073
- setProgress(data.progress);
40183
+ if (!res.ok) throw new Error(`poll ${res.status}`);
40184
+ return res.json();
40185
+ },
40186
+ shouldContinue: (data) => data.status !== "complete" && data.status !== "failed"
40187
+ },
40188
+ (data) => {
40189
+ const newStatus = data.status;
40190
+ setStatus(newStatus);
40191
+ if (data.progress) {
40192
+ setProgress(data.progress);
40193
+ }
40194
+ if (newStatus === "complete" && data.output) {
40195
+ const output = data.output;
40196
+ setTitle(output.title || initialTitle);
40197
+ setDepth(output.depth || "");
40198
+ setSectionCount(output.section_count || 0);
40199
+ setSourceCount(output.source_count || 0);
40200
+ setWordCount(output.word_count || 0);
40201
+ setSummary(output.executive_summary || "");
40202
+ setHtmlUrl(output.html_url || "");
40203
+ if (output.generation_mode) setGenerationMode(output.generation_mode);
40204
+ if (output.template_id) setTemplateId(output.template_id);
40205
+ if (output.template_version_id) setTemplateVersionId(output.template_version_id);
40206
+ if (output.review_status) setReviewStatus(output.review_status);
40207
+ if (output.theme) {
40208
+ setTheme(output.theme);
40074
40209
  }
40075
- if (newStatus === "complete" && data.output) {
40076
- const output = data.output;
40077
- setTitle(output.title || initialTitle);
40078
- setDepth(output.depth || "");
40079
- setSectionCount(output.section_count || 0);
40080
- setSourceCount(output.source_count || 0);
40081
- setWordCount(output.word_count || 0);
40082
- setSummary(output.executive_summary || "");
40083
- setHtmlUrl(output.html_url || "");
40084
- if (output.generation_mode) setGenerationMode(output.generation_mode);
40085
- if (output.template_id) setTemplateId(output.template_id);
40086
- if (output.template_version_id) setTemplateVersionId(output.template_version_id);
40087
- if (output.review_status) setReviewStatus(output.review_status);
40088
- if (output.theme) {
40089
- setTheme(output.theme);
40090
- }
40091
- if (!hasNotifiedRef.current && onCompleteRef.current) {
40092
- hasNotifiedRef.current = true;
40093
- onCompleteRef.current(output);
40094
- }
40210
+ if (!hasNotifiedRef.current && onCompleteRef.current) {
40211
+ hasNotifiedRef.current = true;
40212
+ onCompleteRef.current(output);
40095
40213
  }
40096
- if (newStatus === "failed") {
40097
- const errorMsg = data.error || "Job failed";
40098
- setError(errorMsg);
40099
- if (!hasNotifiedRef.current && onFailedRef.current) {
40100
- hasNotifiedRef.current = true;
40101
- onFailedRef.current(errorMsg);
40102
- }
40214
+ }
40215
+ if (newStatus === "failed") {
40216
+ const errorMsg = data.error || "Job failed";
40217
+ setError(errorMsg);
40218
+ if (!hasNotifiedRef.current && onFailedRef.current) {
40219
+ hasNotifiedRef.current = true;
40220
+ onFailedRef.current(errorMsg);
40103
40221
  }
40104
- } catch {
40105
40222
  }
40106
- };
40107
- poll();
40108
- intervalRef.current = setInterval(poll, 3e3);
40109
- return () => {
40110
- if (intervalRef.current) clearInterval(intervalRef.current);
40111
- };
40112
- }, [isTerminal, pollUrl, authToken, initialTitle]);
40113
- (0, import_react78.useEffect)(() => {
40114
- if (isTerminal && intervalRef.current) {
40115
- clearInterval(intervalRef.current);
40116
- intervalRef.current = null;
40117
40223
  }
40118
- }, [isTerminal]);
40224
+ // Transient fetch errors are ignored — the shared loop retries next tick.
40225
+ );
40119
40226
  const formatWordCount = (count) => {
40120
40227
  if (count >= 1e3) return `${(count / 1e3).toFixed(1)}k`;
40121
40228
  return count.toString();
@@ -40539,7 +40646,7 @@ var ResearchReportJobCard = (props) => {
40539
40646
  };
40540
40647
 
40541
40648
  // src/molecules/generic/WebSearchJobCard/WebSearchJobCard.tsx
40542
- var import_react79 = require("react");
40649
+ var import_react80 = require("react");
40543
40650
  var import_jsx_runtime149 = require("react/jsx-runtime");
40544
40651
  var SearchIcon = () => /* @__PURE__ */ (0, import_jsx_runtime149.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
40545
40652
  /* @__PURE__ */ (0, import_jsx_runtime149.jsx)("circle", { cx: "11", cy: "11", r: "8" }),
@@ -40568,99 +40675,91 @@ var WebSearchJobCard = ({
40568
40675
  onFailed,
40569
40676
  compact = false
40570
40677
  }) => {
40571
- const [status, setStatus] = (0, import_react79.useState)(initialStatus);
40572
- const [query, setQuery] = (0, import_react79.useState)(initialQuery || initialTitle || "");
40573
- const [resultCount, setResultCount] = (0, import_react79.useState)(initialResultCount ?? 0);
40574
- const [searchCount, setSearchCount] = (0, import_react79.useState)(initialSearchCount ?? 0);
40575
- const [summary, setSummary] = (0, import_react79.useState)(initialSummary || "");
40576
- const [results, setResults] = (0, import_react79.useState)(initialResults || []);
40577
- const [error, setError] = (0, import_react79.useState)(initialError);
40578
- const [progress, setProgress] = (0, import_react79.useState)(initialProgress);
40579
- const intervalRef = (0, import_react79.useRef)(null);
40580
- const onCompleteRef = (0, import_react79.useRef)(onComplete);
40581
- const onFailedRef = (0, import_react79.useRef)(onFailed);
40582
- const hasNotifiedRef = (0, import_react79.useRef)(false);
40678
+ const [status, setStatus] = (0, import_react80.useState)(initialStatus);
40679
+ const [query, setQuery] = (0, import_react80.useState)(initialQuery || initialTitle || "");
40680
+ const [resultCount, setResultCount] = (0, import_react80.useState)(initialResultCount ?? 0);
40681
+ const [searchCount, setSearchCount] = (0, import_react80.useState)(initialSearchCount ?? 0);
40682
+ const [summary, setSummary] = (0, import_react80.useState)(initialSummary || "");
40683
+ const [results, setResults] = (0, import_react80.useState)(initialResults || []);
40684
+ const [error, setError] = (0, import_react80.useState)(initialError);
40685
+ const [progress, setProgress] = (0, import_react80.useState)(initialProgress);
40686
+ const onCompleteRef = (0, import_react80.useRef)(onComplete);
40687
+ const onFailedRef = (0, import_react80.useRef)(onFailed);
40688
+ const hasNotifiedRef = (0, import_react80.useRef)(false);
40583
40689
  onCompleteRef.current = onComplete;
40584
40690
  onFailedRef.current = onFailed;
40585
- (0, import_react79.useEffect)(() => {
40691
+ (0, import_react80.useEffect)(() => {
40586
40692
  setStatus(initialStatus);
40587
40693
  }, [initialStatus]);
40588
- (0, import_react79.useEffect)(() => {
40694
+ (0, import_react80.useEffect)(() => {
40589
40695
  if (initialQuery) setQuery(initialQuery);
40590
40696
  }, [initialQuery]);
40591
- (0, import_react79.useEffect)(() => {
40697
+ (0, import_react80.useEffect)(() => {
40592
40698
  if (initialTitle && !initialQuery) setQuery(initialTitle);
40593
40699
  }, [initialTitle, initialQuery]);
40594
- (0, import_react79.useEffect)(() => {
40700
+ (0, import_react80.useEffect)(() => {
40595
40701
  if (initialResultCount !== void 0) setResultCount(initialResultCount);
40596
40702
  }, [initialResultCount]);
40597
- (0, import_react79.useEffect)(() => {
40703
+ (0, import_react80.useEffect)(() => {
40598
40704
  if (initialSearchCount !== void 0) setSearchCount(initialSearchCount);
40599
40705
  }, [initialSearchCount]);
40600
- (0, import_react79.useEffect)(() => {
40706
+ (0, import_react80.useEffect)(() => {
40601
40707
  if (initialSummary) setSummary(initialSummary);
40602
40708
  }, [initialSummary]);
40603
- (0, import_react79.useEffect)(() => {
40709
+ (0, import_react80.useEffect)(() => {
40604
40710
  if (initialResults) setResults(initialResults);
40605
40711
  }, [initialResults]);
40606
- (0, import_react79.useEffect)(() => {
40712
+ (0, import_react80.useEffect)(() => {
40607
40713
  if (initialError) setError(initialError);
40608
40714
  }, [initialError]);
40609
40715
  const progressPct = initialProgress?.percentage;
40610
40716
  const progressStep = initialProgress?.current_step;
40611
- (0, import_react79.useEffect)(() => {
40717
+ (0, import_react80.useEffect)(() => {
40612
40718
  if (initialProgress) setProgress(initialProgress);
40613
40719
  }, [progressPct, progressStep]);
40614
40720
  const isTerminal = status === "complete" || status === "failed";
40615
- (0, import_react79.useEffect)(() => {
40616
- if (isTerminal || !pollUrl) return;
40617
- const poll = async () => {
40618
- try {
40721
+ useSharedPoll(
40722
+ {
40723
+ key: !isTerminal && pollUrl ? pollUrl : null,
40724
+ intervalMs: 3e3,
40725
+ fetcher: async () => {
40619
40726
  const headers = {};
40620
40727
  if (authToken) headers["Authorization"] = `Bearer ${authToken}`;
40621
40728
  const res = await fetch(pollUrl, { headers });
40622
- if (!res.ok) return;
40623
- const data = await res.json();
40624
- const newStatus = data.status;
40625
- setStatus(newStatus);
40626
- if (data.progress) {
40627
- setProgress(data.progress);
40628
- }
40629
- if (newStatus === "complete" && data.output) {
40630
- const output = data.output;
40631
- setQuery(output.query || "");
40632
- setResultCount(output.result_count ?? 0);
40633
- setSearchCount(output.search_count ?? 0);
40634
- setSummary(output.summary || "");
40635
- setResults(output.results || []);
40636
- if (!hasNotifiedRef.current && onCompleteRef.current) {
40637
- hasNotifiedRef.current = true;
40638
- onCompleteRef.current(output);
40639
- }
40729
+ if (!res.ok) throw new Error(`poll ${res.status}`);
40730
+ return res.json();
40731
+ },
40732
+ shouldContinue: (data) => data.status !== "complete" && data.status !== "failed"
40733
+ },
40734
+ (data) => {
40735
+ const newStatus = data.status;
40736
+ setStatus(newStatus);
40737
+ if (data.progress) {
40738
+ setProgress(data.progress);
40739
+ }
40740
+ if (newStatus === "complete" && data.output) {
40741
+ const output = data.output;
40742
+ setQuery(output.query || "");
40743
+ setResultCount(output.result_count ?? 0);
40744
+ setSearchCount(output.search_count ?? 0);
40745
+ setSummary(output.summary || "");
40746
+ setResults(output.results || []);
40747
+ if (!hasNotifiedRef.current && onCompleteRef.current) {
40748
+ hasNotifiedRef.current = true;
40749
+ onCompleteRef.current(output);
40640
40750
  }
40641
- if (newStatus === "failed") {
40642
- const errorMsg = data.error || "Job failed";
40643
- setError(errorMsg);
40644
- if (!hasNotifiedRef.current && onFailedRef.current) {
40645
- hasNotifiedRef.current = true;
40646
- onFailedRef.current(errorMsg);
40647
- }
40751
+ }
40752
+ if (newStatus === "failed") {
40753
+ const errorMsg = data.error || "Job failed";
40754
+ setError(errorMsg);
40755
+ if (!hasNotifiedRef.current && onFailedRef.current) {
40756
+ hasNotifiedRef.current = true;
40757
+ onFailedRef.current(errorMsg);
40648
40758
  }
40649
- } catch {
40650
40759
  }
40651
- };
40652
- poll();
40653
- intervalRef.current = setInterval(poll, 3e3);
40654
- return () => {
40655
- if (intervalRef.current) clearInterval(intervalRef.current);
40656
- };
40657
- }, [isTerminal, pollUrl, authToken]);
40658
- (0, import_react79.useEffect)(() => {
40659
- if (isTerminal && intervalRef.current) {
40660
- clearInterval(intervalRef.current);
40661
- intervalRef.current = null;
40662
40760
  }
40663
- }, [isTerminal]);
40761
+ // Transient fetch errors are ignored — the shared loop retries next tick.
40762
+ );
40664
40763
  if (status === "pending" || status === "running") {
40665
40764
  const pct = progress?.percentage ?? 0;
40666
40765
  const step = progress?.current_step ?? "Starting web search...";
@@ -40800,10 +40899,10 @@ var WebSearchJobCard = ({
40800
40899
  };
40801
40900
 
40802
40901
  // src/molecules/creator-discovery/CampaignSeedCard/CampaignSeedCard.tsx
40803
- var import_react81 = __toESM(require("react"), 1);
40902
+ var import_react82 = __toESM(require("react"), 1);
40804
40903
 
40805
40904
  // src/molecules/creator-discovery/SearchSpecCard/CustomFieldRenderers.tsx
40806
- var import_react80 = require("react");
40905
+ var import_react81 = require("react");
40807
40906
 
40808
40907
  // src/lib/countries.ts
40809
40908
  var countries = [
@@ -41015,10 +41114,10 @@ var CountrySelectEdit = ({
41015
41114
  value,
41016
41115
  onChange
41017
41116
  }) => {
41018
- const [isDropdownOpen, setIsDropdownOpen] = (0, import_react80.useState)(false);
41019
- const [searchTerm, setSearchTerm] = (0, import_react80.useState)("");
41020
- const dropdownRef = (0, import_react80.useRef)(null);
41021
- (0, import_react80.useEffect)(() => {
41117
+ const [isDropdownOpen, setIsDropdownOpen] = (0, import_react81.useState)(false);
41118
+ const [searchTerm, setSearchTerm] = (0, import_react81.useState)("");
41119
+ const dropdownRef = (0, import_react81.useRef)(null);
41120
+ (0, import_react81.useEffect)(() => {
41022
41121
  const handleClickOutside = (event) => {
41023
41122
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
41024
41123
  setIsDropdownOpen(false);
@@ -41027,7 +41126,7 @@ var CountrySelectEdit = ({
41027
41126
  document.addEventListener("mousedown", handleClickOutside);
41028
41127
  return () => document.removeEventListener("mousedown", handleClickOutside);
41029
41128
  }, []);
41030
- const inputValue = (0, import_react80.useMemo)(() => {
41129
+ const inputValue = (0, import_react81.useMemo)(() => {
41031
41130
  if (Array.isArray(value)) return value;
41032
41131
  if (typeof value === "string" && value.trim() !== "") {
41033
41132
  const foundCountry = countries.find(
@@ -41128,7 +41227,7 @@ var CountrySelectEdit = ({
41128
41227
  ] });
41129
41228
  };
41130
41229
  var CountrySelectDisplay = ({ value }) => {
41131
- const displayValues = (0, import_react80.useMemo)(() => {
41230
+ const displayValues = (0, import_react81.useMemo)(() => {
41132
41231
  if (Array.isArray(value)) return value;
41133
41232
  if (typeof value === "string" && value.trim() !== "") return [value];
41134
41233
  return [];
@@ -41304,7 +41403,7 @@ var PlatformSelectEdit = ({
41304
41403
  value,
41305
41404
  onChange
41306
41405
  }) => {
41307
- const selectedPlatforms = (0, import_react80.useMemo)(() => {
41406
+ const selectedPlatforms = (0, import_react81.useMemo)(() => {
41308
41407
  if (Array.isArray(value)) return value;
41309
41408
  if (typeof value === "string" && value.trim() !== "") {
41310
41409
  return value.split(",").map((s) => s.trim()).filter(Boolean);
@@ -41323,7 +41422,7 @@ var PlatformSelectEdit = ({
41323
41422
  onChange([...selectedPlatforms, platform]);
41324
41423
  }
41325
41424
  };
41326
- const options = (0, import_react80.useMemo)(() => {
41425
+ const options = (0, import_react81.useMemo)(() => {
41327
41426
  return DEFAULT_PLATFORMS;
41328
41427
  }, []);
41329
41428
  return /* @__PURE__ */ (0, import_jsx_runtime150.jsx)("div", { className: "flex flex-wrap gap-4 py-2", children: options.map((platform) => /* @__PURE__ */ (0, import_jsx_runtime150.jsxs)(
@@ -41349,7 +41448,7 @@ var PlatformSelectEdit = ({
41349
41448
  )) });
41350
41449
  };
41351
41450
  var PlatformSelectDisplay = ({ value }) => {
41352
- const displayValues = (0, import_react80.useMemo)(() => {
41451
+ const displayValues = (0, import_react81.useMemo)(() => {
41353
41452
  if (Array.isArray(value)) return value;
41354
41453
  if (typeof value === "string" && value.trim() !== "") {
41355
41454
  return value.split(",").map((s) => s.trim()).filter(Boolean);
@@ -41509,7 +41608,7 @@ function buildCampaignSeedFields(data) {
41509
41608
  return generated;
41510
41609
  });
41511
41610
  }
41512
- var CampaignSeedCard = import_react81.default.memo(
41611
+ var CampaignSeedCard = import_react82.default.memo(
41513
41612
  ({
41514
41613
  selectionStatus,
41515
41614
  isLatestMessage = true,
@@ -41521,7 +41620,7 @@ var CampaignSeedCard = import_react81.default.memo(
41521
41620
  sendMessage,
41522
41621
  ...formCardProps
41523
41622
  }) => {
41524
- const fields = (0, import_react81.useMemo)(() => {
41623
+ const fields = (0, import_react82.useMemo)(() => {
41525
41624
  return providedFields || buildCampaignSeedFields(data);
41526
41625
  }, [providedFields, data]);
41527
41626
  const handleProceed = () => {
@@ -41555,7 +41654,7 @@ var CampaignSeedCard = import_react81.default.memo(
41555
41654
  CampaignSeedCard.displayName = "CampaignSeedCard";
41556
41655
 
41557
41656
  // src/molecules/creator-discovery/SearchSpecCard/SearchSpecCard.tsx
41558
- var import_react82 = __toESM(require("react"), 1);
41657
+ var import_react83 = __toESM(require("react"), 1);
41559
41658
  var import_jsx_runtime152 = require("react/jsx-runtime");
41560
41659
  var ObjectDisplay2 = ({ value }) => {
41561
41660
  if (!value || typeof value !== "object") return null;
@@ -41671,7 +41770,7 @@ function buildSearchSpecFields(data) {
41671
41770
  return generated;
41672
41771
  });
41673
41772
  }
41674
- var SearchSpecCard = import_react82.default.memo(
41773
+ var SearchSpecCard = import_react83.default.memo(
41675
41774
  ({
41676
41775
  selectionStatus,
41677
41776
  isLatestMessage = true,
@@ -41685,7 +41784,7 @@ var SearchSpecCard = import_react82.default.memo(
41685
41784
  ...formCardProps
41686
41785
  }) => {
41687
41786
  const resolvedData = data || specData;
41688
- const fields = (0, import_react82.useMemo)(() => {
41787
+ const fields = (0, import_react83.useMemo)(() => {
41689
41788
  return providedFields || buildSearchSpecFields(resolvedData ?? {});
41690
41789
  }, [providedFields, resolvedData]);
41691
41790
  const handleProceed = () => {
@@ -41721,13 +41820,27 @@ var SearchSpecCard = import_react82.default.memo(
41721
41820
  SearchSpecCard.displayName = "SearchSpecCard";
41722
41821
 
41723
41822
  // src/molecules/creator-discovery/MCQCard/MCQCard.tsx
41724
- var import_react83 = __toESM(require("react"), 1);
41823
+ var import_react84 = __toESM(require("react"), 1);
41725
41824
 
41726
41825
  // src/lib/auth-provider.ts
41727
41826
  var _provider = null;
41827
+ var _onUnauthorized = null;
41728
41828
  function setPxAuthTokenProvider(provider) {
41729
41829
  _provider = provider;
41730
41830
  }
41831
+ function setPxUnauthorizedHandler(handler) {
41832
+ _onUnauthorized = handler;
41833
+ }
41834
+ function notifyPxUnauthorized(status) {
41835
+ if (status !== 401) return false;
41836
+ if (_onUnauthorized) {
41837
+ try {
41838
+ _onUnauthorized();
41839
+ } catch {
41840
+ }
41841
+ }
41842
+ return true;
41843
+ }
41731
41844
  function getPxAuthToken() {
41732
41845
  if (_provider) {
41733
41846
  try {
@@ -41797,6 +41910,7 @@ async function defaultFetchSelections(sessionId) {
41797
41910
  body: "{}"
41798
41911
  }
41799
41912
  );
41913
+ if (res.status === 401) notifyPxUnauthorized(res.status);
41800
41914
  if (!res.ok) return {};
41801
41915
  const data = await res.json();
41802
41916
  const selections = data.selections || {};
@@ -41814,7 +41928,7 @@ async function defaultFetchSelections(sessionId) {
41814
41928
  async function defaultPersistSelection(sessionId, questionKey, value) {
41815
41929
  setLocalSelection(sessionId, questionKey, value);
41816
41930
  try {
41817
- await fetch(
41931
+ const res = await fetch(
41818
41932
  `${getBaseUrl()}/sessions/${sessionId}/mcq-selections`,
41819
41933
  {
41820
41934
  method: "PATCH",
@@ -41822,6 +41936,7 @@ async function defaultPersistSelection(sessionId, questionKey, value) {
41822
41936
  body: JSON.stringify({ question_key: questionKey, value })
41823
41937
  }
41824
41938
  );
41939
+ if (res.status === 401) notifyPxUnauthorized(res.status);
41825
41940
  } catch (err) {
41826
41941
  console.warn("[MCQ persist failed]", err);
41827
41942
  }
@@ -41875,7 +41990,7 @@ function inferSelectionLimits(text, optionCount) {
41875
41990
  }
41876
41991
  return null;
41877
41992
  }
41878
- var MCQCard = import_react83.default.memo(
41993
+ var MCQCard = import_react84.default.memo(
41879
41994
  ({
41880
41995
  question,
41881
41996
  options,
@@ -41933,12 +42048,12 @@ var MCQCard = import_react83.default.memo(
41933
42048
  if (propsSelectedOption) return [propsSelectedOption];
41934
42049
  return [];
41935
42050
  };
41936
- const [selectedKeys, setSelectedKeys] = import_react83.default.useState(seedSelection);
41937
- const [isProceeded, setIsProceeded] = import_react83.default.useState(
42051
+ const [selectedKeys, setSelectedKeys] = import_react84.default.useState(seedSelection);
42052
+ const [isProceeded, setIsProceeded] = import_react84.default.useState(
41938
42053
  Boolean(propsSelectedOption || propsSelectedOptions && propsSelectedOptions.length)
41939
42054
  );
41940
- const fetchedSessionRef = import_react83.default.useRef("");
41941
- import_react83.default.useEffect(() => {
42055
+ const fetchedSessionRef = import_react84.default.useRef("");
42056
+ import_react84.default.useEffect(() => {
41942
42057
  if (propsSelectedOption) {
41943
42058
  setSelectedKeys([propsSelectedOption]);
41944
42059
  setIsProceeded(true);
@@ -41947,7 +42062,7 @@ var MCQCard = import_react83.default.memo(
41947
42062
  setIsProceeded(true);
41948
42063
  }
41949
42064
  }, [propsSelectedOption, propsSelectedOptions]);
41950
- const buildQuestionKey = import_react83.default.useCallback((sid, q) => {
42065
+ const buildQuestionKey = import_react84.default.useCallback((sid, q) => {
41951
42066
  let hash = 2166136261;
41952
42067
  for (let i = 0; i < q.length; i++) {
41953
42068
  hash ^= q.charCodeAt(i);
@@ -41955,7 +42070,7 @@ var MCQCard = import_react83.default.memo(
41955
42070
  }
41956
42071
  return `mcq_${sid}_${hash.toString(36)}`;
41957
42072
  }, []);
41958
- import_react83.default.useEffect(() => {
42073
+ import_react84.default.useEffect(() => {
41959
42074
  if (!sessionId || !resolvedQuestion) return;
41960
42075
  const fetchKey = `${sessionId}::${resolvedQuestion}`;
41961
42076
  if (fetchedSessionRef.current === fetchKey) return;
@@ -42627,9 +42742,9 @@ var CreatorActionHeader = ({
42627
42742
  };
42628
42743
 
42629
42744
  // src/molecules/creator-discovery/CreatorSearchBox/CreatorSearch.tsx
42630
- var import_react84 = __toESM(require("react"), 1);
42745
+ var import_react85 = __toESM(require("react"), 1);
42631
42746
  var import_jsx_runtime164 = require("react/jsx-runtime");
42632
- var CreatorSearch = import_react84.default.memo(
42747
+ var CreatorSearch = import_react85.default.memo(
42633
42748
  ({
42634
42749
  selectionStatus,
42635
42750
  isLatestMessage = true,
@@ -42638,7 +42753,7 @@ var CreatorSearch = import_react84.default.memo(
42638
42753
  data,
42639
42754
  ...formCardProps
42640
42755
  }) => {
42641
- const fields = (0, import_react84.useMemo)(() => {
42756
+ const fields = (0, import_react85.useMemo)(() => {
42642
42757
  const baseFields = providedFields || generateFieldsFromData(data);
42643
42758
  return baseFields.map((field) => {
42644
42759
  if (field.key === "platforms") {
@@ -42718,10 +42833,10 @@ var CreatorSearch = import_react84.default.memo(
42718
42833
  CreatorSearch.displayName = "CreatorSearch";
42719
42834
 
42720
42835
  // src/molecules/creator-discovery/CampaignConceptCard/CampaignConceptCard.tsx
42721
- var import_react85 = __toESM(require("react"), 1);
42836
+ var import_react86 = __toESM(require("react"), 1);
42722
42837
  var import_framer_motion = require("framer-motion");
42723
42838
  var import_jsx_runtime165 = require("react/jsx-runtime");
42724
- var CampaignConceptCard = import_react85.default.memo(
42839
+ var CampaignConceptCard = import_react86.default.memo(
42725
42840
  ({
42726
42841
  index,
42727
42842
  isRecommended,
@@ -42737,7 +42852,7 @@ var CampaignConceptCard = import_react85.default.memo(
42737
42852
  onAction,
42738
42853
  ...formCardProps
42739
42854
  }) => {
42740
- const [internalIsOpen, setInternalIsOpen] = (0, import_react85.useState)(false);
42855
+ const [internalIsOpen, setInternalIsOpen] = (0, import_react86.useState)(false);
42741
42856
  const isOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalIsOpen;
42742
42857
  const handleToggle = () => {
42743
42858
  if (onToggle) {
@@ -42756,7 +42871,7 @@ var CampaignConceptCard = import_react85.default.memo(
42756
42871
  });
42757
42872
  };
42758
42873
  const effectiveIsLatest = isLatestMessage && !hasUserResponded;
42759
- const fields = (0, import_react85.useMemo)(() => {
42874
+ const fields = (0, import_react86.useMemo)(() => {
42760
42875
  const baseFields = providedFields || generateFieldsFromData(data);
42761
42876
  const FIELD_ORDER = [
42762
42877
  "description",
@@ -42810,10 +42925,10 @@ var CampaignConceptCard = import_react85.default.memo(
42810
42925
  }) });
42811
42926
  }
42812
42927
  if (typeof val === "object") {
42813
- const entries = Object.entries(val);
42814
- if (entries.length === 0)
42928
+ const entries2 = Object.entries(val);
42929
+ if (entries2.length === 0)
42815
42930
  return /* @__PURE__ */ (0, import_jsx_runtime165.jsx)("span", { className: "text-muted-foreground text-sm", children: "-" });
42816
- return /* @__PURE__ */ (0, import_jsx_runtime165.jsx)("div", { className: "space-y-2", children: entries.map(([k, v], idx) => /* @__PURE__ */ (0, import_jsx_runtime165.jsxs)("div", { className: "flex items-center gap-2", children: [
42931
+ return /* @__PURE__ */ (0, import_jsx_runtime165.jsx)("div", { className: "space-y-2", children: entries2.map(([k, v], idx) => /* @__PURE__ */ (0, import_jsx_runtime165.jsxs)("div", { className: "flex items-center gap-2", children: [
42817
42932
  /* @__PURE__ */ (0, import_jsx_runtime165.jsxs)("span", { className: "text-muted-foreground font-medium", children: [
42818
42933
  idx + 1,
42819
42934
  "."
@@ -43068,14 +43183,14 @@ var CampaignConceptCard = import_react85.default.memo(
43068
43183
  CampaignConceptCard.displayName = "CampaignConceptCard";
43069
43184
 
43070
43185
  // src/molecules/creator-discovery/CreatorWidget/CreatorWidget.tsx
43071
- var import_react93 = require("react");
43186
+ var import_react94 = require("react");
43072
43187
 
43073
43188
  // src/molecules/creator-discovery/CreatorWidget/CreatorImageList.tsx
43074
- var import_react86 = require("react");
43189
+ var import_react87 = require("react");
43075
43190
  var import_jsx_runtime166 = require("react/jsx-runtime");
43076
43191
  function useMediaQuery(query) {
43077
- const [matches, setMatches] = (0, import_react86.useState)(false);
43078
- (0, import_react86.useEffect)(() => {
43192
+ const [matches, setMatches] = (0, import_react87.useState)(false);
43193
+ (0, import_react87.useEffect)(() => {
43079
43194
  const media = window.matchMedia(query);
43080
43195
  const listener = () => setMatches(media.matches);
43081
43196
  listener();
@@ -43158,7 +43273,7 @@ function CreatorImageList({
43158
43273
  }
43159
43274
 
43160
43275
  // src/molecules/creator-discovery/CreatorWidget/CreatorProgressBar.tsx
43161
- var import_react87 = require("react");
43276
+ var import_react88 = require("react");
43162
43277
  var import_framer_motion2 = require("framer-motion");
43163
43278
  var import_jsx_runtime167 = require("react/jsx-runtime");
43164
43279
  function truncateName(name, maxLength) {
@@ -43166,8 +43281,8 @@ function truncateName(name, maxLength) {
43166
43281
  return name.substring(0, maxLength) + "...";
43167
43282
  }
43168
43283
  function ProgressBar({ overallPercentage }) {
43169
- const [showTooltip, setShowTooltip] = (0, import_react87.useState)(true);
43170
- (0, import_react87.useEffect)(() => {
43284
+ const [showTooltip, setShowTooltip] = (0, import_react88.useState)(true);
43285
+ (0, import_react88.useEffect)(() => {
43171
43286
  if (overallPercentage && overallPercentage >= 100) {
43172
43287
  setShowTooltip(false);
43173
43288
  }
@@ -43328,7 +43443,7 @@ function CreatorCompactView({
43328
43443
  }
43329
43444
 
43330
43445
  // src/molecules/creator-discovery/CreatorWidget/CreatorExpandedPanel.tsx
43331
- var import_react91 = require("react");
43446
+ var import_react92 = require("react");
43332
43447
  var import_react_dom2 = __toESM(require("react-dom"), 1);
43333
43448
  var import_framer_motion5 = require("framer-motion");
43334
43449
 
@@ -43356,6 +43471,7 @@ async function defaultFetchVersions(params) {
43356
43471
  const versionParam = params.version ? `&version=${params.version}` : "";
43357
43472
  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}`;
43358
43473
  const res = await fetch(url, { headers: buildHeaders2() });
43474
+ if (res.status === 401) notifyPxUnauthorized(res.status);
43359
43475
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
43360
43476
  return res.json();
43361
43477
  }
@@ -43363,6 +43479,7 @@ async function defaultFetchStatus(params) {
43363
43479
  const backend = getBackendOrigin2();
43364
43480
  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}`;
43365
43481
  const res = await fetch(url, { headers: buildHeaders2() });
43482
+ if (res.status === 401) notifyPxUnauthorized(res.status);
43366
43483
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
43367
43484
  return res.json();
43368
43485
  }
@@ -43378,6 +43495,7 @@ async function defaultFetchCreatorDetails(params) {
43378
43495
  version_no: params.versionNo
43379
43496
  })
43380
43497
  });
43498
+ if (res.status === 401) notifyPxUnauthorized(res.status);
43381
43499
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
43382
43500
  return res.json();
43383
43501
  }
@@ -43799,7 +43917,7 @@ function getPlatformIconColor(platform) {
43799
43917
  }
43800
43918
 
43801
43919
  // src/molecules/creator-discovery/CreatorWidget/PostCard.tsx
43802
- var import_react88 = require("react");
43920
+ var import_react89 = require("react");
43803
43921
  var import_jsx_runtime172 = require("react/jsx-runtime");
43804
43922
  var formatFollowerCount = (count) => {
43805
43923
  if (count >= 1e6) {
@@ -43813,8 +43931,8 @@ var formatFollowerCount = (count) => {
43813
43931
  return Math.floor(count).toString();
43814
43932
  };
43815
43933
  function PostCard({ post, platformUsername }) {
43816
- const [expanded, setExpanded] = (0, import_react88.useState)(false);
43817
- const [errored, setErrored] = (0, import_react88.useState)(false);
43934
+ const [expanded, setExpanded] = (0, import_react89.useState)(false);
43935
+ const [errored, setErrored] = (0, import_react89.useState)(false);
43818
43936
  const thumbnail = post.thumbnail_url || post.thumbnail || post.image || "";
43819
43937
  const likes = post.engagement?.likes ?? post.likes ?? null;
43820
43938
  const comments = post.engagement?.comments ?? post.comments ?? null;
@@ -44024,7 +44142,7 @@ function PlatformPostsSection({
44024
44142
  }
44025
44143
 
44026
44144
  // src/molecules/creator-discovery/CreatorWidget/BrandCollaborationsList.tsx
44027
- var import_react89 = require("react");
44145
+ var import_react90 = require("react");
44028
44146
  var import_react_dom = __toESM(require("react-dom"), 1);
44029
44147
  var import_framer_motion3 = require("framer-motion");
44030
44148
  var import_jsx_runtime174 = require("react/jsx-runtime");
@@ -44226,8 +44344,8 @@ function BrandMentionDetails({
44226
44344
  function BrandCollaborationsList({
44227
44345
  brandBreakdown
44228
44346
  }) {
44229
- const [openDetails, setOpenDetails] = (0, import_react89.useState)(false);
44230
- const [selectedBrand, setSelectedBrand] = (0, import_react89.useState)("");
44347
+ const [openDetails, setOpenDetails] = (0, import_react90.useState)(false);
44348
+ const [selectedBrand, setSelectedBrand] = (0, import_react90.useState)("");
44231
44349
  if (!brandBreakdown?.insights?.brandBreakdown || brandBreakdown.insights.brandBreakdown.length === 0) {
44232
44350
  return null;
44233
44351
  }
@@ -44286,7 +44404,7 @@ function BrandCollaborationsList({
44286
44404
  }
44287
44405
 
44288
44406
  // src/molecules/creator-discovery/CreatorWidget/CreatorGridView.tsx
44289
- var import_react90 = require("react");
44407
+ var import_react91 = require("react");
44290
44408
  var import_framer_motion4 = require("framer-motion");
44291
44409
  var import_jsx_runtime175 = require("react/jsx-runtime");
44292
44410
  var formatFollowerCount3 = (count) => {
@@ -44335,25 +44453,25 @@ var itemsExplanation = [
44335
44453
  { key: "brandSafety", label: "Brand Safety" }
44336
44454
  ];
44337
44455
  function CreatorGridViewCard({ creator }) {
44338
- const [isExpanded, setIsExpanded] = (0, import_react90.useState)(false);
44339
- const [showFullDescription, setShowFullDescription] = (0, import_react90.useState)(false);
44340
- const [isDescriptionOverflowing, setIsDescriptionOverflowing] = (0, import_react90.useState)(false);
44341
- const descriptionRef = (0, import_react90.useRef)(null);
44342
- const cardRef = (0, import_react90.useRef)(null);
44343
- const checkDescriptionOverflow = (0, import_react90.useCallback)(() => {
44456
+ const [isExpanded, setIsExpanded] = (0, import_react91.useState)(false);
44457
+ const [showFullDescription, setShowFullDescription] = (0, import_react91.useState)(false);
44458
+ const [isDescriptionOverflowing, setIsDescriptionOverflowing] = (0, import_react91.useState)(false);
44459
+ const descriptionRef = (0, import_react91.useRef)(null);
44460
+ const cardRef = (0, import_react91.useRef)(null);
44461
+ const checkDescriptionOverflow = (0, import_react91.useCallback)(() => {
44344
44462
  const el = descriptionRef.current;
44345
44463
  if (!el) return;
44346
44464
  setIsDescriptionOverflowing(el.scrollHeight > el.clientHeight + 1);
44347
44465
  }, []);
44348
- (0, import_react90.useEffect)(() => {
44466
+ (0, import_react91.useEffect)(() => {
44349
44467
  checkDescriptionOverflow();
44350
44468
  }, [checkDescriptionOverflow, isExpanded, showFullDescription]);
44351
- (0, import_react90.useEffect)(() => {
44469
+ (0, import_react91.useEffect)(() => {
44352
44470
  const onResize = () => checkDescriptionOverflow();
44353
44471
  window.addEventListener("resize", onResize);
44354
44472
  return () => window.removeEventListener("resize", onResize);
44355
44473
  }, [checkDescriptionOverflow]);
44356
- const platformStats = (0, import_react90.useMemo)(() => {
44474
+ const platformStats = (0, import_react91.useMemo)(() => {
44357
44475
  return [
44358
44476
  {
44359
44477
  platform: "instagram",
@@ -44771,7 +44889,7 @@ function BrandMentionPerformance({ creator }) {
44771
44889
  ] });
44772
44890
  }
44773
44891
  function CreatorFitSummary({ creator, showBrandPerformance }) {
44774
- const [contentExpanded, setContentExpanded] = (0, import_react91.useState)(false);
44892
+ const [contentExpanded, setContentExpanded] = (0, import_react92.useState)(false);
44775
44893
  const hasDeepAnalysis = creator?.sentiment?.deepAnalysis?.deepAnalysis;
44776
44894
  const title = hasDeepAnalysis ? "CREATOR DEEP ANALYSIS" : "CREATOR FIT SUMMARY";
44777
44895
  const content = hasDeepAnalysis ? creator.sentiment.deepAnalysis.deepAnalysis : creator?.sentiment?.aiReasoning || "No data available.";
@@ -44791,7 +44909,7 @@ function CreatorFitSummary({ creator, showBrandPerformance }) {
44791
44909
  ] });
44792
44910
  }
44793
44911
  function ProfileSection({ creator, isValidationComplete }) {
44794
- const [descriptionExpanded, setDescriptionExpanded] = (0, import_react91.useState)(false);
44912
+ const [descriptionExpanded, setDescriptionExpanded] = (0, import_react92.useState)(false);
44795
44913
  const username = creator.platformMetrics?.instagramMetrics?.username ? `@${creator.platformMetrics.instagramMetrics.username}` : creator.platformMetrics?.youtubeMetrics?.channelName ? `@${creator.platformMetrics.youtubeMetrics.channelName}` : creator.platformMetrics?.tiktokMetrics?.username ? `@${creator.platformMetrics.tiktokMetrics.username}` : "";
44796
44914
  const iso2 = normalizeToIso2(creator.country);
44797
44915
  const meta = codeToMeta[iso2];
@@ -44881,7 +44999,7 @@ function CreatorCard({
44881
44999
  creator,
44882
45000
  isValidationComplete
44883
45001
  }) {
44884
- const [detailsExpanded, setDetailsExpanded] = (0, import_react91.useState)(false);
45002
+ const [detailsExpanded, setDetailsExpanded] = (0, import_react92.useState)(false);
44885
45003
  const hasValidBrandMention = (() => {
44886
45004
  const insights = creator?.brandCollaborations?.insights;
44887
45005
  if (!insights) return false;
@@ -44923,7 +45041,7 @@ function CreatorDisplay({
44923
45041
  creators,
44924
45042
  isValidationComplete
44925
45043
  }) {
44926
- const [viewMode, setViewMode] = (0, import_react91.useState)("list");
45044
+ const [viewMode, setViewMode] = (0, import_react92.useState)("list");
44927
45045
  return /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)("div", { className: "px-4", children: [
44928
45046
  /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)("div", { className: "flex justify-end items-center my-3 gap-1", children: [
44929
45047
  /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)("span", { className: "text-xs text-gray600 mr-2", children: [
@@ -45004,10 +45122,10 @@ function CreatorExpandedPanel({
45004
45122
  searchSpec,
45005
45123
  fetchCreatorDetails
45006
45124
  }) {
45007
- const [creators, setCreators] = (0, import_react91.useState)([]);
45008
- const [loading, setLoading] = (0, import_react91.useState)(false);
45125
+ const [creators, setCreators] = (0, import_react92.useState)([]);
45126
+ const [loading, setLoading] = (0, import_react92.useState)(false);
45009
45127
  const fetcher = fetchCreatorDetails ?? defaultFetchCreatorDetails;
45010
- const loadCreators = (0, import_react91.useCallback)(async () => {
45128
+ const loadCreators = (0, import_react92.useCallback)(async () => {
45011
45129
  if (!creatorIds.length) return;
45012
45130
  setLoading(true);
45013
45131
  try {
@@ -45019,7 +45137,7 @@ function CreatorExpandedPanel({
45019
45137
  setLoading(false);
45020
45138
  }
45021
45139
  }, [creatorIds, sessionId, version, fetcher]);
45022
- (0, import_react91.useEffect)(() => {
45140
+ (0, import_react92.useEffect)(() => {
45023
45141
  if (isOpen && creatorIds.length > 0) {
45024
45142
  loadCreators();
45025
45143
  }
@@ -45073,13 +45191,18 @@ function CreatorExpandedPanel({
45073
45191
  }
45074
45192
 
45075
45193
  // src/molecules/creator-discovery/CreatorWidget/useCreatorWidgetPolling.ts
45076
- var import_react92 = require("react");
45194
+ var import_react93 = require("react");
45077
45195
  var DEFAULT_POLLING_CONFIG = {
45078
45196
  pollInterval: 5e3,
45079
45197
  maxDuration: 15 * 60 * 1e3,
45080
45198
  maxErrors: 10,
45081
45199
  secondsPerCreator: 13
45082
45200
  };
45201
+ var formatTime = (seconds) => {
45202
+ if (seconds <= 0) return "to complete";
45203
+ const minutes = Math.floor(seconds / 60);
45204
+ return minutes >= 1 ? `${minutes} min remaining...` : `${seconds} sec remaining...`;
45205
+ };
45083
45206
  function useCreatorWidgetPolling({
45084
45207
  sessionId,
45085
45208
  currentVersion,
@@ -45090,136 +45213,137 @@ function useCreatorWidgetPolling({
45090
45213
  }) {
45091
45214
  const fetchVersions = fetchVersionsProp ?? defaultFetchVersions;
45092
45215
  const fetchStatus = fetchStatusProp ?? defaultFetchStatus;
45093
- const config = (0, import_react92.useMemo)(
45216
+ const config = (0, import_react93.useMemo)(
45094
45217
  () => ({ ...DEFAULT_POLLING_CONFIG, ...pollingConfig }),
45095
45218
  [pollingConfig]
45096
45219
  );
45097
- const [versionData, setVersionData] = (0, import_react92.useState)(null);
45098
- const [totalVersions, setTotalVersions] = (0, import_react92.useState)(0);
45099
- const [selectedVersion, setSelectedVersion] = (0, import_react92.useState)();
45100
- const [isLoadingVersion, setIsLoadingVersion] = (0, import_react92.useState)(false);
45101
- const [isValidationComplete, setIsValidationComplete] = (0, import_react92.useState)(false);
45102
- const [versionStatus, setVersionStatus] = (0, import_react92.useState)("checking");
45103
- const [statusDetails, setStatusDetails] = (0, import_react92.useState)();
45104
- const [timeDisplay, setTimeDisplay] = (0, import_react92.useState)("");
45105
- const [loadingStatus, setLoadingStatus] = (0, import_react92.useState)(true);
45106
- const remainingTimeRef = (0, import_react92.useRef)(0);
45220
+ const [versionData, setVersionData] = (0, import_react93.useState)(null);
45221
+ const [totalVersions, setTotalVersions] = (0, import_react93.useState)(0);
45222
+ const [selectedVersion, setSelectedVersion] = (0, import_react93.useState)();
45223
+ const [isLoadingVersion, setIsLoadingVersion] = (0, import_react93.useState)(false);
45224
+ const [isValidationComplete, setIsValidationComplete] = (0, import_react93.useState)(false);
45225
+ const [versionStatus, setVersionStatus] = (0, import_react93.useState)("checking");
45226
+ const [statusDetails, setStatusDetails] = (0, import_react93.useState)();
45227
+ const [timeDisplay, setTimeDisplay] = (0, import_react93.useState)("");
45228
+ const [loadingStatus, setLoadingStatus] = (0, import_react93.useState)(true);
45229
+ const remainingTimeRef = (0, import_react93.useRef)(0);
45230
+ const countdownRef = (0, import_react93.useRef)(null);
45107
45231
  const requestedVersion = selectedVersion ?? currentVersion ?? versionData?.currentVersion;
45108
- const fetchVersionData = (0, import_react92.useCallback)(async () => {
45109
- if (!sessionId) return;
45110
- if (!versionData) setIsLoadingVersion(true);
45111
- try {
45112
- const data = await fetchVersions({
45113
- sessionId,
45114
- version: requestedVersion,
45115
- validated: isValidationComplete
45116
- });
45117
- if (data.success !== false) {
45232
+ const updateStatus = (0, import_react93.useCallback)(
45233
+ (status) => {
45234
+ setVersionStatus(status);
45235
+ onStatusChange?.(status);
45236
+ },
45237
+ [onStatusChange]
45238
+ );
45239
+ const versionKey = sessionId ? `creator:versions:${sessionId}:${requestedVersion ?? "latest"}:${isValidationComplete ? 1 : 0}` : null;
45240
+ useSharedPoll(
45241
+ {
45242
+ key: versionKey,
45243
+ intervalMs: config.pollInterval,
45244
+ fetcher: async () => {
45245
+ if (!versionData) setIsLoadingVersion(true);
45246
+ return fetchVersions({
45247
+ sessionId,
45248
+ version: requestedVersion,
45249
+ validated: isValidationComplete
45250
+ });
45251
+ },
45252
+ shouldContinue: (data) => !((data?.totalVersions || 0) > 0)
45253
+ },
45254
+ (data) => {
45255
+ if (data && data.success !== false) {
45118
45256
  setVersionData(data);
45119
45257
  setTotalVersions(data.totalVersions || 0);
45120
45258
  }
45121
- } catch (err) {
45122
- if (err.name !== "AbortError") {
45259
+ setIsLoadingVersion(false);
45260
+ },
45261
+ (err) => {
45262
+ if (err?.name !== "AbortError") {
45123
45263
  console.error("Error fetching creator version:", err);
45124
45264
  }
45125
- } finally {
45126
45265
  setIsLoadingVersion(false);
45127
45266
  }
45128
- }, [sessionId, requestedVersion, isValidationComplete, fetchVersions, versionData]);
45129
- (0, import_react92.useEffect)(() => {
45130
- fetchVersionData();
45131
- }, [sessionId, requestedVersion, isValidationComplete]);
45132
- (0, import_react92.useEffect)(() => {
45133
- if (totalVersions > 0 || !sessionId) return;
45134
- const interval = setInterval(() => {
45135
- if (totalVersions === 0) fetchVersionData();
45136
- }, config.pollInterval);
45137
- return () => clearInterval(interval);
45138
- }, [totalVersions, sessionId, fetchVersionData, config.pollInterval]);
45139
- (0, import_react92.useEffect)(() => {
45140
- if (!selectedVersion && !requestedVersion) return;
45141
- const activeVersion = selectedVersion ?? requestedVersion;
45142
- let isMounted = true;
45143
- let intervalId = null;
45144
- let timerIntervalId = null;
45145
- let elapsed = 0;
45146
- let errorCount = 0;
45267
+ );
45268
+ const activeVersion = selectedVersion ?? requestedVersion;
45269
+ const statusKey = sessionId && activeVersion != null ? `creator:status:${sessionId}:${activeVersion}` : null;
45270
+ const errorCountRef = (0, import_react93.useRef)(0);
45271
+ const deadlineRef = (0, import_react93.useRef)(0);
45272
+ const doneRef = (0, import_react93.useRef)(false);
45273
+ const stopCountdown = (0, import_react93.useCallback)(() => {
45274
+ if (countdownRef.current) {
45275
+ clearInterval(countdownRef.current);
45276
+ countdownRef.current = null;
45277
+ }
45278
+ setTimeDisplay("");
45279
+ }, []);
45280
+ (0, import_react93.useEffect)(() => {
45281
+ if (statusKey == null) return;
45147
45282
  setLoadingStatus(true);
45148
45283
  setStatusDetails(void 0);
45149
45284
  setVersionStatus("checking");
45285
+ errorCountRef.current = 0;
45286
+ doneRef.current = false;
45287
+ deadlineRef.current = Date.now() + config.maxDuration;
45150
45288
  const creatorLength2 = versionData?.length || 0;
45151
45289
  remainingTimeRef.current = creatorLength2 > 0 ? creatorLength2 * config.secondsPerCreator : 60;
45152
- const formatTime = (seconds) => {
45153
- if (seconds <= 0) return "to complete";
45154
- const minutes = Math.floor(seconds / 60);
45155
- return minutes >= 1 ? `${minutes} min remaining...` : `${seconds} sec remaining...`;
45156
- };
45157
45290
  setTimeDisplay(formatTime(remainingTimeRef.current));
45158
- timerIntervalId = setInterval(() => {
45291
+ countdownRef.current = setInterval(() => {
45159
45292
  if (remainingTimeRef.current > 0) remainingTimeRef.current -= 1;
45160
45293
  setTimeDisplay(formatTime(remainingTimeRef.current));
45161
45294
  }, 1e3);
45162
- const updateStatus = (status) => {
45163
- setVersionStatus(status);
45164
- onStatusChange?.(status);
45165
- };
45166
- const stopPolling = () => {
45167
- if (intervalId) clearInterval(intervalId);
45168
- if (timerIntervalId) clearInterval(timerIntervalId);
45169
- setTimeDisplay("");
45295
+ return () => {
45296
+ if (countdownRef.current) {
45297
+ clearInterval(countdownRef.current);
45298
+ countdownRef.current = null;
45299
+ }
45170
45300
  };
45171
- const pollStatus = async () => {
45172
- try {
45173
- const data = await fetchStatus({
45174
- sessionId,
45175
- versionNo: activeVersion
45176
- });
45177
- if (!isMounted) return;
45178
- if (data?.status) setStatusDetails(data.status);
45301
+ }, [statusKey]);
45302
+ useSharedPoll(
45303
+ {
45304
+ key: statusKey,
45305
+ intervalMs: config.pollInterval,
45306
+ fetcher: async () => fetchStatus({ sessionId, versionNo: activeVersion }),
45307
+ shouldContinue: (data) => {
45308
+ if (Date.now() >= deadlineRef.current) return false;
45179
45309
  const s = data?.status?.status;
45180
- if (s === "completed" || s === "complete") {
45181
- updateStatus(s);
45182
- setIsValidationComplete(true);
45183
- stopPolling();
45184
- return;
45185
- }
45186
- if (s === "failed") {
45187
- updateStatus("failed");
45188
- stopPolling();
45189
- return;
45190
- }
45191
- errorCount = 0;
45192
- updateStatus(s || "in-progress");
45193
- } catch (err) {
45194
- console.error("Error fetching status:", err);
45195
- errorCount++;
45196
- if (errorCount >= config.maxErrors) {
45197
- console.error(`Polling failed after ${config.maxErrors} consecutive errors`);
45198
- updateStatus("failed");
45199
- setLoadingStatus(false);
45200
- stopPolling();
45201
- return;
45202
- }
45203
- } finally {
45204
- setLoadingStatus(false);
45310
+ return !(s === "completed" || s === "complete" || s === "failed");
45205
45311
  }
45206
- };
45207
- pollStatus();
45208
- intervalId = setInterval(() => {
45209
- elapsed += config.pollInterval;
45210
- if (elapsed >= config.maxDuration) {
45211
- console.warn("Stopped polling after max duration");
45212
- stopPolling();
45312
+ },
45313
+ (data) => {
45314
+ if (data?.status) setStatusDetails(data.status);
45315
+ const s = data?.status?.status;
45316
+ if (s === "completed" || s === "complete") {
45317
+ updateStatus(s);
45318
+ setIsValidationComplete(true);
45319
+ doneRef.current = true;
45320
+ stopCountdown();
45321
+ } else if (s === "failed") {
45322
+ updateStatus("failed");
45323
+ doneRef.current = true;
45324
+ stopCountdown();
45213
45325
  } else {
45214
- pollStatus();
45326
+ errorCountRef.current = 0;
45327
+ updateStatus(s || "in-progress");
45215
45328
  }
45216
- }, config.pollInterval);
45217
- return () => {
45218
- isMounted = false;
45219
- stopPolling();
45220
- };
45221
- }, [selectedVersion, requestedVersion, sessionId]);
45222
- const versionNumbers = (0, import_react92.useMemo)(() => {
45329
+ setLoadingStatus(false);
45330
+ },
45331
+ (err) => {
45332
+ console.error("Error fetching status:", err);
45333
+ errorCountRef.current++;
45334
+ if (errorCountRef.current >= config.maxErrors) {
45335
+ console.error(
45336
+ `Polling failed after ${config.maxErrors} consecutive errors`
45337
+ );
45338
+ updateStatus("failed");
45339
+ doneRef.current = true;
45340
+ stopCountdown();
45341
+ if (statusKey) stopSharedPoll(statusKey);
45342
+ }
45343
+ setLoadingStatus(false);
45344
+ }
45345
+ );
45346
+ const versionNumbers = (0, import_react93.useMemo)(() => {
45223
45347
  if (!totalVersions) return [];
45224
45348
  return Array.from({ length: totalVersions }, (_, i) => i + 1);
45225
45349
  }, [totalVersions]);
@@ -45259,7 +45383,7 @@ function CreatorWidgetInner({
45259
45383
  onAction,
45260
45384
  className
45261
45385
  }) {
45262
- const [isExpanded, setIsExpanded] = (0, import_react93.useState)(false);
45386
+ const [isExpanded, setIsExpanded] = (0, import_react94.useState)(false);
45263
45387
  const {
45264
45388
  versionNumbers,
45265
45389
  selectedVersion,
@@ -45280,11 +45404,11 @@ function CreatorWidgetInner({
45280
45404
  pollingConfig,
45281
45405
  onStatusChange
45282
45406
  });
45283
- const handleVersionSelect = (0, import_react93.useCallback)(
45407
+ const handleVersionSelect = (0, import_react94.useCallback)(
45284
45408
  (version) => setSelectedVersion(version),
45285
45409
  [setSelectedVersion]
45286
45410
  );
45287
- const handleViewCreators = (0, import_react93.useCallback)(() => {
45411
+ const handleViewCreators = (0, import_react94.useCallback)(() => {
45288
45412
  setIsExpanded(true);
45289
45413
  onAction?.({
45290
45414
  type: "view-creators",
@@ -45325,10 +45449,10 @@ function CreatorWidgetInner({
45325
45449
  )
45326
45450
  ] });
45327
45451
  }
45328
- var CreatorWidget = (0, import_react93.memo)(CreatorWidgetInner);
45452
+ var CreatorWidget = (0, import_react94.memo)(CreatorWidgetInner);
45329
45453
 
45330
45454
  // src/molecules/analytics/AnalyticsChart.tsx
45331
- var import_react94 = require("react");
45455
+ var import_react95 = require("react");
45332
45456
  var import_jsx_runtime178 = require("react/jsx-runtime");
45333
45457
  function getCSSVar(name) {
45334
45458
  if (typeof document === "undefined") return "";
@@ -45441,16 +45565,16 @@ function AnalyticsChart({
45441
45565
  loading: loadingProp,
45442
45566
  error: errorProp
45443
45567
  }) {
45444
- const [mounted, setMounted] = (0, import_react94.useState)(false);
45445
- const [fetchedConfig, setFetchedConfig] = (0, import_react94.useState)(null);
45446
- const [fetching, setFetching] = (0, import_react94.useState)(false);
45447
- const [fetchError, setFetchError] = (0, import_react94.useState)(null);
45448
- const containerRef = (0, import_react94.useRef)(null);
45449
- const chartRef = (0, import_react94.useRef)(null);
45450
- (0, import_react94.useEffect)(() => {
45568
+ const [mounted, setMounted] = (0, import_react95.useState)(false);
45569
+ const [fetchedConfig, setFetchedConfig] = (0, import_react95.useState)(null);
45570
+ const [fetching, setFetching] = (0, import_react95.useState)(false);
45571
+ const [fetchError, setFetchError] = (0, import_react95.useState)(null);
45572
+ const containerRef = (0, import_react95.useRef)(null);
45573
+ const chartRef = (0, import_react95.useRef)(null);
45574
+ (0, import_react95.useEffect)(() => {
45451
45575
  setMounted(true);
45452
45576
  }, []);
45453
- (0, import_react94.useEffect)(() => {
45577
+ (0, import_react95.useEffect)(() => {
45454
45578
  if (!chartId || configProp) return;
45455
45579
  let cancelled = false;
45456
45580
  setFetching(true);
@@ -45472,7 +45596,7 @@ function AnalyticsChart({
45472
45596
  };
45473
45597
  }, [chartId, apiBase, authToken, configProp]);
45474
45598
  const activeConfig = configProp ?? fetchedConfig;
45475
- (0, import_react94.useEffect)(() => {
45599
+ (0, import_react95.useEffect)(() => {
45476
45600
  if (!mounted || !activeConfig || !containerRef.current) return;
45477
45601
  const container = containerRef.current;
45478
45602
  let cancelled = false;
@@ -45492,7 +45616,7 @@ function AnalyticsChart({
45492
45616
  cancelled = true;
45493
45617
  };
45494
45618
  }, [mounted, activeConfig]);
45495
- (0, import_react94.useEffect)(() => {
45619
+ (0, import_react95.useEffect)(() => {
45496
45620
  return () => {
45497
45621
  if (chartRef.current) {
45498
45622
  try {
@@ -45503,7 +45627,7 @@ function AnalyticsChart({
45503
45627
  }
45504
45628
  };
45505
45629
  }, []);
45506
- (0, import_react94.useEffect)(() => {
45630
+ (0, import_react95.useEffect)(() => {
45507
45631
  if (!mounted || !containerRef.current) return;
45508
45632
  const obs = new ResizeObserver(() => {
45509
45633
  try {
@@ -45985,7 +46109,7 @@ function EmptyContent({ className, ...props }) {
45985
46109
  }
45986
46110
 
45987
46111
  // src/components/ui/field.tsx
45988
- var import_react95 = require("react");
46112
+ var import_react96 = require("react");
45989
46113
  var import_class_variance_authority10 = require("class-variance-authority");
45990
46114
  var import_jsx_runtime181 = require("react/jsx-runtime");
45991
46115
  function FieldSet({ className, ...props }) {
@@ -46168,7 +46292,7 @@ function FieldError({
46168
46292
  errors,
46169
46293
  ...props
46170
46294
  }) {
46171
- const content = (0, import_react95.useMemo)(() => {
46295
+ const content = (0, import_react96.useMemo)(() => {
46172
46296
  if (children) {
46173
46297
  return children;
46174
46298
  }
@@ -47449,18 +47573,18 @@ var FORM_INPUT_ATOM_NAMES = /* @__PURE__ */ new Set([
47449
47573
  "InputOTPAtom",
47450
47574
  "ToggleAtom"
47451
47575
  ]);
47452
- var PXEngineRenderer = import_react96.default.memo(function PXEngineRenderer2({
47576
+ var PXEngineRenderer = import_react97.default.memo(function PXEngineRenderer2({
47453
47577
  schema,
47454
47578
  onAction,
47455
47579
  disabled,
47456
47580
  theme,
47457
47581
  onFormSubmit
47458
47582
  }) {
47459
- const contextTheme = import_react96.default.useContext(WidgetThemeContext);
47583
+ const contextTheme = import_react97.default.useContext(WidgetThemeContext);
47460
47584
  const effectiveTheme = theme ?? contextTheme;
47461
- const formValuesRef = import_react96.default.useRef({});
47462
- const [, forceUpdate] = import_react96.default.useReducer((x) => x + 1, 0);
47463
- const handleInputValueChange = import_react96.default.useCallback((key, value) => {
47585
+ const formValuesRef = import_react97.default.useRef({});
47586
+ const [, forceUpdate] = import_react97.default.useReducer((x) => x + 1, 0);
47587
+ const handleInputValueChange = import_react97.default.useCallback((key, value) => {
47464
47588
  formValuesRef.current[key] = value;
47465
47589
  forceUpdate();
47466
47590
  }, []);
@@ -47468,12 +47592,12 @@ var PXEngineRenderer = import_react96.default.memo(function PXEngineRenderer2({
47468
47592
  const root = schema.root || schema;
47469
47593
  const renderRecursive = (component, index) => {
47470
47594
  if (Array.isArray(component)) {
47471
- return /* @__PURE__ */ (0, import_jsx_runtime188.jsx)(import_react96.default.Fragment, { children: component.map((child, idx) => renderRecursive(child, idx)) }, index !== void 0 ? `array-${index}` : "array-root");
47595
+ return /* @__PURE__ */ (0, import_jsx_runtime188.jsx)(import_react97.default.Fragment, { children: component.map((child, idx) => renderRecursive(child, idx)) }, index !== void 0 ? `array-${index}` : "array-root");
47472
47596
  }
47473
47597
  if (typeof component === "string" || typeof component === "number") {
47474
47598
  return component;
47475
47599
  }
47476
- if (import_react96.default.isValidElement(component)) {
47600
+ if (import_react97.default.isValidElement(component)) {
47477
47601
  return component;
47478
47602
  }
47479
47603
  if (!component || typeof component !== "object") return null;
@@ -47915,7 +48039,9 @@ PXEngineRenderer.displayName = "PXEngineRenderer";
47915
48039
  generateFieldsFromPropDefinitions,
47916
48040
  getPxAuthToken,
47917
48041
  isInputAtom,
48042
+ notifyPxUnauthorized,
47918
48043
  setPxAuthTokenProvider,
48044
+ setPxUnauthorizedHandler,
47919
48045
  submitWidgetToAgent,
47920
48046
  th,
47921
48047
  useCreatorWidgetPolling,