PageSourceSearch

https://www.hillhousehome.com/cdn/shop/t/552/assets/bundled-upsell-carousel.component.js

js hillhousehome.com collected 2026-09-24 22:11:53 UTC 11,213 bytes, 133 lines download raw bytes

1import { O as Ohm, H as HostAttr, a as autobind, c as Component, h as html, r as repeat, U as handleize, j as getLastSeenPromo, k as SuperTracker, t as t$1 } from './bundled-app.js';
2import { AddToCart } from './bundled-add-to-cart.directive.js';
3import { C as Carousel } from './bundled-carousel.directive.js';
4import { ContentDropdownDirective } from './bundled-content-dropdown.directive.js';
5import { ToggleQuickShop } from './bundled-toggle-quick-shop.directive.js';
6import { i as imgURL, f as formatMoney } from './bundled-ShopifyUtils.js';
7
8function t(t,e,s,i){var o,r=arguments.length,l=r<3?e:null===i?i=Object.getOwnPropertyDescriptor(e,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(t,e,s,i);else for(var a=t.length-1;a>=0;a--)(o=t[a])&&(l=(r<3?o(l):r>3?o(e,s,l):o(e,s))||l);return r>3&&l&&Object.defineProperty(e,s,l),l}function e(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)}Ohm.registerDirectiveClasses([Carousel,AddToCart,ContentDropdownDirective,ToggleQuickShop]);class UpsellCarousel extends Component{onAppInit(){this.setCarouselOptions(),this.host.productsData?.length?this.setState({products:this.host.productsData}):this.productHandles.length&&(this.fetchWhenVisible?(this.observer=new IntersectionObserver(this.onVisibleChange,{rootMargin:"0px 0px -25%"}),this.observer.observe(this.host)):this.fetch(this.productHandles));}render(){let{carouselID:t,sectionTitle:e,carouselOptions:s,noCarou
8sel:o,showItemsVariant:r,showItemsPrice:l}=this,{products:a}=this.state,n=this.renderItems(o,l,r);return a.length?html`
9        <div class="cartUpsell cartUpsell--${t}">
10          <span class="cartUpsell__title">${e}</span>
11
12          ${o?html`
13              <div class="cartUpsell__items">
14                ${n}
15              </div>
16            `:html`
17              <div
18                class="cartUpsell__carousel"
19                carousel
20                carousel-options=${JSON.stringify(s)}>
21                <div class="swiper-wrapper">
22                  ${n}
23                </div>
24              </div>
25              <div class="cartUpsell__scrollbar"></div>
26            </div>
27          `}
28      `:html``}setCarouselOptions(){let{carouselID:t}=this;this.carouselOptions={slidesPerView:"auto",watchOverflow:!0,freeMode:{enabled:!0,sticky:!0},mousewheel:{forceToAxis:!0},scrollbar:{el:`.cartUpsell--${t} .cartUpsell__scrollbar`,draggable:!1,dragSize:136},...this.carouselOptionsOverride};}setProductOptions(t){let{selectedOptions:e}=this.state;t.forEach(t=>{if(!e.find(e=>e.id===t.id)){let s={id:t.id,options:[]};t.options_with_values.forEach(e=>{s.options.push({name:e.name,position:e.position,value:t.variants.find(t=>t.available)?.[`option${e.position}`]});}),e.push(s);}}),this.setState({selectedOptions:e});}async fetch(t){let e=await fetch(`${window.Shopify.routes.root}index/cart-upsell/${t.join(",")}${this.indirectProducts?"|1":""}?view=product-list&t=${Date.now()}`),s=await e.json();200===e.status&&s&&(this.setProductOptions(s.products),this.updateProducts(s.products));}updateProducts(t){let e=this.state.products;this.setState({products:t}),JSON.stringify(e)!==JSON.stringify(this.state.products)&&this.updateCarousel();}updateCarousel(){let t=Ohm.getDirectiveFromHostElement(this.host.querySelector(".cartUpsell__carousel"),Carousel);t&&t.instance&&setTimeout(()=>{t.instance.update();});}renderItems(t,e,s){let{products:r,selectedOptions:l}=this.state;return html`
29      ${repeat(r,t=>t.id,r=>{let{id:a,name:n,price:d,media:c}=r,p=n.replace("UK - ","").split(" - "),u=p[0],m=p[1]||null,_=l.find(t=>t.id==a),y=r.variants.find(t=>
29!_||_.options.every(e=>t[`option${e.position}`]===e.value)),g=y&&y.featured_image?y.featured_image.src:c;return html`
30          <div class="cartUpsell__item${t?"":" swiper-slide"}">
31            <div class="cartUpsell__content">
32              <div class="cartUpsell__media">
33                <img src="${imgURL(g,"16x")}" data-src="${imgURL(g,"192x192")}" alt="${n}" class="inlineImg lazyload" />
34                <span class="Image__Loader"></span>
35              </div>
36
37              <div class="cartUpsell__body">
38                ${e?html`<span class="cartUpsell__productPrice">${formatMoney(d,{removeTrailingZeros:!0,showCurrency:!0})}</span>`:""}
39
40                <span class="cartUpsell__productTitle">${u}</span>
41
42                ${s&&m?html`
43                  <ul class="cartUpsell__details">
44                    <li class="cartUpsell__detail cartUpsell__detail--variant">${m}</li>
45                  </ul>
46                `:""}
47              </div>
48            </div>
49
50            ${_&&html`<div class="cartUpsell__options">
51              <div class="addToCart">
52                ${repeat(r.options_with_values,t=>t.position,t=>{let e=_.options.find(e=>e.name==t.name),s=handleize(t.name);if(!e.value.toLowerCase().includes("default"))return html`
53                    <div
54                      class="addToCart__dropdown-items"
55                      content-dropdown-items-for="${s}UpsellDropdown-${r.id}">
56                      <button
57                        type="button"
58                        class="addToCart__dropdown-items-close"
59                        @click=${this.closeProductOptions.bind(this,r,t.name)}
60                      >
61                        <svg>
62                          <use href="#icon-close"></use>
63                        </svg>
64                      </button>
65                      ${t.name.toLowerCase().includes("color")?this.renderColors(t,r,e?e.value:""):this.renderOption(t,r,e?e.value:"")}
66                    </div>
67                  `})}
68
69                <div id="UpsellDropdown-${r.id}" class="addToCart__wrapper" content-dropdown-group>
70                  ${repeat(r.options_with_values.filter(t=>"color"!==t.name.toLowerCase()),t=>t.position,t=>{let e=_.options.find(e=>e.name==t.name),s=handleize(t.name);if(!(t.values[0].toLowerCase().includes("default")||t.values[0].toLowerCase().includes("digital gift card")))return html`
71                      <div class="addToCart__col addToCart__col--${s}">
72                        <div id="${s}UpsellDropdown-${r.id}" class="addToCart__dropdown" content-dropdown>
73                          <span class="addToCart__dropdown-title">
74                            ${t.name.toLowerCase().includes("color")?this.renderColors(t,r,e?e.value:""):this.renderOption(t,r,e?e.value:"")}
75                          </span>
76
77                          <svg class="addToCart__dropdown-icon">
78                            <use href="#icon-arrow-line-caret"></use>
79                          </svg>
80                        </div>
81                      </div>
82                    `})}
83                </div>
84
85              </div>
86              ${this.renderButton(r,y)}
87            </div>`}
88          </div>
89        `})}
90    `}renderColors(t,e,s){return t.values,null}renderOption(t,e,s){let{selectedOptions:r}=this.state,l=t.values,a=r.find(t=>t.id==e.id),n=a.options.find(e=>e.name===t.name);return html`
91      <ul
92        class="pdpForm__sizeList"
93        active-option-class="selected"
94      >
95        ${repeat(l,t=>t,(o,r)=>{let l=e.variants.find(t=>a.options.every(e=>e.name===n.name||t[`option${e.position}`]===e.value)&&t[`option${n.position}`]===o),d="productOption",c=!1,p=!0;return o===s&&(c=!0,d+=" productOption--active"),0!==l.inventory_quantity&&l.available||(p=!1,d+=" productOption--disabled"),html`
96            <li class="pdpForm__size">
97              <button
98                role='button'
99                for="cart-upsell-${e.id}-${handleize(t.name)}-${r}"
100                class="${d}"
101                data-selected="${!!c}"
102                data-inventory-qty="${l.inventory_quantity}"
103                data-tracking-label="${o}"
104                @click=${p?this.setOptions.bind(this,e,o,t.name):null}
105              >
106                ${o}
107              </button>
108            </li>
109            `})}
110      </ul>
111    `}renderButton(t,e){return this.itemsHaveQuickView?html`
112        <button
113          type="button"
114          aria-label="Open quickview"
115          class="cartUpsell__add cta"
116          data-tracking-label="{{ title | escape }}"
117          data-tracking-action="Open quickview"
118          toggle-quick-shop="${t.handle}">
119          ${this.itemButtonTitle}
120        </button>
121      `:html`
122        <button
123          type="button"
124          aria-label="Add ${t.name} to cart."
125          context="sidecart"
126          @click=${this.onAddClick.bind(this,t)}
127          add-to-cart="${e.id}"
128          class="cartUpsell__add cta">
129          ${this.itemButtonTitle}
130        </button>
131      `}onAddClick(t){if(!t)return;let e=t.datalayer_config;Object.keys(e).forEach(t=>{"undefined"===e[t]&&(e[t]=void 0);});let s=getLastSeenPromo();s&&(e.promotion_id=s.promotion_id,e.promotion_name=s.promotion_name),SuperTracker.getInstance().trackGa({event:"add_to_cart",ecommerce:{currency:window.Shopify.currency.active,view_type:"sidecart",items:[e]}});}onVisibleChange([t]){t.isIntersecting&&(this.observer.disconnect(),this.observer=null,this.fetch(this.productHandles));}setOptions(t,e,s){let i=Ohm.getDirectiveFromHostElement(this.host.querySelector(`#${handleize(s)}UpsellDropdown-${t.id}`),ContentDropdownDirective),{id:o}=t,r=this.state.selectedOptions,l=r.findIndex(t=>t.id==o);l>-1&&(r[l].options.map(t=>(t.name===s&&(t.value=e),t)),this.setState({selectedOptions:r}),i.close());}closeProductOptions(t,e){let s=Ohm.getDirectiveFromHostElement(this.host.querySelector(`#${handleize(e)}UpsellDropdown-${t.id}`),ContentDropdownDirective);s&&s.close();}constructor(...t){super(...t),this.productHandles=[],this.sectionTitle=t$1("sidecart.cross_sell_title"),this.fetchWhenVisible=!1,this.indirectProducts=!1,this.carouselOptionsOverride={},this.noCarousel=!1,this.itemButtonTitle="+ Add",this.showItemsVariant=!0,this.showItemsPrice=!0,this.itemsHaveQuickView=!1,this.state={products:[],selectedOptions:[]},this.carouselID=Math.round(999999*Math.random());}}UpsellCarousel.selector="upsell-carousel",t([HostAttr("="),e("design:type",Array)],UpsellCarousel.prototype,"productHandles",void 0),t([HostAttr(),e("design:type",String)],UpsellCarousel.prototype,"sectionTitle",void 0),t([HostAttr("="),e("design:type",Boolean)],UpsellCarousel.prototype,"fetchWhenVisible",void 0),t([HostAttr("="),e("design:type",Boolean)],UpsellCarousel.prototype,"indirectProducts",void 0),t([HostAttr("=carousel-options"),e("design:type","undefined"==typeof SwiperOptions?Object:SwiperOptions)],UpsellCarousel.prototype,"carouselOptionsOverride",void 0),t([HostAttr("="),e("design:type",Boolean)],UpsellCarousel.prototype,"noCarousel",void 0),t([HostAttr(),e("design:type",String)],UpsellCarousel.prototype,"itemButtonTitle",void 0),t([HostAttr("="),e("design:type",Boolean)],UpsellCarousel.prototype,"showItemsVariant",void 0),t([HostAttr("="),e("design:type",Boolean)],UpsellCarousel.prototype,"showItemsPrice",void 0),t([HostAttr("="),e("design:type",Boolean)],UpsellCarousel.prototype,"itemsHaveQuickView",void 0),t([autobind,e("design:type",Function),e("design:paramtypes",[Array]),e("design:returntype",void 0)],UpsellCarousel.prototype,"onVisibleChange",null);
132
133export { UpsellCarousel as U };

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.