issue-sticker 0.6.0 → 0.8.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 +44 -3
- package/dist/{externalUserPayload-B7zThnol.js → externalUserPayload-k9LSBeMB.js} +574 -292
- package/dist/issue-sticker-headless-react.js +2 -17
- package/dist/issue-sticker-headless.js +2 -186
- package/dist/issue-sticker-react.js +864 -336
- 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;
|
|
@@ -4990,6 +4967,182 @@ function buildJiraCreateFields(exposedFields, fieldDefinitions = [], values = {}
|
|
|
4990
4967
|
includeReadonly: false
|
|
4991
4968
|
}).filter((field) => knownFieldIds.has(normalizeJiraFieldId(field.id))).filter((field) => !CREATE_UNSUPPORTED_FIELD_IDS.has(normalizeJiraFieldId(field.id)));
|
|
4992
4969
|
}
|
|
4970
|
+
const JIRA_FILTERABLE_FIELD_IDS = /* @__PURE__ */ new Set([
|
|
4971
|
+
"status",
|
|
4972
|
+
"priority",
|
|
4973
|
+
"assignee",
|
|
4974
|
+
"reporter",
|
|
4975
|
+
"fixVersions",
|
|
4976
|
+
"issuetype",
|
|
4977
|
+
"project_key",
|
|
4978
|
+
"sprint_id",
|
|
4979
|
+
"sprint_name",
|
|
4980
|
+
"epic_link",
|
|
4981
|
+
"story_points"
|
|
4982
|
+
]);
|
|
4983
|
+
const NOTION_FILTERABLE_FIELD_TYPES = /* @__PURE__ */ new Set(["select", "multi_select", "status", "checkbox"]);
|
|
4984
|
+
function getJiraConfig(integration) {
|
|
4985
|
+
if (integration.service_type !== "JIRA") return null;
|
|
4986
|
+
return integration.config ?? null;
|
|
4987
|
+
}
|
|
4988
|
+
function getNotionConfig(integration) {
|
|
4989
|
+
if (integration.service_type !== "NOTION") return null;
|
|
4990
|
+
return integration.config ?? null;
|
|
4991
|
+
}
|
|
4992
|
+
function getExposedFields(config) {
|
|
4993
|
+
if (!(config == null ? void 0 : config.exposed_fields)) return [];
|
|
4994
|
+
return normalizeExposedJiraFields(
|
|
4995
|
+
Array.isArray(config.exposed_fields) ? config.exposed_fields : void 0
|
|
4996
|
+
);
|
|
4997
|
+
}
|
|
4998
|
+
function getLastKnownJiraFields(config) {
|
|
4999
|
+
const fields = config == null ? void 0 : config.last_known_fields;
|
|
5000
|
+
if (!Array.isArray(fields)) return [];
|
|
5001
|
+
return fields.filter(
|
|
5002
|
+
(field) => Boolean(field) && typeof field === "object" && typeof field.id === "string" && typeof field.name === "string"
|
|
5003
|
+
);
|
|
5004
|
+
}
|
|
5005
|
+
function getSelectedNotionFields(config) {
|
|
5006
|
+
const fields = config == null ? void 0 : config.selected_fields;
|
|
5007
|
+
if (!Array.isArray(fields)) return [];
|
|
5008
|
+
return fields.filter((field) => typeof field === "string");
|
|
5009
|
+
}
|
|
5010
|
+
function getLastKnownNotionFields(config) {
|
|
5011
|
+
const fields = config == null ? void 0 : config.last_known_fields;
|
|
5012
|
+
if (!Array.isArray(fields)) return [];
|
|
5013
|
+
return fields.filter(
|
|
5014
|
+
(field) => Boolean(field) && typeof field === "object" && typeof field.id === "string" && typeof field.name === "string" && typeof field.type === "string"
|
|
5015
|
+
);
|
|
5016
|
+
}
|
|
5017
|
+
const OPTION_CUSTOM_FIELD_TYPES = /* @__PURE__ */ new Set(["select", "multi_select"]);
|
|
5018
|
+
function getSelectableCustomFieldOptions(field) {
|
|
5019
|
+
var _a;
|
|
5020
|
+
if (!OPTION_CUSTOM_FIELD_TYPES.has(field.field_type)) return [];
|
|
5021
|
+
const rawOptions = (_a = field.field_config) == null ? void 0 : _a.options;
|
|
5022
|
+
if (!Array.isArray(rawOptions)) return [];
|
|
5023
|
+
return rawOptions.filter((option) => typeof option === "string" && option.trim().length > 0).map((option) => ({ label: option, value: option }));
|
|
5024
|
+
}
|
|
5025
|
+
function getJiraOptionValue(option) {
|
|
5026
|
+
return option.id;
|
|
5027
|
+
}
|
|
5028
|
+
function getJiraFieldFilterOptions(field) {
|
|
5029
|
+
const options = field.options ?? [];
|
|
5030
|
+
if (!options.length) return [];
|
|
5031
|
+
return options.map((option) => ({
|
|
5032
|
+
label: option.name || option.value || option.id,
|
|
5033
|
+
value: getJiraOptionValue(option)
|
|
5034
|
+
})).filter((option) => option.value.length > 0);
|
|
5035
|
+
}
|
|
5036
|
+
function getNotionFieldFilterOptions(field) {
|
|
5037
|
+
if (field.type === "checkbox") {
|
|
5038
|
+
return [
|
|
5039
|
+
{ label: "체크됨", value: "true" },
|
|
5040
|
+
{ label: "체크 안 됨", value: "false" }
|
|
5041
|
+
];
|
|
5042
|
+
}
|
|
5043
|
+
const options = field.options ?? [];
|
|
5044
|
+
if (!options.length) return [];
|
|
5045
|
+
return options.map((option) => ({
|
|
5046
|
+
label: option.name,
|
|
5047
|
+
value: option.name
|
|
5048
|
+
})).filter((option) => option.value.length > 0);
|
|
5049
|
+
}
|
|
5050
|
+
function mergeOptions(current, next) {
|
|
5051
|
+
const byValue = new Map(current.map((option) => [option.value, option]));
|
|
5052
|
+
for (const option of next) {
|
|
5053
|
+
if (!byValue.has(option.value)) {
|
|
5054
|
+
byValue.set(option.value, option);
|
|
5055
|
+
}
|
|
5056
|
+
}
|
|
5057
|
+
return Array.from(byValue.values()).sort((a2, b) => a2.label.localeCompare(b.label));
|
|
5058
|
+
}
|
|
5059
|
+
function upsertFilterGroup(groups, group) {
|
|
5060
|
+
const existing = groups.get(group.id);
|
|
5061
|
+
if (!existing) {
|
|
5062
|
+
groups.set(group.id, {
|
|
5063
|
+
...group,
|
|
5064
|
+
options: mergeOptions([], group.options)
|
|
5065
|
+
});
|
|
5066
|
+
return;
|
|
5067
|
+
}
|
|
5068
|
+
groups.set(group.id, {
|
|
5069
|
+
...existing,
|
|
5070
|
+
options: mergeOptions(existing.options, group.options)
|
|
5071
|
+
});
|
|
5072
|
+
}
|
|
5073
|
+
function appendCustomFieldFilterGroups(groups, customFields) {
|
|
5074
|
+
for (const field of customFields) {
|
|
5075
|
+
const options = getSelectableCustomFieldOptions(field);
|
|
5076
|
+
if (!options.length) continue;
|
|
5077
|
+
upsertFilterGroup(groups, {
|
|
5078
|
+
kind: "custom",
|
|
5079
|
+
id: `custom:${field.id}`,
|
|
5080
|
+
fieldDefinitionId: field.id,
|
|
5081
|
+
label: field.field_name,
|
|
5082
|
+
options
|
|
5083
|
+
});
|
|
5084
|
+
}
|
|
5085
|
+
}
|
|
5086
|
+
function appendJiraFieldFilterGroups(groups, exposedFieldIds, fields) {
|
|
5087
|
+
for (const field of fields) {
|
|
5088
|
+
const normalizedFieldId = normalizeJiraFieldId(field.id);
|
|
5089
|
+
if (!exposedFieldIds.has(normalizedFieldId) || !JIRA_FILTERABLE_FIELD_IDS.has(normalizedFieldId)) {
|
|
5090
|
+
continue;
|
|
5091
|
+
}
|
|
5092
|
+
const options = getJiraFieldFilterOptions(field);
|
|
5093
|
+
if (!options.length) continue;
|
|
5094
|
+
upsertFilterGroup(groups, {
|
|
5095
|
+
kind: "jira",
|
|
5096
|
+
id: `jira:${normalizedFieldId}`,
|
|
5097
|
+
fieldName: normalizedFieldId,
|
|
5098
|
+
label: field.name,
|
|
5099
|
+
options
|
|
5100
|
+
});
|
|
5101
|
+
}
|
|
5102
|
+
}
|
|
5103
|
+
function appendNotionFieldFilterGroups(groups, selectedFields, fields) {
|
|
5104
|
+
for (const field of fields) {
|
|
5105
|
+
if (!selectedFields.has(field.id) && !selectedFields.has(field.name)) continue;
|
|
5106
|
+
if (!NOTION_FILTERABLE_FIELD_TYPES.has(field.type)) continue;
|
|
5107
|
+
const options = getNotionFieldFilterOptions(field);
|
|
5108
|
+
if (!options.length) continue;
|
|
5109
|
+
upsertFilterGroup(groups, {
|
|
5110
|
+
kind: "notion",
|
|
5111
|
+
id: `notion:${field.id}`,
|
|
5112
|
+
fieldName: field.name,
|
|
5113
|
+
label: field.name,
|
|
5114
|
+
options
|
|
5115
|
+
});
|
|
5116
|
+
}
|
|
5117
|
+
}
|
|
5118
|
+
function composeIssueFilterGroups(integrations, customFields) {
|
|
5119
|
+
const groups = /* @__PURE__ */ new Map();
|
|
5120
|
+
const jiraIntegration = integrations.find((integration) => {
|
|
5121
|
+
const config = getJiraConfig(integration);
|
|
5122
|
+
return integration.is_active !== false && config;
|
|
5123
|
+
});
|
|
5124
|
+
appendCustomFieldFilterGroups(groups, customFields);
|
|
5125
|
+
const jiraConfig = jiraIntegration ? getJiraConfig(jiraIntegration) : null;
|
|
5126
|
+
const configExposedFields = getExposedFields(jiraConfig);
|
|
5127
|
+
if (configExposedFields.length) {
|
|
5128
|
+
appendJiraFieldFilterGroups(
|
|
5129
|
+
groups,
|
|
5130
|
+
new Set(configExposedFields),
|
|
5131
|
+
getLastKnownJiraFields(jiraConfig)
|
|
5132
|
+
);
|
|
5133
|
+
}
|
|
5134
|
+
for (const integration of integrations) {
|
|
5135
|
+
if (integration.is_active === false) continue;
|
|
5136
|
+
const notionConfig = getNotionConfig(integration);
|
|
5137
|
+
if (!notionConfig) continue;
|
|
5138
|
+
appendNotionFieldFilterGroups(
|
|
5139
|
+
groups,
|
|
5140
|
+
new Set(getSelectedNotionFields(notionConfig)),
|
|
5141
|
+
getLastKnownNotionFields(notionConfig)
|
|
5142
|
+
);
|
|
5143
|
+
}
|
|
5144
|
+
return Array.from(groups.values()).sort((a2, b) => a2.label.localeCompare(b.label));
|
|
5145
|
+
}
|
|
4993
5146
|
const STABLE_ATTR_KEYS = [
|
|
4994
5147
|
"data-testid",
|
|
4995
5148
|
"data-test",
|
|
@@ -6509,7 +6662,7 @@ var Popover$1 = (props) => {
|
|
|
6509
6662
|
};
|
|
6510
6663
|
Popover$1.displayName = POPOVER_NAME;
|
|
6511
6664
|
var ANCHOR_NAME = "PopoverAnchor";
|
|
6512
|
-
var PopoverAnchor = React.forwardRef(
|
|
6665
|
+
var PopoverAnchor$1 = React.forwardRef(
|
|
6513
6666
|
(props, forwardedRef) => {
|
|
6514
6667
|
const { __scopePopover, ...anchorProps } = props;
|
|
6515
6668
|
const context = usePopoverContext(ANCHOR_NAME, __scopePopover);
|
|
@@ -6522,7 +6675,7 @@ var PopoverAnchor = React.forwardRef(
|
|
|
6522
6675
|
return /* @__PURE__ */ jsx(Anchor, { ...popperScope, ...anchorProps, ref: forwardedRef });
|
|
6523
6676
|
}
|
|
6524
6677
|
);
|
|
6525
|
-
PopoverAnchor.displayName = ANCHOR_NAME;
|
|
6678
|
+
PopoverAnchor$1.displayName = ANCHOR_NAME;
|
|
6526
6679
|
var TRIGGER_NAME$1 = "PopoverTrigger";
|
|
6527
6680
|
var PopoverTrigger$1 = React.forwardRef(
|
|
6528
6681
|
(props, forwardedRef) => {
|
|
@@ -6745,11 +6898,13 @@ function getState(open) {
|
|
|
6745
6898
|
return open ? "open" : "closed";
|
|
6746
6899
|
}
|
|
6747
6900
|
var Root2 = Popover$1;
|
|
6901
|
+
var Anchor2 = PopoverAnchor$1;
|
|
6748
6902
|
var Trigger = PopoverTrigger$1;
|
|
6749
6903
|
var Portal = PopoverPortal;
|
|
6750
6904
|
var Content2 = PopoverContent$1;
|
|
6751
6905
|
const Popover = Root2;
|
|
6752
6906
|
const PopoverTrigger = Trigger;
|
|
6907
|
+
const PopoverAnchor = Anchor2;
|
|
6753
6908
|
const PopoverContent = React.forwardRef(({ className, align = "center", sideOffset = 6, onEscapeKeyDown, ...props }, ref) => {
|
|
6754
6909
|
const portalContainer = usePortalContainer();
|
|
6755
6910
|
return /* @__PURE__ */ jsx(Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
@@ -12809,12 +12964,6 @@ const DEFAULT_LABELS = {
|
|
|
12809
12964
|
badge: "가이드",
|
|
12810
12965
|
close: "가이드 닫기",
|
|
12811
12966
|
skip: "건너뛰기",
|
|
12812
|
-
skipConfirmTitle: "가이드를 건너뛸까요?",
|
|
12813
|
-
// 표면마다 진입점이 다르다(admin=헤더 아이콘, extension=더보기 메뉴, sdk=FAB 메뉴).
|
|
12814
|
-
// 위치를 특정하면 어느 한쪽에서는 틀린 안내가 되므로 라벨만 가리킨다.
|
|
12815
|
-
skipConfirmBody: "'가이드 다시 보기'를 클릭하면 언제든 다시 열 수 있습니다.",
|
|
12816
|
-
skipConfirmCancel: "계속 보기",
|
|
12817
|
-
skipConfirmConfirm: "건너뛰기",
|
|
12818
12967
|
previous: "이전",
|
|
12819
12968
|
next: "다음",
|
|
12820
12969
|
done: "완료",
|
|
@@ -12822,8 +12971,9 @@ const DEFAULT_LABELS = {
|
|
|
12822
12971
|
};
|
|
12823
12972
|
const MASK_PADDING = 6;
|
|
12824
12973
|
const CUTOUT_RADIUS = 12;
|
|
12825
|
-
const POPOVER_WIDTH =
|
|
12974
|
+
const POPOVER_WIDTH = 360;
|
|
12826
12975
|
const POPOVER_FALLBACK_HEIGHT = 190;
|
|
12976
|
+
const DEFAULT_POPOVER_SIZE = { width: POPOVER_WIDTH, height: POPOVER_FALLBACK_HEIGHT };
|
|
12827
12977
|
const POPOVER_GAP = 12;
|
|
12828
12978
|
function clamp(value, min2, max2) {
|
|
12829
12979
|
return Math.min(Math.max(value, min2), max2);
|
|
@@ -12889,12 +13039,14 @@ function areRectsEqual(previous, next) {
|
|
|
12889
13039
|
if (!previous || !next) return previous === next;
|
|
12890
13040
|
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
13041
|
}
|
|
12892
|
-
function getPopoverCoordinates(position, targetRect
|
|
13042
|
+
function getPopoverCoordinates(position, targetRect, size = {
|
|
13043
|
+
width: POPOVER_WIDTH,
|
|
13044
|
+
height: POPOVER_FALLBACK_HEIGHT
|
|
13045
|
+
}) {
|
|
12893
13046
|
if (Array.isArray(position)) return position;
|
|
12894
13047
|
const viewportWidth = window.innerWidth;
|
|
12895
13048
|
const viewportHeight = window.innerHeight;
|
|
12896
|
-
const width =
|
|
12897
|
-
const height = POPOVER_FALLBACK_HEIGHT;
|
|
13049
|
+
const { width, height } = size;
|
|
12898
13050
|
const maxX = Math.max(POPOVER_GAP, viewportWidth - width - POPOVER_GAP);
|
|
12899
13051
|
const maxY = Math.max(POPOVER_GAP, viewportHeight - height - POPOVER_GAP);
|
|
12900
13052
|
const xOnTarget = targetRect.left + targetRect.width / 2 - width / 2;
|
|
@@ -12928,6 +13080,49 @@ function getPopoverCoordinates(position, targetRect) {
|
|
|
12928
13080
|
];
|
|
12929
13081
|
}
|
|
12930
13082
|
}
|
|
13083
|
+
function rectsOverlap(a2, b) {
|
|
13084
|
+
return a2.left < b.right && a2.right > b.left && a2.top < b.bottom && a2.bottom > b.top;
|
|
13085
|
+
}
|
|
13086
|
+
function overlapArea(a2, b) {
|
|
13087
|
+
const w = Math.min(a2.right, b.right) - Math.max(a2.left, b.left);
|
|
13088
|
+
const h = Math.min(a2.bottom, b.bottom) - Math.max(a2.top, b.top);
|
|
13089
|
+
return w > 0 && h > 0 ? w * h : 0;
|
|
13090
|
+
}
|
|
13091
|
+
const SIDE_ORDER = ["bottom", "top", "right", "left"];
|
|
13092
|
+
const OPPOSITE = {
|
|
13093
|
+
top: "bottom",
|
|
13094
|
+
bottom: "top",
|
|
13095
|
+
left: "right",
|
|
13096
|
+
right: "left"
|
|
13097
|
+
};
|
|
13098
|
+
function resolvePopoverPlacement(position, targetRect, size, avoidRects = []) {
|
|
13099
|
+
if (Array.isArray(position)) return { left: position[0], top: position[1], side: null };
|
|
13100
|
+
if (position === "center") {
|
|
13101
|
+
const [left, top] = getPopoverCoordinates(position, targetRect, size);
|
|
13102
|
+
return { left, top, side: null };
|
|
13103
|
+
}
|
|
13104
|
+
const blockers = [targetRect, ...avoidRects];
|
|
13105
|
+
const requested = position ?? "bottom";
|
|
13106
|
+
const candidates = [requested, OPPOSITE[requested], ...SIDE_ORDER];
|
|
13107
|
+
let best = null;
|
|
13108
|
+
for (const candidate of candidates) {
|
|
13109
|
+
const [left, top] = getPopoverCoordinates(candidate, targetRect, size);
|
|
13110
|
+
const rect = {
|
|
13111
|
+
left,
|
|
13112
|
+
top,
|
|
13113
|
+
right: left + size.width,
|
|
13114
|
+
bottom: top + size.height,
|
|
13115
|
+
width: size.width,
|
|
13116
|
+
height: size.height
|
|
13117
|
+
};
|
|
13118
|
+
const area = blockers.reduce((sum, blocker) => sum + overlapArea(rect, blocker), 0);
|
|
13119
|
+
const placement = { left, top, side: candidate };
|
|
13120
|
+
if (!blockers.some((blocker) => rectsOverlap(rect, blocker))) return placement;
|
|
13121
|
+
if (!best || area < best.area) best = { placement, area };
|
|
13122
|
+
}
|
|
13123
|
+
const fallback = getPopoverCoordinates(requested, targetRect, size);
|
|
13124
|
+
return (best == null ? void 0 : best.placement) ?? { left: fallback[0], top: fallback[1], side: requested };
|
|
13125
|
+
}
|
|
12931
13126
|
function getViewportRect() {
|
|
12932
13127
|
return {
|
|
12933
13128
|
top: 0,
|
|
@@ -12938,6 +13133,9 @@ function getViewportRect() {
|
|
|
12938
13133
|
height: window.innerHeight
|
|
12939
13134
|
};
|
|
12940
13135
|
}
|
|
13136
|
+
const TAP_INSET = 8;
|
|
13137
|
+
const TAP_RIPPLE_SIZE = 44;
|
|
13138
|
+
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
13139
|
function shouldRenderNextButton(step) {
|
|
12942
13140
|
if (step.advanceOnTargetClick) return false;
|
|
12943
13141
|
if (step.advanceOn && !step.allowManualAdvance) return false;
|
|
@@ -12955,117 +13153,139 @@ function OnboardingStyleTag() {
|
|
|
12955
13153
|
transition: opacity ${POPOVER_FADE_MS}ms ease-out;
|
|
12956
13154
|
}
|
|
12957
13155
|
|
|
13156
|
+
@keyframes issue-sticker-onboarding-tap {
|
|
13157
|
+
0%,
|
|
13158
|
+
55%,
|
|
13159
|
+
100% {
|
|
13160
|
+
transform: translate(0, 0);
|
|
13161
|
+
}
|
|
13162
|
+
30% {
|
|
13163
|
+
transform: translate(-5px, -5px);
|
|
13164
|
+
}
|
|
13165
|
+
}
|
|
13166
|
+
|
|
13167
|
+
@keyframes issue-sticker-onboarding-ripple {
|
|
13168
|
+
0% {
|
|
13169
|
+
transform: translate(-50%, -50%) scale(0.3);
|
|
13170
|
+
opacity: 0.5;
|
|
13171
|
+
}
|
|
13172
|
+
55%,
|
|
13173
|
+
100% {
|
|
13174
|
+
transform: translate(-50%, -50%) scale(1.7);
|
|
13175
|
+
opacity: 0;
|
|
13176
|
+
}
|
|
13177
|
+
}
|
|
13178
|
+
|
|
13179
|
+
.issue-sticker-onboarding-tap {
|
|
13180
|
+
animation: issue-sticker-onboarding-tap 1.6s ease-in-out infinite;
|
|
13181
|
+
}
|
|
13182
|
+
|
|
13183
|
+
.issue-sticker-onboarding-tap-ripple {
|
|
13184
|
+
animation: issue-sticker-onboarding-ripple 1.6s ease-out infinite;
|
|
13185
|
+
}
|
|
13186
|
+
|
|
13187
|
+
@keyframes issue-sticker-onboarding-focus {
|
|
13188
|
+
from {
|
|
13189
|
+
transform: scale(1.05);
|
|
13190
|
+
opacity: 0;
|
|
13191
|
+
}
|
|
13192
|
+
to {
|
|
13193
|
+
transform: scale(1);
|
|
13194
|
+
opacity: 1;
|
|
13195
|
+
}
|
|
13196
|
+
}
|
|
13197
|
+
|
|
13198
|
+
.issue-sticker-onboarding-highlight {
|
|
13199
|
+
animation: issue-sticker-onboarding-focus 220ms ease-out;
|
|
13200
|
+
}
|
|
13201
|
+
|
|
12958
13202
|
@media (prefers-reduced-motion: reduce) {
|
|
12959
13203
|
.issue-sticker-onboarding-popover {
|
|
12960
13204
|
transition-duration: 1ms !important;
|
|
12961
13205
|
}
|
|
12962
13206
|
|
|
12963
|
-
.issue-sticker-onboarding-highlight
|
|
13207
|
+
.issue-sticker-onboarding-highlight,
|
|
13208
|
+
.issue-sticker-onboarding-tap,
|
|
13209
|
+
.issue-sticker-onboarding-tap-ripple {
|
|
12964
13210
|
animation: none !important;
|
|
12965
13211
|
}
|
|
12966
13212
|
}
|
|
12967
13213
|
` });
|
|
12968
13214
|
}
|
|
12969
13215
|
function OnboardingPopoverContent({
|
|
13216
|
+
allowSkip,
|
|
12970
13217
|
step,
|
|
12971
13218
|
clickHint,
|
|
12972
13219
|
labels,
|
|
12973
13220
|
canGoPrevious,
|
|
12974
13221
|
isLast,
|
|
12975
13222
|
isVisible,
|
|
12976
|
-
|
|
12977
|
-
onRequestSkip,
|
|
12978
|
-
onCancelSkip,
|
|
12979
|
-
onConfirmSkip,
|
|
13223
|
+
onSkip,
|
|
12980
13224
|
onNext,
|
|
12981
13225
|
onPrevious
|
|
12982
13226
|
}) {
|
|
12983
|
-
|
|
12984
|
-
return /* @__PURE__ */ jsxs(
|
|
12985
|
-
"div",
|
|
12986
|
-
{
|
|
12987
|
-
role: "alertdialog",
|
|
12988
|
-
"aria-modal": "false",
|
|
12989
|
-
"aria-labelledby": "issue-sticker-onboarding-skip-title",
|
|
12990
|
-
"aria-describedby": "issue-sticker-onboarding-skip-desc",
|
|
12991
|
-
children: [
|
|
12992
|
-
/* @__PURE__ */ jsx(
|
|
12993
|
-
"h2",
|
|
12994
|
-
{
|
|
12995
|
-
id: "issue-sticker-onboarding-skip-title",
|
|
12996
|
-
className: "text-sm font-semibold leading-5 text-text-primary",
|
|
12997
|
-
children: labels.skipConfirmTitle
|
|
12998
|
-
}
|
|
12999
|
-
),
|
|
13000
|
-
/* @__PURE__ */ jsx(
|
|
13001
|
-
"p",
|
|
13002
|
-
{
|
|
13003
|
-
id: "issue-sticker-onboarding-skip-desc",
|
|
13004
|
-
className: "mt-2 whitespace-pre-line text-sm leading-5 text-text-secondary",
|
|
13005
|
-
children: labels.skipConfirmBody
|
|
13006
|
-
}
|
|
13007
|
-
),
|
|
13008
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-4 flex items-center justify-end gap-2", children: [
|
|
13009
|
-
/* @__PURE__ */ jsx(
|
|
13010
|
-
"button",
|
|
13011
|
-
{
|
|
13012
|
-
type: "button",
|
|
13013
|
-
onClick: onCancelSkip,
|
|
13014
|
-
disabled: !isVisible,
|
|
13015
|
-
className: "inline-flex h-[30px] items-center justify-center rounded-md border border-line-subtle px-2.5 text-xs font-semibold text-text-secondary transition-colors hover:bg-surface-2 hover:text-text-primary focus-visible:outline-none focus-visible:shadow-focus disabled:pointer-events-none disabled:opacity-50",
|
|
13016
|
-
children: labels.skipConfirmCancel
|
|
13017
|
-
}
|
|
13018
|
-
),
|
|
13019
|
-
/* @__PURE__ */ jsx(
|
|
13020
|
-
"button",
|
|
13021
|
-
{
|
|
13022
|
-
type: "button",
|
|
13023
|
-
onClick: onConfirmSkip,
|
|
13024
|
-
disabled: !isVisible,
|
|
13025
|
-
className: "inline-flex h-[30px] items-center justify-center rounded-md border border-line-subtle px-2.5 text-xs font-semibold text-text-primary transition-colors hover:bg-surface-2 focus-visible:outline-none focus-visible:shadow-focus disabled:pointer-events-none disabled:opacity-50",
|
|
13026
|
-
children: labels.skipConfirmConfirm
|
|
13027
|
-
}
|
|
13028
|
-
)
|
|
13029
|
-
] })
|
|
13030
|
-
]
|
|
13031
|
-
}
|
|
13032
|
-
);
|
|
13033
|
-
}
|
|
13227
|
+
const hasNextButton = shouldRenderNextButton(step);
|
|
13034
13228
|
return /* @__PURE__ */ jsxs("div", { children: [
|
|
13035
13229
|
/* @__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",
|
|
13230
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 whitespace-pre-line text-sm leading-[1.55] text-text-secondary", children: step.body }),
|
|
13231
|
+
step.bodyExtra ? /* @__PURE__ */ jsx("div", { className: "mt-3", children: step.bodyExtra }) : null,
|
|
13232
|
+
clickHint ? (
|
|
13233
|
+
/* 진행 버튼이 없는 단계에서는 이 줄이 유일한 다음 행동이다. 그래서 버튼이 있던
|
|
13234
|
+
* 자리만큼의 무게를 준다 — 작은 글줄로 두면 사용자가 못 보고 다른 버튼을 누른다. */
|
|
13235
|
+
/* @__PURE__ */ jsxs(
|
|
13236
|
+
"p",
|
|
13044
13237
|
{
|
|
13045
|
-
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
children:
|
|
13238
|
+
className: cn(
|
|
13239
|
+
"mt-3 flex items-center gap-1.5 font-semibold text-brand",
|
|
13240
|
+
hasNextButton ? "text-xs leading-5" : "rounded-md border border-brand/40 bg-brand/10 px-3 py-2 text-sm leading-5"
|
|
13241
|
+
),
|
|
13242
|
+
children: [
|
|
13243
|
+
/* @__PURE__ */ jsx(MousePointerClick, { "aria-hidden": "true", className: "h-4 w-4 shrink-0" }),
|
|
13244
|
+
clickHint
|
|
13245
|
+
]
|
|
13050
13246
|
}
|
|
13051
|
-
)
|
|
13247
|
+
)
|
|
13248
|
+
) : null,
|
|
13249
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-4 flex items-center justify-between gap-2", children: [
|
|
13250
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
13251
|
+
allowSkip ? /* @__PURE__ */ jsx(
|
|
13252
|
+
"button",
|
|
13253
|
+
{
|
|
13254
|
+
type: "button",
|
|
13255
|
+
onClick: onSkip,
|
|
13256
|
+
disabled: !isVisible,
|
|
13257
|
+
className: LINK_BUTTON_CLASS,
|
|
13258
|
+
children: labels.skip
|
|
13259
|
+
}
|
|
13260
|
+
) : null,
|
|
13261
|
+
canGoPrevious && !hasNextButton ? /* @__PURE__ */ jsx(
|
|
13262
|
+
"button",
|
|
13263
|
+
{
|
|
13264
|
+
type: "button",
|
|
13265
|
+
onClick: onPrevious,
|
|
13266
|
+
disabled: !isVisible,
|
|
13267
|
+
className: LINK_BUTTON_CLASS,
|
|
13268
|
+
children: labels.previous
|
|
13269
|
+
}
|
|
13270
|
+
) : null
|
|
13271
|
+
] }),
|
|
13052
13272
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
13053
|
-
canGoPrevious ? /* @__PURE__ */ jsx(
|
|
13273
|
+
canGoPrevious && hasNextButton ? /* @__PURE__ */ jsx(
|
|
13054
13274
|
"button",
|
|
13055
13275
|
{
|
|
13056
13276
|
type: "button",
|
|
13057
13277
|
onClick: onPrevious,
|
|
13058
|
-
disabled: !isVisible
|
|
13278
|
+
disabled: !isVisible,
|
|
13059
13279
|
className: "inline-flex h-[30px] items-center justify-center rounded-md border border-line-subtle px-2.5 text-xs font-semibold text-text-secondary transition-colors hover:bg-surface-2 hover:text-text-primary focus-visible:outline-none focus-visible:shadow-focus disabled:pointer-events-none disabled:opacity-50",
|
|
13060
13280
|
children: labels.previous
|
|
13061
13281
|
}
|
|
13062
13282
|
) : null,
|
|
13063
|
-
|
|
13283
|
+
hasNextButton ? /* @__PURE__ */ jsx(
|
|
13064
13284
|
"button",
|
|
13065
13285
|
{
|
|
13066
13286
|
type: "button",
|
|
13067
13287
|
onClick: onNext,
|
|
13068
|
-
disabled: !isVisible
|
|
13288
|
+
disabled: !isVisible,
|
|
13069
13289
|
className: "inline-flex h-[30px] items-center justify-center rounded-md border border-line-subtle px-2.5 text-xs font-semibold text-text-primary transition-colors hover:bg-surface-2 focus-visible:outline-none focus-visible:shadow-focus disabled:pointer-events-none disabled:opacity-50",
|
|
13070
13290
|
children: isLast ? labels.done : step.nextLabel ?? labels.next
|
|
13071
13291
|
}
|
|
@@ -13078,6 +13298,9 @@ function OnboardingOverlay({
|
|
|
13078
13298
|
step,
|
|
13079
13299
|
targetRect,
|
|
13080
13300
|
targetRadius,
|
|
13301
|
+
avoidRects,
|
|
13302
|
+
elevateHighlight,
|
|
13303
|
+
allowSkip = true,
|
|
13081
13304
|
className,
|
|
13082
13305
|
labels,
|
|
13083
13306
|
isPopoverVisible,
|
|
@@ -13088,25 +13311,45 @@ function OnboardingOverlay({
|
|
|
13088
13311
|
onPrevious
|
|
13089
13312
|
}) {
|
|
13090
13313
|
const maskId = React.useId().replace(/:/g, "");
|
|
13091
|
-
const
|
|
13314
|
+
const renderHighlight = (node) => elevateHighlight && typeof document !== "undefined" ? ReactDOM.createPortal(node, document.body) : node;
|
|
13092
13315
|
const cutoutRect = targetRect ? padRect(targetRect, MASK_PADDING) : null;
|
|
13093
13316
|
const cutoutRadius = cutoutRect ? Math.min(
|
|
13094
13317
|
targetRadius === null || targetRadius === void 0 ? CUTOUT_RADIUS : targetRadius + MASK_PADDING,
|
|
13095
13318
|
cutoutRect.width / 2,
|
|
13096
13319
|
cutoutRect.height / 2
|
|
13097
13320
|
) : 0;
|
|
13098
|
-
const
|
|
13321
|
+
const popoverRef = React.useRef(null);
|
|
13322
|
+
const [popoverSize, setPopoverSize] = React.useState(
|
|
13323
|
+
null
|
|
13324
|
+
);
|
|
13325
|
+
React.useLayoutEffect(() => {
|
|
13326
|
+
const element = popoverRef.current;
|
|
13327
|
+
if (!element) return void 0;
|
|
13328
|
+
const measure = () => {
|
|
13329
|
+
const rect = element.getBoundingClientRect();
|
|
13330
|
+
setPopoverSize(
|
|
13331
|
+
(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 }
|
|
13332
|
+
);
|
|
13333
|
+
};
|
|
13334
|
+
measure();
|
|
13335
|
+
if (typeof ResizeObserver === "undefined") return void 0;
|
|
13336
|
+
const observer = new ResizeObserver(measure);
|
|
13337
|
+
observer.observe(element);
|
|
13338
|
+
return () => observer.disconnect();
|
|
13339
|
+
}, [step.id, step.body]);
|
|
13340
|
+
const effectiveSize = popoverSize && popoverSize.width > 0 && popoverSize.height > 0 ? popoverSize : DEFAULT_POPOVER_SIZE;
|
|
13341
|
+
const placement = resolvePopoverPlacement(
|
|
13099
13342
|
step.position ?? (cutoutRect ? "bottom" : "center"),
|
|
13100
|
-
cutoutRect ?? getViewportRect()
|
|
13343
|
+
cutoutRect ?? getViewportRect(),
|
|
13344
|
+
effectiveSize,
|
|
13345
|
+
cutoutRect ? avoidRects ?? [] : []
|
|
13101
13346
|
);
|
|
13347
|
+
const { left: popoverLeft, top: popoverTop } = placement;
|
|
13102
13348
|
const shouldCenterPopover = !cutoutRect && (step.position ?? "center") === "center";
|
|
13103
|
-
const maskColor = "rgba(8, 13, 18, 0.62)";
|
|
13349
|
+
const maskColor = isTargetInteractionStep(step) ? "rgba(8, 13, 18, 0.74)" : "rgba(8, 13, 18, 0.62)";
|
|
13104
13350
|
const isPassthrough = !!step.advanceOn;
|
|
13105
13351
|
const isTargetInteraction = isTargetInteractionStep(step);
|
|
13106
13352
|
const clickHint = isTargetInteraction ? step.clickHint ?? labels.clickHint : null;
|
|
13107
|
-
React.useEffect(() => {
|
|
13108
|
-
setIsSkipConfirmOpen(false);
|
|
13109
|
-
}, [step.id]);
|
|
13110
13353
|
return /* @__PURE__ */ jsxs(
|
|
13111
13354
|
"div",
|
|
13112
13355
|
{
|
|
@@ -13191,58 +13434,97 @@ function OnboardingOverlay({
|
|
|
13191
13434
|
}
|
|
13192
13435
|
}
|
|
13193
13436
|
) : null,
|
|
13194
|
-
cutoutRect ?
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
|
|
13201
|
-
|
|
13202
|
-
|
|
13203
|
-
|
|
13204
|
-
|
|
13205
|
-
|
|
13206
|
-
|
|
13207
|
-
|
|
13208
|
-
|
|
13209
|
-
|
|
13437
|
+
cutoutRect ? renderHighlight(
|
|
13438
|
+
/* @__PURE__ */ jsx(
|
|
13439
|
+
"div",
|
|
13440
|
+
{
|
|
13441
|
+
"aria-hidden": "true",
|
|
13442
|
+
"data-testid": "onboarding-cutout-outline",
|
|
13443
|
+
className: cn(
|
|
13444
|
+
"issue-sticker-onboarding-highlight fixed",
|
|
13445
|
+
isTargetInteraction ? "border-2 border-brand" : "border border-white/90"
|
|
13446
|
+
),
|
|
13447
|
+
style: {
|
|
13448
|
+
left: cutoutRect.left,
|
|
13449
|
+
top: cutoutRect.top,
|
|
13450
|
+
width: cutoutRect.width,
|
|
13451
|
+
height: cutoutRect.height,
|
|
13452
|
+
borderRadius: cutoutRadius,
|
|
13453
|
+
pointerEvents: "none",
|
|
13454
|
+
zIndex: elevateHighlight ? OVERLAY_LAYER_INDEX.runtimeHost : void 0
|
|
13455
|
+
}
|
|
13456
|
+
},
|
|
13457
|
+
step.id
|
|
13458
|
+
)
|
|
13459
|
+
) : null,
|
|
13460
|
+
cutoutRect && isTargetInteraction ? renderHighlight(
|
|
13461
|
+
/* 클릭하는 커서. 테두리만으로는 "봐야 할 곳"까지만 전달되고 "클릭하라"가
|
|
13462
|
+
* 전달되지 않는다. 손 모양 반복 동작이 그 자리를 맡는다. */
|
|
13463
|
+
/* @__PURE__ */ jsxs(
|
|
13464
|
+
"div",
|
|
13465
|
+
{
|
|
13466
|
+
"aria-hidden": "true",
|
|
13467
|
+
"data-testid": "onboarding-cutout-cursor",
|
|
13468
|
+
className: "issue-sticker-onboarding-tap fixed",
|
|
13469
|
+
style: {
|
|
13470
|
+
left: cutoutRect.right - TAP_INSET,
|
|
13471
|
+
top: cutoutRect.bottom - TAP_INSET,
|
|
13472
|
+
pointerEvents: "none",
|
|
13473
|
+
zIndex: elevateHighlight ? OVERLAY_LAYER_INDEX.runtimeHost : void 0
|
|
13474
|
+
},
|
|
13475
|
+
children: [
|
|
13476
|
+
/* @__PURE__ */ jsx(
|
|
13477
|
+
"span",
|
|
13478
|
+
{
|
|
13479
|
+
className: "issue-sticker-onboarding-tap-ripple absolute rounded-full bg-brand",
|
|
13480
|
+
style: { left: 0, top: 0, width: TAP_RIPPLE_SIZE, height: TAP_RIPPLE_SIZE }
|
|
13481
|
+
}
|
|
13482
|
+
),
|
|
13483
|
+
/* @__PURE__ */ jsx(
|
|
13484
|
+
MousePointer2,
|
|
13485
|
+
{
|
|
13486
|
+
className: "relative h-8 w-8",
|
|
13487
|
+
style: { fill: "#ffffff", stroke: "rgba(12, 18, 15, 0.7)" },
|
|
13488
|
+
strokeWidth: 1.4
|
|
13489
|
+
}
|
|
13490
|
+
)
|
|
13491
|
+
]
|
|
13210
13492
|
}
|
|
13211
|
-
|
|
13493
|
+
)
|
|
13212
13494
|
) : null,
|
|
13213
|
-
|
|
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
|
-
|
|
13495
|
+
renderHighlight(
|
|
13496
|
+
/* @__PURE__ */ jsx(
|
|
13497
|
+
"div",
|
|
13498
|
+
{
|
|
13499
|
+
ref: popoverRef,
|
|
13500
|
+
role: "dialog",
|
|
13501
|
+
"aria-modal": "false",
|
|
13502
|
+
...{ [ONBOARDING_POPOVER_DATA_ATTR]: "floating" },
|
|
13503
|
+
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",
|
|
13504
|
+
style: {
|
|
13505
|
+
left: shouldCenterPopover ? "50%" : popoverLeft,
|
|
13506
|
+
top: shouldCenterPopover ? "50%" : popoverTop,
|
|
13507
|
+
opacity: isPopoverVisible ? 1 : 0,
|
|
13508
|
+
transform: shouldCenterPopover ? "translate(-50%, -50%)" : void 0,
|
|
13509
|
+
zIndex: elevateHighlight ? OVERLAY_LAYER_INDEX.runtimeHost : OVERLAY_LAYER_INDEX.tourPopover
|
|
13510
|
+
},
|
|
13511
|
+
children: /* @__PURE__ */ jsx(
|
|
13512
|
+
OnboardingPopoverContent,
|
|
13513
|
+
{
|
|
13514
|
+
allowSkip,
|
|
13515
|
+
step,
|
|
13516
|
+
clickHint,
|
|
13517
|
+
labels,
|
|
13518
|
+
canGoPrevious,
|
|
13519
|
+
isLast,
|
|
13520
|
+
isVisible: isPopoverVisible,
|
|
13521
|
+
onSkip,
|
|
13522
|
+
onNext,
|
|
13523
|
+
onPrevious
|
|
13524
|
+
}
|
|
13525
|
+
)
|
|
13526
|
+
}
|
|
13527
|
+
)
|
|
13246
13528
|
)
|
|
13247
13529
|
]
|
|
13248
13530
|
}
|
|
@@ -13335,7 +13617,9 @@ function OnboardingProvider({
|
|
|
13335
13617
|
className,
|
|
13336
13618
|
labels: labelOverrides,
|
|
13337
13619
|
storage: storageOverride,
|
|
13338
|
-
suppressed = false
|
|
13620
|
+
suppressed = false,
|
|
13621
|
+
elevateHighlight = false,
|
|
13622
|
+
allowSkip = true
|
|
13339
13623
|
}) {
|
|
13340
13624
|
const labels = React.useMemo(() => ({ ...DEFAULT_LABELS, ...labelOverrides }), [labelOverrides]);
|
|
13341
13625
|
const storage = React.useMemo(
|
|
@@ -13617,6 +13901,7 @@ function OnboardingProvider({
|
|
|
13617
13901
|
const allTargetsResolved = activeTargetIds.length > 0 && resolvedTargetRects.every((rect) => rect !== null);
|
|
13618
13902
|
const targetRect = isOpen && isActiveRoute && allTargetsResolved ? unionRect(resolvedTargetRects.filter((r2) => r2 !== null)) : null;
|
|
13619
13903
|
const targetRadius = activeTargetIds.length === 1 ? getElementRadius(targetMapRef.current.get(activeTargetIds[0]) ?? null) : null;
|
|
13904
|
+
const avoidRects = ((activeStep == null ? void 0 : activeStep.avoidTargetIds) ?? []).map((id) => getElementRect(targetMapRef.current.get(id) ?? null)).filter((rect) => rect !== null);
|
|
13620
13905
|
const shouldRenderOverlay = isOpen && activeStep && isActiveRoute && !suppressed && !activeStep.silent && (!stepHasTarget || targetRect);
|
|
13621
13906
|
const isTargetReady = !stepHasTarget || targetRect !== null;
|
|
13622
13907
|
React.useEffect(() => {
|
|
@@ -13668,6 +13953,9 @@ function OnboardingProvider({
|
|
|
13668
13953
|
step: activeStep,
|
|
13669
13954
|
targetRect,
|
|
13670
13955
|
targetRadius,
|
|
13956
|
+
avoidRects,
|
|
13957
|
+
elevateHighlight,
|
|
13958
|
+
allowSkip,
|
|
13671
13959
|
className,
|
|
13672
13960
|
labels,
|
|
13673
13961
|
isPopoverVisible,
|
|
@@ -13895,89 +14183,83 @@ function buildExternalUserPayload(user) {
|
|
|
13895
14183
|
};
|
|
13896
14184
|
}
|
|
13897
14185
|
export {
|
|
13898
|
-
|
|
13899
|
-
|
|
13900
|
-
|
|
14186
|
+
getNotionPageMetadata as $,
|
|
14187
|
+
getLogBackupSessionId as A,
|
|
14188
|
+
createIndexedDbLogBackup as B,
|
|
13901
14189
|
ConsoleCollector as C,
|
|
13902
|
-
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
|
|
13906
|
-
|
|
14190
|
+
PopoverTrigger as D,
|
|
14191
|
+
Input as E,
|
|
14192
|
+
PopoverContent as F,
|
|
14193
|
+
Select$1 as G,
|
|
14194
|
+
SelectTrigger as H,
|
|
13907
14195
|
ISSUE_STICKER_INTERNAL_LOG_PREFIX as I,
|
|
13908
|
-
|
|
13909
|
-
|
|
14196
|
+
SelectValue as J,
|
|
14197
|
+
SelectContent as K,
|
|
13910
14198
|
Label as L,
|
|
13911
|
-
|
|
14199
|
+
SelectItem as M,
|
|
13912
14200
|
NetworkCollector as N,
|
|
13913
|
-
|
|
14201
|
+
getJiraMetadata as O,
|
|
13914
14202
|
Popover as P,
|
|
13915
|
-
|
|
13916
|
-
|
|
14203
|
+
buildJiraIssueFields as Q,
|
|
14204
|
+
Button$1 as R,
|
|
13917
14205
|
ScreenRecordingController as S,
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
14206
|
+
Root2 as T,
|
|
14207
|
+
Trigger as U,
|
|
14208
|
+
ChevronDown as V,
|
|
14209
|
+
Portal as W,
|
|
14210
|
+
Content2 as X,
|
|
14211
|
+
Check as Y,
|
|
14212
|
+
X as Z,
|
|
14213
|
+
DatePicker as _,
|
|
13926
14214
|
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
|
-
|
|
13952
|
-
|
|
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,
|
|
13958
|
-
normalizeJiraFieldId as b,
|
|
14215
|
+
buildNotionFieldViews as a0,
|
|
14216
|
+
DirectUploadError as a1,
|
|
14217
|
+
toast as a2,
|
|
14218
|
+
getSnapshot as a3,
|
|
14219
|
+
subscribe as a4,
|
|
14220
|
+
getRegisteredUploadId as a5,
|
|
14221
|
+
ChevronRight as a6,
|
|
14222
|
+
ReactRemoveScroll as a7,
|
|
14223
|
+
hideOthers as a8,
|
|
14224
|
+
useFocusGuards as a9,
|
|
14225
|
+
FocusScope as aa,
|
|
14226
|
+
getExposedJiraFields as ab,
|
|
14227
|
+
isJiraFieldExposed as ac,
|
|
14228
|
+
normalizeExposedJiraFields as ad,
|
|
14229
|
+
getPrimaryJiraMapping as ae,
|
|
14230
|
+
createCollection as af,
|
|
14231
|
+
useDirection as ag,
|
|
14232
|
+
getPrimaryNotionMapping as ah,
|
|
14233
|
+
buttonVariants as ai,
|
|
14234
|
+
findElementBySelector as aj,
|
|
14235
|
+
findElementByXPath as ak,
|
|
14236
|
+
OnboardingProvider as al,
|
|
14237
|
+
useOnboardingTarget as am,
|
|
14238
|
+
useOnboardingFlow as an,
|
|
14239
|
+
PopoverAnchor as ao,
|
|
14240
|
+
buildJiraCreateFields as b,
|
|
13959
14241
|
captureWithModernScreenshot as c,
|
|
13960
14242
|
directUploadToSignedUrl as d,
|
|
13961
|
-
|
|
13962
|
-
|
|
14243
|
+
buildNotionCreateFields as e,
|
|
14244
|
+
buildGuestOwnerQuery as f,
|
|
13963
14245
|
getElementPosition as g,
|
|
13964
|
-
|
|
14246
|
+
composeIssueFilterGroups as h,
|
|
13965
14247
|
buildIssueIntegrationsPayload as i,
|
|
13966
14248
|
devLogger as j,
|
|
13967
14249
|
filterExcludeServiceRelatedLogs as k,
|
|
13968
14250
|
filterExcludeServiceRelatedConsoleLogs as l,
|
|
13969
14251
|
compactNetworkLogsForTransport as m,
|
|
13970
|
-
|
|
13971
|
-
|
|
14252
|
+
CONSOLE_LOG_SUBMIT_LIMIT as n,
|
|
14253
|
+
buildExternalUserPayload as o,
|
|
13972
14254
|
pristineFetch as p,
|
|
13973
|
-
|
|
13974
|
-
|
|
14255
|
+
shrinkNetworkLogsToFit as q,
|
|
14256
|
+
measureJsonBytes as r,
|
|
13975
14257
|
selectNetworkLogsForSubmit as s,
|
|
13976
|
-
|
|
14258
|
+
sanitizeString as t,
|
|
13977
14259
|
uploadScreenshotDataUrls as u,
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
|
|
14260
|
+
getCurrentPageUrl as v,
|
|
14261
|
+
SessionReplayCaptureController as w,
|
|
14262
|
+
preloadModernScreenshot as x,
|
|
14263
|
+
trimLogBackupPayload as y,
|
|
14264
|
+
createSafeLogBackup as z
|
|
13983
14265
|
};
|