issue-sticker 0.8.0 → 0.8.1

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,12 @@
2
2
 
3
3
  npm 패키지 `issue-sticker`의 변경 이력입니다. 설치·업그레이드에 영향을 주는 변경만 기록합니다.
4
4
 
5
+ ## 0.8.1 - 2026-09-15
6
+
7
+ ### 개선
8
+
9
+ - Chrome에서 화면 녹화를 시작할 때 공유할 화면 선택 창에 지금 보고 있는 탭이 함께 표시되고 탭 목록이 먼저 열립니다. 창·전체 화면도 그대로 선택할 수 있습니다.
10
+
5
11
  ## 0.8.0 - 2026-09-14
6
12
 
7
13
  ### 추가
@@ -18,10 +18,12 @@ function getDefaultDisplayMedia() {
18
18
  if (typeof navigator === "undefined" || !((_a = navigator.mediaDevices) == null ? void 0 : _a.getDisplayMedia)) {
19
19
  throw new Error("Screen recording is not supported in this browser.");
20
20
  }
21
- return navigator.mediaDevices.getDisplayMedia({
22
- video: { frameRate: 30 },
23
- audio: false
24
- });
21
+ const options = {
22
+ video: { frameRate: 30, displaySurface: "browser" },
23
+ audio: false,
24
+ selfBrowserSurface: "include"
25
+ };
26
+ return navigator.mediaDevices.getDisplayMedia(options);
25
27
  }
