@getlupa/client 1.17.1 → 1.17.4

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.
@@ -25251,6 +25251,9 @@ and ensure you are accounting for this risk.
25251
25251
  }
25252
25252
  emit2("product-click");
25253
25253
  handleRoutingEvent(link, event, boxRoutingBehavior.value === "event");
25254
+ if (props.panelOptions.programmaticNavigation) {
25255
+ window.location.assign(link);
25256
+ }
25254
25257
  };
25255
25258
  return (_ctx, _cache) => {
25256
25259
  return openBlock(), createElementBlock("div", _hoisted_1$Z, [
@@ -25871,6 +25874,7 @@ and ensure you are accounting for this risk.
25871
25874
  const suggestedValue = ref(defaultSuggestedValue);
25872
25875
  const opened = ref(props.isSearchContainer);
25873
25876
  const focused = ref(false);
25877
+ const openedAt = ref(null);
25874
25878
  const searchBoxInput = ref(null);
25875
25879
  const { highlightedDocument } = storeToRefs(searchBoxStore);
25876
25880
  const searchValue = computed(() => {
@@ -25907,7 +25911,7 @@ and ensure you are accounting for this risk.
25907
25911
  });
25908
25912
  const goToResultsDebounced = debounce$1(paramsStore.goToResults, (_a = props.options.debounce) != null ? _a : 300);
25909
25913
  onMounted(() => {
25910
- var _a2;
25914
+ var _a2, _b, _c;
25911
25915
  window.addEventListener("keydown", handleKeyDown);
25912
25916
  window.addEventListener("click", handleMouseClick);
25913
25917
  paramsStore.setSearchResultsLink(props.options.links.searchResults);
@@ -25918,6 +25922,9 @@ and ensure you are accounting for this risk.
25918
25922
  if (props.isSearchContainer && searchBoxInput.value) {
25919
25923
  (_a2 = searchBoxInput.value) == null ? void 0 : _a2.focus();
25920
25924
  }
25925
+ if ((_b = props.options.callbacks) == null ? void 0 : _b.onMounted) {
25926
+ (_c = props.options.callbacks) == null ? void 0 : _c.onMounted();
25927
+ }
25921
25928
  });
25922
25929
  onBeforeUnmount(() => {
25923
25930
  window.removeEventListener("keydown", handleKeyDown);
@@ -25925,11 +25932,14 @@ and ensure you are accounting for this risk.
25925
25932
  unbindSearchTriggers(searchTriggers.value, handleCurrentValueSearch);
25926
25933
  });
25927
25934
  const handleMouseClick = (e2) => {
25928
- var _a2, _b;
25935
+ var _a2, _b, _c, _d;
25929
25936
  const el = document.getElementById("lupa-search-box");
25930
25937
  const elementClass = (_b = (_a2 = e2.target) == null ? void 0 : _a2.className) != null ? _b : "";
25931
25938
  const hasLupaClass = typeof elementClass.includes == "function" && elementClass.includes("lupa-search-box");
25932
25939
  const isOutsideElement = el && !el.contains(e2.target) && !hasLupaClass;
25940
+ if (openedAt.value && Date.now() - (openedAt == null ? void 0 : openedAt.value) < 500) {
25941
+ return;
25942
+ }
25933
25943
  if (isOutsideElement && props.options.keepOpen) {
25934
25944
  focused.value = false;
25935
25945
  }
@@ -25938,11 +25948,18 @@ and ensure you are accounting for this risk.
25938
25948
  }
25939
25949
  opened.value = false;
25940
25950
  suggestedValue.value = defaultSuggestedValue;
25951
+ if ((_c = props.options.callbacks) == null ? void 0 : _c.onClosed) {
25952
+ (_d = props.options.callbacks) == null ? void 0 : _d.onClosed();
25953
+ }
25941
25954
  };
25942
25955
  const close = () => {
25956
+ var _a2, _b;
25943
25957
  opened.value = false;
25944
25958
  focused.value = false;
25945
25959
  suggestedValue.value = defaultSuggestedValue;
25960
+ if ((_a2 = props.options.callbacks) == null ? void 0 : _a2.onClosed) {
25961
+ (_b = props.options.callbacks) == null ? void 0 : _b.onClosed();
25962
+ }
25946
25963
  };
25947
25964
  const handleKeyDown = (e2) => {
25948
25965
  var _a2, _b;
@@ -25961,15 +25978,22 @@ and ensure you are accounting for this risk.
25961
25978
  handleSearch();
25962
25979
  resetValues();
25963
25980
  break;
25981
+ case "Escape":
25982
+ opened.value = false;
25983
+ focused.value = false;
25984
+ break;
25964
25985
  }
25965
25986
  };
25966
25987
  const handleInput = (value) => {
25967
- var _a2;
25988
+ var _a2, _b;
25968
25989
  opened.value = true;
25969
25990
  focused.value = true;
25970
25991
  inputValue.value = (_a2 = value == null ? void 0 : value.replace(/\s+$/, "")) != null ? _a2 : "";
25971
25992
  suggestedValue.value = defaultSuggestedValue;
25972
25993
  searchBoxStore.resetHighlightIndex();
25994
+ if ((_b = props.options.callbacks) == null ? void 0 : _b.onSearchBoxInput) {
25995
+ props.options.callbacks.onSearchBoxInput(value);
25996
+ }
25973
25997
  trackSearchQuery(value);
25974
25998
  if (props.isSearchContainer) {
25975
25999
  goToResultsDebounced({
@@ -26102,6 +26126,13 @@ and ensure you are accounting for this risk.
26102
26126
  });
26103
26127
  };
26104
26128
  watch(() => props.options.debounce, handleCurrentValueSearch);
26129
+ watch(opened, () => {
26130
+ if (opened.value) {
26131
+ openedAt.value = Date.now();
26132
+ } else {
26133
+ openedAt.value = null;
26134
+ }
26135
+ });
26105
26136
  const resetValues = () => {
26106
26137
  inputValue.value = "";
26107
26138
  suggestedValue.value = defaultSuggestedValue;
@@ -26113,6 +26144,20 @@ and ensure you are accounting for this risk.
26113
26144
  const slotProps = (props2) => {
26114
26145
  return __spreadValues2({}, props2);
26115
26146
  };
26147
+ const onFocus = () => {
26148
+ var _a2, _b;
26149
+ opened.value = true;
26150
+ if ((_a2 = props.options.callbacks) == null ? void 0 : _a2.onFocused) {
26151
+ (_b = props.options.callbacks) == null ? void 0 : _b.onFocused();
26152
+ }
26153
+ };
26154
+ const onBlur = () => {
26155
+ var _a2, _b;
26156
+ focused.value = false;
26157
+ if ((_a2 = props.options.callbacks) == null ? void 0 : _a2.onBlurred) {
26158
+ (_b = props.options.callbacks) == null ? void 0 : _b.onBlurred();
26159
+ }
26160
+ };
26116
26161
  return (_ctx, _cache) => {
26117
26162
  var _a2;
26118
26163
  return openBlock(), createElementBlock("div", _hoisted_1$W, [
@@ -26125,10 +26170,10 @@ and ensure you are accounting for this risk.
26125
26170
  ref_key: "searchBoxInput",
26126
26171
  ref: searchBoxInput,
26127
26172
  onInput: handleInput,
26128
- onBlur: _cache[0] || (_cache[0] = ($event) => focused.value = false),
26129
- onFocus: _cache[1] || (_cache[1] = ($event) => opened.value = true),
26173
+ onBlur,
26174
+ onFocus,
26130
26175
  onSearch: handleSearch,
26131
- onClose: _cache[2] || (_cache[2] = ($event) => _ctx.$emit("close"))
26176
+ onClose: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("close"))
26132
26177
  }, null, 8, ["options", "suggestedValue", "can-close", "emit-input-on-focus"]),
26133
26178
  opened.value || _ctx.isSearchContainer ? (openBlock(), createBlock(_sfc_main$11, {
26134
26179
  key: 0,
@@ -39597,6 +39642,33 @@ and ensure you are accounting for this risk.
39597
39642
  shadow.appendChild(style);
39598
39643
  }
39599
39644
  };
39645
+ const createDomPing = () => {
39646
+ let intervalId = null;
39647
+ let remaining = 0;
39648
+ return (intervalMs = 100, count = 50) => {
39649
+ if (intervalId !== null) {
39650
+ clearInterval(intervalId);
39651
+ }
39652
+ remaining = count;
39653
+ const flush = () => {
39654
+ if (remaining-- <= 0) {
39655
+ if (intervalId !== null) {
39656
+ clearInterval(intervalId);
39657
+ intervalId = null;
39658
+ }
39659
+ return;
39660
+ }
39661
+ const el = document.createElement("div");
39662
+ el.style.cssText = "position:absolute;width:0;height:0;overflow:hidden;pointer-events:none;";
39663
+ el.setAttribute("data-nudge", Date.now().toString());
39664
+ document.body.appendChild(el);
39665
+ document.body.removeChild(el);
39666
+ };
39667
+ flush();
39668
+ intervalId = window.setInterval(flush, intervalMs);
39669
+ };
39670
+ };
39671
+ const startDomPing = createDomPing();
39600
39672
  const getMountElement = (element, mountingBehavior = "replace", mountToParent) => {
39601
39673
  const parent = element == null ? void 0 : element.parentElement;
39602
39674
  if (mountingBehavior === "replace") {
@@ -39652,6 +39724,58 @@ and ensure you are accounting for this risk.
39652
39724
  recommendations: {},
39653
39725
  chat: {}
39654
39726
  };
39727
+ const addSearchBoxDomPingIfConfigured = (options, mountOptions) => {
39728
+ var _a;
39729
+ if (!((_a = mountOptions == null ? void 0 : mountOptions.domPing) == null ? void 0 : _a.count)) {
39730
+ return options;
39731
+ }
39732
+ const newOptions = __spreadProps(__spreadValues({}, options), {
39733
+ callbacks: {
39734
+ onMounted: () => {
39735
+ var _a2, _b;
39736
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onMounted) == null ? void 0 : _b.call(_a2);
39737
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39738
+ },
39739
+ onBlurred: () => {
39740
+ var _a2, _b;
39741
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onBlurred) == null ? void 0 : _b.call(_a2);
39742
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39743
+ },
39744
+ onFocused: () => {
39745
+ var _a2, _b;
39746
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onFocused) == null ? void 0 : _b.call(_a2);
39747
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39748
+ },
39749
+ onSearchBoxInput: (...args) => {
39750
+ var _a2, _b;
39751
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onSearchBoxInput) == null ? void 0 : _b.call(_a2, ...args);
39752
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39753
+ }
39754
+ }
39755
+ });
39756
+ return newOptions;
39757
+ };
39758
+ const addSearchResultsDomPingIfConfigured = (options, mountOptions) => {
39759
+ var _a;
39760
+ if (!((_a = mountOptions == null ? void 0 : mountOptions.domPing) == null ? void 0 : _a.count)) {
39761
+ return options;
39762
+ }
39763
+ const newOptions = __spreadProps(__spreadValues({}, options), {
39764
+ callbacks: {
39765
+ onMounted: () => {
39766
+ var _a2, _b;
39767
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onMounted) == null ? void 0 : _b.call(_a2);
39768
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39769
+ },
39770
+ onUrlQueryChange: (...args) => {
39771
+ var _a2, _b;
39772
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onUrlQueryChange) == null ? void 0 : _b.call(_a2, ...args);
39773
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39774
+ }
39775
+ }
39776
+ });
39777
+ return newOptions;
39778
+ };
39655
39779
  const applySearchBox = (options, mountOptions) => {
39656
39780
  const existingInstance = app.box[options.inputSelector];
39657
39781
  if (existingInstance) {
@@ -39681,9 +39805,10 @@ and ensure you are accounting for this risk.
39681
39805
  if (!canMount(mountOptions == null ? void 0 : mountOptions.allowedMountUrls)) {
39682
39806
  return;
39683
39807
  }
39808
+ const transformedOptions = addSearchBoxDomPingIfConfigured(options, mountOptions);
39684
39809
  const inputs = (_a = options.inputSelector) == null ? void 0 : _a.split(",");
39685
39810
  for (const input2 of inputs) {
39686
- applySearchBox(__spreadProps(__spreadValues({}, options), { inputSelector: input2.trim() }), mountOptions);
39811
+ applySearchBox(__spreadProps(__spreadValues({}, transformedOptions), { inputSelector: input2.trim() }), mountOptions);
39687
39812
  }
39688
39813
  };
39689
39814
  const searchResults = (options, mountOptions) => {
@@ -39701,12 +39826,13 @@ and ensure you are accounting for this risk.
39701
39826
  }
39702
39827
  return;
39703
39828
  }
