@seekora-ai/ui-sdk-core 0.2.13 → 0.2.15

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/dist/index.js CHANGED
@@ -1404,6 +1404,9 @@ class SearchStateManager {
1404
1404
  this.autoSearch = config.autoSearch !== false;
1405
1405
  this.debounceMs = config.debounceMs || 300;
1406
1406
  this.defaultSearchOptions = config.defaultSearchOptions || { widget_mode: true };
1407
+ this.keepResultsOnClear = config.keepResultsOnClear !== false;
1408
+ this.abTestId = config.abTestId;
1409
+ this.abVariant = config.abVariant;
1407
1410
  this.state = {
1408
1411
  query: config.initialQuery || '',
1409
1412
  refinements: [],
@@ -1452,6 +1455,15 @@ class SearchStateManager {
1452
1455
  }
1453
1456
  return;
1454
1457
  }
1458
+ // When query is cleared to empty and keepResultsOnClear is true,
1459
+ // preserve previous results and skip triggering a search
1460
+ if (query === '' && this.keepResultsOnClear) {
1461
+ log.verbose('SearchStateManager: Query cleared, keeping previous results');
1462
+ this.state.query = '';
1463
+ this.state.currentPage = 1;
1464
+ this.notifyListeners();
1465
+ return;
1466
+ }
1455
1467
  this.state.query = query;
1456
1468
  this.state.currentPage = 1; // Reset to first page on new query
1457
1469
  log.verbose('SearchStateManager: Query updated', { query, triggerSearch, autoSearch: this.autoSearch });
@@ -1650,6 +1662,23 @@ class SearchStateManager {
1650
1662
  }
1651
1663
  });
1652
1664
  }
1665
+ /** Explicitly clear results (bypasses keepResultsOnClear) */
1666
+ clearResults() {
1667
+ this.setState({ results: null, loading: false, error: null });
1668
+ log.verbose('SearchStateManager: Results explicitly cleared');
1669
+ }
1670
+ // A/B test getters
1671
+ getAbTestId() {
1672
+ return this.abTestId;
1673
+ }
1674
+ getAbVariant() {
1675
+ return this.abVariant;
1676
+ }
1677
+ setAbTest(abTestId, abVariant) {
1678
+ this.abTestId = abTestId;
1679
+ this.abVariant = abVariant;
1680
+ log.verbose('SearchStateManager: A/B test updated', { abTestId, abVariant });
1681
+ }
1653
1682
  // Clear all state
1654
1683
  clear() {
1655
1684
  this.state = {
@@ -2629,6 +2658,57 @@ async function getFingerprint(config) {
2629
2658
  return fingerprint.get();
2630
2659
  }
2631
2660
 
2661
+ /**
2662
+ * Analytics beacon utility
2663
+ *
2664
+ * Uses navigator.sendBeacon() for reliable event delivery during page navigation,
2665
+ * with fetch() as the primary method for normal operation.
2666
+ */
2667
+ /**
2668
+ * Send an analytics event using sendBeacon (for page unload scenarios)
2669
+ * or fetch (for normal operation). Returns true if the event was queued.
2670
+ */
2671
+ function sendAnalyticsBeacon(url, payload) {
2672
+ const body = JSON.stringify(payload);
2673
+ // Try sendBeacon first (works during page unload)
2674
+ if (typeof navigator !== 'undefined' && navigator.sendBeacon) {
2675
+ const blob = new Blob([body], { type: 'application/json' });
2676
+ return navigator.sendBeacon(url, blob);
2677
+ }
2678
+ // Fallback to fetch with keepalive
2679
+ if (typeof fetch !== 'undefined') {
2680
+ fetch(url, {
2681
+ method: 'POST',
2682
+ headers: { 'Content-Type': 'application/json' },
2683
+ body,
2684
+ keepalive: true,
2685
+ }).catch(() => {
2686
+ // Silently fail — beacon is best-effort
2687
+ });
2688
+ return true;
2689
+ }
2690
+ return false;
2691
+ }
2692
+ /**
2693
+ * Send an analytics event via fetch (normal operation).
2694
+ * Returns the fetch promise for awaiting if needed.
2695
+ */
2696
+ async function sendAnalyticsEvent(url, payload) {
2697
+ if (typeof fetch === 'undefined')
2698
+ return false;
2699
+ try {
2700
+ const response = await fetch(url, {
2701
+ method: 'POST',
2702
+ headers: { 'Content-Type': 'application/json' },
2703
+ body: JSON.stringify(payload),
2704
+ });
2705
+ return response.ok;
2706
+ }
2707
+ catch {
2708
+ return false;
2709
+ }
2710
+ }
2711
+
2632
2712
  exports.Fingerprint = Fingerprint;
2633
2713
  exports.SearchStateManager = SearchStateManager;
2634
2714
  exports.URLRouter = URLRouter;
@@ -2667,6 +2747,8 @@ exports.parseHighlightedParts = parseHighlightedParts;
2667
2747
  exports.parseQueryHighlightParts = parseQueryHighlightParts;
2668
2748
  exports.prefersHighContrast = prefersHighContrast;
2669
2749
  exports.prefersReducedMotion = prefersReducedMotion;
2750
+ exports.sendAnalyticsBeacon = sendAnalyticsBeacon;
2751
+ exports.sendAnalyticsEvent = sendAnalyticsEvent;
2670
2752
  exports.setAriaDescribedBy = setAriaDescribedBy;
2671
2753
  exports.setDefaultLogger = setDefaultLogger;
2672
2754
  exports.setLogLevel = setLogLevel;