26
28
  function createDefaultMediaRecorder(stream, options) {
27
29
  if (typeof MediaRecorder === "undefined") {
@@ -13299,6 +13301,7 @@ function OnboardingOverlay({
13299
13301
  targetRect,
13300
13302
  targetRadius,
13301
13303
  avoidRects,
13304
+ affordanceRect,
13302
13305
  elevateHighlight,
13303
13306
  allowSkip = true,
13304
13307
  className,
@@ -13318,6 +13321,23 @@ function OnboardingOverlay({
13318
13321
  cutoutRect.width / 2,
13319
13322
  cutoutRect.height / 2
13320
13323
  ) : 0;
13324
+ const hasAffordanceTarget = !!step.affordanceTargetId;
13325
+ const affordanceCutout = affordanceRect ? padRect(affordanceRect, MASK_PADDING) : null;
13326
+ const affordanceDiameter = affordanceRect ? Math.max(affordanceRect.width, affordanceRect.height) + MASK_PADDING * 2 : 0;
13327
+ const affordanceCircle = affordanceRect ? (() => {
13328
+ const centerX = (affordanceRect.left + affordanceRect.right) / 2;
13329
+ const centerY = (affordanceRect.top + affordanceRect.bottom) / 2;
13330
+ const radius = affordanceDiameter / 2;
13331
+ return {
13332
+ left: centerX - radius,
13333
+ top: centerY - radius,
13334
+ right: centerX + radius,
13335
+ bottom: centerY + radius,
13336
+ width: affordanceDiameter,
13337
+ height: affordanceDiameter
13338
+ };
13339
+ })() : null;
13340
+ const popoverAnchorRect = hasAffordanceTarget && affordanceCutout ? affordanceCutout : cutoutRect;
13321
13341
  const popoverRef = React.useRef(null);
13322
13342
  const [popoverSize, setPopoverSize] = React.useState(
13323
13343
  null
@@ -13339,17 +13359,20 @@ function OnboardingOverlay({
13339
13359
  }, [step.id, step.body]);
13340
13360
  const effectiveSize = popoverSize && popoverSize.width > 0 && popoverSize.height > 0 ? popoverSize : DEFAULT_POPOVER_SIZE;
13341
13361
  const placement = resolvePopoverPlacement(
13342
- step.position ?? (cutoutRect ? "bottom" : "center"),
13343
- cutoutRect ?? getViewportRect(),
13362
+ step.position ?? (popoverAnchorRect ? "bottom" : "center"),
13363
+ popoverAnchorRect ?? getViewportRect(),
13344
13364
  effectiveSize,
13345
- cutoutRect ? avoidRects ?? [] : []
13365
+ popoverAnchorRect ? avoidRects ?? [] : []
13346
13366
  );
13347
13367
  const { left: popoverLeft, top: popoverTop } = placement;
13348
- const shouldCenterPopover = !cutoutRect && (step.position ?? "center") === "center";
13368
+ const shouldCenterPopover = !popoverAnchorRect && (step.position ?? "center") === "center";
13349
13369
  const maskColor = isTargetInteractionStep(step) ? "rgba(8, 13, 18, 0.74)" : "rgba(8, 13, 18, 0.62)";
13350
13370
  const isPassthrough = !!step.advanceOn;
13351
13371
  const isTargetInteraction = isTargetInteractionStep(step);
13352
13372
  const clickHint = isTargetInteraction ? step.clickHint ?? labels.clickHint : null;
13373
+ const isCutoutInteractionStyled = isTargetInteraction && !hasAffordanceTarget;
13374
+ const showAffordanceEmphasis = isTargetInteraction && hasAffordanceTarget && !!affordanceCircle;
13375
+ const ringCursorRect = !isTargetInteraction ? null : hasAffordanceTarget ? affordanceCircle : cutoutRect;
13353
13376
  return /* @__PURE__ */ jsxs(
13354
13377
  "div",
13355
13378
  {
@@ -13442,7 +13465,7 @@ function OnboardingOverlay({
13442
13465
  "data-testid": "onboarding-cutout-outline",
13443
13466
  className: cn(
13444
13467
  "issue-sticker-onboarding-highlight fixed",
13445
- isTargetInteraction ? "border-2 border-brand" : "border border-white/90"
13468
+ isCutoutInteractionStyled ? "border-2 border-brand" : "border border-white/90"
13446
13469
  ),
13447
13470
  style: {
13448
13471
  left: cutoutRect.left,
@@ -13457,7 +13480,31 @@ function OnboardingOverlay({
13457
13480
  step.id
13458
13481
  )
13459
13482
  ) : null,
13460
- cutoutRect && isTargetInteraction ? renderHighlight(
13483
+ showAffordanceEmphasis && affordanceCircle ? renderHighlight(
13484
+ /* 강조(컷아웃)와 클릭 유도 위치가 분리된 단계의 브랜드 링. 컷아웃 테두리는
13485
+ * 위에서 이미 순수 강조 스타일로 그렸으니, 여기서는 실제로 눌러야 할 요소
13486
+ * 중심에 원을 그린다 — 사각형 컷아웃과 구별돼야 "강조 대상이 아니라 이걸
13487
+ * 누르라"는 뜻이 선다. */
13488
+ /* @__PURE__ */ jsx(
13489
+ "div",
13490
+ {
13491
+ "aria-hidden": "true",
13492
+ "data-testid": "onboarding-affordance-ring",
13493
+ className: "issue-sticker-onboarding-highlight fixed rounded-full border-2 border-brand",
13494
+ style: {
13495
+ left: affordanceCircle.left,
13496
+ top: affordanceCircle.top,
13497
+ width: affordanceCircle.width,
13498
+ height: affordanceCircle.height,
13499
+ borderRadius: 9999,
13500
+ pointerEvents: "none",
13501
+ zIndex: elevateHighlight ? OVERLAY_LAYER_INDEX.runtimeHost : void 0
13502
+ }
13503
+ },
13504
+ `${step.id}-affordance`
13505
+ )
13506
+ ) : null,
13507
+ ringCursorRect ? renderHighlight(
13461
13508
  /* 클릭하는 커서. 테두리만으로는 "봐야 할 곳"까지만 전달되고 "클릭하라"가
13462
13509
  * 전달되지 않는다. 손 모양 반복 동작이 그 자리를 맡는다. */
13463
13510
  /* @__PURE__ */ jsxs(
@@ -13467,8 +13514,8 @@ function OnboardingOverlay({
13467
13514
  "data-testid": "onboarding-cutout-cursor",
13468
13515
  className: "issue-sticker-onboarding-tap fixed",
13469
13516
  style: {
13470
- left: cutoutRect.right - TAP_INSET,
13471
- top: cutoutRect.bottom - TAP_INSET,
13517
+ left: ringCursorRect.right - TAP_INSET,
13518
+ top: ringCursorRect.bottom - TAP_INSET,
13472
13519
  pointerEvents: "none",
13473
13520
  zIndex: elevateHighlight ? OVERLAY_LAYER_INDEX.runtimeHost : void 0
13474
13521
  },
@@ -13705,18 +13752,24 @@ function OnboardingProvider({
13705
13752
  () => activeTargetIds.map((id) => targetMapRef.current.get(id) ?? null).filter((el) => el !== null),
13706
13753
  [activeTargetIds]
13707
13754
  );
13755
+ const activeAffordanceTargetId = activeStep == null ? void 0 : activeStep.affordanceTargetId;
13756
+ const getObservedElements = React.useCallback(() => {
13757
+ const elements = getActiveTargetElements();
13758
+ const affordanceElement = activeAffordanceTargetId ? targetMapRef.current.get(activeAffordanceTargetId) ?? null : null;
13759
+ return affordanceElement ? [...elements, affordanceElement] : elements;
13760
+ }, [activeAffordanceTargetId, getActiveTargetElements]);
13708
13761
  const scheduleLayoutUpdate = React.useCallback(() => {
13709
13762
  clearLayoutFrame();
13710
13763
  frameRef.current = window.requestAnimationFrame(() => {
13711
13764
  frameRef.current = null;
13712
13765
  const nextRect = unionRect(
13713
- getActiveTargetElements().map(getElementRect).filter((r2) => r2 !== null)
13766
+ getObservedElements().map(getElementRect).filter((r2) => r2 !== null)
13714
13767
  );
13715
13768
  if (areRectsEqual(lastRectRef.current, nextRect)) return;
13716
13769
  lastRectRef.current = nextRect;
13717
13770
  setLayoutVersion((version2) => version2 + 1);
13718
13771
  });
13719
- }, [clearLayoutFrame, getActiveTargetElements]);
13772
+ }, [clearLayoutFrame, getObservedElements]);
13720
13773
  const openAtStep = React.useCallback(
13721
13774
  (stepIndex) => {
13722
13775
  var _a;
@@ -13874,7 +13927,7 @@ function OnboardingProvider({
13874
13927
  }, [activeStep, advanceFromTargetClick, goToStep, isActiveRoute, isOpen]);
13875
13928
  React.useEffect(() => {
13876
13929
  if (!isOpen || !isActiveRoute) return;
13877
- const elements = getActiveTargetElements();
13930
+ const elements = getObservedElements();
13878
13931
  if (elements.length === 0) return;
13879
13932
  scheduleLayoutUpdate();
13880
13933
  window.addEventListener("resize", scheduleLayoutUpdate);
@@ -13889,7 +13942,7 @@ function OnboardingProvider({
13889
13942
  };
13890
13943
  }, [
13891
13944
  clearLayoutFrame,
13892
- getActiveTargetElements,
13945
+ getObservedElements,
13893
13946
  isActiveRoute,
13894
13947
  isOpen,
13895
13948
  scheduleLayoutUpdate,
@@ -13902,6 +13955,7 @@ function OnboardingProvider({
13902
13955
  const targetRect = isOpen && isActiveRoute && allTargetsResolved ? unionRect(resolvedTargetRects.filter((r2) => r2 !== null)) : null;
13903
13956
  const targetRadius = activeTargetIds.length === 1 ? getElementRadius(targetMapRef.current.get(activeTargetIds[0]) ?? null) : null;
13904
13957
  const avoidRects = ((activeStep == null ? void 0 : activeStep.avoidTargetIds) ?? []).map((id) => getElementRect(targetMapRef.current.get(id) ?? null)).filter((rect) => rect !== null);
13958
+ const affordanceRect = (activeStep == null ? void 0 : activeStep.affordanceTargetId) ? getElementRect(targetMapRef.current.get(activeStep.affordanceTargetId) ?? null) : null;
13905
13959
  const shouldRenderOverlay = isOpen && activeStep && isActiveRoute && !suppressed && !activeStep.silent && (!stepHasTarget || targetRect);
13906
13960
  const isTargetReady = !stepHasTarget || targetRect !== null;
13907
13961
  React.useEffect(() => {
@@ -13954,6 +14008,7 @@ function OnboardingProvider({
13954
14008
  targetRect,
13955
14009
  targetRadius,
13956
14010
  avoidRects,
14011
+ affordanceRect,
13957
14012
  elevateHighlight,
13958
14013
  allowSkip,
13959
14014
  className,
@@ -1,4 +1,4 @@
1
- import { u as uploadScreenshotDataUrls, a as uploadSignedMediaWithApi, d as directUploadToSignedUrl, p as pristineFetch, g as getElementPosition, c as captureWithModernScreenshot, b as buildJiraCreateFields, e as buildNotionCreateFields, f as buildGuestOwnerQuery, h as composeIssueFilterGroups, i as buildIssueIntegrationsPayload, j as devLogger, C as ConsoleCollector, N as NetworkCollector, s as selectNetworkLogsForSubmit, k as filterExcludeServiceRelatedLogs, l as filterExcludeServiceRelatedConsoleLogs, m as compactNetworkLogsForTransport, n as CONSOLE_LOG_SUBMIT_LIMIT, o as buildExternalUserPayload, q as shrinkNetworkLogsToFit, r as measureJsonBytes, t as sanitizeString, v as getCurrentPageUrl, S as ScreenRecordingController, w as SessionReplayCaptureController, x as preloadModernScreenshot, I as ISSUE_STICKER_INTERNAL_LOG_PREFIX } from "./externalUserPayload-k9LSBeMB.js";
1
+ import { u as uploadScreenshotDataUrls, a as uploadSignedMediaWithApi, d as directUploadToSignedUrl, p as pristineFetch, g as getElementPosition, c as captureWithModernScreenshot, b as buildJiraCreateFields, e as buildNotionCreateFields, f as buildGuestOwnerQuery, h as composeIssueFilterGroups, i as buildIssueIntegrationsPayload, j as devLogger, C as ConsoleCollector, N as NetworkCollector, s as selectNetworkLogsForSubmit, k as filterExcludeServiceRelatedLogs, l as filterExcludeServiceRelatedConsoleLogs, m as compactNetworkLogsForTransport, n as CONSOLE_LOG_SUBMIT_LIMIT, o as buildExternalUserPayload, q as shrinkNetworkLogsToFit, r as measureJsonBytes, t as sanitizeString, v as getCurrentPageUrl, S as ScreenRecordingController, w as SessionReplayCaptureController, x as preloadModernScreenshot, I as ISSUE_STICKER_INTERNAL_LOG_PREFIX } from "./externalUserPayload-D-P1-QaW.js";
2
2
  import "react/jsx-runtime";
3
3
  import "react";
4
4
  import "./mouse-pointer-2-BR00y3ir.js";
@@ -16,7 +16,7 @@ var __privateWrapper = (obj, member, setter, getter) => ({
16
16
  });
17
17
  var _focused, _cleanup, _setup, _b, _provider, _providerCalled, _c, _online, _cleanup2, _setup2, _d, _gcTimeout, _e, _queryType, _initialState, _revertState, _cache, _client, _retryer, _defaultOptions, _abortSignalConsumed, _Query_instances, isInitialPausedFetch_fn, dispatch_fn, _f, _client2, _currentQuery, _currentQueryInitialState, _currentResult, _currentResultState, _currentResultOptions, _currentThenable, _selectError, _selectFn, _selectResult, _lastQueryWithDefinedData, _staleTimeoutId, _refetchIntervalId, _currentRefetchInterval, _trackedProps, _QueryObserver_instances, executeFetch_fn, updateStaleTimeout_fn, computeRefetchInterval_fn, updateRefetchInterval_fn, updateTimers_fn, clearStaleTimeout_fn, clearRefetchInterval_fn, updateQuery_fn, notify_fn, _g, _client3, _observers, _mutationCache, _retryer2, _Mutation_instances, dispatch_fn2, _h, _mutations, _scopes, _mutationId, _i, _client4, _currentResult2, _currentMutation, _mutateOptions, _MutationObserver_instances, updateResult_fn, notify_fn2, _j, _queries, _k, _queryCache, _mutationCache2, _defaultOptions2, _queryDefaults, _mutationDefaults, _mountCount, _unsubscribeFocus, _unsubscribeOnline, _l, _m;
18
18
  import { O as OVERLAY_LAYER_INDEX, c as createLucideIcon$1, b as usePortalContainer, a as cn$1, d as OVERLAY_LAYER, s as stopEscapePropagation, P as Presence, e as Primitive, f as composeEventHandlers, g as useDismissableLayerSurface, h as useComposedRefs$1, i as Portal$1, j as createContextScope, k as createSlot, D as DismissableLayer, l as useControllableState, m as useId$1, n as useLayoutEffect2, o as useCallbackRef, p as PortalContainerProvider } from "./mouse-pointer-2-BR00y3ir.js";
19
- import { y as trimLogBackupPayload, z as createSafeLogBackup, A as getLogBackupSessionId, N as NetworkCollector, C as ConsoleCollector, B as createIndexedDbLogBackup, b as buildJiraCreateFields, P as Popover, D as PopoverTrigger, E as Input, F as PopoverContent, L as Label, G as Select, H as SelectTrigger, J as SelectValue, K as SelectContent, M as SelectItem, O as getJiraMetadata, Q as buildJiraIssueFields, R as Button, T as Root2$2, U as Trigger$2, V as ChevronDown, W as Portal, X as Content2$1, Y as Check, Z as X$1, _ as DatePicker, e as buildNotionCreateFields, $ as getNotionPageMetadata, a0 as buildNotionFieldViews, c as captureWithModernScreenshot, p as pristineFetch, d as directUploadToSignedUrl, a1 as DirectUploadError, a2 as toast, a3 as getSnapshot, a4 as subscribe, a as uploadSignedMediaWithApi, t as sanitizeString, a5 as getRegisteredUploadId, f as buildGuestOwnerQuery, j as devLogger, v as getCurrentPageUrl, a6 as ChevronRight, a7 as ReactRemoveScroll, a8 as hideOthers, a9 as useFocusGuards, aa as FocusScope, ab as getExposedJiraFields, ac as isJiraFieldExposed, ad as normalizeExposedJiraFields, x as preloadModernScreenshot, u as uploadScreenshotDataUrls, k as filterExcludeServiceRelatedLogs, l as filterExcludeServiceRelatedConsoleLogs, s as selectNetworkLogsForSubmit, m as compactNetworkLogsForTransport, n as CONSOLE_LOG_SUBMIT_LIMIT, g as getElementPosition, o as buildExternalUserPayload, q as shrinkNetworkLogsToFit, r as measureJsonBytes, i as buildIssueIntegrationsPayload, w as SessionReplayCaptureController, ae as getPrimaryJiraMapping, af as createCollection, ag as useDirection, ah as getPrimaryNotionMapping, ai as buttonVariants, aj as findElementBySelector, ak as findElementByXPath, S as ScreenRecordingController, h as composeIssueFilterGroups, al as OnboardingProvider, am as useOnboardingTarget, an as useOnboardingFlow, ao as PopoverAnchor } from "./externalUserPayload-k9LSBeMB.js";
19
+ import { y as trimLogBackupPayload, z as createSafeLogBackup, A as getLogBackupSessionId, N as NetworkCollector, C as ConsoleCollector, B as createIndexedDbLogBackup, b as buildJiraCreateFields, P as Popover, D as PopoverTrigger, E as Input, F as PopoverContent, L as Label, G as Select, H as SelectTrigger, J as SelectValue, K as SelectContent, M as SelectItem, O as getJiraMetadata, Q as buildJiraIssueFields, R as Button, T as Root2$2, U as Trigger$2, V as ChevronDown, W as Portal, X as Content2$1, Y as Check, Z as X$1, _ as DatePicker, e as buildNotionCreateFields, $ as getNotionPageMetadata, a0 as buildNotionFieldViews, c as captureWithModernScreenshot, p as pristineFetch, d as directUploadToSignedUrl, a1 as DirectUploadError, a2 as toast, a3 as getSnapshot, a4 as subscribe, a as uploadSignedMediaWithApi, t as sanitizeString, a5 as getRegisteredUploadId, f as buildGuestOwnerQuery, j as devLogger, v as getCurrentPageUrl, a6 as ChevronRight, a7 as ReactRemoveScroll, a8 as hideOthers, a9 as useFocusGuards, aa as FocusScope, ab as getExposedJiraFields, ac as isJiraFieldExposed, ad as normalizeExposedJiraFields, x as preloadModernScreenshot, u as uploadScreenshotDataUrls, k as filterExcludeServiceRelatedLogs, l as filterExcludeServiceRelatedConsoleLogs, s as selectNetworkLogsForSubmit, m as compactNetworkLogsForTransport, n as CONSOLE_LOG_SUBMIT_LIMIT, g as getElementPosition, o as buildExternalUserPayload, q as shrinkNetworkLogsToFit, r as measureJsonBytes, i as buildIssueIntegrationsPayload, w as SessionReplayCaptureController, ae as getPrimaryJiraMapping, af as createCollection, ag as useDirection, ah as getPrimaryNotionMapping, ai as buttonVariants, aj as findElementBySelector, ak as findElementByXPath, S as ScreenRecordingController, h as composeIssueFilterGroups, al as OnboardingProvider, am as useOnboardingTarget, an as useOnboardingFlow, ao as PopoverAnchor } from "./externalUserPayload-D-P1-QaW.js";
20
20
  import * as React from "react";
21
21
  import { useRef, useState, useEffect, useId, useLayoutEffect, useCallback, forwardRef, createElement, createContext, useContext, Component, Suspense, useInsertionEffect, useMemo, Children, isValidElement, Fragment as Fragment$1, useSyncExternalStore, useDeferredValue } from "react";
22
22
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "issue-sticker",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "IssueSticker SDK - Visual bug tracking widget for web applications",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",