39829
+ const transformedOptions = addSearchResultsDomPingIfConfigured(options, mountOptions);
39704
39830
  const instance = createVue(
39705
39831
  options.containerSelector,
39706
39832
  mountOptions == null ? void 0 : mountOptions.mountingBehavior,
39707
39833
  _sfc_main$3,
39708
39834
  {
39709
- searchResultsOptions: options
39835
+ searchResultsOptions: transformedOptions
39710
39836
  }
39711
39837
  );
39712
39838
  if (!instance) {
@@ -40146,6 +40272,7 @@ and ensure you are accounting for this risk.
40146
40272
  }
40147
40273
  const resolvedConfiguration = JSON.parse(configuration.searchBox);
40148
40274
  const allowedMountUrls = resolvedConfiguration.allowedMountUrls;
40275
+ const domPing = resolvedConfiguration.domPing;
40149
40276
  const visible = yield waitForElementToBeVisible(
40150
40277
  resolvedConfiguration.inputSelector,
40151
40278
  0,
@@ -40161,7 +40288,7 @@ and ensure you are accounting for this risk.
40161
40288
  resolvedConfiguration,
40162
40289
  (_a = optionOverrides == null ? void 0 : optionOverrides.searchBox) != null ? _a : {}
40163
40290
  );
40164
- searchBox(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls });
40291
+ searchBox(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls, domPing });
40165
40292
  });
40166
40293
  const mountSearchResults = (configuration, options, optionOverrides, fetch2 = true, remount = false) => __async(this, null, function* () {
40167
40294
  var _a;
@@ -40170,6 +40297,7 @@ and ensure you are accounting for this risk.
40170
40297
  }
40171
40298
  const resolvedConfiguration = JSON.parse(configuration.searchResults);
40172
40299
  const allowedMountUrls = resolvedConfiguration.allowedMountUrls;
40300
+ const domPing = resolvedConfiguration.domPing;
40173
40301
  const visible = yield waitForElementToBeVisible(
40174
40302
  resolvedConfiguration.containerSelector,
40175
40303
  0,
@@ -40185,7 +40313,7 @@ and ensure you are accounting for this risk.
40185
40313
  resolvedConfiguration,
40186
40314
  (_a = optionOverrides == null ? void 0 : optionOverrides.searchResults) != null ? _a : {}
40187
40315
  );
40188
- searchResults(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls });
40316
+ searchResults(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls, domPing });
40189
40317
  });
