issue-sticker 0.6.0 → 0.7.0
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 +31 -3
- package/dist/{externalUserPayload-B7zThnol.js → externalUserPayload-B26uCsCP.js} +381 -210
- package/dist/issue-sticker-headless-react.js +2 -17
- package/dist/issue-sticker-headless.js +2 -10
- package/dist/issue-sticker-react.js +554 -216
- package/dist/{createLucideIcon-BzRMP02h.js → mouse-pointer-2-BR00y3ir.js} +35 -19
- package/dist/{tooltip-B6UPO-U8.js → tooltip-DH02R32-.js} +1 -1
- package/headless.d.ts +1 -3
- package/package.json +2 -3
|
@@ -1,83 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { q as gzip_1, r as record, a as cn, o as useCallbackRef$1, h as useComposedRefs, e as Primitive, P as Presence, i as Portal$1, f as composeEventHandlers, j as createContextScope, k as createSlot, D as DismissableLayer, C as Content, t as createPopperScope, l as useControllableState, v as Root2$1, m as useId, A as Anchor, w as Arrow, b as usePortalContainer, d as OVERLAY_LAYER, s as stopEscapePropagation, n as useLayoutEffect2, V as VISUALLY_HIDDEN_STYLES, c as createLucideIcon, x as clsx, S as Slot$2, O as OVERLAY_LAYER_INDEX, M as MousePointer2 } from "./mouse-pointer-2-BR00y3ir.js";
|
|
2
2
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import React__default, { useState, createContext, useContext, useCallback, useRef, useLayoutEffect, useEffect, useMemo } from "react";
|
|
5
5
|
import * as ReactDOM from "react-dom";
|
|
6
|
-
const ISSUE_STICKER_HOST_ELEMENT_ID = "issue-sticker-host";
|
|
7
|
-
const ISSUE_STICKER_RUNTIME_OWNER_ATTRIBUTE = "data-issue-sticker-runtime";
|
|
8
|
-
const ISSUE_STICKER_EXTENSION_RUNTIME_READY_EVENT = "issue-sticker:extension-runtime-ready";
|
|
9
|
-
const ISSUE_STICKER_RUNTIME_OWNER = {
|
|
10
|
-
extension: "extension",
|
|
11
|
-
sdk: "sdk"
|
|
12
|
-
};
|
|
13
|
-
function resolveDocument(doc) {
|
|
14
|
-
return typeof document === "undefined" ? null : document;
|
|
15
|
-
}
|
|
16
|
-
function getIssueStickerRuntimeHost(doc) {
|
|
17
|
-
var _a;
|
|
18
|
-
return ((_a = resolveDocument()) == null ? void 0 : _a.getElementById(ISSUE_STICKER_HOST_ELEMENT_ID)) ?? null;
|
|
19
|
-
}
|
|
20
|
-
function getIssueStickerRuntimeOwner(element) {
|
|
21
|
-
const owner = element == null ? void 0 : element.getAttribute(ISSUE_STICKER_RUNTIME_OWNER_ATTRIBUTE);
|
|
22
|
-
if (owner === ISSUE_STICKER_RUNTIME_OWNER.extension || owner === ISSUE_STICKER_RUNTIME_OWNER.sdk) {
|
|
23
|
-
return owner;
|
|
24
|
-
}
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
function markIssueStickerRuntimeHost(element, owner) {
|
|
28
|
-
element.setAttribute(ISSUE_STICKER_RUNTIME_OWNER_ATTRIBUTE, owner);
|
|
29
|
-
}
|
|
30
|
-
function createRuntimeHostElement(owner, doc) {
|
|
31
|
-
const targetDocument = resolveDocument();
|
|
32
|
-
if (!targetDocument) {
|
|
33
|
-
throw new Error("createRuntimeHostElement: document 를 찾을 수 없습니다.");
|
|
34
|
-
}
|
|
35
|
-
const hostElement = targetDocument.createElement("div");
|
|
36
|
-
hostElement.id = ISSUE_STICKER_HOST_ELEMENT_ID;
|
|
37
|
-
markIssueStickerRuntimeHost(hostElement, owner);
|
|
38
|
-
hostElement.style.all = "initial";
|
|
39
|
-
hostElement.style.position = "fixed";
|
|
40
|
-
hostElement.style.top = "0";
|
|
41
|
-
hostElement.style.left = "0";
|
|
42
|
-
hostElement.style.width = "0";
|
|
43
|
-
hostElement.style.height = "0";
|
|
44
|
-
hostElement.style.overflow = "visible";
|
|
45
|
-
hostElement.style.background = "transparent";
|
|
46
|
-
hostElement.style.pointerEvents = "none";
|
|
47
|
-
hostElement.style.zIndex = String(OVERLAY_LAYER_INDEX.runtimeHost);
|
|
48
|
-
hostElement.style.display = "block";
|
|
49
|
-
hostElement.style.isolation = "isolate";
|
|
50
|
-
return hostElement;
|
|
51
|
-
}
|
|
52
|
-
function isEditableTarget(target) {
|
|
53
|
-
if (!(target instanceof HTMLElement)) return false;
|
|
54
|
-
return target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable === true;
|
|
55
|
-
}
|
|
56
|
-
function attachHostTypingGuard(shadowRoot) {
|
|
57
|
-
const handleKeyDown = (event) => {
|
|
58
|
-
const keyboardEvent = event;
|
|
59
|
-
if (keyboardEvent.ctrlKey || keyboardEvent.metaKey || keyboardEvent.altKey) return;
|
|
60
|
-
if (keyboardEvent.key === "Escape") return;
|
|
61
|
-
if (!isEditableTarget(keyboardEvent.composedPath()[0])) return;
|
|
62
|
-
keyboardEvent.stopPropagation();
|
|
63
|
-
};
|
|
64
|
-
shadowRoot.addEventListener("keydown", handleKeyDown);
|
|
65
|
-
return () => shadowRoot.removeEventListener("keydown", handleKeyDown);
|
|
66
|
-
}
|
|
67
|
-
const RUNTIME_OWNER_MARKER_KEY = "__issueStickerRuntimeOwner";
|
|
68
|
-
function markerHost() {
|
|
69
|
-
return typeof window === "undefined" ? null : window;
|
|
70
|
-
}
|
|
71
|
-
function getClaimedIssueStickerRuntimeOwner() {
|
|
72
|
-
var _a;
|
|
73
|
-
return ((_a = markerHost()) == null ? void 0 : _a[RUNTIME_OWNER_MARKER_KEY]) ?? null;
|
|
74
|
-
}
|
|
75
|
-
function isIssueStickerExtensionRuntimeActive(doc) {
|
|
76
|
-
if (getClaimedIssueStickerRuntimeOwner() === ISSUE_STICKER_RUNTIME_OWNER.extension) {
|
|
77
|
-
return true;
|
|
78
|
-
}
|
|
79
|
-
return getIssueStickerRuntimeOwner(getIssueStickerRuntimeHost()) === ISSUE_STICKER_RUNTIME_OWNER.extension;
|
|
80
|
-
}
|
|
81
6
|
const DEFAULT_MAX_DURATION_MS = 12e4;
|
|
82
7
|
const MIME_TYPE_CANDIDATES = ["video/webm;codecs=vp9", "video/webm"];
|
|
83
8
|
function createInitialSnapshot$1() {
|
|
@@ -3949,15 +3874,59 @@ class ConsoleCollector {
|
|
|
3949
3874
|
this.logs = [];
|
|
3950
3875
|
this.originals = {};
|
|
3951
3876
|
this.running = false;
|
|
3877
|
+
this.seenErrors = /* @__PURE__ */ new WeakSet();
|
|
3878
|
+
this.handleWindowError = (event) => {
|
|
3879
|
+
if (this.markSeen(event.error)) return;
|
|
3880
|
+
const detail = event.error != null ? serializeArgs([event.error]) : event.message;
|
|
3881
|
+
this.addErrorLog(`Uncaught ${detail}`, event.error, {
|
|
3882
|
+
lineNumber: event.lineno || void 0,
|
|
3883
|
+
columnNumber: event.colno || void 0
|
|
3884
|
+
});
|
|
3885
|
+
};
|
|
3886
|
+
this.handleUnhandledRejection = (event) => {
|
|
3887
|
+
if (this.markSeen(event.reason)) return;
|
|
3888
|
+
this.addErrorLog(`Unhandled promise rejection: ${serializeArgs([event.reason])}`, event.reason);
|
|
3889
|
+
};
|
|
3890
|
+
this.wrappers = {};
|
|
3952
3891
|
this.onChange = (options == null ? void 0 : options.onChange) ?? null;
|
|
3953
3892
|
}
|
|
3893
|
+
/** 처음 보는 값이면 표시하고 false. 이미 본 오류 객체면 true. */
|
|
3894
|
+
markSeen(value) {
|
|
3895
|
+
if (typeof value !== "object" || value === null) return false;
|
|
3896
|
+
if (this.seenErrors.has(value)) return true;
|
|
3897
|
+
this.seenErrors.add(value);
|
|
3898
|
+
return false;
|
|
3899
|
+
}
|
|
3900
|
+
addErrorLog(message2, error, position) {
|
|
3901
|
+
this.addLog({
|
|
3902
|
+
type: "error",
|
|
3903
|
+
message: redactSensitiveText(message2),
|
|
3904
|
+
timestamp: Date.now(),
|
|
3905
|
+
url: getCurrentPageUrl() || void 0,
|
|
3906
|
+
...position,
|
|
3907
|
+
stackTrace: redactSensitiveText(error instanceof Error ? error.stack : void 0)
|
|
3908
|
+
});
|
|
3909
|
+
}
|
|
3954
3910
|
start() {
|
|
3955
3911
|
if (this.running) return;
|
|
3956
3912
|
this.running = true;
|
|
3913
|
+
if (typeof window !== "undefined") {
|
|
3914
|
+
window.addEventListener("error", this.handleWindowError);
|
|
3915
|
+
window.addEventListener("unhandledrejection", this.handleUnhandledRejection);
|
|
3916
|
+
}
|
|
3957
3917
|
for (const method of CONSOLE_METHODS) {
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3918
|
+
const original = console[method];
|
|
3919
|
+
this.originals[method] = original;
|
|
3920
|
+
const wrapper = (...args) => {
|
|
3921
|
+
if (this.wrappers[method] !== wrapper) {
|
|
3922
|
+
original.apply(console, args);
|
|
3923
|
+
return;
|
|
3924
|
+
}
|
|
3925
|
+
const duplicate = args.some((arg) => arg instanceof Error && this.markSeen(arg));
|
|
3926
|
+
if (duplicate) {
|
|
3927
|
+
original.apply(console, args);
|
|
3928
|
+
return;
|
|
3929
|
+
}
|
|
3961
3930
|
this.addLog({
|
|
3962
3931
|
type: methodToLogType(method),
|
|
3963
3932
|
message: serializeArgs(args),
|
|
@@ -3965,19 +3934,26 @@ class ConsoleCollector {
|
|
|
3965
3934
|
url: getCurrentPageUrl() || void 0,
|
|
3966
3935
|
stackTrace: redactSensitiveText(captureConsoleStackTrace(args))
|
|
3967
3936
|
});
|
|
3968
|
-
|
|
3937
|
+
original.apply(console, args);
|
|
3969
3938
|
};
|
|
3939
|
+
this.wrappers[method] = wrapper;
|
|
3940
|
+
console[method] = wrapper;
|
|
3970
3941
|
}
|
|
3971
3942
|
}
|
|
3972
3943
|
stop() {
|
|
3973
3944
|
if (!this.running) return;
|
|
3974
3945
|
this.running = false;
|
|
3946
|
+
if (typeof window !== "undefined") {
|
|
3947
|
+
window.removeEventListener("error", this.handleWindowError);
|
|
3948
|
+
window.removeEventListener("unhandledrejection", this.handleUnhandledRejection);
|
|
3949
|
+
}
|
|
3975
3950
|
for (const method of CONSOLE_METHODS) {
|
|
3976
|
-
if (this.originals[method]) {
|
|
3951
|
+
if (this.originals[method] && console[method] === this.wrappers[method]) {
|
|
3977
3952
|
console[method] = this.originals[method];
|
|
3978
3953
|
}
|
|
3979
3954
|
}
|
|
3980
3955
|
this.originals = {};
|
|
3956
|
+
this.wrappers = {};
|
|
3981
3957
|
}
|
|
3982
3958
|
/** 리로드 이전 로그를 버퍼 앞에 되돌린다. */
|
|
3983
3959
|
restore(logs) {
|
|
@@ -3999,6 +3975,7 @@ class ConsoleCollector {
|
|
|
3999
3975
|
}
|
|
4000
3976
|
clear() {
|
|
4001
3977
|
this.logs = [];
|
|
3978
|
+
this.seenErrors = /* @__PURE__ */ new WeakSet();
|
|
4002
3979
|
}
|
|
4003
3980
|
addLog(log) {
|
|
4004
3981
|
var _a;
|
|
@@ -12810,7 +12787,7 @@ const DEFAULT_LABELS = {
|
|
|
12810
12787
|
close: "가이드 닫기",
|
|
12811
12788
|
skip: "건너뛰기",
|
|
12812
12789
|
skipConfirmTitle: "가이드를 건너뛸까요?",
|
|
12813
|
-
//
|
|
12790
|
+
// 채널마다 진입점이 다르다(admin=헤더 아이콘, extension=더보기 메뉴, sdk=FAB 메뉴).
|
|
12814
12791
|
// 위치를 특정하면 어느 한쪽에서는 틀린 안내가 되므로 라벨만 가리킨다.
|
|
12815
12792
|
skipConfirmBody: "'가이드 다시 보기'를 클릭하면 언제든 다시 열 수 있습니다.",
|
|
12816
12793
|
skipConfirmCancel: "계속 보기",
|
|
@@ -12822,8 +12799,9 @@ const DEFAULT_LABELS = {
|
|
|
12822
12799
|
};
|
|
12823
12800
|
const MASK_PADDING = 6;
|
|
12824
12801
|
const CUTOUT_RADIUS = 12;
|
|
12825
|
-
const POPOVER_WIDTH =
|
|
12802
|
+
const POPOVER_WIDTH = 360;
|
|
12826
12803
|
const POPOVER_FALLBACK_HEIGHT = 190;
|
|
12804
|
+
const DEFAULT_POPOVER_SIZE = { width: POPOVER_WIDTH, height: POPOVER_FALLBACK_HEIGHT };
|
|
12827
12805
|
const POPOVER_GAP = 12;
|
|
12828
12806
|
function clamp(value, min2, max2) {
|
|
12829
12807
|
return Math.min(Math.max(value, min2), max2);
|
|
@@ -12889,12 +12867,14 @@ function areRectsEqual(previous, next) {
|
|
|
12889
12867
|
if (!previous || !next) return previous === next;
|
|
12890
12868
|
return Math.abs(previous.top - next.top) < 0.5 && Math.abs(previous.right - next.right) < 0.5 && Math.abs(previous.bottom - next.bottom) < 0.5 && Math.abs(previous.left - next.left) < 0.5 && Math.abs(previous.width - next.width) < 0.5 && Math.abs(previous.height - next.height) < 0.5;
|
|
12891
12869
|
}
|
|
12892
|
-
function getPopoverCoordinates(position, targetRect
|
|
12870
|
+
function getPopoverCoordinates(position, targetRect, size = {
|
|
12871
|
+
width: POPOVER_WIDTH,
|
|
12872
|
+
height: POPOVER_FALLBACK_HEIGHT
|
|
12873
|
+
}) {
|
|
12893
12874
|
if (Array.isArray(position)) return position;
|
|
12894
12875
|
const viewportWidth = window.innerWidth;
|
|
12895
12876
|
const viewportHeight = window.innerHeight;
|
|
12896
|
-
const width =
|
|
12897
|
-
const height = POPOVER_FALLBACK_HEIGHT;
|
|
12877
|
+
const { width, height } = size;
|
|
12898
12878
|
const maxX = Math.max(POPOVER_GAP, viewportWidth - width - POPOVER_GAP);
|
|
12899
12879
|
const maxY = Math.max(POPOVER_GAP, viewportHeight - height - POPOVER_GAP);
|
|
12900
12880
|
const xOnTarget = targetRect.left + targetRect.width / 2 - width / 2;
|
|
@@ -12928,6 +12908,49 @@ function getPopoverCoordinates(position, targetRect) {
|
|
|
12928
12908
|
];
|
|
12929
12909
|
}
|
|
12930
12910
|
}
|
|
12911
|
+
function rectsOverlap(a2, b) {
|
|
12912
|
+
return a2.left < b.right && a2.right > b.left && a2.top < b.bottom && a2.bottom > b.top;
|
|
12913
|
+
}
|
|
12914
|
+
function overlapArea(a2, b) {
|
|
12915
|
+
const w = Math.min(a2.right, b.right) - Math.max(a2.left, b.left);
|
|
12916
|
+
const h = Math.min(a2.bottom, b.bottom) - Math.max(a2.top, b.top);
|
|
12917
|
+
return w > 0 && h > 0 ? w * h : 0;
|
|
12918
|
+
}
|
|
12919
|
+
const SIDE_ORDER = ["bottom", "top", "right", "left"];
|
|
12920
|
+
const OPPOSITE = {
|
|
12921
|
+
top: "bottom",
|
|
12922
|
+
bottom: "top",
|
|
12923
|
+
left: "right",
|
|
12924
|
+
right: "left"
|
|
12925
|
+
};
|
|
12926
|
+
function resolvePopoverPlacement(position, targetRect, size, avoidRects = []) {
|
|
12927
|
+
if (Array.isArray(position)) return { left: position[0], top: position[1], side: null };
|
|
12928
|
+
if (position === "center") {
|
|
12929
|
+
const [left, top] = getPopoverCoordinates(position, targetRect, size);
|
|
12930
|
+
return { left, top, side: null };
|
|
12931
|
+
}
|
|
12932
|
+
const blockers = [targetRect, ...avoidRects];
|
|
12933
|
+
const requested = position ?? "bottom";
|
|
12934
|
+
const candidates = [requested, OPPOSITE[requested], ...SIDE_ORDER];
|
|
12935
|
+
let best = null;
|
|
12936
|
+
for (const candidate of candidates) {
|
|
12937
|
+
const [left, top] = getPopoverCoordinates(candidate, targetRect, size);
|
|
12938
|
+
const rect = {
|
|
12939
|
+
left,
|
|
12940
|
+
top,
|
|
12941
|
+
right: left + size.width,
|
|
12942
|
+
bottom: top + size.height,
|
|
12943
|
+
width: size.width,
|
|
12944
|
+
height: size.height
|
|
12945
|
+
};
|
|
12946
|
+
const area = blockers.reduce((sum, blocker) => sum + overlapArea(rect, blocker), 0);
|
|
12947
|
+
const placement = { left, top, side: candidate };
|
|
12948
|
+
if (!blockers.some((blocker) => rectsOverlap(rect, blocker))) return placement;
|
|
12949
|
+
if (!best || area < best.area) best = { placement, area };
|
|
12950
|
+
}
|
|
12951
|
+
const fallback = getPopoverCoordinates(requested, targetRect, size);
|
|
12952
|
+
return (best == null ? void 0 : best.placement) ?? { left: fallback[0], top: fallback[1], side: requested };
|
|
12953
|
+
}
|
|
12931
12954
|
function getViewportRect() {
|
|
12932
12955
|
return {
|
|
12933
12956
|
top: 0,
|
|
@@ -12938,6 +12961,9 @@ function getViewportRect() {
|
|
|
12938
12961
|
height: window.innerHeight
|
|
12939
12962
|
};
|
|
12940
12963
|
}
|
|
12964
|
+
const TAP_INSET = 8;
|
|
12965
|
+
const TAP_RIPPLE_SIZE = 44;
|
|
12966
|
+
const LINK_BUTTON_CLASS = "inline-flex h-[30px] items-center justify-center rounded-sm text-xs font-semibold text-text-tertiary underline-offset-4 transition-colors hover:text-text-primary hover:underline focus-visible:outline-none focus-visible:shadow-focus disabled:pointer-events-none disabled:opacity-50";
|
|
12941
12967
|
function shouldRenderNextButton(step) {
|
|
12942
12968
|
if (step.advanceOnTargetClick) return false;
|
|
12943
12969
|
if (step.advanceOn && !step.allowManualAdvance) return false;
|
|
@@ -12955,18 +12981,67 @@ function OnboardingStyleTag() {
|
|
|
12955
12981
|
transition: opacity ${POPOVER_FADE_MS}ms ease-out;
|
|
12956
12982
|
}
|
|
12957
12983
|
|
|
12984
|
+
@keyframes issue-sticker-onboarding-tap {
|
|
12985
|
+
0%,
|
|
12986
|
+
55%,
|
|
12987
|
+
100% {
|
|
12988
|
+
transform: translate(0, 0);
|
|
12989
|
+
}
|
|
12990
|
+
30% {
|
|
12991
|
+
transform: translate(-5px, -5px);
|
|
12992
|
+
}
|
|
12993
|
+
}
|
|
12994
|
+
|
|
12995
|
+
@keyframes issue-sticker-onboarding-ripple {
|
|
12996
|
+
0% {
|
|
12997
|
+
transform: translate(-50%, -50%) scale(0.3);
|
|
12998
|
+
opacity: 0.5;
|
|
12999
|
+
}
|
|
13000
|
+
55%,
|
|
13001
|
+
100% {
|
|
13002
|
+
transform: translate(-50%, -50%) scale(1.7);
|
|
13003
|
+
opacity: 0;
|
|
13004
|
+
}
|
|
13005
|
+
}
|
|
13006
|
+
|
|
13007
|
+
.issue-sticker-onboarding-tap {
|
|
13008
|
+
animation: issue-sticker-onboarding-tap 1.6s ease-in-out infinite;
|
|
13009
|
+
}
|
|
13010
|
+
|
|
13011
|
+
.issue-sticker-onboarding-tap-ripple {
|
|
13012
|
+
animation: issue-sticker-onboarding-ripple 1.6s ease-out infinite;
|
|
13013
|
+
}
|
|
13014
|
+
|
|
13015
|
+
@keyframes issue-sticker-onboarding-focus {
|
|
13016
|
+
from {
|
|
13017
|
+
transform: scale(1.05);
|
|
13018
|
+
opacity: 0;
|
|
13019
|
+
}
|
|
13020
|
+
to {
|
|
13021
|
+
transform: scale(1);
|
|
13022
|
+
opacity: 1;
|
|
13023
|
+
}
|
|
13024
|
+
}
|
|
13025
|
+
|
|
13026
|
+
.issue-sticker-onboarding-highlight {
|
|
13027
|
+
animation: issue-sticker-onboarding-focus 220ms ease-out;
|
|
13028
|
+
}
|
|
13029
|
+
|
|
12958
13030
|
@media (prefers-reduced-motion: reduce) {
|
|
12959
13031
|
.issue-sticker-onboarding-popover {
|
|
12960
13032
|
transition-duration: 1ms !important;
|
|
12961
13033
|
}
|
|
12962
13034
|
|
|
12963
|
-
.issue-sticker-onboarding-highlight
|
|
13035
|
+
.issue-sticker-onboarding-highlight,
|
|
13036
|
+
.issue-sticker-onboarding-tap,
|
|
13037
|
+
.issue-sticker-onboarding-tap-ripple {
|
|
12964
13038
|
animation: none !important;
|
|
12965
13039
|
}
|
|
12966
13040
|
}
|
|
12967
13041
|
` });
|
|
12968
13042
|
}
|
|
12969
13043
|
function OnboardingPopoverContent({
|
|
13044
|
+
allowSkip,
|
|
12970
13045
|
step,
|
|
12971
13046
|
clickHint,
|
|
12972
13047
|
labels,
|
|
@@ -13031,26 +13106,53 @@ function OnboardingPopoverContent({
|
|
|
13031
13106
|
}
|
|
13032
13107
|
);
|
|
13033
13108
|
}
|
|
13109
|
+
const hasNextButton = shouldRenderNextButton(step);
|
|
13034
13110
|
return /* @__PURE__ */ jsxs("div", { children: [
|
|
13035
13111
|
/* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold leading-5 text-text-primary", children: step.title }),
|
|
13036
|
-
/* @__PURE__ */ jsx("p", { className: "mt-2 whitespace-pre-line text-sm leading-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
"button",
|
|
13112
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 whitespace-pre-line text-sm leading-[1.55] text-text-secondary", children: step.body }),
|
|
13113
|
+
step.bodyExtra ? /* @__PURE__ */ jsx("div", { className: "mt-3", children: step.bodyExtra }) : null,
|
|
13114
|
+
clickHint ? (
|
|
13115
|
+
/* 진행 버튼이 없는 단계에서는 이 줄이 유일한 다음 행동이다. 그래서 버튼이 있던
|
|
13116
|
+
* 자리만큼의 무게를 준다 — 작은 글줄로 두면 사용자가 못 보고 다른 버튼을 누른다. */
|
|
13117
|
+
/* @__PURE__ */ jsxs(
|
|
13118
|
+
"p",
|
|
13044
13119
|
{
|
|
13045
|
-
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
children:
|
|
13120
|
+
className: cn(
|
|
13121
|
+
"mt-3 flex items-center gap-1.5 font-semibold text-brand",
|
|
13122
|
+
hasNextButton ? "text-xs leading-5" : "rounded-md border border-brand/40 bg-brand/10 px-3 py-2 text-sm leading-5"
|
|
13123
|
+
),
|
|
13124
|
+
children: [
|
|
13125
|
+
/* @__PURE__ */ jsx(MousePointerClick, { "aria-hidden": "true", className: "h-4 w-4 shrink-0" }),
|
|
13126
|
+
clickHint
|
|
13127
|
+
]
|
|
13050
13128
|
}
|
|
13051
|
-
)
|
|
13129
|
+
)
|
|
13130
|
+
) : null,
|
|
13131
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-4 flex items-center justify-between gap-2", children: [
|
|
13132
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
13133
|
+
allowSkip ? /* @__PURE__ */ jsx(
|
|
13134
|
+
"button",
|
|
13135
|
+
{
|
|
13136
|
+
type: "button",
|
|
13137
|
+
onClick: onRequestSkip,
|
|
13138
|
+
disabled: !isVisible,
|
|
13139
|
+
className: LINK_BUTTON_CLASS,
|
|
13140
|
+
children: labels.skip
|
|
13141
|
+
}
|
|
13142
|
+
) : null,
|
|
13143
|
+
canGoPrevious && !hasNextButton ? /* @__PURE__ */ jsx(
|
|
13144
|
+
"button",
|
|
13145
|
+
{
|
|
13146
|
+
type: "button",
|
|
13147
|
+
onClick: onPrevious,
|
|
13148
|
+
disabled: !isVisible || isSkipConfirmOpen,
|
|
13149
|
+
className: LINK_BUTTON_CLASS,
|
|
13150
|
+
children: labels.previous
|
|
13151
|
+
}
|
|
13152
|
+
) : null
|
|
13153
|
+
] }),
|
|
13052
13154
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
13053
|
-
canGoPrevious ? /* @__PURE__ */ jsx(
|
|
13155
|
+
canGoPrevious && hasNextButton ? /* @__PURE__ */ jsx(
|
|
13054
13156
|
"button",
|
|
13055
13157
|
{
|
|
13056
13158
|
type: "button",
|
|
@@ -13060,7 +13162,7 @@ function OnboardingPopoverContent({
|
|
|
13060
13162
|
children: labels.previous
|
|
13061
13163
|
}
|
|
13062
13164
|
) : null,
|
|
13063
|
-
|
|
13165
|
+
hasNextButton ? /* @__PURE__ */ jsx(
|
|
13064
13166
|
"button",
|
|
13065
13167
|
{
|
|
13066
13168
|
type: "button",
|
|
@@ -13078,6 +13180,9 @@ function OnboardingOverlay({
|
|
|
13078
13180
|
step,
|
|
13079
13181
|
targetRect,
|
|
13080
13182
|
targetRadius,
|
|
13183
|
+
avoidRects,
|
|
13184
|
+
elevateHighlight,
|
|
13185
|
+
allowSkip = true,
|
|
13081
13186
|
className,
|
|
13082
13187
|
labels,
|
|
13083
13188
|
isPopoverVisible,
|
|
@@ -13088,6 +13193,7 @@ function OnboardingOverlay({
|
|
|
13088
13193
|
onPrevious
|
|
13089
13194
|
}) {
|
|
13090
13195
|
const maskId = React.useId().replace(/:/g, "");
|
|
13196
|
+
const renderHighlight = (node) => elevateHighlight && typeof document !== "undefined" ? ReactDOM.createPortal(node, document.body) : node;
|
|
13091
13197
|
const [isSkipConfirmOpen, setIsSkipConfirmOpen] = React.useState(false);
|
|
13092
13198
|
const cutoutRect = targetRect ? padRect(targetRect, MASK_PADDING) : null;
|
|
13093
13199
|
const cutoutRadius = cutoutRect ? Math.min(
|
|
@@ -13095,12 +13201,35 @@ function OnboardingOverlay({
|
|
|
13095
13201
|
cutoutRect.width / 2,
|
|
13096
13202
|
cutoutRect.height / 2
|
|
13097
13203
|
) : 0;
|
|
13098
|
-
const
|
|
13204
|
+
const popoverRef = React.useRef(null);
|
|
13205
|
+
const [popoverSize, setPopoverSize] = React.useState(
|
|
13206
|
+
null
|
|
13207
|
+
);
|
|
13208
|
+
React.useLayoutEffect(() => {
|
|
13209
|
+
const element = popoverRef.current;
|
|
13210
|
+
if (!element) return void 0;
|
|
13211
|
+
const measure = () => {
|
|
13212
|
+
const rect = element.getBoundingClientRect();
|
|
13213
|
+
setPopoverSize(
|
|
13214
|
+
(current) => current && Math.abs(current.height - rect.height) < 0.5 && Math.abs(current.width - rect.width) < 0.5 ? current : { width: rect.width, height: rect.height }
|
|
13215
|
+
);
|
|
13216
|
+
};
|
|
13217
|
+
measure();
|
|
13218
|
+
if (typeof ResizeObserver === "undefined") return void 0;
|
|
13219
|
+
const observer = new ResizeObserver(measure);
|
|
13220
|
+
observer.observe(element);
|
|
13221
|
+
return () => observer.disconnect();
|
|
13222
|
+
}, [step.id, step.body, isSkipConfirmOpen]);
|
|
13223
|
+
const effectiveSize = popoverSize && popoverSize.width > 0 && popoverSize.height > 0 ? popoverSize : DEFAULT_POPOVER_SIZE;
|
|
13224
|
+
const placement = resolvePopoverPlacement(
|
|
13099
13225
|
step.position ?? (cutoutRect ? "bottom" : "center"),
|
|
13100
|
-
cutoutRect ?? getViewportRect()
|
|
13226
|
+
cutoutRect ?? getViewportRect(),
|
|
13227
|
+
effectiveSize,
|
|
13228
|
+
cutoutRect ? avoidRects ?? [] : []
|
|
13101
13229
|
);
|
|
13230
|
+
const { left: popoverLeft, top: popoverTop } = placement;
|
|
13102
13231
|
const shouldCenterPopover = !cutoutRect && (step.position ?? "center") === "center";
|
|
13103
|
-
const maskColor = "rgba(8, 13, 18, 0.62)";
|
|
13232
|
+
const maskColor = isTargetInteractionStep(step) ? "rgba(8, 13, 18, 0.74)" : "rgba(8, 13, 18, 0.62)";
|
|
13104
13233
|
const isPassthrough = !!step.advanceOn;
|
|
13105
13234
|
const isTargetInteraction = isTargetInteractionStep(step);
|
|
13106
13235
|
const clickHint = isTargetInteraction ? step.clickHint ?? labels.clickHint : null;
|
|
@@ -13191,58 +13320,101 @@ function OnboardingOverlay({
|
|
|
13191
13320
|
}
|
|
13192
13321
|
}
|
|
13193
13322
|
) : null,
|
|
13194
|
-
cutoutRect ?
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
|
|
13201
|
-
|
|
13202
|
-
|
|
13203
|
-
|
|
13204
|
-
|
|
13205
|
-
|
|
13206
|
-
|
|
13207
|
-
|
|
13208
|
-
|
|
13209
|
-
|
|
13323
|
+
cutoutRect ? renderHighlight(
|
|
13324
|
+
/* @__PURE__ */ jsx(
|
|
13325
|
+
"div",
|
|
13326
|
+
{
|
|
13327
|
+
"aria-hidden": "true",
|
|
13328
|
+
"data-testid": "onboarding-cutout-outline",
|
|
13329
|
+
className: cn(
|
|
13330
|
+
"issue-sticker-onboarding-highlight fixed",
|
|
13331
|
+
isTargetInteraction ? "border-2 border-brand" : "border border-white/90"
|
|
13332
|
+
),
|
|
13333
|
+
style: {
|
|
13334
|
+
left: cutoutRect.left,
|
|
13335
|
+
top: cutoutRect.top,
|
|
13336
|
+
width: cutoutRect.width,
|
|
13337
|
+
height: cutoutRect.height,
|
|
13338
|
+
borderRadius: cutoutRadius,
|
|
13339
|
+
pointerEvents: "none",
|
|
13340
|
+
zIndex: elevateHighlight ? OVERLAY_LAYER_INDEX.runtimeHost : void 0
|
|
13341
|
+
}
|
|
13342
|
+
},
|
|
13343
|
+
step.id
|
|
13344
|
+
)
|
|
13345
|
+
) : null,
|
|
13346
|
+
cutoutRect && isTargetInteraction ? renderHighlight(
|
|
13347
|
+
/* 클릭하는 커서. 테두리만으로는 "봐야 할 곳"까지만 전달되고 "클릭하라"가
|
|
13348
|
+
* 전달되지 않는다. 손 모양 반복 동작이 그 자리를 맡는다. */
|
|
13349
|
+
/* @__PURE__ */ jsxs(
|
|
13350
|
+
"div",
|
|
13351
|
+
{
|
|
13352
|
+
"aria-hidden": "true",
|
|
13353
|
+
"data-testid": "onboarding-cutout-cursor",
|
|
13354
|
+
className: "issue-sticker-onboarding-tap fixed",
|
|
13355
|
+
style: {
|
|
13356
|
+
left: cutoutRect.right - TAP_INSET,
|
|
13357
|
+
top: cutoutRect.bottom - TAP_INSET,
|
|
13358
|
+
pointerEvents: "none",
|
|
13359
|
+
zIndex: elevateHighlight ? OVERLAY_LAYER_INDEX.runtimeHost : void 0
|
|
13360
|
+
},
|
|
13361
|
+
children: [
|
|
13362
|
+
/* @__PURE__ */ jsx(
|
|
13363
|
+
"span",
|
|
13364
|
+
{
|
|
13365
|
+
className: "issue-sticker-onboarding-tap-ripple absolute rounded-full bg-brand",
|
|
13366
|
+
style: { left: 0, top: 0, width: TAP_RIPPLE_SIZE, height: TAP_RIPPLE_SIZE }
|
|
13367
|
+
}
|
|
13368
|
+
),
|
|
13369
|
+
/* @__PURE__ */ jsx(
|
|
13370
|
+
MousePointer2,
|
|
13371
|
+
{
|
|
13372
|
+
className: "relative h-8 w-8",
|
|
13373
|
+
style: { fill: "#ffffff", stroke: "rgba(12, 18, 15, 0.7)" },
|
|
13374
|
+
strokeWidth: 1.4
|
|
13375
|
+
}
|
|
13376
|
+
)
|
|
13377
|
+
]
|
|
13210
13378
|
}
|
|
13211
|
-
|
|
13379
|
+
)
|
|
13212
13380
|
) : null,
|
|
13213
13381
|
isSkipConfirmOpen ? /* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "fixed inset-0 pointer-events-auto" }) : null,
|
|
13214
|
-
|
|
13215
|
-
|
|
13216
|
-
|
|
13217
|
-
|
|
13218
|
-
|
|
13219
|
-
|
|
13220
|
-
|
|
13221
|
-
|
|
13222
|
-
|
|
13223
|
-
|
|
13224
|
-
|
|
13225
|
-
|
|
13226
|
-
|
|
13227
|
-
|
|
13228
|
-
|
|
13229
|
-
|
|
13230
|
-
|
|
13231
|
-
|
|
13232
|
-
|
|
13233
|
-
|
|
13234
|
-
|
|
13235
|
-
|
|
13236
|
-
|
|
13237
|
-
|
|
13238
|
-
|
|
13239
|
-
|
|
13240
|
-
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
13382
|
+
renderHighlight(
|
|
13383
|
+
/* @__PURE__ */ jsx(
|
|
13384
|
+
"div",
|
|
13385
|
+
{
|
|
13386
|
+
ref: popoverRef,
|
|
13387
|
+
role: "dialog",
|
|
13388
|
+
"aria-modal": "false",
|
|
13389
|
+
...{ [ONBOARDING_POPOVER_DATA_ATTR]: "floating" },
|
|
13390
|
+
className: "issue-sticker-onboarding-popover fixed w-[22.5rem] max-w-[calc(100vw-24px)] break-keep [overflow-wrap:anywhere] rounded-xl border border-line-subtle bg-surface-0 p-[18px] text-text-primary shadow-lg pointer-events-auto",
|
|
13391
|
+
style: {
|
|
13392
|
+
left: shouldCenterPopover ? "50%" : popoverLeft,
|
|
13393
|
+
top: shouldCenterPopover ? "50%" : popoverTop,
|
|
13394
|
+
opacity: isPopoverVisible ? 1 : 0,
|
|
13395
|
+
transform: shouldCenterPopover ? "translate(-50%, -50%)" : void 0,
|
|
13396
|
+
zIndex: elevateHighlight ? OVERLAY_LAYER_INDEX.runtimeHost : OVERLAY_LAYER_INDEX.tourPopover
|
|
13397
|
+
},
|
|
13398
|
+
children: /* @__PURE__ */ jsx(
|
|
13399
|
+
OnboardingPopoverContent,
|
|
13400
|
+
{
|
|
13401
|
+
allowSkip,
|
|
13402
|
+
step,
|
|
13403
|
+
clickHint,
|
|
13404
|
+
labels,
|
|
13405
|
+
canGoPrevious,
|
|
13406
|
+
isLast,
|
|
13407
|
+
isVisible: isPopoverVisible,
|
|
13408
|
+
isSkipConfirmOpen,
|
|
13409
|
+
onRequestSkip: () => setIsSkipConfirmOpen(true),
|
|
13410
|
+
onCancelSkip: () => setIsSkipConfirmOpen(false),
|
|
13411
|
+
onConfirmSkip: onSkip,
|
|
13412
|
+
onNext,
|
|
13413
|
+
onPrevious
|
|
13414
|
+
}
|
|
13415
|
+
)
|
|
13416
|
+
}
|
|
13417
|
+
)
|
|
13246
13418
|
)
|
|
13247
13419
|
]
|
|
13248
13420
|
}
|
|
@@ -13335,7 +13507,9 @@ function OnboardingProvider({
|
|
|
13335
13507
|
className,
|
|
13336
13508
|
labels: labelOverrides,
|
|
13337
13509
|
storage: storageOverride,
|
|
13338
|
-
suppressed = false
|
|
13510
|
+
suppressed = false,
|
|
13511
|
+
elevateHighlight = false,
|
|
13512
|
+
allowSkip = true
|
|
13339
13513
|
}) {
|
|
13340
13514
|
const labels = React.useMemo(() => ({ ...DEFAULT_LABELS, ...labelOverrides }), [labelOverrides]);
|
|
13341
13515
|
const storage = React.useMemo(
|
|
@@ -13617,6 +13791,7 @@ function OnboardingProvider({
|
|
|
13617
13791
|
const allTargetsResolved = activeTargetIds.length > 0 && resolvedTargetRects.every((rect) => rect !== null);
|
|
13618
13792
|
const targetRect = isOpen && isActiveRoute && allTargetsResolved ? unionRect(resolvedTargetRects.filter((r2) => r2 !== null)) : null;
|
|
13619
13793
|
const targetRadius = activeTargetIds.length === 1 ? getElementRadius(targetMapRef.current.get(activeTargetIds[0]) ?? null) : null;
|
|
13794
|
+
const avoidRects = ((activeStep == null ? void 0 : activeStep.avoidTargetIds) ?? []).map((id) => getElementRect(targetMapRef.current.get(id) ?? null)).filter((rect) => rect !== null);
|
|
13620
13795
|
const shouldRenderOverlay = isOpen && activeStep && isActiveRoute && !suppressed && !activeStep.silent && (!stepHasTarget || targetRect);
|
|
13621
13796
|
const isTargetReady = !stepHasTarget || targetRect !== null;
|
|
13622
13797
|
React.useEffect(() => {
|
|
@@ -13668,6 +13843,9 @@ function OnboardingProvider({
|
|
|
13668
13843
|
step: activeStep,
|
|
13669
13844
|
targetRect,
|
|
13670
13845
|
targetRadius,
|
|
13846
|
+
avoidRects,
|
|
13847
|
+
elevateHighlight,
|
|
13848
|
+
allowSkip,
|
|
13671
13849
|
className,
|
|
13672
13850
|
labels,
|
|
13673
13851
|
isPopoverVisible,
|
|
@@ -13895,66 +14073,59 @@ function buildExternalUserPayload(user) {
|
|
|
13895
14073
|
};
|
|
13896
14074
|
}
|
|
13897
14075
|
export {
|
|
13898
|
-
|
|
13899
|
-
|
|
13900
|
-
|
|
14076
|
+
DatePicker as $,
|
|
14077
|
+
createSafeLogBackup as A,
|
|
14078
|
+
getLogBackupSessionId as B,
|
|
13901
14079
|
ConsoleCollector as C,
|
|
13902
|
-
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
|
|
13906
|
-
|
|
14080
|
+
createIndexedDbLogBackup as D,
|
|
14081
|
+
PopoverTrigger as E,
|
|
14082
|
+
Input as F,
|
|
14083
|
+
PopoverContent as G,
|
|
14084
|
+
Select$1 as H,
|
|
13907
14085
|
ISSUE_STICKER_INTERNAL_LOG_PREFIX as I,
|
|
13908
|
-
|
|
13909
|
-
|
|
14086
|
+
SelectTrigger as J,
|
|
14087
|
+
SelectValue as K,
|
|
13910
14088
|
Label as L,
|
|
13911
|
-
|
|
14089
|
+
SelectContent as M,
|
|
13912
14090
|
NetworkCollector as N,
|
|
13913
|
-
|
|
14091
|
+
SelectItem as O,
|
|
13914
14092
|
Popover as P,
|
|
13915
|
-
|
|
13916
|
-
|
|
14093
|
+
getJiraMetadata as Q,
|
|
14094
|
+
buildJiraIssueFields as R,
|
|
13917
14095
|
ScreenRecordingController as S,
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
14096
|
+
Button$1 as T,
|
|
14097
|
+
Root2 as U,
|
|
14098
|
+
Trigger as V,
|
|
14099
|
+
ChevronDown as W,
|
|
14100
|
+
Portal as X,
|
|
14101
|
+
Content2 as Y,
|
|
14102
|
+
Check as Z,
|
|
14103
|
+
X as _,
|
|
13926
14104
|
uploadSignedMediaWithApi as a,
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
useOnboardingFlow as ao,
|
|
13952
|
-
ISSUE_STICKER_HOST_ELEMENT_ID as ap,
|
|
13953
|
-
getIssueStickerRuntimeOwner as aq,
|
|
13954
|
-
ISSUE_STICKER_RUNTIME_OWNER as ar,
|
|
13955
|
-
createRuntimeHostElement as as,
|
|
13956
|
-
attachHostTypingGuard as at,
|
|
13957
|
-
ISSUE_STICKER_EXTENSION_RUNTIME_READY_EVENT as au,
|
|
14105
|
+
getNotionPageMetadata as a0,
|
|
14106
|
+
buildNotionFieldViews as a1,
|
|
14107
|
+
DirectUploadError as a2,
|
|
14108
|
+
toast as a3,
|
|
14109
|
+
getSnapshot as a4,
|
|
14110
|
+
subscribe as a5,
|
|
14111
|
+
getRegisteredUploadId as a6,
|
|
14112
|
+
ChevronRight as a7,
|
|
14113
|
+
ReactRemoveScroll as a8,
|
|
14114
|
+
hideOthers as a9,
|
|
14115
|
+
useFocusGuards as aa,
|
|
14116
|
+
FocusScope as ab,
|
|
14117
|
+
getExposedJiraFields as ac,
|
|
14118
|
+
isJiraFieldExposed as ad,
|
|
14119
|
+
getPrimaryJiraMapping as ae,
|
|
14120
|
+
createCollection as af,
|
|
14121
|
+
useDirection as ag,
|
|
14122
|
+
getPrimaryNotionMapping as ah,
|
|
14123
|
+
buttonVariants as ai,
|
|
14124
|
+
findElementBySelector as aj,
|
|
14125
|
+
findElementByXPath as ak,
|
|
14126
|
+
OnboardingProvider as al,
|
|
14127
|
+
useOnboardingTarget as am,
|
|
14128
|
+
useOnboardingFlow as an,
|
|
13958
14129
|
normalizeJiraFieldId as b,
|
|
13959
14130
|
captureWithModernScreenshot as c,
|
|
13960
14131
|
directUploadToSignedUrl as d,
|
|
@@ -13979,5 +14150,5 @@ export {
|
|
|
13979
14150
|
getCurrentPageUrl as w,
|
|
13980
14151
|
SessionReplayCaptureController as x,
|
|
13981
14152
|
preloadModernScreenshot as y,
|
|
13982
|
-
|
|
14153
|
+
trimLogBackupPayload as z
|
|
13983
14154
|
};
|