@realtimexsco/live-chat 1.4.6 → 1.4.8

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.
@@ -32,7 +32,19 @@ if (rawConfig) {
32
32
 
33
33
  // Background messages that carry a `notification` payload are displayed
34
34
  // by FCM automatically; initializing messaging here is what enables it.
35
- firebase.messaging();
35
+ var messaging = firebase.messaging();
36
+
37
+ // Log full backend payload when a push arrives in the background.
38
+ // Check this in DevTools → Application → Service Workers → console,
39
+ // or Chrome → chrome://serviceworker-internals
40
+ messaging.onBackgroundMessage(function (payload) {
41
+ console.log("[realtimex-push] FCM background payload (raw):", payload);
42
+ console.log("[realtimex-push] FCM background data:", payload && payload.data);
43
+ console.log(
44
+ "[realtimex-push] FCM background notification:",
45
+ payload && payload.notification,
46
+ );
47
+ });
36
48
  } catch (error) {
37
49
  console.error("[realtimex] Invalid firebase config in SW URL:", error);
38
50
  }
@@ -43,24 +55,98 @@ if (rawConfig) {
43
55
  );
44
56
  }
45
57
 
46
- // Focus (or open) the chat when a notification is clicked.
58
+ function extractNotificationData(notification) {
59
+ var raw = (notification && notification.data) || {};
60
+ var nested =
61
+ raw.FCM_MSG && raw.FCM_MSG.data && typeof raw.FCM_MSG.data === "object"
62
+ ? raw.FCM_MSG.data
63
+ : null;
64
+ var merged = {};
65
+ if (nested) {
66
+ for (var key in nested) {
67
+ if (Object.prototype.hasOwnProperty.call(nested, key)) {
68
+ merged[key] = nested[key];
69
+ }
70
+ }
71
+ }
72
+ for (var key2 in raw) {
73
+ if (Object.prototype.hasOwnProperty.call(raw, key2) && key2 !== "FCM_MSG") {
74
+ merged[key2] = raw[key2];
75
+ }
76
+ }
77
+ return merged;
78
+ }
79
+
80
+ function resolveConversationId(data) {
81
+ if (!data) return "";
82
+ return String(
83
+ data.conversationId ||
84
+ data.conversation_id ||
85
+ data.conversationID ||
86
+ "",
87
+ );
88
+ }
89
+
90
+ function buildTargetUrl(data, conversationId) {
91
+ if (data && data.link) return String(data.link);
92
+
93
+ if (conversationId) {
94
+ return "/chat?conversationId=" + encodeURIComponent(conversationId);
95
+ }
96
+
97
+ return "/chat";
98
+ }
99
+
100
+ function isChatClient(client) {
101
+ try {
102
+ var pathname = new URL(client.url).pathname || "";
103
+ return pathname === "/chat" || pathname.indexOf("/chat/") === 0;
104
+ } catch (e) {
105
+ return false;
106
+ }
107
+ }
108
+
109
+ // Focus (or open) the chat and tell the page which conversation to open.
47
110
  self.addEventListener("notificationclick", function (event) {
48
111
  event.notification.close();
49
112
 
50
- var targetUrl =
51
- (event.notification.data &&
52
- event.notification.data.FCM_MSG &&
53
- event.notification.data.FCM_MSG.data &&
54
- event.notification.data.FCM_MSG.data.link) ||
55
- "/";
113
+ console.log(
114
+ "[realtimex-push] notificationclick raw notification.data:",
115
+ event.notification && event.notification.data,
116
+ );
117
+
118
+ var data = extractNotificationData(event.notification);
119
+ var conversationId = resolveConversationId(data);
120
+ var targetUrl = buildTargetUrl(data, conversationId);
121
+ var message = {
122
+ type: "realtimex:notification-click",
123
+ conversationId: conversationId,
124
+ };
125
+
126
+ console.log("[realtimex-push] notificationclick extracted data:", data);
127
+ console.log("[realtimex-push] notificationclick conversationId:", conversationId);
128
+ console.log("[realtimex-push] notificationclick targetUrl:", targetUrl);
56
129
 
57
130
  event.waitUntil(
58
131
  clients
59
132
  .matchAll({ type: "window", includeUncontrolled: true })
60
133
  .then(function (windowClients) {
134
+ var chatClient = null;
135
+ var anyClient = null;
136
+
61
137
  for (var i = 0; i < windowClients.length; i++) {
62
- if ("focus" in windowClients[i]) return windowClients[i].focus();
138
+ var client = windowClients[i];
139
+ if (!anyClient) anyClient = client;
140
+ if (!chatClient && isChatClient(client)) chatClient = client;
63
141
  }
142
+
143
+ var target = chatClient || anyClient;
144
+ if (target && "focus" in target) {
145
+ return target.focus().then(function () {
146
+ if (target.postMessage) target.postMessage(message);
147
+ });
148
+ }
149
+
64
150
  if (clients.openWindow) return clients.openWindow(targetUrl);
65
151
  return undefined;
66
152
  }),
package/dist/index.cjs CHANGED
@@ -16,7 +16,7 @@ var lucideReact = require('lucide-react');
16
16
  var classVarianceAuthority = require('class-variance-authority');
17
17
  var EmojiPicker = require('emoji-picker-react');
18
18
  var reactDayPicker = require('react-day-picker');
19
- var reactHotToast = require('react-hot-toast');
19
+ var toast2 = require('react-hot-toast');
20
20
 
21
21
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
22
22
 
@@ -41,6 +41,7 @@ function _interopNamespace(e) {
41
41
  var axios__default = /*#__PURE__*/_interopDefault(axios);
42
42
  var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
43
43
  var EmojiPicker__default = /*#__PURE__*/_interopDefault(EmojiPicker);
44
+ var toast2__default = /*#__PURE__*/_interopDefault(toast2);
44
45
 
45
46
  var __defProp = Object.defineProperty;
46
47
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -4653,6 +4654,127 @@ var Chat = ({
4653
4654
  // src/hooks/useChatController.ts
4654
4655
  init_useStore();
4655
4656
  init_store_helpers();
4657
+
4658
+ // src/notifications/open-conversation.ts
4659
+ init_store_helpers();
4660
+ var OPEN_CONVERSATION_EVENT = "realtimex:open-conversation";
4661
+ var NOTIFICATION_CLICK_SW_TYPE = "realtimex:notification-click";
4662
+ var PENDING_STORAGE_KEY = "realtimex:pending-open-conversation";
4663
+ var resolveConversationIdFromPushData = (data) => {
4664
+ if (!data || typeof data !== "object") return "";
4665
+ const nested = data.FCM_MSG && typeof data.FCM_MSG === "object" ? data.FCM_MSG.data : void 0;
4666
+ const source = { ...nested || {}, ...data };
4667
+ return String(
4668
+ source.conversationId || source.conversation_id || source.conversationID || ""
4669
+ );
4670
+ };
4671
+ var peekPendingOpenConversation = () => {
4672
+ try {
4673
+ return sessionStorage.getItem(PENDING_STORAGE_KEY);
4674
+ } catch {
4675
+ return null;
4676
+ }
4677
+ };
4678
+ var consumePendingOpenConversation = () => {
4679
+ const id = peekPendingOpenConversation();
4680
+ try {
4681
+ sessionStorage.removeItem(PENDING_STORAGE_KEY);
4682
+ } catch {
4683
+ }
4684
+ return id;
4685
+ };
4686
+ var requestOpenConversation = (conversationId) => {
4687
+ const id = String(conversationId || "").trim();
4688
+ if (!id) return;
4689
+ try {
4690
+ sessionStorage.setItem(PENDING_STORAGE_KEY, id);
4691
+ } catch {
4692
+ }
4693
+ try {
4694
+ window.dispatchEvent(
4695
+ new CustomEvent(OPEN_CONVERSATION_EVENT, {
4696
+ detail: { conversationId: id }
4697
+ })
4698
+ );
4699
+ } catch {
4700
+ }
4701
+ };
4702
+ var mapConversationToChannel = (conversation, loggedUserId, allUsers) => {
4703
+ const conversationId = String(conversation?._id || conversation?.id || "");
4704
+ const isGroup = isGroupConversation(conversation);
4705
+ if (isGroup) {
4706
+ const rawName2 = conversation.groupName || conversation.name || "Group Chat";
4707
+ return {
4708
+ id: conversationId,
4709
+ conversationId,
4710
+ name: rawName2.charAt(0).toUpperCase() + rawName2.slice(1),
4711
+ image: resolveGroupImage(conversation),
4712
+ isGroup: true,
4713
+ isLeft: !!conversation.isLeft,
4714
+ isBlocked: !!conversation.isBlocked,
4715
+ pinnedCount: conversation.pinnedCount,
4716
+ starredCount: conversation.starredCount
4717
+ };
4718
+ }
4719
+ const { id: otherId, user } = resolveOtherParticipant(
4720
+ conversation,
4721
+ loggedUserId,
4722
+ allUsers
4723
+ );
4724
+ const rawName = user?.name || "Unknown User";
4725
+ return {
4726
+ id: otherId || conversationId,
4727
+ conversationId,
4728
+ name: rawName.charAt(0).toUpperCase() + rawName.slice(1),
4729
+ image: user?.image || void 0,
4730
+ email: user?.email,
4731
+ isGroup: false,
4732
+ isLeft: !!conversation.isLeft,
4733
+ isBlocked: !!conversation.isBlocked,
4734
+ pinnedCount: conversation.pinnedCount,
4735
+ starredCount: conversation.starredCount
4736
+ };
4737
+ };
4738
+ var readConversationIdFromLocation = () => {
4739
+ try {
4740
+ return new URLSearchParams(window.location.search).get("conversationId") || "";
4741
+ } catch {
4742
+ return "";
4743
+ }
4744
+ };
4745
+ var consumedUrlConversationIds = /* @__PURE__ */ new Set();
4746
+ var installNotificationClickBridge = (options = {}) => {
4747
+ if (typeof window === "undefined") return () => void 0;
4748
+ const chatPath = options.chatPath || "/chat";
4749
+ const handleOpen = (conversationId) => {
4750
+ const id = String(conversationId || "").trim();
4751
+ if (!id) return;
4752
+ requestOpenConversation(id);
4753
+ const pathWithQuery = `${chatPath}?conversationId=${encodeURIComponent(id)}`;
4754
+ options.onNavigate?.(id, pathWithQuery);
4755
+ };
4756
+ const onSwMessage = (event) => {
4757
+ const data = event.data;
4758
+ console.log("[realtimex-push] SW \u2192 page message:", data);
4759
+ if (!data || data.type !== NOTIFICATION_CLICK_SW_TYPE) return;
4760
+ console.log(
4761
+ "[realtimex-push] notification click conversationId:",
4762
+ data.conversationId
4763
+ );
4764
+ handleOpen(String(data.conversationId || ""));
4765
+ };
4766
+ navigator.serviceWorker?.addEventListener("message", onSwMessage);
4767
+ const fromUrl = readConversationIdFromLocation();
4768
+ if (fromUrl && !consumedUrlConversationIds.has(fromUrl)) {
4769
+ consumedUrlConversationIds.add(fromUrl);
4770
+ handleOpen(fromUrl);
4771
+ }
4772
+ return () => {
4773
+ navigator.serviceWorker?.removeEventListener("message", onSwMessage);
4774
+ };
4775
+ };
4776
+
4777
+ // src/hooks/useChatController.ts
4656
4778
  function resolveMessageType(content, attachments) {
4657
4779
  if (attachments.length === 0) return "text";
4658
4780
  if (!content.trim() && attachments.length === 1) {
@@ -4725,6 +4847,10 @@ var useChatController = () => {
4725
4847
  const lastDM = exports.useChatStore((s) => s.lastDM);
4726
4848
  const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
4727
4849
  const rateLimitResetAt2 = exports.useChatStore((s) => s.rateLimitResetAt);
4850
+ const allUsers = exports.useChatStore((s) => s.allUsers);
4851
+ const isFetchingConversations = exports.useChatStore((s) => s.isFetchingConversations);
4852
+ const conversations = exports.useChatStore((s) => s.conversations);
4853
+ const [pendingOpenConversationId, setPendingOpenConversationId] = React2.useState(() => peekPendingOpenConversation());
4728
4854
  const conversationsLength = exports.useChatStore(
4729
4855
  (s) => state.activeChannel?.conversationId ? 0 : s.conversations.length
4730
4856
  );
@@ -4753,6 +4879,73 @@ var useChatController = () => {
4753
4879
  isGroupConversation(latestInfo)
4754
4880
  ].join("|");
4755
4881
  });
4882
+ React2.useEffect(() => {
4883
+ const onOpen = (event) => {
4884
+ const id = String(
4885
+ event.detail?.conversationId || ""
4886
+ ).trim();
4887
+ if (id) setPendingOpenConversationId(id);
4888
+ };
4889
+ window.addEventListener(OPEN_CONVERSATION_EVENT, onOpen);
4890
+ return () => window.removeEventListener(OPEN_CONVERSATION_EVENT, onOpen);
4891
+ }, []);
4892
+ React2.useEffect(() => {
4893
+ if (!pendingOpenConversationId || !loggedUserDetails) return;
4894
+ let cancelled = false;
4895
+ const openPending = async () => {
4896
+ const targetId = String(pendingOpenConversationId);
4897
+ let conversation = conversations.find(
4898
+ (c) => String(c._id || c.id) === targetId
4899
+ ) || null;
4900
+ if (!conversation) {
4901
+ const fromInfo = conversationInfos[targetId];
4902
+ if (fromInfo) conversation = fromInfo;
4903
+ }
4904
+ if (!conversation) {
4905
+ if (isFetchingConversations) return;
4906
+ try {
4907
+ await fetchConversationInfo2(targetId);
4908
+ } catch {
4909
+ return;
4910
+ }
4911
+ if (cancelled) return;
4912
+ const stateNow = exports.useChatStore.getState();
4913
+ conversation = stateNow.conversations.find(
4914
+ (c) => String(c._id || c.id) === targetId
4915
+ ) || stateNow.conversationInfos[targetId] || null;
4916
+ }
4917
+ if (!conversation || cancelled) return;
4918
+ const channel = mapConversationToChannel(
4919
+ conversation,
4920
+ loggedUserDetails._id,
4921
+ allUsers
4922
+ );
4923
+ setState((prev) => {
4924
+ if (prev.activeChannel?.conversationId && String(prev.activeChannel.conversationId) === targetId) {
4925
+ return prev;
4926
+ }
4927
+ return {
4928
+ ...prev,
4929
+ activeChannel: channel,
4930
+ activeConversationId: targetId
4931
+ };
4932
+ });
4933
+ consumePendingOpenConversation();
4934
+ setPendingOpenConversationId(null);
4935
+ };
4936
+ void openPending();
4937
+ return () => {
4938
+ cancelled = true;
4939
+ };
4940
+ }, [
4941
+ pendingOpenConversationId,
4942
+ loggedUserDetails,
4943
+ conversations,
4944
+ conversationInfos,
4945
+ isFetchingConversations,
4946
+ allUsers,
4947
+ fetchConversationInfo2
4948
+ ]);
4756
4949
  React2.useEffect(() => {
4757
4950
  const handler = setTimeout(() => {
4758
4951
  updateState({ debouncedSearch: state.searchQuery });
@@ -17389,19 +17582,19 @@ var showNotification = (message, type = "info", icon, duration) => {
17389
17582
  };
17390
17583
  switch (type) {
17391
17584
  case "success":
17392
- reactHotToast.toast.success(message, options);
17585
+ toast2.toast.success(message, options);
17393
17586
  break;
17394
17587
  case "error":
17395
- reactHotToast.toast.error(message, options);
17588
+ toast2.toast.error(message, options);
17396
17589
  break;
17397
17590
  case "info":
17398
- reactHotToast.toast(message, options);
17591
+ toast2.toast(message, options);
17399
17592
  break;
17400
17593
  case "warning":
17401
- reactHotToast.toast(message, { ...options, icon: "\u26A0\uFE0F" });
17594
+ toast2.toast(message, { ...options, icon: "\u26A0\uFE0F" });
17402
17595
  break;
17403
17596
  default:
17404
- reactHotToast.toast(message, options);
17597
+ toast2.toast(message, options);
17405
17598
  }
17406
17599
  };
17407
17600
  var downloadFile = async (src, name) => {
@@ -17610,6 +17803,9 @@ var onForegroundPush = async (callback) => {
17610
17803
  }
17611
17804
  const { fb, messaging } = await getFirebaseMessaging(config.firebaseConfig);
17612
17805
  return fb.onMessage(messaging, (payload) => {
17806
+ console.log("[realtimex-push] FCM foreground payload (raw):", payload);
17807
+ console.log("[realtimex-push] FCM foreground data:", payload?.data);
17808
+ console.log("[realtimex-push] FCM foreground notification:", payload?.notification);
17613
17809
  callback({
17614
17810
  title: payload?.notification?.title,
17615
17811
  body: payload?.notification?.body,
@@ -17630,9 +17826,6 @@ var rememberToastId = (id) => {
17630
17826
  }
17631
17827
  return true;
17632
17828
  };
17633
- var resolveIncomingConversationId = (data) => String(
17634
- data?.conversationId || data?.conversation_id || data?.conversationID || ""
17635
- );
17636
17829
  var resolveToastText = (title, body) => {
17637
17830
  if (title && body) return `${title}: ${body}`;
17638
17831
  return title || body || "";
@@ -17642,7 +17835,39 @@ var emitToast = (payload, onPush) => {
17642
17835
  const title = payload.title || payload.data?.title;
17643
17836
  const body = payload.body || payload.data?.body || payload.data?.message;
17644
17837
  const text = resolveToastText(title, body);
17645
- if (text) showNotification(text, "info");
17838
+ const conversationId = resolveConversationIdFromPushData(payload.data);
17839
+ if (!text) return;
17840
+ if (conversationId) {
17841
+ toast2__default.default.custom(
17842
+ (t) => /* @__PURE__ */ jsxRuntime.jsx(
17843
+ "button",
17844
+ {
17845
+ type: "button",
17846
+ onClick: () => {
17847
+ toast2__default.default.dismiss(t.id);
17848
+ requestOpenConversation(conversationId);
17849
+ },
17850
+ style: {
17851
+ display: "block",
17852
+ width: "100%",
17853
+ textAlign: "left",
17854
+ cursor: "pointer",
17855
+ background: "var(--background, #fff)",
17856
+ color: "var(--foreground, #111)",
17857
+ border: "1px solid rgba(0,0,0,0.08)",
17858
+ borderRadius: 8,
17859
+ padding: "10px 14px",
17860
+ boxShadow: "0 4px 12px rgba(0,0,0,0.12)",
17861
+ font: "inherit"
17862
+ },
17863
+ children: text
17864
+ }
17865
+ ),
17866
+ { duration: 5e3 }
17867
+ );
17868
+ return;
17869
+ }
17870
+ showNotification(text, "info");
17646
17871
  };
17647
17872
  var ForegroundPushBridge = ({ onPush }) => {
17648
17873
  const lastDM = exports.useChatStore((s) => s.lastDM);
@@ -17693,22 +17918,29 @@ var ForegroundPushBridge = ({ onPush }) => {
17693
17918
  let retryTimer = null;
17694
17919
  let cancelled = false;
17695
17920
  const handlePayload = (payload) => {
17696
- const incoming = resolveIncomingConversationId(payload.data);
17921
+ console.log("[realtimex-push] ForegroundPushBridge payload:", payload);
17922
+ console.log("[realtimex-push] ForegroundPushBridge data keys:", payload.data);
17923
+ const incoming = resolveConversationIdFromPushData(payload.data);
17697
17924
  const activeId = String(
17698
17925
  exports.useChatStore.getState().activeConversationId || ""
17699
17926
  );
17700
17927
  const messageId2 = String(
17701
17928
  payload.data?.messageId || payload.data?.message_id || payload.data?.messageID || ""
17702
17929
  );
17930
+ console.log("[realtimex-push] resolved from backend data:", {
17931
+ conversationId: incoming,
17932
+ messageId: messageId2,
17933
+ activeConversationId: activeId
17934
+ });
17703
17935
  if (incoming && activeId && incoming === activeId) {
17704
- console.debug(
17936
+ console.log(
17705
17937
  "[realtimex-push] foreground push suppressed (conversation open):",
17706
17938
  incoming
17707
17939
  );
17708
17940
  return;
17709
17941
  }
17710
17942
  if (!rememberToastId(messageId2)) return;
17711
- console.debug("[realtimex-push] foreground push \u2192 toast:", {
17943
+ console.log("[realtimex-push] foreground push \u2192 toast:", {
17712
17944
  title: payload.title,
17713
17945
  conversationId: incoming,
17714
17946
  activeConversationId: activeId
@@ -17757,8 +17989,20 @@ var ForegroundPushBridge = ({ onPush }) => {
17757
17989
  window.removeEventListener(PUSH_CHANGED_EVENT, onPushChanged);
17758
17990
  };
17759
17991
  }, []);
17992
+ React2.useEffect(() => {
17993
+ const onOpen = (event) => {
17994
+ const id = String(
17995
+ event.detail?.conversationId || ""
17996
+ );
17997
+ if (id) {
17998
+ console.debug("[realtimex-push] open-conversation event:", id);
17999
+ }
18000
+ };
18001
+ window.addEventListener(OPEN_CONVERSATION_EVENT, onOpen);
18002
+ return () => window.removeEventListener(OPEN_CONVERSATION_EVENT, onOpen);
18003
+ }, []);
17760
18004
  return /* @__PURE__ */ jsxRuntime.jsx(
17761
- reactHotToast.Toaster,
18005
+ toast2.Toaster,
17762
18006
  {
17763
18007
  position: "top-right",
17764
18008
  toastOptions: { duration: 4e3 },
@@ -18251,6 +18495,8 @@ exports.LoggedUserDetails = LoggedUserDetails_default;
18251
18495
  exports.MessageInput = ChannelMessageBoxView_default;
18252
18496
  exports.MessageItem = MessageItemView;
18253
18497
  exports.MessageList = ActiveChannelMessagesView_default;
18498
+ exports.NOTIFICATION_CLICK_SW_TYPE = NOTIFICATION_CLICK_SW_TYPE;
18499
+ exports.OPEN_CONVERSATION_EVENT = OPEN_CONVERSATION_EVENT;
18254
18500
  exports.PUSH_CHANGED_EVENT = PUSH_CHANGED_EVENT;
18255
18501
  exports.PushNotificationToggle = PushNotificationToggle;
18256
18502
  exports.apiGetPushConfig = apiGetPushConfig;
@@ -18260,6 +18506,7 @@ exports.apiRemovePushToken = apiRemovePushToken;
18260
18506
  exports.apiUpdatePushPreference = apiUpdatePushPreference;
18261
18507
  exports.capitalizeFirst = capitalizeFirst;
18262
18508
  exports.clampJumpDate = clampJumpDate;
18509
+ exports.consumePendingOpenConversation = consumePendingOpenConversation;
18263
18510
  exports.default = index_default;
18264
18511
  exports.defaultChatClassNames = defaultChatClassNames;
18265
18512
  exports.defaultChatComponents = defaultChatComponents;
@@ -18272,14 +18519,18 @@ exports.getFirstAndLastNameOneCharacter = getFirstAndLastNameOneCharacter;
18272
18519
  exports.getResponsiveWidth = getResponsiveWidth;
18273
18520
  exports.getSocketConfig = getSocketConfig;
18274
18521
  exports.getStoredPushToken = getStoredPushToken;
18522
+ exports.installNotificationClickBridge = installNotificationClickBridge;
18275
18523
  exports.isEmpty = isEmpty;
18276
18524
  exports.isPushSupported = isPushSupported;
18277
18525
  exports.mergeChatCustomization = mergeChatCustomization;
18278
18526
  exports.mergeChatLayoutConfig = mergeChatLayoutConfig;
18279
18527
  exports.onForegroundPush = onForegroundPush;
18280
18528
  exports.packageDefaultComponents = packageDefaultComponents;
18529
+ exports.peekPendingOpenConversation = peekPendingOpenConversation;
18530
+ exports.requestOpenConversation = requestOpenConversation;
18281
18531
  exports.resolveApiUrl = resolveApiUrl;
18282
18532
  exports.resolveChatApiKey = resolveChatApiKey;
18533
+ exports.resolveConversationIdFromPushData = resolveConversationIdFromPushData;
18283
18534
  exports.resolveJumpDateBounds = resolveJumpDateBounds;
18284
18535
  exports.resolveJumpPreset = resolveJumpPreset;
18285
18536
  exports.resolveJumpStep = resolveJumpStep;