40190
40318
  const mountProductList = (configuration, options, optionOverrides, fetch2 = true, remount = false) => __async(this, null, function* () {
40191
40319
  var _a;
@@ -25251,6 +25251,9 @@ const _sfc_main$15 = /* @__PURE__ */ defineComponent({
25251
25251
  }
25252
25252
  emit2("product-click");
25253
25253
  handleRoutingEvent(link, event, boxRoutingBehavior.value === "event");
25254
+ if (props.panelOptions.programmaticNavigation) {
25255
+ window.location.assign(link);
25256
+ }
25254
25257
  };
25255
25258
  return (_ctx, _cache) => {
25256
25259
  return openBlock(), createElementBlock("div", _hoisted_1$Z, [
@@ -25871,6 +25874,7 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
25871
25874
  const suggestedValue = ref(defaultSuggestedValue);
25872
25875
  const opened = ref(props.isSearchContainer);
25873
25876
  const focused = ref(false);
25877
+ const openedAt = ref(null);
25874
25878
  const searchBoxInput = ref(null);
25875
25879
  const { highlightedDocument } = storeToRefs(searchBoxStore);
25876
25880
  const searchValue = computed(() => {
@@ -25907,7 +25911,7 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
25907
25911
  });
25908
25912
  const goToResultsDebounced = debounce$1(paramsStore.goToResults, (_a = props.options.debounce) != null ? _a : 300);
25909
25913
  onMounted(() => {
25910
- var _a2;
25914
+ var _a2, _b, _c;
25911
25915
  window.addEventListener("keydown", handleKeyDown);
25912
25916
  window.addEventListener("click", handleMouseClick);
25913
25917
  paramsStore.setSearchResultsLink(props.options.links.searchResults);
@@ -25918,6 +25922,9 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
25918
25922
  if (props.isSearchContainer && searchBoxInput.value) {
25919
25923
  (_a2 = searchBoxInput.value) == null ? void 0 : _a2.focus();
25920
25924
  }
25925
+ if ((_b = props.options.callbacks) == null ? void 0 : _b.onMounted) {
25926
+ (_c = props.options.callbacks) == null ? void 0 : _c.onMounted();
25927
+ }
25921
25928
  });
25922
25929
  onBeforeUnmount(() => {
25923
25930
  window.removeEventListener("keydown", handleKeyDown);
@@ -25925,11 +25932,14 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
25925
25932
  unbindSearchTriggers(searchTriggers.value, handleCurrentValueSearch);
25926
25933
  });
25927
25934
  const handleMouseClick = (e2) => {
25928
- var _a2, _b;
25935
+ var _a2, _b, _c, _d;
25929
25936
  const el = document.getElementById("lupa-search-box");
25930
25937
  const elementClass = (_b = (_a2 = e2.target) == null ? void 0 : _a2.className) != null ? _b : "";
25931
25938
  const hasLupaClass = typeof elementClass.includes == "function" && elementClass.includes("lupa-search-box");
25932
25939
  const isOutsideElement = el && !el.contains(e2.target) && !hasLupaClass;
25940
+ if (openedAt.value && Date.now() - (openedAt == null ? void 0 : openedAt.value) < 500) {
25941
+ return;
25942
+ }
25933
25943
  if (isOutsideElement && props.options.keepOpen) {
25934
25944
  focused.value = false;
25935
25945
  }
@@ -25938,11 +25948,18 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
25938
25948
  }
25939
25949
  opened.value = false;
25940
25950
  suggestedValue.value = defaultSuggestedValue;
25951
+ if ((_c = props.options.callbacks) == null ? void 0 : _c.onClosed) {
25952
+ (_d = props.options.callbacks) == null ? void 0 : _d.onClosed();
25953
+ }
25941
25954
  };
25942
25955
  const close = () => {
25956
+ var _a2, _b;
25943
25957
  opened.value = false;
25944
25958
  focused.value = false;
25945
25959
  suggestedValue.value = defaultSuggestedValue;
25960
+ if ((_a2 = props.options.callbacks) == null ? void 0 : _a2.onClosed) {
25961
+ (_b = props.options.callbacks) == null ? void 0 : _b.onClosed();
25962
+ }
25946
25963
  };
25947
25964
  const handleKeyDown = (e2) => {
25948
25965
  var _a2, _b;
@@ -25961,15 +25978,22 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
25961
25978
  handleSearch();
25962
25979
  resetValues();
25963
25980
  break;
25981
+ case "Escape":
25982
+ opened.value = false;
25983
+ focused.value = false;
25984
+ break;
25964
25985
  }
25965
25986
  };
25966
25987
  const handleInput = (value) => {
25967
- var _a2;
25988
+ var _a2, _b;
25968
25989
  opened.value = true;
25969
25990
  focused.value = true;
25970
25991
  inputValue.value = (_a2 = value == null ? void 0 : value.replace(/\s+$/, "")) != null ? _a2 : "";
25971
25992
  suggestedValue.value = defaultSuggestedValue;
25972
25993
  searchBoxStore.resetHighlightIndex();
25994
+ if ((_b = props.options.callbacks) == null ? void 0 : _b.onSearchBoxInput) {
25995
+ props.options.callbacks.onSearchBoxInput(value);
25996
+ }
25973
25997
  trackSearchQuery(value);
25974
25998
  if (props.isSearchContainer) {
25975
25999
  goToResultsDebounced({
@@ -26102,6 +26126,13 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
26102
26126
  });
26103
26127
  };
26104
26128
  watch(() => props.options.debounce, handleCurrentValueSearch);
26129
+ watch(opened, () => {
26130
+ if (opened.value) {
26131
+ openedAt.value = Date.now();
26132
+ } else {
26133
+ openedAt.value = null;
26134
+ }
26135
+ });
26105
26136
  const resetValues = () => {
26106
26137
  inputValue.value = "";
26107
26138
  suggestedValue.value = defaultSuggestedValue;
@@ -26113,6 +26144,20 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
26113
26144
  const slotProps = (props2) => {
26114
26145
  return __spreadValues2({}, props2);
26115
26146
  };
26147
+ const onFocus = () => {
26148
+ var _a2, _b;
26149
+ opened.value = true;
26150
+ if ((_a2 = props.options.callbacks) == null ? void 0 : _a2.onFocused) {
26151
+ (_b = props.options.callbacks) == null ? void 0 : _b.onFocused();
26152
+ }
26153
+ };
26154
+ const onBlur = () => {
26155
+ var _a2, _b;
26156
+ focused.value = false;
26157
+ if ((_a2 = props.options.callbacks) == null ? void 0 : _a2.onBlurred) {
26158
+ (_b = props.options.callbacks) == null ? void 0 : _b.onBlurred();
26159
+ }
26160
+ };
26116
26161
  return (_ctx, _cache) => {
26117
26162
  var _a2;
26118
26163
  return openBlock(), createElementBlock("div", _hoisted_1$W, [
@@ -26125,10 +26170,10 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
26125
26170
  ref_key: "searchBoxInput",
26126
26171
  ref: searchBoxInput,
26127
26172
  onInput: handleInput,
26128
- onBlur: _cache[0] || (_cache[0] = ($event) => focused.value = false),
26129
- onFocus: _cache[1] || (_cache[1] = ($event) => opened.value = true),
26173
+ onBlur,
26174
+ onFocus,
26130
26175
  onSearch: handleSearch,
26131
- onClose: _cache[2] || (_cache[2] = ($event) => _ctx.$emit("close"))
26176
+ onClose: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("close"))
26132
26177
  }, null, 8, ["options", "suggestedValue", "can-close", "emit-input-on-focus"]),
26133
26178
  opened.value || _ctx.isSearchContainer ? (openBlock(), createBlock(_sfc_main$11, {
26134
26179
  key: 0,
@@ -39597,6 +39642,33 @@ const attatchShadowDom = ({
39597
39642
  shadow.appendChild(style);
39598
39643
  }
39599
39644
  };
39645
+ const createDomPing = () => {
39646
+ let intervalId = null;
39647
+ let remaining = 0;
39648
+ return (intervalMs = 100, count = 50) => {
39649
+ if (intervalId !== null) {
39650
+ clearInterval(intervalId);
39651
+ }
39652
+ remaining = count;
39653
+ const flush = () => {
39654
+ if (remaining-- <= 0) {
39655
+ if (intervalId !== null) {
39656
+ clearInterval(intervalId);
39657
+ intervalId = null;
39658
+ }
39659
+ return;
39660
+ }
39661
+ const el = document.createElement("div");
39662
+ el.style.cssText = "position:absolute;width:0;height:0;overflow:hidden;pointer-events:none;";
39663
+ el.setAttribute("data-nudge", Date.now().toString());
39664
+ document.body.appendChild(el);
39665
+ document.body.removeChild(el);
39666
+ };
39667
+ flush();
39668
+ intervalId = window.setInterval(flush, intervalMs);
39669
+ };
39670
+ };
39671
+ const startDomPing = createDomPing();
39600
39672
  const getMountElement = (element, mountingBehavior = "replace", mountToParent) => {
39601
39673
  const parent = element == null ? void 0 : element.parentElement;
39602
39674
  if (mountingBehavior === "replace") {
@@ -39652,6 +39724,58 @@ const app = {
39652
39724
  recommendations: {},
39653
39725
  chat: {}
39654
39726
  };
39727
+ const addSearchBoxDomPingIfConfigured = (options, mountOptions) => {
39728
+ var _a;
39729
+ if (!((_a = mountOptions == null ? void 0 : mountOptions.domPing) == null ? void 0 : _a.count)) {
39730
+ return options;
39731
+ }
39732
+ const newOptions = __spreadProps(__spreadValues({}, options), {
39733
+ callbacks: {
39734
+ onMounted: () => {
39735
+ var _a2, _b;
39736
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onMounted) == null ? void 0 : _b.call(_a2);
39737
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39738
+ },
39739
+ onBlurred: () => {
39740
+ var _a2, _b;
39741
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onBlurred) == null ? void 0 : _b.call(_a2);
39742
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39743
+ },
39744
+ onFocused: () => {
39745
+ var _a2, _b;
39746
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onFocused) == null ? void 0 : _b.call(_a2);
39747
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39748
+ },
39749
+ onSearchBoxInput: (...args) => {
39750
+ var _a2, _b;
39751
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onSearchBoxInput) == null ? void 0 : _b.call(_a2, ...args);
39752
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39753
+ }
39754
+ }
39755
+ });
39756
+ return newOptions;
39757
+ };
39758
+ const addSearchResultsDomPingIfConfigured = (options, mountOptions) => {
39759
+ var _a;
39760
+ if (!((_a = mountOptions == null ? void 0 : mountOptions.domPing) == null ? void 0 : _a.count)) {
39761
+ return options;
39762
+ }
39763
+ const newOptions = __spreadProps(__spreadValues({}, options), {
39764
+ callbacks: {
39765
+ onMounted: () => {
39766
+ var _a2, _b;
39767
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onMounted) == null ? void 0 : _b.call(_a2);
39768
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39769
+ },
39770
+ onUrlQueryChange: (...args) => {
39771
+ var _a2, _b;
39772
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onUrlQueryChange) == null ? void 0 : _b.call(_a2, ...args);
39773
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39774
+ }
39775
+ }
39776
+ });
39777
+ return newOptions;
39778
+ };
39655
39779
  const applySearchBox = (options, mountOptions) => {
39656
39780
  const existingInstance = app.box[options.inputSelector];
39657
39781
  if (existingInstance) {
@@ -39681,9 +39805,10 @@ const searchBox = (options, mountOptions) => {
39681
39805
  if (!canMount(mountOptions == null ? void 0 : mountOptions.allowedMountUrls)) {
39682
39806
  return;
39683
39807
  }
39808
+ const transformedOptions = addSearchBoxDomPingIfConfigured(options, mountOptions);
39684
39809
  const inputs = (_a = options.inputSelector) == null ? void 0 : _a.split(",");
39685
39810
  for (const input2 of inputs) {
39686
- applySearchBox(__spreadProps(__spreadValues({}, options), { inputSelector: input2.trim() }), mountOptions);
39811
+ applySearchBox(__spreadProps(__spreadValues({}, transformedOptions), { inputSelector: input2.trim() }), mountOptions);
39687
39812
  }
39688
39813
  };
39689
39814
  const searchResults = (options, mountOptions) => {
@@ -39701,12 +39826,13 @@ const searchResults = (options, mountOptions) => {
39701
39826
  }
39702
39827
  return;
39703
39828
  }
39829
+ const transformedOptions = addSearchResultsDomPingIfConfigured(options, mountOptions);
39704
39830
  const instance = createVue(
39705
39831
  options.containerSelector,
39706
39832
  mountOptions == null ? void 0 : mountOptions.mountingBehavior,
39707
39833
  _sfc_main$3,
39708
39834
  {
39709
- searchResultsOptions: options
39835
+ searchResultsOptions: transformedOptions
39710
39836
  }
39711
39837
  );
39712
39838
  if (!instance) {
@@ -40146,6 +40272,7 @@ const mountSearchBox = (configuration, options, optionOverrides, fetch2 = true,
40146
40272
  }
40147
40273
  const resolvedConfiguration = JSON.parse(configuration.searchBox);
40148
40274
  const allowedMountUrls = resolvedConfiguration.allowedMountUrls;
40275
+ const domPing = resolvedConfiguration.domPing;
40149
40276
  const visible = yield waitForElementToBeVisible(
40150
40277
  resolvedConfiguration.inputSelector,
40151
40278
  0,
@@ -40161,7 +40288,7 @@ const mountSearchBox = (configuration, options, optionOverrides, fetch2 = true,
40161
40288
  resolvedConfiguration,
40162
40289
  (_a = optionOverrides == null ? void 0 : optionOverrides.searchBox) != null ? _a : {}
40163
40290
  );
40164
- searchBox(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls });
40291
+ searchBox(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls, domPing });
40165
40292
  });
40166
40293
  const mountSearchResults = (configuration, options, optionOverrides, fetch2 = true, remount = false) => __async(exports, null, function* () {
40167
40294
  var _a;
@@ -40170,6 +40297,7 @@ const mountSearchResults = (configuration, options, optionOverrides, fetch2 = tr
40170
40297
  }
40171
40298
  const resolvedConfiguration = JSON.parse(configuration.searchResults);
40172
40299
  const allowedMountUrls = resolvedConfiguration.allowedMountUrls;
40300
+ const domPing = resolvedConfiguration.domPing;
40173
40301
  const visible = yield waitForElementToBeVisible(
40174
40302
  resolvedConfiguration.containerSelector,
40175
40303
  0,
@@ -40185,7 +40313,7 @@ const mountSearchResults = (configuration, options, optionOverrides, fetch2 = tr
40185
40313
  resolvedConfiguration,
40186
40314
  (_a = optionOverrides == null ? void 0 : optionOverrides.searchResults) != null ? _a : {}
40187
40315
  );
40188
- searchResults(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls });
40316
+ searchResults(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls, domPing });
40189
40317
  });
40190
40318
  const mountProductList = (configuration, options, optionOverrides, fetch2 = true, remount = false) => __async(exports, null, function* () {
40191
40319
  var _a;
@@ -25249,6 +25249,9 @@ const _sfc_main$15 = /* @__PURE__ */ defineComponent({
25249
25249
  }
25250
25250
  emit2("product-click");
25251
25251
  handleRoutingEvent(link, event, boxRoutingBehavior.value === "event");
25252
+ if (props.panelOptions.programmaticNavigation) {
25253
+ window.location.assign(link);
25254
+ }
25252
25255
  };
25253
25256
  return (_ctx, _cache) => {
25254
25257
  return openBlock(), createElementBlock("div", _hoisted_1$Z, [
@@ -25869,6 +25872,7 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
25869
25872
  const suggestedValue = ref(defaultSuggestedValue);
25870
25873
  const opened = ref(props.isSearchContainer);
25871
25874
  const focused = ref(false);
25875
+ const openedAt = ref(null);
25872
25876
  const searchBoxInput = ref(null);
25873
25877
  const { highlightedDocument } = storeToRefs(searchBoxStore);
25874
25878
  const searchValue = computed(() => {
@@ -25905,7 +25909,7 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
25905
25909
  });
25906
25910
  const goToResultsDebounced = debounce$1(paramsStore.goToResults, (_a = props.options.debounce) != null ? _a : 300);
25907
25911
  onMounted(() => {
25908
- var _a2;
25912
+ var _a2, _b, _c;
25909
25913
  window.addEventListener("keydown", handleKeyDown);
25910
25914
  window.addEventListener("click", handleMouseClick);
25911
25915
  paramsStore.setSearchResultsLink(props.options.links.searchResults);
@@ -25916,6 +25920,9 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
25916
25920
  if (props.isSearchContainer && searchBoxInput.value) {
25917
25921
  (_a2 = searchBoxInput.value) == null ? void 0 : _a2.focus();
25918
25922
  }
25923
+ if ((_b = props.options.callbacks) == null ? void 0 : _b.onMounted) {
25924
+ (_c = props.options.callbacks) == null ? void 0 : _c.onMounted();
25925
+ }
25919
25926
  });
25920
25927
  onBeforeUnmount(() => {
25921
25928
  window.removeEventListener("keydown", handleKeyDown);
@@ -25923,11 +25930,14 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
25923
25930
  unbindSearchTriggers(searchTriggers.value, handleCurrentValueSearch);
25924
25931
  });
25925
25932
  const handleMouseClick = (e2) => {
25926
- var _a2, _b;
25933
+ var _a2, _b, _c, _d;
25927
25934
  const el = document.getElementById("lupa-search-box");
25928
25935
  const elementClass = (_b = (_a2 = e2.target) == null ? void 0 : _a2.className) != null ? _b : "";
25929
25936
  const hasLupaClass = typeof elementClass.includes == "function" && elementClass.includes("lupa-search-box");
25930
25937
  const isOutsideElement = el && !el.contains(e2.target) && !hasLupaClass;
25938
+ if (openedAt.value && Date.now() - (openedAt == null ? void 0 : openedAt.value) < 500) {
25939
+ return;
25940
+ }
25931
25941
  if (isOutsideElement && props.options.keepOpen) {
25932
25942
  focused.value = false;
25933
25943
  }
@@ -25936,11 +25946,18 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
25936
25946
  }
25937
25947
  opened.value = false;
25938
25948
  suggestedValue.value = defaultSuggestedValue;
25949
+ if ((_c = props.options.callbacks) == null ? void 0 : _c.onClosed) {
25950
+ (_d = props.options.callbacks) == null ? void 0 : _d.onClosed();
25951
+ }
25939
25952
  };
25940
25953
  const close = () => {
25954
+ var _a2, _b;
25941
25955
  opened.value = false;
25942
25956
  focused.value = false;
25943
25957
  suggestedValue.value = defaultSuggestedValue;
25958
+ if ((_a2 = props.options.callbacks) == null ? void 0 : _a2.onClosed) {
25959
+ (_b = props.options.callbacks) == null ? void 0 : _b.onClosed();
25960
+ }
25944
25961
  };
25945
25962
  const handleKeyDown = (e2) => {
25946
25963
  var _a2, _b;
@@ -25959,15 +25976,22 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
25959
25976
  handleSearch();
25960
25977
  resetValues();
25961
25978
  break;
25979
+ case "Escape":
25980
+ opened.value = false;
25981
+ focused.value = false;
25982
+ break;
25962
25983
  }
25963
25984
  };
25964
25985
  const handleInput = (value) => {
25965
- var _a2;
25986
+ var _a2, _b;
25966
25987
  opened.value = true;
25967
25988
  focused.value = true;
25968
25989
  inputValue.value = (_a2 = value == null ? void 0 : value.replace(/\s+$/, "")) != null ? _a2 : "";
25969
25990
  suggestedValue.value = defaultSuggestedValue;
25970
25991
  searchBoxStore.resetHighlightIndex();
25992
+ if ((_b = props.options.callbacks) == null ? void 0 : _b.onSearchBoxInput) {
25993
+ props.options.callbacks.onSearchBoxInput(value);
25994
+ }
25971
25995
  trackSearchQuery(value);
25972
25996
  if (props.isSearchContainer) {
25973
25997
  goToResultsDebounced({
@@ -26100,6 +26124,13 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
26100
26124
  });
26101
26125
  };
26102
26126
  watch(() => props.options.debounce, handleCurrentValueSearch);
26127
+ watch(opened, () => {
26128
+ if (opened.value) {
26129
+ openedAt.value = Date.now();
26130
+ } else {
26131
+ openedAt.value = null;
26132
+ }
26133
+ });
26103
26134
  const resetValues = () => {
26104
26135
  inputValue.value = "";
26105
26136
  suggestedValue.value = defaultSuggestedValue;
@@ -26111,6 +26142,20 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
26111
26142
  const slotProps = (props2) => {
26112
26143
  return __spreadValues2({}, props2);
26113
26144
  };
26145
+ const onFocus = () => {
26146
+ var _a2, _b;
26147
+ opened.value = true;
26148
+ if ((_a2 = props.options.callbacks) == null ? void 0 : _a2.onFocused) {
26149
+ (_b = props.options.callbacks) == null ? void 0 : _b.onFocused();
26150
+ }
26151
+ };
26152
+ const onBlur = () => {
26153
+ var _a2, _b;
26154
+ focused.value = false;
26155
+ if ((_a2 = props.options.callbacks) == null ? void 0 : _a2.onBlurred) {
26156
+ (_b = props.options.callbacks) == null ? void 0 : _b.onBlurred();
26157
+ }
26158
+ };
26114
26159
  return (_ctx, _cache) => {
26115
26160
  var _a2;
26116
26161
  return openBlock(), createElementBlock("div", _hoisted_1$W, [
@@ -26123,10 +26168,10 @@ const _sfc_main$10 = /* @__PURE__ */ defineComponent({
26123
26168
  ref_key: "searchBoxInput",
26124
26169
  ref: searchBoxInput,
26125
26170
  onInput: handleInput,
26126
- onBlur: _cache[0] || (_cache[0] = ($event) => focused.value = false),
26127
- onFocus: _cache[1] || (_cache[1] = ($event) => opened.value = true),
26171
+ onBlur,
26172
+ onFocus,
26128
26173
  onSearch: handleSearch,
26129
- onClose: _cache[2] || (_cache[2] = ($event) => _ctx.$emit("close"))
26174
+ onClose: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("close"))
26130
26175
  }, null, 8, ["options", "suggestedValue", "can-close", "emit-input-on-focus"]),
26131
26176
  opened.value || _ctx.isSearchContainer ? (openBlock(), createBlock(_sfc_main$11, {
26132
26177
  key: 0,
@@ -39595,6 +39640,33 @@ const attatchShadowDom = ({
39595
39640
  shadow.appendChild(style);
39596
39641
  }
39597
39642
  };
39643
+ const createDomPing = () => {
39644
+ let intervalId = null;
39645
+ let remaining = 0;
39646
+ return (intervalMs = 100, count = 50) => {
39647
+ if (intervalId !== null) {
39648
+ clearInterval(intervalId);
39649
+ }
39650
+ remaining = count;
39651
+ const flush = () => {
39652
+ if (remaining-- <= 0) {
39653
+ if (intervalId !== null) {
39654
+ clearInterval(intervalId);
39655
+ intervalId = null;
39656
+ }
39657
+ return;
39658
+ }
39659
+ const el = document.createElement("div");
39660
+ el.style.cssText = "position:absolute;width:0;height:0;overflow:hidden;pointer-events:none;";
39661
+ el.setAttribute("data-nudge", Date.now().toString());
39662
+ document.body.appendChild(el);
39663
+ document.body.removeChild(el);
39664
+ };
39665
+ flush();
39666
+ intervalId = window.setInterval(flush, intervalMs);
39667
+ };
39668
+ };
39669
+ const startDomPing = createDomPing();
39598
39670
  const getMountElement = (element, mountingBehavior = "replace", mountToParent) => {
39599
39671
  const parent = element == null ? void 0 : element.parentElement;
39600
39672
  if (mountingBehavior === "replace") {
@@ -39650,6 +39722,58 @@ const app = {
39650
39722
  recommendations: {},
39651
39723
  chat: {}
39652
39724
  };
39725
+ const addSearchBoxDomPingIfConfigured = (options, mountOptions) => {
39726
+ var _a;
39727
+ if (!((_a = mountOptions == null ? void 0 : mountOptions.domPing) == null ? void 0 : _a.count)) {
39728
+ return options;
39729
+ }
39730
+ const newOptions = __spreadProps(__spreadValues({}, options), {
39731
+ callbacks: {
39732
+ onMounted: () => {
39733
+ var _a2, _b;
39734
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onMounted) == null ? void 0 : _b.call(_a2);
39735
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39736
+ },
39737
+ onBlurred: () => {
39738
+ var _a2, _b;
39739
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onBlurred) == null ? void 0 : _b.call(_a2);
39740
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39741
+ },
39742
+ onFocused: () => {
39743
+ var _a2, _b;
39744
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onFocused) == null ? void 0 : _b.call(_a2);
39745
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39746
+ },
39747
+ onSearchBoxInput: (...args) => {
39748
+ var _a2, _b;
39749
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onSearchBoxInput) == null ? void 0 : _b.call(_a2, ...args);
39750
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39751
+ }
39752
+ }
39753
+ });
39754
+ return newOptions;
39755
+ };
39756
+ const addSearchResultsDomPingIfConfigured = (options, mountOptions) => {
39757
+ var _a;
39758
+ if (!((_a = mountOptions == null ? void 0 : mountOptions.domPing) == null ? void 0 : _a.count)) {
39759
+ return options;
39760
+ }
39761
+ const newOptions = __spreadProps(__spreadValues({}, options), {
39762
+ callbacks: {
39763
+ onMounted: () => {
39764
+ var _a2, _b;
39765
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onMounted) == null ? void 0 : _b.call(_a2);
39766
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39767
+ },
39768
+ onUrlQueryChange: (...args) => {
39769
+ var _a2, _b;
39770
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onUrlQueryChange) == null ? void 0 : _b.call(_a2, ...args);
39771
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39772
+ }
39773
+ }
39774
+ });
39775
+ return newOptions;
39776
+ };
39653
39777
  const applySearchBox = (options, mountOptions) => {
39654
39778
  const existingInstance = app.box[options.inputSelector];
39655
39779
  if (existingInstance) {
@@ -39679,9 +39803,10 @@ const searchBox = (options, mountOptions) => {
39679
39803
  if (!canMount(mountOptions == null ? void 0 : mountOptions.allowedMountUrls)) {
39680
39804
  return;
39681
39805
  }
39806
+ const transformedOptions = addSearchBoxDomPingIfConfigured(options, mountOptions);
39682
39807
  const inputs = (_a = options.inputSelector) == null ? void 0 : _a.split(",");
39683
39808
  for (const input2 of inputs) {
39684
- applySearchBox(__spreadProps(__spreadValues({}, options), { inputSelector: input2.trim() }), mountOptions);
39809
+ applySearchBox(__spreadProps(__spreadValues({}, transformedOptions), { inputSelector: input2.trim() }), mountOptions);
39685
39810
  }
39686
39811
  };
39687
39812
  const searchResults = (options, mountOptions) => {
@@ -39699,12 +39824,13 @@ const searchResults = (options, mountOptions) => {
39699
39824
  }
39700
39825
  return;
39701
39826
  }
39827
+ const transformedOptions = addSearchResultsDomPingIfConfigured(options, mountOptions);
39702
39828
  const instance = createVue(
39703
39829
  options.containerSelector,
39704
39830
  mountOptions == null ? void 0 : mountOptions.mountingBehavior,
39705
39831
  _sfc_main$3,
39706
39832
  {
39707
- searchResultsOptions: options
39833
+ searchResultsOptions: transformedOptions
39708
39834
  }
39709
39835
  );
39710
39836
  if (!instance) {
@@ -40144,6 +40270,7 @@ const mountSearchBox = (configuration, options, optionOverrides, fetch2 = true,
40144
40270
  }
40145
40271
  const resolvedConfiguration = JSON.parse(configuration.searchBox);
40146
40272
  const allowedMountUrls = resolvedConfiguration.allowedMountUrls;
40273
+ const domPing = resolvedConfiguration.domPing;
40147
40274
  const visible = yield waitForElementToBeVisible(
40148
40275
  resolvedConfiguration.inputSelector,
40149
40276
  0,
@@ -40159,7 +40286,7 @@ const mountSearchBox = (configuration, options, optionOverrides, fetch2 = true,
40159
40286
  resolvedConfiguration,
40160
40287
  (_a = optionOverrides == null ? void 0 : optionOverrides.searchBox) != null ? _a : {}
40161
40288
  );
40162
- searchBox(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls });
40289
+ searchBox(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls, domPing });
40163
40290
  });
40164
40291
  const mountSearchResults = (configuration, options, optionOverrides, fetch2 = true, remount = false) => __async(void 0, null, function* () {
40165
40292
  var _a;
@@ -40168,6 +40295,7 @@ const mountSearchResults = (configuration, options, optionOverrides, fetch2 = tr
40168
40295
  }
40169
40296
  const resolvedConfiguration = JSON.parse(configuration.searchResults);
40170
40297
  const allowedMountUrls = resolvedConfiguration.allowedMountUrls;
40298
+ const domPing = resolvedConfiguration.domPing;
40171
40299
  const visible = yield waitForElementToBeVisible(
40172
40300
  resolvedConfiguration.containerSelector,
40173
40301
  0,
@@ -40183,7 +40311,7 @@ const mountSearchResults = (configuration, options, optionOverrides, fetch2 = tr
40183
40311
  resolvedConfiguration,
40184
40312
  (_a = optionOverrides == null ? void 0 : optionOverrides.searchResults) != null ? _a : {}
40185
40313
  );
40186
- searchResults(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls });
40314
+ searchResults(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls, domPing });
40187
40315
  });
40188
40316
  const mountProductList = (configuration, options, optionOverrides, fetch2 = true, remount = false) => __async(void 0, null, function* () {
40189
40317
  var _a;
@@ -25253,6 +25253,9 @@ and ensure you are accounting for this risk.
25253
25253
  }
25254
25254
  emit2("product-click");
25255
25255
  handleRoutingEvent(link, event, boxRoutingBehavior.value === "event");
25256
+ if (props.panelOptions.programmaticNavigation) {
25257
+ window.location.assign(link);
25258
+ }
25256
25259
  };
25257
25260
  return (_ctx, _cache) => {
25258
25261
  return openBlock(), createElementBlock("div", _hoisted_1$Z, [
@@ -25873,6 +25876,7 @@ and ensure you are accounting for this risk.
25873
25876
  const suggestedValue = ref(defaultSuggestedValue);
25874
25877
  const opened = ref(props.isSearchContainer);
25875
25878
  const focused = ref(false);
25879
+ const openedAt = ref(null);
25876
25880
  const searchBoxInput = ref(null);
25877
25881
  const { highlightedDocument } = storeToRefs(searchBoxStore);
25878
25882
  const searchValue = computed(() => {
@@ -25909,7 +25913,7 @@ and ensure you are accounting for this risk.
25909
25913
  });
25910
25914
  const goToResultsDebounced = debounce$1(paramsStore.goToResults, (_a = props.options.debounce) != null ? _a : 300);
25911
25915
  onMounted(() => {
25912
- var _a2;
25916
+ var _a2, _b, _c;
25913
25917
  window.addEventListener("keydown", handleKeyDown);
25914
25918
  window.addEventListener("click", handleMouseClick);
25915
25919
  paramsStore.setSearchResultsLink(props.options.links.searchResults);
@@ -25920,6 +25924,9 @@ and ensure you are accounting for this risk.
25920
25924
  if (props.isSearchContainer && searchBoxInput.value) {
25921
25925
  (_a2 = searchBoxInput.value) == null ? void 0 : _a2.focus();
25922
25926
  }
25927
+ if ((_b = props.options.callbacks) == null ? void 0 : _b.onMounted) {
25928
+ (_c = props.options.callbacks) == null ? void 0 : _c.onMounted();
25929
+ }
25923
25930
  });
25924
25931
  onBeforeUnmount(() => {
25925
25932
  window.removeEventListener("keydown", handleKeyDown);
@@ -25927,11 +25934,14 @@ and ensure you are accounting for this risk.
25927
25934
  unbindSearchTriggers(searchTriggers.value, handleCurrentValueSearch);
25928
25935
  });
25929
25936
  const handleMouseClick = (e2) => {
25930
- var _a2, _b;
25937
+ var _a2, _b, _c, _d;
25931
25938
  const el = document.getElementById("lupa-search-box");
25932
25939
  const elementClass = (_b = (_a2 = e2.target) == null ? void 0 : _a2.className) != null ? _b : "";
25933
25940
  const hasLupaClass = typeof elementClass.includes == "function" && elementClass.includes("lupa-search-box");
25934
25941
  const isOutsideElement = el && !el.contains(e2.target) && !hasLupaClass;
25942
+ if (openedAt.value && Date.now() - (openedAt == null ? void 0 : openedAt.value) < 500) {
25943
+ return;
25944
+ }
25935
25945
  if (isOutsideElement && props.options.keepOpen) {
25936
25946
  focused.value = false;
25937
25947
  }
@@ -25940,11 +25950,18 @@ and ensure you are accounting for this risk.
25940
25950
  }
25941
25951
  opened.value = false;
25942
25952
  suggestedValue.value = defaultSuggestedValue;
25953
+ if ((_c = props.options.callbacks) == null ? void 0 : _c.onClosed) {
25954
+ (_d = props.options.callbacks) == null ? void 0 : _d.onClosed();
25955
+ }
25943
25956
  };
25944
25957
  const close = () => {
25958
+ var _a2, _b;
25945
25959
  opened.value = false;
25946
25960
  focused.value = false;
25947
25961
  suggestedValue.value = defaultSuggestedValue;
25962
+ if ((_a2 = props.options.callbacks) == null ? void 0 : _a2.onClosed) {
25963
+ (_b = props.options.callbacks) == null ? void 0 : _b.onClosed();
25964
+ }
25948
25965
  };
25949
25966
  const handleKeyDown = (e2) => {
25950
25967
  var _a2, _b;
@@ -25963,15 +25980,22 @@ and ensure you are accounting for this risk.
25963
25980
  handleSearch();
25964
25981
  resetValues();
25965
25982
  break;
25983
+ case "Escape":
25984
+ opened.value = false;
25985
+ focused.value = false;
25986
+ break;
25966
25987
  }
25967
25988
  };
25968
25989
  const handleInput = (value) => {
25969
- var _a2;
25990
+ var _a2, _b;
25970
25991
  opened.value = true;
25971
25992
  focused.value = true;
25972
25993
  inputValue.value = (_a2 = value == null ? void 0 : value.replace(/\s+$/, "")) != null ? _a2 : "";
25973
25994
  suggestedValue.value = defaultSuggestedValue;
25974
25995
  searchBoxStore.resetHighlightIndex();
25996
+ if ((_b = props.options.callbacks) == null ? void 0 : _b.onSearchBoxInput) {
25997
+ props.options.callbacks.onSearchBoxInput(value);
25998
+ }
25975
25999
  trackSearchQuery(value);
25976
26000
  if (props.isSearchContainer) {
25977
26001
  goToResultsDebounced({
@@ -26104,6 +26128,13 @@ and ensure you are accounting for this risk.
26104
26128
  });
26105
26129
  };
26106
26130
  watch(() => props.options.debounce, handleCurrentValueSearch);
26131
+ watch(opened, () => {
26132
+ if (opened.value) {
26133
+ openedAt.value = Date.now();
26134
+ } else {
26135
+ openedAt.value = null;
26136
+ }
26137
+ });
26107
26138
  const resetValues = () => {
26108
26139
  inputValue.value = "";
26109
26140
  suggestedValue.value = defaultSuggestedValue;
@@ -26115,6 +26146,20 @@ and ensure you are accounting for this risk.
26115
26146
  const slotProps = (props2) => {
26116
26147
  return __spreadValues2({}, props2);
26117
26148
  };
26149
+ const onFocus = () => {
26150
+ var _a2, _b;
26151
+ opened.value = true;
26152
+ if ((_a2 = props.options.callbacks) == null ? void 0 : _a2.onFocused) {
26153
+ (_b = props.options.callbacks) == null ? void 0 : _b.onFocused();
26154
+ }
26155
+ };
26156
+ const onBlur = () => {
26157
+ var _a2, _b;
26158
+ focused.value = false;
26159
+ if ((_a2 = props.options.callbacks) == null ? void 0 : _a2.onBlurred) {
26160
+ (_b = props.options.callbacks) == null ? void 0 : _b.onBlurred();
26161
+ }
26162
+ };
26118
26163
  return (_ctx, _cache) => {
26119
26164
  var _a2;
26120
26165
  return openBlock(), createElementBlock("div", _hoisted_1$W, [
@@ -26127,10 +26172,10 @@ and ensure you are accounting for this risk.
26127
26172
  ref_key: "searchBoxInput",
26128
26173
  ref: searchBoxInput,
26129
26174
  onInput: handleInput,
26130
- onBlur: _cache[0] || (_cache[0] = ($event) => focused.value = false),
26131
- onFocus: _cache[1] || (_cache[1] = ($event) => opened.value = true),
26175
+ onBlur,
26176
+ onFocus,
26132
26177
  onSearch: handleSearch,
26133
- onClose: _cache[2] || (_cache[2] = ($event) => _ctx.$emit("close"))
26178
+ onClose: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("close"))
26134
26179
  }, null, 8, ["options", "suggestedValue", "can-close", "emit-input-on-focus"]),
26135
26180
  opened.value || _ctx.isSearchContainer ? (openBlock(), createBlock(_sfc_main$11, {
26136
26181
  key: 0,
@@ -39599,6 +39644,33 @@ and ensure you are accounting for this risk.
39599
39644
  shadow.appendChild(style);
39600
39645
  }
39601
39646
  };
39647
+ const createDomPing = () => {
39648
+ let intervalId = null;
39649
+ let remaining = 0;
39650
+ return (intervalMs = 100, count = 50) => {
39651
+ if (intervalId !== null) {
39652
+ clearInterval(intervalId);
39653
+ }
39654
+ remaining = count;
39655
+ const flush = () => {
39656
+ if (remaining-- <= 0) {
39657
+ if (intervalId !== null) {
39658
+ clearInterval(intervalId);
39659
+ intervalId = null;
39660
+ }
39661
+ return;
39662
+ }
39663
+ const el = document.createElement("div");
39664
+ el.style.cssText = "position:absolute;width:0;height:0;overflow:hidden;pointer-events:none;";
39665
+ el.setAttribute("data-nudge", Date.now().toString());
39666
+ document.body.appendChild(el);
39667
+ document.body.removeChild(el);
39668
+ };
39669
+ flush();
39670
+ intervalId = window.setInterval(flush, intervalMs);
39671
+ };
39672
+ };
39673
+ const startDomPing = createDomPing();
39602
39674
  const getMountElement = (element, mountingBehavior = "replace", mountToParent) => {
39603
39675
  const parent = element == null ? void 0 : element.parentElement;
39604
39676
  if (mountingBehavior === "replace") {
@@ -39654,6 +39726,58 @@ and ensure you are accounting for this risk.
39654
39726
  recommendations: {},
39655
39727
  chat: {}
39656
39728
  };
39729
+ const addSearchBoxDomPingIfConfigured = (options, mountOptions) => {
39730
+ var _a;
39731
+ if (!((_a = mountOptions == null ? void 0 : mountOptions.domPing) == null ? void 0 : _a.count)) {
39732
+ return options;
39733
+ }
39734
+ const newOptions = __spreadProps(__spreadValues({}, options), {
39735
+ callbacks: {
39736
+ onMounted: () => {
39737
+ var _a2, _b;
39738
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onMounted) == null ? void 0 : _b.call(_a2);
39739
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39740
+ },
39741
+ onBlurred: () => {
39742
+ var _a2, _b;
39743
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onBlurred) == null ? void 0 : _b.call(_a2);
39744
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39745
+ },
39746
+ onFocused: () => {
39747
+ var _a2, _b;
39748
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onFocused) == null ? void 0 : _b.call(_a2);
39749
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39750
+ },
39751
+ onSearchBoxInput: (...args) => {
39752
+ var _a2, _b;
39753
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onSearchBoxInput) == null ? void 0 : _b.call(_a2, ...args);
39754
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39755
+ }
39756
+ }
39757
+ });
39758
+ return newOptions;
39759
+ };
39760
+ const addSearchResultsDomPingIfConfigured = (options, mountOptions) => {
39761
+ var _a;
39762
+ if (!((_a = mountOptions == null ? void 0 : mountOptions.domPing) == null ? void 0 : _a.count)) {
39763
+ return options;
39764
+ }
39765
+ const newOptions = __spreadProps(__spreadValues({}, options), {
39766
+ callbacks: {
39767
+ onMounted: () => {
39768
+ var _a2, _b;
39769
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onMounted) == null ? void 0 : _b.call(_a2);
39770
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39771
+ },
39772
+ onUrlQueryChange: (...args) => {
39773
+ var _a2, _b;
39774
+ (_b = (_a2 = options.callbacks) == null ? void 0 : _a2.onUrlQueryChange) == null ? void 0 : _b.call(_a2, ...args);
39775
+ startDomPing(mountOptions.domPing.intervalMs, mountOptions.domPing.count);
39776
+ }
39777
+ }
39778
+ });
39779
+ return newOptions;
39780
+ };
39657
39781
  const applySearchBox = (options, mountOptions) => {
39658
39782
  const existingInstance = app.box[options.inputSelector];
39659
39783
  if (existingInstance) {
@@ -39683,9 +39807,10 @@ and ensure you are accounting for this risk.
39683
39807
  if (!canMount(mountOptions == null ? void 0 : mountOptions.allowedMountUrls)) {
39684
39808
  return;
39685
39809
  }
39810
+ const transformedOptions = addSearchBoxDomPingIfConfigured(options, mountOptions);
39686
39811
  const inputs = (_a = options.inputSelector) == null ? void 0 : _a.split(",");
39687
39812
  for (const input2 of inputs) {
39688
- applySearchBox(__spreadProps(__spreadValues({}, options), { inputSelector: input2.trim() }), mountOptions);
39813
+ applySearchBox(__spreadProps(__spreadValues({}, transformedOptions), { inputSelector: input2.trim() }), mountOptions);
39689
39814
  }
39690
39815
  };
39691
39816
  const searchResults = (options, mountOptions) => {
@@ -39703,12 +39828,13 @@ and ensure you are accounting for this risk.
39703
39828
  }
39704
39829
  return;
39705
39830
  }
39831
+ const transformedOptions = addSearchResultsDomPingIfConfigured(options, mountOptions);
39706
39832
  const instance = createVue(
39707
39833
  options.containerSelector,
39708
39834
  mountOptions == null ? void 0 : mountOptions.mountingBehavior,
39709
39835
  _sfc_main$3,
39710
39836
  {
39711
- searchResultsOptions: options
39837
+ searchResultsOptions: transformedOptions
39712
39838
  }
39713
39839
  );
39714
39840
  if (!instance) {
@@ -40148,6 +40274,7 @@ and ensure you are accounting for this risk.
40148
40274
  }
40149
40275
  const resolvedConfiguration = JSON.parse(configuration.searchBox);
40150
40276
  const allowedMountUrls = resolvedConfiguration.allowedMountUrls;
40277
+ const domPing = resolvedConfiguration.domPing;
40151
40278
  const visible = yield waitForElementToBeVisible(
40152
40279
  resolvedConfiguration.inputSelector,
40153
40280
  0,
@@ -40163,7 +40290,7 @@ and ensure you are accounting for this risk.
40163
40290
  resolvedConfiguration,
40164
40291
  (_a = optionOverrides == null ? void 0 : optionOverrides.searchBox) != null ? _a : {}
40165
40292
  );
40166
- searchBox(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls });
40293
+ searchBox(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls, domPing });
40167
40294
  });
40168
40295
  const mountSearchResults = (configuration, options, optionOverrides, fetch2 = true, remount = false) => __async(this, null, function* () {
40169
40296
  var _a;
@@ -40172,6 +40299,7 @@ and ensure you are accounting for this risk.
40172
40299
  }
40173
40300
  const resolvedConfiguration = JSON.parse(configuration.searchResults);
40174
40301
  const allowedMountUrls = resolvedConfiguration.allowedMountUrls;
40302
+ const domPing = resolvedConfiguration.domPing;
40175
40303
  const visible = yield waitForElementToBeVisible(
40176
40304
  resolvedConfiguration.containerSelector,
40177
40305
  0,
@@ -40187,7 +40315,7 @@ and ensure you are accounting for this risk.
40187
40315
  resolvedConfiguration,
40188
40316
  (_a = optionOverrides == null ? void 0 : optionOverrides.searchResults) != null ? _a : {}
40189
40317
  );
40190
- searchResults(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls });
40318
+ searchResults(__spreadProps(__spreadValues({}, mergedOptions), { options }), { fetch: fetch2, allowedMountUrls, domPing });
40191
40319
  });
40192
40320
  const mountProductList = (configuration, options, optionOverrides, fetch2 = true, remount = false) => __async(this, null, function* () {
40193
40321
  var _a;
@@ -12,27 +12,47 @@ declare const lupaSearch: {
12
12
  fetch?: boolean;
13
13
  mountingBehavior?: "replace" | "append" | "prepend";
14
14
  allowedMountUrls?: string[];
15
+ domPing?: {
16
+ intervalMs?: number;
17
+ count?: number;
18
+ };
15
19
  }) => void;
16
20
  searchResults: (options: SearchResultsOptions, mountOptions?: {
17
21
  fetch?: boolean;
18
22
  mountingBehavior?: "replace" | "append" | "prepend";
19
23
  allowedMountUrls?: string[];
24
+ domPing?: {
25
+ intervalMs?: number;
26
+ count?: number;
27
+ };
20
28
  }) => void;
21
29
  tracking: (options: TrackingOptions) => void;
22
30
  productList: (options: ProductListOptions, mountOptions?: {
23
31
  fetch?: boolean;
24
32
  mountingBehavior?: "replace" | "append" | "prepend";
25
33
  allowedMountUrls?: string[];
34
+ domPing?: {
35
+ intervalMs?: number;
36
+ count?: number;
37
+ };
26
38
  }) => void;
27
39
  searchContainer: (options: SearchContainerOptions, mountOptions?: {
28
40
  fetch?: boolean;
29
41
  mountingBehavior?: "replace" | "append" | "prepend";
30
42
  allowedMountUrls?: string[];
43
+ domPing?: {
44
+ intervalMs?: number;
45
+ count?: number;
46
+ };
31
47
  }) => void;
32
48
  recommendations: (options: ProductRecommendationOptions, mountOptions?: {
33
49
  fetch?: boolean;
34
50
  mountingBehavior?: "replace" | "append" | "prepend";
35
51
  allowedMountUrls?: string[];
52
+ domPing?: {
53
+ intervalMs?: number;
54
+ count?: number;
55
+ };
36
56
  }) => void;
37
57
  clearSearchBox: (selector?: string) => void;
38
58
  clearSearchResults: (selector?: string) => void;
@@ -43,12 +63,20 @@ declare const lupaSearch: {
43
63
  fetch?: boolean;
44
64
  mountingBehavior?: "replace" | "append" | "prepend";
45
65
  allowedMountUrls?: string[];
66
+ domPing?: {
67
+ intervalMs?: number;
68
+ count?: number;
69
+ };
46
70
  }) => void;
47
71
  clearChat: (selector?: string) => void;
48
72
  preconfiguredSearchContainer: (preconfiguredSearchContainerOptions: PreconfiguredSearchContainerOptions, mountOptions?: {
49
73
  fetch?: boolean;
50
74
  mountingBehavior?: "replace" | "append" | "prepend";
51
75
  allowedMountUrls?: string[];
76
+ domPing?: {
77
+ intervalMs?: number;
78
+ count?: number;
79
+ };
52
80
  }) => void;
53
81
  getSearchBoxComponent: ({ searchBoxOptions, labels, panelOptions, redirections, placeholderImage }: PreconfiguredSearchContainerOptions) => SearchBoxOptions;
54
82
  getSearchResultsComponent: ({ searchResultOptions, labels, redirections, placeholderImage, configuratorOverrides, callbacks, additionalFields }: PreconfiguredSearchContainerOptions) => SearchResultsOptions;
@@ -24,6 +24,10 @@ declare const _default: {
24
24
  keepOpen?: boolean;
25
25
  } & {
26
26
  allowedMountUrls?: string[];
27
+ domPing?: {
28
+ intervalMs?: number;
29
+ count?: number;
30
+ };
27
31
  } & {
28
32
  minInputLength?: number;
29
33
  labels?: import("@getlupa/vue/dist/src/types/search-box/SearchBoxOptions").SearchBoxOptionLabels;
@@ -82,6 +86,10 @@ declare const _default: {
82
86
  initialFilters?: import("@getlupa/client-sdk/Types").FilterGroup | Record<string, import("@getlupa/vue/dist/src/types/DataExtraction").DataExtraction>;
83
87
  } & {
84
88
  allowedMountUrls?: string[];
89
+ domPing?: {
90
+ intervalMs?: number;
91
+ count?: number;
92
+ };
85
93
  } & Partial<SearchResultsOptions>;
86
94
  };
87
95
  export default _default;
@@ -5,6 +5,10 @@ type MountOptions = {
5
5
  fetch?: boolean;
6
6
  mountingBehavior?: 'replace' | 'append' | 'prepend';
7
7
  allowedMountUrls?: string[];
8
+ domPing?: {
9
+ intervalMs?: number;
10
+ count?: number;
11
+ };
8
12
  };
9
13
  export declare const applySearchBox: (options: SearchBoxOptions, mountOptions?: MountOptions) => void;
10
14
  export declare const searchBox: (options: SearchBoxOptions, mountOptions?: MountOptions) => void;
@@ -1,9 +1,17 @@
1
1
  import { ProductListOptions, ProductRecommendationOptions, SearchBoxOptions, SearchResultsOptions } from '@getlupa/vue';
2
2
  export type ResolvedSearchBoxOptions = SearchBoxOptions & {
3
3
  allowedMountUrls?: string[];
4
+ domPing?: {
5
+ intervalMs?: number;
6
+ count?: number;
7
+ };
4
8
  };
5
9
  export type ResolvedSearchResultOptions = SearchResultsOptions & {
6
10
  allowedMountUrls?: string[];
11
+ domPing?: {
12
+ intervalMs?: number;
13
+ count?: number;
14
+ };
7
15
  };
8
16
  export type ResolvedProductListOptions = ProductListOptions & {
9
17
  allowedMountUrls?: string[];
@@ -1,4 +1,6 @@
1
1
  import { type Component } from 'vue';
2
+ export declare const createDomPing: () => (intervalMs?: number, count?: number) => void;
3
+ export declare const startDomPing: (intervalMs?: number, count?: number) => void;
2
4
  export declare const createVue: (selector: string | Element, mountingBehavior: string, rootComponent: Component, options: Record<string, unknown>, mountToParent?: boolean) => {
3
5
  mountedApp: import("vue").ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, import("vue").ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}, {}, string, {}>, {}, {}>;
4
6
  mountedComponent: any;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getlupa/client",
3
- "version": "1.17.1",
3
+ "version": "1.17.4",
4
4
  "main": "dist/lupaSearch.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/src/index.d.ts",
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "devDependencies": {
22
22
  "@getlupa/client-sdk": "^1.3.4",
23
- "@getlupa/vue": "0.17.1",
23
+ "@getlupa/vue": "0.17.4",
24
24
  "@rushstack/eslint-patch": "^1.3.2",
25
25
  "@tsconfig/node18": "^2.0.1",
26
26
  "@types/jsdom": "^21.1.1",