@sylergydigital/issue-pin-sdk 0.6.5 → 0.6.6

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/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  All notable changes to `@sylergydigital/issue-pin-sdk` are documented here.
4
4
 
5
+ ## [0.6.6] - 2026-04-15
6
+
7
+ ### Fixed
8
+ - **SSO handoff for federated pin click-through** — clicking a pin on a 3rd-party app now auto-logs the user into the IssuePin dashboard via `external-sso-launch` magic link, instead of landing on the login page. Falls back to direct link when not in a federated context.
9
+
5
10
  ## [0.6.5] - 2026-04-15
6
11
 
7
12
  ### Added
package/dist/index.cjs CHANGED
@@ -487,6 +487,34 @@ function FeedbackProvider({
487
487
  const onModeChangeUnified = config.onModeChange ?? (config.onFeedbackActiveChange ? ((m) => config.onFeedbackActiveChange(m === "annotate")) : void 0);
488
488
  const controlledModeFromProps = config.mode !== void 0 ? config.mode : config.feedbackActive !== void 0 ? config.feedbackActive ? "annotate" : "view" : void 0;
489
489
  const initialModeUncontrolled = config.mode ?? (config.feedbackActive !== void 0 ? config.feedbackActive ? "annotate" : "view" : "view");
490
+ const openThreadInDashboard = (0, import_react2.useCallback)((threadId) => {
491
+ const threadPath = `/threads/${threadId}`;
492
+ const baseUrl = resolved.siteUrl?.replace(/\/+$/, "") || window.location.origin;
493
+ if (config.apiKey && autoIdentity.accessToken) {
494
+ const functionsBaseUrl = getFunctionsBaseUrl(resolved.supabaseUrl);
495
+ fetch(`${functionsBaseUrl}/external-sso-launch`, {
496
+ method: "POST",
497
+ headers: {
498
+ "Content-Type": "application/json",
499
+ Authorization: `Bearer ${autoIdentity.accessToken}`
500
+ },
501
+ body: JSON.stringify({
502
+ apiKey: config.apiKey,
503
+ nextPath: threadPath
504
+ })
505
+ }).then((res) => res.ok ? res.json() : null).then((data) => {
506
+ if (data?.redirect_url) {
507
+ window.open(data.redirect_url, "_blank", "noopener,noreferrer");
508
+ } else {
509
+ window.open(`${baseUrl}${threadPath}`, "_blank", "noopener,noreferrer");
510
+ }
511
+ }).catch(() => {
512
+ window.open(`${baseUrl}${threadPath}`, "_blank", "noopener,noreferrer");
513
+ });
514
+ return;
515
+ }
516
+ window.open(`${baseUrl}${threadPath}`, "_blank", "noopener,noreferrer");
517
+ }, [resolved.supabaseUrl, resolved.siteUrl, config.apiKey, autoIdentity.accessToken]);
490
518
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
491
519
  FeedbackProviderInner,
492
520
  {
@@ -513,6 +541,7 @@ function FeedbackProvider({
513
541
  userId: effectiveUserId,
514
542
  userEmail: effectiveEmail,
515
543
  userDisplayName: effectiveDisplayName,
544
+ openThreadInDashboard,
516
545
  children
517
546
  }
518
547
  );
@@ -541,7 +570,8 @@ function FeedbackProviderInner({
541
570
  debug,
542
571
  userId,
543
572
  userEmail,
544
- userDisplayName
573
+ userDisplayName,
574
+ openThreadInDashboard
545
575
  }) {
546
576
  const debugLog = (0, import_react2.useCallback)((message, extra) => {
547
577
  if (!debug) return;
@@ -932,7 +962,8 @@ function FeedbackProviderInner({
932
962
  setPendingScreenshotPin,
933
963
  submitThread,
934
964
  submitScreenshotThread,
935
- refreshThreads: fetchThreads
965
+ refreshThreads: fetchThreads,
966
+ openThreadInDashboard
936
967
  },
937
968
  children: [
938
969
  children,
@@ -1292,7 +1323,7 @@ function ThreadPins() {
1292
1323
  const signedUrlCache = (0, import_react5.useRef)({});
1293
1324
  const threads = ctx?.threads ?? EMPTY_THREADS;
1294
1325
  const client = ctx?.client;
1295
- const threadBaseUrl = ctx?.siteUrl?.replace(/\/+$/, "") || window.location.origin;
1326
+ const openThreadInDashboard = ctx?.openThreadInDashboard;
1296
1327
  const scrollContainer = ctx?.scrollContainer;
1297
1328
  const container = scrollContainer?.ref.current ?? null;
1298
1329
  const getSignedUrl = (0, import_react5.useCallback)(async (path) => {
@@ -1416,8 +1447,8 @@ function ThreadPins() {
1416
1447
  });
1417
1448
  return;
1418
1449
  }
1419
- window.open(`${threadBaseUrl}/threads/${pin.threadId}`, "_blank", "noopener,noreferrer");
1420
- }, [getSignedUrl, threadBaseUrl]);
1450
+ openThreadInDashboard?.(pin.threadId);
1451
+ }, [getSignedUrl, openThreadInDashboard]);
1421
1452
  const containerLayer = (0, import_react5.useMemo)(() => {
1422
1453
  if (!container || containerPositions.length === 0) return null;
1423
1454
  const { width, height } = getContainerContentSize(container);
@@ -1544,7 +1575,7 @@ function ReviewSurfaceOverlay() {
1544
1575
  const mode = ctx?.mode ?? "view";
1545
1576
  const reviewUrl = ctx?.reviewUrl ?? null;
1546
1577
  const threads = ctx?.threads ?? EMPTY_THREADS2;
1547
- const threadBaseUrl = ctx?.siteUrl?.replace(/\/+$/, "") || window.location.origin;
1578
+ const openThreadInDashboard = ctx?.openThreadInDashboard;
1548
1579
  const updateMetrics = (0, import_react6.useCallback)(() => {
1549
1580
  const iframe = iframeRef.current;
1550
1581
  if (!iframe) return;
@@ -1722,7 +1753,7 @@ function ReviewSurfaceOverlay() {
1722
1753
  index: index + 1,
1723
1754
  left,
1724
1755
  top,
1725
- onClick: () => window.open(`${threadBaseUrl}/threads/${thread.id}`, "_blank", "noopener,noreferrer")
1756
+ onClick: () => openThreadInDashboard?.(thread.id)
1726
1757
  },
1727
1758
  thread.id
1728
1759
  );