PageSourceSearch

https://jagrutiseva.org/js/storefront-layout-components.js

js jagrutiseva.org collected 2026-10-09 03:21:00 UTC 407,444 bytes, 7,122 lines download raw bytes

1(function () {
2if (typeof window.SwymStorefrontLayoutAPI === 'undefined') {
3  window.SwymStorefrontLayoutAPI = {};
4}
5if (typeof window.SwymStorefrontLayoutContext === 'undefined') {
6  window.SwymStorefrontLayoutContext = {};
7}
8if(typeof window.SwymStorefrontLayoutExtensions === 'undefined'){
9  window.SwymStorefrontLayoutExtensions = {};
10}
11var SWYM_SHOP_API_KEY = 'd612f58ce0decfaba38849af3396fb5b';
12function swymEscAttr(str) {
13  if (!str) return '';
14  return String(str)
15    .replace(/&/g, '&')
16    .replace(/"/g, '"')
17    .replace(/</g, '&lt;')
18    .replace(/>/g, '&gt;')
19    .replace(/'/g, '&#39;');
20}
21
22function isShopifyStoreRTLEnabled() {
23  // Check dir attributes
24  const htmlDir = document.documentElement.getAttribute('dir');
25  const bodyDir = document.body.getAttribute('dir');
26
27  // Check computed CSS direction
28  const htmlCSSDir = getComputedStyle(document.documentElement).direction;
29  const bodyCSSDir = getComputedStyle(document.body).direction;
30
31  // Optional: check for common theme class
32  const hasRTLClass = document.documentElement.classList.contains('rtl') || 
33                      document.body.classList.contains('rtl') ||
34                      document.querySelector('.rtl, .is-rtl') !== null;
35
36  return (
37    htmlDir === 'rtl' ||
38    bodyDir === 'rtl' ||
39    htmlCSSDir === 'rtl' ||
40    bodyCSSDir === 'rtl' ||
41    hasRTLClass
42  );
43}
44
45const isRTL = isShopifyStoreRTLEnabled();
46if (isRTL) {
47  document.body.classList.add('swym-ccui-rtl');
48}
49
50SwymStorefrontLayoutContext.ActionTypes = {
51  ManageListItem: 'ManageListItem',
52  ManageSflListItem: 'ManageSflListItem',
53  ManageSfyListItem: 'ManageSfyListItem',
54  AddToCollection: 'AddToCollection',
55  CreateCollection: 'CreateCollection',
56  EditCollection: 'EditCollection',
57  SaveCollection: 'SaveCollection',
58  ShareSingleWishlist: 'ShareSingleWishlist'
59}
60
61SwymStorefrontLayoutContext.NotificationStatusTypes = {
62  Success: 'success',
63  Error: 'error',
64  Warning: 'Warning',
65  Info: 'info',
66  Neutral: 'neutral',
67  Toast: 'toast'
68}
69
70SwymStorefrontLayoutContext.NotificationActionTypes = {
71  AddedToWishlist: 'added-to-wishlist',
72  AddToCollection: 'add-to-collection',
73  AddedToCollection: 'added-to-collection',
74  AddedToCart: 'added-to-cart'
75}
76
77SwymStorefrontLayoutContext.StorefrontLayoutUrls = Object.assign(
78  SwymStorefrontLayoutContext.StorefrontLayoutUrls || {},
79  {
80    List: '#swym-list',
81    Collections: '#swym-collections',
82    CollectionList: '#swym-collection:'
83  }
84);
85
86SwymStorefrontLayoutContext.NotificationIconType = {
87  SuccessIcon: 'SuccessIcon',
88  RemoveIcon: 'RemoveIcon'
89}
90
91SwymStorefrontLayoutContext.LoaderViewType = {
92  WishlistListItem: 'wishlist-list-item',
93  CarouselListItem: 'carousel-list-item',
94  CollectionImages: 'collection-view-images',
95  SpinnerLoader: 'spinner-loader'
96}
97
98SwymStorefrontLayoutContext.StorefrontLayoutViewType = {
99  Wishlist: 'tabWishlist',
100  SaveForLater: 'tabSavedForLater',
101  SavedForYou: 'tabSavedForYou'
102}
103
104SwymStorefrontLayoutContext.Tabs = [SwymStorefrontLayoutContext.StorefrontLayoutViewType.Wishlist]
105
106SwymStorefrontLayoutContext.ListItemType = {
107  WishlistItem: 'WishlistItem',
108  CollectionItem: 'CollectionItem',
109  SaveForLaterItem: 'SaveForLaterItem',
110  SavedForYouItem: 'SavedForYouItem'
111}
112SwymStorefrontLayoutContext.CommonAddtoWL = false;
113SwymStorefrontLayoutContext.CommonRemovefromWL = false;
114
115/**
116 * Helper function to determine if multiple wishlists should be shown
117 * Returns an object with two flags:
118 * - shouldShowMultiple: true if carousel and collections should be displayed
119 * - canCreateLists: true if user can create new lists (feature flag is on)
120 */
121SwymStorefrontLayoutContext.getMultiWishlistConfig = function() {
122  const isOldControlCentre = !('multiple-wishlist' in (window?.SwymEnabledCommonFeatures || {}));
123  const canCreateLists = isOldControlCentre
124    ? SwymStorefrontLayoutContext?.Settings?.EnableStorefrontLayoutCollection
125    : window?.SwymEnabledCommonFeatures?.['multiple-wishlist'];
126  
127  // Show multiple wishlists if feature is enabled OR if user has more than 1 list
128  const hasMultipleLists = window.SwymStorefrontLayoutContext?.allLists?.length > 1;
129  const shouldShowMultiple = canCreateLists || hasMultipleLists;
130  
131  return {
132    shouldShowMultiple,
133    canCreateLists
134  };
135};
136
137// The list name used by the SDK's auto-wishlist feature in multi-list mode
138const SFY_LIST_NAME = 'Saved For Me';
139
140// Returns the dedicated "Saved For Me" list object in multi-list mode, or null in single-list mode.
141SwymStorefrontLayoutContext.getSfyList = function() {
142  const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
143  if (!shouldShowMultiple) return null;
144  return (SwymStorefrontLayoutContext.allLists || []).find(l => l.lname === SFY_LIST_NAME) || null;
145};
146
147/**
148 * Helper function to check if education layer (tooltips/toasts on collection and PDP pages) is enabled.
149 * Controlled via shop metafield `swym_wishlist.educationLayerEnabled`.
150 * Defaults to true (enabled) unless explicitly set to false.
151 */
152SwymStorefrontLayoutContext.isEducationLayerEnabled = function() {
153  return window.SwymEducationLayerEnabled !== false;
154};
155
156/**
157 * Returns whether the login nudge is enabled for this store.
158 * Defaults to true (enabled) unless explicitly set to false.
159 */
160SwymStorefrontLayoutContext.isLoginNudgeEnabled = function() {
161  return window.SwymLoginNudgeEnabled !== false;
162};
163
164window._SwymAJAXCart = async function () {
165  try {
166    const cartComponent = document.querySelector('cart-notification') || document.querySelector('cart-drawer');
167    if (!cartComponent || typeof cartComponent.getSectionsToRender !== 'function') {
168      console.warn('[Cart Refresh] Cart component or getSectionsToRender is missing.');
169      const modalPopup = document.querySelector("modal-popup");
170      if(modalPopup && window.routes.cart) {
171        modalPopup.trigger("updateCart", {
172            callback: () => {
173                modalPopup.forwardEvent("openPopup", {
174                    target: "CART",
175                    url: window.routes.cart
176                });
177            }
178        });
179        return;
180      } 
181      
182      // Get current theme info
183      const currentThemeName = window?.Shopify?.theme?.schema_name?.trim();
184      const currentThemeId = window?.Shopify?.theme?.theme_store_id;
185
186      if (!currentThemeName) return false;
187
188      // Use preset API to get theme event configuration
189      window._swat.fetchThemePreset({ 
190        themeStoreId: currentThemeId, 
191        schemaName: currentThemeName
192      }, (themeData) => {
193        if (themeData?.AJAXCartEvent?.[0]?.eventName) {
194          try {
195            // Get event details from preset API response
196            const event = themeData.AJAXCartEvent?.[0];
197            
198            // Create event config object only with defined properties
199            const eventConfig = {};
200            if (event.bubbles !== undefined) {
201              eventConfig.bubbles = event.bubbles;
202            }
203            if (event.detail !== undefined) {
204              eventConfig.detail = event.detail;
205            }
206            
207            // Create and dispatch custom event with only defined properties
208            const customEvent = new CustomEvent(event?.eventName, eventConfig);
209
210            // Dispatch event on appropriate target
211            const target = event.bubbles ? document.documentElement : document;
212            target.dispatchEvent(customEvent);
213          } catch (err) {
214            console.warn(`[Cart Refresh] Failed to dispatch event for theme ${currentThemeName}`, err);
215          }
216        }
217      });
218      return;
219    }
220    
221    const sectionsToRender = cartComponent.getSectionsToRender();
222    const sectionIds = sectionsToRender.map(section => section.id).join(',');
223    if (!sectionIds) {
224      console.warn('[Cart Refresh] No section IDs found to render.');
225      return;
226    }
227
228    const [sectionRes, cartDataRes] = await Promise.all([
229      fetch(`/?sections=${sectionIds}`).then(res => res.ok ? res.json() : Promise.reject('Failed to fetch sections')),
230      fetch('/cart.js').then(res => res.ok ? res.json() : Promise.reject('Failed to fetch cart data'))
231    ]);
232
233    const parser = new DOMParser();
234
235    // Update cart icon bubble
236    const cartIconBubble = document.getElementById('cart-icon-bubble');
237    const iconHtmlDoc = parser.parseFromString(sectionRes['cart-icon-bubble'], 'text/html');
238    const iconBubbleContent = iconHtmlDoc.getElementById('shopify-section-cart-icon-bubble')?.innerHTML;
239    if (cartIconBubble && iconBubbleContent) {
240      cartIconBubble.innerHTML = iconBubbleContent;
241    }
242
243    // Update cart drawer if it exists
244    const cartDrawer = document.querySelector('cart-drawer');
245    if (cartDrawer) {
246      const drawerHtmlDoc = parser.parseFromString(sectionRes['cart-drawer'], 'text/html');
247      const newDrawerContent = drawerHtmlDoc.querySelector('cart-drawer')?.innerHTML;
248
249      if (newDrawerContent !== undefined) {
250        cartDrawer.classList.toggle('is-empty', cartDataRes.item_count === 0);
251        cartDrawer.innerHTML = newDrawerContent;
252
253        const overlay = cartDrawer.querySelector('#CartDrawer-Overlay');
254        if (overlay) {
255        overlay.addEventListener('click', cartDrawer.close?.bind(cartDrawer));
256        }
257      }
258    }
259  } catch (error) {
260      console.error('[Cart Refresh] An error occurred:', error);
261  }
262};
263
264/**
265 * Checks if the current user has permission to edit the given wishlist.
266 * @param {Object} list - The wishlist to check.
267 * @returns {boolean} - Returns true if the user can edit the list, otherwise false.
268 */
269SwymStorefrontLayoutContext.checkUserCanEditList = (list) => {
270  if(!list){
271      window._swat?.utils.warn('list not exist to check list access');
272    return false;
273  }
274  if(list?.lty === 'sfl'){
275    let canEditList = SwymStorefrontLayoutContext?.sflList?.lid === list?.lid;
276    return canEditList;
277  }
278  let canEditList = SwymStorefrontLayoutContext?.lists?.some((userList)=> userList?.lid === list?.lid);
279  return canEditList;
280}
281
282/**
283 * Formats a given price based on the store's money formatting settings.
284 * @param {number} value - The price value to format.
285 * @returns {string} - The formatted price string.
286 */
287SwymStorefrontLayoutContext.FormatPrice = (value) => {
288  try {
289    if (window.SwymOverrideFormatMoneyFn) {
290      return window.SwymOverrideFormatMoneyFn(value);
291    }
292    if (window._swat.platform.formatMoney) {
293      if (
294          window._swat.platform.currentMoneyFormat &&
295          window._swat.platform.currentMoneyFormat()
296      ) {
297        return window._swat.platform.formatMoney(
298          value * 100,
299          window._swat.platform.currentMoneyFormat()
300        );
301      }
302    }
303  } catch (err) {
304    window._swat?.utils.error("Error formatting price - " + value + err);
305  }
306  const currency = window._swat.currency;
307  return currency + window._swat.utils.padDecimal(value);
308}
309
310
311/**
312 * Retrieves the selected variant from a given item based on the provided variant ID.
313 *
314 * @param {Object} item - The item containing product data and variants.
315 * @param {string | number} variantId - The ID of the variant to find.
316 * @returns {Object | null} - The matching variant object if found, otherwise null.
317 */
318SwymStorefrontLayoutContext.getSelectedVariant = (item, variantId) => {
319  return variantId? item?.productData?.variants?.find((variant) => variant?.id === variantId) || null:null;
320}
321
322/**
323 * Applies a transform function to listcontents across all context list references
324 * (DefaultList, collections, lists, allLists) to keep them in sync.
325 * @param {Function} transformFn - (listcontents: Array) => Array
326 */
327SwymStorefrontLayoutContext.updateAllListContents = (transformFn) => {
328  if (SwymStorefrontLayoutContext.DefaultList) {
329    SwymStorefrontLayoutContext.DefaultList = {
330      ...SwymStorefrontLayoutContext.DefaultList,
331      listcontents: transformFn(SwymStorefrontLayoutContext.DefaultList.listcontents)
332    };
333  }
334  ['collections', 'lists', 'allLists'].forEach(key => {
335    if (SwymStorefrontLayoutContext[key]) {
336      SwymStorefrontLayoutContext[key] = SwymStorefrontLayoutContext[key].map(list => ({
337        ...list,
338        listcontents: transformFn(list.listcontents)
339      }));
340    }
341  });
342};
343
344/**
345 * Calculates the difference in hours between the current time and a given date-time string.
346 * @param {number} hours - The threshold hours to compare.
347 * @param {string} dateTimeString - The stored date-time string.
348 * @returns {boolean} - Returns true if the time difference exceeds the given hours, otherwise false.
349 */
350SwymStorefrontLayoutExtensions.calcDifferenceInHours = (hours, dateTimeString) => {
351  try {
352    if (!dateTimeString) {
353      window._swat?.utils.warn("[WARNING] Date time string empty");
354      return;
355    }
356    const storedDateTime = new Date(dateTimeString?.trim());
357    const currentDateTime = new Date();
358
359    const differenceInMs = Math.abs(currentDateTime - storedDateTime);
360    const differenceInHours = differenceInMs / (1000 * 60 * 60);
361    return differenceInHours > hours;
362  } catch (error) {
363    window._swat?.utils.warn("[Error/Warning] while performing health check", error);
364    return false;
365  }
366}
367
368
369/**
370 * Checks if a given container has a scrollbar and applies/removes a CSS class accordingly.
371 * @param {HTMLElement} container - The container element to check.
372 */
373SwymStorefrontLayoutExtensions.checkContainerScrollbar = (container) => {
374  try{
375    if(!container){
376      window._swat?.utils.warn("container not available for scrollbar check");
377      return;
378    }
379    if (container.scrollHeight > container.clientHeight) {
380      container.classList.add("swym-storefront-layout-container-has-scroll");
381    } else {
382      container.classList.remove("swym-storefront-layout-container-has-scroll");
383    }
384  }catch(error){
385    window._swat?.utils.warn("invalid container for scrollbar check");
386  }
387}
388
389/**
390 * Extracts computed font styles from heading elements (h1, h2, h3) with fallback to body.
391 * @returns {Object}
391 - An object containing font family and other relevant font properties.
392 */
393SwymStorefrontLayoutExtensions.getHeadingFontStyles = () => {
394  try {
395    // Find the first available heading element (h1, h2, or h3)
396    const headingEl = document.querySelector('h1, h2, h3') || document.body;
397    const computedStyles = window.getComputedStyle(headingEl);
398    
399    return {
400      fontFamily: computedStyles.fontFamily,
401      fontWeight: computedStyles.fontWeight,
402      letterSpacing: computedStyles.letterSpacing
403    };
404  } catch (error) {
405    window._swat?.utils.warn("Error extracting heading font styles", error);
406    // Fallback to body styles if heading extraction fails
407    try {
408      const bodyStyles = window.getComputedStyle(document.body);
409      return {
410        fontFamily: bodyStyles.fontFamily,
411        fontWeight: bodyStyles.fontWeight,
412        letterSpacing: bodyStyles.letterSpacing
413      };
414    } catch (fallbackError) {
415      window._swat?.utils.warn("Error extracting body font styles", fallbackError);
416      return {};
417    }
418  }
419}
420
421/**
422 * Applies heading font styles to a given title element.
423 * @param {HTMLElement} titleElement - The title element to apply styles to.
424 */
425SwymStorefrontLayoutExtensions.applyHeadingFontStyles = (titleElement) => {
426  try {
427    const headingFontStyles = SwymStorefrontLayoutExtensions?.getHeadingFontStyles();
428    // When theme CSS mapping is active, typography is handled via CSS variables.
429    // Skip inline overrides for font-family, font-weight, and letter-spacing
430    // to avoid clobbering the CSS variable values with computed page styles.
431    const themeMappingActive = !!document.querySelector('[data-swym-theme-mapping]');
432    
433    if (titleElement && headingFontStyles) {
434      if (!themeMappingActive) {
435        // Apply font styles from heading elements to the title
436        if (headingFontStyles.fontFamily) {
437          titleElement.style.fontFamily = headingFontStyles.fontFamily;
438        }
439        if (headingFontStyles.fontWeight) {
440          titleElement.style.fontWeight = headingFontStyles.fontWeight;
441        }
442        if (headingFontStyles.letterSpacing) {
443          titleElement.style.letterSpacing = headingFontStyles.letterSpacing;
444        }
445      }
446      // Note: We don't apply fontSize and lineHeight as the title should maintain its own sizing
447    }
448  } catch (error) {
449    window._swat?.utils.warn(`Error applying heading font styles`, error);
450  }
451}
452
453SwymStorefrontLayoutExtensions.refreshWishList = () => {
454  try {
455    SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.updateList();
456  } catch (error) {
457    window._swat?.utils.error('Failed to fetch wishlist', error);
458  }
459}
460
461SwymStorefrontLayoutExtensions.getShareIconSvg = () => {
462  return `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none" aria-hidden="true" focusable="false">
463    <path d="M13.5 2.375C14.6669 2.375 15.625 3.33306 15.625 4.5C15.625 5.66694 14.6669 6.625 13.5 6.625C12.8556 6.625 12.2862 6.30928 11.8828 5.81445C11.7533 5.65562 11.5425 5.59393 11.3516 5.65137L11.2715 5.68359L6.77539 7.93262C6.5655 8.03762 6.45726 8.27438 6.51465 8.50195C6.58433 8.77824 6.625 8.86302 6.625 9C6.625 9.13698 6.58433 9.22176 6.51465 9.49805C6.45726 9.72562 6.5655 9.96238 6.77539 10.0674L11.2715 12.3164C11.4808 12.4211 11.7349 12.3669 11.8828 12.1855C12.2862 11.6907 12.8556 11.375 13.5 11.375C14.6669 11.375 15.625 12.3331 15.625 13.5C15.625 14.6669 14.6669 15.625 13.5 15.625C12.3331 15.625 11.375 14.6669 11.375 13.5C11.375 13.363 11.4157 13.2782 11.4854 13.002C11.5427 12.7744 11.4345 12.5376 11.2246 12.4326L6.72852 10.1836C6.54532 10.0919 6.32732 10.1214 6.17676 10.252L6.11719 10.3145C5.71385 10.8093 5.1444 11.125 4.5 11.125C3.33306 11.125 2.375 10.1669 2.375 9C2.375 7.83306 3.33306 6.875 4.5 6.875C5.1444 6.875 5.71385 7.19072 6.11719 7.68555C6.2651 7.86695 6.51918 7.92112 6.72852 7.81641L11.2246 5.56738C11.4345 5.46238 11.5427 5.22562 11.4854 4.99805C11.4157 4.72176 11.375 4.63698 11.375 4.5C11.375 3.33306 12.3331 2.375 13.5 2.375ZM13.5 11.5C12.3888 11.5 11.5 12.3888 11.5 13.5C11.5 14.6112 12.3888 15.5 13.5 15.5C14.6112 15.5 15.5 14.6112 15.5 13.5C15.5 12.3888 14.6112 11.5 13.5 11.5ZM4.5 7C3.38877 7 2.5 7.88877 2.5 9
463C2.5 10.1112 3.38877 11 4.5 11C5.61123 11 6.5 10.1112 6.5 9C6.5 7.88877 5.61123 7 4.5 7ZM13.5 2.5C12.3888 2.5 11.5 3.38877 11.5 4.5C11.5 5.61123 12.3888 6.5 13.5 6.5C14.6112 6.5 15.5 5.61123 15.5 4.5C15.5 3.38877 14.6112 2.5 13.5 2.5Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
464  </svg>`;
465}
466
467/**
468 * Returns the wishlist icon SVG markup.
469 * Currently uses a hardcoded heart icon. Dynamic icon support (heart/star/bookmark
470 * based on retailer config) will be added later.
471 * @param {'filled'|'unfilled'} state - Whether to return the filled or unfilled icon variant
472 * @param {object} [opts] - Optional overrides
473 * @param {string} [opts.color] - Icon stroke/fill color (default: 'currentColor')
474 * @param {string} [opts.width] - SVG width attribute (default: '17')
475 * @param {string} [opts.height] - SVG height attribute (default: '15')
476 * @returns {string} SVG markup string
477 */
478SwymStorefrontLayoutExtensions.getWishlistIconSvg = (state = 'filled', opts = {}) => {
479  const color = opts.color || 'currentColor';
480  const width = opts.width || '17';
481  const height = opts.height || '15';
482
483  if (state === 'unfilled') {
484    return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 17 16" fill="none" aria-hidden="true" focusable="false">
485      <path d="M3.94617 0.518585C4.71879 0.439587 5.46423 0.623711 6.12292 0.918976C7.09924 1.35664 7.94118 2.06375 8.495 2.66019C8.69022 2.42887 8.92463 2.21448 9.18054 2.02249C9.66446 1.65956 10.2568 1.35316 10.8905 1.14944C12.1427 0.746943 13.6652 0.716791 14.8436 1.60062C16.0064 2.47285 16.4537 3.64555 16.3866 4.90921C16.3211 6.14189 15.7705 7.444 14.993 8.66409C13.4387 11.1032 10.8538 13.404 8.76746 14.4473L8.53113 14.5655L8.30066 14.4375C5.98745 13.1524 3.46501 10.932 1.9364 8.58597C1.17217 7.41299 0.633191 6.17363 0.521362 4.97757C0.407722 3.76125 0.739132 2.59768 1.69031 1.64651C2.39175 0.945176 3.16373 0.598678 3.94617 0.518585Z" fill="white" stroke="${color}"/>
486    </svg>`;
487  }
488  return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 17 15" fill="none" aria-hidden="true" focusable="false">
489    <path d="M2.04363 2.00013C4.54368 -0.499876 7.71029 2.33346 8.54363 3.50012C9.21029 2.00012 12.5437 0.500119 14.5437 2.00013C18.6166 5.05486 12.5437 12.0001 8.54363 14.0001C4.04367 11.5001 -1.29179 5.3355 2.04363 2.00013Z" fill="${color}"/>
490  </svg>`;
491}
492
493SwymStorefrontLayoutExtensions.refreshSFLList = () => {
494  try {
495    SwymStorefrontLayoutAPI?.SwymSFLAsyncApis?.updateSflList();
496  } catch (error) {
497    window._swat?.utils.error('Failed to fetch sfl list', error);
498  }
499}
500
501/**
502 * Add All To Cart — Control Centre UI only.
503 *
504 * Gated by the retailer setting `UI.ShowStorefrontLayoutAddAllToCart`. This is a
505 * separate key from the legacy UI's `UI.ShowAddAllToCart` so the two UIs can be
506 * switched on independently for a merchant.
507 */
508SwymStorefrontLayoutExtensions.AddAllToCart = {
509  /**
510   * True when the merchant has enabled Add All To Cart for this UI.
511   * @returns {boolean}
512   */
513  isEnabled() {
514    return window._swat?.retailerSettings?.UI?.ShowStorefrontLayoutAddAllToCart === true;
515  },
516
517  /**
518   * Items from a list that can actually go into the cart: the selected variant is in
519   * stock and, when tag based actions are on, the product is not tagged to hide or
520   * disable add to cart.
521   * @param {object} list - Wishlist or collection with a `listcontents` array
522   * @returns {Array<object>} eligible list items
523   */
524  getEligibleItems(list) {
525    const settings = window._swat?.retailerSettings;
526    const tagBasedActionEnabled = settings?.Wishlist?.TagBasedActionEnabled;
527    const hideAddToCartTag = settings?.UI?.HideAddToCartTag || 'swym-hide-addtocart';
528    const disabledAddToCartTag = settings?.UI?.DisabledAddtoCartTag || 'swym-disabled-addtocart-with-text';
529
530    return (list?.listcontents || []).filter((item) => {
531      const variantId = item?.cprops?.selectedVariantId || item?.epi;
532      const variant = SwymStorefrontLayoutContext?.getSelectedVariant(item, variantId);
533      if (variant && !variant.available) return false;
534      if (!tagBasedActionEnabled) return true;
535      const isTagged = (tag) => window._swat?.platform?.isTagAvailable(tag, item?.productData);
536      return !isTagged(hideAddToCartTag) && !isTagged(disabledAddToCartTag);
537    });
538  },
539
540  /**
541   * The drawer is a narrow column with a long scroll, so the button belongs in a
542   * sticky footer the way a cart drawer's checkout button does. The modal and the
543   * page are wide, where a full-width bar reads as a banner — there the button sits
544   * right aligned in the header row instead.
545   * @returns {'bottom'|'top'} which mount point this layout uses
546   */
547  getPlacement() {
548    return SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer' ? 'bottom' : 'top';
549  },
550
551  /**
552   * Renders the button into whichever mount point suits the current layout, and
553   * wires its click handler. Renders nothing when the setting is off or the list
554   * has no item that can be added.
555   * @param {HTMLElement} root - Element holding the top and bottom mount points
556   * @param {object} list - Wishlist or collection the button acts on
557   */
558  mount(root, list) {
559    if (!root) return;
560    const containers = root.querySelectorAll('.swym-storefront-layout-add-all-to-cart-container');
561    containers.forEach((container) => { container.innerHTML = ''; });
562    if (!this.isEnabled() || !this.getEligibleItems(list).length) return;
563
564    const container = root.querySelector(`.swym-storefront-layout-add-all-to-cart-${this.getPlacement()}`);
565    if (!container) return;
566
567    const cta = SwymStorefrontLayoutContext?.Strings?.addAllToCartCta || 'Add All To Cart';
568    container.innerHTML = `
569      <button class="swym-storefront-layout-add-all-to-cart-button" data-action="add-all-to-cart" aria-label="${swymEscAttr(cta)}">${cta}</button>
570    `;
571    const button = container.querySelector('[data-action="add-all-to-cart"]');
572    button?.addEventListener('click', () => this.handleClick(button, list));
573  },
574
575  /**
576   * Click handler for the button — puts it in its loading state and starts the add.
577   * @param {HTMLElement} button
578   * @param {object} list
579   */
580  handleClick(button, list) {
581    const eligibleItems = this.getEligibleItems(list);
582    if (!eligibleItems.length) {
583      this.showError(SwymStorefrontLayoutContext?.Strings?.addAllToCartEmptyText);
584      return;
585    }
586
587    const originalLabel = button.innerHTML;
588    button.innerHTML = SwymStorefrontLayoutContext?.Strings?.addingToCart || 'Adding To Cart';
589    button.setAttribute('disabled', true);
590    this.addItemsToCart(eligibleItems, button, originalLabel);
591  },
592
593  /**
594   * Adds the given items to the cart in a single request.
595   * @param {Array<object>} items
596   * @param {HTMLElement} button
597   * @param {string} originalLabel - Button label to restore on failure
598   */
599  addItemsToCart(items, button, originalLabel) {
600    window._swat?.platform?.addAllToCart(
601      items.map(({ epi, empi, qty }) => ({ epi, empi, qty: qty || 1 })),
602      () => this.onAddSuccess(items, button, originalLabel),
603      (error) => {
604        // Shopify's /cart/add.js is atomic: one unaddable line rejects the whole payload
605        // with 422 and adds nothing. Its 422 body is only {status, message, description} —
606        // no variant id — so the failing line cannot be identified from the response.
607        // Retry the lines one at a time and let Shopify judge each on its own instead of
608        // parsing the message, which is merchant locale specific and would drop a
609        // "Shirt XL" when the error names "Shirt".
610        if (error?.status === 422 && items.length > 1) {
611          this.addItemsOneByOne(items, button, originalLabel);
612          return;
613        }
614        button.innerHTML = originalLabel;
615        button.removeAttribute('disabled');
616        this.showError(error?.description || error?.detail || SwymStorefrontLayoutContext?.Strings?.addAllToCartErrorText);
617      }
618    );
619  },
620
621  /**
622   * Adds items one at a time, sequentially, keeping whichever lines Shopify accepts.
623   * Sequential rather than parallel because concurrent cart mutations race each other.
624   * @param {Array<object>} items
625   * @param {HTMLElement} button
626   * @param {string} originalLabel
627   */
628  addItemsOneByOne(items, button, originalLabel) {
629    const addedItems = [];
630    let lastError = null;
631
632    const addNext = (index) => {
633      if (index >= items.length) {
634        if (addedItems.length) {
635          this.onAddSuccess(addedItems, button, originalLabel);
636          return;
637        }
638        button.innerHTML = originalLabel;
639        button.removeAttribute('disabled');
640        this.showError(lastError?.description || lastError?.detail || SwymStorefrontLayoutContext?.Strings?.addAllToCartErrorText);
641        return;
642      }
643
644      const { epi, empi, qty } = items[index];
645      window._swat?.platform?.addAllToCart(
646        [{ epi, empi, qty: qty || 1 }],
647        () => { addedItems.push(items[index]); addNext(index + 1); },
648        (error) => { lastError = error; addNext(index + 1); }
649      );
650    };
651
652    addNext(0);
653  },
654
655  /**
656   * Restores the button, notifies the shopper and refreshes the theme cart.
657   * @param {Array<object>} itemsAdded
658   * @param {HTMLElement} button
659   * @param {string} originalLabel
660   */
661  onAddSuccess(itemsAdded, button, originalLabel) {
662    button.innerHTML = originalLabel;
663    button.removeAttribute('disabled');
664
665    const successText = SwymStorefrontLayoutContext?.Strings?.addAllToCartSuccessText || '';
666    SwymStorefrontLayoutExtensions?.Notification?.setMessage({
667      message: window._swat?.utils?.renderTemplateString(successText, { addCount: itemsAdded.length }),
668      status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Neutral,
669      actionType: SwymStorefrontLayoutContext?.NotificationActionTypes?.AddedToCart,
670      duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
671      action: {
672        label: SwymStorefrontLayoutContext?.Strings?.notificationActionGoToCart,
673        onClick: () => {
674          window.location.href = `${window.Shopify.routes.root}cart`;
675        }
676      }
677    }, {
678      showActionButton: true,
679      showImage: false
680    });
681
682    window._swat?.instrumentV3(
683      SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutAddedAllToCart,
684      {
685        "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutCartConversion,
686        itemCount: itemsAdded.length
687      }
688    );
689    window?._SwymAJAXCart();
690  },
691
692  /**
693   * Shows an error notification for a failed add.
694   * @param {string} message
695   */
696  showError(message) {
697    SwymStorefrontLayoutExtensions?.Notification?.setMessage({
698      title: message || SwymStorefrontLayoutContext?.Strings?.addAllToCartErrorText,
699      status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Error
700    }, {
701      showTitle: true,
702      showImage: false
703    });
704  }
705}
706
707/**
708 * Theme CSS variable mapping — maps Shopify theme CSS variables to Swym's
709 * --swym-storefront-layout-* variables so the drawer inherits theme colors,
710 * typography, button styles, and input styles automatically.
711 *
712 * Supports Dawn-family and Horizon-family themes. Unknown themes fall back
713 * to the existing hardcoded :root values in storefront-layout.css.
714 *
715 * Runs once at init — injects a single <style> block, zero ongoing cost.
716 */
717SwymStorefrontLayoutExtensions.ThemeCSSMapping = (() => {
718  /**
719   * Detects theme family using CSS variable feature detection.
720   * Dawn-family themes define --font-heading-family on :root.
721   * Horizon-family themes define --font-h2--family on :root.
722   * This approach works with custom-named / forked themes that still use
723   * the same CSS variable system as their parent theme.
724   * Falls back to name-based matching as a secondary check.
725   */
726  const DAWN_THEMES = ['Dawn', 'Craft', 'Crave', 'Sense', 'Taste', 'Studio', 'Ride', 'Colorblock', 'Refresh', 'Origin', 'Publisher', 'Spotlight', 'Trade', 'Rise'];
727  const HORIZON_THEMES = ['Horizon', 'Ritual', 'Heritage', 'Atelier', 'Pitch', 'Tinker', 'Dwell', 'Vessel', 'Savor', 'Fabric'];
728
729  function getThemeFamily() {
730    try {
731      // Primary: CSS variable feature detection (works with custom-named themes)
732      const rootStyles = getComputedStyle(document.documentElement);
733      const hasDawnVars = rootStyles.getPropertyValue('--font-heading-family').trim();
734      const hasHorizonVars = rootStyles.getPropertyValue('--font-h2--family').trim();
735      if (hasDawnVars) return 'dawn';
736      if (hasHorizonVars) return 'horizon';
737
738      // Fallback: name-based matching
739      const themeName = window.Shopify?.theme?.name;
740      if (!themeName) return null;
741      if (DAWN_THEMES.some(t => themeName.includes(t))) return 'dawn';
742      if (HORIZON_THEMES.some(t => themeName.includes(t))) return 'horizon';
743      return null;
744    } catch (e) {
745      return null;
746    }
747  }
748
749  function getDawnThemeVariables() {
750    return `
751      :root {
752        /* UI */
753        --swym-theme-layout-ui-bg-color: rgb(var(--color-background));
754        --swym-theme-layout-ui-text-color: rgba(var(--color-foreground), 0.75);
755        --swym-theme-layout-color-bg: rgb(var(--color-background));
756        --swym-theme-layout-color-text: rgb(var(--color-foreground));
757        --swym-theme-layout-color-text-default: rgb(var(--color-foreground));
758        --swym-theme-layout-color-text-sub: rgba(var(--color-foreground), 0.55);
759        --swym-theme-layout-color-text-sub2: rgba(var(--color-foreground), 0.4);
760        --swym-theme-layout-color-border: rgba(var(--color-foreground), 0.15);
761        --swym-theme-layout-border-color: rgba(var(--color-foreground), 0.15);
762
763        /* TYPOGRAPHY */
764        --swym-theme-layout-font-family-heading: var(--font-heading-family);
765        --swym-theme-layout-font-weight-heading: var(--font-heading-weight);
766        --swym-theme-layout-font-style-heading: var(--font-heading-style);
767        --swym-theme-layout-text-transform-heading: none;
768        --swym-theme-layout-letter-spacing-heading: calc(var(--font-heading-scale) * 0.06rem);
769        --swym-theme-layout-text-color-heading: rgb(var(--color-foreground));
770        --swym-theme-layout-font-family-body: var(--font-body-family);
771        --swym-theme-layout-font-weight-body: var(--font-body-weight);
772        --swym-theme-layout-font-weight-body-bold: var(--font-body-weight-bold);
773        --swym-theme-layout-font-style-body: var(--font-body-style);
774        --swym-theme-layout-letter-spacing-body: 0.06rem;
775        --swym-theme-layout-text-transform-body: none;
776
777        /* BUTTONS — primary */
778        --swym-theme-layout-button-border-color-primary: rgba(var(--color-button-text), calc(1 - var(--buttons-border-opacity, 1)));
779        --swym-theme-layout-button-border-radius: var(--buttons-radius, 0px);
780        --swym-theme-layout-button-border-radius-primary: var(--buttons-radius, 0px);
781        --swym-theme-layout-button-border-style-primary: solid;
782        --swym-theme-layout-button-border-width-primary: var(--buttons-border-width, 0px);
783        --swym-theme-layout-button-box-shadow-primary: var(--buttons-shadow-horizontal-offset, 0px) var(--buttons-shadow-vertical-offset, 0px) var(--buttons-shadow-blur-radius, 0px) rgba(var(--color-shadow, 0, 0, 0), var(--buttons-shadow-opacity, 0));
784        --swym-theme-layout-button-color-bg-primary: rgba(var(--color-button), var(--alpha-button-background));
785        --swym-theme-layout-button-color-text-primary: rgb(var(--color-button-text));
786        --swym-theme-layout-button-font-family-primary: var(--font-body-family);
787        --swym-theme-layout-button-font-size-primary: 1.5rem;
788        --swym-theme-layout-button-font-style-primary: ;
789        --swym-theme-layout-button-font-weight-primary: var(--font-body-weight);
790        --swym-theme-layout-button-letter-spacing-primary: 0.1rem;
791        --swym-theme-layout-button-text-transform-primary: none;
792
793        /* BUTTONS — secondary */
794        --swym-theme-layout-button-border-color-secondary: rgba(var(--color-secondary-button-text), var(--buttons-border-opacity, 1));
795        --swym-theme-layout-button-border-radius-secondary: var(--buttons-radius, 0px);
796        --swym-theme-layout-button-border-style-secondary: solid;
797        --swym-theme-layout-button-border-width-secondary: var(--buttons-border-width, 0px);
798        --swym-theme-layout-button-box-shadow-secondary: var(--buttons-shadow-horizontal-offset, 0px) var(--buttons-shadow-vertical-offset, 0px) var(--buttons-shadow-blur-radius, 0px) rgba(var(--color-shadow, 0, 0, 0), var(--buttons-shadow-opacity, 0));
799        --swym-theme-layout-button-color-bg-secondary: rgb(var(--color-secondary-button));
800        --swym-theme-layout-button-color-text-secondary: rgb(var(--color-secondary-button-text));
801        --swym-theme-layout-button-font-family-secondary: var(--font-body-family);
802        --swym-theme-layout-button-font-size-secondary: 1.5rem;
803        --swym-theme-layout-button-font-style-secondary: ;
804        --swym-theme-layout-button-font-weight-secondary: var(--font-body-weight);
805        --swym-theme-layout-button-letter-spacing-secondary: 0.1rem;
806        --swym-theme-layout-button-text-transform-secondary: none;
807
808        /* INPUTS */
809        --swym-theme-layout-input-color-bg: rgb(var(--color-background));
810        --swym-theme-layout-input-color-text: rgb(var(--color-foreground));
811        --swym-theme-layout-input-border-color: rgba(var(--color-foreground), var(--inputs-border-opacity, 0.55));
812        --swym-theme-layout-input-border-radius: var(--inputs-radius, 0px);
813        --swym-theme-layout-input-border-style: solid;
814        --swym-theme-layout-input-border-width: var(--inputs-border-width, 1px);
815        --swym-theme-layout-input-box-shadow: 0;
816        --swym-theme-layout-input-box-shadow-hover: 0 0 0 var(--inputs-border-width, 1px) rgba(var(--color-foreground), var(--inputs-border-opacity, 0.55));
817        --swym-theme-layout-input-box-shadow-focus: 0 0 0 var(--inputs-border-width, 1px) rgba(var(--color-foreground), 1);
818        --swym-theme-layout-input-focus-border-color: rgba(var(--color-foreground), 1);
819        --swym-theme-layout-input-focus-outline-color: transparent;
820        --swym-theme-layout-input-focus-outline-offset: 0;
821        --swym-theme-layout-input-focus-outline-style: solid;
822        --swym-theme-layout-input-focus-outline-width: 0;
823        --swym-theme-layout-input-transition: box-shadow var(--duration-short, 100ms) ease;
824      }
825    `;
826  }
827
828  function getHorizonThemeVariables() {
829    return `
830      :root {
831        /* UI */
832        --swym-theme-layout-ui-bg-color: var(--color-background);
833        --swym-theme-layout-ui-text-color: var(--color-foreground);
834        --swym-theme-layout-color-bg: var(--color-background);
835        --swym-theme-layout-color-text: var(--color-foreground);
836        --swym-theme-layout-color-text-default: var(--color-foreground);
837        --swym-theme-layout-color-text-sub: color-mix(in srgb, var(--color-foreground) 55%, transparent);
838        --swym-theme-layout-color-text-sub2: color-mix(in srgb, var(--color-foreground) 40%, transparent);
839        --swym-theme-layout-color-border: color-mix(in srgb, var(--color-foreground) 15%, transparent);
840        --swym-theme-layout-border-color: color-mix(in srgb, var(--color-foreground) 15%, transparent);
841
842        /* TYPOGRAPHY */
843        --swym-theme-layout-font-family-heading: var(--font-h2--family);
844        --swym-theme-layout-font-weight-heading: var(--font-h2--weight);
845        --swym-theme-layout-font-style-heading: var(--font-h2--style);
846        --swym-theme-layout-text-transform-heading: var(--font-h2--case);
847        --swym-theme-layout-letter-spacing-heading: var(--font-h2--letter-spacing);
848        --swym-theme-layout-text-color-heading: var(--font-h2--color);
849        --swym-theme-layout-font-family-body: var(--font-paragraph--family);
850        --swym-theme-layout-font-weight-body: var(--font-paragraph--weight);
851        --swym-theme-layout-font-weight-body-bold: bold;
852        --swym-theme-layout-font-style-body: var(--font-paragraph--style);
853        --swym-theme-layout-letter-spacing-body: var(--font-paragraph--letter-spacing);
854        --swym-theme-layout-text-transform-body: var(--font-paragraph--case);
855
856        /* BUTTONS — primary */
857        --swym-theme-layout-button-border-color-primary: var(--color-primary-button-background);
858        --swym-theme-layout-button-border-radius: var(--style-border-radius-buttons-primary);
859        --swym-theme-layout-button-border-radius-primary: var(--style-border-radius-buttons-primary);
860        --swym-theme-layout-button-border-style-primary: solid;
861        --swym-theme-layout-button-border-width-primary: 0;
862        --swym-theme-layout-button-box-shadow-primary: inset 0 0 0 var(--style-border-width-primary) var(--color-primary-button-border);
863        --swym-theme-layout-button-color-bg-primary: var(--color-primary-button-background);
864        --swym-theme-layout-button-color-text-primary: var(--color-primary-button-text);
865        --swym-theme-layout-button-font-family-primary: var(--button-font-family-primary);
866        --swym-theme-layout-button-font-size-primary: var(--font-paragraph--size);
867        --swym-theme-layout-button-font-style-primary: var(--font-paragraph--style);
868        --swym-theme-layout-button-font-weight-primary: var(--font-paragraph--weight);
869        --swym-theme-layout-button-letter-spacing-primary: var(--font-paragraph--letter-spacing);
870        --swym-theme-layout-button-text-transform-primary: var(--button-text-case-primary);
871
872        /* BUTTONS — secondary */
873        --swym-theme-layout-button-border-color-secondary: var(--color-secondary-button-background);
874        --swym-theme-layout-button-border-radius-secondary: var(--style-border-radius-buttons-secondary);
875        --swym-theme-layout-button-border-style-secondary: solid;
876        --swym-theme-layout-button-border-width-secondary: 0;
877        --swym-theme-layout-button-box-shadow-secondary: inset 0 0 0 var(--style-border-width-secondary) var(--color-secondary-button-border);
878        --swym-theme-layout-button-color-bg-secondary: var(--color-secondary-button-background);
879        --swym-theme-layout-button-color-text-secondary: var(--color-secondary-button-text);
880        --swym-theme-layout-button-font-family-secondary: var(--button-font-family-secondary);
881        --swym-theme-layout-button-font-size-secondary: var(--font-paragraph--size);
882        --swym-theme-layout-button-font-style-secondary: var(--font-paragraph--style);
883        --swym-theme-layout-button-font-weight-secondary: var(--font-paragraph--weight);
884        --swym-theme-layout-button-letter-spacing-secondary: var(--font-paragraph--letter-spacing);
885        --swym-theme-layout-button-text-transform-secondary: var(--button-text-case-secondary);
886
887        /* INPUTS */
888        --swym-theme-layout-input-color-bg: var(--color-input-background);
889        --swym-theme-layout-input-color-text: var(--color-input-text);
890        --swym-theme-layout-input-border-color: var(--color-input-border);
891        --swym-theme-layout-input-border-radius: var(--style-border-radius-inputs);
892        --swym-theme-layout-input-border-style: solid;
893        --swym-theme-layout-input-border-width: var(--style-border-width-inputs);
894        --swym-theme-layout-input-box-shadow: 0;
895        --swym-theme-layout-input-box-shadow-hover: 0;
896        --swym-theme-layout-input-box-shadow-focus: 0;
897        --swym-theme-layout-input-focus-border-color: var(--color-input-border);
898        --swym-theme-layout-input-focus-outline-color: currentColor;
899        --swym-theme-layout-input-focus-outline-offset: var(--focus-outline-offset);
900        --swym-theme-layout-input-focus-outline-style: solid;
901        --swym-theme-layout-input-focus-outline-width: var(--focus-outline-width);
902        --swym-theme-layout-input-transition: none;
903      }
904    `;
905  }
906
907  function getBridgeVariables() {
908    return `
909      #swym-storefront-layout-container {
910        /* UI */
911        --swym-storefront-layout-ui-bg-color: var(--swym-theme-layout-ui-bg-color);
912        --swym-storefront-layout-ui-text-color: var(--swym-theme-layout-ui-text-color);
913        --swym-storefront-layout-color-bg: var(--swym-theme-layout-color-bg);
914        --swym-storefront-layout-color-text: var(--swym-theme-layout-color-text);
915        --swym-storefront-layout-color-text-default: var(--swym-theme-layout-color-text-default);
916        --swym-storefront-layout-color-text-sub: var(--swym-theme-layout-color-text-sub);
917        --swym-storefront-layout-color-text-sub2: var(--swym-theme-layout-color-text-sub2);
918        --swym-storefront-layout-color-border: var(--swym-theme-layout-color-border);
919        --swym-storefront-layout-border-color: var(--swym-theme-layout-border-color);
920
921        /* TYPOGRAPHY */
922        --swym-storefront-layout-font-family-heading: var(--swym-theme-layout-font-family-heading);
923        --swym-storefront-layout-font-weight-heading: var(--swym-theme-layout-font-weight-heading);
924        --swym-storefront-layout-font-style-heading: var(--swym-theme-layout-font-style-heading);
925        --swym-storefront-layout-text-transform-heading: var(--swym-theme-layout-text-transform-heading);
926        --swym-storefront-layout-letter-spacing-heading: var(--swym-theme-layout-letter-spacing-heading);
927        --swym-storefront-layout-text-color-heading: var(--swym-theme-layout-text-color-heading);
928        --swym-storefront-layout-font-family-body: var(--swym-theme-layout-font-family-body);
929        --swym-storefront-layout-font-weight-body: var(--swym-theme-layout-font-weight-body);
930        --swym-storefront-layout-font-weight-body-bold: var(--swym-theme-layout-font-weight-body-bold);
931        --swym-storefront-layout-font-style-body: var(--swym-theme-layout-font-style-body);
932        --swym-storefront-layout-letter-spacing-body: var(--swym-theme-layout-letter-spacing-body);
933
934        /* BUTTONS — primary */
935        --swym-storefront-layout-button-color-bg-primary: var(--swym-theme-layout-button-color-bg-primary);
936        --swym-storefront-layout-button-color-text-primary: var(--swym-theme-layout-button-color-text-primary);
937        --swym-storefront-layout-button-color-bg-secondary: var(--swym-theme-layout-button-color-bg-secondary);
938        --swym-storefront-layout-button-color-text-secondary: var(--swym-theme-layout-button-color-text-secondary);
939        --swym-storefront-layout-button-border-color-primary: var(--swym-theme-layout-button-border-color-primary);
940        --swym-storefront-layout-button-border-radius: var(--swym-theme-layout-button-border-radius);
941        --swym-storefront-layout-button-border-radius-primary: var(--swym-theme-layout-button-border-radius-primary);
942        --swym-storefront-layout-button-border-style-primary: var(--swym-theme-layout-button-border-style-primary);
943        --swym-storefront-layout-button-border-width-primary: var(--swym-theme-layout-button-border-width-primary);
944        --swym-storefront-layout-button-box-shadow-primary: var(--swym-theme-layout-button-box-shadow-primary);
945        --swym-storefront-layout-button-font-family-primary: var(--swym-theme-layout-button-font-family-primary);
946        --swym-storefront-layout-button-font-weight-primary: var(--swym-theme-layout-button-font-weight-primary);
947        --swym-storefront-layout-button-font-size-primary: var(--swym-theme-layout-button-font-size-primary);
948        --swym-storefront-layout-button-font-style-primary: var(--swym-theme-layout-button-font-style-primary);
949        --swym-storefront-layout-button-text-transform-primary: var(--swym-theme-layout-button-text-transform-primary);
950        --swym-storefront-layout-button-letter-spacing-primary: var(--swym-theme-layout-button-letter-spacing-primary);
951
952        /* BUTTONS — secondary */
953        --swym-storefront-layout-button-border-color-secondary: var(--swym-theme-layout-button-border-color-secondary);
954        --swym-storefront-layout-button-border-radius-secondary: var(--swym-theme-layout-button-border-radius-secondary);
955        --swym-storefront-layout-button-border-style-secondary: var(--swym-theme-layout-button-border-style-secondary);
956        --swym-storefront-layout-button-border-width-secondary: var(--swym-theme-layout-button-border-width-secondary);
957        --swym-storefront-layout-button-box-shadow-secondary: var(--swym-theme-layout-button-box-shadow-secondary);
958        --swym-storefront-layout-button-font-family-secondary: var(--swym-theme-layout-button-font-family-secondary);
959        --swym-storefront-layout-button-font-weight-secondary: var(--swym-theme-layout-button-font-weight-secondary);
960        --swym-storefront-layout-button-font-style-secondary: var(--swym-theme-layout-button-font-style-secondary);
961        --swym-storefront-layout-button-text-transform-secondary: var(--swym-theme-layout-button-text-transform-secondary);
962        --swym-storefront-layout-button-letter-spacing-secondary: var(--swym-theme-layout-button-letter-spacing-secondary);
963        --swym-storefront-layout-button-font-size-secondary: var(--swym-theme-layout-button-font-size-secondary);
964
965        /* INPUTS */
966        --swym-storefront-layout-input-color-bg: var(--swym-theme-layout-input-color-bg);
967        --swym-storefront-layout-input-color-text: var(--swym-theme-layout-input-color-text);
968        --swym-storefront-layout-input-border-color: var(--swym-theme-layout-input-border-color);
969        --swym-storefront-layout-input-border-radius: var(--swym-theme-layout-input-border-radius);
970        --swym-storefront-layout-input-border-style: var(--swym-theme-layout-input-border-style);
971        --swym-storefront-layout-input-border-width: var(--swym-theme-layout-input-border-width);
972        --swym-storefront-layout-input-box-shadow: var(--swym-theme-layout-input-box-shadow);
973        --swym-storefront-layout-input-box-shadow-hover: var(--swym-theme-layout-input-box-shadow-hover);
974        --swym-storefront-layout-input-box-shadow-focus: var(--swym-theme-layout-input-box-shadow-focus);
975        --swym-storefront-layout-input-focus-border-color: var(--swym-theme-layout-input-focus-border-color);
976        --swym-storefront-layout-input-focus-outline-color: var(--swym-theme-layout-input-focus-outline-color);
977        --swym-storefront-layout-input-focus-outline-offset: var(--swym-theme-layout-input-focus-outline-offset);
978        --swym-storefront-layout-input-focus-outline-style: var(--swym-theme-layout-input-focus-outline-style);
979        --swym-storefront-layout-input-focus-outline-width: var(--swym-theme-layout-input-focus-outline-width);
980        --swym-storefront-layout-input-transition: var(--swym-theme-layout-input-transition);
981      }
982    `;
983  }
984
985  function inject() {
986    try {
987      const family = getThemeFamily();
988      if (!family) return; // Unknown theme — keep existing hardcoded :root values
989
990      // When block settings are enabled, the merchant controls colors via the
991      // theme editor. Skip the entire CSS mapping (theme vars + bridge) so
992      // block settings and :root defaults are used — matching pre-mapping behavior.
993      const blockSettingsEnabled = window.SwymStorefrontLayoutContext?.BlockSettingsEnabled || false;
994      if (blockSettingsEnabled) return;
995
996      const themeVars = family === 'dawn' ? getDawnThemeVariables() : getHorizonThemeVariables();
997      const bridgeVars = getBridgeVariables();
998
999      const style = document.createElement('style');
1000      style.setAttribute('data-swym-theme-mapping', family);
1001      style.textContent = themeVars + bridgeVars;
1002      document.head.appendChild(style);
1003    } catch (e) {
1004      // Silently fail — fallback to hardcoded :root values
1005    }
1006  }
1007
1008  return { inject, getThemeFamily };
1009})();
1010
1011/**
1012 * Defines action codes for various storefront layout events.
1013 */
1014SwymStorefrontLayoutExtensions.InstrumentActionCodes = {
1015  StorefrontLayoutInitialized: 701,
1016  StorefrontLayoutOpened: 702,
1017  StorefrontLayoutClosed: 703,
1018  StorefrontLayoutUserLogIn: 704,
1019  StorefrontLayoutCollectionRendered: 705,
1020  StorefrontLayoutWishlistItemsRendered: 706,
1021  StorefrontLayoutVariantChanged: 707,
1022  StorefrontLayoutItemAddedToCart: 708,
1023  StorefrontLayoutItemAddedToList: 709,
1024  StorefrontLayoutItemRemovedFromList: 710,
1025  StorefrontLayoutCollectionCreated: 711,
1026  StorefrontLayoutCollectionOpened: 712,
1027  StorefrontLayoutCollectionRenamed: 713,
1028  StorefrontLayoutCollectionDeleted: 714,
1029  StorefrontLayoutCollectionGridViewOpened: 715,
1030  StorefrontLayoutSFLInitialized: 716,
1031  StorefrontLayoutSFLItemsRendered: 717,
1032  StorefrontLayoutSFLItemAddedToList: 718,
1033  StorefrontLayoutSFLItemRemovedFromList: 719,
1034  StorefrontLayoutSFLItemMovedToCart: 720,
1035  StorefrontLayoutPageRendered: 721,
1036  StorefrontLayoutModalRendered: 722,
1037  StorefrontLayoutSideDrawerRendered: 723,
1038  // Saved For You
1039  StorefrontLayoutSFYTabViewed: 724,
1040  StorefrontLayoutSFYItemAddedToCart: 725,
1041  StorefrontLayoutSFYItemRemoved: 726,
1042  StorefrontLayoutSFYItemMovedToWishlist: 727,
1043  // AW Login Nudge
1044  StorefrontLayoutAWNudge1Shown: 728,
1045  StorefrontLayoutAWNudge1LoginClicked: 729,
1046  StorefrontLayoutAWNudge1Dismissed: 730,
1047  StorefrontLayoutAWNudge2Shown: 731,
1048  StorefrontLayoutAWNudge2LoginClicked: 732,
1049  StorefrontLayoutAWNudge2Dismissed: 733,
1050  // Explicit WL Login Nudge
1051  StorefrontLayoutExplicitNudge1Shown: 734,
1052  StorefrontLayoutExplicitNudge1LoginClicked: 735,
1053  StorefrontLayoutExplicitNudge1Dismissed: 736,
1054  StorefrontLayoutExplicitNudge2Shown: 737,
1055  StorefrontLayoutExplicitNudge2LoginClicked: 738,
1056  StorefrontLayoutExplicitNudge2Dismissed: 739,
1057  // Sign in with Shop
1058  StorefrontLayoutLoginNudgeShopLoginShown: 740,
1059  StorefrontLayoutWishlistUiShopLoginShown: 741,
1060  StorefrontLayoutLoginNudgeShopLoginSuccess: 742,
1061  StorefrontLayoutWishlistUiShopLoginSuccess: 743,
1062  // Add All To Cart
1063  StorefrontLayoutAddedAllToCart: 744,
1064  // Sign in with Shop (failure/fallback) — renumbered 744-748 -> 745-749, 744 collided
1065  // with the already-shipped Add All To Cart code above.
1066  StorefrontLayoutLoginNudgeShopLoginDeclined: 745,
1067  StorefrontLayoutWishlistUiShopLoginDeclined: 746,
1068  StorefrontLayoutLoginNudgeShopLoginFallback: 747,
1069  StorefrontLayoutWishlistUiShopLoginFallback: 748,
1070  StorefrontLayoutWishlistUiClassicLoginClicked: 749,
1071  // Education Layer
1072  EducationLayerToastShownCollections: 812,
1073  EducationLayerTooltipShownCollections: 813,
1074  EducationLayerTooltipDismissedCollections: 814,
1075  EducationLayerTooltipShownPDP: 815,
1076  EducationLayerTooltipDismissedPDP: 816,
1077  EducationLayerButtonTransitionShownPDP: 817,
1078  EducationLayerToastShownPDP: 818,
1079  EducationLayerToastCTAClicked: 819,
1080  EducationLayerSessionStopped: 820
1081};
1082
1083/**
1084 * Defines UTM terms for tracking user engagement and interactions.
1085 */
1086SwymStorefrontLayoutExtensions.InstrumentUtmTerms = {
1087  StorefrontLayoutUiEngagement: "storefront_layout_ui_engagement",
1088  StorefrontLayoutCollectionInteractions: "storefront_layout_collection_interactions",
1089  StorefrontLayoutItemInteractions: "storefront_layout_item_interactions",
1090  StorefrontLayoutCartConversion: "storefront_layout_cart_conversion",
1091  EducationLayerEngagement: "education",
1092  StorefrontLayoutAWLoginNudgeEngagement: "aw_login_nudge",
1093  StorefrontLayoutExplicitLoginNudgeEngagement: "explicit_login_nudge",
1094  StorefrontLayoutShopLoginNudgeEngagement: "nudge_shop_login_shown",
1095  StorefrontLayoutShopLoginWishlistUiEngagement: "wishlist_ui_shop_login_shown",
1096  StorefrontLayoutShopLoginNudgeSuccessEngagement: "nudge_shop_login_success",
1097  StorefrontLayoutShopLoginWishlistUiSuccessEngagement: "wishlist_ui_shop_login_success",
1098  StorefrontLayoutShopLoginNudgeDeclinedEngagement: "nudge_shop_login_declined",
1099  StorefrontLayoutShopLoginWishlistUiDeclinedEngagement: "wishlist_ui_shop_login_declined",
1100  StorefrontLayoutShopLoginNudgeFallbackEngagement: "nudge_shop_login_fallback",
1101  StorefrontLayoutShopLoginWishlistUiFallbackEngagement: "wishlist_ui_shop_login_fallback",
1102  StorefrontLayoutShopLoginWishlistUiClassicLoginClickedEngagement: "wishlist_ui_classic_login_clicked"
1103};
1104
1105if (typeof window !== 'undefined') {
1106  if (!window.SwymCallbacks) {
1107    window.SwymCallbacks = [];
1108  }
1109  
1110  let vsClosedListenerRegistered = false;
1111  
1112  window.SwymCallbacks.push(function(swat) {
1113    if (vsClosedListenerRegistered) return;
1114    vsClosedListenerRegistered = true;
1115    
1116    if (!swat || !swat.evtLayer) return;
1117    
1118    swat.evtLayer.addEventListener('sw:vs:closed', (e) => {
1119      const detail = e?.detail || {};
1120      const empi = detail.empi;
1121      const listId = detail.listId;
1122      
1123      if (!empi || !listId) return;
1124      
1125      const gridItem = window.SwymStorefrontLayoutExtensions?._vsActiveItem;
1126      if (gridItem && gridItem.item?.empi === empi && gridItem.list?.lid === listId) {
1127        if (!gridItem._variantConfirmed) {
1128          gridItem._variantConfirmed = true;
1129          gridItem.renderItem();
1130          gridItem.initItemElements();
1131          gridItem.addEventListeners();
1132        }
1133      }
1134      
1135      if (window.SwymStorefrontLayoutExtensions) {
1136        window.SwymStorefrontLayoutExtensions._vsActiveItem = null;
1137      }
1138    });
1139  });
1140}
1141
1142/**
1143 * SwymWishlistCore Component
1144 *
1145 * This component serves as the base class for Swym Wishlist Storefront Layout, 
1146 * providing the core functionality shared across different layout implementations:
1147 * - Drawer
1148 * - Page Section
1149 * - Modal
1150 *
1151 * Key Responsibilities:
1152 * - Initializes the UI and sets up event listeners for wishlist interactions.
1153 * - Handles fetching and rendering of wishlist items and collections.
1154 * - Monitors hash changes to update the UI accordingly.
1155 * - Integrates with Swym's API for wishlist actions and notifications.
1156 * - Provides a structured foundation for extending different storefront layout types.
1157 *
1158 * The component can be extended by specific layout implementations such as:
1159 * - `SwymStorefrontLayoutAsDrawer`
1160 * - `SwymStorefrontLayoutAsPageSection`
1161 * - `SwymStorefrontLayoutAsModal`
1162 */
1163class SwymWishlistCore extends HTMLElement {
1164  constructor() {
1165    super();
1166    this.elements = {};
1167    this.initUi();
1168  }
1169
1170  initUi(){
1171    this.setAttribute('id', 'swym-storefront-layout');
1172    // Inject theme-aware CSS variables (Dawn/Horizon) — runs once, no-op for unknown themes
1173    SwymStorefrontLayoutExtensions.ThemeCSSMapping.inject();
1174    window.addEventListener('hashchange', ()=>{
1175      this.checkForSwymDrawerHash();
1176    });
1177
1178    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.LayoutInitialized, () => {
1179      SwymStorefrontLayoutContext?.swat.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutInitialized, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
1180      this.checkForSwymDrawerHash();
1181      this.initElement();
1182      SwymStorefrontLayoutContext?.swat.evtLayer.addEventListener(SwymStorefrontLayoutContext?.swat.JSEvents.StringsLoaded, (event) => {
1183        this.loadStrings();
1184      });
1185
1186      // Handle race condition: StringsLoaded may have fired before LayoutInitialized
1187      // (e.g. after login redirect when UI bundle is cached). Check if locale strings
1188      // are already present in retailerSettings and load them immediately if so.
1189      // setTimeout(0) defers the call until after all LayoutInitialized listeners have
1190      // fired, so the Tabs component's _layoutInitHandler can set up SwymStorefrontLayoutContext.Tabs
1191      // before reRenderStorefrontLayoutUI() recreates the DOM.
1192      const retailerStrings = window._swat?.retailerSettings?.Strings || {};
1193      const stringsAlreadyLoaded = retailerStrings.ThemeAppStorefrontLayoutTitle || retailerStrings.ThemeAppStorefrontLayoutEmptyWishlistTitle;
1194      if (stringsAlreadyLoaded) {
1195        setTimeout(() => this.loadStrings(), 0);
1196      }
1197
1198      this.attachSwymEventListeners(SwymStorefrontLayoutContext.swat);
1199      this.instrumentLayoutType();
1200    });
1201
1202    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.WishlistFetched, () => {
1203      this.checkForSwymDrawerHash();
1204    })
1205  }
1206
1207  instrumentLayoutType(){
1208    let StorefrontLayoutType = SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType;
1209    if(StorefrontLayoutType === 'as-drawer'){
1210      SwymStorefrontLayoutContext?.swat.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutSideDrawerRendered, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
1211    }else if(StorefrontLayoutType === 'as-modal'){
1212      SwymStorefrontLayoutContext?.swat.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutModalRendered, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
1213    }else if(StorefrontLayoutType === 'as-section'){
1214      SwymStorefrontLayoutContext?.swat.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutPageRendered, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
1215    }
1216  }
1217
1218  reRenderStorefrontLayoutUI() {
1219    this.reRenderUI();
1220    this.initElement();
1221  }
1222
1223  initElement(){
1224
1225    SwymStorefrontLayoutExtensions.SwymStorefrontLayout = document.querySelector('swym-storefront-layout #swym-storefront-layout');
1226    SwymStorefrontLayoutExtensions.SwymStorefrontLayoutActions = document.querySelector('#swym-storefront-layout-actions') || document.querySelector('#swym-storefront-layout-actions-target-page');
1227    SwymStorefrontLayoutExtensions.SwymStorefrontLayoutActionTooltip = document.querySelector('#swym-storefront-layout-action-tooltip') || document.querySelector('#swym-storefront-layout-action-tooltip-target-page');
1228    SwymStorefrontLayoutExtensions.Notification = document.querySelector('swym-storefront-layout-notification');
1229    SwymStorefrontLayoutExtensions.collectionsListComponent = document.querySelector('swym-storefront-layout-collection-list');
1230
1231  }
1232
1233  loadStrings() {
1234    try {
1235      const RetailerStrings = window._swat?.retailerSettings?.Strings || {};
1236      const {
1237        ThemeAppStorefrontLayoutTitle,
1238
1239        ThemeAppStorefrontLayoutAddToCartCTA,
1240        ThemeAppStorefrontLayoutAddedToCartCTA,
1241        ThemeAppStorefrontLayoutAddAllToCartCTA,
1242        ThemeAppStorefrontLayoutAddAllToCartSuccessText,
1243        ThemeAppStorefrontLayoutAddAllToCartEmptyText,
1244        ThemeAppStorefrontLayoutAddAllToCartErrorText,
1245        ThemeAppStorefrontLayoutAddingToCartCTA,
1246        ThemeAppStorefrontLayoutSoldoutCTA,
1247        ThemeAppStorefrontLayoutViewCartCTA,
1248        ThemeAppStorefrontLayoutMoveToCartCTA,
1249        ThemeAppStorefrontLayoutMoveingToCartCTA,
1250        ThemeAppStorefrontLayoutRemoveSFLItemCTA,
1251
1252        ThemeAppStorefrontLayoutLoginHeading,
1253        ThemeAppStorefrontLayoutLoginMessage,
1254        ThemeAppStorefrontLayoutLoginButtonCTA,
1255        ThemeAppStorefrontLayoutLoggedUserWelcomeMessage,
1256
1257        ThemeAppStorefrontLayoutWishlistTitle,
1258        ThemeAppStorefrontLayoutWishlistInfo,
1259        ThemeAppStorefrontLayoutEmptyWishlistTitle,
1260        ThemeAppStorefrontLayoutEmptyWishlistDescription,
1261
1262        ThemeAppStorefrontLayoutCollectionsTitle,
1263        ThemeAppStorefrontLayoutEmptyCarouselCollectionsDescription,
1264        ThemeAppStorefrontLayoutEmptyCollectionsTitle,
1265        ThemeAppStorefrontLayoutEmptyCollectionsDescription,
1266
1267        ThemeAppStorefrontLayoutAddToCollectionsTitle,
1268        ThemeAppStorefrontLayoutAddToCollectionCTA,
1269        ThemeAppStorefrontLayoutCreateCollectionCTA,
1270        ThemeAppStorefrontLayoutSaveNewCollectionCTA,
1271        ThemeAppStorefrontLayoutRemoveItemCTA,
1272        ThemeAppStorefrontLayoutRenameCollectionCTA,
1273        ThemeAppStorefrontLayoutDeleteCollectionCTA,
1274        ThemeAppStorefrontLayoutShareCollectionCTA,
1275        ThemeAppStorefrontLayoutSaveCollectionCTA,
1276        ThemeAppStorefrontLayoutEditCollectionCTA,
1277        ThemeAppStorefrontLayoutShareCollectionTitle,
1278        ThemeAppStorefrontLayoutShareCollectionMessage,
1279        ThemeAppStorefrontLayoutSharedCollectionMessage,
1280        ThemeAppStorefrontLayoutUpdateCollectionTitle,
1281
1282        ThemeAppStorefrontLayoutErrorMessageListNameRequired,
1283        ThemeAppStorefrontLayoutErrorMessageListNameRequired3Char,
1284        ThemeAppStorefrontLayoutErrorMessageListNameAlreadyExist,
1285
1286        ThemeAppStorefrontLayoutNotificationMessageItemSaved,
1287        ThemeAppStorefrontLayoutNotificationMessageItemRemoved,
1288        ThemeAppStorefrontLayoutNotificationMessageAddedToCart,
1289        ThemeAppStorefrontLayoutNotificationMessageAddedToCollection,
1290        ThemeAppStorefrontLayoutNotificationMessageCollectionSaved,
1291        ThemeAppStorefrontLayoutNotificationMessageCollectionDeleted,
1292        ThemeAppStorefrontLayoutNotificationMessageCollectionUpdated,
1293        ThemeAppStorefrontLayoutNotificationMessageCollectionUnavailable,
1294        ThemeAppStorefrontLayoutNotificationMessageSFLItemSaved,
1295        ThemeAppStorefrontLayoutNotificationMessageSFLItemRemoved,
1296        ThemeAppStorefrontLayoutNotificationMessageMovedToCart,
1297
1298        ThemeAppStorefrontLayoutNotificationActionAddToCollection,
1299        ThemeAppStorefrontLayoutNotificationActionView,
1300        ThemeAppStorefrontLayoutNotificationActionViewCollection,
1301        ThemeAppStorefrontLayoutNotificationActionGoToCart,
1302
1303        ThemeAppStorefrontLayoutTextItem,
1304        ThemeAppStorefrontLayoutTextItems,
1305
1306        ThemeAppStorefrontLayoutTabWishlist,
1307        ThemeAppStorefrontLayoutTabSavedForLater,
1308        ThemeAppStorefrontLayoutSaveForLaterTitle,
1309        ThemeAppStorefrontLayoutEmptySavedForLaterTitle,
1310        ThemeAppStorefrontLayoutEmptySavedForLaterDescription,
1311        VariantSelectorBtnText,
1312
1313        ThemeAppStorefrontLayoutEmptySingleLoggedInTitle,
1314        ThemeAppStorefrontLayoutEmptySingleLoggedInDescription,
1315        ThemeAppStorefrontLayoutEmptySingleLoggedInBullet1,
1316        ThemeAppStorefrontLayoutEmptySingleLoggedInBullet2,
1317        ThemeAppStorefrontLayoutEmptySingleLoggedInBullet3,
1318        ThemeAppStorefrontLayoutEmptySingleLoggedInCTA,
1319
1320        ThemeAppStorefrontLayoutEmptyMultiLoggedInTitle,
1321        ThemeAppStorefrontLayoutEmptyMultiLoggedInDescription,
1322        ThemeAppStorefrontLayoutEmptyMultiLoggedInCreateTitle,
1323        ThemeAppStorefrontLayoutEmptyMultiLoggedInCreateDescription,
1324        ThemeAppStorefrontLayoutEmptyMultiLoggedInBrowseLabel,
1325        ThemeAppStorefrontLayoutEmptyMultiLoggedInCTA,
1326        ThemeAppStorefrontLayoutEmptyMultiLoggedInTag1,
1327        ThemeAppStorefrontLayoutEmptyMultiLoggedInTag2,
1328        ThemeAppStorefrontLayoutEmptyMultiLoggedInTag3,
1329        ThemeAppStorefrontLayoutEmptyMultiLoggedInTag4,
1330        ThemeAppStorefrontLayoutEmptyMultiLoggedInTag5,
1331
1332        ThemeAppStorefrontLayoutEmptyGuestTitle,
1333        ThemeAppStorefrontLayoutEmptyGuestDescription,
1334        ThemeAppStorefrontLayoutEmptyGuestSingleNotice,
1335        ThemeAppStorefrontLayoutEmptyGuestMultiNotice,
1336        ThemeAppStorefrontLayoutEmptyGuestLoginCTA,
1337        ThemeAppStorefrontLayoutEmptyGuestBrowseCTA,
1338        ThemeAppStorefrontLayoutEmptyGuestSignupText,
1339        ThemeAppStorefrontLayoutEmptyGuestSignupCTA,
1340
1341        ThemeAppStorefrontLayoutEmptySflTitle,
1342        ThemeAppStorefrontLayoutEmptySflDescription,
1343        ThemeAppStorefrontLayoutEmptySflStep1Title,
1344        ThemeAppStorefrontLayoutEmptySflStep1Description,
1345        ThemeAppStorefrontLayoutEmptySflStep2Title,
1346        ThemeAppStorefrontLayoutEmptySflStep2Description,
1347        ThemeAppStorefrontLayoutEmptySflLoggedInNotice,
1348        ThemeAppStorefrontLayoutEmptySflGuestNotice,
1349        ThemeAppStorefrontLayoutEmptySflGoToCartCTA,
1350        ThemeAppStorefrontLayoutEmptySflLoginCTA,
1351        ThemeAppStorefrontLayoutEmptySflSignupText,
1352        ThemeAppStorefrontLayoutEmptySflSignupCTA,
1353
1354        ThemeAppStorefrontLayoutTabSavedForYou,
1355
1356        // Drawer UI Polish — personalized titles and share footer (single wishlist mode)
1357        ThemeAppStorefrontLayoutPersonalizedTitle,
1358        ThemeAppStorefrontLayoutPersonalizedSfyTitle,
1359        ThemeAppStorefrontLayoutShareCTA,
1360        ThemeAppStorefrontLayoutShareThisListCTA,
1361        ThemeAppStorefrontLayoutLoginToSaveCTA,
1362
1363        // Auto-Wishlist login nudge strings (corner notification)
1364        ThemeAppStorefrontLayoutAwNudgeMessage,
1365        ThemeAppStorefrontLayoutAwNudgeMessageSub,
1366        ThemeAppStorefrontLayoutAwNudgeLoginCTA,
1367        ThemeAppStorefrontLayoutAwNudgeDismiss,
1368      } = RetailerStrings;
1369
1370      SwymStorefrontLayoutContext.Strings = {
1371        ...SwymStorefrontLayoutContext?.Strings,
1372        ...(ThemeAppStorefrontLayoutTitle ? { 'title': ThemeAppStorefrontLayoutTitle } : {}),
1373        ...(VariantSelectorBtnText ? { 'VariantSelectorBtnText': VariantSelectorBtnText } : {}),
1374        ...(ThemeAppStorefrontLayoutAddToCartCTA ? { 'addToCart': ThemeAppStorefrontLayoutAddToCartCTA } : {}),
1375        ...(ThemeAppStorefrontLayoutAddedToCartCTA ? { 'addedToCart': ThemeAppStorefrontLayoutAddedToCartCTA } : {}),
1376        addAllToCartCta: ThemeAppStorefrontLayoutAddAllToCartCTA || 'Add All To Cart',
1377        addAllToCartSuccessText: ThemeAppStorefrontLayoutAddAllToCartSuccessText || 'Successfully added {{addCount}} items to your cart.',
1378        addAllToCartEmptyText: ThemeAppStorefrontLayoutAddAllToCartEmptyText || 'There are no items that can be added to the cart.',
1379        addAllToCartErrorText: ThemeAppStorefrontLayoutAddAllToCartErrorText || 'Error adding all items to cart.',
1380        ...(ThemeAppStorefrontLayoutAddingToCartCTA ? { 'addingToCart': ThemeAppStorefrontLayoutAddingToCartCTA } : {}),
1381        ...(ThemeAppStorefrontLayoutSoldoutCTA ? { 'soldOut': ThemeAppStorefrontLayoutSoldoutCTA } : {}),
1382        ...(ThemeAppStorefrontLayoutViewCartCTA ? { 'viewCartCta': ThemeAppStorefrontLayoutViewCartCTA } : {}),
1383        ...(ThemeAppStorefrontLayoutMoveToCartCTA ? { 'moveToCartCta': ThemeAppStorefrontLayoutMoveToCartCTA } : {}),
1384        ...(ThemeAppStorefrontLayoutMoveingToCartCTA ? { 'movingToCartCta': ThemeAppStorefrontLayoutMoveingToCartCTA } : {}),
1385        ...(ThemeAppStorefrontLayoutRemoveSFLItemCTA ? { 'removeSflItemCta': ThemeAppStorefrontLayoutRemoveSFLItemCTA } : {}),
1386
1387        ...(ThemeAppStorefrontLayoutLoginHeading ? { 'loginHeading': ThemeAppStorefrontLayoutLoginHeading } : {}),
1388        ...(ThemeAppStorefrontLayoutLoginMessage ? { 'loginText': ThemeAppStorefrontLayoutLoginMessage } : {}),
1389        ...(ThemeAppStorefrontLayoutLoginButtonCTA ? { 'loginButtonText': ThemeAppStorefrontLayoutLoginButtonCTA } : {}),
1390        ...(ThemeAppStorefrontLayoutLoggedUserWelcomeMessage ? { 'loggedUserWelcomeMessage': ThemeAppStorefrontLayoutLoggedUserWelcomeMessage } : {}),
1391
1392        ...(ThemeAppStorefrontLayoutWishlistTitle ? { 'wishlistTitle': ThemeAppStorefrontLayoutWishlistTitle } : {}),
1393        ...(ThemeAppStorefrontLayoutWishlistInfo ? { 'wishlistInfo': ThemeAppStorefrontLayoutWishlistInfo } : {}),
1394        ...(ThemeAppStorefrontLayoutEmptyWishlistTitle ? { 'emptyWishlistTitle': ThemeAppStorefrontLayoutEmptyWishlistTitle } : {}),
1395        ...(ThemeAppStorefrontLayoutEmptyWishlistDescription ? { 'emptyWishlistDescription': ThemeAppStorefrontLayoutEmptyWishlistDescription } : {}),
1396
1397        ...(ThemeAppStorefrontLayoutCollectionsTitle ? { 'collectionTitle': ThemeAppStorefrontLayoutCollectionsTitle } : {}),
1398        ...(ThemeAppStorefrontLayoutEmptyCarouselCollectionsDescription ? { 'emptyCarouselCollectionText': ThemeAppStorefrontLayoutEmptyCarouselCollectionsDescription } : {}),
1399        ...(ThemeAppStorefrontLayoutEmptyCollectionsTitle ? { 'emptyCollectionText': ThemeAppStorefrontLayoutEmptyCollectionsTitle } : {}),
1400        ...(ThemeAppStorefrontLayoutEmptyCollectionsDescription ? { 'emptyCollectionDescription': ThemeAppStorefrontLayoutEmptyCollectionsDescription } : {}),
1401
1402        ...(ThemeAppStorefrontLayoutAddToCollectionsTitle ? { 'addToCollectionTitle': ThemeAppStorefrontLayoutAddToCollectionsTitle } : {}),
1403        ...(ThemeAppStorefrontLayoutAddToCollectionCTA ? { 'addToCollectionCta': ThemeAppStorefrontLayoutAddToCollectionCTA } : {}),
1404        ...(ThemeAppStorefrontLayoutCreateCollectionCTA ? { 'createCollectionCta': ThemeAppStorefrontLayoutCreateCollectionCTA } : {}),
1405        ...(ThemeAppStorefrontLayoutSaveNewCollectionCTA ? { 'saveNewCollectionCta': ThemeAppStorefrontLayoutSaveNewCollectionCTA } : {}),
1406        ...(ThemeAppStorefrontLayoutRemoveItemCTA ? { 'removeItemCta': ThemeAppStorefrontLayoutRemoveItemCTA } : {}),
1407        ...(ThemeAppStorefrontLayoutRenameCollectionCTA ? { 'renameCollectionCta': ThemeAppStorefrontLayoutRenameCollectionCTA } : {}),
1408        ...(ThemeAppStorefrontLayoutDeleteCollectionCTA ? { 'deleteCollectionCta': ThemeAppStorefrontLayoutDeleteCollectionCTA } : {}),
1409        ...(ThemeAppStorefrontLayoutShareCollectionCTA ? { 'shareCollectionCta': ThemeAppStorefrontLayoutShareCollectionCTA } : {}),
1410        ...(ThemeAppStorefrontLayoutSaveCollectionCTA ? { 'saveCollectionCta': ThemeAppStorefrontLayoutSaveCollectionCTA } : {}),
1411        ...(ThemeAppStorefrontLayoutEditCollectionCTA ? { 'editCollectionCta': ThemeAppStorefrontLayoutEditCollectionCTA } : {}),
1412        ...(ThemeAppStorefrontLayoutShareCollectionTitle ? { 'shareCollectionTitle': ThemeAppStorefrontLayoutShareCollectionTitle } : {}),
1413        ...(ThemeAppStorefrontLayoutShareCollectionMessage ? { 'shareCollectionMessage': ThemeAppStorefrontLayoutShareCollectionMessage } : {}),
1414        ...(ThemeAppStorefrontLayoutSharedCollectionMessage ? { 'sharedCollectionMessage': ThemeAppStorefrontLayoutSharedCollectionMessage } : {}),
1415        ...(ThemeAppStorefrontLayoutUpdateCollectionTitle ? { 'updateCollectionTitle': ThemeAppStorefrontLayoutUpdateCollectionTitle } : {}),
1416
1417        ...(ThemeAppStorefrontLayoutErrorMessageListNameRequired ? { 'errorMessageListNameRequired': ThemeAppStorefrontLayoutErrorMessageListNameRequired } : {}),
1418        ...(ThemeAppStorefrontLayoutErrorMessageListNameRequired3Char ? { 'errorMessageListNameRequire3Char': ThemeAppStorefrontLayoutErrorMessageListNameRequired3Char } : {}),
1419        ...(ThemeAppStorefrontLayoutErrorMessageListNameAlreadyExist ? { 'errorMessageListNameAlreadyExist': ThemeAppStorefrontLayoutErrorMessageListNameAlreadyExist } : {}),
1420
1421        ...(ThemeAppStorefrontLayoutNotificationMessageItemSaved ? { 'notificationMessageItemSaved': ThemeAppStorefrontLayoutNotificationMessageItemSaved } : {}),
1422        ...(ThemeAppStorefrontLayoutNotificationMessageItemRemoved ? { 'notificationMessageItemRemoved': ThemeAppStorefrontLayoutNotificationMessageItemRemoved } : {}),
1423        ...(ThemeAppStorefrontLayoutNotificationMessageAddedToCart ? { 'notificationMessageAddedToCart': ThemeAppStorefrontLayoutNotificationMessageAddedToCart } : {}),
1424        ...(ThemeAppStorefrontLayoutNotificationMessageAddedToCollection ? { 'notificationMessageAddedToCollection': ThemeAppStorefrontLayoutNotificationMessageAddedToCollection } : {}),
1425        ...(ThemeAppStorefrontLayoutNotificationMessageCollectionSaved ? { 'notificationMessageCollectionSaved': ThemeAppStorefrontLayoutNotificationMessageCollectionSaved } : {}),
1426        ...(ThemeAppStorefrontLayoutNotificationMessageCollectionDeleted ? { 'notificationMessageCollectionDeleted': ThemeAppStorefrontLayoutNotificationMessageCollectionDeleted } : {}),
1427        ...(ThemeAppStorefrontLayoutNotificationMessageCollectionUpdated ? { 'notificationMessageCollectionUpdated': ThemeAppStorefrontLayoutNotificationMessageCollectionUpdated } : {}),
1428        ...(ThemeAppStorefrontLayoutNotificationMessageCollectionUnavailable ? { 'notificationMessageCollectionUnavailable': ThemeAppStorefrontLayoutNotificationMessageCollectionUnavailable } : {}),
1429        ...(ThemeAppStorefrontLayoutNotificationMessageSFLItemSaved ? { 'notificationMessageSFLItemSaved': ThemeAppStorefrontLayoutNotificationMessageSFLItemSaved } : {}),
1430        ...(ThemeAppStorefrontLayoutNotificationMessageSFLItemRemoved ? { 'notificationMessageSFLItemRemoved': ThemeAppStorefrontLayoutNotificationMessageSFLItemRemoved } : {}),
1431        ...(ThemeAppStorefrontLayoutNotificationMessageMovedToCart ? { 'notificationMessageMovedToCart': ThemeAppStorefrontLayoutNotificationMessageMovedToCart } : {}),
1432        
1433        ...(ThemeAppStorefrontLayoutNotificationActionAddToCollection ? { 'notificationActionAddToCollection': ThemeAppStorefrontLayoutNotificationActionAddToCollection } : {}),
1434        ...(ThemeAppStorefrontLayoutNotificationActionView ? { 'notificationActionView': ThemeAppStorefrontLayoutNotificationActionView } : {}),
1435        ...(ThemeAppStorefrontLayoutNotificationActionViewCollection ? { 'notificationActionViewCollection': ThemeAppStorefrontLayoutNotificationActionViewCollection } : {}),
1436        ...(ThemeAppStorefrontLayoutNotificationActionGoToCart ? { 'notificationActionGoToCart': ThemeAppStorefrontLayoutNotificationActionGoToCart } : {}),
1437
1438        ...(ThemeAppStorefrontLayoutTextItem ? { 'item': ThemeAppStorefrontLayoutTextItem } : {}),
1439        ...(ThemeAppStorefrontLayoutTextItems ? { 'items': ThemeAppStorefrontLayoutTextItems } : {}),
1440        
1441        ...(ThemeAppStorefrontLayoutTabWishlist ? { 'tabWishlist': ThemeAppStorefrontLayoutTabWishlist } : {}),
1442        ...(ThemeAppStorefrontLayoutTabSavedForLater ? { 'tabSavedForLater': ThemeAppStorefrontLayoutTabSavedForLater } : {}),
1443        tabSavedForYou: ThemeAppStorefrontLayoutTabSavedForYou || RetailerStrings?.AutoWishlistedTabText || 'Saved For You',
1444        ...(ThemeAppStorefrontLayoutSaveForLaterTitle ? { 'savedForLaterTitle': ThemeAppStorefrontLayoutSaveForLaterTitle } : {}),
1445        ...(ThemeAppStorefrontLayoutEmptySavedForLaterTitle ? { 'emptySavedForLaterTitle': ThemeAppStorefrontLayoutEmptySavedForLaterTitle } : {}),
1446        ...(ThemeAppStorefrontLayoutEmptySavedForLaterDescription ? { 'emptySavedForLaterDescription': ThemeAppStorefrontLayoutEmptySavedForLaterDescription } : {}),
1447
1448        ...(ThemeAppStorefrontLayoutEmptySingleLoggedInTitle ? { 'emptySingleLoggedInTitle': ThemeAppStorefrontLayoutEmptySingleLoggedInTitle } : {}),
1449        ...(ThemeAppStorefrontLayoutEmptySingleLoggedInDescription ? { 'emptySingleLoggedInDescription': ThemeAppStorefrontLayoutEmptySingleLoggedInDescription } : {}),
1450        ...(ThemeAppStorefrontLayoutEmptySingleLoggedInBullet1 ? { 'emptySingleLoggedInBullet1': ThemeAppStorefrontLayoutEmptySingleLoggedInBullet1 } : {}),
1451        ...(ThemeAppStorefrontLayoutEmptySingleLoggedInBullet2 ? { 'emptySingleLoggedInBullet2': ThemeAppStorefrontLayoutEmptySingleLoggedInBullet2 } : {}),
1452        ...(ThemeAppStorefrontLayoutEmptySingleLoggedInBullet3 ? { 'emptySingleLoggedInBullet3': ThemeAppStorefrontLayoutEmptySingleLoggedInBullet3 } : {}),
1453        ...(ThemeAppStorefrontLayoutEmptySingleLoggedInCTA ? { 'emptySingleLoggedInCTA': ThemeAppStorefrontLayoutEmptySingleLoggedInCTA } : {}),
1454
1455        ...(ThemeAppStorefrontLayoutEmptyMultiLoggedInTitle ? { 'emptyMultiLoggedInTitle': ThemeAppStorefrontLayoutEmptyMultiLoggedInTitle } : {}),
1456        ...(ThemeAppStorefrontLayoutEmptyMultiLoggedInDescription ? { 'emptyMultiLoggedInDescription': ThemeAppStorefrontLayoutEmptyMultiLoggedInDescription } : {}),
1457        ...(ThemeAppStorefrontLayoutEmptyMultiLoggedInCreateTitle ? { 'emptyMultiLoggedInCreateTitle': ThemeAppStorefrontLayoutEmptyMultiLoggedInCreateTitle } : {}),
1458        ...(ThemeAppStorefrontLayoutEmptyMultiLoggedInCreateDescription ? { 'emptyMultiLoggedInCreateDescription': ThemeAppStorefrontLayoutEmptyMultiLoggedInCreateDescription } : {}),
1459        ...(ThemeAppStorefrontLayoutEmptyMultiLoggedInBrowseLabel ? { 'emptyMultiLoggedInBrowseLabel': ThemeAppStorefrontLayoutEmptyMultiLoggedInBrowseLabel } : {}),
1460        ...(ThemeAppStorefrontLayoutEmptyMultiLoggedInCTA ? { 'emptyMultiLoggedInCTA': ThemeAppStorefrontLayoutEmptyMultiLoggedInCTA } : {}),
1461        ...(ThemeAppStorefrontLayoutEmptyMultiLoggedInTag1 ? { 'emptyMultiLoggedInTag1': ThemeAppStorefrontLayoutEmptyMultiLoggedInTag1 } : {}),
1462        ...(ThemeAppStorefrontLayoutEmptyMultiLoggedInTag2 ? { 'emptyMultiLoggedInTag2': ThemeAppStorefrontLayoutEmptyMultiLoggedInTag2 } : {}),
1463        ...(ThemeAppStorefrontLayoutEmptyMultiLoggedInTag3 ? { 'emptyMultiLoggedInTag3': ThemeAppStorefrontLayoutEmptyMultiLoggedInTag3 } : {}),
1464        ...(ThemeAppStorefrontLayoutEmptyMultiLoggedInTag4 ? { 'emptyMultiLoggedInTag4': ThemeAppStorefrontLayoutEmptyMultiLoggedInTag4 } : {}),
1465        ...(ThemeAppStorefrontLayoutEmptyMultiLoggedInTag5 ? { 'emptyMultiLoggedInTag5': ThemeAppStorefrontLayoutEmptyMultiLoggedInTag5 } : {}),
1466
1467        ...(ThemeAppStorefrontLayoutEmptyGuestTitle ? { 'emptyGuestTitle': ThemeAppStorefrontLayoutEmptyGuestTitle } : {}),
1468        ...(ThemeAppStorefrontLayoutEmptyGuestDescription ? { 'emptyGuestDescription': ThemeAppStorefrontLayoutEmptyGuestDescription } : {}),
1469        ...(ThemeAppStorefrontLayoutEmptyGuestSingleNotice ? { 'emptyGuestSingleNotice': ThemeAppStorefrontLayoutEmptyGuestSingleNotice } : {}),
1470        ...(ThemeAppStorefrontLayoutEmptyGuestMultiNotice ? { 'emptyGuestMultiNotice': ThemeAppStorefrontLayoutEmptyGuestMultiNotice } : {}),
1471        ...(ThemeAppStorefrontLayoutEmptyGuestLoginCTA ? { 'emptyGuestLoginCTA': ThemeAppStorefrontLayoutEmptyGuestLoginCTA } : {}),
1472        ...(ThemeAppStorefrontLayoutEmptyGuestBrowseCTA ? { 'emptyGuestBrowseCTA': ThemeAppStorefrontLayoutEmptyGuestBrowseCTA } : {}),
1473        ...(ThemeAppStorefrontLayoutEmptyGuestSignupText ? { 'emptyGuestSignupText': ThemeAppStorefrontLayoutEmptyGuestSignupText } : {}),
1474        ...(ThemeAppStorefrontLayoutEmptyGuestSignupCTA ? { 'emptyGuestSignupCTA': ThemeAppStorefrontLayoutEmptyGuestSignupCTA } : {}),
1475
1476        ...(ThemeAppStorefrontLayoutEmptySflTitle ? { 'emptySflTitle': ThemeAppStorefrontLayoutEmptySflTitle } : {}),
1477        ...(ThemeAppStorefrontLayoutEmptySflDescription ? { 'emptySflDescription': ThemeAppStorefrontLayoutEmptySflDescription } : {}),
1478        ...(ThemeAppStorefrontLayoutEmptySflStep1Title ? { 'emptySflStep1Title': ThemeAppStorefrontLayoutEmptySflStep1Title } : {}),
1479        ...(ThemeAppStorefrontLayoutEmptySflStep1Description ? { 'emptySflStep1Description': ThemeAppStorefrontLayoutEmptySflStep1Description } : {}),
1480        ...(ThemeAppStorefrontLayoutEmptySflStep2Title ? { 'emptySflStep2Title': ThemeAppStorefrontLayoutEmptySflStep2Title } : {}),
1481        ...(ThemeAppStorefrontLayoutEmptySflStep2Description ? { 'emptySflStep2Description': ThemeAppStorefrontLayoutEmptySflStep2Description } : {}),
1482        ...(ThemeAppStorefrontLayoutEmptySflLoggedInNotice ? { 'emptySflLoggedInNotice': ThemeAppStorefrontLayoutEmptySflLoggedInNotice } : {}),
1483        ...(ThemeAppStorefrontLayoutEmptySflGuestNotice ? { 'emptySflGuestNotice': ThemeAppStorefrontLayoutEmptySflGuestNotice } : {}),
1484        ...(ThemeAppStorefrontLayoutEmptySflGoToCartCTA ? { 'emptySflGoToCartCTA': ThemeAppStorefrontLayoutEmptySflGoToCartCTA } : {}),
1485        ...(ThemeAppStorefrontLayoutEmptySflLoginCTA ? { 'emptySflLoginCTA': ThemeAppStorefrontLayoutEmptySflLoginCTA } : {}),
1486        ...(ThemeAppStorefrontLayoutEmptySflSignupText ? { 'emptySflSignupText': ThemeAppStorefrontLayoutEmptySflSignupText } : {}),
1487        ...(ThemeAppStorefrontLayoutEmptySflSignupCTA ? { 'emptySflSignupCTA': ThemeAppStorefrontLayoutEmptySflSignupCTA } : {}),
1488
1489        // Auto-Wishlist login nudge strings
1490        // Fallback chain: merchant Liquid override → SDK locale strings (strings/*.js via retailerSettings) → empty string
1491        awNudgeMessage: ThemeAppStorefrontLayoutAwNudgeMessage || RetailerStrings?.ThemeAppStorefrontLayoutAwNudgeMessage || '',
1492        awNudgeMessageSub: ThemeAppStorefrontLayoutAwNudgeMessageSub || RetailerStrings?.ThemeAppStorefrontLayoutAwNudgeMessageSub || '',
1493        awNudgeLoginCTA: ThemeAppStorefrontLayoutAwNudgeLoginCTA || RetailerStrings?.ThemeAppStorefrontLayoutAwNudgeLoginCTA || '',
1494        awNudgeDismiss: ThemeAppStorefrontLayoutAwNudgeDismiss || RetailerStrings?.ThemeAppStorefrontLayoutAwNudgeDismiss || '',
1495        // Explicit WL login nudge — only bold message differs; sub-message, CTA and dismiss reuse AW strings
1496        explicitNudgeMessage: RetailerStrings?.ThemeAppStorefrontLayoutExplicitNudgeMessage || '',
1497
1498        // Drawer UI Polish — personalized titles and share footer
1499        personalizedTitle: ThemeAppStorefrontLayoutPersonalizedTitle || RetailerStrings?.ThemeAppStorefrontLayoutPersonalizedTitle || "{{name}}'s Wishlist",
1500        personalizedSfyTitle: ThemeAppStorefrontLayoutPersonalizedSfyTitle || RetailerStrings?.ThemeAppStorefrontLayoutPersonalizedSfyTitle || 'Saved For {{name}}',
1501        shareCta: ThemeAppStorefrontLayoutShareCTA || RetailerStrings?.ThemeAppStorefrontLayoutShareCTA || 'Share',
1502        shareThisListCta: ThemeAppStorefrontLayoutShareThisListCTA || RetailerStrings?.ThemeAppStorefrontLayoutShareThisListCTA || 'Share This List',
1503        loginToSaveCta: ThemeAppStorefrontLayoutLoginToSaveCTA || RetailerStrings?.ThemeAppStorefrontLayoutLoginToSaveCTA || 'Login to Save',
1504
1505      }
1506      SwymStorefrontLayoutContext.stringsLoaded = true;
1507      this.reRenderStorefrontLayoutUI();
1508    } catch (error) {
1509      window._swat?.utils.error(error);
1510    }
1511  }
1512
1513  async checkForSwymDrawerHash() {
1514    const { StorefrontLayoutType, StorefrontLayoutAsSectionPageURL } = SwymStorefrontLayoutContext?.Settings;
1515    const currentHash = window.location.hash;
1516    const swymOpenParam = new URLSearchParams(window.location.search).get('swymOpen');
1517    const shouldOpenFromQuery = swymOpenParam === 'wishlist';
1518
1519    if(!SwymStorefrontLayoutExtensions.SwymStorefrontLayout){
1520      SwymStorefrontLayoutExtensions.SwymStorefrontLayout = document.querySelector('swym-storefront-layout #swym-storefront-layout');
1521    }
1522
1523    if(!currentHash && !shouldOpenFromQuery && SwymStorefrontLayoutExtensions.SwymStorefrontLayout?.isOpen){
1524      SwymStorefrontLayoutExtensions.SwymStorefrontLayout?.close?.();
1525      return;
1526    }
1527
1528    const openWishlistPage = () => {
1529        if (StorefrontLayoutType === 'as-drawer' || StorefrontLayoutType === 'as-modal') {
1530            SwymStorefrontLayoutExtensions?.SwymStorefrontLayout?.open();
1531        } else if (StorefrontLayoutType === 'as-section') {
1532          const normalize = s => s.replace(/\/+$/, '');
1533          const ensureLeadingSlash = s => (s?.startsWith('/') ? s : `/${s || ''}`);
1534          const localeRoot = window.Shopify?.routes?.root || '/';
1535          const formattedLocale = localeRoot === '/' ? '' : localeRoot.replace(/\/$/, '');
1536          const sectionPath = ensureLeadingSlash(StorefrontLayoutAsSectionPageURL);
1537          const expected = normalize(`${formattedLocale}${sectionPath}`);
1538          const current = normalize(window.location.pathname);
1539          
1540          if (current !== expected) {
1541            const redirectUrl = `${window.location.origin}${formattedLocale}${sectionPath}${window.location.search}`;
1542            window.location.replace(redirectUrl);
1543          }
1544        }
1545    };
1546
1547    if (currentHash === SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.List || shouldOpenFromQuery) {
1548      SwymStorefrontLayoutExtensions?.collectionsListComponent?.closeCollectinListView();
1549        openWishlistPage();
1550    } else if (currentHash.startsWith(SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.CollectionList)) {
1551        const collectionId = currentHash.slice(SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.CollectionList.length);
1552
1553        if (collectionId && SwymStorefrontLayoutContext?.collections) {
1554            const selectedCollection = SwymStorefrontLayoutContext?.collections?.find(collection => collection.lid === collectionId);
1555
1556            if (selectedCollection) {
1557              const { shouldShowMultiple, canCreateLists } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
1558              SwymStorefrontLayoutExtensions?.collectionsListComponent?.setData({
1559                list: selectedCollection,
1560                collections: SwymStorefrontLayoutContext?.collections,
1561                canCreateLists: canCreateLists,
1562                shouldShowMultiple: shouldShowMultiple
1563              });
1564              SwymStorefrontLayoutExtensions?.collectionsListComponent?.openCollectionListView();
1565            } else {
1566              try{
1567                const sharedListDetails = await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.fetchListDetails(collectionId);
1568                if(sharedListDetails?.list){
1569                  let [list] = await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.fetchProductDataForLists([sharedListDetails.list], true) || [];
1570                  if(list){
1571                    const { shouldShowMultiple, canCreateLists } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
1572                    SwymStorefrontLayoutExtensions?.collectionsListComponent?.setData({
1573                      list,
1574                      collections: SwymStorefrontLayoutContext?.collections,
1575                      canCreateLists: canCreateLists,
1576                      shouldShowMultiple: shouldShowMultiple
1577                    });
1578                    SwymStorefrontLayoutExtensions?.collectionsListComponent?.openCollectionListView();
1579                  }else{
1580                    throw 'Failed to get product data for shared list';
1581                  }
1582                }else{
1583                  throw 'Collection Not Available';
1584                }
1585              }catch(e){
1586                SwymStorefrontLayoutExtensions?.Notification?.setMessage({
1587                  message: SwymStorefrontLayoutContext?.Strings?.notificationMessageCollectionUnavailable,
1588                  status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Error,
1589                  duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration
1590                });
1591                window._swat?.utils.error(`Collection detail not found for ID: ${collectionId}. It may have been deleted or is unavailable.`,e);
1592              }
1593            }
1594
1595            openWishlistPage();
1596        }
1597    }
1598  }
1599
1600    /**
1601   * Attaches event listeners to Swym's event layer for handling various storefront layout interactions.
1602   * 
1603   * Key Features:
1604   * - Refreshes the wishlist and save-for-later (SFL) lists when customer information is updated.
1605   * - Handles events for adding and removing items from the wishlist and SFL.
1606   * - Displays notifications for user actions such as adding to wishlist, remov
1606ing items, or moving items to the cart.
1607   * - Tracks user interactions using Swym's instrumentation for analytics.
1608   * - Supports multi-list and collection features based on retailer settings.
1609   * 
1610   * Events Handled:
1611   * - `customerInfoRefreshed`: Refreshes wishlist and SFL lists.
1612   * - `addedToWishlist`: Updates the wishlist and displays a notification when an item is added.
1613   * - `removedFromWishlist`: Updates the wishlist and displays a notification when an item is removed.
1614   * - `addedToSFL`: Updates the SFL list and displays a notification when an item is added.
1615   * - `removedFromSFL`: Updates the SFL list and displays a notification when an item is removed.
1616   * - `movedToCartFromSFL`: Refreshes the SFL list when an item is moved to the cart.
1617   * 
1618   * Dependencies:
1619   * - SwymStorefrontLayoutExtensions: Provides methods for refreshing lists and managing notifications.
1620   * - SwymStorefrontLayoutContext: Provides context for settings, strings, and instrumentation codes.
1621   * - Swym's event layer (`swat.evtLayer`): Listens for and triggers events.
1622   */
1623  
1624  attachSwymEventListeners(swat) {
1625
1626    swat?.evtLayer?.addEventListener(swat?.JSEvents?.customerInfoRefreshed, ()=>{
1627      SwymStorefrontLayoutExtensions?.refreshWishList();
1628      if(window._swat?.retailerSettings?.SFL?.SFLFeatureEnabled){
1629        SwymStorefrontLayoutExtensions?.refreshSFLList();
1630      }
1631    })
1632
1633    //Wishlist Events 
1634    swat?.evtLayer?.addEventListener(swat?.JSEvents?.addedToWishlist, 
1634(event) => {
1635      if (SwymStorefrontLayoutContext._sfyMoveToWishlist) return;
1636      SwymStorefrontLayoutExtensions?.refreshWishList();
1637
1638      let image = event?.detail?.d?.iu || null;
1639      let { epi, empi } = event?.detail?.d || {};
1640      let product = event?.detail.d;
1641      
1642      const { shouldShowMultiple, canCreateLists } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
1643      
1644      swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutItemAddedToList, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutItemInteractions, epi, empi });
1645        if(SwymStorefrontLayoutContext?.swat?.ui?.uiRef?.settings?.UI?.WishlistShowNotification && !SwymStorefrontLayoutContext.CommonAddtoWL){
1646          SwymStorefrontLayoutExtensions?.Notification?.setMessage({
1647            message: SwymStorefrontLayoutContext?.Strings?.notificationMessageItemSaved,
1648            status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Neutral,
1649            actionType: SwymStorefrontLayoutContext?.NotificationActionTypes.AddedToWishlist,
1650            duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
1651            product,
1652            image
1653          },{
1654            showImage: true,
1655            showProgress: true
1656          });
1657    
1658          setTimeout(()=>{
1659                if(SwymStorefrontLayoutExtensions?.Notification?.notificationData?.actionType === SwymStorefrontLayoutContext?.NotificationActionTypes?.AddedToWishlist){
1660                  SwymStorefrontLayoutExtensions?.Notification?.setMessage({
1661                    status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Neutral,
1662                    actionType: SwymStorefrontLayoutContext?.NotificationActionTypes.AddedToWishlist,
1663                    duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
1664                    product,
1665                    image,
1666                    action: {
1667                        label: canCreateLists ? SwymStorefrontLayoutContext?.Strings?.notificationActionAddToCollection : SwymStorefrontLayoutContext?.Strings?.notificationActionView,
1668                        onClick: () => {
1669                          if(canCreateLists){
1670                            SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutPageActions?.setData({
1671                              listId: SwymStorefrontLayoutContext?.DefaultList?.lid,
1672                              list: SwymStorefrontLayoutContext?.DefaultList,
1673                              item: product,
1674                              collections: SwymStorefrontLayoutContext?.collections,
1675                              actionType: SwymStorefrontLayoutContext?.ActionTypes.AddToCollection
1676                            });
1677                            SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutPageActions?.openDrawer();
1678                          }else{
1679                            window.location.hash = SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.List; 
1680                          }
1681                        }
1682                    }
1683                  },{
1684                    showImage: true,
1685                    showActionButton: true,
1686                    showTitle: true
1687                  });
1688                }
1689          },3000);
1690        }
1691      if(SwymStorefrontLayoutContext.CommonAddtoWL && !SwymStorefrontLayoutContext.CommonRemovefromWL) {
1692        SwymStorefrontLayoutExtensions?.Notification?.setMessage({
1693            message: SwymStorefrontLayoutContext?.Strings?.notificationMessageItemSaved,
1694            status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Neutral,
1695            actionType: SwymStorefrontLayoutContext?.NotificationActionTypes.AddedToWishlist,
1696            duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
1697            product,
1698            image
1699          },{
1700            showImage: true,
1701            showProgress: true
1702          });
1703        SwymStorefrontLayoutContext.CommonAddtoWL = false  
1704
1705        setTimeout(() => {
1706          SwymStorefrontLayoutExtensions?.Notification?.setMessage({
1707                    status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Neutral,
1708                    actionType: SwymStorefrontLayoutContext?.NotificationActionTypes.AddedToWishlist,
1709                    duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
1710                    product,
1711                    image,
1712                    action: {
1713                        label: SwymStorefrontLayoutContext?.Strings?.notificationActionView,
1714                        onClick: () => {
1715                         _swat.ui.open();
1716                        }
1717                    }
1718                  },{
1719                    showImage: true,
1720                    showActionButton: true,
1721                    showTitle: true
1722                  });
1723        }, 3000)
1724      }
1725    });
1726
1727    swat?.evtLayer?.addEventListener(swat?.JSEvents?.removedFromWishlist, (event) => {
1728      if (SwymStorefrontLayoutContext._sfyMoveToWishlist) return;
1729
1730      let image = event?.detail?.d?.iu || null;
1731      let { epi, empi } = event?.detail?.d || {};
1732      const product = event?.detail.d;
1733      if( epi && empi){
1734        // Use the new helper to determine behavior
1735        const { shouldShowMultiple, canCreateLists } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
1736        
1737        // If showing multiple lists (either feature enabled OR multiple lists exist), do a full refresh
1738        if (shouldShowMultiple) {
1739          SwymStorefrontLayoutExtensions?.refreshWishList();
1740        } else {
1741          // Single wishlist: Update local state instead of refetching to avoid price double-formatting issue
1742          if (SwymStorefrontLayoutContext.DefaultList) {
1743            SwymStorefrontLayoutContext.DefaultList.listcontents = 
1744              (SwymStorefrontLayoutContext.DefaultList.listcontents || []).filter(item => item.epi !== epi);
1745          }
1746          if (SwymStorefrontLayoutContext.collections) {
1747            SwymStorefrontLayoutContext.collections = (SwymStorefrontLayoutContext.collections || []).map(list => ({
1748              ...list,
1749              listcontents: (list.listcontents || []).filter(item => item.epi !== epi)
1750            }));
1751          }
1752          if (SwymStorefrontLayoutContext.lists) {
1753            SwymStorefrontLayoutContext.lists = (SwymStorefrontLayoutContext.lists || []).map(list => ({
1754              ...list,
1755              listcontents: (list.listcontents || []).filter(item => item.epi !== epi)
1756            }));
1757          }
1758          
1759          // Dispatch WishlistFetched event to update UI components
1760          if(SwymStorefrontLayoutContext?.CustomEvents?.WishlistFetched){
1761            var wishlistFetchedEvent = new CustomEvent(SwymStorefrontLayoutContext.CustomEvents.WishlistFetched, {
1762              detail: { 
1763                defaultList: SwymStorefrontLayoutContext.DefaultList, 
1764                collections: SwymStorefrontLayoutContext.collections, 
1765                lists: SwymStorefrontLayoutContext.lists 
1766              }
1767            });
1768            document.dispatchEvent(wishlistFetchedEvent);
1769          }
1770        }
1771        
1772        swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutItemRemovedFromList, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutItemInteractions, epi, empi }); 
1773      }
1774      if((SwymStorefrontLayoutContext.CommonRemovefromWL && SwymStorefrontLayoutContext.CommonAddtoWL) || SwymStorefrontLayoutContext.CommonRemovefromWL) {
1775          if(SwymStorefrontLayoutContext.CommonRemovefromWL && !SwymStorefrontLayoutContext.CommonAddtoWL) {
1776            SwymStorefrontLayoutExtensions?.Notification?.setMessage({
1777              message: SwymStorefrontLayoutContext?.Strings?.notificationMessageItemRemoved,
1778              status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Toast,
1779              duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
1780              image
1781            });        
1782            SwymStorefrontLayoutContext.CommonRemovefromWL = false;
1783            setTimeout(() => {
1784              SwymStorefrontLayoutExtensions?.Notification?.setMessage({
1785                status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Neutral,
1786                actionType: SwymStorefrontLayoutContext?.NotificationActionTypes.AddedToWishlist,
1787                duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
1788                product,
1789                image,
1790                action: {
1791                    label: SwymStorefrontLayoutContext?.Strings?.notificationActionView,
1792                    onClick: () => {
1793                    _swat.ui.open();
1794                    }
1795                }
1796              },{
1797                showImage: true,
1798                showActionButton: true,
1799                showTitle: true
1800              });
1801            }, 3000)
1802        }
1803        return
1804      }
1805      SwymStorefrontLayoutExtensions?.Notification?.setMessage({
1806          message: SwymStorefrontLayoutContext?.Strings?.notificationMessageItemRemoved,
1807          status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Toast,
1808          duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
1809          image
1810        });
1811    });
1812
1813    //SFL Events 
1814    if(window._swat?.retailerSettings?.SFL?.SFLFeatureEnabled){
1815      swat.evtLayer.addEventListener(swat.JSEvents.addedToSFL, (event) => {
1816        let image = event?.detail?.d?.iu || null;
1817        let title = event?.detail?.d?.dt || null;
1818        let { epi, empi } = event?.detail?.d || {};
1819        window._swat.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutSFLItemAddedToList, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutItemInteractions, epi, empi });
1820        
1821        SwymStorefrontLayoutExtensions?.refreshSFLList();
1822
1823        SwymStorefrontLayoutExtensions?.Notification?.setMessage({
1824          message: SwymStorefrontLayoutContext?.Strings?.notificationMessageSFLItemSaved,
1825          status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Neutral,
1826          duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
1827          image,
1828          title
1829        },{
1830          showProgress: true,
1831          showTitle: true
1832        });
1833      });
1834
1835      swat.evtLayer.addEventListener(swat.JSEvents.removedFromSFL, (event) => {
1836        let image = event?.detail?.d?.iu || null;
1837        let title = event?.detail?.d?.dt || null;
1838        let { epi, empi } = event?.detail?.d || {};
1839        window._swat.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutSFLItemRemovedFromList, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutItemInteractions, epi, empi });
1840        SwymStorefrontLayoutExtensions?.refreshSFLList();
1841
1842        SwymStorefrontLayoutExtensions?.Notification?.setMessage({
1843          message: SwymStorefrontLayoutContext?.Strings?.notificationMessageSFLItemRemoved,
1844          status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Neutral,
1845          duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
1846          image,
1847          title
1848        },{
1849          showProgress: true,
1850          showTitle: true
1851        });
1852      });
1853
1854      swat.evtLayer.addEventListener(swat.JSEvents.movedToCartFromSFL, (event) => {
1855        swat.utils.debounce(()=>{
1856          SwymStorefrontLayoutExtensions?.refreshSFLList();
1857        }, 1000)();
1858      });
1859
1860    }
1861  }
1862
1863}
1864
1865/**
1866 * SwymStorefrontLayoutAsModal
1867 * 
1868 * This class extends SwymWishlistCore to render a modal-based storefront layout for the Swym wishlist.
1869 * It manages UI rendering, event listeners, and open/close interactions.
1870 * 
1871 * Features:
1872 * - Displays a modal layout for wishlist functionality.
1873 * - Supports collection carousel based on SwymStorefrontLayoutContext settings.
1874 * - Provides a close button and backdrop click handling to close the modal.
1875 * - Tracks UI engagement using Swym's instrumentation.
1876 * 
1877 * Methods:
1878 * - renderUI(): Generates the modal's HTML structure.
1879 * - initUIElement(): Initializes UI elements and event listeners.
1880 * - attachDrawerEventListner(): Binds click events to close the modal.
1881 * - open(): Opens the modal and updates the UI state.
1882 * - close(): Closes the modal, removes body scroll lock, and updates history state.
1883 * - reRenderUI(): Re-renders the UI while preserving the open state.
1884 * 
1885 * Usage:
1886 * <swym-storefront-layout-as-modal></swym-storefront-layout-as-modal>
1887 */
1888  class SwymStorefrontLayoutAsModal extends SwymWishlistCore {
1889    constructor() {
1890      super();
1891      this.renderUI();
1892    }
1893
1894    renderUI() {
1895      this.innerHTML = `
1896      <div id="swym-storefront-layout-container" class="swym-storefront-layout-drawer swym-storefront-layout-hide-view" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="swym-wishlist-title" aria-hidden="true" inert>
1897        <div class="swym-storefront-layout-backdrop"></div>
1898        <div class="swym-storefront-layout-layout">
1899          <swym-storefront-layout-tabs></swym-storefront-layout-tabs>
1900          <button id="swym-storefront-layout-close-drawer-button" aria-label="${SwymStorefrontLayoutContext?.Strings?.closeDrawer || 'Close'}" class="swym-storefront-layout-close-button">
1901            <svg xmlns="http://www.w3.org/2000/svg" width="27" height="27" viewBox="0 0 27 27" fill="none" aria-hidden="true">
1902              <path d="M0 13.5C0 6.04416 6.04416 0 13.5 0C20.9558 0 27 6.04416 27 13.5C27 20.9558 20.9558 27 13.5 27C6.04416 27 0 20.9558 0 13.5Z" fill="none" fill-opacity="0.5"/>
1903              <path d="M16.0245 17.8326C16.2477 18.0558 16.6095 18.0558 16.8326 17.8326C17.0558 17.6095 17.0558 17.2477 16.8326 17.0245L13.8081 14L16.8326 10.9755C17.0558 10.7523 17.0558 10.3905 16.8326 10.1674C16.6095 9.94421 16.2477 9.94421 16.0245 10.1674L13 13.1919L9.97549 10.1674C9.75233 9.94421 9.39052 9.94421 9.16737 10.1674C8.94421 10.3905 8.94421 10.7523 9.16737 10.9755L12.1919 14L9.16737 17.0245C8.94421 17.2477 8.94421 17.6095 9.16737 17.8326C9.39052 18.0558 9.75233 18.0558 9.97549 17.8326L13 14.8081L16.0245 17.8326Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
1904            </svg>
1905          </button>
1906          <swym-storefront-layout-tab-content class="swym-storefront-layout-container swym-storefront-layout-scrollable"></swym-storefront-layout-tab-content>
1907          <swym-storefront-layout-login-user showLogin="true"></swym-storefront-layout-login-user>
1908        </div>
1909      </div>
1910    `;
1911
1912      this.initUIElement();
1913    }
1914
1915  initUIElement() {
1916    this.elements = {
1917      drawer: this.querySelector('.swym-storefront-layout-drawer'),
1918      drawerCloseButton: this.querySelector('#swym-storefront-layout-close-drawer-button'),
1919      drawerbackdrop: this.querySelector('.swym-storefront-layout-backdrop'),
1920      collectionList: this.querySelector('#swym-storefront-layout-collection-list'),
1921    }
1922
1923
1924    // Strengthen notification accessibility with polite live region
1925    try {
1926      const notificationEl = document.querySelector('swym-storefront-layout-notification');
1927      if (notificationEl) {
1928        notificationEl.setAttribute('aria-live', 'polite');
1929      }
1930    } catch (e) {
1931      window._swat?.utils.warn('Unable to set notification aria-live', e);
1932    }
1933
1934    // Announce list updates for screen readers
1935    try {
1936      document.querySelectorAll('.swym-storefront-layout-total-list-items-count').forEach((itemsCountEl) => {
1937        itemsCountEl.setAttribute('aria-live', 'polite');
1938      });
1939    } catch (e) {
1940      window._swat?.utils.warn('Unable to set items count aria-l
1940ive', e);
1941    }
1942    this.attachDrawerEventListner();
1943
1944  }
1945
1946    getDeepFocusableElements(root) {
1947      const focusableSelector =
1948        'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
1949      let elements = Array.from(root.querySelectorAll(focusableSelector));
1950      for (const el of elements) {
1951        if (el.shadowRoot) {
1952          elements = elements.concat(
1953            this.getDeepFocusableElements(el.shadowRoot)
1954          );
1955        }
1956      }
1957      return elements;
1958    }
1959
1960    trapFocus = (e) => {
1961      const isTabPressed = e.key === "Tab" || e.keyCode === 9;
1962      if (!isTabPressed) return;
1963
1964      const modal = this.elements.drawer;
1965      const focusableElements = this.getDeepFocusableElements(modal);
1966
1967      if (focusableElements.length === 0) return;
1968
1969      const first = focusableElements[0];
1970      const last = focusableElements[focusableElements.length - 1];
1971
1972      if (e.shiftKey) {
1973        if (
1974          document.activeElement === first ||
1975          !modal.contains(document.activeElement)
1976        ) {
1977          e.preventDefault();
1978          last.focus();
1979        }
1980      } else {
1981        if (
1982          document.activeElement === last ||
1983          !modal.contains(document.activeElement)
1984        ) {
1985          e.preventDefault();
1986          first.focus();
1987        }
1988      }
1989    };
1990
1991    attachDrawerEventListner() {
1992      this.elements.drawerCloseButton.addEventListener('click', this.close.bind(this));
1993      this.elements.drawerbackdrop.addEventListener('click', this.close.bind(this));
1994
1995      // Close on ESC (focus trap is handled in open/close methods)
1996      const keydownHandler = (e) => {
1997        const isOpen = this.elements?.drawer && !this.elements.drawer.classList.contains('swym-storefront-layout-hide-view');
1998        if (!isOpen) return;
1999        if (e.key === 'Escape') {
2000          e.preventDefault();
2001          this.close();
2002        }
2003      };
2004      document.addEventListener('keydown', keydownHandler);
2005    }
2006
2007    open() {
2008      this.isOpen = true;
2009      this.previouslyFocused = document.activeElement;
2010
2011      if (this.elements?.drawer) {
2012        this.elements.drawer.classList.remove(
2013          "swym-storefront-layout-hide-view"
2014        );
2015        this.elements.drawer.removeAttribute("aria-hidden");
2016        this.elements.drawer.removeAttribute("inert");
2017        document.body.classList.add("swym-storefront-layout-body-no-scroll");
2018
2019        this.elements.drawer.focus();
2020        document.addEventListener("keydown", this.trapFocus, true);
2021        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutOpened, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
2022        if (SwymStorefrontLayoutContext?.CustomEvents?.Opened) {
2023          document.dispatchEvent(new CustomEvent(SwymStorefrontLayoutContext.CustomEvents.Opened));
2024        }
2025      }
2026    }
2027
2028    close() {
2029      this.isOpen = false;
2030
2031      if (this.elements?.drawer) {
2032        this.elements.drawer.classList.add("swym-storefront-layout-hide-view");
2033        this.elements.drawer.setAttribute("aria-hidden", "true");
2034        this.elements.drawer.setAttribute("inert", "");
2035        document.body.classList.remove("swym-storefront-layout-body-no-scroll");
2036
2037        document.removeEventListener("keydown", this.trapFocus, true);
2038
2039        if (this.previouslyFocused && typeof this.previouslyFocused.focus === "function") {
2040          this.previouslyFocused.focus();
2041        }
2042
2043        history.replaceState(null, '', window.location.pathname + window.location.search);
2044        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutClosed, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
2045      }
2046    }
2047
2048    reRenderUI() {
2049      this.renderUI();
2050      if (this.isOpen) this.open();
2051    }
2052  }
2053
2054/**
2055 * SwymStorefrontLayoutAsSection
2056 * 
2057 * This class extends SwymWishlistCore to render a storefront wishlist layout as a section within a specified container.
2058 * It dynamically injects the wishlist UI into the provided container element.
2059 * 
2060 * Features:
2061 * - Renders the wishlist section inside a container specified by the `container-id` attribute.
2062 * - Supports collection carousel based on SwymStorefrontLayoutContext settings.
2063 * - Displays wishlist items and user login UI.
2064 * - Handles rendering errors gracefully and logs warnings if an invali
2064d container ID is provided.
2065 * 
2066 * Methods:
2067 * - renderUI(): Generates the section-based wishlist UI and injects it into the specified container.
2068 * - reRenderUI(): Re-renders the UI to reflect any updates.
2069 * 
2070 * Usage:
2071 * <swym-storefront-layout-as-section container-id="your-container-id"></swym-storefront-layout-as-section>
2072 */
2073
2074class SwymStorefrontLayoutAsSection extends SwymWishlistCore {
2075  constructor() {
2076    super();
2077    this.containerId = this.getAttribute('container-id');
2078    this.renderUI();
2079  }
2080
2081  renderUI() {
2082    let { StorefrontLayoutType } = SwymStorefrontLayoutContext?.Settings;
2083    if(StorefrontLayoutType === 'as-section'){
2084      this.listContainerToRender = null;
2085      try {
2086        this.listContainerToRender = document.getElementById(this.containerId);
2087
2088        // Only proceed if the container exists in the DOM
2089        if (!this.listContainerToRender) {
2090          // Container doesn't exist yet - this can happen during page transitions or layout changes
2091          // We'll skip rendering for now and wait for the container to be available
2092          return;
2093        }
2094
2095        this.listContainerToRender.innerHTML = `
2096        <div id="swym-storefront-layout-container">
2097          <div id="swym-storefront-layout-section-container" class="swym-storefront-layout-layout">
2098            <swym-storefront-layout-tabs></swym-storefront-layout-tabs>
2099            <swym-storefront-layout-login-user showLogin="true"></swym-storefront-layout-login-user>
2100            <swym-storefront-layout-tab-content class="swym-storefront-layout-container"></swym-storefront-layout-tab-content>
2101          </div>
2102        </div>
2103        `
2104
2105        this.listContainerToRender.classList.add('swym-storefront-layout-root-component');
2106
2107      } catch (error) {
2108        window._swat?.utils.warn('Invalid List Container Selector ', this.containerId);
2109      }
2110    }
2111  }
2112
2113  reRenderUI() {
2114    this.renderUI();
2115  }
2116
2117  close() {
2118    if (document.referrer && history.length > 1) {
2119      try {
2120        const referrerOrigin = new URL(document.referrer).origin;
2121        if (referrerOrigin === window.location.origin) {
2122          history.back();
2123          return;
2124        }
2125      } catch (e) { /* invalid referrer URL, fall through */ }
2126    }
2127    window.location.href = window.Shopify?.routes?.root || '/';
2128  }
2129
2130}
2131
2132/**
2133 * SwymStorefrontLayoutAsDrawer
2134 * 
2135 * This class extends SwymWishlistCore to implement a drawer-style storefront wishlist layout.
2136 * It provides an interactive UI for users to view and manage their wishlist within a side drawer.
2137 * 
2138 * Features:
2139 * - Renders a wishlist drawer that slides in/out based on user interaction.
2140 * - Supports collection carousel display based on SwymStorefrontLayoutContext settings.
2141 * - Includes login UI for authentication-related actions.
2142 * - Implements event listeners for closing the drawer via a close button or backdrop click.
2143 * - Triggers instrumentation events for UI engagement tracking.
2144 * 
2145 * Methods:
2146 * - renderUI(): Generates the wishlist drawer UI and injects it into the component.
2147 * - initUIElement(): Caches DOM elements required for interactions.
2148 * - attachDrawerEventListner(): Attaches event listeners for closing the drawer.
2149 * - open(): Opens the drawer and prevents background scrolling.
2150 * - close(): Closes the drawer, restores scrolling, and updates browser history.
2151 * - reRenderUI(): Re-renders the UI and retains the open state if applicable.
2152 * 
2153 * Usage:
2154 * <swym-storefront-layout-as-drawer></swym-storefront-layout-as-drawer>
2155 */
2156  class SwymStorefrontLayoutAsDrawer extends SwymWishlistCore {
2157    constructor() {
2158      super();
2159      this.renderUI();
2160    }
2161
2162    renderUI() {
2163      this.innerHTML = `
2164      <div id="swym-storefront-layout-container" class="swym-storefront-layout-drawer swym-storefront-layout-hide-view swym-storefront-layout-drawer-position-${SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutDrawerPosition}" role="dialog" aria-modal="true" aria-labelledby="swym-wishlist-title" tabindex="-1" aria-hidden="true" inert>
2165        <div class="swym-storefront-layout-backdrop"></div>
2166        <div class="swym-storefront-layout-layout">
2167          <button id="swym-storefront-layout-close-drawer-button" aria-label="${SwymStorefrontLayoutContext?.Strings?.closeDrawer || 'Close'}" class="swym-storefront-layout-close-button">
2168            <svg xmlns="http://www.w3.org/2000/svg" width="27" height="27" viewB
2168ox="0 0 27 27" fill="none" aria-hidden="true">
2169              <path d="M0 13.5C0 6.04416 6.04416 0 13.5 0C20.9558 0 27 6.04416 27 13.5C27 20.9558 20.9558 27 13.5 27C6.04416 27 0 20.9558 0 13.5Z" fill="none" fill-opacity="0.5"/>
2170              <path d="M16.0245 17.8326C16.2477 18.0558 16.6095 18.0558 16.8326 17.8326C17.0558 17.6095 17.0558 17.2477 16.8326 17.0245L13.8081 14L16.8326 10.9755C17.0558 10.7523 17.0558 10.3905 16.8326 10.1674C16.6095 9.94421 16.2477 9.94421 16.0245 10.1674L13 13.1919L9.97549 10.1674C9.75233 9.94421 9.39052 9.94421 9.16737 10.1674C8.94421 10.3905 8.94421 10.7523 9.16737 10.9755L12.1919 14L9.16737 17.0245C8.94421 17.2477 8.94421 17.6095 9.16737 17.8326C9.39052 18.0558 9.75233 18.0558 9.97549 17.8326L13 14.8081L16.0245 17.8326Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
2171            </svg>
2172          </button>
2173          <swym-storefront-layout-tab-content class="swym-storefront-layout-container swym-storefront-layout-scrollable"></swym-storefront-layout-tab-content>
2174          <swym-storefront-layout-login-user showLogin="true"></swym-storefront-layout-login-user>
2175          <swym-storefront-layout-actions id="swym-storefront-layout-actions"></swym-storefront-layout-actions>
2176          <swym-storefront-layout-tabs></swym-storefront-layout-tabs>
2177        </div>
2178      </div>
2179    `;
2180      this.initUIElement();
2181    }
2182
2183    initUIElement() {
2184      this.elements = {
2185        drawer: this.querySelector('.swym-storefront-layout-drawer'),
2186        drawerCloseButton: this.querySelector('#swym-storefront-layout-close-drawer-button'),
2187        drawerbackdrop: this.querySelector('.swym-storefront-layout-backdrop'),
2188        collectionList: this.querySelector('#swym-storefront-layout-collection-list')
2189      }
2190      this.attachDrawerEventListner();
2191    }
2192
2193    attachDrawerEventListner() {
2194      this.elements.drawerCloseButton.addEventListener('click', this.close.bind(this));
2195      this.elements.drawerbackdrop.addEventListener('click', this.close.bind(this));
2196
2197      // Close on ESC (focus trap is handled in open/close methods)
2198      const keydownHandler = (e) => {
2199        const isOpen = this.elements?.drawer && !this.elements.drawer.classList.contains('swym-storefront-layout-hide-view');
2200        if (!isOpen) return;
2201        if (e.key === 'Escape') {
2202          e.preventDefault();
2203          this.close();
2204        }
2205      };
2206      document.addEventListener('keydown', keydownHandler);
2207    }
2208
2209    getFocusableElements(root) {
2210      const selectors =
2211        'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])';
2212      const elements = Array.from(root.querySelectorAll(selectors));
2213
2214      return elements.filter(
2215        (el) => el.offsetParent !== null || el instanceof SVGElement
2216      );
2217    }
2218
2219    trapFocus = (e) => {
2220      if (e.key !== "Tab") return;
2221
2222      const focusableEls = this.getFocusableElements(this.elements.drawer);
2223      if (focusableEls.length === 0) return;
2224
2225      const first = focusableEls[0];
2226      const last = focusableEls[focusableEls.length - 1];
2227
2228      if (e.shiftKey) {
2229        if (document.activeElement === first || !this.elements.drawer.contains(document.activeElement)) {
2230          e.preventDefault();
2231          last.focus();
2232        }
2233      } else {
2234        if (document.activeElement === last || !this.elements.drawer.contains(document.activeElement)) {
2235          e.preventDefault();
2236          first.focus();
2237        }
2238      }
2239    };
2240
2241    open() {
2242      this.isOpen = true;
2243      this.previouslyFocused = document.activeElement;
2244
2245      if (this.elements?.drawer) {
2246        this.elements.drawer.classList.remove("swym-storefront-layout-hide-view");
2247        this.elements.drawer.removeAttribute("aria-hidden");
2248        this.elements.drawer.removeAttribute("inert");
2249        document.body.classList.add("swym-storefront-layout-body-no-scroll");
2250
2251        // Set focus to the drawer itself
2252        this.elements.drawer.focus();
2253
2254        // Trap focus inside the drawer
2255        document.addEventListener("keydown", this.trapFocus, true);
2256
2257        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutOpened, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
2258        if (SwymStorefrontLayoutContext?.CustomEvents?.Opened) {
2259          document.dispatchEvent(new CustomEvent(SwymStorefrontLayoutContext.CustomEvents.Opened));
2260        }
2261      }
2262    }
2263
2264    close() {
2265      this.isOpen = false;
2266
2267      if (this.elements?.drawer) {
2268        this.elements.drawer.classList.add("swym-storefront-layout-hide-view");
2269        this.elements.drawer.setAttribute("aria-hidden", "true");
2270        this.elements.drawer.setAttribute("inert", "");
2271        document.body.classList.remove("swym-storefront-layout-body-no-scroll");
2272
2273        document.removeEventListener("keydown", this.trapFocus, true);
2274
2275        // Return focus to the previously focused element
2276        if (this.previouslyFocused && typeof this.previouslyFocused.focus === "function") {
2277          this.previouslyFocused.focus();
2278        }
2279
2280        history.replaceState(null, '', window.location.pathname + window.location.search);
2281        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutClosed, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
2282      }
2283    }
2284
2285    reRenderUI() {
2286      this.renderUI();
2287      if (this.isOpen) this.open();
2288    }
2289  }
2290
2291/**
2292 * SwymStorefrontLayoutCollectionCarousel
2293 * 
2294 * This custom Web Component is responsible for rendering a carousel of collection lists 
2295 * within the storefront layout. It dynamically updates based on the provided collection 
2296 * data and offers smooth scrolling functionality with navigation buttons.
2297 * 
2298 * Features:
2299 * - Dynamically renders collections with images and item counts.
2300 * - Implements smooth scrolling with previous/next buttons.
2301 * - Updates button visibility based on scroll position.
2302 * - Tracks user interactions using Swym's instrumentation.
2303 * - Provides an action button for each collection with a tooltip menu.
2304 * - Supports localization via `SwymStorefrontLayoutContext?.Strings`.
2305 * 
2306 * Usage:
2307 * - Call `setData({ collections })` to populate the carousel with collection data.
2308 * 
2309 * Dependencies:
2310 * - `window.SwymStorefrontLayoutContext` for localized strings and configurations.
2311 * - `window._swat?.instrumentV3` for tracking user interactions.
2312 * - `SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip` for managing action tooltips.
2313 * 
2314 */
2315class SwymStorefrontLayoutCollectionCarousel extends HTMLElement {
2316  constructor() {
2317    super();
2318    this.collections = [];
2319    
2320    // Check multi-wishlist config to determine initial visibility
2321    const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
2322    this.shouldShowMultiple = shouldShowMultiple;
2323    
2324    this.renderUI();
2325    this.elements = {
2326      title: this.querySelector('.swym-storefront-layout-collection-carousel-title'),
2327      carouselContainer: this.querySelector('.swym-storefront-layout-carousel-container'),
2328      carousel: this.querySelector('#swym-storefront-layout-collection-carousel-items-container'),
2329      carouselPrevButton: this.querySelector('.swym-storefront-layout-carousel-prev-btn'),
2330      carouselNextButton: this.querySelector('.swym-storefront-layout-carousel-next-btn')
2331    }
2332    
2333    // Hide carousel initially if multi-wishlist should not be shown
2334    if (!this.shouldShowMultiple) {
2335      this.style.display = 'none';
2336    }
2337    
2338    this.attachEventListner();
2339  }
2340
2341  setData({ collections, canCreateLists = true, shouldShowMultiple = false }) {
2342    this.collections = collections;
2343    this.canCreateLists = canCreateLists;
2344    this.shouldShowMultiple = shouldShowMultiple;
2345    this.renderCollections();
2346  }
2347
2348  renderUI() {
2349    this.innerHTML = `
2350    <div class="swym-storefront-layout-collection-carousel-container">
2351      <div class="swym-storefront-layout-collection-carousel-title" role="heading" aria-level="2">${SwymStorefrontLayoutContext?.Strings?.collectionTitle}</div>
2352      <div class="swym-storefront-layout-carousel-container" role="region" aria-label="${SwymStorefrontLayoutContext?.Strings?.collectionTitle}">
2353        <button class="swym-storefront-layout-carousel-btn swym-storefront-layout-carousel-prev-btn" aria-label="${SwymStorefrontLayoutContext?.Strings?.scrollLeft || 'Scroll Left'}">
2354          <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" class="swym-storefront-layout-scroll-button-icon" aria-hidden="true"><path d="m13.333 8 8 8-8 8" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"></path></svg>
2355        </button>
2356        <div id="swym-storefront-layout-collection-carousel-items-container" class="swym-storefront-layout-carousel swym-storefront-layout-scrollable" role="list" tabindex="0" aria-label="${SwymStorefrontLayoutContext?.Strings?.collectionTitle || 'Collections'}">
2357          <swym-storefront-layout-loader loading="true" loadertype="${SwymStorefrontLayoutContext?.LoaderViewType.CarouselListItem}" width="100%" height="100px"></swym-storefront-layout-loader>
2358        </div>
2359        <button class="swym-storefront-layout-carousel-btn swym-storefront-layout-carousel-next-btn" aria-label="${SwymStorefrontLayoutContext?.Strings?.scrollRight || 'Scroll Right'}">
2360          <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" class="swym-storefront-layout-scroll-button-icon" aria-hidden="true"><path d="m13.333 8 8 8-8 8" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"></path></svg>
2361        </button>
2362      </div>
2363    </div>
2364    `
2365  }
2366
2367  attachEventListner() {
2368
2369    this.elements.carouselPrevButton.addEventListener("click", () => {
2370      this.elements.carousel.scrollBy({
2371        left: -320,
2372        behavior: "smooth",
2373      });
2374    });
2375
2376    this.elements.carouselNextButton.addEventListener("click", () => {
2377      this.elements.carousel.scrollBy({
2378        left: 320,
2379        behavior: "smooth",
2380      });
2381    });
2382
2383    this.elements.carousel.addEventListener("scroll", () => this.updateCarouselButtonVisibility());
2384
2385  }
2386
2387  renderCollections() {
2388    const collectionsContainer = this.querySelector('#swym-storefront-layout-collection-carousel-items-container');
2389    if (collectionsContainer) {
2390
2391      window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutCollectionRendered, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
2392
2393      // Show carousel if shouldShowMultiple is true (feature enabled or multiple lists exist)
2394      if (!this.shouldShowMultiple) {
2395        this.style.display = 'none';
2396        return;
2397      }
2398
2399      // Show the carousel
2400      this.style.display = '';
2401
2402      if (this.collections && this.collections.length) {
2403        this.elements.carouselContainer.classList.add('swym-storefront-layout-has-items');
2404        collectionsContainer.innerHTML = this.collections
2405          .map(
2406            (collection) => {
2407              let { lname, listcontents, lid } = collection;
2408
2409              const listImagesHtml = Array.from({ length: 3 })
2410                .map((_, i) => {
2411                  let item = listcontents[i];
2412                  return `
2413                  <div class="${i === 0 ? 'swym-storefront-layout-collection-grid-item-primary-image' : 'swym-storefront-layout-collection-grid-item-secondary-image'} ">
2414                    ${item?.iu ? `<img src="${item ? item.iu : null}" alt="${item?.dt ? swymEscAttr(item?.dt) : 'product Image'}" class="swym-storefront-layout-collection-grid-item-image" />` : `<div class="swym-storefront-layout-collection-grid-item-image" ></div>`}
2415                  </div>
2416                `;
2417                })
2418                .join("");
2419
2420              const count = listcontents.length;
2421
2422              return `
2423              <div class="swym-storefront-layout-collection-grid-item" data-lid="${lid}" role="listitem" aria-label="${lname}">
2424                <div class="swym-storefront-layout-collection-grid-item-image-container">
2425                  ${listImagesHtml}
2426                </div>
2427                <div class="swym-storefront-layout-collection-grid-item-info-container">
2428                  <div class="swym-storefront-layout-collection-grid-item-name">${lname}</div>
2429                  <div class="swym-storefront-layout-collection-grid-item-count">${count} ${count === 1 ? SwymStorefrontLayoutContext?.Strings?.item : SwymStorefrontLayoutContext?.Strings?.items}</div>
2430                </div>
2431                <div class="swym-storefront-layout-collection-grid-item-option-button" role="button" tabindex="0" aria-haspopup="dialog" aria-expanded="false" aria-label="More options for ${lname}">
2432                  <svg xmlns="http://www.w3.org/2000/svg" width="3" height="13" viewBox="0 0 3 13" fill="none" aria-hidden="true" focusable="false">
2433                    <circle cx="1.5" cy="1.50014" r="1.5" fill="#B1B7C3"/>
2434                    <circle cx="1.5" cy="6.50014" r="1.5" fill="#B1B7C3"/>
2435                    <circle cx="1.5" cy="11.5001" r="1.5" fill="#B1B7C3"/>
2436                  </svg>
2437                </div>
2438              </div>
2439            `
2440            }
2441          )
2442          .join('');
2443        this.updateCarouselButtonVisibility();
2444        this.attachEventListnerToCollectionGrid();
2445      } else {
2446        // Show empty state when shouldShowMultiple is true but no collections
2447        this.elements.carouselContainer.classList.remove('swym-storefront-layout-has-items');
2448        collectionsContainer.innerHTML = `
2449          <div class="swym-storefront-layout-collection-empty">${SwymStorefrontLayoutContext?.Strings?.emptyCarouselCollectionText}</div>`;
2450      }
2451
2452      let collectionCount = this.collections?.length;
2453      if(this.elements.title){
2454        this.elements.title.innerHTML = `${SwymStorefrontLayoutContext?.Strings?.collectionTitle} ${collectionCount?`(${collectionCount})`:''}`;
2455      }
2456    }
2457  }
2458
2459
2460  updateCarouselButtonVisibility() {
2461    const scrollLeft = this.elements.carousel.scrollLeft;
2462    const maxScrollLeft = this.elements.carousel.scrollWidth - this.elements.carousel.clientWidth;
2463
2464    this.elements.carouselPrevButton.style.display = scrollLeft > 0 ? "flex" : "none";
2465    this.elements.carouselNextButton.style.display = scrollLeft < maxScrollLeft ? "flex" : "none";
2466  }
2467
2468  attachEventListnerToCollectionGrid() {
2469    this.collections.forEach((collection) => {
2470      const collectionItem = this.elements.carousel.querySelector(
2471        `[data-lid="${collection.lid}"]`
2472      );
2473      collectionItem?.addEventListener("click", (event) => {
2474        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutCollectionOpened, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
2475        window.location.hash = SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.CollectionList + collection.lid;
2476      });
2477
2478      let collectionItemActionButton =  collectionItem.querySelector('.swym-storefront-layout-collection-grid-item-option-button');
2479      collectionItemActionButton?.addEventListener("click", (event) => {
2480        event.preventDefault();
2481        event.stopPropagation();
2482        if(SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.isTooltipOpen && SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.currentTarget === event.target){
2483          SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.closeTooltip();
2484          collectionItemActionButton?.setAttribute('aria-expanded', 'false');
2485        }else{
2486          SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.setData({
2487            listId: collection.lid,
2488            list: collection,
2489            collections: this.collections,
2490            actionType: SwymStorefrontLayoutContext?.ActionTypes.EditCollection
2491          });
2492          SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.showOnTarget(event.target);
2493          collectionItemActionButton?.setAttribute('aria-expanded', 'true');
2494        }
2495      })
2496
2497      // Keyboard support for option button
2498      collectionItemActionButton?.addEventListener('keydown', (e) => {
2499        if (e.key === 'Enter' || e.key === ' ') {
2500          e.preventDefault();
2501          collectionItemActionButton.click();
2502        }
2503      });
2504
2505    })
2506  }
2507}
2508
2509/**
2510 * SwymStorefrontLayoutWishlistItem
2511 *
2512 * This custom web component represents an item in the Swym Storefront Layout Wishlist.
2513 * It dynamically renders product details, pricing, and actions such as adding to cart
2514 * or managing wishlist options. It also handles variant selection and user interactions
2515 * based on the store's configuration settings.
2516 *
2517 * Key Features:
2518 * - Displays product title, image, price, and compare-at price.
2519 * - Supports multiple product variants and allows selection.
2520 * - Handles "Add to Cart" functionality with visual feedback.
2521 * - Manages user interactions for wishlist options and collections.
2522 * - Ensures compatibility with store localization settings.
2523 *
2524 * Dependencies:
2525 * - SwymStorefrontLayoutContext: Provides store settings, strings, and utilities.
2526 * - SwymStorefrontLayoutExtensions: Handles tooltips and notifications.
2527 * - _swat.platform: Manages cart operations.
2528 *
2529 * Usage:
2530 * This component should be used within the Swym Storefront Layout to display 
2531 * wishlist items effectively while maintaining a seamless user experience.
2532 */
2533class SwymStorefrontLayoutWishlistItem extends HTMLElement{
2534  constructor() {
2535    super();
2536    this.item = null;
2537    this.list = null;
2538    this.sflList = null;
2539    this.selectedVariant = null;
2540    this.collections = null;
2541    this.listItemType = SwymStorefrontLayoutContext?.ListItemType?.WishlistItem;
2542    this.quantityUpdateTimeout = null;
2543    this._listenerController = null;
2544  }
2545
2546  disconnectedCallback() {
2547    this._listenerController?.abort();
2548    this._listenerController = null;
2549    if (this.quantityUpdateTimeout) {
2550      clearTimeout(this.quantityUpdateTimeout);
2551      this.quantityUpdateTimeout = null;
2552    }
2553  }
2554
2555  setData({ item, list, sflList, listItemType, collections, canCreateLists = true }) {
2556    this.item = item;
2557    this.listItemType = listItemType;
2558    this.list = list;
2559    this.sflList = sflList;
2560    this.collections = collections;
2561    this.canCreateLists = canCreateLists;
2562
2563    this.selectedVariantId = this.item?.cprops?.selectedVariantId || this.item?.epi;
2564    this.selectedVariant = SwymStorefrontLayoutContext?.getSelectedVariant(this.item, this.selectedVariantId);
2565
2566    this.dataset.epi = this.selectedVariant?.id || this.item?.epi;
2567    this.dataset.empi = this.item?.empi;
2568    this.dataset.du = this.item?.['du-mkt'] || this.item?.du;
2569
2570    this.renderItem();
2571    this.initItemElements();
2572    this.addEventListeners();
2573  }
2574
2575  getProductImage() {
2576    const productImage = this.selectedVariant?.featured_image;
2577    const imageUrl = typeof productImage === 'string' ? productImage : productImage?.src;
2578    return (
2579      imageUrl ||
2580      this.item?.productData?.featured_image ||
2581      this.item?.iu
2582    );
2583  }
2584
2585  getFormattedPrice() {
2586    let price = this.selectedVariant?.price ?? this.item?.productData?.price;  
2587    if (price === undefined || price === null) {
2588      price = this.item?.pr;
2589    }
2590    return price !== undefined && price !== null
2591    ? SwymStorefrontLayoutContext?.FormatPrice(price)
2592    : '';
2593  }
2594  getFormattedComparePrice() {
2595    let price = this.selectedVariant?.compare_at_price ?? this.item?.productData?.compare_at_price;
2596    if (price === undefined || price === null) {
2597      price = this.item?.op;
2598    }
2599    return price !== undefined && price !== null
2600    ? SwymStorefrontLayoutContext?.FormatPrice(price)
2601    : '';
2602  }
2603
2604  getButtonState() {
2605    const isInCart = _swat.platform.isInDeviceCart(this.selectedVariant?.id);
2606    if(this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.SaveForLaterItem){
2607      return this.selectedVariant?.available
2608      ? SwymStorefrontLayoutContext?.Strings?.moveToCartCta
2609      : SwymStorefrontLayoutContext?.Strings?.soldOut;
2610    }else{
2611      return this.selectedVariant?.available
2612      ? isInCart
2613        ? SwymStorefrontLayoutContext?.Strings?.addedToCart
2614        : SwymStorefrontLayoutContext?.Strings?.addToCart
2615      : SwymStorefrontLayoutContext?.Strings?.soldOut;
2616    }
2617  }
2618
2619  renderVariants() {
2620    if (SwymStorefrontLayoutContext?.Settings?.EnableStorefrontLayoutVariantSelector && this.item?.productData?.variants?.length > 1) {
2621      return `
2622        <span class="swym-storefront-layout-price-devider">|</span>
2623        <div class="swym-storefront-layout-grid-item-variants-container">
2624          ${this.item.productData.options
2625            .map(
2626              (option, index) => `
2627                  ${index==0?'':'<span class="swym-storefront-layout-variant-devider"></span>'}
2628                  <div class="swym-storefront-layout-variant">
2629                    ${option.values
2630                      .map(
2631                        (value) =>
2632                        this.selectedVariant?.[`option${index + 1}`] === value?value:''
2633                      )
2634                      .join('')}
2635                  </div>
2636                `
2637            )
2638            .join('')}
2639        </div>
2640      `;
2641    }
2642    return '';
2643  }
2644
2645  renderVariantSelector() {
2646    if (SwymStorefrontLayoutContext?.Settings?.EnableStorefrontLayoutVariantSelector && this.item?.productData?.variants?.length > 1) {
2647      return `
2648        <div class="swym-storefront-layout-grid-item-variant-selector-container">
2649          ${this.item.productData.options
2650            .map(
2651              (option, index) => `
2652                ${option.values && option.values.length>1 ? `
2653                  <select class="swym-storefront-layout-variant-selector">
2654                    <option value="${option.name}" disabled>${option.name}</option>
2655                    ${option.values
2656                      .map(
2657                        (value) =>
2658                          `<option value="${value}" ${
2659                            this.selectedVariant[`option${index + 1}`] === value ? 'selected' : ''
2660                          }>${value}</option>`
2661                      )
2662                      .join('')}
2663                  </select>
2664                `:''}
2665              `
2666            )
2667            .join('')}
2668        </div>
2669      `;
2670    }
2671    return '';
2672  }
2673    renderOptionButton() {
2674      // Get multi-wishlist configuration
2675      const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
2676      const isDrawer = SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer';
2677
2678      // Drawer UI Polish: In drawer + single wishlist mode, show trash icon instead of 3-dot menu
2679      // Clicking opens tooltip with "Remove from wishlist" confirmation (no direct delete)
2680      if (isDrawer && !shouldShowMultiple) {
2681        if (this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.SavedForYouItem ||
2682            SwymStorefrontLayoutContext?.checkUserCanEditList(this.list || this.sflList)) {
2683          const ariaLabel = this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.SavedForYouItem
2684            ? (SwymStorefrontLayoutContext?.Strings?.removeItemCta || 'Remove from Saved For You')
2685            : (SwymStorefrontLayoutContext?.Strings?.removeItemCta || 'Remove item');
2686          return `
2687      <button class="swym-storefront-layout-grid-item-option-button swym-storefront-layout-delete-btn" tabindex="0" role="button" aria-label="${ariaLabel}" aria-haspopup="dialog" aria-expanded="false">
2688        <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true" focusable="false">
2689          <path d="M11.5 9V13.25M8.5 9V13.25M5.75 12.2V6H14.25C14.25 8.421 14.25 9.779 14.25 12.2C14.25 13.053 14.25 13.647 14.212 14.11C14.175 14.563 14.106 14.824 14.005 15.021C13.7822 15.4476 13.4408 15.8008 13.022 16.038C12.825 16.138 12.564 16.208 12.111 16.245C11.648 16.282 11.054 16.283 10.201 16.283H9.801C8.948 16.283 8.354 16.283 7.891 16.245C7.438 16.208 7.177 16.139 6.98 16.038C6.56083 15.8009 6.21911 15.4478 5.996 15.021C5.896 14.824 5.826 14.563 5.789 14.11C5.75 13.647 5.75 13.053 5.75 12.2Z" stroke="currentColor" stroke-linecap="round"/>
2690          <path d="M4.25 6H15.75M8 5.25C8 4.71957 8.21071 4.21086 8.58579 3.83579C8.96086 3.46071 9.46957 3.25 10 3.25C10.5304 3.25 11.0391 3.46071 11.4142 3.83579C11.7893 4.21086 12 4.71957 12 5.25" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
2691        </svg>
2692      </button>
2693    `;
2694        }
2695        return '';
2696      }
2697
2698      // SavedForYouItem only supports remove — show option button for that
2699      if (this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.SavedForYouItem) {
2700        return `
2701      <button class="swym-storefront-layout-grid-item-option-button" tabindex="0" role="button" aria-label="Remove from Saved For You">
2702        <svg xmlns="http://www.w3.org/2000/svg" width="3" height="13" viewBox="0 0 3 13" fill="currentcolor" aria-hidden="true" focusable="false">
2703          <circle cx="1.5" cy="1.50014" r="1.5" fill="#B1B7C3"/>
2704          <circle cx="1.5" cy="6.50014" r="1.5" fill="#B1B7C3"/>
2705          <circle cx="1.5" cy="11.5001" r="1.5" fill="#B1B7C3"/>
2706        </svg>
2707      </button>
2708    `;
2709      }
2710
2711      // Show options button if:
2712      // 1. Multiple lists should be shown (feature enabled OR multiple lists exist), OR
2713      // 2. User can edit the list (for delete/rename options)
2714      if (
2715        shouldShowMultiple ||
2716        SwymStorefrontLayoutContext?.checkUserCanEditList(
2717          this.list || this.sflList
2718        )
2719      ) {
2720        return `
2721      <button class="swym-storefront-layout-grid-item-option-button" tabindex="0" role="button" aria-label="Open item options" aria-haspopup="dialog" aria-expanded="false">
2722        <svg xmlns="http://www.w3.org/2000/svg" width="3" height="13" viewBox="0 0 3 13" fill="currentcolor" aria-hidden="true" focusable="false">
2723          <circle cx="1.5" cy="1.50014" r="1.5" fill="#B1B7C3"/>
2724          <circle cx="1.5" cy="6.50014" r="1.5" fill="#B1B7C3"/>
2725          <circle cx="1.5" cy="11.5001" r="1.5" fill="#B1B7C3"/>
2726        </svg>
2727      </button>
2728    `;
2729      }
2730      return "";
2731    }
2732  isTagAvailable(tag, product) {
2733    return window._swat && window._swat.platform?.isTagAvailable(
2734      tag,
2735      product
2736    );
2737  }
2738
2739  getDefaultValue(val, defaultValue) {
2740    return val ? val : defaultValue;
2741  }
2742
2743  getMinQuantity() {
2744    return window._swat?.retailerSettings?.UI?.MinimumQuantity || 1;
2745  }
2746
2747  getMaxQuantity() {
2748    return window._swat?.retailerSettings?.UI?.MaximumQuantity;
2749  }
2750  
2751  renderItem() {
2752    if(_swat.marketsEnabled && this.item?.['du-mkt'] === null ){
2753      return;
2754    }
2755    const settings = window._swat.retailerSettings;
2756    const IsTagBasedActionEnabled = settings?.Wishlist?.TagBasedActionEnabled;
2757
2758    const hideAddtoCartTag = this.getDefaultValue(settings?.UI?.HideAddToCartTag, "swym-hide-addtocart");
2759    const disabledAddtoCartTag = this.getDefaultValue(settings?.UI?.DisabledAddtoCartTag, "swym-disabled-addtocart-with-text");
2760    const hideProductPriceTag = this.getDefaultValue(settings?.UI?.HideProductPriceTag, "swym-hide-productprice");
2761    
2762    const productInfo = this.item?.productData;
2763
2764    const isHidden = IsTagBasedActionEnabled && this.isTagAvailable(hideAddtoCartTag, productInfo);
2765    const isDisabled = IsTagBasedActionEnabled && this.isTagAvailable(disabledAddtoCartTag, productInfo);
2766    const hidePrice = IsTagBasedActionEnabled && this.isTagAvailable(hideProductPriceTag, productInfo);
2767    
2768    // Use du-mkt if available (market-specific URL), otherwise fall back to du
2769    let localizedUrl = this.item?.['du-mkt'] || this.item?.du || '';
2770    
2771    // Append variant parameter if not already present
2772    if (localizedUrl && this.item?.epi) {
2773      const urlObj = new URL(localizedUrl, window.location.origin);
2774      if (!urlObj.searchParams.has('variant')) {
2775        urlObj.searchParams.set('variant', this.item.epi);
2776        localizedUrl = urlObj.toString();
2777      }
2778    }
2779
2780    const noVariant = this.selectedVariant?.title === "Default Title";
2781    const matchingItem = this.list?.listcontents.find(item => item.epi === this.selectedVariant?.id);
2782    const isAutoWishlist = this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.SavedForYouItem
2783      && matchingItem?.source === "auto-wishlist";
2784    const isFirstVariant = matchingItem?.productData?.variants?.[0]?.id === this.selectedVariant?.id;
2785
2786    let price = this.getFormattedPrice();
2787    let comparePrice = this.getFormattedComparePrice();
2788
2789    this.innerHTML = `
2790      <div class="swym-storefront-layout-grid-item">
2791        <a href="${localizedUrl}" class="swym-storefront-layout-grid-item-image-container">
2792          <img src="${this.getProductImage()}" alt="${swymEscAttr(this.item?.productData?.title || this.item?.dt) || 'Product image'}" class="swym-storefront-layout-grid-item-image" />
2793        </a>
2794        <div class="swym-storefront-layout-grid-item-content">
2795          <a href="${localizedUrl}" class="swym-storefront-layout-grid-item-title">${this.item?.productData?.title || this.item?.dt || ''}</a>
2796          <div class="swym-storefront-layout-grid-item-price-variant">
2797           ${!hidePrice ? `<span class="swym-storefront-layout-grid-item-final-price">${price}</span>` : ''}
2798           ${comparePrice && comparePrice !== price && !hidePrice && this.selectedVariant?.compare_at_price ? `<span class="swym-storefront-layout-grid-item-compare-price">${comparePrice}</span>`: ''}
2799${this.renderVariants()}
2800          </div>
2801          <div class="swym-storefront-layout-grid-item-action-container">
2802            ${!isHidden && this.isSfsQuantityFeatureEnabled() ? `<div class="swym-storefront-layout-quantity-container">
2803              <div class="swym-storefront-layout-quantity-selector">
2804                <button type="button" class="swym-storefront-layout-quantity-btn swym-storefront-layout-quantity-minus" data-action="quantity-decrease" aria-label="${SwymStorefrontLayoutContext?.Strings?.decreaseQuantity || 'Decrease quantity'}">−</button>
2805                <input type="number" class="swym-storefront-layout-quantity-input" 
2806                       value="${this.item.qty || this.getMinQuantity()}" min="${this.getMinQuantity()}" ${this.getMaxQuantity() ? `max="${this.getMaxQuantity()}"` : ''} step="1" data-action="quantity-change">
2807                <button type="button" class="swym-storefront-layout-quantity-btn swym-storefront-layout-quantity-plus" data-action="quantity-increase" aria-label="${SwymStorefrontLayoutContext?.Strings?.increaseQuantity || 'Increase quantity'}">+</button>
2808              </div>
2809            </div>` : ''}
2810          ${isAutoWishlist && isFirstVariant && !noVariant && !isHidden && !this._variantConfirmed ?
2811            `<button class="swym-variant-selector">
2812              ${window.SwymStorefrontLayoutContext?.Strings?.VariantSelectorBtnText}
2813              <svg xmlns="http://www.w3.org/2000/svg" width="7" height="11" viewB
2813ox="0 0 7 11" fill="none">
2814                            <path d="M1 9.5L5.44444 5.5L1 1.5" stroke="currentColor" stroke-width="1.5"/>
2815                          </svg>
2816            </button>` : ``}
2817            ${isAutoWishlist && !isHidden && (
2818                !isFirstVariant || noVariant || (isFirstVariant && !noVariant && this._variantConfirmed)
2819              ) ?
2820              `<div class="swym-sfy-action-row">
2821                <button class="swym-storefront-layout-grid-item-add-to-cart-button" data-action="add-to-cart"
2822                  ${!this.selectedVariant?.available || isDisabled ? 'disabled' : ''}>
2823                  ${this.getButtonState()}
2824                </button>
2825                <button class="swym-sfy-add-to-wishlist-btn ${SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer' ? 'swym-sfy-heart-btn' : ''}" data-action="add-to-wishlist" aria-label="${SwymStorefrontLayoutContext?.Strings?.sfyAddToWishlistCta || 'Add to Wishlist'}">
2826                  ${SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer' ? (SwymStorefrontLayoutExtensions?.getWishlistIconSvg?.('unfilled', { width: '17', height: '16' }) || '') : (SwymStorefrontLayoutContext?.Strings?.sfyAddToWishlistCta || 'Add to Wishlist')}
2827                </button>
2828              </div>` : ""
2829            }
2830            ${isAutoWishlist && !isHidden && isFirstVariant && !noVariant && !this._variantConfirmed ?
2831              `<button class="swym-sfy-add-to-wishlist-btn ${SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer' ? 'swym-sfy-heart-btn' : ''}" data-action="add-to-wishlist" aria-label="${SwymStorefrontLayoutContext?.Strings?.sfyAddToWishlistCta || 'Add to Wishlist'}">
2832                ${SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer' ? (SwymStorefrontLayoutExtensions?.getWishlistIconSvg?.('unfilled', { width: '17', height: '16' }) || '') : (SwymStorefrontLayoutContext?.Strings?.sfyAddToWishlistCta || 'Add to Wishlist')}
2833              </button>` : ""
2834            }
2835            ${!isAutoWishlist && !isHidden ? 
2836              `<button class="swym-storefront-layout-grid-item-add-to-cart-button" data-action="add-to-cart"
2837              ${!this.selectedVariant?.available || isDisabled ? 'disabled' : ''}>
2838              ${this.getButtonState()}
2839            </button>`: ""
2840            }
2841          </div>
2842        </div>
2843        ${this.renderOptionButton()}
2844      </div>
2845    `;
2846
2847  }
2848
2849  initItemElements(){
2850    this.elements = {
2851      AddToCartButton: this.querySelector('[data-action="add-to-cart"]'),
2852      AddToWishlistButton: this.querySelector('[data-action="add-to-wishlist"]'),
2853      Image: this.querySelector('.swym-storefront-layout-grid-item-image'),
2854      Price: this.querySelector('.swym-storefront-layout-grid-item-final-price'),
2855      ComparePrice: this.querySelector('.swym-storefront-layout-grid-item-compare-price'),
2856      OptionButton: this.querySelector('.swym-storefront-layout-grid-item-option-button'),
2857      sflItemsContainer : document.querySelector(`swym-storefront-layout-sfl-container .swym-storefront-layout-items-container`),
2858      swymVariantSelector: this.querySelector('.swym-variant-selector'),
2859      QuantityInput: this.querySelector('.swym-storefront-layout-quantity-input'),
2860      QuantityMinusBtn: this.querySelector('[data-action="quantity-decrease"]'),
2861      QuantityPlusBtn: this.querySelector('[data-action="quantity-increase"]')
2862    }
2863    
2864    // Initialize button states (only if SFS quantity feature is enabled)
2865    if (this.isSfsQuantityFeatureEnabled()) {
2866      this.updateQuantityButtonStates();
2867    }
2868  }
2869
2870  addEventListeners() {
2871    // Re-entrant calls (e.g. after variant-selector confirmation) must tear down
2872    // the previous set of listeners first, otherwise they accumulate on every re-render.
2873    this._listenerController?.abort();
2874    this._listenerController = new AbortController();
2875    const { signal } = this._listenerController;
2876
2877    this.elements.AddToCartButton?.addEventListener('click', (event) => {
2878      if(this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.SaveForLaterItem){
2879        this.handleMoveToCart(event);
2880      }else{
2881        this.handleAddToCart(event);
2882      }
2883    }, { signal });
2884    this.elements.OptionButton?.addEventListener('click', (event) => {
2885      if(SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.isTooltipOpen && SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.currentTarget === event.target){
2886        SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.closeTooltip();
2887        this.elements.OptionButton?.setAttribute('aria-expanded', 'false');
2888      }else{
2889        if(this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.WishlistItem || this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.CollectionItem){
2890          SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.setData({
2891            listId: this.list.lid,
2892            list: this.list,
2893            item: this.item,
2894            selectedVariantId: this.selectedVariant?.id,
2895            collections: this.collections,
2896            actionType: SwymStorefrontLayoutContext?.ActionTypes.ManageListItem,
2897            canCreateLists: this.canCreateLists
2898          });
2899          SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.showOnTarget(event.target);
2900        }else if(this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.SaveForLaterItem){
2901          SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.setData({
2902            listId: this.sflList?.lid,
2903            list: this.sflList,
2904            item: this.item,
2905            selectedVariantId: this.selectedVariant?.id,
2906            collections: this.collections,
2907            actionType: SwymStorefrontLayoutContext?.ActionTypes.ManageSflListItem,
2908            canCreateLists: this.canCreateLists
2909          });
2910          SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.showOnTarget(event.target);
2911        }else if(this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.SavedForYouItem){
2912          SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.setData({
2913            listId: this.list?.lid,
2914            list: this.list,
2915            item: this.item,
2916            selectedVariantId: this.selectedVariant?.id,
2917            collections: this.collections,
2918            actionType: SwymStorefrontLayoutContext?.ActionTypes.ManageSfyListItem,
2919            canCreateLists: this.canCreateLists
2920          });
2921          SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.showOnTarget(event.target);
2922        }
2923        this.elements.OptionButton?.setAttribute('aria-expanded', 'true');
2924      }
2925    }, { signal });
2926    // Keyboard support for options button
2927    this.elements.OptionButton?.addEventListener('keydown', (e) => {
2928      if (e.key === 'Enter' || e.key === ' ') {
2929        e.preventDefault();
2930        this.elements.OptionButton.click();
2931      }
2932    }, { signal });
2933    this.elements.AddToWishlistButton?.addEventListener('click', (event) => {
2934      event.preventDefault();
2935      this.handleMoveToWishlist();
2936    }, { signal });
2937    this.elements.AddToWishlistButton?.addEventListener('keydown', (e) => {
2938      if (e.key === 'Enter' || e.key === ' ') {
2939        e.preventDefault();
2940        this.handleMoveToWishlist();
2941      }
2942    }, { signal });
2943    const variantSelectors = this.querySelectorAll('.swym-storefront-layout-variant-selector');
2944    variantSelectors?.forEach((selector) =>
2945      selector.addEventListener('change', () => this.handleVariantSelectionChange(), { signal })
2946    );
2947    this.elements.swymVariantSelector?.addEventListener('click', (event) => {
2948      if (!window.SwymStorefrontLayoutExtensions) {
2949        window.SwymStorefrontLayoutExtensions = {};
2950      }
2951      window.SwymStorefrontLayoutExtensions._vsActiveItem = this;
2952      
2953      window._swat.evtLayer.dispatchEvent(new CustomEvent("sw:renderVS", {
2954        detail: {
2955          variant: this.selectedVariant,
2956          lid: this.item.lid,
2957          product: {
2958            epi: this.item.epi,
2959            empi: this.item.empi, 
2960            dt: this.item.dt,
2961            variants: this.item.productData.variants,
2962            du: this.item?.['du-mkt'] || this.item.du,
2963            options: this.item.productData.options
2964          }
2965        }
2966      }))
2967    }, { signal });
2968
2969    // Add quantity input event listeners (only if SFS quantity feature is enabled)
2970    if (this.isSfsQuantityFeatureEnabled()) {
2971      this.elements.QuantityInput?.addEventListener('change', (event) => {
2972        this.handleQuantityChange(event);
2973      }, { signal });
2974
2975      this.elements.QuantityInput?.addEventListener('blur', (event) => {
2976        this.validateQuantityInput(event);
2977      }, { signal });
2978
2979      // Add plus/minus button event listeners
2980      this.elements.QuantityMinusBtn?.addEventListener('click', (event) => {
2981        this.handleQuantityDecrease(event);
2982      }, { signal });
2983
2984      this.elements.QuantityPlusBtn?.addEventListener('click', (event) => {
2985        this.handleQuantityIncrease(event);
2986      }, { signal });
2987    }
2988  }
2989
2990  async handleDirectRemove() {
2991    try {
2992      const { epi, empi, du } = this.item;
2993      const lid = (this.list || this.sflList)?.lid;
2994
2995      if (this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.SavedForYouItem) {
2996        // SFY item: optimistic UI update + API call (same pattern as addSfyOptionEventListeners)
2997        SwymStorefrontLayoutContext.updateAllListContents((listcontents = []) =>
2998          listcontents.filter(item => String(item.epi) !== String(epi))
2999        );
3000        if (SwymStorefrontLayoutContext?.CustomEvents?.WishlistFetched) {
3001          document.dispatchEvent(new CustomEvent(SwymStorefrontLayoutContext.CustomEvents.WishlistFetched, {
3002            detail: {
3003              defaultList: SwymStorefrontLayoutContext.DefaultList,
3004              collections: SwymStorefrontLayoutContext.collections,
3005              lists: SwymStorefrontLayoutContext.lists
3006            }
3007          }));
3008        }
3009        SwymStorefrontLayoutExtensions?.Notification?.setMessage({
3010          message: SwymStorefrontLayoutContext?.Strings?.notificationMessageItemRemoved,
3011          status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Toast,
3012          duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
3013          image: this.item?.iu
3014        });
3015        await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.removeProductFromList({ epi, empi, du }, lid);
3016        SwymStorefrontLayoutExtensions?.refreshWishList();
3017        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutSFYItemRemoved, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutItemInteractions, epi, empi });
3018      } else if (this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.SaveForLaterItem) {
3019        // SFL item: use removeProductFromSFL (same pattern as addSflOptionEventListeners)
3020        let selectedEpi = this.selectedVariant?.id || epi;
3021        await SwymStorefrontLayoutAPI?.SwymSFLAsyncApis?.removeProductFromSFL({ epi: selectedEpi, empi, du }, SwymStorefrontLayoutContext?.sflListId);
3022        this.remove();
3023        window._swat?.triggerSwymEvent(window._swat?.JSEvents?.removedFromSFL, this.item);
3024      } else {
3025        // Regular wishlist item: use same pattern as removeFromListBtn in addOptionEventListeners
3026        let selectedEpi = this.selectedVariant?.id || epi;
3027        await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.removeProductFromList({ epi: selectedEpi, empi, du }, lid);
3028        this.remove();
3029        SwymStorefrontLayoutExtensions?.refreshWishList();
3030        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutItemRemovedFromList, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutItemInteractions, epi: selectedEpi, empi });
3031      }
3032    } catch (error) {
3033      window._swat?.utils.error('Failed to remove product:', error);
3034    }
3035  }
3036
3037  async handleMoveToWishlist() {
3038    try {
3039      const { empi, du } = this.item;
3040      const epi = this.selectedVariant?.id || this.item.epi;
3041      const lid = this.list?.lid;
3042
3043      // Check multi-wishlist config
3044      const { shouldShowMultiple, canCreateLists } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
3045
3046      if (shouldShowMultiple) {
3047        // Multi-list: open AddToCollection drawer so user picks the target list
3048        SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActions?.setData({
3049          listId: lid,
3050          list: this.list,
3051          item: this.item,
3052          collections: SwymStorefrontLayoutContext?.collections || [],
3053          actionType: SwymStorefrontLayoutContext?.ActionTypes.AddToCollection,
3054          canCreateLists: canCreateLists
3055        });
3056        SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActions?.openDrawer();
3057        return;
3058      }
3059
3060      // Single list: move to default wishlist directly
3061      const atwBtn = this.querySelector('[data-action="add-to-wis
3061hlist"]');
3062      if (atwBtn) {
3063        atwBtn.innerHTML = SwymStorefrontLayoutContext?.Strings?.addingToWishlist || 'Adding...';
3064        atwBtn.setAttribute('disabled', 'true');
3065      }
3066
3067      // Instant local state update across ALL context references
3068      SwymStorefrontLayoutContext.updateAllListContents((listcontents = []) =>
3069        listcontents.map(item =>
3070          String(item.epi) === String(epi) ? { ...item, source: undefined } : item
3071        )
3072      );
3073
3074      // Switch to Wishlist tab and update UI immediately
3075      SwymStorefrontLayoutContext.SelectedLayoutView = SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.Wishlist;
3076      if (SwymStorefrontLayoutContext?.CustomEvents?.WishlistFetched) {
3077        document.dispatchEvent(new CustomEvent(SwymStorefrontLayoutContext.CustomEvents.WishlistFetched, {
3078          detail: {
3079            defaultList: SwymStorefrontLayoutContext.DefaultList,
3080            collections: SwymStorefrontLayoutContext.collections,
3081            lists: SwymStorefrontLayoutContext.lists
3082          }
3083        }));
3084      }
3085
3086      SwymStorefrontLayoutExtensions?.Notification?.setMessage({
3087        message: SwymStorefrontLayoutContext?.Strings?.notificationMessageItemSaved,
3088        status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Toast,
3089        iconType: SwymStorefrontLayoutContext?.NotificationIconType?.SuccessIcon
3090      });
3091
3092      // Fire API calls THEN refresh; suppress duplicate notifications from SDK event listeners
3093      SwymStorefrontLayoutContext._sfyMoveToWishlist = true;
3094      try {
3095        await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.removeProductFromList({ epi, empi, du }, lid);
3096        await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.addProductToLists({ epi, empi, du }, [lid]);
3097      } finally {
3098        SwymStorefrontLayoutContext._sfyMoveToWishlist = false;
3099        SwymStorefrontLayoutExtensions?.refreshWishList();
3100      }
3101
3102      window._swat?.instrumentV3(
3103        SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutSFYItemMovedToWishlist,
3104        { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutItemInteractions, epi, empi }
3105      );
3106    } catch (err) {
3107      window._swat?.utils.error('[SFY] Move to wishlist failed', err);
3108    }
3109  }
3110
3111  handleAddToCart(event) {
3112    event.preventDefault();
3113    let button = event.target;
3114
3115    let { empi, epi, du } = this.dataset;
3116    let quantity = this.getCurrentQuantity();
3117
3118    let originalButtonState = button.innerHTML;
3119    button.innerHTML = SwymStorefrontLayoutContext?.Strings?.addingToCart;
3120    button.setAttribute('disabled', true);
3121
3122    _swat.api.replayAddToCart(
3123      { empi: +empi, du: du, qty: quantity },
3124      +epi,
3125      (success) => {
3126        button.innerHTML = SwymStorefrontLayoutContext?.Strings?.addedToCart;
3127        button.removeAttribute('disabled');
3128
3129        SwymStorefrontLayoutExtensions?.Notification?.setMessage({
3130          message: SwymStorefrontLayoutContext?.Strings?.notificationMessageAddedToCart,
3131          status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Neutral,
3132          actionType: SwymStorefrontLayoutContext?.NotificationActionTypes.AddedToCart,
3133          image: this.item.iu,
3134          product: this.item,
3135          title: this.item?.productData?.title || this.item?.dt,
3136          duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
3137          action: {
3138            label: SwymStorefrontLayoutContext?.Strings?.notificationActionGoToCart,
3139            onClick: () => {
3140              window.location.href = `${window.Shopify.routes.root}cart`;
3141            }
3142          }
3143        }, {
3144          showActionButton: true,
3145          showTitle: true
3146        });
3147
3148        if (this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.SavedForYouItem) {
3149          window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutSFYItemAddedToCart, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutCartConversion, epi, empi });
3150        } else {
3151          window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutItemAddedToCart, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutCartConversion, epi, empi });
3152        }
3153        window?._SwymAJAXCart();
3154      },
3155      (error) => {
3156        button.innerHTML = originalButtonState;
3157        button.removeAttribute('disabled');
3158        window._swat?.utils.warn('Error :', error.description);
3159        SwymStorefrontLayoutExtensions?.Notification?.setMessage({
3160          title: error.description,
3161          status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Error
3162        },{
3163          showTitle: true,
3164          showImage: false
3165        });
3166      }
3167    );
3168  }
3169
3170  handleMoveToCart(event) {
3171    event.preventDefault();
3172    let button = event.target;
3173
3174    let { empi, epi, du } = this.dataset;
3175    let quantity = this.getCurrentQuantity();
3176
3177    let originalButtonState = button.innerHTML;
3178    button.innerHTML = SwymStorefrontLayoutContext?.Strings?.movingToCartCta;
3179    button.setAttribute('disabled', true);
3180    
3181    window._swat?.api.replayAddToCart(
3182      { empi: +empi, du: du, qty: quantity },
3183      +epi,
3184      async (success) => {
3185        try{
3186          await SwymStorefrontLayoutAPI?.SwymSFLAsyncApis?.removeProductFromSFL({ epi, empi, du }, SwymStorefrontLayoutContext.sflListId);
3187          let elementDeleted = this.elements.sflItemsContainer?.querySelector(`[data-epi="${epi}"]`);
3188          elementDeleted?.remove();
3189          window._swat?.triggerSwymEvent(window._swat?.JSEvents?.movedToCartFromSFL, this.item);
3190
3191          SwymStorefrontLayoutExtensions?.Notification?.setMessage({
3192            message: SwymStorefrontLayoutContext?.Strings?.notificationMessageMovedToCart,
3193            status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Neutral,
3194            actionType: SwymStorefrontLayoutContext?.NotificationActionTypes.AddedToCart,
3195            image: this.item.iu,
3196            product: this.item,
3197            title: this.item?.productData?.title || this.item?.dt,
3198            duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
3199            action: {
3200              label: SwymStorefrontLayoutContext?.Strings?.notificationActionGoToCart,
3201              onClick: () => {
3202                window.location.href = `${window.Shopify.routes.root}cart`;
3203              }
3204            }
3205          }, {
3206            showActionButton: true,
3207            showTitle: true
3208          });
3209  
3210          window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutSFLItemMovedToCart, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutCartConversion, epi, empi });
3211          window?._SwymAJAXCart();
3212        }catch(error){
3213          button.innerHTML = originalButtonState;
3214          button.removeAttribute('disabled');
3215          window._swat?.utils.warn('Error removing SFL Items:', error);
3216        }
3217
3218      },
3219      (error) => {
3220        button.innerHTML = originalButtonState;
3221        button.removeAttribute('disabled');
3222        window._swat?.utils.warn('Error :', error.description);
3223        SwymStorefrontLayoutExtensions?.Notification?.setMessage({
3224          title: error.description,
3225          status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Error
3226        },{
3227          showTitle: true,
3228          showImage: false
3229        });
3230      }
3231    );
3232  }
3233
3234  async handleVariantSelectionChange() {
3235
3236    let selectedOptions = {};
3237    const variantSelectors = this.querySelectorAll(".swym-storefront-layout-variant-selector");
3238    
3239    variantSelectors.forEach((selector) => {
3240      const selectedValue = selector.value?.trim();
3241      const optionIndex = selector.dataset.optionindex;
3242    
3243      if (selectedValue && optionIndex) {
3244        selectedOptions[`option${optionIndex}`] = selectedValue;
3245      }
3246    });
3247    
3248    const selectedVariant = this.item.productData.variants.find((variant) =>
3249      Object.entries(selectedOptions).every(([key, value]) => variant[key] === value)
3250    );
3251
3252    this.selectedVariant = selectedVariant;
3253    this.dataset.epi = selectedVariant.id;
3254    this.item.cprops = this.item.cprops ?? {};
3255    this.item.cprops.selectedVariantId = selectedVariant.id;
3256
3257    if (selectedVariant) {
3258      const buttonText = this.getButtonState();
3259      this.elements.AddToCartButton.textContent = buttonText;
3260      // The button relies on its text content for its accessible name
3261      if (selectedVariant.available) {
3262        this.elements.AddToCartButton.removeAttribute('disabled');
3263      } else {
3264        this.elements.AddToCartButton.setAttribute('disabled', true);
3265      }
3266
3267      this.elements.Price.textContent =this.getFormattedPrice();
3268      this.elements.ComparePrice.textContent = this.getFormattedComparePrice();
3269
3270      const productImage = selectedVariant?.featured_image?.src || this.item.productData?.featured_image || item.iu;
3271      this.elements.Image.src = productImage;
3272
3273      let canEdit = (this.list?.userinfo?.em === SwymStorefrontLayoutContext?.SwymCustomerData?.email) || this.list?.canEdit;
3274
3275      if(SwymStorefrontLayoutContext?.checkUserCanEditList(this.list)){
3276        let { epi, empi, du } = this.item;
3277        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutVariantChanged, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutItemInteractions, epi, empi });
3278        await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.updateProductFromList({ epi, empi, du, cprops: { selectedVariantId: selectedVariant.id } }, this.list.lid);
3279      }
3280    } else {
3281      window._swat?.utils.warn("No matching variant found for the selected options:", selectedOptions);
3282    }
3283  }
3284
3285  validateQuantityInput(event) {
3286    if (!this.isSfsQuantityFeatureEnabled()) return;
3287    
3288    const input = event.target;
3289    let value = parseInt(input.value);
3290    const minQty = this.getMinQuantity();
3291    const maxQty = this.getMaxQuantity();
3292    const quantitySelector = input.closest('.swym-storefront-layout-quantity-selector');
3293    
3294    let hasError = false;
3295    
3296    // Check if value is within bounds
3297    if (isNaN(value) || value < minQty || (maxQty && value > maxQty)) {
3298      hasError = true;
3299    }
3300    
3301    // Add or remove error styling
3302    if (quantitySelector) {
3303      if (hasError) {
3304        quantitySelector.classList.add('swym-quantity-error');
3305        // Don't auto-correct the value, keep the invalid value visible
3306        
3307        // Show error toast notification
3308        const minQty = this.getMinQuantity();
3309        const maxQty = this.getMaxQuantity();
3310        let errorMessage = '';
3311        
3312        if (isNaN(value) || value < minQty) {
3313          errorMessage = `Minimum allowed quantity is ${minQty}`;
3314        } else if (maxQty && value > maxQty) {
3315          errorMessage = `Maximum allowed quantity is ${maxQty}`;
3316        }
3317        
3318        SwymStorefrontLayoutExtensions?.Notification?.setMessage({
3319          title: errorMessage,
3320          status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Error,
3321          duration: 3000
3322        }, {
3323          showTitle: true,
3324          showImage: false
3325        });
3326      } else {
3327        quantitySelector.classList.remove('swym-quantity-error');
3328        // Only update the item quantity if it's valid
3329        this.item.qty = value;
3330        // Debounce the backend update for valid values
3331        this.debouncedUpdateItemQuantity(value);
3332      }
3333    }
3334    
3335    // Update button states
3336    this.updateQuantityButtonStates();
3337  }
3338
3339  handleQuantityChange(event) {
3340    if (!this.isSfsQuantityFeatureEnabled()) return;
3341    
3342    const input = event.target;
3343    const newQuantity = parseInt(input.value);
3344    const minQty = this.getMinQuantity();
3345    const maxQty = this.getMaxQuantity();
3346    
3347    // Only update if the quantity is valid
3348    if (!isNaN(newQuantity) && newQuantity >= minQty && (!maxQty || newQuantity <= maxQty)) {
3349      // Update the item's quantity
3350      this.item.qty = newQuantity;
3351      
3352      // Debounce the backend update
3353      this.debouncedUpdateItemQuantity(newQuantity);
3354    }
3355    
3356    // Always update button states
3357    this.updateQuantityButtonStates();
3358  }
3359
3360  async updateItemQuantity(quantity) {
3361    try {
3362      const minQty = this.getMinQuantity();
3363      const maxQty = this.getMaxQuantity();
3364      
3365      // Validate quantity before updating
3366      if (quantity < minQty || (maxQty && quantity > maxQty)) {
3367        window._swat?.utils.warn(`Quantity ${quantity} is outside allowed range (${minQty}${maxQty ? `-${maxQty}` : '+'})`);
3368        return;
3369      }
3370      
3371      if (this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.WishlistItem || 
3372          this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.CollectionItem) {
3373        
3374        // Update wishlist item quantity
3375        const updatedItem = { epi: this.item?.epi, empi: this.item?.empi, du: this.item?.du, qty: quantity };
3376        await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.updateProductFromList(updatedItem, this.list.lid);
3377        
3378      } else if (this.listItemType === SwymStorefrontLayoutContext?.ListItemType?.SaveForLaterItem) {
3379        
3380        // Update SFL item quantity
3381        const updatedItem = { epi: this.item?.epi, empi: this.item?.empi, du: this.item?.du, qty: quantity };
3382        await SwymStorefrontLayoutAPI?.SwymSFLAsyncApis?.updateProductInSFL(updatedItem, SwymStorefrontLayoutContext.sflListId);
3383        
3384      }
3385    } catch (error) {
3386      window._swat?.utils.warn('Error updating item quantity:', error);
3387      // Revert the input value on error
3388      if (this.elements.QuantityInput) {
3389        this.elements.QuantityInput.value = this.item.qty || this.getMinQuantity();
3390      }
3391    }
3392  }
3393
3394  getCurrentQuantity() {
3395    if (!this.isSfsQuantityFeatureEnabled()) {
3396      return this.item.qty || 1;
3397    }
3398    return parseInt(this.elements.QuantityInput?.value) || this.item.qty || 1;
3399  }
3400
3401  debouncedUpdateItemQuantity(quantity) {
3402    // Clear any existing timeout
3403    if (this.quantityUpdateTimeout) {
3404      clearTimeout(this.quantityUpdateTimeout);
3405    }
3406    
3407    // Set a new timeout for 500ms
3408    this.quantityUpdateTimeout = setTimeout(() => {
3409      this.updateItemQuantity(quantity);
3410    }, 500);
3411  }
3412
3413  isSfsQuantityFeatureEnabled() {
3414    try {
3415      const retailerSettings = window._swat?.retailerSettings;
3416      if (!retailerSettings) return false;
3417      
3418      // Check if WishlistPlusPDPButtonAPI is available and use its SFS check
3419      if (typeof window.WishlistPlusPDPButtonAPI?.isSfsFeatureEnabled === 'function') {
3420        return window.WishlistPlusPDPButtonAPI.isSfsFeatureEnabled('WishlistQuantity', retailerSettings);
3421      }
3422      
3423        // Fallback: Check if SFS/EngageUI is enabled
3424        const SFSEnabled = retailerSettings?.General?.EngageUI?.Enabled;
3425        const features = retailerSettings?.General?.EngageUI?.Features;
3426      const quantityFeatureEnabled = features?.some(
3427        (feature) => feature?.featureName === 'WishlistQuantity' && feature?.enabled === true
3428      );
3429      
3430      return SFSEnabled && quantityFeatureEnabled;
3431    } catch (error) {
3432      window._swat?.utils.warn('Error checking SFS quantity feature:', error);
3433      return false;
3434    }
3435  }
3436
3437  updateQuantityButtonStates() {
3438    if (!this.isSfsQuantityFeatureEnabled()) return;
3439    
3440    const currentQty = this.getCurrentQuantity();
3441    const minQty = this.getMinQuantity();
3442    const maxQty = this.getMaxQuantity();
3443    const quantitySelector = this.elements.QuantityInput?.closest('.swym-storefront-layout-quantity-selector');
3444    const hasError = quantitySelector?.classList.contains('swym-quantity-error');
3445    
3446    // Update minus button state
3447    if (this.elements.QuantityMinusBtn) {
3448      if (hasError || currentQty <= minQty) {
3449        this.elements.QuantityMinusBtn.disabled = true;
3450      } else {
3451        this.elements.QuantityMinusBtn.disabled = false;
3452      }
3453    }
3454    
3455    // Update plus button state
3456    if (this.elements.QuantityPlusBtn) {
3457      if (hasError || (maxQty && currentQty >= maxQty)) {
3458        this.elements.QuantityPlusBtn.disabled = true;
3459      } else {
3460        this.elements.QuantityPlusBtn.disabled = false;
3461      }
3462    }
3463  }
3464
3465  handleQuantityDecrease(event) {
3466    if (!this.isSfsQuantityFeatureEnabled()) return;
3467    
3468    event.preventDefault();
3469    const currentQty = this.getCurrentQuantity();
3470    const minQty = this.getMinQuantity();
3471    if (currentQty > minQty) {
3472      const newQty = currentQty - 1;
3473      this.elements.QuantityInput.value = newQty;
3474      
3475      // Update the item's quantity immediately for UI responsiveness
3476      this.item.qty = newQty;
3477      
3478      // Update button states immediately
3479      this.updateQuantityButtonStates();
3480      
3481      // Debounce the backend update
3482      this.debouncedUpdateItemQuantity(newQty);
3483    }
3484  }
3485
3486  handleQuantityIncrease(event) {
3487    if (!this.isSfsQuantityFeatureEnabled()) return;
3488    
3489    event.preventDefault();
3490    const currentQty = this.getCurrentQuantity();
3491    const maxQty = this.getMaxQuantity();
3492    if (!maxQty || currentQty < maxQty) {
3493      const newQty = currentQty + 1;
3494      this.elements.QuantityInput.value = newQty;
3495      
3496      // Update the item's quantity immediately for UI responsiveness
3497      this.item.qty = newQty;
3498      
3499      // Update button states immediately
3500      this.updateQuantityButtonStates();
3501      
3502      // Debounce the backend update
3503      this.debouncedUpdateItemQuantity(newQty);
3504    }
3505  }
3506
3507}
3508
3509/**
3510 * SwymStorefrontLayoutDefaultWishList
3511 * 
3512 * This custom HTML element represents the default wishlist layout in the storefront.
3513 * It handles rendering wishlist items dynamically and updating the UI when new wishlist data is set.
3514 * 
3515 * Features:
3516 * - Initializes with a loading state until wishlist data is available.
3517 * - Fetches product details for wishlist items and updates the UI.
3518 * - Displays an empty state when no wishlist items exist.
3519 * - Uses Swym API and instrumentation to track interactions.
3520 * 
3521 * Usage:
3522 * <swym-storefront-layout-default-wishlist></swym-storefront-layout-default-wishlist>
3523 */
3524class SwymStorefrontLayoutDefaultWishList extends HTMLElement {
3525  constructor() {
3526    super();
3527    this.wishlist = null;
3528    this.collections = null;
3529    this.renderUI();
3530    this.elements = {
3531      title: this.querySelector('.swym-storefront-layout-default-list-title'),
3532      itemsContainer: this.querySelector('#swym-storefront-layout-items-container')
3533    }
3534  }
3535
3536  handleAddToCart(event, productDetail) {
3537    event.preventDefault();
3538    let button = event.target;
3539
3540    let empi = productDetail.empi; //8445423517851;
3541    let epi = productDetail.epi; //46212304076955;
3542    let du = productDetail.du; //"https://swym-test-onboarding-2-0.myshopify.com/products/the-collection-snowboard-hydrogen"
3543
3544    let originalButtonState = button.innerHTML;
3545    button.innerHTML = SwymStorefrontLayoutContext?.Strings?.addingToCart;
3546    button.setAttribute('disabled', true);
3547
3548    _swat.api.replayAddToCart(
3549      { empi: +empi, du: du, qty: 1 },
3550      +epi,
3551      (success) => {
3552        button.innerHTML = SwymStorefrontLayoutContext?.Strings?.addedToCart;
3553        button.removeAttribute('disabled');
3554
3555        SwymStorefrontLayoutExtensions?.Notification?.setMessage({
3556          message: SwymStorefrontLayoutContext?.Strings?.notificationMessageAddedToCart,
3557          status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Neutral,
3558          actionType: SwymStorefrontLayoutContext?.NotificationActionTypes.AddedToCart,
3559          image: "",
3560          product: "",
3561          duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
3562          action: {
3563            label: SwymStorefrontLayoutContext?.Strings?.notificationActionGoToCart,
3564            onClick: () => {
3565              window.location.href = `${window.Shopify.routes.root}cart`;
3566            }
3567          }
3568        }, {
3569          showActionButton: true,
3570          showTitle: true
3571        });
3572      },
3573      (error) => {
3574        button.innerHTML = originalButtonState;
3575        button.removeAttribute('disabled');
3576        window._swat?.utils.warn('Error :', error.description);
3577        SwymStorefrontLayoutExtensions?.Notification?.setMessage({
3578          title: error.description,
3579          status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Error
3580        },{
3581          showTitle: true,
3582          showImage: false
3583        });
3584      }
3585    );
3586  }
3587
3588  renderUI() {
3589    if(window.Shopify.designMode && !window.SwymCurrentStorePath) {
3590      const swymMockProductData = window.SwymSampleProduct;
3591      
3592      // Extract and clean up the IDs
3593      const swymMockProductId = swymMockProductData?.id?.replace('gid://shopify/Product/', '');
3594      const swymMockVariantId = swymMockProductData?.variants?.edges?.[0]?.node?.id?.replace('gid://shopify/ProductVariant/', '');
3595      
3596      // Construct the product URL using Shopify.shop
3597      const swymMockProductUrl = `https://${window.Shopify.shop}/products/${swymMockProductData?.handle}`;
3598      
3599      window.SwymParsedSampleProduct = {
3600        image: swymMockProductData?.variants?.edges?.[0]?.node?.image,
3601        empi: swymMockProductId,
3602        epi: swymMockVariantId,
3603        du: swymMockProductUrl,
3604        title: swymMockProductData?.variants?.edges?.[0]?.node?.title,
3605        price: `$${swymMockProductData?.variants?.edges?.[0]?.node?.price}`
3606      };
3607
3608      this.innerHTML = `<div id="swym-storefront-layout-items-container" class="swym-storefront-layout-items-container"><div class="swym-storefront-layout-grid-item">
3609          <a href="#" class="swym-storefront-layout-grid-item-image-container">
3610            <img src="${window.SwymParsedSampleProduct?.image}" alt="${window.SwymParsedSampleProduct?.title ? window.SwymParsedSampleProduct.title : 'Product image'}" class="swym-storefront-layout-grid-item-image" />
3611          </a>
3612          <div class="swym-storefront-layout-grid-item-content">
3613            <a href="${window.SwymParsedSampleProduct?.du}" class="swym-storefront-layout-grid-item-title">${window.SwymParsedSampleProduct.title || ''}</a>
3614            <div class="swym-storefront-layout-grid-item-price-variant">
3615              <span class="swym-storefront-layout-grid-item-final-price">${window.SwymParsedSampleProduct?.price}</span>
3616            </div>
3617            <div class="swym-storefront-layout-grid-item-action-container">
3618              <button class="swym-storefront-layout-grid-item-add-to-cart-button" data-action="add-to-cart">
3619                ${SwymStorefrontLayoutContext?.Strings?.addToCart || 'Add to cart'}
3620              </button>
3621            </div>
3622          </div>
3623        </div></div>`
3624
3625        const addToCartBtn = this.querySelector(".swym-storefront-layout-grid-item-add-to-cart-button");
3626        if (addToCartBtn) {
3627          addToCartBtn.addEventListener("click", (e) => {
3628            this.handleAddToCart(e, window.SwymParsedSampleProduct)
3629          });
3630        }
3631        return;
3632    }
3633    
3634    const { shouldShowMultiple, canCreateLists } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
3635
3636    this.innerHTML = `
3637      <div class="swym-storefront-layout-default-list-container">
3638      ${shouldShowMultiple ? `
3639          <div class="swym-storefront-layout-default-list-title-container"> 
3640            <div class="swym-storefront-layout-default-list-title">${SwymStorefrontLayoutContext?.Strings?.wishlistTitle}</div>
3641            <div class="swym-storefront-layout-default-list-info">${SwymStorefrontLayoutContext?.Strings?.wishlistInfo}</div>
3642          </div>
3643        ` : ''}
3644        <div class="swym-storefront-layout-add-all-to-cart-container swym-storefront-layout-add-all-to-cart-top"></div>
3645        <div id="swym-storefront-layout-items-container" class="swym-storefront-layout-items-container">
3646          <swym-storefront-layout-loader loading="true" loadertype="${SwymStorefrontLayoutContext?.LoaderViewType.WishlistListItem}" buttonCta="${SwymStorefrontLayoutContext?.Strings?.addToCart}" height="100px"></swym-storefront-layout-loader>
3647        </div>
3648        <div class="swym-storefront-layout-add-all-to-cart-container swym-storefront-layout-add-all-to-cart-bottom"></div>
3649      </div>
3650    `
3651  }
3652
3653  setData({ wishlist, collections, canCreateLists = true }) {
3654    this.wishlist = wishlist;
3655    this.collections = collections;
3656    this.canCreateLists = canCreateLists;
3657    if (this.elements?.itemsContainer?.dataset && this.wishlist?.lid) {
3658      this.elements.itemsContainer.dataset.lid = this.wishlist.lid;
3659    }
3660    this.renderWishlist();
3661  }
3662
3663  async renderWishlist() {
3664    SwymStorefrontLayoutExtensions?.AddAllToCart?.mount(this, this.wishlist);
3665    if (this.wishlist?.listcontents?.length && this.elements.itemsContainer) {
3666      
3667      window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutWishlistItemsRendered, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
3668
3669      const wishlistedProducts = this.wishlist?.listcontents;
3670      const fragment = document.createDocumentFragment();
3671
3672      wishlistedProducts.forEach((item) => {
3673        const wishlistItem = document.createElement('template');
3674        wishlistItem.innerHTML = `<swym-storefront-layout-item id="swym-storefront-layout-item-${item.empi}-${item.epi}" ></swym-storefront-layout-item>`;
3675        fragment.appendChild(wishlistItem.content);
3676      });
3677      
3678      this.elements.itemsContainer.innerHTML = '';
3679      this.elements.itemsContainer.appendChild(fragment);
3680
3681      wishlistedProducts.forEach((item) => {
3682        let wishlistItemElement = document.querySelector(`#swym-storefront-layout-item-${item.empi}-${item.epi}`);
3683        wishlistItemElement?.setData({
3684          item,
3685          listItemType: SwymStorefrontLayoutContext?.ListItemType?.WishlistItem,
3686          list: this.wishlist,
3687          collections: this.collections,
3688          canCreateLists: this.canCreateLists
3689        })
3690      });
3691      this.elements.itemsContainer.classList.remove('swym-storefront-layout-items-has-empty');
3692    }else{
3693      const isLoggedIn = SwymStorefrontLayoutContext?.isShopperLoggedIn;
3694      const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
3695      const rootUrl = (window.Shopify?.routes?.root || '/').replace(/\/$/, '');
3696      const accountUrl = `${rootUrl}/account`;
3697      const homeUrl = window.Shopify?.routes?.root || '/';
3698
3699      let emptyStateHtml = '';
3700      let noticeText = '';
3701
3702      if (!shouldShowMultiple && isLoggedIn) {
3703        // State 1: Single wishlist – Logged in (new rich design)
3704        emptyStateHtml = `
3705          <div class="swym-storefront-layout-empty-container swym-storefront-layout-empty-state-single-logged">
3706            <div class="swym-storefront-layout-empty-wishlist-container">
3707              <div class="swym-storefront-layout-empty-wishlist-content">
3708                <div class="swym-storefront-layout-empty-state-icon">
3709                  <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="none">
3710                    <circle cx="24" cy="24" r="24" fill="#F5F5F5"/>
3711                    <path d="M20 18H18C17.4696 18 16.9609 18.2107 16.5858 18.5858C16.2107 18.9609 16 19.4696 16 20V32C16 32.5304 16.2107 33.0391 16.5858 33.4142C16.9609 33.7893 17.4696 34 18 34H30C30.5304 34 31.0391 33.7893 31.4142 33.4142C31.7893 33.0391 32 32.5304 32 32V20C32 19.4696 31.7893 18.9609 31.4142 18.5858C31.0391 18.2107 30.5304 18 30 18H28M20 18V16C20 15.4696 20.2107 14.9609 20.5858 14.5858C20.9609 14.2107 21.4696 14 22 14H26C26.5304 14 27.0391 14.2107 27.4142 14.5858C27.7893 14.9609 28 15.4696 28 16V18M20 18H28M24 24V28M22 26H26" stroke="#9B9B9B" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
3712                  </svg>
3713                  <span class="swym-storefront-layout-empty-state-badge">
3714                    <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none">
3715                      <circle cx="7" cy="7" r="7" fill="#E8A0BF"/>
3716                      <path d="M7 4V10M4 7H10" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
3717                    </svg>
3718                  </span>
3719                </div>
3720                <div class="swym-storefront-layout-empty-wishlist-title">${SwymStorefrontLayoutContext?.Strings?.emptySingleLoggedInTitle || ''}</div>
3721                <div class="swym-storefront-layout-empty-wishlist-description">${SwymStorefrontLayoutContext?.Strings?.emptySingleLoggedInDescription || ''}</div>
3722                <div class="swym-storefront-layout-empty-state-card">
3723                  <ul class="swym-storefront-layout-empty-state-bullet-list">
3724                    <li>${SwymStorefrontLayoutContext?.Strings?.emptySingleLoggedInBullet1 || ''}</li>
3725                    <li>${SwymStorefrontLayoutContext?.Strings?.emptySingleLoggedInBullet2 || ''}</li>
3726                    <li>${SwymStorefrontLayoutContext?.Strings?.emptySingleLoggedInBullet3 || ''}</li>
3727                  </ul>
3728                </div>
3729                <hr class="swym-storefront-layout-empty-state-divider" />
3730                <a href="${homeUrl}" class="swym-storefront-layout-empty-state-cta-button swym-storefront-layout-empty-state-start-browsing">
3731                  ${SwymStorefrontLayoutContext?.Strings?.emptySingleLoggedInCTA || ''}
3732                  <svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" viewBox="0 0 14 9" fill="none"><path d="M13.8536 4.85368C14.0488 4.65841 14.0488 4.34183 13.8536 4.14657L10.6716 0.964589C10.4763 0.769327 10.1597 0.769327 9.96447 0.964589C9.7692 1.15985 9.7692 1.47643 9.96447 1.6717L12.7929 4.50012L9.96447 7.32855C9.7692 7.52381 9.7692 7.84039 9.96447 8.03566C10.1597 8.23092 10.4763 8.23092 10.6716 8.03566L13.8536 4.85368ZM0.5 5.00012L13.5 5.00012L13.5 4.00012L0.5 4.00012L0.5 5.00012Z" fill="currentColor"/></svg>
3733                </a>
3734              </div>
3735            </div>
3736          </div>
3737        `;
3738      } else if (!shouldShowMultiple && !isLoggedIn) {
3739        // State 2: Single wishlist – Guest (new rich design)
3740        noticeText = SwymStorefrontLayoutContext?.Strings?.emptyGuestSingleNotice || '';
3741
3742        emptyStateHtml = `
3743          <div class="swym-storefront-layout-empty-container swym-storefront-layout-empty-state-guest">
3744            <div class="swym-storefront-layout-empty-wishlist-container">
3745              <div class="swym-storefront-layout-empty-wishlist-content">
3746                <div class="swym-storefront-layout-empty-state-icon">
3747                  <svg xmlns="http://www.w3.org/2000/svg" width="56" height="56" viewB
3747ox="0 0 56 56" fill="none">
3748                    <circle cx="28" cy="28" r="28" fill="#F5F3FF"/>
3749                    <path d="M28 38L17.55 28.03C16.6264 27.0846 16.0453 25.8579 15.8955 24.5427C15.7457 23.2275 16.0356 21.8986 16.72 20.766C17.4045 19.6334 18.4445 18.7606 19.6772 18.2842C20.9099 17.8079 22.2674 17.7551 23.533 18.134C24.468 18.4101 25.3178 18.916 26.005 19.604L28 21.6L29.995 19.604C30.6822 18.916 31.532 18.4101 32.467 18.134C33.7326 17.7551 35.0901 17.8079 36.3228 18.2842C37.5555 18.7606 38.5955 19.6334 39.28 20.766C39.9644 21.8986 40.2543 23.2275 40.1045 24.5427C39.9547 25.8579 39.3736 27.0846 38.45 28.03L28 38Z" stroke="#8B7EC8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" fill="#C8B8F0"/>
3750                  </svg>
3751                </div>
3752                <div class="swym-storefront-layout-empty-wishlist-title">${SwymStorefrontLayoutContext?.Strings?.emptyGuestTitle || ''}</div>
3753                <div class="swym-storefront-layout-empty-wishlist-description">${SwymStorefrontLayoutContext?.Strings?.emptyGuestDescription || ''}</div>
3754                <div class="swym-storefront-layout-empty-state-notice">
3755                  <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none">
3756                    <circle cx="9" cy="9" r="8" stroke="#B45309" stroke-width="1.2"/>
3757                    <path d="M9 5V9L11 11" stroke="#B45309" stroke-width="1.2" stroke-linecap="round"/>
3758                  </svg>
3759                  <span class="swym-storefront-layout-empty-state-notice-text"></span>
3760                </div>
3761                <hr class="swym-storefront-layout-empty-state-divider" />
3762                <a href="${accountUrl}" class="swym-storefront-layout-empty-state-cta-button swym-storefront-layout-empty-state-login-cta">
3763                  ${SwymStorefrontLayoutContext?.Strings?.emptyGuestLoginCTA || ''}
3764                  <svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" viewBox="0 0 14 9" fill="none"><path d="M13.8536 4.85368C14.0488 4.65841 14.0488 4.34183 13.8536 4.14657L10.6716 0.964589C10.4763 0.769327 10.1597 0.769327 9.96447 0.964589C9.7692 1.15985 9.7692 1.47643 9.96447 1.6717L12.7929 4.50012L9.96447 7.32855C9.7692 7.52381 9.7692 7.84039 9.96447 8.03566C10.1597 8.23092 10.4763 8.23092 10.6716 8.03566L13.8536 4.85368ZM0.5 5.00012L13.5 5.00012L13.5 4.00012L0.5 4.00012L0.5 5.00012Z" fill="currentColor"/></svg>
3765                </a>
3766                <button class="swym-storefront-layout-empty-state-cta-button swym-storefront-layout-empty-state-browse-cta" data-action="close-drawer">
3767                  ${SwymStorefrontLayoutContext?.Strings?.emptyGuestBrowseCTA || ''}
3768                </button>
3769                <div class="swym-storefront-layout-empty-state-signup-text">
3770                  ${SwymStorefrontLayoutContext?.Strings?.emptyGuestSignupText || ''} <a href="${accountUrl}" class="swym-storefront-layout-empty-state-signup-link">${SwymStorefrontLayoutContext?.Strings?.emptyGuestSignupCTA || ''}</a>
3771                </div>
3772              </div>
3773            </div>
3774          </div>
3775        `;
3776      } else {
3777        // Multi wishlist – old simple empty state (logged in or guest)
3778        emptyStateHtml = `
3779          <div class="swym-storefront-layout-empty-container">
3780            <div class="swym-storefront-layout-empty-wishlist-container">
3781              <div class="swym-storefront-layout-empty-wishlist-content">
3782                <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="85" viewBox="0 0 86 85" fill="none">
3783                <rect width="59.5441" height="78.6833" transform="translate(0.710449 6.1748) rotate(-5.46887)" fill="white"/>
3784                <rect x="0.710938" y="6.1748" width="59.5441" height="78.6833" rx="1.21519" transform="rotate(-5.46887 0.710938 6.1748)" fill="#FDFDFD"/>
3785                <rect x="0.983626" y="6.39984" width="59.0441" height="78.1833" rx="0.965186" transform="rotate(-5.46887 0.983626 6.39984)" stroke="black" stroke-opacity="0.1" stroke-width="0.5"/>
3786                <rect x="5.57364" y="10.7446" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 5.57364 10.7446)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
3787                <rect x="13.0841" y="11.0938" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 13.0841 11.0938)" fill="#D0D0D0"/>
3788                <rect x="6.44223" y="19.8169" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 6.44223 19.8169)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
3789                <rect x="13.9527" y="20.166" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 13.9527 20.166)" fill="#D0D0D0"/>
3790                <rect x="7.31107" y="28.8892" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 7.31107 28.8892)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
3791                <rect x="14.8214" y="29.2383" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 14.8214 29.2383)" fill="#D0D0D0"/>
3792                <rect x="8.17942" y="37.9619" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 8.17942 37.9619)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
3793                <rect x="15.6899" y="38.311" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 15.6899 38.311)" fill="#D0D0D0"/>
3794                <rect x="9.04825" y="47.0342" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 9.04825 47.0342)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
3795                <rect x="16.5587" y="47.3833" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 16.5587 47.3833)" fill="#D0D0D0"/>
3796                <rect x="9.91666" y="56.1069" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 9.91666 56.1069)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
3797                <rect x="17.4271" y="56.4561" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 17.4271 56.4561)" fill="#D0D0D0"/>
3798                <rect x="10.7854" y="65.1792" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 10.7854 65.1792)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
3799                <rect x="18.2959" y="65.5283" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 18.2959 65.5283)" fill="#D0D0D0"/>
3800                <rect x="11.6538" y="74.2515" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 11.6538 74.2515)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
3801                <rect x="19.1643" y="74.6006" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 19.1643 74.6006)" fill="#D0D0D0"/>
3802                <rect x="55.0288" y="35.834" width="31.0853" height="31.0853" transform="rotate(13.2248 55.0288 35.834)" fill="url(#pattern0_489_1797)"/>
3803                <defs>
3804                <pattern id="pattern0_489_1797" patternContentUnits="objectBoundingBox" width="1" height="1">
3805                <use xlink:href="#image0_489_1797" transform="scale(0.0104167)"/>
3806                </pattern>
3807                <image id="image0_489_1797" width="96" height="96" xlink:href="data:image/png;base64,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"/>
3808                </defs>
3809              </svg>
3810                <div class="swym-storefront-layout-empty-wishlist-title">${SwymStorefrontLayoutContext?.Strings?.emptyWishlistTitle}</div>
3811                <div class="swym-storefront-layout-empty-wishlist-description">${SwymStorefrontLayoutContext?.Strings?.emptyWishlistDescription}</div>
3812              </div>
3813            </div>
3814          </div>
3815        `;
3816      }
3817
3818      this.elements.itemsContainer.innerHTML = emptyStateHtml;
3819      this.elements.itemsContainer.classList.add('swym-storefront-layout-items-has-empty');
3820
3821      // Safely set notice text as innerHTML (controlled locale string with <strong> tags)
3822      const noticeEl = this.elements.itemsContainer.querySelector('.swym-storefront-layout-empty-state-notice-text');
3823      if (noticeEl) {
3824        noticeEl.innerHTML = noticeText || '';
3825      }
3826
3827      // Attach event listener for "Keep browsing first" button (closes the drawer)
3828      const browseBtn = this.elements.itemsContainer.querySelector('[data-action="close-drawer"]');
3829      if (browseBtn) {
3830        browseBtn.addEventListener('click', () => {
3831          const layout = SwymStorefrontLayoutExtensions.SwymStorefrontLayout
3832            || document.querySelector('swym-storefront-layout #swym-storefront-layout');
3833          layout?.close?.();
3834        });
3835      }
3836
3837      // Attach event listener for multi-logged-in "+ Create a new list" card 
3837in items empty state
3838      const createCardItems = this.elements.itemsContainer.querySelector('[data-action="create-collection"]');
3839      if (createCardItems) {
3840        createCardItems.addEventListener('click', () => {
3841          SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActions?.setData({
3842            listId: SwymStorefrontLayoutContext?.DefaultList?.lid,
3843            list: SwymStorefrontLayoutContext?.DefaultList,
3844            item: { iu: '', dt: '' },
3845            collections: SwymStorefrontLayoutContext?.collections || [],
3846            actionType: SwymStorefrontLayoutContext?.ActionTypes.AddToCollection,
3847            canCreateLists: true
3848          });
3849          SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActions?.openDrawer();
3850        });
3851      }
3852    }
3853
3854    let wishlistCount = (this.wishlist?.listcontents || []).filter(item => item.source !== 'auto-wishlist').length;
3855    if(this.elements.title){
3856      this.elements.title.innerHTML = `${SwymStorefrontLayoutContext?.Strings?.wishlistTitle} ${wishlistCount?`(${wishlistCount})`:''}`;
3857    }
3858  }
3859
3860
3861}
3862
3863/**
3864 * SwymStorefrontLayoutCollectionList
3865 *
3866 * A custom HTML element representing a collection list within the Swym Storefront Layout.
3867 * This component is responsible for rendering a list of collections, displaying wishlist items, 
3868 * handling user interactions, and managing collection data.
3869 *
3870 * Features:
3871 * - Initializes and renders the UI dynamically.
3872 * - Fetches and displays wishlist items for a collection.
3873 * - Handles user permissions for editing or saving collections.
3874 * - Provides UI elements like back navigation, action buttons, and collection details.
3875 *
3876 * Usage:
3877 * ```html
3878 * <swym-storefront-layout-collection-list></swym-storefront-layout-collection-list>
3879 * ```
3880 * JavaScript:
3881 * ```js
3882 * const collectionListElement = document.createElement('swym-storefront-layout-collection-list');
3883 * collectionListElement.setData({ list: myList, collections: myCollections });
3884 * document.body.appendChild(collectionListElement);
3885 * ```
3886 */
3887class SwymStorefrontLayoutCollectionList extends HTMLElement {
3888  constructor() {
3889    super();
3890    this.collectionList = null;
3891    this.collections = null;
3892  }
3893  initUI(){
3894    this.renderUI();
3895    this.elements = {
3896      backButton: this.querySelector('.swym-storefront-layout-collection-list-back-button'),
3897      itemsContainer: this.querySelector('#swym-storefront-layout-collection-list-items-container'),
3898      collectionCount: this.querySelector('.swym-storefront-layout-collection-items-count'),
3899      title: this.querySelector('.swym-storefront-layout-collection-title'),
3900      swymListActionButton: this.querySelector('.swym-storefront-layout-collection-option-button'),
3901      userAccessInfo: this.querySelector('#swym-storefront-layout-collection-list-access-info'),
3902      collectionImages: this.querySelector('#swym-storefront-layout-collection-list-images-container')
3903    }
3904    this.addEventListenerToView();
3905  }
3906
3907  setData({ list, collections, canCreateLists = true, shouldShowMultiple = true }) {
3908    this.initUI();
3909    this.renderLoader();
3910    this.collectionList = list;
3911    this.collections = collections;
3912    this.canCreateLists = canCreateLists;
3913    this.shouldShowMultiple = shouldShowMultiple;
3914    if(this.collectionList){
3915      this.elements.itemsContainer.dataset.lid = this.collectionList.lid;
3916      this.canEdit = SwymStorefrontLayoutContext?.checkUserCanEditList(this.collectionList);
3917      this.renderCollectionlist();
3918    }
3919  }
3920
3921  renderUI() {
3922    this.innerHTML = `
3923    <div class="swym-storefront-layout-collection-list-container">
3924      <div class="swym-storefront-layout-collection-list-header">
3925        <div id="swym-storefront-layout-collection-list-images-container">
3926        </div>
3927        <div class="swym-storefront-layout-collection-list-header-content">
3928          <div class="swym-storefront-layout-collection-list-back-button">
3929            <svg data-v-bfb713a3="" data-v-326364ff="" viewBox="0 0 16 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="base-icon back-icon" aria-hidden="true"><path d="M15.44 7a.96.96 0 0 0-.96-.96H3.951l3.903-3.638A.96.96 0 1 0 6.544 1L.856 6.297a.963.963 0 0 0 0 1.404L6.543 13a.96.96 0 1 0 1.31-1.404L3.952 7.96H14.48a.96.96 0 0 0 .96-.96Z" fill="currentColor"></path></svg>
3930          </div>
3931          <div class="swym-storefront-layout-collection-title-container">
3932            <div class="swym-storefront-layout-collection-title"></div>
3933            <div class="swym-storefront-layout-collection-items-count"></div>
3934            <div class="swym-storefront-layout-collection-option-button">
3935              <svg xmlns="http://www.w3.org/2000/svg" width="3" height="13" viewBox="0 0 3 13" fill="currentcolor">
3936                <circle cx="1.5" cy="1.50014" r="1.5" fill="currentColor"></circle>
3937                <circle cx="1.5" cy="6.50014" r="1.5" fill="currentColor"></circle>
3938                <circle cx="1.5" cy="11.5001" r="1.5" fill="currentColor"></circle>
3939              </svg>
3940            </div>
3941          </div>
3942        </div>
3943      </div>
3944      <div class="swym-storefront-layout-collection-list-content swym-storefront-layout-scrollable">
3945        <div id="swym-storefront-layout-collection-list-access-info"></div>
3946        <div class="swym-storefront-layout-add-all-to-cart-container swym-storefront-layout-add-all-to-cart-top"></div>
3947        <div id="swym-storefront-layout-collection-list-items-container" class="swym-storefront-layout-items-container">
3948        </div>
3949        <div class="swym-storefront-layout-add-all-to-cart-container swym-storefront-layout-add-all-to-cart-bottom"></div>
3950      </div>
3951      <swym-storefront-layout-login-user showLogin="true"></swym-storefront-layout-login-user>
3952    </div>
3953    `
3954  }
3955
3956  addEventListenerToView() {
3957    this.elements.backButton.addEventListener('click', () => {
3958      window.location.hash = SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.List;
3959      this.closeCollectinListView()
3960    });
3961
3962    this.elements.swymListActionButton?.addEventListener('click', (event) => {
3963      event.preventDefault();
3964      event.stopPropagation();
3965      if(SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.isTooltipOpen && SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.currentTarget === event.target){
3966        SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.closeTooltip();
3967      }else{
3968        if(this.canEdit){
3969          SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.setData({
3970            listId: this.collectionList.lid,
3971            list: this.collectionList,
3972            collections: this.collections,
3973            actionType: SwymStorefrontLayoutContext?.ActionTypes.EditCollection
3974          });
3975        }else{
3976          SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.setData({
3977            listId: this.collectionList.lid,
3978            list: this.collectionList,
3979            collections: this.collections,
3980            actionType: SwymStorefrontLayoutContext?.ActionTypes.SaveCollection
3981          });
3982        }
3983        SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.showOnTarget(event.target);
3984      }
3985    });
3986  }
3987
3988  async renderCollectionlist() {
3989    SwymStorefrontLayoutExtensions?.AddAllToCart?.mount(this, this.collectionList);
3990    if (this.collectionList && this.collectionList.listcontents && this.elements.itemsContainer) {
3991
3992      this.elements.title.innerHTML = `<div class="swym-storefront-layout-collection-title">${this.collectionList.lname}</div>`;
3993
3994      let itemsCount = this.collectionList?.listcontents?.length || 0;
3995      this.elements.collectionCount.innerHTML = itemsCount?`${itemsCount} ${itemsCount<=1? SwymStorefrontLayoutContext?.Strings?.item : SwymStorefrontLayoutContext?.Strings?.items }`:'';
3996      
3997      const wishlistedProducts = this.collectionList.listcontents;
3998      const fragment = document.createDocumentFragment();
3999
4000      this.elements.collectionImages.innerHTML = `
4001        <div class="swym-storefront-layout-collection-list-images">
4002          ${wishlistedProducts.slice(0, 5).map((item, index) => 
4003            item 
4004              ? `<img class="swym-storefront-layout-collection-list-image swym-storefront-layout-collection-list-image-${index}" src="${item.iu}" alt="Wishlist Image">`
4005              : ``
4006          ).join('')}
4007        </div>
4008      `;
4009
4010      
4011
4012      if(itemsCount){
4013        wishlistedProducts.forEach((item) => {
4014          const wishlistItem = document.createElement('template');
4015          wishlistItem.innerHTML = `<swym-storefront-layout-item id="swym-storefront-layout-collection-item-${item.empi}-${item.epi}" ></swym-storefront-layout-item>`;
4016          fragment.appendChild(wishlistItem.content);
4017        });
4018        
4019        this.elements.itemsContainer.innerHTML = '';
4020        this.elements.itemsContainer.appendChild(fragment);
4021  
4022        wishlistedProducts.forEach((item) => {
4023          let wishlistItemElement = document.querySelector(`#swym-storefront-layout-collection-item-${item.empi}-${item.epi}`);
4024          wishlistItemElement?.setData({
4025            item,
4026            listItemType: SwymStorefrontLayoutContext?.ListItemType?.CollectionItem,
4027            list: this.collectionList,
4028            collections: this.collections,
4029            canCreateLists: this.canCreateLists
4030          })
4031        });
4032      }else{
4033        this.renderEmptyView();
4034      }
4035
4036      let isUserLogged = SwymStorefrontLayoutContext?.isShopperLoggedIn;
4037      if(isUserLogged && !!this.collectionList?.userinfo?.em && this.collectionList?.userinfo?.em != SwymStorefrontLayoutContext?.SwymCustomerData?.email){
4038        let email = this.collectionList?.userinfo?.em;
4039        this.elements.userAccessInfo.innerHTML = window._swat?.utils?.renderTemplateString( SwymStorefrontLayoutContext?.Strings?.sharedCollectionMessage, { email });
4040      }else{
4041        this.elements.userAccessInfo.innerHTML = ``;
4042      }
4043
4044      this.openCollectionListView();
4045    }
4046  }
4047
4048  renderEmptyView(){
4049    this.elements.itemsContainer.innerHTML = `
4050      <div class="swym-storefront-layout-empty-container">
4051        <div class="swym-storefront-layout-empty-wishlist-container">
4052          <div class="swym-storefront-layout-empty-wishlist-content">
4053            <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="85" viewBox="0 0 86 85" fill="none">
4054              <rect width="59.5441" height="78.6833" transform="translate(0.710449 6.1748) rotate(-5.46887)" fill="white"/>
4055              <rect x="0.710938" y="6.1748" width="59.5441" height="78.6833" rx="1.21519" transform="rotate(-5.46887 0.710938 6.1748)" fill="#FDFDFD"/>
4056              <rect x="0.983626" y="6.39984" width="59.0441" height="78.1833" rx="0.965186" transform="rotate(-5.46887 0.983626 6.39984)" stroke="black" stroke-opacity="0.1" stroke-width="0.5"/>
4057              <rect x="5.57364" y="10.7446" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 5.57364 10.7446)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
4058              <rect x="13.0841" y="11.0938" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 13.0841 11.0938)" fill="#D0D0D0"/>
4059              <rect x="6.44223" y="19.8169" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 6.44223 19.8169)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
4060              <rect x="13.9527" y="20.166" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 13.9527 20.166)" fill="#D0D0D0"/>
4061              <rect x="7.31107" y="28.8892" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 7.31107 28.8892)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
4062              <rect x="14.8214" y="29.2383" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 14.8214 29.2383)" fill="#D0D0D0"/>
4063              <rect x="8.17942" y="37.9619" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 8.17942 37.9619)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
4064              <rect x="15.6899" y="38.311" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 15.6899 38.311)" fill="#D0D0D0"/>
4065              <rect x="9.04825" y="47.0342" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 9.04825 47.0342)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
4066              <rect x="16.5587" y="47.3833" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 16.5587 47.3833)" fill="#D0D0D0"/>
4067              <rect x="9.91666" y="56.1069" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 9.91666 56.1069)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
4068              <rect x="17.4271" y="56.4561" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 17.4271 56.4561)" fill="#D0D0D0"/>
4069              <rect x="10.7854" y="65.1792" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 10.7854 65.1792)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
4070              <rect x="18.2959" y="65.5283" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 18.2959 65.5283)" fill="#D0D0D0"/>
4071              <rect x="11.6538" y="74.2515" width="5.16454" height="5.16454" rx="0.455695" transform="rotate(-5.46887 11.6538 74.2515)" fill="#FBFBFB" stroke="#D0D0D0" stroke-width="0.303797"/>
4072              <rect x="19.1643" y="74.6006" width="44.6581" height="3.03797" rx="0.607593" transform="rotate(-5.46887 19.1643 74.6006)" fill="#D0D0D0"/>
4073              <rect x="55.0288" y="35.834" width="31.0853" height="31.0853" transform="rotate(13.2248 55.0288 35.834)" fill="url(#swym-empty-collection-pattern)"/>
4074              <defs>
4075              <pattern id="swym-empty-collection-pattern" patternContentUnits="objectBoundingBox" width="1" height="1">
4076              <use xlink:href="#swym-empty-collection-image" transform="scale(0.0104167)"/>
4077              </pattern>
4078              <image id="swym-empty-collection-image" width="96" height="96" xlink:href="data:image/png;base64,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"/>
4079              </defs>
4080            </svg>
4081            <div class="swym-storefront-layout-empty-wishlist-title">${SwymStorefrontLayoutContext?.Strings?.emptyCollectionText}</div>
4082            <div class="swym-storefront-layout-empty-wishlist-description">${SwymStorefrontLayoutContext?.Strings?.emptyCollectionDescription}</div>
4083          </div>
4084        </div>
4085      </div>
4086    `;
4087    this.elements.itemsContainer.classList.add('swym-storefront-layout-items-has-empty');
4088  }
4089
4090  renderLoader(){
4091    this.elements.collectionImages.innerHTML = `<swym-storefront-layout-loader loading="true" loadertype="${SwymStorefrontLayoutContext?.LoaderViewType.CollectionImages}" height="80%"></swym-storefront-layout-loader>`;
4092    this.elements.itemsContainer.innerHTML = `<swym-storefront-layout-loader loading="true" loadertype="${SwymStorefrontLayoutContext?.LoaderViewType.WishlistListItem}" height="80%"></swym-storefront-layout-loader>`;
4093  }
4094
4095  clearUI(){
4096    this.innerHTML = '';
4097  }
4098
4099  openCollectionListView() {
4100    this.classList.add('swym-storefront-layout-show-collection-list');
4101  }
4102
4103  closeCollectinListView() {
4104    this.classList.remove('swym-storefront-layout-show-collection-list');
4105    setTimeout(()=>{
4106      this.clearUI();
4107    },100);
4108  }
4109
4110}
4111
4112
4113/**
4114 * SwymStorefrontLayoutActions - Custom Web Component
4115 *
4116 * This class extends `HTMLElement` to create and manage the UI for wishlist-related actions 
4117 * in the Swym Storefront Layout. It handles functionalities such as:
4118 *
4119 * - Displaying a modal-like action panel for managing wishlist items.
4120 * - Supporting different action types (e.g., adding an item to a collection).
4121 * - Rendering the UI dynamically based on the selected list or collection.
4122 * - Managing event listeners to update UI interactions seamlessly.
4123 *
4124 * Key Features:
4125 * - Renders a structured UI layout with an image, title, options, and action buttons.
4126 * - Supports selecting collections and dynamically updates the UI upon selection.
4127 * - Implements event handling for collection management, including adding new collections.
4128 * - Uses `SwymStorefrontLayoutContext` for accessing relevant wishlist and collection data.
4129 *
4130 * Usage:
4131 * - This component is initialized automatically when added to the DOM.
4132 * - Data can be set via `setData({ listId, list, item, selectedVariantId, collections, actionType })`.
4133 * - Internal methods like `renderAddToCollection()` handle specific UI updates.
4134 *
4135 * Example:
4136 * ```html
4137 * <swym-storefront-layout-actions></swym-storefront-layout-actions>
4138 * ```
4139 *
4140 * Dependencies:
4141 * - Requires `SwymStorefrontLayoutContext` for accessing wishlist and collection data.
4142 * - Uses event listeners for handling user interactions.
4143 *
4144 * Notes:
4145 * - Ensures smooth UI updates with proper event handling and DOM manipulations.
4146 * - Uses query selectors to manage DOM elements efficiently.
4147 */
4148class SwymStorefrontLayoutActions extends HTMLElement {
4149  constructor() {
4150    super();
4151
4152    this.actionType = SwymStorefrontLayoutContext?.ActionTypes.ManageListItem;
4153
4154    this.wishlistItem = null;
4155    this.collections = null;
4156    this.listId = null;
4157    this.list = null;
4158    this.selectedCollectionLid = null;
4159    this.selectedList = null;
4160    this.renderUI();
4161    this.elements = {
4162      container: this.querySelector('.swym-storefront-layout-actions-container'),
4163      backdrop: this.querySelector('.swym-storefront-layout-action-backdrop'),
4164      closeButton: this.querySelector('.swym-storefront-layout-action-close-button'),
4165      title: this.querySelector('.swym-storefront-layout-action-title-container'),
4166      optionsContainer: this.querySelector('.swym-storefront-layout-action-options'),
4167      actionContianer: this.querySelector('.swym-storefront-layout-action-container'),
4168      wishlistItemsContainer: document.querySelector('swym-storefront-layout-wishlist-container #swym-storefront-layout-items-container'),
4169      sflItemsContainer: document.querySelector('swym-storefront-layout-sfl-container #swym-storefront-layout-sfl-items-container'),
4170      imageContainer: this.querySelector('.swym-storefront-layout-action-image-container')
4171    }
4172    this.addEventListenerToView();
4173  }
4174
4175  renderUI() {
4176    this.innerHTML = `
4177    <div class="swym-storefront-layout-actions-container">
4178      <div class="swym-storefront-layout-action-backdrop"></div>
4179      <div class="swym-storefront-layout-action-layout">
4180        <div class="swym-storefront-layout-action-image-container"></div>
4181        <div class="swym-storefront-layout-action-content">
4182          <div class="swym-storefront-layout-action-header">
4183            <div class="swym-storefront-layout-action-title-container"></div>
4184            <button type="button" aria-label="${SwymStorefrontLayoutContext?.Strings?.closeDrawer || 'Close'}" class="swym-storefront-layout-action-close-button">
4185              <svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
4186                <path d="M0 10C0 4.47715 4.47715 0 10 0C15.5228 0 20 4.47715 20 10C20 15.5228 15.5228 20 10 20C4.47715 20 0 15.5228 0 10Z" fill="white"/>
4187                <path d="M13.9697 15.0303C14.2626 15.3232 14.7374 15.3232 15.0303 15.0303C15.3232 14.7374 15.3232 14.2626 15.0303 13.9697L11.0607 10L15.0303 6.03033C15.3232 5.73744 15.3232 5.26256 15.0303 4.96967C14.7374 4.67678 14.2626 4.67678 13.9697 4.96967L10 8.93934L6.03033 4.96967C5.73744 4.67678 5.26256 4.67678 4.96967 4.96967C4.67678 5.26256 4.67678 5.73744 4.96967 6.03033L8.93934 10L4.96967 13.9697C4.67678 14.2626 4.67678 14.7374 4.96967 15.0303C5.26256 15.3232 5.73744 15.3232 6.03033 15.0303L10 11.0607L13.9697 15.0303Z" fill="currentColor"/>
4188              </svg>
4189            </button>
4190          </div>
4191          <div class="swym-storefront-layout-action-options"></div>
4192          <div class="swym-storefront-layout-action-container"></div>
4193        </div>
4194      </div>
4195    </div>
4196    `
4197  }
4198
4199  setData({ listId, list, item, selectedVariantId, collections, actionType = SwymStorefrontLayoutContext?.ActionTypes.ManageListItem, canCreateLists = true }) {
4200    this.listId = listId;
4201    this.list = list;
4202    this.wishlistItem = item;
4203    this.collections = SwymStorefrontLayoutContext?.collections;
4204    this.currentSlectedVariantId = selectedVariantId;
4205    this.selectedCollectionLid = this.collections[0]?.lid;
4206    this.selectedList = this.collections[0] || null;
4207    this.canCreateLists = canCreateLists;
4208    this.elements.wishlistItemsContainer = document.querySelector(`.swym-storefront-layout-items-container[data-lid="${listId}"]`);
4209    this.elements.actionContianer.innerHTML = '';
4210    if (actionType === SwymStorefrontLayoutContext?.ActionTypes.AddToCollection) {
4211      this.renderAddToCollection();
4212    } 
4213    SwymStorefrontLayoutExtensions?.checkContainerScrollbar(this.elements.optionsContainer);
4214  }
4215
4216  async renderAddToCollection() {
4217    this.collections = SwymStorefrontLayoutContext?.collections || [];
4218    if (this.collections && this.elements.optionsContainer) {
4219
4220      if (this.wishlistItem.iu) {
4221        this.elements.imageContainer.innerHTML = `<img src="${this.wishlistItem.iu}" alt="${swymEscAttr(this.wishlistItem.dt) || 'Product image'}">`;
4222        this.elements.imageContainer.style.display = '';
4223      } else {
4224        this.elements.imageContainer.innerHTML = '';
4225        this.elements.imageContainer.style.display = 'none';
4226      }
4227      
4228      this.elements.title.innerHTML = `
4229        <div class="swym-storefront-layout-action-addtocollection-title">
4230          <div class="swym-storefront-layout-action-product-title">${this.wishlistItem.dt}</div>
4231          <div class="swym-storefront-layout-action-title">${SwymStorefrontLayoutContext?.Strings?.addToCollectionTitle}</div>
4232        </div>
4233      `
4234      this.renderCollectionOptions();
4235      this.renderCreteCollectionAction()
4236    }
4237  }
4238
4239  renderCollectionOptions(){
4240    this.elements.optionsContainer.innerHTML = `
4241        ${this.collections.map((collection) => {
4242
4243        let { lid, lname, listcontents } = collection;
4244        let item = listcontents[0];
4245        let count = listcontents.length;
4246
4247        // Check if current product exists in this collection
4248        const productExists = listcontents.some(listItem => 
4249            listItem.epi === this.wishlistItem.epi
4250        );
4251
4252        const listImagesHtml = Array.from({ length: 3 })
4253          .map((_, i) => {
4254            let item = listcontents[i];
4255            return `
4256            <div class="${i === 0 ? 'swym-storefront-layout-action-collection-item-image-primary' : 'swym-storefront-layout-action-collection-item-image-secondary'} ">
4257              ${item?.iu ? `<img src="${item ? item.iu : null}" alt="${swymEscAttr(item?.dt) || ''}" class="swym-storefront-layout-action-collection-item-image" />` : `<div class="swym-storefront-layout-action-collection-item-image" ></div>`}
4258            </div>
4259          `;
4260          })
4261          .join("");
4262
4263        return `
4264            <div class="swym-storefront-layout-collection-action-btn add-item-to-collection swym-storefront-layout-action-collection-item-container" data-lid="${lid}">
4265              <div class="swym-storefront-layout-action-collection-image-container">
4266                ${listImagesHtml}
4267              </div>
4268              <div class="swym-storefront-layout-action-collection-content">
4269                <div class="swym-storefront-layout-action-collection-item-name">${lname}</div>
4270                <div class="swym-storefront-layout-action-collection-item-count">${count} ${count === 1 ? SwymStorefrontLayoutContext?.Strings?.item : SwymStorefrontLayoutContext?.Strings?.items}</div>
4271              </div>
4272              <div class="swym-storefront-layout-checkbox-container">
4273                <label class="swym-storefront-layout-checkbox">
4274                  <input type="checkbox" ${productExists ? 'checked' : ''} name="swym-storefront-layout-collections">
4275                  <span class="swym-storefront-layout-checkmark"></span>
4276                </label>
4277              </div>
4278            </div>
4279          `
4280      }).join('')}
4281      `;
4282
4283      this.addMangeCollectionEventListeners();
4284  }
4285
4286  addMangeCollectionEventListeners() {
4287    // Track initial checkbox states
4288    this.initialCheckStates = new Map();
4289    this.newlyCheckedLids = [];    // Declare at class level
4290    this.newlyUncheckedLids = [] // Array for newly unchecked lids
4291    
4292    this.collections.forEach((collection) => {
4293      const collectionItem = this.querySelector(`[data-lid="${collection.lid}"]`);
4294      const checkbox = collectionItem?.querySelector('input[type="checkbox"]');
4295      
4296      // Store initial checked state
4297      if (checkbox) {
4298        this.initialCheckStates.set(collection.lid, checkbox.checked);
4299      }
4300
4301      // Add event listener specifically for the checkbox
4302      collectionItem?.addEventListener("click", async (event) => {
4303        event.preventDefault();
4304        event.stopPropagation();
4305
4306        // Toggle checkbox
4307        if (checkbox) {
4308          checkbox.checked = !checkbox.checked;
4309        }
4310        
4311        const collectionSaveButton = this.querySelector('.swym-storefront-layout-save-collection-list-button');
4312        // Clear arrays on each click
4313        this.newlyCheckedLids = [];
4314        this.newlyUncheckedLids = [];
4315
4316        const collectionNameInput = this.querySelector('.swym-storefront-layout-create-collection-name-input');
4317
4318        this.collections.forEach(col => {
4319          const item = this.querySelector(`[data-lid="${col.lid}"]`);
4320          const cb = item?.querySelector('input[type="checkbox"]');
4321          if (cb) {
4322            const wasChecked = this.initialCheckStates.get(col.lid);
4323            const isNowChecked = cb.checked;
4324            
4325            if (!wasChecked && isNowChecked) {
4326                this.newlyCheckedLids.push(col.lid);
4327            }
4328            if (wasChecked && !isNowChecked) {
4329                this.newlyUncheckedLids.push(col.lid);
4330            }
4331          }
4332        });
4333
4334        // Enable button if there are any changes
4335        if (collectionSaveButton) {
4336          const hasChanges = this.newlyCheckedLids.length > 0 || this.newlyUncheckedLids.length > 0;
4337          collectionSaveButton.disabled = !hasChanges;      
4338          // Update button text based on changes
4339          if (hasChanges) {
4340            if (this.newlyUncheckedLids.length > 0 && this.newlyCheckedLids.length === 0) {
4341                // Only unchecking existing items
4342             if (!collectionNameInput.value.trim()) {
4343                    collectionSaveButton.textContent = SwymStorefrontLayoutContext?.Strings?.removeItemCta;
4344                } else {
4345                    collectionSaveButton.textContent = SwymStorefrontLayoutContext?.Strings?.updateCollectionCta || "Upd
4345ate List";
4346                }
4347              } else if (this.newlyCheckedLids.length > 0 && this.newlyUncheckedLids.length === 0) {
4348                // Only adding new items
4349                collectionSaveButton.textContent = SwymStorefrontLayoutContext?.Strings?.addToCollectionCta || "Add to Collection";
4350            } else {
4351                // Both adding and removing
4352                collectionSaveButton.textContent = SwymStorefrontLayoutContext?.Strings?.updateCollectionCta || "Update List";
4353            }
4354          } else {
4355            if (collectionNameInput.value.trim() && collectionNameInput.value.trim().length >= 3) {
4356              collectionSaveButton.textContent = SwymStorefrontLayoutContext?.Strings?.addToCollectionCta || "Add to Collection";
4357              collectionSaveButton.disabled = false;
4358            }
4359          }
4360        }
4361        // Toggle selected class on the parent container
4362        collectionItem.classList.toggle('swym-storefront-layout-checkbox-selected');
4363        // Your existing logic for handling checkbox state
4364      });
4365      // Prevent checkbox from triggering twice
4366      checkbox?.addEventListener('click', (event) => {
4367          event.stopPropagation();
4368      });
4369    });
4370  }
4371
4372  renderCreteCollectionAction(){
4373    // Render save button always, but only show create collection input if user can create new lists
4374    this.elements.actionContianer.innerHTML = `
4375        <form class="swym-storefront-layout-create-collection-form">
4376          ${this.canCreateLists ? `
4377          <div class="swym-storefront-layout-create-collection-name-form-group">
4378            <input
4379              type="text"
4380              class="swym-storefront-layout-action-input create-collection-name-input swym-storefront-layout-create-collection-name-input"
4381              placeholder="${SwymStorefrontLayoutContext?.Strings?.createCollectionCta}"
4382            />
4383            <div class="swym-storefront-layout-checkbox-container">
4384              <label class="swym-storefront-layout-checkbox">
4385                <input type="checkbox" ${this.selectedCollectionLid === 'fromInput'?'checked':''} name="swym-storefront-layout-collections">
4386                <span class="swym-storefront-layout-checkmark"></span>
4387              </label>
4388            </div>
4389            <div class="swym-storefront-layout-create-collection-error-message-container error-message" style="display: none;">
4390              <svg width="12" height="12" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="base-icon error-icon" aria-hidden="true"><path d="M7 .7a6.3 6.3 0 1 0 0 12.6A6.3 6.3 0 0 0 7 .7Zm.7 9.8H6.3V9.1h1.4v1.4Zm0-2.1H6.3V3.5h1.4v4.9Z" fill="currentColor"></path></svg>
4391              <span class="swym-storefront-layout-create-collection-error-message">Name is required</span>
4392            </div>
4393          </div>
4394          ` : ''}
4395          <button type="submit" class="swym-storefront-layout-save-collection-list-button" disabled>${SwymStorefrontLayoutContext?.Strings?.addToCollectionCta}</button>
4396        </form>
4397      `;
4398      this.addCreateCollectionEventListeners();
4399  }
4400
4401  addCreateCollectionEventListeners() {
4402    const createCollectionForm = this.querySelector('.swym-storefront-layout-create-collection-form');
4403    const collectionNameInputContainer = this.querySelector('.swym-storefront-layout-create-collection-name-form-group');
4404    const collectionNameInput = this.querySelector('.swym-storefront-layout-create-collection-name-input');
4405
4406    // Only add input-specific listeners if the input exists (when canCreateLists is true)
4407    if (collectionNameInput) {
4408      collectionNameInput.addEventListener("focus", () => {
4409        this.selectedCollectionLid = 'fromInput';
4410        this.validateCollectionInputField(false);
4411      });
4412      
4413      collectionNameInput.addEventListener("blur", () => {
4414        if (!collectionNameInput.value.trim()) {
4415          const errorMessageContainer = this.querySelector('.swym-storefront-layout-create-collection-error-message-container');
4416          const errorMessage = this.querySelector('.swym-storefront-layout-create-collection-error-message');
4417          
4418          // Hide error message
4419          errorMessage.innerHTML = '';
4420          errorMessageContainer.style.display = 'none';
4421          collectionNameInput.classList.remove('swym-storefront-layout-input-has-error');
4422        }
4423      });
4424
4425      collectionNameInput.addEventListener('input', () => {
4426        this.validateCollectionInputField();
4427      });
4428      
4429      // auto focus create collection input by default when no collection available
4430      // Small delay ensures the input is focusable after the dialog/DOM finishes rendering.
4431      const COLLECTION_INPUT_FOCUS_DELAY_MS = 50;
4432      if(!this.collections?.length){
4433        setTimeout(() => {
4434          collectionNameInput?.focus();
4435        }, COLLECTION_INPUT_FOCUS_DELAY_MS);
4436      }
4437    }
4438
4439    // Always add form submit listener (works whether input exists or not)
4440    createCollectionForm?.addEventListener('submit', async (event) => {
4441      try {
4442        event.preventDefault();
4443        let listIdToAdd;
4444        if(this.selectedCollectionLid === 'fromInput' && collectionNameInput.value.length >= 3){
4445          let name = collectionNameInput.value.trim();
4446          let newList = await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.createList(name);
4447          listIdToAdd = newList.lid;
4448          this.newlyCheckedLids.push(listIdToAdd);
4449          this.selectedList = newList;
4450        } 
4451        let { epi, empi, du, iu } = this.wishlistItem;
4452
4453         // Check if item is being moved from default list
4454        // Check if item exists in default list
4455        const isInDefaultList = SwymStorefrontLayoutContext?.DefaultList?.listcontents.some(
4456          item => item.epi === epi && item.empi === empi
4457        );
4458        // If item is from the SFY list, remove it from there when adding to a collection
4459        const sfyList = SwymStorefrontLayoutContext.getSfyList();
4460        if (sfyList && this.listId === sfyList.lid) {
4461          this.newlyUncheckedLids.push(sfyList.lid);
4462        }
4463        if(this.newlyCheckedLids.length >  0 && this.newlyUncheckedLids.length > 0) {
4464         SwymStorefrontLayoutContext.CommonAddtoWL = true; 
4465         SwymStorefrontLayoutContext.CommonRemovefromWL = true;
4466        }
4467        this.closeDrawer();
4468
4469        if(this.newlyCheckedLids.length > 0) {
4470          // Add to new lists
4471          SwymStorefrontLayoutContext.CommonAddtoWL = true; 
4472           if(isInDefaultList) {
4473            SwymStorefrontLayoutContext.CommonRemovefromWL = true; 
4474            this.newlyUncheckedLids.push(SwymStorefrontLayoutContext?.DefaultList?.lid); 
4475          }
4476          await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.addProductToLists(
4477            { empi, epi, du }, 
4478            this.newlyCheckedLids
4479          );
4480        }
4481        // Handle unchecked lists (except default list)
4482        if(this.newlyUncheckedLids.length > 0) {
4483          SwymStorefrontLayoutContext.CommonRemovefromWL = true;
4484          await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.removeProductFromLists(
4485            { empi, epi, du },
4486            this.newlyUncheckedLids
4487          );
4488        }
4489        // Show notification
4490        if(this.newlyCheckedLids.length > 0 && this.newlyUncheckedLids.length > 0) {
4491          SwymStorefrontLayoutExtensions?.Notification?.setMessage({
4492            title: SwymStorefrontLayoutContext?.Strings?.notificationMessageCollectionUpdated,
4493            message: SwymStorefrontLayoutContext?.Strings?.notificationMessageCollectionUpdated,
4494            status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Neutral,
4495            actionType: "",
4496            duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
4497            product: this.wishlistItem,
4498            image: iu,
4499            action: {
4500              label:  SwymStorefrontLayoutContext?.Strings?.notificationActionView,
4501              onClick: () => {
4502                _swat.ui.open();
4503              },
4504            }
4505          },{
4506            showActionButton: true,
4507            showTitle: false,
4508            showProgress: true
4509          });   
4510          SwymStorefrontLayoutContext.CommonAddtoWL = false;
4511          SwymStorefrontLayoutContext.CommonRemovefromWL = false;  
4512        }
4513        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutCollectionCreated, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutCollectionInteractions });
4514      } catch (error) {
4515        window._swat?.utils.error('Error on create and add product to list', error);
4516      }
4517    }); 
4518  }
4519
4520  validateCollectionInputField(showError = true){
4521
4522    const collectionNameInput = this.querySelector('.swym-storefront-layout-create-collection-name-input');
4523    const collectionSaveButton = this.querySelector('.swym-storefront-layout-save-collection-list-button');
4524    const errorMessageContainer = this.querySelector('.swym-storefront-layout-create-collection-error-message-container');
4525    const errorMessage = this.querySelector('.swym-storefront-layout-create-collection-error-message');
4526    const checkbox = collectionNameInput.closest('.swym-storefront-layout-create-collection-name-form-group')?.querySelector('input[type="checkbox"]');
4527
4528    let name = collectionNameInput.value.trim();
4529    let error;
4530
4531    let isNameExist = this.collections.some(collection => collection.lname.toLowerCase() === name.toLowerCase());
4532
4533    // Check if there are any newly checked or unchecked items
4534    const hasChanges = this.newlyCheckedLids.length > 0 || this.newlyUncheckedLids.length > 0;
4535
4536    if (name === '') {
4537      error = SwymStorefrontLayoutContext?.Strings?.errorMessageListNameRequired;
4538      checkbox.checked = false;
4539      if (this.selectedCollectionLid === 'fromInput') {
4540        this.selectedCollectionLid = null;
4541      }
4542    } else if (name.length < 3) {
4543      error = SwymStorefrontLayoutContext?.Strings?.errorMessageListNameRequire3Char;
4544      checkbox.checked = false;
4545        if (this.selectedCollectionLid === 'fromInput') {
4546        this.selectedCollectionLid = null;
4547      }
4548    }else if(isNameExist){
4549      error = SwymStorefrontLayoutContext?.Strings?.errorMessageListNameAlreadyExist;
4550      checkbox.checked = false;
4551      if (this.selectedCollectionLid === 'fromInput') {
4552        this.selectedCollectionLid = null;
4553      }
4554    }
4555
4556    if (name.length > 0) {
4557      collectionNameInput.classList.add('swym-storefront-layout-input-has-value');
4558    } else {
4559      collectionNameInput.classList.remove('swym-storefront-layout-input-has-value');
4560    }
4561
4562    if (error) {
4563      if(showError){
4564        errorMessage.innerHTML = error;
4565        errorMessageContainer.style.display = 'flex';
4566        collectionNameInput.classList.add('swym-storefront-layout-input-has-error');
4567      }
4568      // Only disable button if there are no other changes
4569      collectionSaveButton.disabled = !hasChanges;
4570    } else {
4571      errorMessage.innerHTML = '';
4572      errorMessageContainer.style.display = 'none';
4573      collectionSaveButton.disabled = false;
4574      collectionNameInput.classList.remove('swym-storefront-layout-input-has-error');
4575      // Auto check the checkbox when input is valid
4576      checkbox.checked = true;
4577      this.selectedCollectionLid = 'fromInput';
4578      // Update button text
4579      collectionSaveButton.textContent = SwymStorefrontLayoutContext?.Strings?.addToCollectionCta;
4580    }
4581  }
4582
4583  addEventListenerToView() {
4584    this.elements.backdrop.addEventListener('click', () => this.closeDrawer());
4585    this.elements.closeButton.addEventListener('click', () => this.closeDrawer());
4586  }
4587
4588  openDrawer() {
4589    this.elements.container.classList.add('swym-storefront-layout-show-action-view');
4590  }
4591
4592  closeDrawer() {
4593    this.elements.container.classList.remove('swym-storefront-layout-show-action-view');
4594  }
4595
4596}
4597
4598/**
4599 * SwymStorefrontLayoutActionTooltip
4600 * 
4601 * This custom Web Component manages the action tooltip for storefront layout interactions.
4602 * It provides UI options for managing wishlist items, including adding to collections 
4603 * and removing from lists. The tooltip dynamically updates based on user actions 
4604 * and permissions.
4605 * 
4606 * Features:
4607 * - Displays options based on the selected wishlist item.
4608 * - Supports adding/removing items from collections or lists.
4609 * - Listens for user interactions and updates the UI accordingly.
4610 * - Ensures smooth integration with SwymStorefrontLayoutContext?.
4611 * 
4612 * Dependencies:
4613 * - SwymStorefrontLayoutContext: Provides necessary context for actions and permissions.
4614 * - SwymStorefrontLayoutAPI: Handles wishlist operations.
4615 * - SwymStorefrontLayoutExtensions: Manages UI interactions like opening drawers.
4616 */
4617class SwymStorefrontLayoutActionTooltip extends HTMLElement {
4618  constructor() {
4619    super();
4620
4621    this.isTooltipOpen = false;
4622    this.currentTarget = null;
4623    this._tooltipKeydownController = null;
4624    this.actionType = SwymStorefrontLayoutContext?.ActionTypes.ManageListItem;
4625
4626    this.listItem = null;
4627    this.collections = null;
4628    this.listId = null;
4629    this.list = null;
4630    this.renderUI();
4631    this.elements = {
4632      viewPortLayout: document.querySelector('.swym-storefront-layout-layout'),
4633      tooltipLayout: this.querySelector('.swym-storefront-layout-action-tooltip-layout'),
4634      optionsContainer: this.querySelector('#swym-storefront-layout-action-tooltip-options'),
4635      wishlistItemsContainer: document.querySelector('swym-storefront-layout-wishlist-container #swym-storefront-layout-items-container'),
4636      sflItemsContainer: document.querySelector('swym-storefront-layout-sfl-container #swym-storefront-layout-sfl-items-container')
4637    }
4638    this.addEventListenerToView();
4639  }
4640
4641    renderUI() {
4642      this.innerHTML = `
4643    <div class="swym-storefront-layout-action-tooltip-layout">
4644      <div id="swym-storefront-layout-action-tooltip-options" tabindex="-1" aria-label="Wishlist options"></div>
4645    </div>
4646  `;
4647    }
4648
4649  setData({ listId, list, item, selectedVariantId, collections, actionType = SwymStorefrontLayoutContext?.ActionTypes.ManageListItem, canCreateLists = true }) {
4650    this.listId = listId;
4651    this.list = list;
4652    this.listItem = item;
4653    this.collections = SwymStorefrontLayoutContext?.collections;
4654    this.currentSlectedVariantId = selectedVariantId;
4655    this.canCreateLists = canCreateLists;
4656    this.elements.wishlistItemsContainer = document.querySelector(`swym-storefront-layout-wishlist-container .swym-storefront-layout-items-container[data-lid="${listId}"]`)
4657    this.elements.sflItemsContainer = document.querySelector(`swym-storefront-layout-sfl-container .swym-storefront-layout-items-container[data-lid="${listId}"]`);
4658    this.elements.collectionItemsContainer = document.querySelector(`swym-storefront-layout-collection-list .swym-storefront-layout-items-container[data-lid="${listId}"]`);
4659    if (actionType === SwymStorefrontLayoutContext?.ActionTypes.ManageListItem) {
4660      this.renderWishlistItemOptions();
4661    }else if(actionType === SwymStorefrontLayoutContext?.ActionTypes.EditCollection){
4662      this.renderEditCollection();
4663    }else if(actionType === SwymStorefrontLayoutContext?.ActionTypes.SaveCollection){
4664      this.renderSaveCollection();
4665    }else if(actionType === SwymStorefrontLayoutContext?.ActionTypes.ManageSflListItem){
4666      this.renderSflListItemOptions();
4667    }else if(actionType === SwymStorefrontLayoutContext?.ActionTypes.ManageSfyListItem){
4668      this.renderSfyListItemOptions();
4669    } else if(actionType ===  SwymStorefrontLayoutContext?.ActionTypes.ShareSingleWishlist) {
4670      this.renderShareSingleWishlist();
4671    }
4672  }
4673
4674  async renderWishlistItemOptions() {
4675    if (this.listItem && this.elements.optionsContainer) {
4676      let selectedVariantId = this.currentSlectedVariantId || this.listItem?.epi;
4677      const selectedVariant = SwymStorefrontLayoutContext?.getSelectedVariant(this.listItem, selectedVariantId);
4678      const productImage = selectedVariant?.featured_image?.src || this.listItem.productData?.featured_image || this.listItem.iu;
4679      let canEdit = SwymStorefrontLayoutContext?.checkUserCanEditList(this.list);
4680      
4681      // Get multi-wishlist configuration to determine if we should show "Add to list" option
4682      const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
4683
4684      this.elements.optionsContainer.innerHTML = `
4685        ${shouldShowMultiple? `<div class="swym-storefront-layout-action-tooltip-btn add-to-collection-button" role="button" tabindex="0" aria-label="${SwymStorefrontLayoutContext?.Strings?.addToCollectionCta || 'Add to collection'}">
4686          <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewB
4686ox="0 0 16 16" fill="currentColor" aria-hidden="true">
4687            <path d="M7.33331 8.66683H3.33331V7.3335H7.33331V3.3335H8.66665V7.3335H12.6666V8.66683H8.66665V12.6668H7.33331V8.66683Z" fill="currentColor"/>
4688          </svg>
4689          ${SwymStorefrontLayoutContext?.Strings?.addToCollectionCta}
4690        </div>` : ''}
4691        ${canEdit?`<div class="swym-storefront-layout-action-tooltip-btn remove-from-list-button" role="button" tabindex="0" aria-label="${SwymStorefrontLayoutContext?.Strings?.removeItemCta || 'Remove from list'}">
4692          <svg xmlns="http://www.w3.org/2000/svg" width="16" height="17" viewBox="0 0 16 17" fill="currentColor" aria-hidden="true">
4693            <path d="M4.66669 14.5C4.30002 14.5 3.98613 14.3694 3.72502 14.1083C3.46391 13.8472 3.33335 13.5333 3.33335 13.1667V4.5H2.66669V3.16667H6.00002V2.5H10V3.16667H13.3334V4.5H12.6667V13.1667C12.6667 13.5333 12.5361 13.8472 12.275 14.1083C12.0139 14.3694 11.7 14.5 11.3334 14.5H4.66669ZM11.3334 4.5H4.66669V13.1667H11.3334V4.5ZM6.00002 11.8333H7.33335V5.83333H6.00002V11.8333ZM8.66669 11.8333H10V5.83333H8.66669V11.8333Z" fill="currentColor"></path>
4694          </svg>
4695          ${SwymStorefrontLayoutContext?.Strings?.removeItemCta || 'Remove from list'}
4696        </div>`:''}
4697      `;
4698      this.addOptionEventListeners();
4699    }
4700  }
4701
4702  async renderShareSingleWishlist() {
4703    // Check if user is logged in before showing share option
4704    const isLoggedIn = window._swat?.platform?.isLoggedIn();
4705    if(!isLoggedIn) {
4706      this.elements.optionsContainer.innerHTML = '';
4707      return;
4708    }
4709
4710    if(this.elements.optionsContainer) {
4711            this.elements.optionsContainer.innerHTML = `<div class="swym-storefront-layout-action-tooltip-btn share-collection-button" role="button" tabindex="0" aria-label="${SwymStorefrontLayoutContext?.Strings?.shareCollectionCta || 'Share collection'}">
4712                <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="currentColor" aria-hidden="true">
4713                  <path d="M9.91666 12.8337C9.43055 12.8337 9.01735 12.6635 8.67707 12.3232C8.3368 11.983 8.16666 11.5698 8.16666 11.0837C8.16666 11.0253 8.18124 10.8892 8.21041 10.6753L4.11249 8.28366C3.95693 8.42949 3.77707 8.54373 3.57291 8.62637C3.36874 8.70901 3.14999 8.75033 2.91666 8.75033C2.43055 8.75033 2.01735 8.58019 1.67707 8.23991C1.3368 7.89963 1.16666 7.48644 1.16666 7.00033C1.16666 6.51421 1.3368 6.10102 1.67707 5.76074C2.01735 5.42046 2.43055 5.25033 2.91666 5.25033C3.14999 5.25033 3.36874 5.29164 3.57291 5.37428C3.77707 5.45692 3.95693 5.57116 4.11249 5.71699L8.21041 3.32533C8.19096 3.25727 8.17881 3.19164 8.17395 3.12845C8.16909 3.06526 8.16666 2.99477 8.16666 2.91699C8.16666 2.43088 8.3368 2.01769 8.67707 1.67741C9.01735 1.33713 9.43055 1.16699 9.91666 1.16699C10.4028 1.16699 10.816 1.33713 11.1562 1.67741C11.4965 2.01769 11.6667 2.43088 11.6667 2.91699C11.6667 3.4031 11.4965 3.8163 11.1562 4.15658C10.816 4.49685 10.4028 4.66699 9.91666 4.66699C9.68332 4.66699 9.46457 4.62567 9.26041 4.54303C9.05624 4.46039 8.87638 4.34616 8.72082 4.20033L4.62291 6.59199C4.64235 6.66005 4.6545 6.72567 4.65936 6.78887C4.66423 6.85206 4.66666 6.92255 4.66666 7.00033C4.66666 7.0781 4.66423 7.14859 4.65936 7.21178C4.6545 7.27498 4.64235 7.3406 4.62291 7.40866L8.72082 9.80033C8.87638 9.65449 9.05624 9.54026 9.26041 9.45762C9.46457 9.37498 9.68332 9.33366 9.91666 9.33366C10.4028 9.33366 10.816 9.5038 11.1562 9.84408C11.4965 10.1844 11.6667 10.5975 11.6667 11.0837C11.6667 11.5698 11.4965 11.983 11.1562 12.3232C10.816 12.6635 10.4028 12.8337 9.91666 12.8337ZM9.91666 11.667C10.0819 11.667 10.2205 11.6111 10.3323 11.4993C10.4441 11.3875 10.5 11.2489 10.5 11.0837C10.5 10.9184 10.4441 10.7798 10.3323 10.668C10.2205 10.5562 10.0819 10.5003 9.91666 10.5003C9.75138 10.5003 9.61284 10.5562 9.50103 10.668C9.38923 10.7798 9.33332 10.9184 9.33332 11.0837C9.33332 11.2489 9.38923 11.3875 9.50103 11.4993C9.61284 11.6111 9.75138 11.667 9.91666 11.667ZM2.91666 7.58366C3.08193 7.58366 3.22048 7.52776 3.33228 7.41595C3.44409 7.30415 3.49999 7.1656 3.49999 7.00033C3.49999 6.83505 3.44409 6.69651 3.33228 6.5847C3.22048 6.4729 3.08193 6.41699 2.91666 6.41699C2.75138 6.41699 2.61284 6.4729 2.50103 6.5847C2.38923 6.69651 2.33332 6.83505 2.33332 7.00033C2.33332 7.1656 2.38923 7.30415 2.50103 7.41595C2.61284 7.52776 2.75138 7.58366 2.91666 7.58366ZM9.91666 3.50033C10.0819 3.50033 10.2205 3.44442 10.3323 3.33262C10.4441 3.22081 10.5 3.08227 10.5 2.91699C10.5 2.75171 10.4441 2.61317 10.3323 2.50137C10.2205 2.38956 10.0819 2.33366 9.91666 2.33366C9.75138 2.33366 9.61284 2.38956 9.50103 2.50137C9.38923 2.61317 9.33332 2.75171 9.33332 2.91699C9.33332 3.08227 9.38923 3.22081 9.50103 3.33262C9.61284 3.44442 9.75138 3.50033 9.91666 3.50033Z" fill="currentColor" fill-opacity="0.8"/>
4714                </svg>
4715                ${SwymStorefrontLayoutContext?.Strings?.shareCollectionCta}
4716              </div>`;
4717              this.addEditCollectionEventListeners();
4718    }
4719  }
4720
4721  async renderShareSFLWishlist() {
4722    // Check if user is logged in before showing share option
4723    const isLoggedIn = window._swat?.platform?.isLoggedIn();
4724    if(!isLoggedIn) {
4725      this.elements.optionsContainer.innerHTML = '';
4726      return;
4727    }
4728
4729    if(this.elements.optionsContainer) {
4730      this.elements.optionsContainer.innerHTML = `<div class="swym-storefront-layout-action-tooltip-btn share-collection-button" role="button" tabindex="0" aria-label="${SwymStorefrontLayoutContext?.Strings?.shareCollectionCta || 'Share collection'}">
4731          <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="currentColor" aria-hidden="true">
4732            <path d="M9.91666 12.8337C9.43055 12.8337 9.01735 12.6635 8.67707 12.3232C8.3368 11.983 8.16666 11.5698 8.16666 11.0837C8.16666 11.0253 8.18124 10.8892 8.21041 10.6753L4.11249 8.28366C3.95693 8.42949 3.77707 8.54373 3.57291 8.62637C3.36874 8.70901 3.14999 8.75033 2.91666 8.75033C2.43055 8.75033 2.01735 8.58019 1.67707 8.23991C1.3368 7.89963 1.16666 7.48644 1.16666 7.00033C1.16666 6.51421 1.3368 6.10102 1.67707 5.76074C2.01735 5.42046 2.43055 5.25033 2.91666 5.25033C3.14999 5.25033 3.36874 5.29164 3.57291 5.37428C3.77707 5.45692 3.95693 5.57116 4.11249 5.71699L8.21041 3.32533C8.19096 3.25727 8.17881 3.19164 8.17395 3.12845C8.16909 3.06526 8.16666 2.99477 8.16666 2.91699C8.16666 2.43088 8.3368 2.01769 8.67707 1.67741C9.01735 1.33713 9.43055 1.16699 9.91666 1.16699C10.4028 1.16699 10.816 1.33713 11.1562 1.67741C11.4965 2.01769 11.6667 2.43088 11.6667 2.91699C11.6667 3.4031 11.4965 3.8163 11.1562 4.15658C10.816 4.49685 10.4028 4.66699 9.91666 4.66699C9.68332 4.66699 9.46457 4.62567 9.26041 4.54303C9.05624 4.46039 8.87638 4.34616 8.72082 4.20033L4.62291 6.59199C4.64235 6.66005 4.6545 6.72567 4.65936 6.78887C4.66423 6.85206 4.66666 6.92255 4.66666 7.00033C4.66666 7.0781 4.66423 7.14859 4.65936 7.21178C4.6545 7.27498 4.64235 7.3406 4.62291 7.40866L8.72082 9.80033C8.87638 9.65449 9.05624 9.54026 9.26041 9.45762C9.46457 9.37498 9.68332 9.33366 9.91666 9.33366C10.4028 9.33366 10.816 9.5038 11.1562 9.84408C11.4965 10.1844 11.6667 10.5975 11.6667 11.0837C11.6667 11.5698 11.4965 11.983 11.1562 12.3232C10.816 12.6635 10.4028 12.8337 9.91666 12.8337ZM9.91666 11.667C10.0819 11.667 10.2205 11.6111 10.3323 11.4993C10.4441 11.3875 10.5 11.2489 10.5 11.0837C10.5 10.9184 10.4441 10.7798 10.3323 10.668C10.2205 10.5562 10.0819 10.5003 9.91666 10.5003C9.75138 10.5003 9.61284 10.5562 9.50103 10.668C9.38923 10.7798 9.33332 10.9184 9.33332 11.0837C9.33332 11.2489 9.38923 11.3875 9.50103 11.4993C9.61284 11.6111 9.75138 11.667 9.91666 11.667ZM2.91666 7.58366C3.08193 7.58366 3.22048 7.52776 3.33228 7.41595C3.44409 7.30415 3.49999 7.1656 3.49999 7.00033C3.49999 6.83505 3.44409 6.69651 3.33228 6.5847C3.22048 6.4729 3.08193 6.41699 2.91666 6.41699C2.75138 6.41699 2.61284 6.4729 2.50103 6.5847C2.38923 6.69651 2.33332 6.83505 2.33332 7.00033C2.33332 7.1656 2.38923 7.30415 2.50103 7.41595C2.61284 7.52776 2.75138 7.58366 2.91666 7.58366ZM9.91666 3.50033C10.0819 3.50033 10.2205 3.44442 10.3323 3.33262C10.4441 3.22081 10.5 3.08227 10.5 2.91699C10.5 2.75171 10.4441 2.61317 10.3323 2.50137C10.2205 2.38956 10.0819 2.33366 9.91666 2.33366C9.75138 2.33366 9.61284 2.38956 9.50103 2.50137C9.38923 2.61317 9.33332 2.75171 9.33332 2.91699C9.33332 3.08227 9.38923 3.22081 9.50103 3.33262C9.61284 3.44442 9.75138 3.50033 9.91666 3.50033Z" fill="currentColor" fill-opacity="0.8"/>
4733          </svg>
4734          ${SwymStorefrontLayoutContext?.Strings?.shareCollectionCta}
4735        </div>`;
4736        this.addShareSFLEventListeners();
4737    }
4738  }
4739
4740  addEditCollectionEventListeners() {
4741    const shareCollectionBtn = this.querySelector('.share-collection-button');
4742    const deleteCollectionBtn = this.querySelector('.delete-list-button');
4743    this.listId = SwymStorefrontLayoutContext?.sflList?.lid;
4744    
4745    shareCollectionBtn?.addEventListener('click', () => {
4746      this.shareCollection();
4747    });
4748    
4749    // Keyboard support for share button
4750    shareCollectionBtn?.addEventListener('keydown', (e) => {
4751      if (e.key === 'Enter' || e.key === ' ') {
4752        e.preventDefault();
4753        this.shareCollection();
4754      }
4755    });
4756    
4757    deleteCollectionBtn?.addEventListener('click', async () => {
4758      try {
4759        await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.deleteLists([this.list]);
4760        this.closeTooltip();
4761        window.location.hash = SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.List;
4762        SwymStorefrontLayoutExtensions?.refreshWishList();
4763        const collectionListView = document.querySelector('swym-storefront-layout-collection-list');
4764        collectionListView.closeCollectinListView();
4765
4766        SwymStorefrontLayoutExtensions?.Notification?.setMessage({
4767          message: SwymStorefrontLayoutContext?.Strings?.notificationMessageCollectionDeleted,
4768          status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Toast,
4769          iconType: SwymStorefrontLayoutContext?.NotificationIconType?.SuccessIcon
4770        });
4771
4772        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutCollectionDeleted, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutCollectionInteractions });
4773
4774      } catch (error) {
4775        window._swat?.utils.error('Failed to delete collection:', error);
4776      }
4777    });
4778    
4779    // Keyboard support for delete button
4780    deleteCollectionBtn?.addEventListener('keydown', (e) => {
4781      if (e.key === 'Enter' || e.key === ' ') {
4782        e.preventDefault();
4783        deleteCollectionBtn.click();
4784      }
4785    });
4786  }
4787
4788  addShareSFLEventListeners() {
4789    const shareCollectionBtn = this.querySelector('.share-collection-button');
4790    shareCollectionBtn?.addEventListener('click', () => {
4791      this.shareCollection(SwymStorefrontLayoutContext.sflList);
4792    });
4793    
4794    // Keyboard support for share button
4795    shareCollectionBtn?.addEventListener('keydown', (e) => {
4796      if (e.key === 'Enter' || e.key === ' ') {
4797        e.preventDefault();
4798        this.shareCollection(SwymStorefrontLayoutContext.sflList);
4799      }
4800    });
4801  }
4802  
4803  addOptionEventListeners() {
4804    const addToCollectionBtn = this.querySelector('.add-to-collection-button');
4805    const removeFromListBtn = this.querySelector('.remove-from-list-button');
4806
4807    addToCollectionBtn?.addEventListener('click', () => {
4808      this.closeTooltip();
4809      
4810      SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActions?.setData({
4811        listId: this.listId,
4812        list: this.list,
4813        item: this.listItem,
4814        collections: this.collections,
4815        actionType: SwymStorefrontLayoutContext?.ActionTypes.AddToCollection,
4816        canCreateLists: this.canCreateLists
4817      });
4818      SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActions?.openDrawer();
4819
4820    });
4821
4822    removeFromListBtn?.addEventListener('click', async () => {
4823      try {
4824
4825        this.closeTooltip();
4826
4827        let { epi, empi, du } = this.listItem;
4828        if(this.currentSlectedVariantId){
4829          epi = this.currentSlectedVariantId;
4830        }
4831        await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.removeProductFromList({ epi, empi, du }, this.listId);
4832
4833        // Try to find and remove the element from whichever container it's in
4834        let elementDeleted = this.elements.wishlistItemsContainer?.querySelector(`[data-epi="${epi}"]`) ||
4835                            this.elements.collectionItemsContainer?.querySelector(`[data-epi="${epi}"]`);
4836        elementDeleted?.remove();
4837
4838        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutItemRemovedFromList, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutItemInteractions, epi, empi });
4839
4840      } catch (error) {
4841        window._swat?.utils.error('Failed to remove product from the list:', error);
4842      }
4843    });
4844  }
4845
4846  async renderEditCollection() {
4847    if (this.list && this.elements.optionsContainer) {
4848      // Check if user is logged in before showing share option
4849      const isLoggedIn = window._swat?.platform?.isLoggedIn();
4850      
4851      const shareButton = isLoggedIn ? `
4852        <div class="swym-storefront-layout-action-tooltip-btn share-collection-button" role="button" tabindex="0" aria-label="${SwymStorefrontLayoutContext?.Strings?.shareCollectionCta || 'Share collection'}">
4853          <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="currentColor" aria-hidden="true">
4854            <path d="M9.91666 12.8337C9.43055 12.8337 9.01735 12.6635 8.67707 12.3232C8.3368 11.983 8.16666 11.5698 8.16666 11.0837C8.16666 11.0253 8.18124 10.8892 8.21041 10.6753L4.11249 8.28366C3.95693 8.42949 3.77707 8.54373 3.57291 8.62637C3.36874 8.70901 3.14999 8.75033 2.91666 8.75033C2.43055 8.75033 2.01735 8.58019 1.67707 8.23991C1.3368 7.89963 1.16666 7.48644 1.16666 7.00033C1.16666 6.51421 1.3368 6.10102 1.67707 5.76074C2.01735 5.42046 2.43055 5.25033 2.91666 5.25033C3.14999 5.25033 3.36874 5.29164 3.57291 5.37428C3.77707 5.45692 3.95693 5.57116 4.11249 5.71699L8.21041 3.32533C8.19096 3.25727 8.17881 3.19164 8.17395 3.12845C8.16909 3.06526 8.16666 2.99477 8.16666 2.91699C8.16666 2.43088 8.3368 2.01769 8.67707 1.67741C9.01735 1.33713 9.43055 1.16699 9.91666 1.16699C10.4028 1.16699 10.816 1.33713 11.1562 1.67741C11.4965 2.01769 11.6667 2.43088 11.6667 2.91699C11.6667 3.4031 11.4965 3.8163 11.1562 4.15658C10.816 4.49685 10.4028 4.66699 9.91666 4.66699C9.68332 4.66699 9.46457 4.62567 9.26041 4.54303C9.05624 4.46039 8.87638 4.34616 8.72082 4.20033L4.62291 6.59199C4.64235 6.66005 4.6545 6.72567 4.65936 6.78887C4.66423 6.85206 4.66666 6.92255 4.66666 7.00033C4.66666 7.0781 4.66423 7.14859 4.65936 7.21178C4.6545 7.27498 4.64235 7.3406 4.62291 7.40866L8.72082 9.80033C8.87638 9.65449 9.05624 9.54026 9.26041 9.45762C9.46457 9.37498 9.68332 9.33366 9.91666 9.33366C10.4028 9.33366 10.816 9.5038 11.1562 9.84408C11.4965 10.1844 11.6667 10.5975 11.6667 11.0837C11.6667 11.5698 11.4965 11.983 11.1562 12.3232C10.816 12.6635 10.4028 12.8337 9.91666 12.8337ZM9.91666 11.667C10.0819 11.667 10.2205 11.6111 10.3323 11.4993C10.4441 11.3875 10.5 11.2489 10.5 11.0837C10.5 10.9184 10.4441 10.7798 10.3323 10.668C10.2205 10.5562 10.0819 10.5003 9.91666 10.5003C9.7
48545138 10.5003 9.61284 10.5562 9.50103 10.668C9.38923 10.7798 9.33332 10.9184 9.33332 11.0837C9.33332 11.2489 9.38923 11.3875 9.50103 11.4993C9.61284 11.6111 9.75138 11.667 9.91666 11.667ZM2.91666 7.58366C3.08193 7.58366 3.22048 7.52776 3.33228 7.41595C3.44409 7.30415 3.49999 7.1656 3.49999 7.00033C3.49999 6.83505 3.44409 6.69651 3.33228 6.5847C3.22048 6.4729 3.08193 6.41699 2.91666 6.41699C2.75138 6.41699 2.61284 6.4729 2.50103 6.5847C2.38923 6.69651 2.33332 6.83505 2.33332 7.00033C2.33332 7.1656 2.38923 7.30415 2.50103 7.41595C2.61284 7.52776 2.75138 7.58366 2.91666 7.58366ZM9.91666 3.50033C10.0819 3.50033 10.2205 3.44442 10.3323 3.33262C10.4441 3.22081 10.5 3.08227 10.5 2.91699C10.5 2.75171 10.4441 2.61317 10.3323 2.50137C10.2205 2.38956 10.0819 2.33366 9.91666 2.33366C9.75138 2.33366 9.61284 2.38956 9.50103 2.50137C9.38923 2.61317 9.33332 2.75171 9.33332 2.91699C9.33332 3.08227 9.38923 3.22081 9.50103 3.33262C9.61284 3.44442 9.75138 3.50033 9.91666 3.50033Z" fill="currentColor" fill-opacity="0.8"/>
4855          </svg>
4856          ${SwymStorefrontLayoutContext?.Strings?.shareCollectionCta}
4857        </div>` : '';
4858
4859      this.elements.optionsContainer.innerHTML = `
4860        ${shareButton}
4861        <div class="swym-storefront-layout-action-tooltip-btn delete-list-button" role="button" tabindex="0"        aria-label="${SwymStorefrontLayoutContext?.Strings?.deleteCollectionCta || 'Delete collection'}">
4862                  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="17" viewBox="0 0 16 17" fill="currentColor" aria-hidden="true">
4863                    <path d="M4.66667 14.5C4.3000114.5 3.98612 14.3694 3.72501 14.1083C3.46389 13.8472 3.33334 13.5333 3.33334 13.1667V4.5H2.66667V3.16667H6.00001V2.5H10V3.16667H13.3333V4.5H12.6667V13.1667C12.6667 13.5333 12.5361 13.8472 12.275 14.1083C12.0139 14.3694 11.7 14.5 11.3333 14.5H4.66667ZM11.3333 4.5H4.66667V13.1667H11.3333V4.5ZM6.00001 11.8333H7.33334V5.83333H6.00001V11.8333ZM8.66667 11.8333H10V5.83333H8.66667V11.8333Z" fill="currentColor"/>
4864          </svg>
4865          ${SwymStorefrontLayoutContext?.Strings?.deleteCollectionCta}
4866        </div>
4867      `;
4868      this.addEditCollectionEventListeners();
4869    }
4870  }
4871
4872  addEditCollectionEventListeners() {
4873    const shareCollectionBtn = this.querySelector('.share-collection-button');
4874    const deleteListBtn = this.querySelector('.delete-list-button');
4875
4876    shareCollectionBtn?.addEventListener('click', () => {
4877      this.shareCollection();
4878      this.closeTooltip();
4879    });
4880    
4881    // Keyboard support for share button
4882    shareCollectionBtn?.addEventListener('keydown', (e) => {
4883      if (e.key === 'Enter' || e.key === ' ') {
4884        e.preventDefault();
4885        this.shareCollection();
4886        this.closeTooltip();
4887      }
4888    });
4889
4890    deleteListBtn?.addEventListener('click', async () => {
4891      try {
4892        await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.deleteLists([this.list]);
4893        this.closeTooltip();
4894        window.location.hash = SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.List;
4895        SwymStorefrontLayoutExtensions?.refreshWishList();
4896        const collectionListView = document.querySelector('swym-storefront-layout-collection-list');
4897        collectionListView.closeCollectinListView();
4898
4899        SwymStorefrontLayoutExtensions?.Notification?.setMessage({
4900          message: SwymStorefrontLayoutContext?.Strings?.notificationMessageCollectionDeleted,
4901          status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Toast,
4902          iconType: SwymStorefrontLayoutContext?.NotificationIconType?.SuccessIcon
4903        });
4904
4905        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutCollectionDeleted, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutCollectionInteractions });
4906
4907      } catch (error) {
4908        window._swat?.utils.error('Failed to remove product from the list:', error);
4909      }
4910    });
4911    
4912    // Keyboard support for delete button
4913    deleteListBtn?.addEventListener('keydown', (e) => {
4914      if (e.key === 'Enter' || e.key === ' ') {
4915        e.preventDefault();
4916        deleteListBtn.click();
4917      }
4918    });
4919  }
4920
4921  async renderSaveCollection() {
4922    if (this.list && this.elements.optionsContainer) {
4923      this.elements.optionsContainer.innerHTML = `
4924        <div class="swym-storefront-layout-action-tooltip-btn save-collection-button" role="button" tabindex="0"        aria-label="${SwymStorefrontLayoutContext?.Strings?.saveCollectionCta || 'Save collection'}">
4925                  <svg xmlns="http://www.w3.org/2000/svg" width="12px" height="12px" viewBox="0 0 48 48" fill="none" aria-hidden="true">
4926            <path d="M8 28H24" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
4927            <path d="M8 37H24" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
4928            <path d="M8 19H40" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
4929            <path d="M8 10H40" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
4930            <path d="M30 33H40" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
4931            <path d="M35 28L35 38" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
4932          </svg>
4933          ${SwymStorefrontLayoutContext?.Strings?.saveCollectionCta}
4934        </div>
4935      `;
4936      this.addSaveCollectionEventListeners();
4937    }
4938  }
4939
4940  addSaveCollectionEventListeners() {
4941    const saveCollectionBtn = this.querySelector('.save-collection-button');
4942    
4943    saveCollectionBtn?.addEventListener('click', () => {
4944      this.closeTooltip();
4945      this.handleSaveCollection();
4946    });
4947  }
4948  async shareCollection() {
4949    const activeTab = document.querySelector('.swym-storefront-layout-tab-button.swym-storefront-layout-tab-button-active');
4950    const activeDataView = activeTab?.getAttribute('data-view');
4951    window._swat.evtLayer.dispatchEvent(new CustomEvent('sw:renderShareWishlistUI', {
4952      detail: {
4953        lid: this.list?.lid || this.listId,
4954        lname: '',
4955        list: activeDataView === "tabSavedForLater" ? SwymStorefrontLayoutContext?.sflList : this.list,
4956        layoutType: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType,
4957        senderName: '', // optional,
4958        activeDataView
4959      }
4960    }));
4961  }
4962  
4963  async handleSaveCollection(){
4964    let savedList = await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.createList(this.list.lname);
4965    let itemsToAdd = this.list.listcontents.map(({ empi, epi, du }) => ({ empi, epi, du }));
4966    await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.addProductsToList(itemsToAdd, savedList.lid);
4967    window.location.hash = SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.List;
4968    
4969    SwymStorefrontLayoutExtensions?.Notification?.setMessage({
4970      message: SwymStorefrontLayoutContext?.Strings?.notificationMessageCollectionSaved,
4971      status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Neutral,
4972      iconType: SwymStorefrontLayoutContext?.NotificationIconType?.SuccessIcon,
4973      duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
4974      action: {
4975        label: SwymStorefrontLayoutContext?.Strings?.notificationActionViewCollection,
4976        onClick: () => {
4977          window.location.hash = SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.CollectionList + savedList.lid;
4978        }
4979      }
4980    });
4981
4982  }
4983
4984  addEventListenerToView() {
4985    document.addEventListener("click", (event) => {
4986      if (!this.elements.tooltipLayout.contains(event.target)) {
4987        this.closeTooltip();
4988      }
4989    });
4990  }
4991
4992  async renderSflListItemOptions(){
4993    if (this.listItem && this.elements.optionsContainer) {
4994      let selectedVariantId = this.currentSlectedVariantId || this.listItem?.epi;
4995      const selectedVariant = SwymStorefrontLayoutContext?.getSelectedVariant(this.listItem, selectedVariantId);
4996      let canEdit = SwymStorefrontLayoutContext?.checkUserCanEditList(this.list);
4997      this.elements.optionsContainer.innerHTML = `
4998        ${canEdit?`<div class="swym-storefront-layout-action-tooltip-btn remove-from-list-button" role="button" tabindex="0"        aria-label="${SwymStorefrontLayoutContext?.Strings?.removeSflItemCta || 'Remove from list'}">
4999                  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="17" viewBox="0 0 16 17" fill="currentColor" aria-hidden="true">
5000                    <path d="M4.66669 14.5C4.30002 14.5 3.98613 14.3694 3.72502 14.1083C3.46391 13.8472 3.33335 13.5333 3.33335 13.1667V4.5H2.66669V3.16667H6.00002V2.5H10V3.16667H13.3334V4.5H12.6667V13.1667C12.6667 13.5333 12.5361 13.8472 12.275 14.1083C12.0139 14.3694 11.7 14.5 11.3334 14.5H4.66669ZM11.3334 4.5H4.66669V13.1667H11.3334V4.5ZM6.00002 11.8333H7.33335V5.83333H6.00002V11.8333ZM8.66669 11.8333H10V5.83333H8.66669V11.8333Z" fill="currentColor"></path>
5001                  </svg>
5002                  ${SwymStorefrontLayoutContext?.Strings?.removeSflItemCta || 'Remove from list'}
5003        </div>`:''}
5004      `;
5005      this.addSflOptionEventListeners();
5006    }
5007  }
5008
5009  async renderSfyListItemOptions(){
5010    if (this.listItem && this.elements.optionsContainer) {
5011      this.elements.optionsContainer.innerHTML = `
5012        <div class="swym-storefront-layout-action-tooltip-btn swym-sfy-remove-button" role="button" tabindex="0" aria-label="${SwymStorefrontLayoutContext?.Strings?.removeItemCta || 'Remove'}">
5013          <svg xmlns="http://www.w3.org/2000/svg" width="16" height="17" viewBox="0 0 16 17" fill="currentColor" aria-hidden="true">
5014            <path d="M4.66669 14.5C4.30002 14.5 3.98613 14.3694 3.72502 14.1083C3.46391 13.8472 3.33335 13.5333 3.33335 13.1667V4.5H2.66669V3.16667H6.00002V2.5H10V3.16667H13.3334V4.5H12.6667V13.1667C12.6667 13.5333 12.5361 13.8472 12.275 14.1083C12.0139 14.3694 11.7 14.5 11.3334 14.5H4.66669ZM11.3334 4.5H4.66669V13.1667H11.3334V4.5ZM6.00002 11.8333H7.33335V5.83333H6.00002V11.8333ZM8.66669 11.8333H10V5.83333H8.66669V11.8333Z" fill="currentColor"></path>
5015          </svg>
5016          ${SwymStorefrontLayoutContext?.Strings?.removeItemCta || 'Remove'}
5017        </div>
5018      `;
5019      this.addSfyOptionEventListeners();
5020    }
5021  }
5022
5023  addSfyOptionEventListeners() {
5024    const removeBtn = this.querySelector('.swym-sfy-remove-button');
5025    removeBtn?.addEventListener('click', async () => {
5026      try {
5027        this.closeTooltip();
5028        const { epi, empi, du } = this.listItem;
5029        const lid = this.listId;
5030
5031        // Remove item from ALL context references (String comparison for type safety)
5032        SwymStorefrontLayoutContext.updateAllListContents((listcontents = []) =>
5033          listcontents.filter(item => String(item.epi) !== String(epi))
5034        );
5035
5036        // Dispatch WishlistFetched to update UI immediately
5037        if (SwymStorefrontLayoutContext?.CustomEvents?.WishlistFetched) {
5038          document.dispatchEvent(new CustomEvent(SwymStorefrontLayoutContext.CustomEvents.WishlistFetched, {
5039            detail: {
5040              defaultList: SwymStorefrontLayoutContext.DefaultList,
5041              collections: SwymStorefrontLayoutContext.collections,
5042              lists: SwymStorefrontLayoutContext.lists
5043            }
5044          }));
5045        }
5046
5047        SwymStorefrontLayoutExtensions?.Notification?.setMessage({
5048          message: SwymStorefrontLayoutContext?.Strings?.notificationMessageItemRemoved,
5049          status: SwymStorefrontLayoutContext?.NotificationStatusTypes?.Toast,
5050          duration: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutNotificationDuration,
5051          image: this.listItem?.iu
5052        });
5053
5054        // Fire API THEN refresh to reconcile with server
5055        await SwymStorefrontLayoutAPI?.SwymWLAsyncApis?.removeProductFromList({ epi, empi, du }, lid);
5056        SwymStorefrontLayoutExtensions?.refreshWishList();
5057        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutSFYItemRemoved, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutItemInteractions, epi, empi });
5058      } catch (err) {
5059        window._swat?.utils.error('[SFY] Remove failed', err);
5060      }
5061    });
5062    removeBtn?.addEventListener('keydown', (e) => {
5063      if (e.key === 'Enter' || e.key === ' ') {
5064        e.preventDefault();
5065        removeBtn.click();
5066      }
5067    });
5068  }
5069
5070  addSflOptionEventListeners() {
5071    const removeFromListBtn = this.querySelector('.remove-from-list-button');
5072
5073    removeFromListBtn?.addEventListener('click', async () => {
5074      try {
5075
5076        this.closeTooltip();
5077
5078        let { epi, empi, du } = this.listItem;
5079        if(this.currentSlectedVariantId){
5080          epi = this.currentSlectedVariantId;
5081        }
5082        await SwymStorefrontLayoutAPI?.SwymSFLAsyncApis?.removeProductFromSFL({ epi, empi, du }, this.listId);
5083
5084        let elementDeleted = this.elements.sflItemsContainer?.querySelector(`[data-epi="${epi}"]`);
5085        elementDeleted?.remove();
5086
5087        window._swat?.triggerSwymEvent(window._swat?.JSEvents?.removedFromSFL, this.listItem);
5088
5089      } catch (error) {
5090        window._swat?.utils.error('Failed to remove product from the list:', error);
5091      }
5092    });
5093  }
5094
5095  attachEventToHideTooltip(){
5096
5097    window.removeEventListener("scroll", ()=> this.closeTooltip());
5098    window.addEventListener("scroll", ()=> this.closeTooltip());
5099
5100    let scrollableElements = document.querySelectorAll('.swym-storefront-layout-scrollable');
5101
5102    scrollableElements.forEach((element) => {
5103      element.removeEventListener("scroll", ()=> this.closeTooltip());
5104      element.addEventListener("scroll", ()=> this.closeTooltip());
5105    });
5106  }
5107
5108    openTooltip() {
5109      this.isTooltipOpen = true;
5110      this._closedViaKeyboard = false;
5111      const tl = this.elements.tooltipLayout;
5112
5113      // Abort any previous keydown listener to prevent accumulation
5114      if (this._tooltipKeydownController) {
5115        this._tooltipKeydownController.abort();
5116      }
5117      this._tooltipKeydownController = new AbortController();
5118
5119      tl.classList.add("swym-storefront-layout-show-action-tooltip-view");
5120      tl.setAttribute("role", "dialog");
5121      tl.setAttribute("aria-label", "Wishlist options");
5122      tl.setAttribute("aria-hidden", "false");
5123      tl.setAttribute("tabindex", "-1");
5124
5125      const firstBtn = this.elements.optionsContainer?.querySelector('.swym-storefront-layout-action-tooltip-btn');
5126      if (firstBtn) {
5127        firstBtn.focus();
5128      } else {
5129        tl.focus();
5130      }
5131
5132      tl.addEventListener(
5133        "keydown",
5134        (e) => {
5135          if (["Enter", " "].includes(e.key)) {
5136            const activeBtn = document.activeElement?.closest('[role="button"]');
5137            if (activeBtn && tl.contains(activeBtn)) {
5138              e.preventDefault();
5139              activeBtn.click();
5140            }
5141          }
5142          if (e.key === "Escape") {
5143            e.preventDefault();
5144            this._closedViaKeyboard = true;
5145            this.closeTooltip();
5146          }
5147        },
5148        { signal: this._tooltipKeydownController.signal }
5149      );
5150
5151      this.attachEventToHideTooltip();
5152    }
5153
5154  showOnTarget(buttonTarget){
5155    this.closeTooltip();
5156
5157    let viewPort = document.querySelector('.swym-storefront-layout-layout');
5158
5159    const tooltip = this.elements.tooltipLayout;
5160    let buttonRect = buttonTarget.getBoundingClientRect();
5161    let viewPortRect = viewPort?.getBoundingClientRect();
5162
5163    const buttonRight = buttonRect.right;
5164    const buttonLeft = buttonRect.left;
5165    const buttonLeftOnViewPort = buttonRect.left - viewPortRect?.left;
5166
5167    const tooltipWidth = this.elements.tooltipLayout.offsetWidth
5168    const viewportWidth = viewPort.clientWidth
5169
5170
5171    if (buttonLeftOnViewPort > viewportWidth / 2) {
5172      tooltip.style.left = `${(buttonLeft + 2) - tooltipWidth}px`
5173      tooltip.style.top = `${buttonRect.top + 25}px`
5174    } else {
5175      tooltip.style.left = `${buttonLeft + 2 }px`
5176      tooltip.style.top = `${buttonRect.top + 25}px`
5177    }
5178
5179    setTimeout(()=>{
5180      this.openTooltip();
5181      this.currentTarget = buttonTarget;
5182    },100)
5183
5184  }
5185
5186  closeTooltip() {
5187    this.isTooltipOpen = false;
5188    const tl = this.elements.tooltipLayout;
5189    tl.classList.remove('swym-storefront-layout-show-action-tooltip-view');
5190    tl.setAttribute("aria-hidden", "true");
5191    tl.removeAttribute("role");
5192    tl.removeAttribute("aria-label");
5193    if (this._tooltipKeydownController) {
5194      this._tooltipKeydownController.abort();
5195      this._tooltipKeydownController = null;
5196    }
5197    if (this._closedViaKeyboard && this.currentTarget) {
5198      this.currentTarget.focus();
5199    }
5200    this._closedViaKeyboard = false;
5201  }
5202
5203}
5204
5205/**
5206 * SwymStorefrontLayoutNotification
5207 * 
5208 * A Web Component for displaying notifications in the storefront layout. 
5209 * It supports customizable configurations, auto-hide functionality, 
5210 * and dynamic content rendering based on user actions.
5211 * 
5212 * Features:
5213 * - Supports various notification types (success, info, etc.).
5214 * - Configurable options for displaying images, titles, messages, and action buttons.
5215 * - Auto-hide functionality with configurable duration.
5216 * - Supports icons and images based on notification type.
5217 * - Integrates with `SwymStorefrontLayoutContext?.Settings` to check if notifications are enabled.
5218 * 
5219 * Dependencies:
5220 * - `SwymStorefrontLayoutContext`: Provides settings and icon type references.
5221 * 
5222 * Usage:
5223 * ```html
5224 * <swym-storefront-layout-notification></swym-storefront-layout-notification>
5225 * ```
5226 * 
5227 * Example JavaScript Usage:
5228 * ```javascript
5229 * const notification = document.querySelector('swym-storefront-layout-notification');
5230 * notification.setMessage({
5231 *   message: 'Item added to wishlist!',
5232 *   status: 'success',
5233 *   duration: 4000,
5234 *   image: 'https://example.com/image.jpg',
5235 *   action: {
5236 *     label: 'View Wishlist',
5237 *     onClick: () => console.log('Wishlist opened')
5238 *   }
5239 * });
5240 * ```
5241 * 
5242 * Attributes:
5243 * - `status` (String) - Defines the notification status (e.g., `success`, `info`, `error`).
5244 * - `role` (String) - Defaults to `"alert"` for accessibility.
5245 * 
5246 * Methods:
5247 * - `setMessage(data, config)`: Sets notification content and displays it.
5248 * - `setNotificationConfig(config)`: Merges user-defined configuration with defaults.
5249 * - `renderUI()`: Updates the UI based on the provided notification data.
5250 * - `autoHide(duration)`: Automatically hides the notification after a specified duration.
5251 * - `showNotification()`: Displays the notification.
5252 * - `hideNotification()`: Hides the notification.
5253 * 
5254 * Events:
5255 * - `click` on `.swym-storefront-layout-notification-action` triggers the provided action callback.
5256 */
5257class SwymStorefrontLayoutNotification extends HTMLElement {
5258  constructor() {
5259    super();
5260    this.timeout = null;
5261    this.notificationData = null;
5262    this.defaultConfig = {
5263      showProgress: false,
5264      showImage: true,
5265      showActionButton: false,
5266      showMessage: true,
5267      showTitle: false
5268    };
5269
5270    this.notificationConfig = this.defaultConfig;
5271  }
5272
5273  connectedCallback() {
5274    this.setAttribute('role', this.getAttribute('role') || 'alert');
5275    this.setAttribute('status', this.getAttribute('status') || 'info');
5276  }
5277
5278  setMessage(data, config = {}) {
5279    // Login nudge is intentionally persistent — suppress transient toasts while it is visible.
5280    // Pass config.priority = 'high' (e.g. errors) to break through and dismiss the nudge.
5281    if (this.hasAttribute('data-nudge-active')) {
5282      if (config.priority !== 'high') return;
5283      this.removeAttribute('data-nudge-active');
5284    }
5285    const {
5286      actionType, message, title, status = 'success', duration = 3000, action, image, product, icon, iconType
5287    } = data;
5288    
5289    this.notificationData = {
5290      actionType, message, status, duration, action, image, product, icon, iconType,
5291      title: title || product?.dt || null
5292    };
5293    
5294    if (SwymStorefrontLayoutContext?.Settings?.EnableStorefrontLayoutNotification) {
5295      this.setAttribute('status', status);
5296      this.setNotificationConfig(config);
5297      this.renderUI();
5298      this.autoHide(duration);
5299    }
5300  }
5301
5302  setNotificationConfig(config) {
5303    this.notificationConfig = { ...this.defaultConfig, ...config };
5304  }
5305
5306  renderUI() {
5307    if (!this.notificationData) return;
5308    
5309    const { message, image, iconType, title, action } = this.notificationData;
5310    const { showProgress, showImage, showActionButton, showMessage, showTitle } = this.notificationConfig;
5311    
5312    this.innerHTML = `
5313      ${showProgress ? '<div class="swym-storefront-layout-notification-progress-bar swym-storefront-notification-animated"></div>' : ''}
5314      <div class="swym-storefront-layout-notification-container">
5315        <div class="swym-storefront-layout-notification-content-container"> 
5316          ${showImage && (image || iconType) ?`<div class="swym-storefront-layout-notification-image-container">
5317            ${ image ? `<img class="swym-storefront-layout-notification-image" src="${image}" alt="Notification Icon">` : ''}
5318            ${iconType ? this.getIconHtml(iconType) : ''}
5319          </div>`:''}
5320          <div class="swym-storefront-layout-notification-content">
5321            ${showTitle && title ? `<div class="swym-storefront-layout-notification-title">${title}</div>` : ''}
5322            ${showMessage && message ? `<div class="swym-storefront-layout-notification-message">${message}</div>` : ''}
5323          </div>
5324        </div>
5325        ${showActionButton && action ? `<button class="swym-storefront-layout-notification-action">${action.label}</button>` : ''}
5326      </div>
5327    `;
5328    
5329    if (action) {
5330      this.querySelector('.swym-storefront-layout-notification-action')?.addEventListener('click', (event) => {
5331        this.hideNotification();
5332        action.onClick?.(event);
5333      });
5334    }
5335  }
5336
5337  getIconHtml(iconType) {
5338    if (iconType === SwymStorefrontLayoutContext?.NotificationIconType?.SuccessIcon) {
5339      return `<svg viewBox="0 0 18 18" fill="none" class="swym-storefront-layout-notification-icon" aria-hidden="true">
5340        <path d="m12.053 5.429-.62.645-3.782 3.98-1.131-1.04-.654-.602-1.152 1.384.661.603 1.745 1.606.613.566 5.553-5.844-1.233-1.298Z" fill="currentColor"></path>
5341      </svg>`;
5342    }
5343    return '';
5344  }
5345
5346  autoHide(duration) {
5347    clearTimeout(this.timeout);
5348    this.showNotification();
5349    this.timeout = setTimeout(() => this.hideNotification(), duration);
5350  }
5351
5352  showNotification() {
5353    this.classList.add('swym-storefront-layout-notification-visible');
5354  }
5355
5356  hideNotification() {
5357    this.classList.remove('swym-storefront-layout-notification-visible');
5358  }
5359
5360  /**
5361   * setLoginNudge — shows a persistent corner notification prompting guest users to
5362   * log in when auto-wishlist has accumulated >= THRESHOLD items this session.
5363   *
5364   * Design choices:
5365   *  - Reuses this element (already bottom-left corner, clear of ATC bars).
5366   *  - No autoHide — stays until the user acts (login or dismiss).
5367   *  - _swat.wrapLogin respects the merchant's configured LoginPath and restores
5368   *    the current page after login via the POSTLOGINRD cookie.
5369   *  - Two thresholds: first nudge at 3 items (no +N), second nudge at 5 items (3 thumbs + +N).
5370   *  - sessionStorage keys are set immediately on show so each threshold fires at most once per session.
5371   */
5372  setLoginNudge() {
5373    const THRESHOLD_FIRST = 3;
5374    const THRESHOLD_SECOND = 5;
5375    const SESSION_KEY_FIRST = 'swym-login-nudge-3';
5376    const SESSION_KEY_SECOND = 'swym-login-nudge-5';
5377    const AUTO_DISMISS_MS = 2 * 60 * 1000;
5378    if (!SwymStorefrontLayoutContext.isLoginNudgeEnabled()) return;
5379    if (SwymStorefrontLayoutContext?.isShopperLoggedIn) return;
5380    if (!SwymStorefrontLayoutContext?.Settings?.EnableStorefrontLayoutNotification) return;
5381    const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig?.() || {};
5382    const SFY_LIST_NAME = 'Saved For Me';
5383    // B1: separate AW vs explicit counts — whichever hits threshold first fires
5384    let awItems, explicitItems;
5385    if (shouldShowMultiple) {
5386      awItems = SwymStorefrontLayoutContext.getSfyList?.()?.listcontents || [];
5387      explicitItems = (SwymStorefrontLayoutContext?.allLists || [])
5388        .filter(list => list.lname !== SFY_LIST_NAME)
5389        .flatMap(list => list.listcontents || []);
5390    } else {
5391      const defaultContents = SwymStorefrontLayoutContext?.DefaultList?.listcontents || [];
5392      awItems = defaultContents.filter(item => item.source === 'auto-wishlist');
5393      explicitItems = defaultContents.filter(item => item.source !== 'auto-wishlist');
5394    }
5395    const awCount = awItems.length;
5396    const explicitCount = explicitItems.length;
5397    // Priority: AW threshold-2 > AW threshold-1 > explicit threshold-2 > explicit threshold-1
5398    // Build priority-ordered candidate list, then walk it skipping session-suppressed entries.
5399    // Shared session keys (swym-login-nudge-3 / -5) are intentional: once a threshold nudge
5400    // fires for either AW or explicit items, that same threshold won't fire again this session
5401    // regardless of item type — preventing double-nudging within a session.
5402    const candidates = [
5403      ...(awCount >= THRESHOLD_SECOND        ? [{ sessionKey: SESSION_KEY_SECOND, showExtras: true,  nudgeItems: awItems,       isAW: true  }] : []),
5404      ...(awCount >= THRESHOLD_FIRST         ? [{ sessionKey: SESSION_KEY_FIRST,  showExtras: fal
5404se, nudgeItems: awItems,       isAW: true  }] : []),
5405      ...(explicitCount >= THRESHOLD_SECOND  ? [{ sessionKey: SESSION_KEY_SECOND, showExtras: true,  nudgeItems: explicitItems, isAW: false }] : []),
5406      ...(explicitCount >= THRESHOLD_FIRST   ? [{ sessionKey: SESSION_KEY_FIRST,  showExtras: false, nudgeItems: explicitItems, isAW: false }] : []),
5407    ];
5408    let chosen = null;
5409    for (const c of candidates) {
5410      try { if (sessionStorage.getItem(c.sessionKey)) continue; } catch (e) {}
5411      chosen = c;
5412      break;
5413    }
5414    if (!chosen) return;
5415    const { sessionKey, showExtras, nudgeItems, isAW } = chosen;
5416    const InstrumentActionCodes = SwymStorefrontLayoutExtensions?.InstrumentActionCodes;
5417    const InstrumentUtmTerms = SwymStorefrontLayoutExtensions?.InstrumentUtmTerms;
5418    const nudgeCodes = isAW
5419      ? (sessionKey === SESSION_KEY_FIRST
5420          ? {
5421              shown: InstrumentActionCodes?.StorefrontLayoutAWNudge1Shown,
5422              loginClicked: InstrumentActionCodes?.StorefrontLayoutAWNudge1LoginClicked,
5423              dismissed: InstrumentActionCodes?.StorefrontLayoutAWNudge1Dismissed,
5424            }
5425          : {
5426              shown: InstrumentActionCodes?.StorefrontLayoutAWNudge2Shown,
5427              loginClicked: InstrumentActionCodes?.StorefrontLayoutAWNudge2LoginClicked,
5428              dismissed: InstrumentActionCodes?.StorefrontLayoutAWNudge2Dismissed,
5429            })
5430      : (sessionKey === SESSION_KEY_FIRST
5431          ? {
5432              shown: InstrumentActionCodes?.StorefrontLayoutExplicitNudge1Shown,
5433              loginClicked: InstrumentActionCodes?.StorefrontLayoutExplicitNudge1LoginClicked,
5434              dismissed: InstrumentActionCodes?.StorefrontLayoutExplicitNudge1Dismissed,
5435            }
5436          : {
5437              shown: InstrumentActionCodes?.StorefrontLayoutExplicitNudge2Shown,
5438              loginClicked: InstrumentActionCodes?.StorefrontLayoutExplicitNudge2LoginClicked,
5439              dismissed: InstrumentActionCodes?.StorefrontLayoutExplicitNudge2Dismissed,
5440            });
5441    const nudgeUtmTerm = isAW
5442      ? InstrumentUtmTerms?.StorefrontLayoutAWLoginNudgeEngagement
5443      : InstrumentUtmTerms?.StorefrontLayoutExplicitLoginNudgeEngagement;
5444    const count = nudgeItems.length;
5445    const strings = SwymStorefrontLayoutContext?.Strings;
5446    const thumbs = nudgeItems.slice(0, THRESHOLD_FIRST); // always first 3
5447    const extraCount = showExtras ? count - THRESHOLD_FIRST : 0;
5448    // XSS: escape item.iu — alt is already escaped with &quot; but src was not
5449    const escAttr = (s) => (s || '').replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
5450    const thumbsHtml = thumbs.map(item => `<img class="swym-aw-nudge-thumb" src="${escAttr(item.iu)}" alt="${escAttr(item.dt)}" loading="lazy" />`).join('');
5451    const extraHtml = extraCount >
5451 0 ? `<span class="swym-aw-nudge-extra">+${extraCount}</span>` : '';
5452    // No hardcoded English fallbacks — strings come from strings/*.js locale files via retailerSettings
5453    const boldMessage = (isAW
5454      ? (strings?.awNudgeMessage || '')
5455      : (strings?.explicitNudgeMessage || '')
5456    ).replace('{count}', count);
5457    const subMessage = strings?.awNudgeMessageSub || '';
5458    const dismissLabel = strings?.awNudgeDismiss || '';
5459    const loginLabel = strings?.awNudgeLoginCTA || '';
5460    clearTimeout(this.timeout);
5461    // Use data-nudge-active instead of status to avoid inheriting the dark info background
5462    this.setAttribute('data-nudge-active', '');
5463    this.removeAttribute('status');
5464    // Mark as shown immediately — each threshold fires at most once per session
5465    try { sessionStorage.setItem(sessionKey, '1'); } catch (e) {}
5466    this.innerHTML = `
5467      <div class="swym-aw-nudge-card">
5468        <div class="swym-aw-nudge-header">
5469          <div class="swym-aw-nudge-thumbs-row">
5470            ${thumbsHtml}${extraHtml}
5471          </div>
5472          <button type="button" class="swym-aw-nudge-dismiss-btn" aria-label="${escAttr(dismissLabel)}"><svg width="10" height="10" viewBox="0 0 10 10" fill="none" aria-hidden="true" focusable="false"><path d="M1 1l8 8M9 1L1 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></button>
5473        </div>
5474        <p class="swym-aw-nudge-message"><strong>${escAttr(boldMessage)}</strong> ${escAttr(subMessage)}</p>
5475        <div class="swym-aw-nudge-login-container"></div>
5476      </div>
5477    `;
5478    const nudgeLoginContainer = this.querySelector('.swym-aw-nudge-login-container');
5479    const loginUrl = SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.Login;
5480    const renderNudgeClassicBtn = () => {
5481      window._swat?.instrumentV3(InstrumentActionCodes?.StorefrontLayoutLoginNudgeShopLoginFallback, { "utm-term": InstrumentUtmTerms?.StorefrontLayoutShopLoginNudgeFallbackEngagement });
5482      nudgeLoginContainer.innerHTML = `<button type="button" class="swym-aw-nudge-login-btn" aria-label="${escAttr(loginLabel)}">${escAttr(loginLabel)}</button>`;
5483      nudgeLoginContainer.querySelector('.swym-aw-nudge-login-btn')?.addEventListener('click', () => {
5484        clearTimeout(this._nudgeAutoDismissTimer);
5485        window._swat?.instrumentV3(nudgeCodes.loginClicked, { 'utm-term': nudgeUtmTerm });
5486        window.location.href = loginUrl || '/account/login';
5487      });
5488    };
5489    window._swat?.initShopLogin(nudgeLoginContainer, {
5490      apiKey: SWYM_SHOP_API_KEY,
5491      showFallbackImmediately: true,
5492      loginUrl: loginUrl,
5493      presentationMode: 'card',
5494      onComplete: (event) => {
5495        if (event.signedIn) {
5496          clearTimeout(this._nudgeAutoDismissTimer);
5497          window._swat?.instrumentV3(InstrumentActionCodes?.StorefrontLayoutLoginNudgeShopLoginSuccess, { "utm-term": InstrumentUtmTerms?.StorefrontLayoutShopLoginNudgeSuccessEngagement });
5498          window.location.reload();
5499        } else {
5500          window._swat?.instrumentV3(InstrumentActionCodes?.StorefrontLayoutLoginNudgeShopLoginDeclined, { "utm-term": InstrumentUtmTerms?.StorefrontLayoutShopLoginNudgeDeclinedEngagement });
5501        }
5502      },
5503      onFallback: renderNudgeClassicBtn,
5504      onShown: () => {
5505        window._swat?.instrumentV3(InstrumentActionCodes?.StorefrontLayoutLoginNudgeShopLoginShown, { "utm-term": InstrumentUtmTerms?.StorefrontLayoutShopLoginNudgeEngagement });
5506      },
5507      // Routed into the existing declined code, not a new one: onError means the SDK
5508      // itself broke before the shopper could make a choice, but at the RAT level this
5509      // and a real decline are both "didn't sign in" outcomes for this surface.
5510      onError: () => {
5511        window._swat?.instrumentV3(InstrumentActionCodes?.StorefrontLayoutLoginNudgeShopLoginDeclined, { "utm-term": InstrumentUtmTerms?.StorefrontLayoutShopLoginNudgeDeclinedEngagement });
5512      }
5513    });
5514    this.querySelector('.swym-aw-nudge-dismiss-btn')?.addEventListener('click', () => {
5515      clearTimeout(this._nudgeAutoDismissTimer);
5516      nudgeLoginContainer.innerHTML = '';
5517      window._swat?.instrumentV3(nudgeCodes.dismissed, { "utm-term": nudgeUtmTerm });
5518      this.removeAttribute('data-nudge-active');
5519      this.hideNotification();
5520    });
5521    this.showNotification();
5522    window._swat?.instrumentV3(nudgeCodes.shown, { "utm-term": nudgeUtmTerm });
5523    // Auto-dismiss after 2 minutes — unblocks setMessage callers after a reasonable window
5524    this._nudgeAutoDismissTimer = setTimeout(() => {
5525      if (this.hasAttribute('data-nudge-active')) {
5526        this.removeAttribute('data-nudge-active');
5527        this.hideNotification();
5528      }
5529    }
5529, AUTO_DISMISS_MS);
5530  }
5531}
5532
5533/**
5534 * SwymStorefrontLayoutLoader Web Component
5535 *
5536 * This custom element is responsible for rendering different types of loading placeholders 
5537 * for the storefront layout. The type of loader is determined by the `loadertype` attribute.
5538 *
5539 * Supported loader types:
5540 * - WishlistListItem: Displays skeleton loaders for wishlist items.
5541 * - CollectionImages: Displays a placeholder for collection images.
5542 * - CarouselListItem: Displays skeleton loaders for carousel items.
5543 * - SpinnerLoader: Displays a rotating spinner for loading states.
5544 *
5545 * The component listens for attribute changes to control visibility (`loading`) 
5546 * and size (`width`, `height`).
5547 *
5548 * Usage:
5549 * <swym-storefront-layout-loader loadertype="WishlistListItem" loading="true"></swym-storefront-layout-loader>
5550 */
5551class SwymStorefrontLayoutLoader extends HTMLElement {
5552  constructor() {
5553    super();
5554
5555    this.renderLoader();
5556
5557  }
5558
5559  renderLoader() {
5560    const loadertype = this.getAttribute('loadertype');
5561    const buttonCta = this.getAttribute('buttonCta');
5562
5563    const loaderListItemHtml = Array.from({ length: 5 })
5564    .map((_, i) => {
5565      return `
5566      <swym-storefront-layout-item class="swym-storefront-layout-loader">
5567        <div class="swym-storefront-layout-grid-item">
5568          <div class="swym-storefront-layout-grid-item-image-container">
5569            <div class="swym-storefront-layout-grid-item-image"></div>
5570          </div>
5571          <div class="swym-storefront-layout-grid-item-content">
5572            <div class="swym-storefront-layout-grid-item-title"></div>
5573            <div class="swym-storefront-layout-grid-item-price-variant">
5574            </div>
5575            <div class="swym-storefront-layout-grid-item-action-container">
5576              ${buttonCta?`<button class="swym-storefront-layout-grid-item-add-to-cart-button" data-action="add-to-cart">${buttonCta}</button>`:''}
5577            </div>
5578          </div>
5579          
5580          <div tabindex="-1" class="swym-storefront-layout-grid-item-option-button">
5581            <svg xmlns="http://www.w3.org/2000/svg" width="3" height="13" viewBox="0 0 3 13" fill="currentcolor">
5582              <circle cx="1.5" cy="1.50014" r="1.5" fill="#B1B7C3"></circle>
5583              <circle cx="1.5" cy="6.50014" r="1.5" fill="#B1B7C3"></circle>
5584              <circle cx="1.5" cy="11.5001" r="1.5" fill="#B1B7C3"></circle>
5585            </svg>
5586          </div>
5587        
5588        </div>
5589      </swym-storefront-layout-item>
5590    `;
5591    })
5592    .join("");
5593
5594    if(loadertype === SwymStorefrontLayoutContext?.LoaderViewType.WishlistListItem){
5595      this.parentElement.innerHTML = `${loaderListItemHtml}`
5596    }else if(loadertype === SwymStorefrontLayoutContext?.LoaderViewType.CollectionImages){
5597      this.parentElement.innerHTML = `
5598        <div class="swym-storefront-layout-loader swym-storefront-layout-collection-list-images"></div>
5599      `
5600    }else if(loadertype === SwymStorefrontLayoutContext?.LoaderViewType.CarouselListItem){
5601      const loaderCollectionListHtml = Array.from({ length: 3 })
5602                .map((_, i) => {
5603                  return `
5604                  <div class="swym-storefront-layout-loader swym-storefront-layout-collection-grid-item">
5605                    <div class="swym-storefront-layout-collection-grid-item-image-container">
5606                      
5607                      <div class="swym-storefront-layout-collection-grid-item-primary-image ">
5608                        <div class="swym-storefront-layout-collection-grid-item-image"></div>
5609                      </div>
5610                    
5611                      <div class="swym-storefront-layout-collection-grid-item-secondary-image ">
5612                      <div class="swym-storefront-layout-collection-grid-item-image"></div>
5613                      </div>
5614                    
5615                      <div class="swym-storefront-layout-collection-grid-item-secondary-image ">
5616                        <div class="swym-storefront-layout-collection-grid-item-image"></div>
5617                      </div>
5618                    
5619                    </div>
5620                    <div class="swym-storefront-layout-collection-grid-item-info-container">
5621                      <div>
5622                        <div class="swym-storefront-layout-collection-grid-item-name"></div>
5623                        <div class="swym-storefront-layout-collection-grid-item-count"></div>
5624                      </div>
5625                      <div class="swym-storefront-layout-collection-grid-item-count"></div>
5626                    </div>
5627                    <div class="swym-storefront-layout-collection-grid-item-option-button">
5628                      <svg xmlns="http://www.w3.org/2000/svg" width="3" height="13" viewBox="0 0 3 13" fill="none">
5629                        <circle cx="1.5" cy="1.50014" r="1.5" fill="#B1B7C3"></circle>
5630                        <circle cx="1.5" cy="6.50014" r="1.5" fill="#B1B7C3"></circle>
5631                        <circle cx="1.5" cy="11.5001" r="1.5" fill="#B1B7C3"></circle>
5632                      </svg>
5633                    </div>
5634                  </div>
5635                `;
5636                })
5637                .join("");
5638
5639              this.parentElement.innerHTML = `${loaderCollectionListHtml}`
5640    }else if(loadertype === SwymStorefrontLayoutContext?.LoaderViewType.SpinnerLoader){
5641      this.innerHTML = `
5642      <div class="swym-storefront-layout-loader-container">
5643        <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
5644          viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
5645            <path fill="currentColor" d="M73,50c0-12.7-10.3-23-23-23S27,37.3,27,50 M30.9,50c0-10.5,8.5-19.1,19.1-19.1S69.1,39.5,69.1,50">
5646              <animateTransform 
5647            <animateTransform 
5648              <animateTransform 
5649                attributeName="transform" 
5650              attributeName="transform" 
5651                attributeName="transform" 
5652                attributeType="XML" 
5653              attributeType="XML" 
5654                attributeType="XML" 
5655                type="rotate"
5656                dur="1s" 
5657              dur="1s" 
5658                dur="1s" 
5659                from="0 50 50"
5660                to="360 50 50" 
5661              to="360 50 50" 
5662                to="360 50 50" 
5663                repeatCount="indefinite" />
5664          </path>
5665        </svg>
5666      </div>
5667      `;
5668    }
5669  }
5670
5671  static get observedAttributes() {
5672    return ['loading', 'width', 'height'];
5673  }
5674
5675  attributeChangedCallback(name, oldValue, newValue) {
5676    if (name === 'loading') {
5677      if (newValue === 'true') {
5678        this.style.display = 'flex';
5679      } else {
5680        this.style.display = 'none';
5681      }
5682    } else if (name == 'width') {
5683      this.style.width = newValue;
5684    } else if (name == 'height') {
5685      this.style.height = newValue;
5686    }
5687  }
5688}
5689
5690/**
5691 * SwymStorefrontLayoutTitle Web Component
5692 *
5693 * This custom element is responsible for rendering the title section of the storefront layout, 
5694 * including the wishlist title and total item count.
5695 *
5696 * Functionality:
5697 * - Displays the wishlist title using `SwymStorefrontLayoutContext?.Strings?.title`.
5698 * - Shows the total count of wishlist items retrieved from `SwymStorefrontLayoutContext?.lists`.
5699 * - Listens for the `WishlistFetched` event and updates the title dynamically when the wishlist is fetched.
5700 *
5701 * Usage:
5702 * <swym-storefront-layout-title></swym-storefront-layout-title>
5703 */
5704class SwymStorefrontLayoutTitle extends HTMLElement {
5705  constructor() {
5706    super();
5707
5708    this.renderTitle();
5709
5710    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.WishlistFetched, () => {
5711      this.renderTitle();
5712    })
5713  }
5714
5715  renderTitle() {
5716    // Exclude the Saved For You list and auto-wishlist items — those are shown in the Saved For You tab
5717    const totalCount = (SwymStorefrontLayoutContext?.allLists || [])
5718      .filter(list => list.lname !== SFY_LIST_NAME)
5719      .reduce((total, list) => total + (list.listcontents || []).filter(item => item.source !== 'auto-wishlist').length, 0);
5720
5721    // Drawer UI Polish: personalize title for single wishlist + logged-in users (drawer only)
5722    const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
5723    const isDrawer = SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer';
5724    const isLoggedIn = SwymStorefrontLayoutContext?.isShopperLoggedIn;
5725    const customerName = swymEscAttr(SwymStorefrontLayoutContext?.SwymCustomerData?.name?.split(' ')?.[0]);
5726    // Strings start as "" (see swymStorefrontLayout.liquid) and only get overwritten when the
5727    // retailer has configured a title, so fall back to keep this heading from rendering empty --
5728    // the drawer/modal points aria-labelledby at it, so an empty heading also leaves the dialog unnamed.
5729    let titleText = SwymStorefrontLayoutContext?.Strings?.title || 'Wishlist';
5730    if (isDrawer && !shouldShowMultiple && isLoggedIn && customerName) {
5731      titleText = (SwymStorefrontLayoutContext?.Strings?.personalizedTitle || "{{name}}'s Wishlist").replace('{{name}}', customerName);
5732    }
5733
5734    const hideCount = isDrawer && !shouldShowMultiple;
5735    const titleIcon = isDrawer ? (SwymStorefrontLayoutExtensions?.getWishlistIconSvg?.('filled') || '') : '';
5736    this.innerHTML = `
5737    <div>
5738      <div class="swym-storefront-layout-title" id="swym-wishlist-title" role="heading" aria-level="2">
5739        ${titleIcon}
5740        ${titleText}
5741      </div>
5742      ${ !hideCount && totalCount?`<div class="swym-storefront-layout-total-list-items-count" aria-live="polite">${totalCount} ${totalCount<=1? SwymStorefrontLayoutContext?.Strings?.item : SwymStorefrontLayoutContext?.Strings?.items }</div>`:''}
5743    </div>
5744    `;
5745    
5746    // Apply heading font styles after rendering the HTML using shared utility
5747    const titleElement = this.querySelector('.swym-storefront-layout-title');
5748    SwymStorefrontLayoutExtensions?.applyHeadingFontStyles(titleElement);
5749  }
5750
5751}
5752
5753/**
5754 * SwymStorefrontLayoutLoggedUser Web Component
5755 *
5756 * This custom element handles user authentication UI within the storefront layout.
5757 *
5758 * Functionality:
5759 * - Checks if a user is logged in using `SwymStorefrontLayoutContext?.isShopperLoggedIn`.
5760 * - Displays a login prompt if the user is not logged in (when `showLogin="true"`).
5761 * - Shows a welcome message with the user's name or email (when `showuser="true"`).
5762 * - Registers a callback in `window.SwymCallbacks` to update UI when Swym state changes.
5763 * - Tracks login button clicks via `SwymStorefrontLayoutExtensions?.InstrumentActionCodes`.
5764 *
5765 * Attributes:
5766 * - `showuser` (boolean): Determines whether to display logged-in user details.
5767 * - `showLogin` (boolean): Determines whether to display the login prompt.
5768 *
5769 * Usage:
5770 * <swym-storefront-layout-logged-user showuser="true" showLogin="true"></swym-storefront-layout-logged-user>
5771 */
5772class SwymStorefrontLayoutLoggedUser extends HTMLElement {
5773  constructor() {
5774    super();
5775    if (!window.SwymCallbacks) {
5776      window.SwymCallbacks = [];
5777    }
5778    window.SwymCallbacks.push(this.swymCallbackFn.bind(this));
5779    // Re-evaluate login prompt visibility after wishlist data is fetched,
5780    // since DefaultList may not be populated when swymCallbackFn first fires
5781    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.WishlistFetched, () => {
5782      this.updateLoginPromptVisibility();
5783    });
5784    // Re-evaluate on drawer/modal open too: initShopLogin() must not run while the
5785    // panel is still hidden, since the Shop SDK's onShown() only checks userFound,
5786    // not whether the ancestor panel is actually visible on screen.
5787    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.Opened, () => {
5788      this.updateLoginPromptVisibility();
5789    });
5790  }
5791
5792  // The drawer/modal panel is rendered into the DOM up front and only ever
5793  // toggles the hide-view class on open/close, so this element can be connected
5794  // (and asked to init Shop Login) long before the shopper opens the panel.
5795  // No drawer/modal ancestor (e.g. as-section) means there's nothing to be
5796  // hidden behind, so treat it as always open.
5797  isAncestorPanelOpen() {
5798    const panel = this.closest('.swym-storefront-layout-drawer');
5799    return !panel || !panel.classList.contains('swym-storefront-layout-hide-view');
5800  }
5801
5802  /**
5803   * Destroy any pending Shop Login instance from a previous render before this component
5804   * re-renders (WishlistFetched can fire updateLoginPromptVisibility again after the initial
5805   * swymCallbackFn render). Without this, a stale instance's async detection can still resolve
5806   * and fire onShown/onComplete against a container this.innerHTML already replaced, logging
5807   * RAT 740/741 for a button the shopper isn't actually looking at anymore.
5808   */
5809  destroyPendingShopLogin() {
5810    if (this._shopLoginHandle) {
5811      this._shopLoginHandle.destroy();
5812      this._shopLoginHandle = null;
5813    }
5814  }
5815
5816  swymCallbackFn(swat) {
5817    const showUser = this.getAttribute('showuser') === 'true';
5818    const showLogin = this.getAttribute('showLogin') === 'true';
5819    let isUserLogged = SwymStorefrontLayoutContext?.isShopperLoggedIn;
5820
5821    if (!isUserLogged && showLogin) {
5822      this.updateLoginPromptVisibility();
5823    } else if (isUserLogged && showUser) {
5824      this.renderUserDetails();
5825    } else if (isUserLogged && showLogin) {
5826      // For drawer + single wishlist: render share button in the login-user container
5827      // (same background, no heading/description text)
5828      this.renderLoggedInShareContainer();
5829    }
5830
5831  }
5832
5833  updateLoginPromptVisibility() {
5834    const showLogin = this.getAttribute('showLogin') === 'true';
5835    if (!showLogin) return;
5836    let isUserLogged = SwymStorefrontLayoutContext?.isShopperLoggedIn;
5837    if (isUserLogged) return;
5838
5839    // Always show login prompt inside collection list view for guests,
5840    // since the collection list overlays the main empty state
5841    const isInsideCollectionList = this.closest('swym-storefront-layout-collection-list');
5842    if (isInsideCollectionList) {
5843      this.renderLoginContainer();
5844      return;
5845    }
5846
5847    // Hide the separate login prompt when wishlist is empty, since
5848    // the guest empty state already includes login CTAs
5849    const wishlistIsEmpty = !SwymStorefrontLayoutContext?.DefaultList?.listcontents?.length;
5850    if (wishlistIsEmpty) {
5851      this.innerHTML = '';
5852      return;
5853    }
5854    this.renderLoginContainer();
5855  }
5856
5857  renderUserDetails() {
5858    this.destroyPendingShopLogin();
5859    let customer = SwymStorefrontLayoutContext?.SwymCustomerData;
5860    this.innerHTML = `
5861      <div class="swym-storefront-layout-logged-user-container"> 
5862        <div class="swym-storefront-layout-logged-user-welcome-message">${SwymStorefrontLayoutContext?.Strings?.loggedUserWelcomeMessage} <span class="swym-storefront-layout-logged-user-name">${customer?.name ? customer?.name : customer?.email}</span></div>
5863      </div>
5864    `
5865  }
5866
5867  renderLoginContainer() {
5868    this.destroyPendingShopLogin();
5869    const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
5870    const layoutType = SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType;
5871    const isDrawer = layoutType === 'as-drawer';
5872    const showInlineButtons = isDrawer && !shouldShowMultiple;
5873    // Button presentation only for separate-page and modal layouts; drawer (including
5874    // multi-wishlist drawer, which falls through to the shared block below) stays card.
5875    const presentationMode = (layoutType === 'as-section' || layoutType === 'as-modal') ? 'button' : 'card';
5876
5877    // Drawer + single wishlist: show inline Login to Save + Share buttons
5878    if (showInlineButtons) {
5879      const shareIcon = SwymStorefrontLayoutExtensions.getShareIconSvg();
5880
5881      const loginToSaveCta = SwymStorefrontLayoutContext?.Strings?.loginToSaveCta || 'Login to Save';
5882      const inlineButtons = `
5883        <div class="swym-storefront-layout-login-actions">
5884          <div class="swym-storefront-layout-shop-login-container"></div>
5885          <button class="swym-storefront-layout-share-footer-share-btn" data-action="share" aria-label="${SwymStorefrontLayoutContext?.Strings?.shareCta || 'Share'}">
5886            ${shareIcon} ${SwymStorefrontLayoutContext?.Strings?.shareCta || 'Share'}
5887          </button>
5888        </div>`;
5889
5890      this.innerHTML = `
5891        <div class="swym-storefront-layout-login-user-container">
5892          <div class="swym-storefront-layout-login-content">
5893            <div class="swym-storefront-layout-login-heading">${SwymStorefrontLayoutContext?.Strings?.loginHeading}</div>
5894            <div class="swym-storefront-layout-login-description">${SwymStorefrontLayoutContext?.Strings?.loginText}</div>
5895          </div>
5896          ${inlineButtons}
5897        </div>
5898      `;
5899      const shopLoginContainer = this.querySelector('.swym-storefront-layout-shop-login-container');
5900      const loginUrl = SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.Login;
5901      const renderDrawerClassicBtn = () => {
5902        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutWishlistUiShopLoginFallback, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutShopLoginWishlistUiFallbackEngagement });
5903        shopLoginContainer.innerHTML = `<button class="swym-storefront-layout-sh
5903are-footer-login-btn" data-action="login" aria-label="${loginToSaveCta}">${loginToSaveCta} <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true" focusable="false"><path fill-rule="evenodd" clip-rule="evenodd" d="M3.49951 10C3.49951 9.58579 3.8353 9.25 4.24951 9.25L13.9391 9.25L11.2192 6.53036C10.9263 6.23748 10.9263 5.7626 11.2192 5.4697C11.512 5.17679 11.9869 5.17676 12.2798 5.46964L16.2802 9.46964C16.4209 9.6103 16.4999 9.80107 16.4999 10C16.4999 10.1989 16.4209 10.3897 16.2802 10.5304L12.2798 14.5304C11.9869 14.8232 11.512 14.8232 11.2192 14.5303C10.9263 14.2374 10.9263 13.7625 11.2192 13.4696L13.9391 10.75L4.24951 10.75C3.8353 10.75 3.49951 10.4142 3.49951 10Z" fill="currentColor"/></svg></button>`;
5904        shopLoginContainer.querySelector('[data-action="login"]')?.addEventListener('click', () => {
5905          window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutWishlistUiClassicLoginClicked, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutShopLoginWishlistUiClassicLoginClickedEngagement });
5906          window.location.href = loginUrl || '/account/login';
5907        });
5908      };
5909      // Don't init the Shop SDK button while the panel is still hidden - onShown()
5910      // only checks userFound, not panel visibility, so it would fire "shown" for
5911      // guests who never actually opened the drawer. Re-runs via the Opened listener.
5912      if (this.isAncestorPanelOpen()) {
5913        this._shopLoginHandle = window._swat?.initShopLogin(shopLoginContainer, {
5914          apiKey: SWYM_SHOP_API_KEY,
5915          loginUrl: loginUrl,
5916          presentationMode: presentationMode,
5917          showFallbackImmediately: true,
5918          onComplete: (event) => {
5919            if (event.signedIn) {
5920              window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutWishlistUiShopLoginSuccess, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutShopLoginWishlistUiSuccessEngagement });
5921              window.location.reload();
5922            } else {
5923              window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutWishlistUiShopLoginDeclined, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutShopLoginWishlistUiDeclinedEngagement });
5924            }
5925          },
5926          onFallback: renderDrawerClassicBtn,
5927          onShown: () => {
5928            window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutWishlistUiShopLoginShown, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutShopLoginWishlistUiEngagement });
5929          },
5930          // Routed into the existing declined code, not a new one: onError means the SDK
5931          // itself broke before the shopper could make a choice, but at the RAT level this
5932          // and a real decline are both "didn't sign in" outcomes for this surface.
5933          onError: () => {
5934            window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutWishlistUiShopLoginDeclined, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutShopLoginWishlistUiDeclinedEngagement });
5935          }
5936        });
5937      }
5938      this.attachShareFooterEvents();
5939      return;
5940    }
5941
5942    // Default: modal/section/multi-wishlist
5943    this.innerHTML = `
5944      <div class="swym-storefront-layout-login-user-container">
5945        <div class="swym-storefront-layout-login-content">
5946          <div class="swym-storefront-layout-login-heading">${SwymStorefrontLayoutContext?.Strings?.loginHeading}</div>
5947          <div class="swym-storefront-layout-login-description">${SwymStorefrontLayoutContext?.Strings?.loginText}</div>
5948        </div>
5949        <div class="swym-storefront-layout-shop-login-container"></div>
5950      </div>
5951    `;
5952    const shopLoginContainer = this.querySelector('.swym-storefront-layout-shop-login-container');
5953    const loginUrl = SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.Login;
5954    const renderModalClassicBtn = () => {
5955      window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutWishlistUiShopLoginFallback, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutShopLoginWishlistUiFallbackEngagement });
5956      shopLoginContainer.innerHTML = `<button class="swym-storefront-layout-login-button">${SwymStorefrontLayoutContext?.Strings?.loginButtonText} <svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" viewBox="0 0 14 9" fill="none"><path d="M13.8536 4.85368C14.0488 4.65841 14.0488 4.34183 13.8536 4.14657L10.6716 0.964589C10.4763 0.769327 10.1597 0.769327 9.96447 0.964589C9.7692 1.15985 9.7692 1.47643 9.96447 1.6717L12.7929 4.50012L9.96447 7.32855C9.7692 7.52381 9.7692 7.84039 9.96447 8.03566C10.1597 8.23092 10.4763 8.23092 10.6716 8.03566L13.8536 4.85368ZM0.5 5.00012L13.5 5.00012L13.5 4.00012L0.5 4.00012L0.5 5.00012Z" fill="currentColor"/></svg></button>`;
5957      shopLoginContainer.querySelector('.swym-storefront-layout-login-button')?.addEventListener('click', () => {
5958        window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutWishlistUiClassicLoginClicked, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutShopLoginWishlistUiClassicLoginClickedEngagement });
5959        window.location.href = loginUrl || '/account/login';
5960      });
5961    };
5962    // Don't init the Shop SDK button while the panel is still hidden - onShown()
5963    // only checks userFound, not panel visibility, so it would fire "shown" for
5964    // guests who never actually opened the modal. Re-runs via the Opened listener.
5965    if (this.isAncestorPanelOpen()) {
5966      this._shopLoginHandle = window._swat?.initShopLogin(shopLoginContainer, {
5967        apiKey: SWYM_SHOP_API_KEY,
5968        loginUrl: loginUrl,
5969        presentationMode: presentationMode,
5970        showFallbackImmediately: true,
5971        onComplete: (event) => {
5972          if (event.signedIn) {
5973            window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutWishlistUiShopLoginSuccess, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutShopLoginWishlistUiSuccessEngagement });
5974            window.location.reload();
5975          } else {
5976            window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutWishlistUiShopLoginDeclined, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutShopLoginWishlistUiDeclinedEngagement });
5977          }
5978        },
5979        onFallback: renderModalClassicBtn,
5980        onShown: () => {
5981          window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutWishlistUiShopLoginShown, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutShopLoginWishlistUiEngagement });
5982        },
5983        // Routed into the existing declined code, not a new one: onError means the SDK
5984        // itself broke before the shopper could make a choice, but at the RAT level this
5985        // and a real decline are both "didn't sign in" outcomes for this surface.
5986        onError: () => {
5987          window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutWishlistUiShopLoginDeclined, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutShopLoginWishlistUiDeclinedEngagement });
5988        }
5989      });
5990    }
5991  }
5992
5993  attachShareFooterEvents() {
5994    const shareBtn = this.querySelector('[data-action="share"]');
5995    const loginBtn = this.querySelector('[data-action="login"]');
5996
5997    shareBtn?.addEventListener('click', (event) => {
5998      event.preventDefault();
5999      event.stopPropagation();
6000      const isLoggedIn = window._swat?.platform?.isLoggedIn();
6001      if (!isLoggedIn) {
6002        const loginUrl = SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.Login || '/account/login';
6003        window.location.href = loginUrl;
6004        return;
6005      }
6006      const activeTab = document.querySelector('.swym-storefront-layout-tab-button.swym-storefront-layout-tab-button-active');
6007      const activeDataView = activeTab?.getAttribute('data-view');
6008      const list = SwymStorefrontLayoutContext?.DefaultList;
6009      const isSflTab = activeDataView === 'tabSavedForLater';
6010      const activeList = isSflTab ? SwymStorefrontLayoutContext?.sflList : list;
6011      window._swat?.evtLayer?.dispatchEvent(new CustomEvent('sw:renderShareWishlistUI', {
6012        detail: {
6013          lid: activeList?.lid || '',
6014          lname: '',
6015          list: activeList,
6016          layoutType: SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType,
6017          senderName: '',
6018          activeDataView
6019        }
6020      }));
6021    });
6022
6023    loginBtn?.addEventListener('click', () => {
6024      const loginUrl = SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.Login || '/account/login';
6025      window.location.href = loginUrl;
6026    });
6027  }
6028
6029  renderLoggedInShareContainer() {
6030    this.destroyPendingShopLogin();
6031    const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
6032    const isDrawer = SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer';
6033    if (!isDrawer || shouldShowMultiple) {
6034      this.innerHTML = '';
6035      return;
6036    }
6037
6038    const selectedView = SwymStorefrontLayoutContext?.SelectedLayoutView;
6039    const isSfyTab = selectedView === SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.SavedForYou;
6040    const shareLabel = isSfyTab
6041      ? (SwymStorefrontLayoutContext?.Strings?.shareThisListCta || 'Share This List')
6042      : (SwymStorefrontLayoutContext?.Strings?.shareCta || 'Share');
6043
6044    const shareIcon = SwymStorefrontLayoutExtensions.getShareIconSvg();
6045
6046        this.innerHTML = `
6047          <div class="swym-storefront-layout-login-user-container">
6048        <div class="swym-storefront-layout-login-actions">
6049          <button class="swym-storefront-layout-share-footer-share-btn swym-storefront-layout-share-footer-share-btn-full" data-action="share" aria-label="${shareLabel}">
6050            ${shareIcon} ${shareLabel}
6051          </button>
6052        </div>
6053      </div>
6054    `;
6055
6056    this.attachShareFooterEvents();
6057
6058    // Listen for tab changes to update share button label.
6059    // Remove any previous listener first to prevent stacking on re-render.
6060    if (this._tabChangeListener) {
6061      document.removeEventListener('click', this._tabChangeListener);
6062    }
6063    this._tabChangeListener = (e) => {
6064      if (e.target?.closest?.('.swym-storefront-layout-tab-button')) {
6065        requestAnimationFrame(() => this.renderLoggedInShareContainer());
6066      }
6067    };
6068    document.addEventListener('click', this._tabChangeListener);
6069  }
6070
6071  disconnectedCallback() {
6072    if (this._tabChangeListener) {
6073      document.removeEventListener('click', this._tabChangeListener);
6074      this._tabChangeListener = null;
6075    }
6076  }
6077
6078}
6079
6080class SwymStorefrontLayoutTabs extends HTMLElement {
6081  constructor() {
6082    super();
6083    this.elements = {};
6084    SwymStorefrontLayoutContext.SelectedLayoutView = SwymStorefrontLayoutContext?.Tabs?.[0] || null;
6085  }
6086
6087  connectedCallback(){
6088    this.initUI();
6089    this._layoutInitHandler = () => {
6090      SwymStorefrontLayoutContext.Tabs = [SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.Wishlist];
6091      if(window._swat.retailerSettings.SFL?.SFLFeatureEnabled){
6092        SwymStorefrontLayoutContext.Tabs.push(SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.SaveForLater);
6093      }
6094      // SavedForYou tab is added/removed dynamically by the WishlistFetched listener below
6095      this.initUI();
6096    };
6097    this._wishlistFetchedHandler = () => {
6098      if (window.SwymEnabledCommonFeatures?.['auto-add-to-wishlist-from-pdp']?.enabled) {
6099        const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
6100        const hasAutoWishlistItems = shouldShowMultiple
6101          ? (SwymStorefrontLayoutContext.getSfyList()?.listcontents?.length > 0)
6102          : (SwymStorefrontLayoutContext?.DefaultList?.listcontents || []).some(item => item.source === 'auto-wishlist');
6103        const savedForYouViewType = SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.SavedForYou;
6104        const currentIdx = SwymStorefrontLayoutContext.Tabs?.indexOf(savedForYouViewType);
6105        if (hasAutoWishlistItems && currentIdx === -1) {
6106          SwymStorefrontLayoutContext.Tabs.splice(1, 0, savedForYouViewType);
6107        } else if (!hasAutoWishlistItems && currentIdx !== -1) {
6108          SwymStorefrontLayoutContext.Tabs.splice(currentIdx, 1);
6109          if (SwymStorefrontLayoutContext.SelectedLayoutView === savedForYouViewType) {
6110            SwymStorefrontLayoutContext.SelectedLayoutView = SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.Wishlist;
6111          }
6112        }
6113      }
6114      // Always re-render to update tab count badges
6115      this.initUI();
6116    };
6117    this._sflFetchedHandler = () => { this.initUI(); };
6118    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.LayoutInitialized, this._layoutInitHandler);
6119    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.WishlistFetched, this._wishlistFetchedHandler);
6120    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.SavedForLaterFetched, this._sflFetchedHandler);
6121  }
6122
6123  disconnectedCallback(){
6124    if (this._layoutInitHandler) {
6125      document.removeEventListener(SwymStorefrontLayoutContext?.CustomEvents?.LayoutInitialized, this._layoutInitHandler);
6126    }
6127    if (this._wishlistFetchedHandler) {
6128      document.removeEventListener(SwymStorefrontLayoutContext?.CustomEvents?.WishlistFetched, this._wishlistFetchedHandler);
6129    }
6130    if (this._sflFetchedHandler) {
6131      document.removeEventListener(SwymStorefrontLayoutContext?.CustomEvents?.SavedForLaterFetched, this._sflFetchedHandler);
6132    }
6133  }
6134
6135  initUI(){
6136    this.renderUI();
6137    this.initElement();
6138
6139    // Always sync content panels visibility with SelectedLayoutView
6140    const selectedView = SwymStorefrontLayoutContext?.SelectedLayoutView || SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.Wishlist;
6141    const tabContent = document.querySelector('swym-storefront-layout-tab-content');
6142    tabContent?.querySelectorAll('.swym-storefront-layout-tab-container').forEach(container => {
6143      const isActive = container.id === selectedView;
6144      container.classList.toggle('swym-storefront-layout-tab-content-active', isActive);
6145      if (isActive) container.removeAttribute('hidden');
6146      else container.setAttribute('hidden', '');
6147
6148      // The panel's tab button only exists when its view is in SwymStorefrontLayoutContext.Tabs
6149      // AND there's more than one tab (renderUI() above renders an empty tablist otherwise).
6150      // Reconcile against the Tabs array itself, not document.getElementById -- this runs
6151      // before SwymStorefrontLayoutTabContent's panels are upgraded into the DOM on first load,
6152      // so a DOM lookup here would always miss.
6153      const tabs = SwymStorefrontLayoutContext?.Tabs;
6154      if (tabs?.length > 1 && tabs.includes(container.id)) {
6155        container.setAttribute('role', 'tabpanel');
6156        container.setAttribute('aria-labelledby', 'tab-' + container.id);
6157        container.removeAttribute('aria-label');
6158        container.setAttribute('tabindex', '0');
6159      } else {
6160        container.removeAttribute('role');
6161        container.removeAttribute('aria-labelledby');
6162        container.setAttribute('aria-label', SwymStorefrontLayoutContext?.Strings?.[container.id] || '');
6163        container.removeAttribute('tabindex');
6164      }
6165    });
6166
6167    if (this.elements.currentSelectedTab) {
6168      this.setTabSelection(this.elements.currentSelectedTab);
6169      this.attachEvents();
6170    }
6171  }
6172
6173  renderUI() {
6174    let tabs = SwymStorefrontLayoutContext?.Tabs;
6175    if (!tabs?.length || tabs?.length<=1){
6176      this.innerHTML = '';
6177      return;
6178    }
6179    
6180    this.innerHTML = `
6181      <div class="swym-storefront-layout-tabs-view">
6182        <div class="swym-storefront-layout-tabs" role="tablist" aria-label="Wishlist views">
6183          ${tabs.map((tab, index)=>{
6184            const isActive = tab===SwymStorefrontLayoutContext?.SelectedLayoutView;
6185            const isDrawerLayout = SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer';
6186            const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
6187            const tabCount = isDrawerLayout ? this.getTabItemCount(tab) : 0;
6188            const hideCount = !isDrawerLayout || shouldShowMultiple || !isActive;
6189            const countBadge = isDrawerLayout ? `<span class="swym-storefront-layout-tab-count${hideCount ? ' swym-storefront-layout-tab-count-hidden' : ''}">${tabCount}</span>` : '';
6190            return `<button class="swym-storefront-layout-tab-button ${isActive?'swym-storefront-layout-tab-button-active':''}" data-view="${tab}" role="tab" aria-selected="${isActive}" aria-controls="${tab}" tabindex="${isActive ? '0' : '-1'}" id="tab-${tab}">${SwymStorefrontLayoutContext?.Strings?.[tab]}${countBadge}</button>`
6191          }).join('')}
6192        </div>
6193        <div class="swym-storefront-layout-tab-indicator"></div>
6194      </div>
6195    `;
6196  }
6197
6198  getTabItemCount(tab) {
6199    if (tab === SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.Wishlist) {
6200      const allItems = SwymStorefrontLayoutContext?.DefaultList?.listcontents || [];
6201      const hasSfyTab = SwymStorefrontLayoutContext?.Tabs?.includes(SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.SavedForYou);
6202      return hasSfyTab ? allItems.filter(item => item.source !== 'auto-wishlist').length : allItems.length;
6203    }
6204    if (tab === SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.SavedForYou) {
6205      return SwymStorefrontLayoutContext?.savedForYouItems?.length || 0;
6206    }
6207    if (tab === SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.SaveForLater) {
6208      return SwymStorefrontLayoutContext?.sflListItems?.length || 0;
6209    }
6210    return 0;
6211  }
6212
6213  initElement(){
6214    this.elements = {
6215      tabs: this.querySelectorAll('.swym-storefront-layout-tab-button'),
6216      tabIndicator: this.querySelector('.swym-storefront-layout-tab-indicator'),
6217      currentSelectedTab: this.querySelector('.swym-storefront-layout-tab-button-active'),
6218      tabContent: document.querySelector('swym-storefront-layout-tab-content')
6219    };
6220  }
6221
6222  setTabSelection(selectedTab){
6223    if (!selectedTab) return;
6224
6225    const selectedView = selectedTab.getAttribute('data-view');
6226    if (!selectedView) return;
6227
6228    SwymStorefrontLayoutContext.SelectedLayoutView = selectedView || SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.Wishlist;
6229
6230    this.elements.tabContainers = this.elements.tabContent?.querySelectorAll('.swym-storefront-layout-tab-container');
6231
6232    // Update ARIA attributes and tabindex for accessibility
6233    this.elements.tabs?.forEach(tab => {
6234      const isSelected = tab === selectedTab;
6235      tab.classList.toggle('swym-storefront-layout-tab-button-active', isSelected);
6236      tab.setAttribute('aria-selected', isSelected);
6237      tab.setAttribute('tabindex', isSelected ? '0' : '-1');
6238      // Toggle tab count visibility (opacity) for drawer layout — always hidden for multi-wishlist
6239      const countBadge = tab.querySelector('.swym-storefront-layout-tab-count');
6240      if (countBadge) {
6241        const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
6242        countBadge.classList.toggle('swym-storefront-layout-tab-count-hidden', shouldShowMultiple || !isSelected);
6243      }
6244    });
6245    
6246    this.elements.tabContainers?.forEach(tabContainer => {
6247      const isActive = tabContainer.id === selectedView;
6248      tabContainer.classList.toggle('swym-storefront-layout-tab-content-active', isActive);
6249      // Manage hidden attribute for better accessibility
6250      if (isActive) {
6251        tabContainer.removeAttribute('hidden');
6252      } else {
6253        tabContainer.setAttribute('hidden', '');
6254      }
6255    });
6256    
6257    this.setTabIndicator();
6258  }
6259
6260  setTabIndicator(){
6261    let selectedTab = this.elements.currentSelectedTab;
6262    if(selectedTab){
6263    // Wait for next frame to ensure layout is complete
6264      requestAnimationFrame(() => {
6265        const tabCenter = selectedTab.offsetLeft + selectedTab.offsetWidth / 2;
6266        this.elements.tabIndicator?.style.setProperty(
6267          'left',
6268          `${tabCenter - (this.elements.tabIndicator.offsetWidth ?? 0) / 2}px`
6269        );
6270      })
6271    }
6272  }
6273  
6274  attachEvents() {
6275    this.elements.tabs?.forEach((tab) => {
6276      // Click event handler
6277      tab.addEventListener('click', (event) => {
6278        const clickedTab = event.target?.closest('[role="tab"]');
6279        if (!clickedTab) return;
6280        this.elements.currentSelectedTab = clickedTab;
6281        this.setTabSelection(clickedTab);
6282        if (clickedTab.getAttribute('data-view') === SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.SavedForYou) {
6283          window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutSFYTabViewed, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
6284        }
6285      });
6286      
6287      // Keyboard navigation for accessibility
6288      tab.addEventListener('keydown', (event) => {
6289        // Validate event target is a tab
6290        const eventTarget = event.target?.closest('[role="tab"]');
6291        if (!eventTarget) return;
6292
6293        const tabArray = Array.from(this.elements.tabs || []);
6294        if (tabArray.length === 0) return;
6295
6296        const currentIndex = tabArray.indexOf(eventTarget);
6297        if (currentIndex === -1) return; // Target not in tabs array
6298        
6299        let targetTab = null;
6300        
6301        switch(event.key) {
6302          case 'ArrowRight':
6303            event.preventDefault();
6304            targetTab = tabArray[(currentIndex + 1) % tabArray.length];
6305            break;
6306          case 'ArrowLeft':
6307            event.preventDefault();
6308            targetTab = tabArray[(currentIndex - 1 + tabArray.length) % tabArray.length];
6309            break;
6310          case 'Home':
6311            event.preventDefault();
6312            targetTab = tabArray[0];
6313            break;
6314          case 'End':
6315            event.preventDefault();
6316            targetTab = tabArray[tabArray.length - 1];
6317            break;
6318          case 'Enter':
6319          case ' ':
6320            event.preventDefault();
6321            this.elements.currentSelectedTab = eventTarget;
6322            this.setTabSelection(eventTarget);
6323            if (eventTarget.getAttribute('data-view') === SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.SavedForYou) {
6324              window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutSFYTabViewed, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
6325            }
6326            return;
6327          default:
6328            return;
6329        }
6330        
6331        if (targetTab) {
6332          this.elements.currentSelectedTab = targetTab;
6333          this.setTabSelection(targetTab);
6334          targetTab.focus();
6335        }
6336      });
6337    });
6338    
6339    // Debounced resize handler to reposition indicator
6340    if (window.addEventListener && SwymStorefrontLayoutContext?.swat?.utils?.debounce) {
6341      window.addEventListener('resize', SwymStorefrontLayoutContext.swat.utils.debounce(() => {
6342        this.setTabIndicator();
6343      }, 200));
6344    }
6345  }
6346}
6347
6348class SwymStorefrontLayoutTabContent extends HTMLElement {
6349  constructor() {
6350    super();
6351    this.renderUI();
6352  }
6353
6354  renderUI() {
6355    // Tabs is always populated by module load (defaults to [Wishlist]), so this reflects the
6356    // real tab-button set even though it runs before SwymStorefrontLayoutTabs has rendered any
6357    // buttons -- unlike a DOM lookup for the button, which would race against that render.
6358    // A tab button only exists when there's more than one tab (SwymStorefrontLayoutTabs.renderUI()
6359    // renders an empty tablist otherwise).
6360    const ariaAttrs = (viewType) => (SwymStorefrontLayoutContext?.Tabs?.length > 1 && SwymStorefrontLayoutContext.Tabs.includes(viewType))
6361      ? `role="tabpanel" aria-labelledby="tab-${viewType}" tabindex="0"`
6362      : `aria-label="${SwymStorefrontLayoutContext?.Strings?.[viewType] || ''}"`;
6363    this.innerHTML = `
6364      <swym-storefront-layout-wishlist-container
6365        id="${SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.Wishlist}"
6366        class="swym-storefront-layout-tab-container swym-storefront-layout-tab-content-active"
6367        ${ariaAttrs(SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.Wishlist)}
6368      ></swym-storefront-layout-wishlist-container>
6369      <swym-storefront-layout-sfl-container
6370        id="${SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.SaveForLater}"
6371        class="swym-storefront-layout-tab-container"
6372        ${ariaAttrs(SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.SaveForLater)}
6373        hidden
6374      ></swym-storefront-layout-sfl-container>
6375      <swym-storefront-layout-saved-for-you-container
6376        id="${SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.SavedForYou}"
6377        class="swym-storefront-layout-tab-container"
6378        ${ariaAttrs(SwymStorefrontLayoutContext?.StorefrontLayoutViewType?.SavedForYou)}
6379        hidden
6380      ></swym-storefront-layout-saved-for-you-container>
6381
6382    `;
6383  }
6384}
6385
6386
6387class SwymStorefrontLayoutWishlistContainer extends HTMLElement {
6388  constructor() {
6389    super();
6390    this.wishlist = null;
6391    this.collections = [];
6392    this.elements = {};
6393    this.initUI();
6394    document.addEventListener(
6395      SwymStorefrontLayoutContext?.CustomEvents?.LayoutInitialized,
6396      () => {
6397        this.attachSwymEventListeners(SwymStorefrontLayoutContext?.swat);
6398      }
6399    );
6400    document.addEventListener(
6401      SwymStorefrontLayoutContext?.CustomEvents?.AsyncApisInitialized,
6402      () => {
6403        SwymStorefrontLayoutExtensions?.refreshWishList();
6404      }
6405    );
6406    this.attachEventListner();
6407  }
6408
6409  initUI() {
6410    this.renderUI();
6411    this.initElement();
6412  }
6413
6414  renderUI() {
6415    const isLoggedIn = window._swat?.platform?.isLoggedIn();
6416    
6417    // Always render carousel element - it will show/hide itself based on data
6418    // We can't conditionally render here because allLists data isn't available yet
6419    this.innerHTML = `
6420      <div class="swym-storefront-layout-header">
6421        <swym-storefront-layout-title></swym-storefront-layout-title>
6422        ${isLoggedIn ? 
6423          `<button class="swym-storefront-layout-collection-option-button swym-single-share-wishlist-btn swym-hidden" tabindex="0" aria-haspopup="dialog" aria-expanded="false" aria-label="Action menu options">
6424          <svg xmlns="http://www.w3.org/2000/svg" width="3" height="13" viewBox="0 0 3 13" fill="currentcolor">
6425            <circle cx="1.5" cy="1.50014" r="1.5" fill="currentColor"></circle>
6426            <circle cx="1.5" cy="6.50014" r="1.5" fill="currentColor"></circle>
6427            <circle cx="1.5" cy="11.5001" r="1.5" fill="currentColor"></circle>
6428          </svg>
6429        </button>` : ""}
6430      </div>
6431      <div class="swym-storefront-layout-body" role="region" aria-label="Wishlist Content Section">
6432        <swym-storefront-layout-collection-carousel></swym-storefront-layout-collection-carousel>
6433        <swym-storefront-layout-default-wishlist></swym-storefront-layout-default-wishlist>
6434        <swym-storefront-layout-collection-list id="swym-storefront-layout-collection-list" role="list" aria-label="Your Wishlist Collections"></swym-storefront-layout-collection-list>
6435     </div>
6436    `;
6437  }
6438
6439  initElement() {
6440    this.elements = {
6441      wishlistListComponent: this.querySelector("swym-storefront-layout-default-wishlist"),
6442      collectionsCarouselComponent: this.querySelector("swym-storefront-layout-collection-carousel"),
6443      collectionsListComponent: this.querySelector("swym-storefront-layout-collection-list"),
6444      swymListActionButton: this.querySelector(".swym-storefront-layout-collection-option-button"),
6445    };
6446  }
6447
6448    attachEventListner(){
6449    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.WishlistFetched, () => {
6450      this.wishlist = SwymStorefrontLayoutContext?.DefaultList || null;
6451      // Use allLists as the source for collections, excluding default list and the SFY list
6452      // (SFY list is shown in its own dedicated tab, not in the collections carousel)
6453      const allLists = SwymStorefrontLayoutContext?.allLists || SwymStorefrontLayoutContext?.collections || [];
6454      const defaultListId = SwymStorefrontLayoutContext?.DefaultList?.lid;
6455      const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
6456      const sfyListId = shouldShowMultiple ? SwymStorefrontLayoutContext.getSfyList()?.lid : null;
6457      this.collections = allLists.filter(list => list.lid !== defaultListId && list.lid !== sfyListId);
6458      this.renderWishlistAndCollections();
6459    })
6460    this.elements.swymListActionButton?.addEventListener('click', (event) => {
6461      event.preventDefault();
6462      event.stopPropagation();
6463      if(SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.isTooltipOpen && SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.currentTarget === event.target){
6464        SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.closeTooltip();
6465        event.target.setAttribute('aria-expanded', 'false');
6466      }else{
6467        SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.setData({
6468          listId: "",
6469          list: this.wishlist,
6470          collections: this.collections,
6471          actionType: SwymStorefrontLayoutContext?.ActionTypes.ShareSingleWishlist
6472        });
6473        SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.showOnTarget(event.target);
6474        event.target.setAttribute('aria-expanded', 'true');
6475      }
6476    });
6477
6478  }
6479  attachSwymEventListeners(swat) {
6480    swat?.evtLayer?.addEventListener(
6481      swat?.JSEvents?.storeAddedToCart,
6482      (data) => {
6483        swat.utils.debounce(() => {
6484          this.renderWishlistAndCollections();
6485        }, 1000)();
6486      }
6487    );
6488
6489    swat?.evtLayer?.addEventListener(
6490      swat?.JSEvents?.storeRemovedFromCart,
6491      (data) => {
6492        swat.utils.debounce(() => {
6493          this.renderWishlistAndCollections();
6494        }, 1000)();
6495      }
6496    );
6497  }
6498
6499
6500  renderWishlistAndCollections() {
6501    // Use centralized helper to determine multi-wishlist behavior
6502    const { shouldShowMultiple, canCreateLists } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
6503    // Check for auto-wishlist items directly — don't rely on Tabs array state since
6504    // the Tabs listener and this listener fire in undefined order on the same event.
6505    const autoWishlistEnabled = window.SwymEnabledCommonFeatures?.['auto-add-to-wishlist-from-pdp']?.enabled;
6506    // Multi-list: SFY items live in the dedicated "Saved For Me" list, not in DefaultList
6507    const hasSfyItems = autoWishlistEnabled && (
6508      shouldShowMultiple
6509        ? (SwymStorefrontLayoutContext.getSfyList()?.listcontents?.length > 0)
6510        : (SwymStorefrontLayoutContext?.DefaultList?.listcontents || []).some(item => item.source === 'auto-wishlist')
6511    );
6512
6513    const isDrawer = SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer';
6514    if(this.collections?.length > 0 || (this.wishlist && this.wishlist?.listcontents?.length > 0)) {
6515      // Hide the 3-dot menu in drawer + single wishlist — share is handled by the footer button
6516      if (!(isDrawer && !shouldShowMultiple)) {
6517        this.querySelector(".swym-storefront-layout-collection-option-button")?.classList.remove('swym-hidden');
6518      }
6519    }
6520    
6521    if ( this.wishlist || this.collections) {
6522      if(window.location.hash.startsWith(SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.CollectionList)){
6523        const collectionId = window.location.hash.slice(SwymStorefrontLayoutContext?.StorefrontLayoutUrls?.CollectionList.length);
6524        if(this.elements.collectionsListComponent && this.collections){
6525          let selectedCollection = this.collections?.find((collection)=> collection.lid === collectionId);
6526          this.elements.collectionsListComponent.setData({ 
6527            list: selectedCollection, 
6528            collections: this.collections,
6529            canCreateLists: canCreateLists,
6530            shouldShowMultiple: shouldShowMultiple
6531          })
6532        }
6533      }
6534
6535      // Filter auto-wishlist items from the Wishlist tab — they belong in the SFY tab only.
6536      // In single-list mode, both share DefaultList. In multi-list mode, this is a safety net
6537      // in case DefaultList somehow contains auto-wishlist items (e.g. SFY list was lists[0]).
6538      const wishlistForDisplay = hasSfyItems
6539        ? { ...this.wishlist, listcontents: (this.wishlist?.listcontents || []).filter(item => item.source !== 'auto-wishlist') }
6540        : this.wishlist;
6541
6542      this.elements.wishlistListComponent?.setData({ 
6543        wishlist: wishlistForDisplay, 
6544        collections: this.collections,
6545        canCreateLists: canCreateLists,
6546        shouldShowMultiple: shouldShowMultiple
6547      });
6548
6549      // Always call setData on carousel so it can manage its own visibility
6550      if (this.elements.collectionsCarouselComponent) {
6551        this.elements.collectionsCarouselComponent?.setData({ 
6552          collections: shouldShowMultiple ? this.collections : [],
6553          canCreateLists: canCreateLists,
6554          shouldShowMultiple: shouldShowMultiple
6555        });
6556      }
6557    }
6558  }
6559}
6560
6561class SwymStorefrontLayoutSaveForLaterContainer extends HTMLElement{
6562  constructor(){
6563    super();
6564    this.sflData = null;
6565    this.collections = [];
6566    this.elements = {};
6567
6568    this.initUI();
6569
6570    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.AsyncApisInitialized, (
6570) => {
6571      if(window._swat?.retailerSettings.SFL?.SFLFeatureEnabled){
6572        this.initSfl();
6573      }
6574    })
6575
6576    this.attachEventListner();
6577  }
6578
6579  initUI(){
6580    this.renderUI();
6581    this.initElement();
6582  }
6583
6584  renderUI(){
6585    const isLoggedIn = window?._swat?.platform?.isLoggedIn();
6586    const isDrawer = SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer';
6587    const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
6588    const hideOptionButton = isDrawer && !shouldShowMultiple;
6589    this.innerHTML = `
6590      <div class="swym-storefront-layout-header">
6591        <swym-storefront-layout-sfl-title></swym-storefront-layout-sfl-title>
6592        ${isLoggedIn && !hideOptionButton ?
6593        `<div class="swym-storefront-layout-collection-option-button swym-hidden">
6594          <svg xmlns="http://www.w3.org/2000/svg" width="3" height="13" viewBox="0 0 3 13" fill="currentcolor">
6595            <circle cx="1.5" cy="1.50014" r="1.5" fill="currentColor"></circle>
6596            <circle cx="1.5" cy="6.50014" r="1.5" fill="currentColor"></circle>
6597            <circle cx="1.5" cy="11.5001" r="1.5" fill="currentColor"></circle>
6598          </svg>
6599        </div>` : ""
6600        }
6601      </div>
6602      <div class="swym-storefront-layout-body">
6603        <swym-storefront-layout-sfl-list></swym-storefront-layout-sfl-list>
6604      </div>
6605    `;
6606  }
6607
6608  initElement(){
6609    this.elements = {
6610      sflList: this.querySelector('swym-storefront-layout-sfl-list'),
6611      swymListActionButton: this.querySelector('.swym-storefront-layout-collection-option-button')
6612    }
6613  }
6614
6615  async initSfl(){
6616    if(!SwymStorefrontLayoutContext?.sflListId){
6617      await SwymStorefrontLayoutAPI?.SwymSFLAsyncApis?.updateSflList();
6618      window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutSFLInitialized, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
6619    }
6620
6621    if(!SwymStorefrontLayoutContext?.sflList){
6622      SwymStorefrontLayoutExtensions?.refreshSFLList();
6623    }
6624    if(SwymStorefrontLayoutContext?.sflList) {
6625      const isDrawer = SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer';
6626      const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
6627      // Hide the 3-dot menu in drawer + single wishlist — share is handled by the footer button
6628      if (!(isDrawer && !shouldShowMultiple)) {
6629        this.querySelector(".swym-storefront-layout-collection-option-button")?.classList.remove("swym-hidden");
6630      }
6631    } 
6632  }
6633  attachEventListner(){
6634    this.elements.swymListActionButton?.addEventListener('click', (event) => {
6635      event.preventDefault();
6636      event.stopPropagation();
6637      if(SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.isTooltipOpen && SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.currentTarget === event.target){
6638        SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.closeTooltip();
6639      }else{
6640        SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.setData({
6641          listId: SwymStorefrontLayoutContext?.sflListId,
6642          list: "",
6643          collections: "",
6644          actionType: SwymStorefrontLayoutContext?.ActionTypes.ShareSingleWishlist
6645        });
6646
6647        SwymStorefrontLayoutExtensions?.SwymStorefrontLayoutActionTooltip?.showOnTarget(event.target);
6648      }
6649    });
6650
6651  }
6652}
6653
6654class SwymStorefrontLayoutSaveForLaterTitle extends HTMLElement {
6655  constructor() {
6656    super();
6657
6658    this.renderTitle();
6659
6660    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.SavedForLaterFetched, () => {
6661      this.renderTitle();
6662    })
6663  }
6664
6665  renderTitle() {
6666    const totalCount = SwymStorefrontLayoutContext?.sflListItems?.length || 0;
6667    this.innerHTML = `
6668    <div>
6669      <div class="swym-storefront-layout-title" id="swym-sfl-title" role="heading" aria-level="2">
6670        ${SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer' ? (SwymStorefrontLayoutExtensions?.getWishlistIconSvg?.('filled') || '') : ''}
6671        ${SwymStorefrontLayoutContext?.Strings?.savedForLaterTitle}
6672      </div>
6673      ${ totalCount?`<div class="swym-storefront-layout-total-list-items-count" aria-live="polite">${totalCount} ${totalCount<=1? SwymStorefrontLayoutContext?.Strings?.item : SwymStorefrontLayoutContext?.Strings?.items }</div>`:''}
6674    </div>
6675    `;
6676    
6677    // Apply heading font styles after rendering the HTML using shared utility
6678    const titleElement = this.querySelector('.swym-storefront-layout-title');
6679    SwymStorefrontLayoutExtensions?.applyHeadingFontStyles(titleElement);
6680  }
6681
6682}
6683class SwymStorefrontLayoutSaveForLaterList extends HTMLElement {
6684  constructor() {
6685    super();
6686    this.renderUI();
6687    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.SavedForLaterFetched, () => {
6688      this.renderSFL();
6689    })
6690  }
6691
6692  renderUI() {
6693    let sflData = SwymStorefrontLayoutContext?.sflData || null;
6694    this.innerHTML = `
6695      <div id="swym-storefront-layout-sfl-items-container" class="swym-storefront-layout-items-container swym-storefront-layout-sfl-list-container">
6696        ${sflData===null?`<swym-storefront-layout-loader loading="true" loadertype="${SwymStorefrontLayoutContext?.LoaderViewType?.WishlistListItem}" buttonCta="${SwymStorefrontLayoutContext?.Strings?.moveToCartCta}" height="100px"></swym-storefront-layout-loader>`:''}
6697      </div>
6698    `
6699    this.initElements();
6700  }
6701
6702  initElements(){
6703    this.elements = {
6704      title: this.querySelector('.swym-storefront-layout-sfl-list-title'),
6705      itemsContainer: this.querySelector('#swym-storefront-layout-sfl-items-container')
6706    }
6707  }
6708
6709
6710  async renderSFL() {
6711    const slfListItems =  SwymStorefrontLayoutContext?.sflListItems;
6712    if (slfListItems?.length && this.elements.itemsContainer) {
6713      
6714      const fragment = document.createDocumentFragment();
6715
6716      slfListItems.forEach((item) => {
6717        const sflItem = document.createElement('template');
6718        sflItem.innerHTML = `<swym-storefront-layout-item id="swym-storefront-layout-sfl-item-${item.empi}-${item.epi}" class="swym-storefront-layout-sfl-item"></swym-storefront-layout-item>`;
6719        fragment.appendChild(sflItem.content);
6720      });
6721      
6722      this.elements.itemsContainer.innerHTML = '';
6723      this.elements.itemsContainer.appendChild(fragment);
6724
6725      slfListItems.forEach(async (item) => {
6726        let sflItemElement = document.querySelector(`#swym-storefront-layout-sfl-item-${item.empi}-${item.epi}`);
6727        sflItemElement?.setData({
6728          item,
6729          listItemType: SwymStorefrontLayoutContext?.ListItemType?.SaveForLaterItem,
6730          sflList: SwymStorefrontLayoutContext?.sflData?.list
6731        })
6732      });
6733      this.elements.itemsContainer.classList.remove('swym-storefront-layout-items-has-empty');
6734      window._swat?.instrumentV3(SwymStorefrontLayoutExtensions?.InstrumentActionCodes?.StorefrontLayoutSFLItemsRendered, { "utm-term": SwymStorefrontLayoutExtensions?.InstrumentUtmTerms?.StorefrontLayoutUiEngagement });
6735    }else{
6736      const isLoggedIn = SwymStorefrontLayoutContext?.isShopperLoggedIn;
6737      const { shouldShowMultiple: sflShouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
6738      const cartUrl = (window.Shopify?.routes?.root || '/').replace(/\/$/, '') + '/cart';
6739      const accountUrl = (window.Shopify?.routes?.root || '/').replace(/\/$/, '') + '/account';
6740
6741      if (sflShouldShowMultiple) {
6742        // Multi wishlist – old simple SFL empty state
6743        this.elements.itemsContainer.innerHTML = `
6744          <div class="swym-storefront-layout-empty-container">
6745            <div class="swym-storefront-layout-empty-sfl-container">
6746              <div class="swym-storefront-layout-empty-sfl-content">
6747                <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="75" height="75" viewBox="0 0 75 75" fill="none">
6748                <rect width="75" height="75" fill="url(#pattern0_1065_979)" fill-opacity="0.8"/>
6749                <defs>
6750                <pattern id="pattern0_1065_979" patternContentUnits="objectBoundingBox" width="1" height="1">
6751                <use xlink:href="#image0_1065_979" transform="scale(0.00195312)"/>
6752                </pattern>
6753                <image id="image0_1065_979" width="512" height="512" preserveAspectRatio="none" xlink:href="data:image/png;base64,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"/>
6754                </defs>
6755              </svg>
6756                <div class="swym-storefront-layout-empty-sfl-title">${SwymStorefrontLayoutContext?.Strings?.emptySavedForLaterTitle}</div>
6757                <div class="swym-storefront-layout-empty-sfl-description">${SwymStorefrontLayoutContext?.Strings?.emptySavedForLaterDescription}</div>
6758                <a class="swym-storefront-layout-empty-sfl-view-cart-button" href="${(window.Shopify?.routes?.root || '/').replace(/\/$/, '') + '/cart'}">${SwymStorefrontLayoutContext?.Strings?.viewCartCta}</a>
6759              </div>
6760            </div>
6761          </div>
6762        `;
6763        this.elements.itemsContainer.classList.add('swym-storefront-layout-items-has-empty');
6764        return;
6765      }
6766
6767      let sflNoticeText = '';
6768
6769      if (isLoggedIn) {
6770        sflNoticeText = SwymStorefrontLayoutContext?.Strings?.emptySflLoggedInNotice || '';
6771        this.elements.itemsContainer.innerHTML = `
6772          <div class="swym-storefront-layout-empty-container swym-storefront-layout-empty-state-sfl swym-storefront-layout-empty-state-sfl-logged">
6773            <div class="swym-storefront-layout-empty-wishlist-container">
6774              <div class="swym-storefront-layout-empty-wishlist-content">
6775                <div class="swym-storefront-layout-empty-state-icon">
6776                  <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="none">
6777                    <circle cx="24" cy="24" r="24" fill="#F5F5F5"/>
6778                    <path d="M20 18H18C17.4696 18 16.9609 18.2107 16.5858 18.5858C16.2107 18.9609 16 19.4696 16 20V32C16 32.5304 16.2107 33.0391 16.5858 33.4142C16.9609 33.7893 17.4696 34 18 34H30C30.5304 34 31.0391 33.7893 31.4142 33.4142C31.7893 33.0391 32 32.5304 32 32V20C32 19.4696 31.7893 18.9609 31.4142 18.5858C31.0391 18.2107 30.5304 18 30 18H28M20 18V16C20 15.4696 20.2107 14.9609 20.5858 14.5858C20.9609 14.2107 21.4696 14 22 14H26C26.5304 14 27.0391 14.2107 27.4142 14.5858C27.7893 14.9609 28 15.4696 28 16V18M20 18H28" stroke="#9B9B9B" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
6779                    <path d="M20 24H28M20 28H25" stroke="#9B9B9B" stroke-width="1.5" stroke-linecap="round"/>
6780                  </svg>
6781                  <span class="swym-storefront-layout-empty-state-badge">
6782                    <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none">
6783                      <circle cx="7" cy="7" r="7" fill="#4CAF77"/>
6784                      <path d="M4 7L6 9L10 5" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
6785                    </svg>
6786                  </span>
6787                </div>
6788                <div class="swym-storefront-layout-empty-wishlist-title">${SwymStorefrontLayoutContext?.Strings?.emptySflTitle || ''}</div>
6789                <div class="swym-storefront-layout-empty-wishlist-description">${SwymStorefrontLayoutContext?.Strings?.emptySflDescription || ''}</div>
6790                <div class="swym-storefront-layout-empty-sfl-steps-card">
6791                  <div class="swym-storefront-layout-empty-sfl-step">
6792                    <div class="swym-storefront-layout-empty-sfl-step-icon swym-storefront-layout-empty-sfl-step-icon--green">
6793                      <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none">
6794                        <path d="M1.5 1.5H3.5L4.8 8.8C4.9 9.3 5.3 9.6 5.8 9.6H13.2C13.7 9.6 14.1 9.2 14.2 8.7L15.5 4H4" stroke="#4CAF77" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
6795                        <circle cx="6.5" cy="12.5" r="1.3" stroke="#4CAF77" stroke-width="1.3"/>
6796                        <circle cx="13" cy="12.5" r="1.3" stroke="#4CAF77" stroke-width="1.3"/>
6797                      </svg>
6798                    </div>
6799                    <div class="swym-storefront-layout-empty-sfl-step-content">
6800                      <div class="swym-storefront-layout-empty-sfl-step-title">${SwymStorefrontLayoutContext?.Strings?.emptySflStep1Title || ''}</div>
6801                      <div class="swym-storefront-layout-empty-sfl-step-desc">${SwymStorefrontLayoutContext?.Strings?.emptySflStep1Description || ''}</div>
6802                    </div>
6803                  </div>
6804                  <div class="swym-storefront-layout-empty-sfl-step-divider"></div>
6805                  <div class="swym-storefront-layout-empty-sfl-step">
6806                    <div class="swym-storefront-layout-empty-sfl-step-icon swym-storefront-layout-empty-sfl-step-icon--red">
6807                      <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none">
6808                        <path d="M3 5H15" stroke="#E53E3E" stroke-width="1.3" stroke-linecap="round"/>
6809                        <path d="M6 5V3H12V5" stroke="#E53E3E" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
6810                        <path d="M4.5 5L5.5 15H12.5L13.5 5" stroke="#E53E3E" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
6811                        <path d="M7.5 8V12M10.5 8V12" stroke="#E53E3E" stroke-width="1.3" stroke-linecap="round"/>
6812                      </svg>
6813                    </div>
6814                    <div class="swym-storefront-layout-empty-sfl-step-content">
6815                      <div class="swym-storefront-layout-empty-sfl-step-title">${SwymStorefrontLayoutContext?.Strings?.emptySflStep2Title || ''}</div>
6816                      <div class="swym-storefront-layout-empty-sfl-step-desc">${SwymStorefrontLayoutContext?.Strings?.emptySflStep2Description || ''}</div>
6817                    </div>
6818                  </div>
6819                </div>
6820                <div class="swym-storefront-layout-empty-sfl-notice swym-storefront-layout-empty-sfl-notice--grey">
6821                  <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none">
6822                    <circle cx="9" cy="9" r="8" stroke="#9B9B9B" stroke-width="1.2"/>
6823                    <path d="M6 9L8 11L12 7" stroke="#9B9B9B" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
6824                  </svg>
6825                  <span class="swym-storefront-layout-empty-sfl-notice-text"></span>
6826                </div>
6827                <hr class="swym-storefront-layout-empty-state-divider" />
6828                <a href="${cartUrl}" class="swym-storefront-layout-empty-state-cta-button swym-storefront-layout-empty-sfl-go-to-cart">
6829                  ${SwymStorefrontLayoutContext?.Strings?.emptySflGoToCartCTA || ''}
6830                  <svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" viewBox="0 0 14 9" fill="none"><path d="M13.8536 4.85368C14.0488 4.65841 14.0488 4.34183 13.8536 4.14657L10.6716 0.964589C10.4763 0.769327 10.1597 0.769327 9.96447 0.964589C9.7692 1.15985 9.7692 1.47643 9.96447 1.6717L12.7929 4.50012L9.96447 7.32855C9.7692 7.52381 9.7692 7.84039 9.96447 8.03566C10.1597 8.23092 10.4763 8.23092 10.6716 8.03566L13.8536 4.85368ZM0.5 5.00012L13.5 5.00012L13.5 4.00012L0.5 4.00012L0.5 5.00012Z" fill="currentColor"/></svg>
6831                </a>
6832              </div>
6833            </div>
6834          </div>
6835        `;
6836      } else {
6837        sflNoticeText = SwymStorefrontLayoutContext?.Strings?.emptySflGuestNotice || '';
6838        this.elements.itemsContainer.innerHTML = `
6839          <div class="swym-storefront-layout-empty-container swym-storefront-layout-empty-state-sfl swym-storefront-layout-empty-state-sfl-guest">
6840            <div class="swym-storefront-layout-empty-wishlist-container">
6841              <div class="swym-storefront-layout-empty-wishlist-content">
6842                <div class="swym-storefront-layout-empty-state-icon">
6843                  <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="none">
6844                    <circle cx="24" cy="24" r="24" fill="#F5F5F5"/>
6845                    <path d="M20 18H18C17.4696 18 16.9609 18.2107 16.5858 18.5858C16.2107 18.9609 16 19.4696 16 20V32C16 32.5304 16.2107 33.0391 16.5858 33.4142C16.9609 33.7893 17.4696 34 18 34H30C30.5304 34 31.0391 33.7893 31.4142 33.4142C31.7893 33.0391 32 32.5304 32 32V20C32 19.4696 31.7893 18.9609 31.4142 18.5858C31.0391 18.2107 30.5304 18 30 18H28M20 18V16C20 15.4696 20.2107 14.9609 20.5858 14.5858C20.9609 14.2107 21.4696 14 22 14H26C26.5304 14 27.0391 14.2107 27.4142 14.5858C27.7893 14.9609 28 15.4696 28 16V18M20 18H28" stroke="#9B9B9B" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
6846                    <path d="M20 24H28M20 28H25" stroke="#9B9B9B" stroke-width="1.5" stroke-linecap="round"/>
6847                  </svg>
6848                  <span class="swym-storefront-layout-empty-state-badge">
6849                    <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none">
6850                      <circle cx="7" cy="7" r="7" fill="#4CAF77"/>
6851                      <path d="M4 7L6 9L10 5" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
6852                    </svg>
6853                  </span>
6854                </div>
6855                <div class="swym-storefront-layout-empty-wishlist-title">${SwymStorefrontLayoutContext?.Strings?.emptySflTitle || ''}</div>
6856                <div class="swym-storefront-layout-empty-wishlist-description">${SwymStorefrontLayoutContext?.Strings?.emptySflDescription || ''}</div>
6857                <div class="swym-storefront-layout-empty-sfl-steps-card">
6858                  <div class="swym-storefront-layout-empty-sfl-step">
6859                    <div class="swym-storefront-layout-empty-sfl-step-icon swym-storefront-layout-empty-sfl-step-icon--green">
6860                      <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none">
6861                        <path d="M1.5 1.5H3.5L4.8 8.8C4.9 9.3 5.3 9.6 5.8 9.6H13.2C13.7 9.6 14.1 9.2 14.2 8.7L15.5 4H4" stroke="#4CAF77" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
6862                        <circle cx="6.5" cy="12.5" r="1.3" stroke="#4CAF77" stroke-width="1.3"/>
6863                        <circle cx="13" cy="12.5" r="1.3" stroke="#4CAF77" stroke-width="1.3"/>
6864                      </svg>
6865                    </div>
6866                    <div class="swym-storefront-layout-empty-sfl-step-content">
6867                      <div class="swym-storefront-layout-empty-sfl-step-title">${SwymStorefrontLayoutContext?.Strings?.emptySflStep1Title || ''}</div>
6868                      <div class="swym-storefront-layout-empty-sfl-step-desc">${SwymStorefrontLayoutContext?.Strings?.emptySflStep1Description || ''}</div>
6869                    </div>
6870                  </div>
6871                  <div class="swym-storefront-layout-empty-sfl-step-divider"></div>
6872                  <div class="swym-storefront-layout-empty-sfl-step">
6873                    <div class="swym-storefront-layout-empty-sfl-step-icon swym-storefront-layout-empty-sfl-step-icon--red">
6874                      <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none">
6875                        <path d="M3 5H15" stroke="#E53E3E" stroke-width="1.3" stroke-linecap="round"/>
6876                        <path d="M6 5V3H12V5" stroke="#E53E3E" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
6877                        <path d="M4.5 5L5.5 15H12.5L13.5 5" stroke="#E53E3E" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
6878                        <path d="M7.5 8V12M10.5 8V12" stroke="#E53E3E" stroke-width="1.3" stroke-linecap="round"/>
6879                      </svg>
6880                    </div>
6881                    <div class="swym-storefront-layout-empty-sfl-step-content">
6882                      <div class="swym-storefront-layout-empty-sfl-step-title">${SwymStorefrontLayoutContext?.Strings?.emptySflStep2Title || ''}</div>
6883                      <div class="swym-storefront-layout-empty-sfl-step-desc">${SwymStorefrontLayoutContext?.Strings?.emptySflStep2Description || ''}</div>
6884                    </div>
6885                  </div>
6886                </div>
6887                <div class="swym-storefront-layout-empty-sfl-notice swym-storefront-layout-empty-sfl-notice--amber">
6888                  <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none">
6889                    <circle cx="9" cy="9" r="8" stroke="#B45309" stroke-width="1.2"/>
6890                    <path d="M9 5V9L11 11" stroke="#B45309" stroke-width="1.2" stroke-linecap="round"/>
6891                  </svg>
6892                  <span class="swym-storefront-layout-empty-sfl-notice-text"></span>
6893                </div>
6894                <hr class="swym-storefront-layout-empty-state-divider" />
6895                <a href="${cartUrl}" class="swym-storefront-layout-empty-state-cta-button swym-storefront-layout-empty-sfl-go-to-cart">
6896                  ${SwymStorefrontLayoutContext?.Strings?.emptySflGoToCartCTA || ''}
6897                  <svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" viewBox="0 0 14 9" fill="none"><path d="M13.8536 4.85368C14.0488 4.65841 14.0488 4.34183 13.8536 4.14657L10.6716 0.964589C10.4763 0.769327 10.1597 0.769327 9.96447 0.964589C9.7692 1.15985 9.7692 1.47643 9.96447 1.6717L12.7929 4.50012L9.96447 7.32855C9.7692 7.52381 9.7692 7.84039 9.96447 8.03566C10.1597 8.23092 10.4763 8.23092 10.6716 8.03566L13.8536 4.85368ZM0.5 5.00012L13.5 5.00012L13.5 4.00012L0.5 4.00012L0.5 5.00012Z" fill="currentColor"/></svg>
6898                </a>
6899                <a href="${accountUrl}" class="swym-storefront-layout-empty-state-cta-button swym-storefront-layout-empty-sfl-login-cta">
6900                  ${SwymStorefrontLayoutContext?.Strings?.emptySflLoginCTA || ''}
6901                </a>
6902                <div class="swym-storefront-layout-empty-state-signup-text">
6903                  ${SwymStorefrontLayoutContext?.Strings?.emptySflSignupText || ''} <a href="${accountUrl}" class="swym-storefront-layout-empty-state-signup-link">${SwymStorefrontLayoutContext?.Strings?.emptySflSignupCTA || ''}</a>
6904                </div>
6905              </div>
6906            </div>
6907          </div>
6908        `;
6909      }
6910
6911      this.elements.itemsContainer.classList.add('swym-storefront-layout-items-has-empty');
6912
6913      const sflNoticeEl = this.elements.itemsContainer.querySelector('.swym-storefront-layout-empty-sfl-notice-text');
6914      if (sflNoticeEl) {
6915        sflNoticeEl.innerHTML = sflNoticeText || '';
6916      }
6917    }
6918
6919
6920  }
6921}
6922
6923
6924class SwymStorefrontLayoutSavedForYouContainer extends HTMLElement {
6925  constructor() {
6926    super();
6927    this.elements = {};
6928    this.initUI();
6929    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.WishlistFetched, () => {
6930      this.loadSavedForYouItems();
6931    });
6932  }
6933
6934  initUI() {
6935    this.renderUI();
6936    this.initElement();
6937  }
6938
6939  renderUI() {
6940    this.innerHTML = `
6941      <div class="swym-storefront-layout-header">
6942        <swym-storefront-layout-saved-for-you-title></swym-storefront-layout-saved-for-you-title>
6943      </div>
6944      <div class="swym-storefront-layout-body" role="region" aria-labelledby="swym-saved-for-you-title">
6945        <swym-storefront-layout-saved-for-you-list></swym-storefront-layout-saved-for-you-list>
6946      </div>
6947    `;
6948  }
6949
6950  initElement() {
6951    this.elements = {
6952      savedForYouList: this.querySelector('swym-storefront-layout-saved-for-you-list')
6953    };
6954  }
6955
6956  loadSavedForYouItems() {
6957    const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
6958    if (shouldShowMultiple) {
6959      // Multi-list: items live in the dedicated "Saved For Me" list
6960      const sfyList = SwymStorefrontLayoutContext.getSfyList();
6961      SwymStorefrontLayoutContext.savedForYouItems = sfyList?.listcontents || [];
6962      SwymStorefrontLayoutContext.savedForYouList = sfyList || SwymStorefrontLayoutContext?.DefaultList;
6963    } else {
6964      // Single-list: items are source-tagged inside DefaultList
6965      const allItems = SwymStorefrontLayoutContext?.DefaultList?.listcontents || [];
6966      SwymStorefrontLayoutContext.savedForYouItems = allItems.filter(item => item.source === 'auto-wishlist');
6967      SwymStorefrontLayoutContext.savedForYouList = SwymStorefrontLayoutContext?.DefaultList;
6968    }
6969    document.dispatchEvent(new CustomEvent(SwymStorefrontLayoutContext?.CustomEvents?.SavedForYouFetched));
6970  }
6971}
6972
6973class SwymStorefrontLayoutSavedForYouTitle extends HTMLElement {
6974  constructor() {
6975    super();
6976    this.renderTitle();
6977    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.SavedForYouFetched, () => {
6978      this.renderTitle();
6979    });
6980  }
6981
6982  renderTitle() {
6983    const totalCount = SwymStorefrontLayoutContext?.savedForYouItems?.length || 0;
6984
6985    // Drawer UI Polish: personalize SFY title for single wishlist + logged-in users (drawer only)
6986    const { shouldShowMultiple } = SwymStorefrontLayoutContext.getMultiWishlistConfig();
6987    const isDrawer = SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-drawer';
6988    const isLoggedIn = SwymStorefrontLayoutContext?.isShopperLoggedIn;
6989    const customerName = swymEscAttr(SwymStorefrontLayoutContext?.SwymCustomerData?.name?.split(' ')?.[0]);
6990    let sfyTitleText = SwymStorefrontLayoutContext?.Strings?.tabSavedForYou || 'Saved For You';
6991    if (isDrawer && !shouldShowMultiple && isLoggedIn && customerName) {
6992      sfyTitleText = (SwymStorefrontLayoutContext?.Strings?.personalizedSfyTitle || 'Saved For {{name}}').replace('{{name}}', customerName);
6993    }
6994
6995    const hideCount = isDrawer && !shouldShowMultiple;
6996    const sfyTitleIcon = isDrawer ? (SwymStorefrontLayoutExtensions?.getWishlistIconSvg?.('filled') || '') : '';
6997
6998    this.innerHTML = `
6999      <div>
7000        <div class="swym-storefront-layout-title" id="swym-saved-for-you-title" role="heading" aria-level="2">
7001          ${sfyTitleIcon}
7002          ${sfyTitleText}
7003        </div>
7004        ${ !hideCount && totalCount ? `<div class="swym-storefront-layout-total-list-items-count" id="swym-saved-for-you-items-count" aria-live="polite">${totalCount} ${totalCount <= 1 ? SwymStorefrontLayoutContext?.Strings?.item : SwymStorefrontLayoutContext?.Strings?.items}</div>` : ''}
7005      </div>
7006    `;
7007    const titleElement = this.querySelector('.swym-storefront-layout-title');
7008    SwymStorefrontLayoutExtensions?.applyHeadingFontStyles(titleElement);
7009  }
7010}
7011
7012class SwymStorefrontLayoutSavedForYouList extends HTMLElement {
7013  constructor() {
7014    super();
7015    this.elements = {};
7016    this.renderUI();
7017    document.addEventListener(SwymStorefrontLayoutContext?.CustomEvents?.SavedForYouFetched, () => {
7018      this.renderItems();
7019    });
7020  }
7021
7022  renderUI() {
7023    this.innerHTML = `
7024      <div id="swym-storefront-layout-sfy-items-container" class="swym-storefront-layout-items-container swym-storefront-layout-saved-for-you-list-container" role="list" aria-label="${SwymStorefrontLayoutContext?.Strings?.tabSavedForYou || 'Saved For You'} items" aria-busy="true" aria-live="polite">
7025        <swym-storefront-layout-loader loading="true" loadertype="${SwymStorefrontLayoutContext?.LoaderViewType?.WishlistListItem}" buttonCta="${SwymStorefrontLayoutContext?.Strings?.addToCart}" height="100px"></swym-storefront-layout-loader>
7026      </div>
7027    `;
7028    this.elements = {
7029      itemsContainer: this.querySelector('#swym-storefront-layout-sfy-items-container')
7030    };
7031  }
7032
7033  async renderItems() {
7034    const items = SwymStorefrontLayoutContext?.savedForYouItems || [];
7035    // In multi-list mode this is the "Saved For Me" list; in single-list it's DefaultList.
7036    // The correct lid is needed so remove/move operations target the right list.
7037    const list = SwymStorefrontLayoutContext?.savedForYouList || SwymStorefrontLayoutContext?.DefaultList;
7038
7039    if (!this.elements.itemsContainer) return;
7040
7041    if (items.length === 0) {
7042      this.elements.itemsContainer.innerHTML = `
7043        <div class="swym-storefront-layout-empty-container swym-storefront-layout-empty-sfy"></div>
7044      `;
7045      this.elements.itemsContainer.classList.add('swym-storefront-layout-items-has-empty');
7046      this.elements.itemsContainer.setAttribute('aria-busy', 'false');
7047      return;
7048    }
7049
7050    // Reverse-chronological: most recently auto-wishlisted appears first
7051    const sortedItems = [...items].sort((a, b) => (b.cdate || b.ts || 0) - (a.cdate || a.ts || 0));
7052
7053    const fragment = document.createDocumentFragment();
7054    sortedItems.forEach((item) => {
7055      const el = document.createElement('template');
7056      el.innerHTML = `<swym-storefront-layout-item id="swym-storefront-layout-sfy-item-${item.empi}-${item.epi}" class="swym-storefront-layout-sfy-item"></swym-storefront-layout-item>`;
7057      fragment.appendChild(el.content);
7058    });
7059    this.elements.itemsContainer.innerHTML = '';
7060    this.elements.itemsContainer.appendChild(fragment);
7061
7062    sortedItems.forEach((item) => {
7063      const el = document.querySelector(`#swym-storefront-layout-sfy-item-${item.empi}-${item.epi}`);
7064      el?.setData({
7065        item,
7066        listItemType: SwymStorefrontLayoutContext?.ListItemType?.SavedForYouItem,
7067        list
7068      });
7069    });
7070    this.elements.itemsContainer.classList.remove('swym-storefront-layout-items-has-empty');
7071    this.elements.itemsContainer.setAttribute('aria-busy', 'false');
7072  }
7073}
7074
7075// Show the login nudge when wishlist data is available.
7076document.addEventListener(
7077  SwymStorefrontLayoutContext?.CustomEvents?.WishlistFetched,
7078  () => { SwymStorefrontLayoutExtensions?.Notification?.setLoginNudge?.(); }
7079);
7080
7081// Warm the Shop Login SDK ahead of time when Shopify's own native signal says this
7082// visitor is worth it, so the nudge/drawer don't pay script-load + init latency later.
7083// Fires as soon as swat itself is ready (SwymCallbacks), not on WishlistFetched --
7084// the signal we check here doesn't depend on wishlist data, only swat.preloadShopLogin
7085// being callable, so waiting for the wishlist fetch to finish would be unnecessary delay.
7086if (typeof window !== 'undefined') {
7087  if (!window.SwymCallbacks) {
7088    window.SwymCallbacks = [];
7089  }
7090  window.SwymCallbacks.push((swat) => {
7091    const signInWithShop = window.Shopify?.SignInWithShop;
7092    if (signInWithShop?.eligible && signInWithShop?.User?.recognized) {
7093      swat?.preloadShopLogin?.(SWYM_SHOP_API_KEY);
7094    }
7095  });
7096}
7097
7098customElements.define('swym-storefront-layout-as-modal', SwymStorefrontLayoutAsModal);
7099if(SwymStorefrontLayoutContext?.Settings?.StorefrontLayoutType === 'as-section'){
7100  customElements.define('swym-storefront-layout-as-section', SwymStorefrontLayoutAsSection);
7101}
7102customElements.define('swym-storefront-layout-as-drawer', SwymStorefrontLayoutAsDrawer);
7103customElements.define('swym-storefront-layout-collection-carousel', SwymStorefrontLayoutCollectionCarousel);
7104customElements.define('swym-storefront-layout-item', SwymStorefrontLayoutWishlistItem);
7105customElements.define('swym-storefront-layout-default-wishlist', SwymStorefrontLayoutDefaultWishList);
7106customElements.define('swym-storefront-layout-collection-list', SwymStorefrontLayoutCollectionList);
7107customElements.define('swym-storefront-layout-actions', SwymStorefrontLayoutActions);
7108customElements.define('swym-storefront-layout-action-tooltip', SwymStorefrontLayoutActionTooltip);
7109customElements.define('swym-storefront-layout-notification', SwymStorefrontLayoutNotification);
7110customElements.define('swym-storefront-layout-loader', SwymStorefrontLayoutLoader);
7111customElements.define('swym-storefront-layout-login-user', SwymStorefrontLayoutLoggedUser);
7112customElements.define('swym-storefront-layout-title', SwymStorefrontLayoutTitle);
7113customElements.define('swym-storefront-layout-tabs', SwymStorefrontLayoutTabs);
7114customElements.define('swym-storefront-layout-tab-content', SwymStorefrontLayoutTabContent);
7115customElements.define('swym-storefront-layout-wishlist-container', SwymStorefrontLayoutWishlistContainer);
7116customElements.define('swym-storefront-layout-sfl-container', SwymStorefrontLayoutSaveForLaterContainer);
7117customElements.define('swym-storefront-layout-sfl-title', SwymStorefrontLayoutSaveForLaterTitle);
7118customElements.define('swym-storefront-layout-sfl-list', SwymStorefrontLayoutSaveForLaterList);
7119customElements.define('swym-storefront-layout-saved-for-you-container', SwymStorefrontLayoutSavedForYouContainer);
7120customElements.define('swym-storefront-layout-saved-for-you-title', SwymStorefrontLayoutSavedForYouTitle);
7121customElements.define('swym-storefront-layout-saved-for-you-list', SwymStorefrontLayoutSavedForYouList);
7122})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.