@dropins/storefront-quick-order 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
1
  /*! Copyright 2026 Adobe
2
2
  All Rights Reserved. */
3
- import{jsxs as w,jsx as t,Fragment as Q}from"@dropins/tools/preact-jsx-runtime.js";import{memo as F,useCallback as O,useState as I,useRef as D,useEffect as x,useMemo as L}from"@dropins/tools/preact-compat.js";import{InputFile as J,CartList as X,Divider as Y,Button as Z,CartItem as W,AccordionSection as U,PriceRange as ee,Input as re}from"@dropins/tools/components.js";import{Slot as T}from"@dropins/tools/lib.js";import{useState as B,useRef as te,useEffect as j,useMemo as ae,useCallback as H}from"@dropins/tools/preact-hooks.js";import{events as se}from"@dropins/tools/event-bus.js";import{d as ne,c as K}from"./debounce.js";const ce=({t:e,onFileUpload:r,error:a,fileName:c,onDownloadSample:d,showSampleDownload:s,disabled:l})=>{const u=O(f=>{var h;const m=(h=f.target.files)==null?void 0:h[0];m&&r(m)},[r]);return w("div",{className:"b2b-quick-order-csv-file-input",children:[t("div",{className:"b2b-quick-order-csv-file-input__title",children:e.title}),w("div",{className:"b2b-quick-order-csv-file-input__helper",children:[e.helperText,s&&t(Q,{children:t("button",{type:"button",className:"b2b-quick-order-csv-file-input__download-link",onClick:d,"data-testid":"download-sample",disabled:l,children:e.downloadSample})})]}),t("div",{className:`b2b-quick-order-csv-file-input__input-wrapper ${l?"b2b-quick-order-csv-file-input__input-wrapper--disabled":""}`,children:t(J,{id:"quick-order-csv-file-input",label:e.inputLabel,className:"b2b-quick-order-csv-file-input__input",onChange:u,accept:".csv",disabled:l})}),c&&w("div",{className:"b2b-quick-order-csv-file-input__file-name","data-testid":"file-name",children:[e.selectedFile,": ",c]}),a&&t("div",{className:"b2b-quick-order-csv-file-input__error","data-testid":"error-message",role:"alert",children:a})]})},$e=F(ce),ie=[{attribute:"visibility",in:["Search","Catalog, Search"]}],le=e=>{const{containerRef:r,itemSelected:a,initialValue:c,currentValue:d,onValueRestore:s,onClose:l}=e,u=document.activeElement;(r==null?void 0:r.contains(u))||(l(),!a&&c!==d&&s(c))},ue=(e,r=150)=>window.setTimeout(()=>{le(e)},r),M=e=>{e&&clearTimeout(e)},oe=(e,r)=>r===0?-1:e<r-1?e+1:e,de=e=>e>0?e-1:-1,he=()=>0,pe=e=>Math.max(0,e-1),me=(e,r,a)=>e>=0&&r[e]?(a(r[e]),!0):!1,be=(e,r,a,c)=>{a(e),c(),r&&"blur"in r&&typeof r.blur=="function"&&r.blur()},z=({productsSearch:e,initialSku:r,replaceItemSku:a,searchFilter:c=ie})=>{const[d,s]=B(r),[l,u]=B([]),[n,f]=B(!1),o=te(!0);j(()=>()=>{o.current=!1},[]),j(()=>{n||s(r)},[r,n]);const m=ae(()=>ne(async b=>{if(!b||!e){o.current&&u([]);return}try{const k=await e({phrase:b,filter:c});o.current&&u(k.items||[])}catch(k){console.error("Error searching products:",k),o.current&&u([])}},300),[e,c]),h=H(b=>{const v=b.target.value;s(v),f(!0),m(v)},[m]),q=H(()=>{s(""),u([]),f(!1)},[]),y=H(b=>{const k={sku:b.sku,...b.variantSku&&{variantSku:b.variantSku},quantity:1,...a&&{replaceItemSku:a}};se.emit("quick-order/add-items",[k]),q()},[a,q]);return{searchValue:d,searchResults:l,handleSearchChange:h,shouldShowResults:n,resetSearch:q,handleItemClick:y}},fe=({value:e,onChange:r,items:a,shouldShowResults:c=!0,onItemClick:d})=>{const[s,l]=I(-1),[u,n]=I(""),[f,o]=I(!1),[m,h]=I(!1),q=D(`search-results-${Math.random().toString(36).substr(2,9)}`),y=D(null),b=D([]),k=D(null),v=D(null),S=!!e&&!m,_=c&&S&&a.length>0,R=c&&S&&a.length===0;x(()=>{l(-1)},[a]),x(()=>()=>{M(v.current)},[]),x(()=>{if(s>=0&&b.current[s]){const p=b.current[s];p&&typeof p.scrollIntoView=="function"&&p.scrollIntoView({behavior:"smooth",block:"nearest"})}},[s]);const g=O(p=>{m&&h(!1),r==null||r(p)},[r,m]),N=O(p=>()=>{o(!0),h(!0),d==null||d(p),l(-1)},[d]),E=O(()=>{M(v.current),v.current=null,n(e||""),o(!1),h(!1)},[e]),P=O(()=>{v.current=ue({containerRef:k.current,itemSelected:f,initialValue:u,currentValue:e||"",onValueRestore:p=>{r==null||r({target:{value:p}})},onClose:()=>{h(!0)}})},[f,u,e,r]),C=O(p=>{if(_)switch(p.key){case"ArrowDown":p.preventDefault(),l(i=>oe(i,a.length));break;case"ArrowUp":p.preventDefault(),l(i=>de(i));break;case"Home":_&&a.length>0&&(p.preventDefault(),l(he()));break;case"End":_&&a.length>0&&(p.preventDefault(),l(pe(a.length)));break;case"Tab":M(v.current),v.current=null,h(!0),r==null||r({target:{value:u}});break;case"Enter":{me(s,a,A=>{o(!0),h(!0),d==null||d(A),l(-1)})&&p.preventDefault();break}case"Escape":p.preventDefault(),be(u,y.current,i=>{r==null||r({target:{value:i}}),l(-1),h(!0)},()=>{h(!0)});break}},[_,a,s,d,r,u]),V=O(()=>{if(s>=0&&_)return`${q.current}-item-${s}`},[s,_]);return{activeIndex:s,showResults:_,showEmptyState:R,resultsId:q,inputRef:y,itemRefs:b,containerRef:k,handleChange:g,handleFocus:E,handleBlur:P,handleKeyDown:C,createItemClickHandler:N,getActiveDescendant:V}},ke=({t:e,items:r,onRemove:a,clearItems:c,onUpdateQuantity:d,slots:s,handleAddToCart:l,isItemUpdating:u,loading:n,isDisabledButton:f,productsSearch:o,searchFilter:m})=>{const{searchValue:h,searchResults:q,handleSearchChange:y,shouldShowResults:b,handleItemClick:k}=z({productsSearch:o,initialSku:"",searchFilter:m});return w("div",{className:K(["b2b-quick-order-form-quick-order-items-list"]),role:"region","aria-label":e.title,children:[t("div",{className:"b2b-quick-order-form-quick-order-items-list__title",children:e.title}),r.length>0&&w(Q,{children:[t(X,{role:"list",className:"b2b-quick-order-form-quick-order-items-list__list",children:r.map(v=>t(qe,{item:v,t:e,onRemove:a,onUpdateQuantity:d,isUpdating:u==null?void 0:u(v.sku),loading:n,productsSearch:o,searchFilter:m,slots:s},v.sku))}),t(Y,{variant:"secondary"})]}),t("div",{className:"b2b-quick-order-form-quick-order-items-list__global-search",children:t(G,{t:e,onChange:y,items:q,value:h,shouldShowResults:b,onItemClick:k,className:"b2b-quick-order-form-quick-order-items-list__search"})}),r.length===0&&t("div",{className:"b2b-quick-order-form-quick-order-items-list__empty","data-testid":"empty-items",children:e.emptyList}),t(T,{slot:s==null?void 0:s.AddAllToCartButton,name:"AddAllToCartButton",context:{handleAddToCart:l,clearItems:c,loading:n,isDisabledButton:f},"data-testid":"addAllToCart",children:t("div",{className:"b2b-quick-order-form-quick-order-items-list__actions",children:t(Z,{variant:"primary",onClick:l,"data-testid":"add-all-to-cart-button",disabled:n||f,children:e.addAllToCart})})})]})},De=F(ke),ve=({item:e,t:r,onRemove:a,onUpdateQuantity:c,isUpdating:d,loading:s,productsSearch:l,searchFilter:u,slots:n})=>{var V,p;const f=`quick-order-item-${e.id||e.variantSku||e.sku}`,o=(e==null?void 0:e.variantSku)??(e==null?void 0:e.sku),{searchValue:m,searchResults:h,handleSearchChange:q,shouldShowResults:y,handleItemClick:b}=z({productsSearch:l,initialSku:o,replaceItemSku:e.sku,searchFilter:u}),k=`form-${e.id||o}`,v=e.inStock&&e.addToCartAllowed,S=e.options&&e.options.length>0,_=L(()=>S&&e.options.some(i=>i.required),[S,e.options]),R=L(()=>S&&e.options.some(i=>i.items&&i.items.some(A=>A.selected)),[S,e.options]),g=L(()=>_?e.options.every(i=>i.required?i.items&&i.items.some(A=>A.selected):!0):R,[_,R,e.options]),N=L(()=>{var i;return(i=e.images)==null?void 0:i.find(A=>{var $;return($=A.roles)==null?void 0:$.includes("image")})},[e.images]),E=O(()=>{a==null||a(e.id||e.sku)},[a,e.id,e.sku]),P=O(i=>{c==null||c(e.sku,i);const A=document.forms[k];if(A){const $=A.querySelector('input[name="quantity"]');$&&($.value=String(i))}},[c,e.sku,k]),C=t(T,{name:"QuickOrderItemSearch",slot:n==null?void 0:n.QuickOrderItemSearch,context:{item:e,scope:f,handleSearchChange:q,searchResults:h,searchValue:m,shouldShowResults:y,handleItemClick:b},children:t(G,{t:r,onChange:q,items:h,value:m,shouldShowResults:y,className:"b2b-quick-order-form-quick-order-items__item-search",onItemClick:b,slots:n})});return!e.name&&!((V=e.images)!=null&&V.length)?w("form",{name:k,className:"b2b-quick-order-form-quick-order-items__item-form",onSubmit:i=>i.preventDefault(),"data-sku":e.sku,children:[t("input",{type:"hidden",name:"sku",value:e.sku}),t("input",{type:"hidden",name:"quantity",value:e.quantity}),t("input",{type:"hidden",name:"valid",value:"false"}),t("input",{type:"hidden",name:"productType",value:""}),C,t(W,{sku:t("span",{children:e.sku}),title:t("span",{children:r.productNotFound}),quantity:e.quantity,alert:t("div",{className:"b2b-quick-order-items__error",children:(p=r.productNotFoundDescription)==null?void 0:p.replace("{sku}",e.sku)}),disabled:s,onRemove:E,ariaLabel:`${r.productNotFound} - ${e.sku}`})]},e.sku):w("form",{name:k,className:"b2b-quick-order-form-quick-order-items__item-form",onSubmit:i=>i.preventDefault(),"data-sku":o,children:[t("input",{type:"hidden",name:"sku",value:o}),t("input",{type:"hidden",name:"quantity",value:e.quantity}),t("input",{type:"hidden",name:"valid",value:v?"true":"false"}),t("input",{type:"hidden",name:"productType",value:e.productType||""}),C,t(W,{title:t("span",{children:e.name}),sku:t("span",{children:o}),image:N?t("img",{src:N.url,alt:N.label||e.name}):void 0,price:t(T,{name:"ProductPrice",slot:n==null?void 0:n.ProductPrice,context:{item:e,scope:f},children:t(ee,{minimumAmount:e.prices.final.minimumAmount,maximumAmount:e.prices.final.maximumAmount,amount:e.prices.final.amount,currency:e.prices.final.currency})}),quantity:e.quantity,alert:e.inStock===!1?t("div",{className:"b2b-quick-order-items__alert",children:r.outOfStock}):void 0,warning:S&&!g?t("div",{className:"b2b-quick-order-items__warning",children:r.configurableOptionsWarning}):void 0,footer:S?t(U,{title:r.productOptions,ariaLabelTitle:r.productOptions,defaultOpen:!g,className:"b2b-quick-order-list-item__accordion",actionIconPosition:"left",children:t(T,{name:"ProductOptions",slot:n==null?void 0:n.ProductOptions,context:{item:e,scope:f},children:t("div",{className:"b2b-quick-order-items__configurable-error",children:r.configurableProductErrorDescription})})}):void 0,updating:d,disabled:s,loading:s,onRemove:E,onQuantity:P,ariaLabel:`${e.name} - ${e.sku}`})]},o)},qe=F(ve),_e={cursor:"pointer"},ye={cursor:"default"},Se=({t:e,value:r,onChange:a,items:c,shouldShowResults:d=!0,className:s,onItemClick:l,slots:u})=>{const{activeIndex:n,showResults:f,showEmptyState:o,resultsId:m,inputRef:h,itemRefs:q,containerRef:y,handleChange:b,handleFocus:k,handleBlur:v,handleKeyDown:S,createItemClickHandler:_,getActiveDescendant:R}=fe({value:r,onChange:a,items:c,shouldShowResults:d,onItemClick:l});return w("div",{ref:y,className:K(["b2b-quick-order-search",s]),children:[t(re,{ref:h,className:"b2b-quick-order-search__input",value:r,onChange:b,onFocus:k,onBlur:v,placeholder:e.searchPlaceholder,"aria-label":e.searchAriaLabel,role:"combobox","aria-autocomplete":"list","aria-expanded":f,"aria-controls":m.current,"aria-activedescendant":R(),onKeyDown:S}),f&&t("div",{id:m.current,role:"listbox",className:"b2b-quick-order-search__results","aria-label":e.searchAriaLabel,children:c.map((g,N)=>t(T,{slot:u==null?void 0:u.QuickOrderSearchAutocompleteItem,name:"QuickOrderSearchAutocompleteItem",context:{item:g,index:N,createItemClickHandler:_,activeIndex:n},children:t("div",{id:`${m.current}-item-${N}`,ref:E=>q.current[N]=E,role:"option","aria-selected":N===n,className:K(["b2b-quick-order-search__result-item",N===n&&"b2b-quick-order-search__result-item--active"]),onClick:_(g),style:l?_e:ye,children:`${g.sku} ${g.name}`})},g.sku))}),o&&t("div",{className:"b2b-quick-order-search__empty-state",role:"status","aria-live":"polite",children:e.searchEmptyState}),f&&w("div",{className:"sr-only",role:"status","aria-live":"polite","aria-atomic":"true",children:[c.length," ",c.length===1?e.resultAvailable:e.resultsAvailable,"."," ",e.srInstructions]})]})},G=F(Se),Te=({isDisabled:e,message:r,children:a})=>w("div",{className:"b2b-quick-order-disabled-overlay",children:[t("div",{className:"b2b-quick-order-disabled-overlay__content",style:{pointerEvents:e?"none":"auto"},children:a}),e&&w(Q,{children:[t("div",{className:"b2b-quick-order-disabled-overlay__blur"}),t("div",{className:"b2b-quick-order-disabled-overlay__message",children:r})]})]});export{$e as C,Te as Q,De as a};
3
+ import{jsxs as w,jsx as t,Fragment as K}from"@dropins/tools/preact-jsx-runtime.js";import{memo as L,useCallback as A,useState as V,useRef as $,useEffect as F,useMemo as P}from"@dropins/tools/preact-compat.js";import{InputFile as G,CartList as J,Divider as X,Button as Y,CartItem as Q,AccordionSection as Z,PriceRange as U,Input as ee}from"@dropins/tools/components.js";import{Slot as D}from"@dropins/tools/lib.js";import{useState as x,useRef as re,useEffect as W,useMemo as te,useCallback as B}from"@dropins/tools/preact-hooks.js";import{events as ae}from"@dropins/tools/event-bus.js";import{d as ne,c as M}from"./debounce.js";const se=[{attribute:"visibility",in:["Search","Catalog, Search"]}],ce=e=>{const{containerRef:r,itemSelected:n,initialValue:i,currentValue:d,onValueRestore:s,onClose:u}=e,l=document.activeElement;(r==null?void 0:r.contains(l))||(u(),!n&&i!==d&&s(i))},ie=(e,r=150)=>window.setTimeout(()=>{ce(e)},r),H=e=>{e&&clearTimeout(e)},ue=(e,r)=>r===0?-1:e<r-1?e+1:e,le=e=>e>0?e-1:-1,oe=()=>0,de=e=>Math.max(0,e-1),pe=(e,r,n)=>e>=0&&r[e]?(n(r[e]),!0):!1,he=(e,r,n,i)=>{n(e),i(),r&&"blur"in r&&typeof r.blur=="function"&&r.blur()},be=({t:e,onFileUpload:r,error:n,fileName:i,onDownloadSample:d,showSampleDownload:s,disabled:u})=>{const l=A(f=>{var p;const h=(p=f.target.files)==null?void 0:p[0];h&&r(h)},[r]);return w("div",{className:"b2b-quick-order-csv-file-input",children:[t("div",{className:"b2b-quick-order-csv-file-input__title",children:e.title}),w("div",{className:"b2b-quick-order-csv-file-input__helper",children:[e.helperText,s&&t(K,{children:t("button",{type:"button",className:"b2b-quick-order-csv-file-input__download-link",onClick:d,"data-testid":"download-sample",disabled:u,children:e.downloadSample})})]}),t("div",{className:`b2b-quick-order-csv-file-input__input-wrapper ${u?"b2b-quick-order-csv-file-input__input-wrapper--disabled":""}`,children:t(G,{id:"quick-order-csv-file-input",label:e.inputLabel,className:"b2b-quick-order-csv-file-input__input",onChange:l,accept:".csv",disabled:u})}),i&&w("div",{className:"b2b-quick-order-csv-file-input__file-name","data-testid":"file-name",children:[e.selectedFile,": ",i]}),n&&t("div",{className:"b2b-quick-order-csv-file-input__error","data-testid":"error-message",role:"alert",children:n})]})},Ee=L(be),j=({productsSearch:e,initialSku:r,replaceItemSku:n,searchFilter:i=se})=>{const[d,s]=x(r),[u,l]=x([]),[c,f]=x(!1),o=re(!0);W(()=>()=>{o.current=!1},[]),W(()=>{c||s(r)},[r,c]);const h=te(()=>ne(async b=>{if(!b||!e){o.current&&l([]);return}try{const k=await e({phrase:b,filter:i});o.current&&l(k.items||[])}catch(k){console.error("Error searching products:",k),o.current&&l([])}},300),[e,i]),p=B(b=>{const m=b.target.value;s(m),f(!0),h(m)},[h]),q=B(()=>{s(""),l([]),f(!1)},[]),_=B(b=>{const k={sku:b.sku,...b.variantSku&&{variantSku:b.variantSku},quantity:1,...n&&{replaceItemSku:n}};ae.emit("quick-order/add-items",[k]),q()},[n,q]);return{searchValue:d,searchResults:u,handleSearchChange:p,shouldShowResults:c,resetSearch:q,handleItemClick:_}},me=({value:e,onChange:r,items:n,shouldShowResults:i=!0,onItemClick:d})=>{const[s,u]=V(-1),[l,c]=V(""),[f,o]=V(!1),[h,p]=V(!1),q=$(`search-results-${Math.random().toString(36).substr(2,9)}`),_=$(null),b=$([]),k=$(null),m=$(null),S=!!e&&!h,y=i&&S&&n.length>0,R=i&&S&&n.length===0;F(()=>{u(-1)},[n]),F(()=>()=>{H(m.current)},[]),F(()=>{if(s>=0&&b.current[s]){const a=b.current[s];a&&typeof a.scrollIntoView=="function"&&a.scrollIntoView({behavior:"smooth",block:"nearest"})}},[s]);const N=A(a=>{h&&p(!1),r==null||r(a)},[r,h]),g=A(a=>()=>{o(!0),p(!0),d==null||d(a),u(-1)},[d]),E=A(()=>{H(m.current),m.current=null,c(e||""),o(!1),p(!1)},[e]),T=A(()=>{m.current=ie({containerRef:k.current,itemSelected:f,initialValue:l,currentValue:e||"",onValueRestore:a=>{r==null||r({target:{value:a}})},onClose:()=>{p(!0)}})},[f,l,e,r]),C=A(a=>{if(y)switch(a.key){case"ArrowDown":a.preventDefault(),u(v=>ue(v,n.length));break;case"ArrowUp":a.preventDefault(),u(v=>le(v));break;case"Home":y&&n.length>0&&(a.preventDefault(),u(oe()));break;case"End":y&&n.length>0&&(a.preventDefault(),u(de(n.length)));break;case"Tab":H(m.current),m.current=null,p(!0),r==null||r({target:{value:l}});break;case"Enter":{pe(s,n,O=>{o(!0),p(!0),d==null||d(O),u(-1)})&&a.preventDefault();break}case"Escape":a.preventDefault(),he(l,_.current,v=>{r==null||r({target:{value:v}}),u(-1),p(!0)},()=>{p(!0)});break}},[y,n,s,d,r,l]),I=A(()=>{if(s>=0&&y)return`${q.current}-item-${s}`},[s,y]);return{activeIndex:s,showResults:y,showEmptyState:R,resultsId:q,inputRef:_,itemRefs:b,containerRef:k,handleChange:N,handleFocus:E,handleBlur:T,handleKeyDown:C,createItemClickHandler:g,getActiveDescendant:I}},fe=({t:e,items:r,onRemove:n,clearItems:i,onUpdateQuantity:d,slots:s,handleAddToCart:u,isItemUpdating:l,loading:c,isDisabledButton:f,productsSearch:o,searchFilter:h})=>{const{searchValue:p,searchResults:q,handleSearchChange:_,shouldShowResults:b,handleItemClick:k}=j({productsSearch:o,initialSku:"",searchFilter:h});return w("div",{className:M(["b2b-quick-order-form-quick-order-items-list"]),role:"region","aria-label":e.title,children:[t("div",{className:"b2b-quick-order-form-quick-order-items-list__title",children:e.title}),r.length>0&&w(K,{children:[t(J,{role:"list",className:"b2b-quick-order-form-quick-order-items-list__list",children:r.map(m=>t(ve,{item:m,t:e,onRemove:n,onUpdateQuantity:d,isUpdating:l==null?void 0:l(m.variantSku||m.sku),loading:c,productsSearch:o,searchFilter:h,slots:s},m.id||m.sku))}),t(X,{variant:"secondary"})]}),t("div",{className:"b2b-quick-order-form-quick-order-items-list__global-search",children:t(z,{t:e,onChange:_,items:q,value:p,shouldShowResults:b,onItemClick:k,className:"b2b-quick-order-form-quick-order-items-list__search"})}),r.length===0&&t("div",{className:"b2b-quick-order-form-quick-order-items-list__empty","data-testid":"empty-items",children:e.emptyList}),t(D,{slot:s==null?void 0:s.AddAllToCartButton,name:"AddAllToCartButton",context:{handleAddToCart:u,clearItems:i,loading:c,isDisabledButton:f},"data-testid":"addAllToCart",children:t("div",{className:"b2b-quick-order-form-quick-order-items-list__actions",children:t(Y,{variant:"primary",onClick:u,"data-testid":"add-all-to-cart-button",disabled:c||f,children:e.addAllToCart})})})]})},$e=L(fe),ke=({item:e,t:r,onRemove:n,onUpdateQuantity:i,isUpdating:d,loading:s,productsSearch:u,searchFilter:l,slots:c})=>{var C,I;const f=`quick-order-item-${e.id||e.variantSku||e.sku}`,o=(e==null?void 0:e.variantSku)??(e==null?void 0:e.sku),{searchValue:h,searchResults:p,handleSearchChange:q,shouldShowResults:_,handleItemClick:b}=j({productsSearch:u,initialSku:o,replaceItemSku:e.sku,searchFilter:l}),k=`form-${e.id||o}`,m=e.inStock&&e.addToCartAllowed,S=e.options&&e.options.length>0,y=P(()=>S&&e.options.some(a=>a.required),[S,e.options]),R=P(()=>S?y?e.options.every(a=>a.required?a.items&&a.items.some(v=>v.selected):!0):e.options.every(a=>a.items&&a.items.some(v=>v.selected)):!0,[S,y,e.options]),N=P(()=>{var a;return(a=e.images)==null?void 0:a.find(v=>{var O;return(O=v.roles)==null?void 0:O.includes("image")})},[e.images]),g=A(()=>{n==null||n(e.id||e.sku)},[n,e.id,e.sku]),E=A(a=>{i==null||i(o,a);const v=document.forms[k];if(v){const O=v.querySelector('input[name="quantity"]');O&&(O.value=String(a))}},[i,o,k]),T=t(D,{name:"QuickOrderItemSearch",slot:c==null?void 0:c.QuickOrderItemSearch,context:{item:e,scope:f,handleSearchChange:q,searchResults:p,searchValue:h,shouldShowResults:_,handleItemClick:b},children:t(z,{t:r,onChange:q,items:p,value:h,shouldShowResults:_,className:"b2b-quick-order-form-quick-order-items__item-search",onItemClick:b,slots:c})});return!e.name&&!((C=e.images)!=null&&C.length)?w("form",{name:k,className:"b2b-quick-order-form-quick-order-items__item-form",onSubmit:a=>a.preventDefault(),"data-sku":e.sku,children:[t("input",{type:"hidden",name:"sku",value:e.sku}),t("input",{type:"hidden",name:"quantity",value:e.quantity}),t("input",{type:"hidden",name:"valid",value:"false"}),t("input",{type:"hidden",name:"productType",value:""}),e.parentSku&&t("input",{type:"hidden",name:"parentSku",value:e.parentSku}),T,t(Q,{sku:t("span",{children:e.sku}),title:t("span",{children:r.productNotFound}),quantity:e.quantity,alert:t("div",{className:"b2b-quick-order-items__error",children:(I=r.productNotFoundDescription)==null?void 0:I.replace("{sku}",e.sku)}),disabled:s,onRemove:g,ariaLabel:`${r.productNotFound} - ${e.sku}`})]},e.sku):w("form",{name:k,className:"b2b-quick-order-form-quick-order-items__item-form",onSubmit:a=>a.preventDefault(),"data-sku":o,children:[t("input",{type:"hidden",name:"sku",value:o}),t("input",{type:"hidden",name:"quantity",value:e.quantity}),t("input",{type:"hidden",name:"valid",value:m?"true":"false"}),t("input",{type:"hidden",name:"productType",value:e.productType||""}),e.id&&t("input",{type:"hidden",name:"itemId",value:e.id}),e.parentSku&&t("input",{type:"hidden",name:"parentSku",value:e.parentSku}),T,t(Q,{title:t("span",{children:e.name}),sku:t("span",{children:o}),image:N?t("img",{src:N.url,alt:N.label||e.name}):void 0,price:t(D,{name:"ProductPrice",slot:c==null?void 0:c.ProductPrice,context:{item:e,scope:f},children:t(U,{minimumAmount:e.prices.final.minimumAmount,maximumAmount:e.prices.final.maximumAmount,amount:e.prices.final.amount,currency:e.prices.final.currency})}),quantity:e.quantity,alert:e.inStock===!1?t("div",{className:"b2b-quick-order-items__alert",children:r.outOfStock}):void 0,warning:S&&!R?t("div",{className:"b2b-quick-order-items__warning",children:r.configurableOptionsWarning}):void 0,footer:S?t(Z,{title:r.productOptions,ariaLabelTitle:r.productOptions,defaultOpen:!R,className:"b2b-quick-order-list-item__accordion",actionIconPosition:"left",children:t(D,{name:"ProductOptions",slot:c==null?void 0:c.ProductOptions,context:{item:e,scope:f},children:t("div",{className:"b2b-quick-order-items__configurable-error",children:r.configurableProductErrorDescription})})}):void 0,updating:d,disabled:s,loading:s,onRemove:g,onQuantity:E,ariaLabel:`${e.name} - ${e.sku}`})]},o)},ve=L(ke),qe={cursor:"pointer"},ye={cursor:"default"},_e=({t:e,value:r,onChange:n,items:i,shouldShowResults:d=!0,className:s,onItemClick:u,slots:l})=>{const{activeIndex:c,showResults:f,showEmptyState:o,resultsId:h,inputRef:p,itemRefs:q,containerRef:_,handleChange:b,handleFocus:k,handleBlur:m,handleKeyDown:S,createItemClickHandler:y,getActiveDescendant:R}=me({value:r,onChange:n,items:i,shouldShowResults:d,onItemClick:u});return w("div",{ref:_,className:M(["b2b-quick-order-search",s]),children:[t(ee,{ref:p,className:"b2b-quick-order-search__input",value:r,onChange:b,onFocus:k,onBlur:m,placeholder:e.searchPlaceholder,"aria-label":e.searchAriaLabel,role:"combobox","aria-autocomplete":"list","aria-expanded":f,"aria-controls":h.current,"aria-activedescendant":R(),onKeyDown:S}),f&&t("div",{id:h.current,role:"listbox",className:"b2b-quick-order-search__results","aria-label":e.searchAriaLabel,children:i.map((N,g)=>t(D,{slot:l==null?void 0:l.QuickOrderSearchAutocompleteItem,name:"QuickOrderSearchAutocompleteItem",context:{item:N,index:g,createItemClickHandler:y,activeIndex:c},children:t("div",{id:`${h.current}-item-${g}`,ref:E=>q.current[g]=E,role:"option","aria-selected":g===c,className:M(["b2b-quick-order-search__result-item",g===c&&"b2b-quick-order-search__result-item--active"]),onClick:y(N),style:u?qe:ye,children:`${N.sku} ${N.name}`})},N.sku))}),o&&t("div",{className:"b2b-quick-order-search__empty-state",role:"status","aria-live":"polite",children:e.searchEmptyState}),f&&w("div",{className:"sr-only",role:"status","aria-live":"polite","aria-atomic":"true",children:[i.length," ",i.length===1?e.resultAvailable:e.resultsAvailable,"."," ",e.srInstructions]})]})},z=L(_e),De=({isDisabled:e,message:r,children:n})=>w("div",{className:"b2b-quick-order-disabled-overlay",children:[t("div",{className:"b2b-quick-order-disabled-overlay__content",style:{pointerEvents:e?"none":"auto"},children:n}),e&&w(K,{children:[t("div",{className:"b2b-quick-order-disabled-overlay__blur"}),t("div",{className:"b2b-quick-order-disabled-overlay__message",children:r})]})]});export{Ee as C,De as Q,$e as a};
4
4
  //# sourceMappingURL=QuickOrderDisabledOverlay.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"QuickOrderDisabledOverlay.js","sources":["/@dropins/storefront-quick-order/src/components/CsvFileInput/CsvFileInput.tsx","/@dropins/storefront-quick-order/src/configs/search-filter.config.ts","/@dropins/storefront-quick-order/src/lib/searchBlurHandler.ts","/@dropins/storefront-quick-order/src/lib/searchKeyboardNavigation.ts","/@dropins/storefront-quick-order/src/hooks/useItemSearch.tsx","/@dropins/storefront-quick-order/src/hooks/useSearch.tsx","/@dropins/storefront-quick-order/src/components/QuickOrderItemsList/QuickOrderItemsList.tsx","/@dropins/storefront-quick-order/src/components/QuickOrderListItem/QuickOrderListItem.tsx","/@dropins/storefront-quick-order/src/components/Search/Search.tsx","/@dropins/storefront-quick-order/src/components/QuickOrderDisabledOverlay/QuickOrderDisabledOverlay.tsx"],"sourcesContent":["/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { FunctionComponent, useCallback, memo } from 'preact/compat';\nimport { InputFile } from '@adobe-commerce/elsie/components';\nimport { CsvFileInputProps } from '@/b2b-quick-order/types/quickOrderCsvUpload.types';\nimport '@/b2b-quick-order/components/CsvFileInput/CsvFileInput.css';\n\nconst CsvFileInputComponent: FunctionComponent<CsvFileInputProps> = ({\n t,\n onFileUpload,\n error,\n fileName,\n onDownloadSample,\n showSampleDownload,\n disabled,\n}) => {\n const handleFileChange = useCallback(\n (e: Event) => {\n const target = e.target as HTMLInputElement;\n const file = target.files?.[0];\n if (file) {\n onFileUpload(file);\n }\n },\n [onFileUpload]\n );\n\n const inputClassName = 'b2b-quick-order-csv-file-input__input';\n\n return (\n <div className=\"b2b-quick-order-csv-file-input\">\n <div className=\"b2b-quick-order-csv-file-input__title\">{t.title}</div>\n\n <div className=\"b2b-quick-order-csv-file-input__helper\">\n {t.helperText}\n {showSampleDownload && (\n <>\n <button\n type=\"button\"\n className=\"b2b-quick-order-csv-file-input__download-link\"\n onClick={onDownloadSample}\n data-testid=\"download-sample\"\n disabled={disabled}\n >\n {t.downloadSample}\n </button>\n </>\n )}\n </div>\n\n <div\n className={`b2b-quick-order-csv-file-input__input-wrapper ${\n disabled\n ? 'b2b-quick-order-csv-file-input__input-wrapper--disabled'\n : ''\n }`}\n >\n <InputFile\n id={'quick-order-csv-file-input'}\n label={t.inputLabel}\n className={inputClassName}\n onChange={handleFileChange}\n accept={'.csv'}\n disabled={disabled}\n />\n </div>\n\n {fileName && (\n <div\n className=\"b2b-quick-order-csv-file-input__file-name\"\n data-testid=\"file-name\"\n >\n {t.selectedFile}: {fileName}\n </div>\n )}\n\n {error && (\n <div\n className=\"b2b-quick-order-csv-file-input__error\"\n data-testid=\"error-message\"\n role=\"alert\"\n >\n {error}\n </div>\n )}\n </div>\n );\n};\n\nexport const CsvFileInput = memo(CsvFileInputComponent);\n","export const SEARCH_FILTER = [\n {\n attribute: 'visibility',\n in: ['Search', 'Catalog, Search'],\n },\n];\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nexport interface BlurHandlerOptions {\n containerRef: HTMLElement | null;\n itemSelected: boolean;\n initialValue: string;\n currentValue: string;\n onValueRestore: (value: string) => void;\n onClose: () => void;\n}\n\n/**\n * Handles blur logic for search component\n * Checks if focus moved outside component and restores initial value if needed\n */\nexport const handleSearchBlur = (options: BlurHandlerOptions): void => {\n const {\n containerRef,\n itemSelected,\n initialValue,\n currentValue,\n onValueRestore,\n onClose,\n } = options;\n\n const activeElement = document.activeElement;\n const isWithinComponent = containerRef?.contains(activeElement);\n\n if (!isWithinComponent) {\n onClose();\n\n if (!itemSelected && initialValue !== currentValue) {\n onValueRestore(initialValue);\n }\n }\n};\n\n/**\n * Creates a blur handler with timeout\n */\nexport const createBlurHandler = (\n options: BlurHandlerOptions,\n delay: number = 150\n): number => {\n return window.setTimeout(() => {\n handleSearchBlur(options);\n }, delay);\n};\n\n/**\n * Clears blur timeout if exists\n */\nexport const clearBlurTimeout = (timeoutRef: number | null): void => {\n if (timeoutRef) {\n clearTimeout(timeoutRef);\n }\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\n/**\n * WCAG 2.1 compliant keyboard navigation for combobox with listbox pattern.\n * Focus always remains on the input element, visual indication via aria-activedescendant.\n * Reference: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/\n */\n\n/**\n * Calculates next active index when ArrowDown is pressed\n * Returns next index in list or current if at end\n */\nexport const handleArrowDown = (\n currentIndex: number,\n itemsLength: number\n): number => {\n if (itemsLength === 0) return -1;\n return currentIndex < itemsLength - 1 ? currentIndex + 1 : currentIndex;\n};\n\n/**\n * Calculates next active index when ArrowUp is pressed\n * Returns previous index or -1 to return focus to input\n */\nexport const handleArrowUp = (currentIndex: number): number => {\n return currentIndex > 0 ? currentIndex - 1 : -1;\n};\n\n/**\n * Moves visual focus to first item in list (Home key)\n */\nexport const handleHomeKey = (): number => {\n return 0;\n};\n\n/**\n * Moves visual focus to last item in list (End key)\n */\nexport const handleEndKey = (itemsLength: number): number => {\n return Math.max(0, itemsLength - 1);\n};\n\n/**\n * Handles Enter key press on active item\n * Returns true if item was selected, false otherwise\n */\nexport const handleEnterKey = <T>(\n activeIndex: number,\n items: T[],\n onItemSelect: (item: T) => void\n): boolean => {\n if (activeIndex >= 0 && items[activeIndex]) {\n onItemSelect(items[activeIndex]);\n return true;\n }\n return false;\n};\n\n/**\n * Handles Escape key press - restores initial value and closes results\n */\nexport const handleEscapeKey = (\n initialValue: string,\n inputRef: HTMLElement | null,\n onValueRestore: (value: string) => void,\n onClose: () => void\n): void => {\n onValueRestore(initialValue);\n onClose();\n if (inputRef && 'blur' in inputRef && typeof inputRef.blur === 'function') {\n inputRef.blur();\n }\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport {\n useCallback,\n useState,\n useMemo,\n useRef,\n useEffect,\n} from 'preact/hooks';\nimport { debounce } from '@adobe-commerce/elsie/lib/debounce';\nimport { OrderItem, UseItemSearchProps } from '@/b2b-quick-order/types';\nimport { events } from '@adobe-commerce/event-bus';\nimport { SEARCH_FILTER } from '@/b2b-quick-order/configs';\n\nexport const useItemSearch = ({\n productsSearch,\n initialSku,\n replaceItemSku,\n searchFilter = SEARCH_FILTER,\n}: UseItemSearchProps) => {\n const [searchValue, setSearchValue] = useState(initialSku);\n const [searchResults, setSearchResults] = useState<OrderItem[]>([]);\n const [isTouched, setIsTouched] = useState(false);\n\n // Track if component is mounted to prevent state updates after unmount\n const isMountedRef = useRef(true);\n\n useEffect(() => {\n return () => {\n isMountedRef.current = false;\n };\n }, []);\n\n // Update search value when initialSku changes (e.g., after merge)\n useEffect(() => {\n if (!isTouched) {\n setSearchValue(initialSku);\n }\n }, [initialSku, isTouched]);\n\n const debouncedSearch = useMemo(\n () =>\n debounce(async (searchTerm: string) => {\n if (!searchTerm || !productsSearch) {\n if (isMountedRef.current) {\n setSearchResults([]);\n }\n return;\n }\n\n try {\n const result = await productsSearch({\n phrase: searchTerm,\n filter: searchFilter,\n });\n if (isMountedRef.current) {\n setSearchResults(result.items || []);\n }\n } catch (error) {\n console.error('Error searching products:', error);\n if (isMountedRef.current) {\n setSearchResults([]);\n }\n }\n }, 300),\n [productsSearch, searchFilter]\n );\n\n const handleSearchChange = useCallback(\n (e: Event) => {\n const target = e.target as HTMLInputElement;\n const value = target.value;\n setSearchValue(value);\n setIsTouched(true);\n debouncedSearch(value);\n },\n [debouncedSearch]\n );\n\n const resetSearch = useCallback(() => {\n setSearchValue('');\n setSearchResults([]);\n setIsTouched(false);\n }, []);\n\n const handleItemClick = useCallback(\n (clickedItem: OrderItem) => {\n // Build item data for emission\n // Just send the data as-is from the search result\n // The deduplication logic will handle matching correctly\n const itemData = {\n sku: clickedItem.sku,\n ...(clickedItem.variantSku && { variantSku: clickedItem.variantSku }),\n quantity: 1,\n ...(replaceItemSku && { replaceItemSku }),\n };\n\n events.emit('quick-order/add-items', [itemData]);\n resetSearch();\n },\n [replaceItemSku, resetSearch]\n );\n\n return {\n searchValue,\n searchResults,\n handleSearchChange,\n shouldShowResults: isTouched,\n resetSearch,\n handleItemClick,\n };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport React, { useCallback, useState, useRef, useEffect } from 'preact/compat';\nimport { SearchItem } from '@/b2b-quick-order/types/search.types';\nimport {\n createBlurHandler,\n clearBlurTimeout,\n handleArrowDown,\n handleArrowUp,\n handleEnterKey,\n handleEscapeKey,\n handleHomeKey,\n handleEndKey,\n} from '@/b2b-quick-order/lib';\n\nexport interface UseSearchOptions<T extends SearchItem> {\n value: string;\n onChange?: (e: any) => void;\n items: T[];\n shouldShowResults?: boolean;\n onItemClick?: (item: T) => void;\n}\n\nexport interface UseSearchReturn<T extends SearchItem> {\n // State\n activeIndex: number;\n showResults: boolean;\n showEmptyState: boolean;\n\n // Refs\n resultsId: React.MutableRefObject<string>;\n inputRef: React.RefObject<HTMLInputElement>;\n itemRefs: React.MutableRefObject<(HTMLDivElement | null)[]>;\n containerRef: React.RefObject<HTMLDivElement>;\n\n // Handlers\n handleChange: (e: any) => void;\n handleFocus: () => void;\n handleBlur: () => void;\n handleKeyDown: (e: KeyboardEvent) => void;\n createItemClickHandler: (item: T) => () => void;\n getActiveDescendant: () => string | undefined;\n}\n\nexport const useSearch = <T extends SearchItem = SearchItem>({\n value,\n onChange,\n items,\n shouldShowResults = true,\n onItemClick,\n}: UseSearchOptions<T>): UseSearchReturn<T> => {\n const [activeIndex, setActiveIndex] = useState(-1);\n const [initialValue, setInitialValue] = useState('');\n const [itemSelected, setItemSelected] = useState(false);\n const [isClosedManually, setIsClosedManually] = useState(false);\n\n const resultsId = useRef(\n `search-results-${Math.random().toString(36).substr(2, 9)}`\n );\n const inputRef = useRef<HTMLInputElement>(null);\n const itemRefs = useRef<(HTMLDivElement | null)[]>([]);\n const containerRef = useRef<HTMLDivElement>(null);\n const blurTimeoutRef = useRef<number | null>(null);\n\n const isOpen = Boolean(value) && !isClosedManually;\n const showResults = shouldShowResults && isOpen && items.length > 0;\n const showEmptyState = shouldShowResults && isOpen && items.length === 0;\n\n useEffect(() => {\n setActiveIndex(-1);\n // Don't reset isClosedManually here - only reset on focus\n // This prevents results from reopening after Tab\n }, [items]);\n\n useEffect(() => {\n return () => {\n clearBlurTimeout(blurTimeoutRef.current);\n };\n }, []);\n\n useEffect(() => {\n // Auto-scroll active item into view when navigating with keyboard\n if (activeIndex >= 0 && itemRefs.current[activeIndex]) {\n const element = itemRefs.current[activeIndex];\n if (element && typeof element.scrollIntoView === 'function') {\n element.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n });\n }\n }\n }, [activeIndex]);\n\n const handleChange = useCallback(\n (e: any) => {\n // Reset isClosedManually when user types\n if (isClosedManually) {\n setIsClosedManually(false);\n }\n onChange?.(e);\n },\n [onChange, isClosedManually]\n );\n\n const createItemClickHandler = useCallback(\n (item: T) => () => {\n setItemSelected(true);\n setIsClosedManually(true);\n onItemClick?.(item);\n setActiveIndex(-1);\n },\n [onItemClick]\n );\n\n const handleFocus = useCallback(() => {\n clearBlurTimeout(blurTimeoutRef.current);\n blurTimeoutRef.current = null;\n setInitialValue(value || '');\n setItemSelected(false);\n setIsClosedManually(false);\n }, [value]);\n\n const handleBlur = useCallback(() => {\n blurTimeoutRef.current = createBlurHandler({\n containerRef: containerRef.current,\n itemSelected,\n initialValue,\n currentValue: value || '',\n onValueRestore: (restoredValue) => {\n onChange?.({ target: { value: restoredValue } } as any);\n },\n onClose: () => {\n setIsClosedManually(true);\n },\n });\n }, [itemSelected, initialValue, value, onChange]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (!showResults) return;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n setActiveIndex((prev) => handleArrowDown(prev, items.length));\n break;\n case 'ArrowUp':\n e.preventDefault();\n setActiveIndex((prev) => handleArrowUp(prev));\n break;\n case 'Home':\n if (showResults && items.length > 0) {\n e.preventDefault();\n setActiveIndex(handleHomeKey());\n }\n break;\n case 'End':\n if (showResults && items.length > 0) {\n e.preventDefault();\n setActiveIndex(handleEndKey(items.length));\n }\n break;\n case 'Tab':\n clearBlurTimeout(blurTimeoutRef.current);\n blurTimeoutRef.current = null;\n setIsClosedManually(true);\n onChange?.({ target: { value: initialValue } } as any);\n break;\n case 'Enter': {\n const wasHandled = handleEnterKey(activeIndex, items, (item) => {\n setItemSelected(true);\n setIsClosedManually(true);\n onItemClick?.(item);\n setActiveIndex(-1);\n });\n if (wasHandled) {\n e.preventDefault();\n }\n break;\n }\n case 'Escape':\n e.preventDefault();\n handleEscapeKey(\n initialValue,\n inputRef.current,\n (restoredValue) => {\n onChange?.({ target: { value: restoredValue } } as any);\n setActiveIndex(-1);\n setIsClosedManually(true);\n },\n () => {\n setIsClosedManually(true);\n }\n );\n break;\n }\n },\n [showResults, items, activeIndex, onItemClick, onChange, initialValue]\n );\n\n const getActiveDescendant = useCallback(() => {\n if (activeIndex >= 0 && showResults) {\n return `${resultsId.current}-item-${activeIndex}`;\n }\n return undefined;\n }, [activeIndex, showResults]);\n\n return {\n activeIndex,\n showResults,\n showEmptyState,\n resultsId,\n inputRef,\n itemRefs,\n containerRef,\n handleChange,\n handleFocus,\n handleBlur,\n handleKeyDown,\n createItemClickHandler,\n getActiveDescendant,\n };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { FunctionComponent, memo } from 'preact/compat';\nimport { Button, CartList, Divider } from '@adobe-commerce/elsie/components';\nimport { classes } from '@adobe-commerce/elsie/lib/classes';\nimport { QuickOrderItemsListProps } from '@/b2b-quick-order/types';\nimport { Slot } from '@adobe-commerce/elsie/lib';\nimport { QuickOrderListItem, Search } from '@/b2b-quick-order/components';\nimport { useItemSearch } from '@/b2b-quick-order/hooks';\nimport '@/b2b-quick-order/components/QuickOrderItemsList/QuickOrderItemsList.css';\n\nconst QuickOrderItemsListComponent: FunctionComponent<\n QuickOrderItemsListProps\n> = ({\n t,\n items,\n onRemove,\n clearItems,\n onUpdateQuantity,\n slots,\n handleAddToCart,\n isItemUpdating,\n loading,\n isDisabledButton,\n productsSearch,\n searchFilter,\n}) => {\n const {\n searchValue,\n searchResults,\n handleSearchChange,\n shouldShowResults,\n handleItemClick,\n } = useItemSearch({\n productsSearch,\n initialSku: '',\n searchFilter,\n });\n\n return (\n <div\n className={classes(['b2b-quick-order-form-quick-order-items-list'])}\n role=\"region\"\n aria-label={t.title}\n >\n <div className=\"b2b-quick-order-form-quick-order-items-list__title\">\n {t.title}\n </div>\n\n {items.length > 0 && (\n <>\n <CartList\n role=\"list\"\n className=\"b2b-quick-order-form-quick-order-items-list__list\"\n >\n {items.map((item) => (\n <QuickOrderListItem\n key={item.sku}\n item={item}\n t={t}\n onRemove={onRemove}\n onUpdateQuantity={onUpdateQuantity}\n isUpdating={isItemUpdating?.(item.sku)}\n loading={loading}\n productsSearch={productsSearch}\n searchFilter={searchFilter}\n slots={slots}\n />\n ))}\n </CartList>\n <Divider variant={'secondary'} />\n </>\n )}\n <div className=\"b2b-quick-order-form-quick-order-items-list__global-search\">\n <Search\n t={t}\n onChange={handleSearchChange}\n items={searchResults}\n value={searchValue}\n shouldShowResults={shouldShowResults}\n onItemClick={handleItemClick}\n className=\"b2b-quick-order-form-quick-order-items-list__search\"\n />\n </div>\n {items.length === 0 && (\n <div\n className=\"b2b-quick-order-form-quick-order-items-list__empty\"\n data-testid=\"empty-items\"\n >\n {t.emptyList}\n </div>\n )}\n <Slot\n slot={slots?.AddAllToCartButton}\n name=\"AddAllToCartButton\"\n context={{\n handleAddToCart,\n clearItems,\n loading,\n isDisabledButton,\n }}\n data-testid=\"addAllToCart\"\n >\n <div className=\"b2b-quick-order-form-quick-order-items-list__actions\">\n <Button\n variant=\"primary\"\n onClick={handleAddToCart}\n data-testid=\"add-all-to-cart-button\"\n disabled={loading || isDisabledButton}\n >\n {t.addAllToCart}\n </Button>\n </div>\n </Slot>\n </div>\n );\n};\n\nexport const QuickOrderItemsList = memo(QuickOrderItemsListComponent);\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { FunctionComponent, useMemo, useCallback, memo } from 'preact/compat';\nimport {\n CartItem,\n AccordionSection,\n PriceRange,\n} from '@adobe-commerce/elsie/components';\nimport { Slot } from '@adobe-commerce/elsie/lib';\nimport { QuickOrderListItemProps } from '@/b2b-quick-order/types';\nimport { useItemSearch } from '@/b2b-quick-order/hooks';\nimport '@/b2b-quick-order/components/QuickOrderListItem/QuickOrderListItem.css';\nimport { Search } from '@/b2b-quick-order/components';\n\nconst QuickOrderListItemComponent: FunctionComponent<\n QuickOrderListItemProps\n> = ({\n item,\n t,\n onRemove,\n onUpdateQuantity,\n isUpdating,\n loading,\n productsSearch,\n searchFilter,\n slots,\n}) => {\n // Generate unique scope identifier Dropins - use item.id if available to distinguish multiple items with same sku\n const scope = `quick-order-item-${item.id || item.variantSku || item.sku}`;\n const currentSku = item?.variantSku ?? item?.sku;\n\n const {\n searchValue,\n searchResults,\n handleSearchChange,\n shouldShowResults,\n handleItemClick,\n } = useItemSearch({\n productsSearch,\n initialSku: currentSku,\n replaceItemSku: item.sku,\n searchFilter,\n });\n\n const formName = `form-${item.id || currentSku}`;\n const isValid = item.inStock && item.addToCartAllowed;\n const hasOptions = item.options && item.options.length > 0;\n\n const hasRequiredOptions = useMemo(\n () => hasOptions && item.options.some((option) => option.required),\n [hasOptions, item.options]\n );\n\n const hasSelectedOptions = useMemo(\n () =>\n hasOptions &&\n item.options.some(\n (option) =>\n option.items && option.items.some((optionItem) => optionItem.selected)\n ),\n [hasOptions, item.options]\n );\n\n // Check if all required options are selected\n const allRequiredOptionsSelected = useMemo(() => {\n if (hasRequiredOptions) {\n // If there are required options, check that all are selected\n return item.options.every((option) => {\n if (!option.required) return true;\n return (\n option.items && option.items.some((optionItem) => optionItem.selected)\n );\n });\n }\n // If no required options, return hasSelectedOptions\n return hasSelectedOptions;\n }, [hasRequiredOptions, hasSelectedOptions, item.options]);\n\n const mainImage = useMemo(\n () => item.images?.find((img) => img.roles?.includes('image')),\n [item.images]\n );\n\n // Memoize handlers\n const handleRemove = useCallback(() => {\n // Use item.id if available, otherwise fall back to sku\n onRemove?.(item.id || item.sku);\n }, [onRemove, item.id, item.sku]);\n\n const handleQuantityChange = useCallback(\n (newQty: number) => {\n onUpdateQuantity?.(item.sku, newQty);\n // Update hidden quantity field\n const form = document.forms[formName as any] as HTMLFormElement;\n if (form) {\n const qtyInput = form.querySelector(\n 'input[name=\"quantity\"]'\n ) as HTMLInputElement;\n if (qtyInput) qtyInput.value = String(newQty);\n }\n },\n [onUpdateQuantity, item.sku, formName]\n );\n\n const searchSlot = (\n <Slot\n name=\"QuickOrderItemSearch\"\n slot={slots?.QuickOrderItemSearch}\n context={{\n item,\n scope,\n handleSearchChange,\n searchResults,\n searchValue,\n shouldShowResults,\n handleItemClick,\n }}\n >\n <Search\n t={t}\n onChange={handleSearchChange}\n items={searchResults}\n value={searchValue}\n shouldShowResults={shouldShowResults}\n className=\"b2b-quick-order-form-quick-order-items__item-search\"\n onItemClick={handleItemClick}\n slots={slots}\n />\n </Slot>\n );\n\n if (!item.name && !item.images?.length) {\n return (\n <form\n key={item.sku}\n name={formName}\n className=\"b2b-quick-order-form-quick-order-items__item-form\"\n onSubmit={(e) => e.preventDefault()}\n data-sku={item.sku}\n >\n <input type=\"hidden\" name=\"sku\" value={item.sku} />\n <input type=\"hidden\" name=\"quantity\" value={item.quantity} />\n <input type=\"hidden\" name=\"valid\" value=\"false\" />\n <input type=\"hidden\" name=\"productType\" value=\"\" />\n {searchSlot}\n\n <CartItem\n sku={<span>{item.sku}</span>}\n title={<span>{t.productNotFound}</span>}\n quantity={item.quantity}\n alert={\n <div className=\"b2b-quick-order-items__error\">\n {t.productNotFoundDescription?.replace('{sku}', item.sku)}\n </div>\n }\n disabled={loading}\n onRemove={handleRemove}\n ariaLabel={`${t.productNotFound} - ${item.sku}`}\n />\n </form>\n );\n }\n\n return (\n <form\n key={currentSku}\n name={formName}\n className=\"b2b-quick-order-form-quick-order-items__item-form\"\n onSubmit={(e) => e.preventDefault()}\n data-sku={currentSku}\n >\n <input type=\"hidden\" name=\"sku\" value={currentSku} />\n <input type=\"hidden\" name=\"quantity\" value={item.quantity} />\n <input type=\"hidden\" name=\"valid\" value={isValid ? 'true' : 'false'} />\n <input type=\"hidden\" name=\"productType\" value={item.productType || ''} />\n {searchSlot}\n <CartItem\n title={<span>{item.name}</span>}\n sku={<span>{currentSku}</span>}\n image={\n mainImage ? (\n <img src={mainImage.url} alt={mainImage.label || item.name} />\n ) : undefined\n }\n price={\n <Slot\n name=\"ProductPrice\"\n slot={slots?.ProductPrice}\n context={{\n item,\n scope,\n }}\n >\n <PriceRange\n minimumAmount={item.prices.final.minimumAmount}\n maximumAmount={item.prices.final.maximumAmount}\n amount={item.prices.final.amount}\n currency={item.prices.final.currency}\n />\n </Slot>\n }\n quantity={item.quantity}\n alert={\n item.inStock === false ? (\n <div className=\"b2b-quick-order-items__alert\">{t.outOfStock}</div>\n ) : undefined\n }\n warning={\n hasOptions && !allRequiredOptionsSelected ? (\n <div className=\"b2b-quick-order-items__warning\">\n {t.configurableOptionsWarning}\n </div>\n ) : undefined\n }\n footer={\n hasOptions ? (\n <AccordionSection\n title={t.productOptions}\n ariaLabelTitle={t.productOptions}\n defaultOpen={!allRequiredOptionsSelected}\n className=\"b2b-quick-order-list-item__accordion\"\n actionIconPosition=\"left\"\n >\n <Slot\n name=\"ProductOptions\"\n slot={slots?.ProductOptions}\n context={{\n item,\n scope,\n }}\n >\n <div className=\"b2b-quick-order-items__configurable-error\">\n {t.configurableProductErrorDescription}\n </div>\n </Slot>\n </AccordionSection>\n ) : undefined\n }\n updating={isUpdating}\n disabled={loading}\n loading={loading}\n onRemove={handleRemove}\n onQuantity={handleQuantityChange}\n ariaLabel={`${item.name} - ${item.sku}`}\n />\n </form>\n );\n};\n\nexport const QuickOrderListItem = memo(QuickOrderListItemComponent);\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { memo } from 'preact/compat';\nimport { Input } from '@adobe-commerce/elsie/components';\nimport { classes } from '@adobe-commerce/elsie/lib/classes';\nimport { SearchProps, SearchItem } from '@/b2b-quick-order/types/search.types';\nimport { useSearch } from '@/b2b-quick-order/hooks/useSearch';\nimport '@/b2b-quick-order/components/Search/Search.css';\nimport { Slot } from '@adobe-commerce/elsie/lib';\n\nconst cursorStyle = { cursor: 'pointer' as const };\nconst defaultCursorStyle = { cursor: 'default' as const };\n\nconst SearchComponent = <T extends SearchItem = SearchItem>({\n t,\n value,\n onChange,\n items,\n shouldShowResults = true,\n className,\n onItemClick,\n slots,\n}: SearchProps<T>) => {\n const {\n activeIndex,\n showResults,\n showEmptyState,\n resultsId,\n inputRef,\n itemRefs,\n containerRef,\n handleChange,\n handleFocus,\n handleBlur,\n handleKeyDown,\n createItemClickHandler,\n getActiveDescendant,\n } = useSearch({\n value,\n onChange,\n items,\n shouldShowResults,\n onItemClick,\n });\n\n return (\n <div\n ref={containerRef}\n className={classes(['b2b-quick-order-search', className])}\n >\n <Input\n ref={inputRef}\n className=\"b2b-quick-order-search__input\"\n value={value}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n placeholder={t.searchPlaceholder}\n aria-label={t.searchAriaLabel}\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded={showResults}\n aria-controls={resultsId.current}\n aria-activedescendant={getActiveDescendant()}\n onKeyDown={handleKeyDown}\n />\n\n {showResults && (\n <div\n id={resultsId.current}\n role=\"listbox\"\n className=\"b2b-quick-order-search__results\"\n aria-label={t.searchAriaLabel}\n >\n {items.map((item, index) => (\n <Slot\n key={item.sku}\n slot={slots?.QuickOrderSearchAutocompleteItem}\n name={'QuickOrderSearchAutocompleteItem'}\n context={{\n item,\n index,\n createItemClickHandler,\n activeIndex,\n }}\n >\n <div\n id={`${resultsId.current}-item-${index}`}\n ref={(el) => (itemRefs.current[index] = el)}\n role=\"option\"\n aria-selected={index === activeIndex}\n className={classes([\n 'b2b-quick-order-search__result-item',\n index === activeIndex &&\n 'b2b-quick-order-search__result-item--active',\n ])}\n onClick={createItemClickHandler(item)}\n style={onItemClick ? cursorStyle : defaultCursorStyle}\n >\n {`${item.sku} ${item.name}`}\n </div>\n </Slot>\n ))}\n </div>\n )}\n\n {showEmptyState && (\n <div\n className=\"b2b-quick-order-search__empty-state\"\n role=\"status\"\n aria-live=\"polite\"\n >\n {t.searchEmptyState}\n </div>\n )}\n\n {showResults && (\n <div\n className=\"sr-only\"\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n >\n {items.length}{' '}\n {items.length === 1 ? t.resultAvailable : t.resultsAvailable}.{' '}\n {t.srInstructions}\n </div>\n )}\n </div>\n );\n};\n\nexport const Search = memo(SearchComponent) as typeof SearchComponent;\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { FunctionComponent } from 'preact/compat';\nimport { QuickOrderDisabledOverlayProps } from '@/b2b-quick-order/types';\nimport '@/b2b-quick-order/components/QuickOrderDisabledOverlay/QuickOrderDisabledOverlay.css';\n\nexport const QuickOrderDisabledOverlay: FunctionComponent<\n QuickOrderDisabledOverlayProps\n> = ({ isDisabled, message, children }) => {\n return (\n <div className=\"b2b-quick-order-disabled-overlay\">\n <div\n className=\"b2b-quick-order-disabled-overlay__content\"\n style={{ pointerEvents: isDisabled ? 'none' : 'auto' }}\n >\n {children}\n </div>\n {isDisabled && (\n <>\n <div className=\"b2b-quick-order-disabled-overlay__blur\" />\n <div className=\"b2b-quick-order-disabled-overlay__message\">\n {message}\n </div>\n </>\n )}\n </div>\n );\n};\n"],"names":["CsvFileInputComponent","t","onFileUpload","error","fileName","onDownloadSample","showSampleDownload","disabled","handleFileChange","useCallback","e","file","_a","jsxs","jsx","Fragment","InputFile","CsvFileInput","memo","SEARCH_FILTER","handleSearchBlur","options","containerRef","itemSelected","initialValue","currentValue","onValueRestore","onClose","activeElement","createBlurHandler","delay","clearBlurTimeout","timeoutRef","handleArrowDown","currentIndex","itemsLength","handleArrowUp","handleHomeKey","handleEndKey","handleEnterKey","activeIndex","items","onItemSelect","handleEscapeKey","inputRef","useItemSearch","productsSearch","initialSku","replaceItemSku","searchFilter","searchValue","setSearchValue","useState","searchResults","setSearchResults","isTouched","setIsTouched","isMountedRef","useRef","useEffect","debouncedSearch","useMemo","debounce","searchTerm","result","handleSearchChange","value","resetSearch","handleItemClick","clickedItem","itemData","events","useSearch","onChange","shouldShowResults","onItemClick","setActiveIndex","setInitialValue","setItemSelected","isClosedManually","setIsClosedManually","resultsId","itemRefs","blurTimeoutRef","isOpen","showResults","showEmptyState","element","handleChange","createItemClickHandler","item","handleFocus","handleBlur","restoredValue","handleKeyDown","prev","getActiveDescendant","QuickOrderItemsListComponent","onRemove","clearItems","onUpdateQuantity","slots","handleAddToCart","isItemUpdating","loading","isDisabledButton","classes","CartList","QuickOrderListItem","Divider","Search","Slot","Button","QuickOrderItemsList","QuickOrderListItemComponent","isUpdating","scope","currentSku","formName","isValid","hasOptions","hasRequiredOptions","option","hasSelectedOptions","optionItem","allRequiredOptionsSelected","mainImage","img","handleRemove","handleQuantityChange","newQty","form","qtyInput","searchSlot","CartItem","_b","PriceRange","AccordionSection","cursorStyle","defaultCursorStyle","SearchComponent","className","Input","index","el","QuickOrderDisabledOverlay","isDisabled","message","children"],"mappings":"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"}
1
+ {"version":3,"file":"QuickOrderDisabledOverlay.js","sources":["/@dropins/storefront-quick-order/src/configs/search-filter.config.ts","/@dropins/storefront-quick-order/src/lib/searchBlurHandler.ts","/@dropins/storefront-quick-order/src/lib/searchKeyboardNavigation.ts","/@dropins/storefront-quick-order/src/components/CsvFileInput/CsvFileInput.tsx","/@dropins/storefront-quick-order/src/hooks/useItemSearch.tsx","/@dropins/storefront-quick-order/src/hooks/useSearch.tsx","/@dropins/storefront-quick-order/src/components/QuickOrderItemsList/QuickOrderItemsList.tsx","/@dropins/storefront-quick-order/src/components/QuickOrderListItem/QuickOrderListItem.tsx","/@dropins/storefront-quick-order/src/components/Search/Search.tsx","/@dropins/storefront-quick-order/src/components/QuickOrderDisabledOverlay/QuickOrderDisabledOverlay.tsx"],"sourcesContent":["export const SEARCH_FILTER = [\n {\n attribute: 'visibility',\n in: ['Search', 'Catalog, Search'],\n },\n];\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nexport interface BlurHandlerOptions {\n containerRef: HTMLElement | null;\n itemSelected: boolean;\n initialValue: string;\n currentValue: string;\n onValueRestore: (value: string) => void;\n onClose: () => void;\n}\n\n/**\n * Handles blur logic for search component\n * Checks if focus moved outside component and restores initial value if needed\n */\nexport const handleSearchBlur = (options: BlurHandlerOptions): void => {\n const {\n containerRef,\n itemSelected,\n initialValue,\n currentValue,\n onValueRestore,\n onClose,\n } = options;\n\n const activeElement = document.activeElement;\n const isWithinComponent = containerRef?.contains(activeElement);\n\n if (!isWithinComponent) {\n onClose();\n\n if (!itemSelected && initialValue !== currentValue) {\n onValueRestore(initialValue);\n }\n }\n};\n\n/**\n * Creates a blur handler with timeout\n */\nexport const createBlurHandler = (\n options: BlurHandlerOptions,\n delay: number = 150\n): number => {\n return window.setTimeout(() => {\n handleSearchBlur(options);\n }, delay);\n};\n\n/**\n * Clears blur timeout if exists\n */\nexport const clearBlurTimeout = (timeoutRef: number | null): void => {\n if (timeoutRef) {\n clearTimeout(timeoutRef);\n }\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\n/**\n * WCAG 2.1 compliant keyboard navigation for combobox with listbox pattern.\n * Focus always remains on the input element, visual indication via aria-activedescendant.\n * Reference: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/\n */\n\n/**\n * Calculates next active index when ArrowDown is pressed\n * Returns next index in list or current if at end\n */\nexport const handleArrowDown = (\n currentIndex: number,\n itemsLength: number\n): number => {\n if (itemsLength === 0) return -1;\n return currentIndex < itemsLength - 1 ? currentIndex + 1 : currentIndex;\n};\n\n/**\n * Calculates next active index when ArrowUp is pressed\n * Returns previous index or -1 to return focus to input\n */\nexport const handleArrowUp = (currentIndex: number): number => {\n return currentIndex > 0 ? currentIndex - 1 : -1;\n};\n\n/**\n * Moves visual focus to first item in list (Home key)\n */\nexport const handleHomeKey = (): number => {\n return 0;\n};\n\n/**\n * Moves visual focus to last item in list (End key)\n */\nexport const handleEndKey = (itemsLength: number): number => {\n return Math.max(0, itemsLength - 1);\n};\n\n/**\n * Handles Enter key press on active item\n * Returns true if item was selected, false otherwise\n */\nexport const handleEnterKey = <T>(\n activeIndex: number,\n items: T[],\n onItemSelect: (item: T) => void\n): boolean => {\n if (activeIndex >= 0 && items[activeIndex]) {\n onItemSelect(items[activeIndex]);\n return true;\n }\n return false;\n};\n\n/**\n * Handles Escape key press - restores initial value and closes results\n */\nexport const handleEscapeKey = (\n initialValue: string,\n inputRef: HTMLElement | null,\n onValueRestore: (value: string) => void,\n onClose: () => void\n): void => {\n onValueRestore(initialValue);\n onClose();\n if (inputRef && 'blur' in inputRef && typeof inputRef.blur === 'function') {\n inputRef.blur();\n }\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { FunctionComponent, useCallback, memo } from 'preact/compat';\nimport { InputFile } from '@adobe-commerce/elsie/components';\nimport { CsvFileInputProps } from '@/b2b-quick-order/types/quickOrderCsvUpload.types';\nimport '@/b2b-quick-order/components/CsvFileInput/CsvFileInput.css';\n\nconst CsvFileInputComponent: FunctionComponent<CsvFileInputProps> = ({\n t,\n onFileUpload,\n error,\n fileName,\n onDownloadSample,\n showSampleDownload,\n disabled,\n}) => {\n const handleFileChange = useCallback(\n (e: Event) => {\n const target = e.target as HTMLInputElement;\n const file = target.files?.[0];\n if (file) {\n onFileUpload(file);\n }\n },\n [onFileUpload]\n );\n\n const inputClassName = 'b2b-quick-order-csv-file-input__input';\n\n return (\n <div className=\"b2b-quick-order-csv-file-input\">\n <div className=\"b2b-quick-order-csv-file-input__title\">{t.title}</div>\n\n <div className=\"b2b-quick-order-csv-file-input__helper\">\n {t.helperText}\n {showSampleDownload && (\n <>\n <button\n type=\"button\"\n className=\"b2b-quick-order-csv-file-input__download-link\"\n onClick={onDownloadSample}\n data-testid=\"download-sample\"\n disabled={disabled}\n >\n {t.downloadSample}\n </button>\n </>\n )}\n </div>\n\n <div\n className={`b2b-quick-order-csv-file-input__input-wrapper ${\n disabled\n ? 'b2b-quick-order-csv-file-input__input-wrapper--disabled'\n : ''\n }`}\n >\n <InputFile\n id={'quick-order-csv-file-input'}\n label={t.inputLabel}\n className={inputClassName}\n onChange={handleFileChange}\n accept={'.csv'}\n disabled={disabled}\n />\n </div>\n\n {fileName && (\n <div\n className=\"b2b-quick-order-csv-file-input__file-name\"\n data-testid=\"file-name\"\n >\n {t.selectedFile}: {fileName}\n </div>\n )}\n\n {error && (\n <div\n className=\"b2b-quick-order-csv-file-input__error\"\n data-testid=\"error-message\"\n role=\"alert\"\n >\n {error}\n </div>\n )}\n </div>\n );\n};\n\nexport const CsvFileInput = memo(CsvFileInputComponent);\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport {\n useCallback,\n useState,\n useMemo,\n useRef,\n useEffect,\n} from 'preact/hooks';\nimport { debounce } from '@adobe-commerce/elsie/lib/debounce';\nimport { OrderItem, UseItemSearchProps } from '@/b2b-quick-order/types';\nimport { events } from '@adobe-commerce/event-bus';\nimport { SEARCH_FILTER } from '@/b2b-quick-order/configs';\n\nexport const useItemSearch = ({\n productsSearch,\n initialSku,\n replaceItemSku,\n searchFilter = SEARCH_FILTER,\n}: UseItemSearchProps) => {\n const [searchValue, setSearchValue] = useState(initialSku);\n const [searchResults, setSearchResults] = useState<OrderItem[]>([]);\n const [isTouched, setIsTouched] = useState(false);\n\n // Track if component is mounted to prevent state updates after unmount\n const isMountedRef = useRef(true);\n\n useEffect(() => {\n return () => {\n isMountedRef.current = false;\n };\n }, []);\n\n // Update search value when initialSku changes (e.g., after merge)\n useEffect(() => {\n if (!isTouched) {\n setSearchValue(initialSku);\n }\n }, [initialSku, isTouched]);\n\n const debouncedSearch = useMemo(\n () =>\n debounce(async (searchTerm: string) => {\n if (!searchTerm || !productsSearch) {\n if (isMountedRef.current) {\n setSearchResults([]);\n }\n return;\n }\n\n try {\n const result = await productsSearch({\n phrase: searchTerm,\n filter: searchFilter,\n });\n if (isMountedRef.current) {\n setSearchResults(result.items || []);\n }\n } catch (error) {\n console.error('Error searching products:', error);\n if (isMountedRef.current) {\n setSearchResults([]);\n }\n }\n }, 300),\n [productsSearch, searchFilter]\n );\n\n const handleSearchChange = useCallback(\n (e: Event) => {\n const target = e.target as HTMLInputElement;\n const value = target.value;\n setSearchValue(value);\n setIsTouched(true);\n debouncedSearch(value);\n },\n [debouncedSearch]\n );\n\n const resetSearch = useCallback(() => {\n setSearchValue('');\n setSearchResults([]);\n setIsTouched(false);\n }, []);\n\n const handleItemClick = useCallback(\n (clickedItem: OrderItem) => {\n // Build item data for emission\n // Just send the data as-is from the search result\n // The deduplication logic will handle matching correctly\n const itemData = {\n sku: clickedItem.sku,\n ...(clickedItem.variantSku && { variantSku: clickedItem.variantSku }),\n quantity: 1,\n ...(replaceItemSku && { replaceItemSku }),\n };\n\n events.emit('quick-order/add-items', [itemData]);\n resetSearch();\n },\n [replaceItemSku, resetSearch]\n );\n\n return {\n searchValue,\n searchResults,\n handleSearchChange,\n shouldShowResults: isTouched,\n resetSearch,\n handleItemClick,\n };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport React, { useCallback, useState, useRef, useEffect } from 'preact/compat';\nimport { SearchItem } from '@/b2b-quick-order/types/search.types';\nimport {\n createBlurHandler,\n clearBlurTimeout,\n handleArrowDown,\n handleArrowUp,\n handleEnterKey,\n handleEscapeKey,\n handleHomeKey,\n handleEndKey,\n} from '@/b2b-quick-order/lib';\n\nexport interface UseSearchOptions<T extends SearchItem> {\n value: string;\n onChange?: (e: any) => void;\n items: T[];\n shouldShowResults?: boolean;\n onItemClick?: (item: T) => void;\n}\n\nexport interface UseSearchReturn<T extends SearchItem> {\n // State\n activeIndex: number;\n showResults: boolean;\n showEmptyState: boolean;\n\n // Refs\n resultsId: React.MutableRefObject<string>;\n inputRef: React.RefObject<HTMLInputElement>;\n itemRefs: React.MutableRefObject<(HTMLDivElement | null)[]>;\n containerRef: React.RefObject<HTMLDivElement>;\n\n // Handlers\n handleChange: (e: any) => void;\n handleFocus: () => void;\n handleBlur: () => void;\n handleKeyDown: (e: KeyboardEvent) => void;\n createItemClickHandler: (item: T) => () => void;\n getActiveDescendant: () => string | undefined;\n}\n\nexport const useSearch = <T extends SearchItem = SearchItem>({\n value,\n onChange,\n items,\n shouldShowResults = true,\n onItemClick,\n}: UseSearchOptions<T>): UseSearchReturn<T> => {\n const [activeIndex, setActiveIndex] = useState(-1);\n const [initialValue, setInitialValue] = useState('');\n const [itemSelected, setItemSelected] = useState(false);\n const [isClosedManually, setIsClosedManually] = useState(false);\n\n const resultsId = useRef(\n `search-results-${Math.random().toString(36).substr(2, 9)}`\n );\n const inputRef = useRef<HTMLInputElement>(null);\n const itemRefs = useRef<(HTMLDivElement | null)[]>([]);\n const containerRef = useRef<HTMLDivElement>(null);\n const blurTimeoutRef = useRef<number | null>(null);\n\n const isOpen = Boolean(value) && !isClosedManually;\n const showResults = shouldShowResults && isOpen && items.length > 0;\n const showEmptyState = shouldShowResults && isOpen && items.length === 0;\n\n useEffect(() => {\n setActiveIndex(-1);\n // Don't reset isClosedManually here - only reset on focus\n // This prevents results from reopening after Tab\n }, [items]);\n\n useEffect(() => {\n return () => {\n clearBlurTimeout(blurTimeoutRef.current);\n };\n }, []);\n\n useEffect(() => {\n // Auto-scroll active item into view when navigating with keyboard\n if (activeIndex >= 0 && itemRefs.current[activeIndex]) {\n const element = itemRefs.current[activeIndex];\n if (element && typeof element.scrollIntoView === 'function') {\n element.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n });\n }\n }\n }, [activeIndex]);\n\n const handleChange = useCallback(\n (e: any) => {\n // Reset isClosedManually when user types\n if (isClosedManually) {\n setIsClosedManually(false);\n }\n onChange?.(e);\n },\n [onChange, isClosedManually]\n );\n\n const createItemClickHandler = useCallback(\n (item: T) => () => {\n setItemSelected(true);\n setIsClosedManually(true);\n onItemClick?.(item);\n setActiveIndex(-1);\n },\n [onItemClick]\n );\n\n const handleFocus = useCallback(() => {\n clearBlurTimeout(blurTimeoutRef.current);\n blurTimeoutRef.current = null;\n setInitialValue(value || '');\n setItemSelected(false);\n setIsClosedManually(false);\n }, [value]);\n\n const handleBlur = useCallback(() => {\n blurTimeoutRef.current = createBlurHandler({\n containerRef: containerRef.current,\n itemSelected,\n initialValue,\n currentValue: value || '',\n onValueRestore: (restoredValue) => {\n onChange?.({ target: { value: restoredValue } } as any);\n },\n onClose: () => {\n setIsClosedManually(true);\n },\n });\n }, [itemSelected, initialValue, value, onChange]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (!showResults) return;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n setActiveIndex((prev) => handleArrowDown(prev, items.length));\n break;\n case 'ArrowUp':\n e.preventDefault();\n setActiveIndex((prev) => handleArrowUp(prev));\n break;\n case 'Home':\n if (showResults && items.length > 0) {\n e.preventDefault();\n setActiveIndex(handleHomeKey());\n }\n break;\n case 'End':\n if (showResults && items.length > 0) {\n e.preventDefault();\n setActiveIndex(handleEndKey(items.length));\n }\n break;\n case 'Tab':\n clearBlurTimeout(blurTimeoutRef.current);\n blurTimeoutRef.current = null;\n setIsClosedManually(true);\n onChange?.({ target: { value: initialValue } } as any);\n break;\n case 'Enter': {\n const wasHandled = handleEnterKey(activeIndex, items, (item) => {\n setItemSelected(true);\n setIsClosedManually(true);\n onItemClick?.(item);\n setActiveIndex(-1);\n });\n if (wasHandled) {\n e.preventDefault();\n }\n break;\n }\n case 'Escape':\n e.preventDefault();\n handleEscapeKey(\n initialValue,\n inputRef.current,\n (restoredValue) => {\n onChange?.({ target: { value: restoredValue } } as any);\n setActiveIndex(-1);\n setIsClosedManually(true);\n },\n () => {\n setIsClosedManually(true);\n }\n );\n break;\n }\n },\n [showResults, items, activeIndex, onItemClick, onChange, initialValue]\n );\n\n const getActiveDescendant = useCallback(() => {\n if (activeIndex >= 0 && showResults) {\n return `${resultsId.current}-item-${activeIndex}`;\n }\n return undefined;\n }, [activeIndex, showResults]);\n\n return {\n activeIndex,\n showResults,\n showEmptyState,\n resultsId,\n inputRef,\n itemRefs,\n containerRef,\n handleChange,\n handleFocus,\n handleBlur,\n handleKeyDown,\n createItemClickHandler,\n getActiveDescendant,\n };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { FunctionComponent, memo } from 'preact/compat';\nimport { Button, CartList, Divider } from '@adobe-commerce/elsie/components';\nimport { classes } from '@adobe-commerce/elsie/lib/classes';\nimport { QuickOrderItemsListProps } from '@/b2b-quick-order/types';\nimport { Slot } from '@adobe-commerce/elsie/lib';\nimport { QuickOrderListItem, Search } from '@/b2b-quick-order/components';\nimport { useItemSearch } from '@/b2b-quick-order/hooks';\nimport '@/b2b-quick-order/components/QuickOrderItemsList/QuickOrderItemsList.css';\n\nconst QuickOrderItemsListComponent: FunctionComponent<\n QuickOrderItemsListProps\n> = ({\n t,\n items,\n onRemove,\n clearItems,\n onUpdateQuantity,\n slots,\n handleAddToCart,\n isItemUpdating,\n loading,\n isDisabledButton,\n productsSearch,\n searchFilter,\n}) => {\n const {\n searchValue,\n searchResults,\n handleSearchChange,\n shouldShowResults,\n handleItemClick,\n } = useItemSearch({\n productsSearch,\n initialSku: '',\n searchFilter,\n });\n\n return (\n <div\n className={classes(['b2b-quick-order-form-quick-order-items-list'])}\n role=\"region\"\n aria-label={t.title}\n >\n <div className=\"b2b-quick-order-form-quick-order-items-list__title\">\n {t.title}\n </div>\n\n {items.length > 0 && (\n <>\n <CartList\n role=\"list\"\n className=\"b2b-quick-order-form-quick-order-items-list__list\"\n >\n {items.map((item) => (\n <QuickOrderListItem\n key={item.id || item.sku}\n item={item}\n t={t}\n onRemove={onRemove}\n onUpdateQuantity={onUpdateQuantity}\n isUpdating={isItemUpdating?.(item.variantSku || item.sku)}\n loading={loading}\n productsSearch={productsSearch}\n searchFilter={searchFilter}\n slots={slots}\n />\n ))}\n </CartList>\n <Divider variant={'secondary'} />\n </>\n )}\n <div className=\"b2b-quick-order-form-quick-order-items-list__global-search\">\n <Search\n t={t}\n onChange={handleSearchChange}\n items={searchResults}\n value={searchValue}\n shouldShowResults={shouldShowResults}\n onItemClick={handleItemClick}\n className=\"b2b-quick-order-form-quick-order-items-list__search\"\n />\n </div>\n {items.length === 0 && (\n <div\n className=\"b2b-quick-order-form-quick-order-items-list__empty\"\n data-testid=\"empty-items\"\n >\n {t.emptyList}\n </div>\n )}\n <Slot\n slot={slots?.AddAllToCartButton}\n name=\"AddAllToCartButton\"\n context={{\n handleAddToCart,\n clearItems,\n loading,\n isDisabledButton,\n }}\n data-testid=\"addAllToCart\"\n >\n <div className=\"b2b-quick-order-form-quick-order-items-list__actions\">\n <Button\n variant=\"primary\"\n onClick={handleAddToCart}\n data-testid=\"add-all-to-cart-button\"\n disabled={loading || isDisabledButton}\n >\n {t.addAllToCart}\n </Button>\n </div>\n </Slot>\n </div>\n );\n};\n\nexport const QuickOrderItemsList = memo(QuickOrderItemsListComponent);\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { FunctionComponent, useMemo, useCallback, memo } from 'preact/compat';\nimport {\n CartItem,\n AccordionSection,\n PriceRange,\n} from '@adobe-commerce/elsie/components';\nimport { Slot } from '@adobe-commerce/elsie/lib';\nimport { QuickOrderListItemProps } from '@/b2b-quick-order/types';\nimport { useItemSearch } from '@/b2b-quick-order/hooks';\nimport '@/b2b-quick-order/components/QuickOrderListItem/QuickOrderListItem.css';\nimport { Search } from '@/b2b-quick-order/components';\n\nconst QuickOrderListItemComponent: FunctionComponent<\n QuickOrderListItemProps\n> = ({\n item,\n t,\n onRemove,\n onUpdateQuantity,\n isUpdating,\n loading,\n productsSearch,\n searchFilter,\n slots,\n}) => {\n // Generate unique scope identifier Dropins - use item.id if available to distinguish multiple items with same sku\n const scope = `quick-order-item-${item.id || item.variantSku || item.sku}`;\n const currentSku = item?.variantSku ?? item?.sku;\n\n const {\n searchValue,\n searchResults,\n handleSearchChange,\n shouldShowResults,\n handleItemClick,\n } = useItemSearch({\n productsSearch,\n initialSku: currentSku,\n replaceItemSku: item.sku,\n searchFilter,\n });\n\n const formName = `form-${item.id || currentSku}`;\n const isValid = item.inStock && item.addToCartAllowed;\n const hasOptions = item.options && item.options.length > 0;\n\n const hasRequiredOptions = useMemo(\n () => hasOptions && item.options.some((option) => option.required),\n [hasOptions, item.options]\n );\n\n // Check if all required options are selected\n const allRequiredOptionsSelected = useMemo(() => {\n if (!hasOptions) return true;\n\n if (hasRequiredOptions) {\n // If there are required options, check that all required ones are selected\n // (optional options can be left unselected)\n return item.options.every((option) => {\n if (!option.required) return true; // Skip optional options\n return (\n option.items && option.items.some((optionItem) => optionItem.selected)\n );\n });\n }\n\n // If NO required options, ALL options must be selected to close accordion\n return item.options.every((option) => {\n return (\n option.items && option.items.some((optionItem) => optionItem.selected)\n );\n });\n }, [hasOptions, hasRequiredOptions, item.options]);\n\n const mainImage = useMemo(\n () => item.images?.find((img) => img.roles?.includes('image')),\n [item.images]\n );\n\n // Memoize handlers\n const handleRemove = useCallback(() => {\n // Use item.id if available, otherwise fall back to sku\n onRemove?.(item.id || item.sku);\n }, [onRemove, item.id, item.sku]);\n\n const handleQuantityChange = useCallback(\n (newQty: number) => {\n onUpdateQuantity?.(currentSku, newQty);\n // Update hidden quantity field\n const form = document.forms[formName as any] as HTMLFormElement;\n if (form) {\n const qtyInput = form.querySelector(\n 'input[name=\"quantity\"]'\n ) as HTMLInputElement;\n if (qtyInput) qtyInput.value = String(newQty);\n }\n },\n [onUpdateQuantity, currentSku, formName]\n );\n\n const searchSlot = (\n <Slot\n name=\"QuickOrderItemSearch\"\n slot={slots?.QuickOrderItemSearch}\n context={{\n item,\n scope,\n handleSearchChange,\n searchResults,\n searchValue,\n shouldShowResults,\n handleItemClick,\n }}\n >\n <Search\n t={t}\n onChange={handleSearchChange}\n items={searchResults}\n value={searchValue}\n shouldShowResults={shouldShowResults}\n className=\"b2b-quick-order-form-quick-order-items__item-search\"\n onItemClick={handleItemClick}\n slots={slots}\n />\n </Slot>\n );\n\n if (!item.name && !item.images?.length) {\n return (\n <form\n key={item.sku}\n name={formName}\n className=\"b2b-quick-order-form-quick-order-items__item-form\"\n onSubmit={(e) => e.preventDefault()}\n data-sku={item.sku}\n >\n <input type=\"hidden\" name=\"sku\" value={item.sku} />\n <input type=\"hidden\" name=\"quantity\" value={item.quantity} />\n <input type=\"hidden\" name=\"valid\" value=\"false\" />\n <input type=\"hidden\" name=\"productType\" value=\"\" />\n {item.parentSku && <input type=\"hidden\" name=\"parentSku\" value={item.parentSku} />}\n {searchSlot}\n\n <CartItem\n sku={<span>{item.sku}</span>}\n title={<span>{t.productNotFound}</span>}\n quantity={item.quantity}\n alert={\n <div className=\"b2b-quick-order-items__error\">\n {t.productNotFoundDescription?.replace('{sku}', item.sku)}\n </div>\n }\n disabled={loading}\n onRemove={handleRemove}\n ariaLabel={`${t.productNotFound} - ${item.sku}`}\n />\n </form>\n );\n }\n\n return (\n <form\n key={currentSku}\n name={formName}\n className=\"b2b-quick-order-form-quick-order-items__item-form\"\n onSubmit={(e) => e.preventDefault()}\n data-sku={currentSku}\n >\n <input type=\"hidden\" name=\"sku\" value={currentSku} />\n <input type=\"hidden\" name=\"quantity\" value={item.quantity} />\n <input type=\"hidden\" name=\"valid\" value={isValid ? 'true' : 'false'} />\n <input type=\"hidden\" name=\"productType\" value={item.productType || ''} />\n {item.id && <input type=\"hidden\" name=\"itemId\" value={item.id} />}\n {item.parentSku && <input type=\"hidden\" name=\"parentSku\" value={item.parentSku} />}\n {searchSlot}\n <CartItem\n title={<span>{item.name}</span>}\n sku={<span>{currentSku}</span>}\n image={\n mainImage ? (\n <img src={mainImage.url} alt={mainImage.label || item.name} />\n ) : undefined\n }\n price={\n <Slot\n name=\"ProductPrice\"\n slot={slots?.ProductPrice}\n context={{\n item,\n scope,\n }}\n >\n <PriceRange\n minimumAmount={item.prices.final.minimumAmount}\n maximumAmount={item.prices.final.maximumAmount}\n amount={item.prices.final.amount}\n currency={item.prices.final.currency}\n />\n </Slot>\n }\n quantity={item.quantity}\n alert={\n item.inStock === false ? (\n <div className=\"b2b-quick-order-items__alert\">{t.outOfStock}</div>\n ) : undefined\n }\n warning={\n hasOptions && !allRequiredOptionsSelected ? (\n <div className=\"b2b-quick-order-items__warning\">\n {t.configurableOptionsWarning}\n </div>\n ) : undefined\n }\n footer={\n hasOptions ? (\n <AccordionSection\n title={t.productOptions}\n ariaLabelTitle={t.productOptions}\n defaultOpen={!allRequiredOptionsSelected}\n className=\"b2b-quick-order-list-item__accordion\"\n actionIconPosition=\"left\"\n >\n <Slot\n name=\"ProductOptions\"\n slot={slots?.ProductOptions}\n context={{\n item,\n scope,\n }}\n >\n <div className=\"b2b-quick-order-items__configurable-error\">\n {t.configurableProductErrorDescription}\n </div>\n </Slot>\n </AccordionSection>\n ) : undefined\n }\n updating={isUpdating}\n disabled={loading}\n loading={loading}\n onRemove={handleRemove}\n onQuantity={handleQuantityChange}\n ariaLabel={`${item.name} - ${item.sku}`}\n />\n </form>\n );\n};\n\nexport const QuickOrderListItem = memo(QuickOrderListItemComponent);\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { memo } from 'preact/compat';\nimport { Input } from '@adobe-commerce/elsie/components';\nimport { classes } from '@adobe-commerce/elsie/lib/classes';\nimport { SearchProps, SearchItem } from '@/b2b-quick-order/types/search.types';\nimport { useSearch } from '@/b2b-quick-order/hooks/useSearch';\nimport '@/b2b-quick-order/components/Search/Search.css';\nimport { Slot } from '@adobe-commerce/elsie/lib';\n\nconst cursorStyle = { cursor: 'pointer' as const };\nconst defaultCursorStyle = { cursor: 'default' as const };\n\nconst SearchComponent = <T extends SearchItem = SearchItem>({\n t,\n value,\n onChange,\n items,\n shouldShowResults = true,\n className,\n onItemClick,\n slots,\n}: SearchProps<T>) => {\n const {\n activeIndex,\n showResults,\n showEmptyState,\n resultsId,\n inputRef,\n itemRefs,\n containerRef,\n handleChange,\n handleFocus,\n handleBlur,\n handleKeyDown,\n createItemClickHandler,\n getActiveDescendant,\n } = useSearch({\n value,\n onChange,\n items,\n shouldShowResults,\n onItemClick,\n });\n\n return (\n <div\n ref={containerRef}\n className={classes(['b2b-quick-order-search', className])}\n >\n <Input\n ref={inputRef}\n className=\"b2b-quick-order-search__input\"\n value={value}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n placeholder={t.searchPlaceholder}\n aria-label={t.searchAriaLabel}\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded={showResults}\n aria-controls={resultsId.current}\n aria-activedescendant={getActiveDescendant()}\n onKeyDown={handleKeyDown}\n />\n\n {showResults && (\n <div\n id={resultsId.current}\n role=\"listbox\"\n className=\"b2b-quick-order-search__results\"\n aria-label={t.searchAriaLabel}\n >\n {items.map((item, index) => (\n <Slot\n key={item.sku}\n slot={slots?.QuickOrderSearchAutocompleteItem}\n name={'QuickOrderSearchAutocompleteItem'}\n context={{\n item,\n index,\n createItemClickHandler,\n activeIndex,\n }}\n >\n <div\n id={`${resultsId.current}-item-${index}`}\n ref={(el) => (itemRefs.current[index] = el)}\n role=\"option\"\n aria-selected={index === activeIndex}\n className={classes([\n 'b2b-quick-order-search__result-item',\n index === activeIndex &&\n 'b2b-quick-order-search__result-item--active',\n ])}\n onClick={createItemClickHandler(item)}\n style={onItemClick ? cursorStyle : defaultCursorStyle}\n >\n {`${item.sku} ${item.name}`}\n </div>\n </Slot>\n ))}\n </div>\n )}\n\n {showEmptyState && (\n <div\n className=\"b2b-quick-order-search__empty-state\"\n role=\"status\"\n aria-live=\"polite\"\n >\n {t.searchEmptyState}\n </div>\n )}\n\n {showResults && (\n <div\n className=\"sr-only\"\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n >\n {items.length}{' '}\n {items.length === 1 ? t.resultAvailable : t.resultsAvailable}.{' '}\n {t.srInstructions}\n </div>\n )}\n </div>\n );\n};\n\nexport const Search = memo(SearchComponent) as typeof SearchComponent;\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { FunctionComponent } from 'preact/compat';\nimport { QuickOrderDisabledOverlayProps } from '@/b2b-quick-order/types';\nimport '@/b2b-quick-order/components/QuickOrderDisabledOverlay/QuickOrderDisabledOverlay.css';\n\nexport const QuickOrderDisabledOverlay: FunctionComponent<\n QuickOrderDisabledOverlayProps\n> = ({ isDisabled, message, children }) => {\n return (\n <div className=\"b2b-quick-order-disabled-overlay\">\n <div\n className=\"b2b-quick-order-disabled-overlay__content\"\n style={{ pointerEvents: isDisabled ? 'none' : 'auto' }}\n >\n {children}\n </div>\n {isDisabled && (\n <>\n <div className=\"b2b-quick-order-disabled-overlay__blur\" />\n <div className=\"b2b-quick-order-disabled-overlay__message\">\n {message}\n </div>\n </>\n )}\n </div>\n );\n};\n"],"names":["SEARCH_FILTER","handleSearchBlur","options","containerRef","itemSelected","initialValue","currentValue","onValueRestore","onClose","activeElement","createBlurHandler","delay","clearBlurTimeout","timeoutRef","handleArrowDown","currentIndex","itemsLength","handleArrowUp","handleHomeKey","handleEndKey","handleEnterKey","activeIndex","items","onItemSelect","handleEscapeKey","inputRef","CsvFileInputComponent","t","onFileUpload","error","fileName","onDownloadSample","showSampleDownload","disabled","handleFileChange","useCallback","e","file","_a","jsxs","jsx","Fragment","InputFile","CsvFileInput","memo","useItemSearch","productsSearch","initialSku","replaceItemSku","searchFilter","searchValue","setSearchValue","useState","searchResults","setSearchResults","isTouched","setIsTouched","isMountedRef","useRef","useEffect","debouncedSearch","useMemo","debounce","searchTerm","result","handleSearchChange","value","resetSearch","handleItemClick","clickedItem","itemData","events","useSearch","onChange","shouldShowResults","onItemClick","setActiveIndex","setInitialValue","setItemSelected","isClosedManually","setIsClosedManually","resultsId","itemRefs","blurTimeoutRef","isOpen","showResults","showEmptyState","element","handleChange","createItemClickHandler","item","handleFocus","handleBlur","restoredValue","handleKeyDown","prev","getActiveDescendant","QuickOrderItemsListComponent","onRemove","clearItems","onUpdateQuantity","slots","handleAddToCart","isItemUpdating","loading","isDisabledButton","classes","CartList","QuickOrderListItem","Divider","Search","Slot","Button","QuickOrderItemsList","QuickOrderListItemComponent","isUpdating","scope","currentSku","formName","isValid","hasOptions","hasRequiredOptions","option","allRequiredOptionsSelected","optionItem","mainImage","img","handleRemove","handleQuantityChange","newQty","form","qtyInput","searchSlot","CartItem","_b","PriceRange","AccordionSection","cursorStyle","defaultCursorStyle","SearchComponent","className","Input","index","el","QuickOrderDisabledOverlay","isDisabled","message","children"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  /*! Copyright 2026 Adobe
2
2
  All Rights Reserved. */
3
- import{jsx as v,jsxs as D}from"@dropins/tools/preact-jsx-runtime.js";import{AlertBanner as rr}from"@dropins/tools/components.js";import{Q as tr,a as er}from"../chunks/QuickOrderDisabledOverlay.js";import{classes as P}from"@dropins/tools/lib.js";import"../chunks/debounce.js";import{useState as R,useRef as J,useCallback as A,useEffect as y}from"@dropins/tools/preact-hooks.js";import{events as S}from"@dropins/tools/event-bus.js";import{useText as z}from"@dropins/tools/i18n.js";import"@dropins/tools/preact-compat.js";import{c as nr}from"../chunks/getStoreConfig.js";import"@dropins/tools/fetch-graphql.js";const sr=["sku","parentSku","quantity","optionsUIDs","valid","productType"],ir=e=>{const t=[],r=[];return e.forEach((n,u)=>{if(sr.includes(u))return;const i=n;i&&i.match(/^[A-Za-z0-9+/=]+$/)?t.push(i):r.push({uid:u,value:i})}),{optionUIDs:t,enteredOptions:r}},or=e=>{const t=Number(e.get("quantity")),r=!t||t<1?1:t,n={sku:e.get("sku"),quantity:r},u=e.get("parentSku");u&&(n.parentSku=u);const{optionUIDs:i,enteredOptions:a}=ir(e);return i.length>0&&(n.optionsUIDs=i),a.length>0&&(n.enteredOptions=a),n},_={sku:"",quantity:1,name:"",images:[],inStock:!1,addToCartAllowed:!1,isBundle:!1,prices:{},attributes:[],options:[],url:"",urlKey:"",externalId:"",productType:"simple",shortDescription:"",metaDescription:"",metaKeyword:"",metaTitle:"",description:""},L=(e,t)=>!t||!Array.isArray(t)?e.map(r=>({..._,sku:r.sku,quantity:r.quantity??1})):e.map(r=>{const n=t.find(u=>(u==null?void 0:u.sku)===(r==null?void 0:r.sku));return n?{...n,...r.variantSku&&{variantSku:r.variantSku},quantity:r.quantity??1}:{..._,sku:r.sku,...r.variantSku&&{variantSku:r.variantSku},quantity:r.quantity??1}}),K=e=>e.length===0?!1:e.every(t=>!((t.urlKey||t.url)&&t.name)||t.inStock===!1?!1:t.options&&t.options.length>0?t.options.some(i=>i.required)?t.options.every(i=>{var a;return i.required?(a=i.items)==null?void 0:a.some(l=>l.selected):!0}):t.options.some(i=>i.items&&i.items.length>0&&i.items.some(a=>a.selected===!0)):!0),x=e=>{const t=[];return e.forEach(r=>{if(!((r.urlKey||r.url)&&r.name)){t.push({sku:r.sku,name:r.name||"Unknown",reason:"incomplete_data"});return}if(r.inStock===!1){t.push({sku:r.sku,name:r.name,reason:"out_of_stock"});return}if(r.options&&r.options.length>0){if(r.options.some(a=>a.required)){r.options.every(l=>{var h;return l.required?(h=l.items)==null?void 0:h.some(Q=>Q.selected):!0})||t.push({sku:r.sku,name:r.name,reason:"missing_required_options"});return}r.options.some(a=>a.items&&a.items.length>0&&a.items.some(l=>l.selected===!0))||t.push({sku:r.sku,name:r.name,reason:"missing_options"})}}),t},w=e=>`quick-order-item-${e.id||e.variantSku||e.sku}`,W=e=>`${e}-${Date.now()}-${Math.random().toString(36).substring(2,9)}`,j=(e,t)=>e.findIndex(r=>t.variantSku&&r.variantSku?r.variantSku===t.variantSku:r.variantSku&&!t.variantSku&&t.sku?r.variantSku===t.sku:t.variantSku&&!r.variantSku&&r.sku?r.sku===t.variantSku:!t.variantSku&&!r.variantSku?r.sku===t.sku:!1),ar=(e,t,r)=>e.findIndex(n=>n.id===r?!1:t.variantSku&&n.variantSku?n.variantSku===t.variantSku:t.variantSku&&!n.variantSku&&n.sku?n.sku===t.variantSku:!1),ur=(e,t,r,n=1)=>e.map((u,i)=>i===r?{...u,quantity:u.quantity+n}:i===t?null:u).filter(Boolean),cr=(e,t,r)=>{const n=[...e],u=[],i=[],a=[];return t.forEach((l,h)=>{const Q=r[h];if(Q!=null&&Q.replaceItemSku){const p=n.findIndex(g=>g.sku===Q.replaceItemSku||g.id===Q.replaceItemSku);if(p!==-1){const g=j(n,l);if(g!==-1&&g!==p){n.splice(p,1);const O=g>p?g-1:g;n[O]={...n[O],quantity:n[O].quantity+l.quantity},a.push(n[O])}else{const O={...l,id:W(l.sku)};n[p]=O,i.push(O)}return}}const q=j(n,l);if(q!==-1)n[q]={...n[q],quantity:n[q].quantity+l.quantity},a.push(n[q]);else{const p={...l,id:W(l.sku)};n.push(p),u.push(p)}}),{updatedItems:n,addedItems:u,replacedItems:i,mergedItems:a}},dr=(e,t,r,n=1)=>{const u=t?ar(e,r,t):-1;if(u!==-1){const a=e.findIndex(l=>l.id===t);return{updatedItems:ur(e,a,u,n),wasMerged:!0,mergedIntoIndex:u}}return{updatedItems:e.map(a=>t&&a.id===t?{...a,...r,id:t}:!t&&a.sku===r.sku?{...a,...r}:a),wasMerged:!1}},lr=e=>e.map(t=>{const r=t.id||t.sku,n=document.forms[`form-${r}`];if(!n)return null;const u=new FormData(n);return u.get("valid")==="true"?or(u):null}),kr=e=>{let t=[];return e&&typeof e=="object"?e.optionsUIDs&&Array.isArray(e.optionsUIDs)?t=e.optionsUIDs:Array.isArray(e)&&(t=e):typeof e=="string"&&(t=[e]),t},G=e=>{try{const t=localStorage.getItem(e);if(t)return JSON.parse(t)}catch(t){console.error("Error reading from localStorage:",t)}return{}},fr=(e,t,r)=>{if(r.length!==0)try{const n=G(e);n[t]=r,localStorage.setItem(e,JSON.stringify(n))}catch(n){console.error("Error saving to localStorage:",n)}},pr=(e,t,r)=>e.map(n=>{const u=t.find(i=>n.sku===i.sku||n.sku===i.variantSku);if(u){const i=u.id||u.sku,a=r[i];if(a&&a.length>0)return{...n,optionsUIDs:a}}return n}),mr=e=>{const t=!e.inStock||!e.addToCartAllowed;if(e.options&&e.options.length>0){if(e.options.some(i=>!i.items||i.items.length===0))return!0;if(e.options.some(i=>i.required)){const i=e.options.every(a=>{var l;return a.required?(l=a.items)==null?void 0:l.some(h=>h.selected):!0});return t||!i}const u=e.options.some(i=>i.items&&i.items.length>0&&i.items.some(a=>a.selected===!0));return t||!u}return t},hr=({getProductsData:e,handleAddToCart:t}={})=>{const[r,n]=R([]),[u,i]=R(!1),[a,l]=R(new Set),[h,Q]=R(!1),[q,p]=R(null),[g,O]=R([]),C=J([]),I=z({validationError:"QuickOrder.QuickOrderItem.notification.validationError",backendError:"QuickOrder.QuickOrderItem.notification.backendError",success:"QuickOrder.QuickOrderItem.notification.success",partialSuccess:"QuickOrder.QuickOrderItem.notification.partialSuccess",unexpectedError:"QuickOrder.QuickOrderItem.notification.unexpectedError"}),B="quick-order-selected-options",F=A(()=>{p(null)},[]),b=A(s=>{Q(s)},[]);y(()=>{const s=S.on("quick-order/loading",o=>{i(o)},{eager:!0});return()=>{s==null||s.off()}},[]),y(()=>{const s=S.on("quick-order/add-items",async o=>{if(o&&o.length>0){if(!e)return;i(!0),S.emit("quick-order/loading",!0);const k=o.map(d=>d.sku).filter(Boolean);l(d=>new Set([...Array.from(d),...k]));try{let d=[];try{const f=await e(o)??[];b(o.length!==f.length),d=L(o,f)}catch(f){console.error("Error fetching products data:",f),d=L(o,[])}const c=x(d);if(c.length>0){const f=c.map(m=>m.sku);p(m=>{if((m==null?void 0:m.type)==="validation"&&m.clickableSkus){const T=[...new Set([...m.clickableSkus,...f])];return{...m,clickableSkus:T}}return{type:"validation",variant:"warning",message:I.validationError,clickableSkus:f}})}n(f=>{const{updatedItems:m,addedItems:T,mergedItems:H,replacedItems:X}=cr(f,d,o);return X.forEach(E=>{const U=w(E);S.emit(`${U}/pdp/data`,E)}),H.forEach(E=>{const U=w(E);S.emit(`${U}/pdp/data`,E)}),T.forEach(E=>{const U=w(E);S.emit(`${U}/pdp/data`,E)}),m})}finally{i(!1),S.emit("quick-order/loading",!1),l(d=>new Set(Array.from(d).filter(c=>!k.includes(c))))}}},{eager:!0});return()=>{s==null||s.off()}},[e,b]),y(()=>{const s=r.map(o=>{const k=w(o),d=o.id;return S.on(`${k}/pdp/data`,c=>{n(f=>dr(f,d||"",c,o.quantity||1).updatedItems)})});return()=>{s==null||s.forEach(o=>{o==null||o.off()})}},[r]),y(()=>{const s=K(r);b(!s)},[r,b]),y(()=>{p(s=>{if(!s||!s.clickableSkus||s.clickableSkus.length===0)return s;const o=s.clickableSkus.filter(k=>{const d=r.filter(c=>c.sku===k||c.variantSku===k);return d.length===0?!1:d.some(c=>mr(c))});return o.length===0?null:o.length!==s.clickableSkus.length?{...s,clickableSkus:o}:s})},[r]),y(()=>{!h||r.length===0||p(s=>{if(s&&(s.type==="validation"||s.type==="partial-success"))return s;const o=x(r);if(o.length===0)return s;const k=[...new Set(o.map(f=>f.sku))],d=(s==null?void 0:s.clickableSkus)||[];return k.length!==d.length||!k.every(f=>d.includes(f))?{type:"validation",variant:"warning",message:I.validationError,clickableSkus:k}:s})},[h,r,I.validationError]),y(()=>{const s=r.map(o=>{const k=w(o),d=o.id||o.sku;return S.on(`${k}/pdp/values`,c=>{const f=kr(c);fr(B,d,f)})});return()=>{s.forEach(o=>{o==null||o.off()})}},[r,B]),y(()=>{C.current=g},[g]),y(()=>{const s=S.on("cart/product/added",k=>{const d=Array.isArray(k)?k.length:0,c=Array.isArray(k)?k.map(f=>f.sku).filter(Boolean):[];if(g.length>0){const f=g.filter(m=>!c.includes(m));f.length>0&&d>0&&(p({type:"partial-success",variant:"warning",message:I.partialSuccess,count:d,clickableSkus:f}),O([]))}else return}),o=S.on("quick-order/add-to-cart-error",k=>{p({type:"backend-error",variant:"warning",message:I.backendError,details:k.message}),O([])});return()=>{s==null||s.off(),o==null||o.off()}},[g]),y(()=>{const s=S.on("cart/data",o=>{if(C.current.length===0||!(o!=null&&o.items)||o.items.length===0)return;const k=o.items.flatMap(c=>{var m;const f=[];return c.sku&&f.push(c.sku),(m=c.product)!=null&&m.sku&&f.push(c.product.sku),f}),d=C.current.filter(c=>k.includes(c));d.length!==0&&(p({type:"success",variant:"success",message:I.success,count:d.length}),O([]),S.emit("quick-order/loading",!1))},{eager:!0});return()=>{s==null||s.off()}},[]);const M=A(s=>{n(o=>o.filter(k=>k.id!==s&&k.sku!==s))},[]),N=A(()=>{n([]),p(null)},[]),V=A((s,o)=>{n(k=>k.map(d=>d.sku===s?{...d,quantity:o}:d))},[]),$=A(s=>a.has(s),[a]),Z=A(()=>{const s=lr(r).filter(c=>c!==null);if(r.length>0&&!K(r)){const m=x(r).map(T=>T.sku);p({type:"validation",variant:"warning",message:I.validationError,clickableSkus:m});return}if(s.length===0){if(r.length>0){const f=x(r).map(m=>m.sku);p({type:"validation",variant:"warning",message:I.validationError,clickableSkus:f})}return}p(null);const o=s.map(c=>c.sku).filter(c=>!!c);O(o);const k=G(B),d=pr(s,r,k);t?(S.emit("quick-order/loading",!0),Promise.resolve(t(d,N)).then(c=>{c&&typeof c=="string"&&(p({type:"backend-error",variant:"warning",message:I.backendError,details:c}),O([]))}).catch(c=>{p({type:"backend-error",variant:"warning",message:I.backendError,details:c.message||I.unexpectedError}),O([])}).finally(()=>{S.emit("quick-order/loading",!1)})):S.emit("quick-order/add-to-cart",d)},[r,t,B]);return{items:r,loading:u,removeItem:M,clearItems:N,updateItemQuantity:V,addToCart:Z,isItemUpdating:$,isDisabledButton:h,setDisabledCartButton:b,notification:q,dismissNotification:F}},gr=({notification:e,onDismiss:t,onSkuClick:r,validationErrorText:n,backendErrorText:u,successText:i,partialSuccessText:a})=>{if(!e)return null;const l=()=>{switch(e.type){case"validation":return Or(n,e.clickableSkus,e.details,r);case"partial-success":return Sr(a,e.message,e.count,e.clickableSkus,r);case"backend-error":return Ir(u,e.details);case"success":return Qr(i,e.count);default:return v("span",{children:e.message})}};return v("div",{className:P(["b2b-quick-order-notification-banner",[`b2b-quick-order-notification-banner--${e.variant}`,e.variant]]),children:v(rr,{variant:e.variant,message:l(),onDismiss:t})})};function Y(e,t){return e.map((r,n)=>D("span",{children:[v("a",{href:"#",onClick:u=>{u.preventDefault(),t(r)},style:{cursor:"pointer",textDecoration:"underline",color:"white"},children:r}),n<e.length-1?", ":""]},r))}function Or(e,t,r,n){return t!=null&&t.length&&n?D("span",{children:[e," - ",Y(t,n)]}):D("span",{children:[e," - ",r]})}function Sr(e,t,r,n,u){if(!e)return v("span",{children:t});const i=e.replace("{count}",String(r||0)).replace("{total}",String((r||0)+((n==null?void 0:n.length)||0)));return n!=null&&n.length&&u?D("span",{children:[i,": ",Y(n,u)]}):D("span",{children:[i,": ",(n==null?void 0:n.join(", "))||"Unknown"]})}function Ir(e,t){return D("span",{children:[e,t?` - ${t}`:""]})}function Qr(e,t){return t!==void 0?v("span",{children:e.replace("{count}",String(t))}):v("span",{children:e})}const Ur=({className:e,slots:t,getProductsData:r,handleAddToCart:n,productsSearch:u,searchFilter:i})=>{const a=nr.getConfig().quickOrderActive,l=J(null),h=z({title:"QuickOrder.QuickOrderItem.title",quantity:"QuickOrder.QuickOrderItem.quantity",price:"QuickOrder.QuickOrderItem.price",remove:"QuickOrder.QuickOrderItem.remove",removeItem:"QuickOrder.QuickOrderItem.removeItem",showOptions:"QuickOrder.QuickOrderItem.showOptions",hideOptions:"QuickOrder.QuickOrderItem.hideOptions",additionalOptions:"QuickOrder.QuickOrderItem.additionalOptions",noAdditionalOptions:"QuickOrder.QuickOrderItem.noAdditionalOptions",emptyList:"QuickOrder.QuickOrderItem.emptyList",sku:"QuickOrder.QuickOrderItem.sku",loading:"QuickOrder.QuickOrderItem.loading",productNotFound:"QuickOrder.QuickOrderItem.productNotFound",productNotFoundDescription:"QuickOrder.QuickOrderItem.productNotFoundDescription",productOptions:"QuickOrder.QuickOrderItem.productOptions",configurableProductError:"QuickOrder.QuickOrderItem.configurableProductError",configurableProductErrorDescription:"QuickOrder.QuickOrderItem.configurableProductErrorDescription",addAllToCart:"QuickOrder.QuickOrderItem.addAllToCart",configurableOptionsWarning:"QuickOrder.QuickOrderItem.configurableOptionsWarning",configurableOptionsWarningDescription:"QuickOrder.QuickOrderItem.configurableOptionsWarningDescription",outOfStock:"QuickOrder.QuickOrderItem.outOfStock",searchPlaceholder:"QuickOrder.Search.placeholder",searchAriaLabel:"QuickOrder.Search.ariaLabel",searchEmptyState:"QuickOrder.Search.emptyState",resultsAvailable:"QuickOrder.Search.resultsAvailable",resultAvailable:"QuickOrder.Search.resultAvailable",srInstructions:"QuickOrder.Search.srInstructions",notificationValidationError:"QuickOrder.QuickOrderItem.notification.validationError",notificationBackendError:"QuickOrder.QuickOrderItem.notification.backendError",notificationSuccess:"QuickOrder.QuickOrderItem.notification.success",notificationPartialSuccess:"QuickOrder.QuickOrderItem.notification.partialSuccess",disabledMessage:"QuickOrder.QuickOrderItem.disabledMessage"}),{items:Q,loading:q,removeItem:p,clearItems:g,updateItemQuantity:O,addToCart:C,isItemUpdating:I,setDisabledCartButton:B,isDisabledButton:F,notification:b,dismissNotification:M}=hr({getProductsData:r,handleAddToCart:n});y(()=>{b&&b.variant==="warning"&&l.current&&l.current.scrollIntoView({behavior:"smooth",block:"start"})},[b]);const N=V=>{const $=document.querySelector(`form[data-sku="${V}"]`);$&&$.scrollIntoView({behavior:"smooth",block:"center"})};return D("div",{className:P(["b2b-quick-order-quick-order-items",!a&&"b2b-quick-order-disabled",e]),"data-testid":"quick-order-items",style:{position:"relative"},children:[v("div",{ref:l,children:v(gr,{notification:b,onDismiss:M,onSkuClick:N,validationErrorText:h.notificationValidationError,backendErrorText:h.notificationBackendError,successText:h.notificationSuccess,partialSuccessText:h.notificationPartialSuccess})}),v(tr,{isDisabled:!a,message:h.disabledMessage,children:v(er,{t:h,items:Q,onRemove:p,clearItems:g,onUpdateQuantity:O,handleAddToCart:C,isItemUpdating:I,slots:t,loading:q,setDisabledCartButton:B,isDisabledButton:F,productsSearch:u,searchFilter:i})})]})};export{Ur as QuickOrderItems,Ur as default};
3
+ import{jsx as b,jsxs as N}from"@dropins/tools/preact-jsx-runtime.js";import{AlertBanner as tr}from"@dropins/tools/components.js";import{Q as er,a as nr}from"../chunks/QuickOrderDisabledOverlay.js";import{classes as G}from"@dropins/tools/lib.js";import"../chunks/debounce.js";import{useState as w,useRef as Y,useCallback as U,useEffect as v}from"@dropins/tools/preact-hooks.js";import{events as g}from"@dropins/tools/event-bus.js";import{useText as Z}from"@dropins/tools/i18n.js";import"@dropins/tools/preact-compat.js";import{c as ir}from"../chunks/getStoreConfig.js";import"@dropins/tools/fetch-graphql.js";const sr=["sku","parentSku","itemId","quantity","optionsUIDs","valid","productType"],or=e=>{const t=[],r=[];return e.forEach((n,u)=>{if(sr.includes(u))return;const i=n;i&&i.match(/^[A-Za-z0-9+/=]+$/)?t.push(i):r.push({uid:u,value:i})}),{optionUIDs:t,enteredOptions:r}},ar=e=>{const t=Number(e.get("quantity")),r=!t||t<1?1:t,n={sku:e.get("sku"),quantity:r},u=e.get("itemId");u&&(n.itemId=u);const i=e.get("parentSku");i&&(n.parentSku=i);const{optionUIDs:o,enteredOptions:c}=or(e);return o.length>0&&(n.optionsUIDs=o),c.length>0&&(n.enteredOptions=c),n},W={sku:"",quantity:1,name:"",images:[],inStock:!1,addToCartAllowed:!1,isBundle:!1,prices:{},attributes:[],options:[],url:"",urlKey:"",externalId:"",productType:"simple",shortDescription:"",metaDescription:"",metaKeyword:"",metaTitle:"",description:""},j=(e,t)=>!t||!Array.isArray(t)?e.map(r=>({...W,sku:r.sku,quantity:r.quantity??1})):e.map(r=>{const n=t.find(u=>(u==null?void 0:u.sku)===(r==null?void 0:r.sku));if(n){const u=r.variantSku||n.variantSku;return{...n,...u&&{variantSku:r.variantSku||n.variantSku,parentSku:n.sku},quantity:r.quantity??1}}return{...W,sku:r.sku,...r.variantSku&&{variantSku:r.variantSku,parentSku:r.sku},quantity:r.quantity??1}}),P=e=>e.length===0?!1:e.every(t=>!((t.urlKey||t.url)&&t.name)||t.inStock===!1?!1:t.options&&t.options.length>0?t.options.some(i=>i.required)?t.options.every(i=>{var o;return i.required?(o=i.items)==null?void 0:o.some(c=>c.selected):!0}):t.options.some(i=>i.items&&i.items.length>0&&i.items.some(o=>o.selected===!0)):!0),F=e=>{const t=[];return e.forEach(r=>{if(!((r.urlKey||r.url)&&r.name)){t.push({sku:r.sku,name:r.name||"Unknown",reason:"incomplete_data"});return}if(r.inStock===!1){t.push({sku:r.sku,name:r.name,reason:"out_of_stock"});return}if(r.options&&r.options.length>0){if(r.options.some(o=>o.required)){r.options.every(c=>{var S;return c.required?(S=c.items)==null?void 0:S.some(I=>I.selected):!0})||t.push({sku:r.sku,name:r.name,reason:"missing_required_options"});return}r.options.some(o=>o.items&&o.items.length>0&&o.items.some(c=>c.selected===!0))||t.push({sku:r.sku,name:r.name,reason:"missing_options"})}}),t},$=e=>`quick-order-item-${e.id||e.variantSku||e.sku}`,J=e=>`${e}-${Date.now()}-${Math.random().toString(36).substring(2,9)}`,z=(e,t)=>e.findIndex(r=>t.variantSku&&r.variantSku?r.variantSku===t.variantSku:r.variantSku&&!t.variantSku&&t.sku?r.variantSku===t.sku:t.variantSku&&!r.variantSku&&r.sku?r.sku===t.variantSku:!t.variantSku&&!r.variantSku?r.sku===t.sku:!1),ur=(e,t,r)=>e.findIndex(n=>n.id===r?!1:t.variantSku&&n.variantSku?n.variantSku===t.variantSku:t.variantSku&&!n.variantSku&&n.sku?n.sku===t.variantSku:!1),cr=(e,t,r,n=1)=>{const u=e[t];return e.map((i,o)=>o===r?{...i,quantity:i.quantity+n,parentSku:i.parentSku||(u==null?void 0:u.parentSku)}:o===t?null:i).filter(Boolean)},dr=(e,t,r)=>{const n=[...e],u=[],i=[],o=[];return t.forEach((c,S)=>{const I=r[S];if(I!=null&&I.replaceItemSku){const p=n.findIndex(O=>O.sku===I.replaceItemSku||O.id===I.replaceItemSku);if(p!==-1){const O=z(n,c);if(O!==-1&&O!==p){n.splice(p,1);const h=O>p?O-1:O;n[h]={...n[h],quantity:n[h].quantity+c.quantity,parentSku:n[h].parentSku||c.parentSku},o.push(n[h])}else{const h={...c,id:J(c.sku)};n[p]=h,i.push(h)}return}}const E=z(n,c);if(E!==-1)n[E]={...n[E],quantity:n[E].quantity+c.quantity,parentSku:n[E].parentSku||c.parentSku},o.push(n[E]);else{const p={...c,id:J(c.sku)};n.push(p),u.push(p)}}),{updatedItems:n,addedItems:u,replacedItems:i,mergedItems:o}},lr=(e,t,r,n=1)=>{const u=t?ur(e,r,t):-1;if(u!==-1){const o=e.findIndex(c=>c.id===t);return{updatedItems:cr(e,o,u,n),wasMerged:!0,mergedIntoIndex:u}}return{updatedItems:e.map(o=>t&&o.id===t?{...o,...r,id:t,parentSku:r.parentSku!==void 0?r.parentSku:o.parentSku||(r.variantSku?o.sku:void 0)}:!t&&o.sku===r.sku?{...o,...r,parentSku:r.parentSku!==void 0?r.parentSku:o.parentSku||(r.variantSku?o.sku:void 0)}:o),wasMerged:!1}},kr=e=>e.map(t=>{const r=t.id||t.sku,n=document.forms[`form-${r}`];if(!n)return null;const u=new FormData(n);return u.get("valid")==="true"?ar(u):null}),fr=e=>{let t=[];return e&&typeof e=="object"?e.optionsUIDs&&Array.isArray(e.optionsUIDs)?t=e.optionsUIDs:Array.isArray(e)&&(t=e):typeof e=="string"&&(t=[e]),t},H=e=>{try{const t=localStorage.getItem(e);if(t)return JSON.parse(t)}catch(t){console.error("Error reading from localStorage:",t)}return{}},pr=(e,t,r)=>{if(r.length!==0)try{const n=H(e);n[t]=r,localStorage.setItem(e,JSON.stringify(n))}catch(n){console.error("Error saving to localStorage:",n)}},mr=(e,t,r)=>e.map(n=>{let u=n.itemId?t.find(i=>(i.id||i.sku)===n.itemId):void 0;if(u||(u=t.find(i=>n.sku===i.sku||n.sku===i.variantSku)),u){const i=u.id||u.sku,o=r[i],c={...n};return o&&o.length>0&&(c.optionsUIDs=o),u.parentSku&&(c.parentSku=u.parentSku),c}return n}),hr=e=>{const t=!e.inStock||!e.addToCartAllowed;if(e.options&&e.options.length>0){if(e.options.some(i=>!i.items||i.items.length===0))return!0;if(e.options.some(i=>i.required)){const i=e.options.every(o=>{var c;return o.required?(c=o.items)==null?void 0:c.some(S=>S.selected):!0});return t||!i}const u=e.options.some(i=>i.items&&i.items.length>0&&i.items.some(o=>o.selected===!0));return t||!u}return t},Sr=({getProductsData:e,handleAddToCart:t}={})=>{const[r,n]=w([]),[u,i]=w(!1),[o,c]=w(new Set),[S,I]=w(!1),[E,p]=w(null),[O,h]=w([]),B=Y([]),Q=Z({validationError:"QuickOrder.QuickOrderItem.notification.validationError",backendError:"QuickOrder.QuickOrderItem.notification.backendError",success:"QuickOrder.QuickOrderItem.notification.success",partialSuccess:"QuickOrder.QuickOrderItem.notification.partialSuccess",unexpectedError:"QuickOrder.QuickOrderItem.notification.unexpectedError"}),R="quick-order-selected-options",M=U(()=>{p(null)},[]),q=U(s=>{I(s)},[]);v(()=>{const s=g.on("quick-order/loading",a=>{i(a)},{eager:!0});return()=>{s==null||s.off()}},[]),v(()=>{const s=g.on("quick-order/add-items",async a=>{if(a&&a.length>0){if(!e)return;i(!0),g.emit("quick-order/loading",!0);const k=a.map(l=>l.variantSku||l.sku).filter(Boolean);c(l=>new Set([...Array.from(l),...k]));try{let l=[];try{const f=await e(a)??[];q(a.length!==f.length),l=j(a,f)}catch(f){console.error("Error fetching products data:",f),l=j(a,[])}const d=F(l);if(d.length>0){const f=d.map(m=>m.sku);p(m=>{if((m==null?void 0:m.type)==="validation"&&m.clickableSkus){const D=[...new Set([...m.clickableSkus,...f])];return{...m,clickableSkus:D}}return{type:"validation",variant:"warning",message:Q.validationError,clickableSkus:f}})}n(f=>{const{updatedItems:m,addedItems:D,mergedItems:y,replacedItems:C}=dr(f,l,a);return C.forEach(A=>{const T=$(A);g.emit(`${T}/pdp/data`,A)}),y.forEach(A=>{const T=$(A);g.emit(`${T}/pdp/data`,A)}),D.forEach(A=>{const T=$(A);g.emit(`${T}/pdp/data`,A)}),m})}finally{i(!1),g.emit("quick-order/loading",!1),c(l=>new Set(Array.from(l).filter(d=>!k.includes(d))))}}},{eager:!0});return()=>{s==null||s.off()}},[e,q]),v(()=>{const s=r.map(a=>{const k=$(a),l=a.id;return g.on(`${k}/pdp/data`,d=>{n(f=>lr(f,l||"",d,a.quantity||1).updatedItems)})});return()=>{s==null||s.forEach(a=>{a==null||a.off()})}},[r,R]),v(()=>{const s=P(r);q(!s)},[r,q]),v(()=>{p(s=>{if(!s||!s.clickableSkus||s.clickableSkus.length===0)return s;const a=s.clickableSkus.filter(k=>{const l=r.filter(d=>d.sku===k||d.variantSku===k);return l.length===0?!1:l.some(d=>hr(d))});return a.length===0?null:a.length!==s.clickableSkus.length?{...s,clickableSkus:a}:s})},[r]),v(()=>{!S||r.length===0||p(s=>{if(s&&(s.type==="validation"||s.type==="partial-success"))return s;const a=F(r);if(a.length===0)return s;const k=[...new Set(a.map(f=>f.sku))],l=(s==null?void 0:s.clickableSkus)||[];return k.length!==l.length||!k.every(f=>l.includes(f))?{type:"validation",variant:"warning",message:Q.validationError,clickableSkus:k}:s})},[S,r,Q.validationError]),v(()=>{const s=r.map(a=>{const k=$(a),l=a.id||a.sku;return g.on(`${k}/pdp/values`,d=>{const f=fr(d);pr(R,l,f)})});return()=>{s.forEach(a=>{a==null||a.off()})}},[r,R]),v(()=>{B.current=O},[O]),v(()=>{const s=g.on("cart/product/added",k=>{const l=Array.isArray(k)?k.length:0,d=Array.isArray(k)?k.map(f=>f.sku).filter(Boolean):[];if(B.current.length>0){const f=B.current.reduce((y,C)=>(y[C]=(y[C]||0)+1,y),{}),m=d.reduce((y,C)=>(y[C]=(y[C]||0)+1,y),{}),D=[];Object.keys(f).forEach(y=>{const C=f[y],A=m[y]||0,T=C-A;for(let K=0;K<T;K++)D.push(y)}),D.length>0&&l>0&&(p({type:"partial-success",variant:"warning",message:Q.partialSuccess,count:l,clickableSkus:D}),h([]))}else return}),a=g.on("quick-order/add-to-cart-error",k=>{p({type:"backend-error",variant:"warning",message:Q.backendError,details:k.message}),h([])});return()=>{s==null||s.off(),a==null||a.off()}},[O]),v(()=>{const s=g.on("cart/data",a=>{if(B.current.length===0||!(a!=null&&a.items)||a.items.length===0)return;const k=a.items.flatMap(d=>{var m;const f=[];return d.sku&&f.push(d.sku),(m=d.product)!=null&&m.sku&&f.push(d.product.sku),f}),l=B.current.filter(d=>k.includes(d));l.length!==0&&(p({type:"success",variant:"success",message:Q.success,count:l.length}),h([]),g.emit("quick-order/loading",!1))},{eager:!0});return()=>{s==null||s.off()}},[]);const _=U(s=>{n(a=>a.filter(k=>k.id!==s&&k.sku!==s))},[]),x=U(()=>{n([]),p(null)},[]),L=U((s,a)=>{n(k=>k.map(l=>(l.variantSku||l.sku)===s?{...l,quantity:a}:l))},[]),V=U(s=>o.has(s),[o]),rr=U(()=>{const s=kr(r).filter(d=>d!==null);if(r.length>0&&!P(r)){const m=F(r).map(D=>D.sku);p({type:"validation",variant:"warning",message:Q.validationError,clickableSkus:m});return}if(s.length===0){if(r.length>0){const f=F(r).map(m=>m.sku);p({type:"validation",variant:"warning",message:Q.validationError,clickableSkus:f})}return}p(null);const a=s.map(d=>d.sku).filter(d=>!!d);h(a);const k=H(R),l=mr(s,r,k);t?(g.emit("quick-order/loading",!0),Promise.resolve(t(l,x)).then(d=>{d&&typeof d=="string"?(p({type:"backend-error",variant:"warning",message:Q.backendError,details:d}),h([])):h([])}).catch(d=>{p({type:"backend-error",variant:"warning",message:Q.backendError,details:d.message||Q.unexpectedError}),h([])}).finally(()=>{g.emit("quick-order/loading",!1)})):g.emit("quick-order/add-to-cart",l)},[r,t,R]);return{items:r,loading:u,removeItem:_,clearItems:x,updateItemQuantity:L,addToCart:rr,isItemUpdating:V,isDisabledButton:S,setDisabledCartButton:q,notification:E,dismissNotification:M}},gr=({notification:e,onDismiss:t,onSkuClick:r,validationErrorText:n,backendErrorText:u,successText:i,partialSuccessText:o})=>{if(!e)return null;const c=()=>{switch(e.type){case"validation":return Or(n,e.clickableSkus,e.details,r);case"partial-success":return Qr(o,e.message,e.count,e.clickableSkus,r);case"backend-error":return yr(u,e.details);case"success":return Ir(i,e.count);default:return b("span",{children:e.message})}};return b("div",{className:G(["b2b-quick-order-notification-banner",[`b2b-quick-order-notification-banner--${e.variant}`,e.variant]]),children:b(tr,{variant:e.variant,message:c(),onDismiss:t})})};function X(e,t){return e.map((r,n)=>N("span",{children:[b("a",{href:"#",onClick:u=>{u.preventDefault(),t(r)},style:{cursor:"pointer",textDecoration:"underline",color:"white"},children:r}),n<e.length-1?", ":""]},r))}function Or(e,t,r,n){return t!=null&&t.length&&n?N("span",{children:[e," - ",X(t,n)]}):N("span",{children:[e," - ",r]})}function Qr(e,t,r,n,u){if(!e)return b("span",{children:t});const i=e.replace("{count}",String(r||0)).replace("{total}",String((r||0)+((n==null?void 0:n.length)||0)));return n!=null&&n.length&&u?N("span",{children:[i,": ",X(n,u)]}):N("span",{children:[i,": ",(n==null?void 0:n.join(", "))||"Unknown"]})}function yr(e,t){return N("span",{children:[e,t?` - ${t}`:""]})}function Ir(e,t){return t!==void 0?b("span",{children:e.replace("{count}",String(t))}):b("span",{children:e})}const Nr=({className:e,slots:t,getProductsData:r,handleAddToCart:n,productsSearch:u,searchFilter:i})=>{const o=ir.getConfig().quickOrderActive,c=Y(null),S=Z({title:"QuickOrder.QuickOrderItem.title",quantity:"QuickOrder.QuickOrderItem.quantity",price:"QuickOrder.QuickOrderItem.price",remove:"QuickOrder.QuickOrderItem.remove",removeItem:"QuickOrder.QuickOrderItem.removeItem",showOptions:"QuickOrder.QuickOrderItem.showOptions",hideOptions:"QuickOrder.QuickOrderItem.hideOptions",additionalOptions:"QuickOrder.QuickOrderItem.additionalOptions",noAdditionalOptions:"QuickOrder.QuickOrderItem.noAdditionalOptions",emptyList:"QuickOrder.QuickOrderItem.emptyList",sku:"QuickOrder.QuickOrderItem.sku",loading:"QuickOrder.QuickOrderItem.loading",productNotFound:"QuickOrder.QuickOrderItem.productNotFound",productNotFoundDescription:"QuickOrder.QuickOrderItem.productNotFoundDescription",productOptions:"QuickOrder.QuickOrderItem.productOptions",configurableProductError:"QuickOrder.QuickOrderItem.configurableProductError",configurableProductErrorDescription:"QuickOrder.QuickOrderItem.configurableProductErrorDescription",addAllToCart:"QuickOrder.QuickOrderItem.addAllToCart",configurableOptionsWarning:"QuickOrder.QuickOrderItem.configurableOptionsWarning",configurableOptionsWarningDescription:"QuickOrder.QuickOrderItem.configurableOptionsWarningDescription",outOfStock:"QuickOrder.QuickOrderItem.outOfStock",searchPlaceholder:"QuickOrder.Search.placeholder",searchAriaLabel:"QuickOrder.Search.ariaLabel",searchEmptyState:"QuickOrder.Search.emptyState",resultsAvailable:"QuickOrder.Search.resultsAvailable",resultAvailable:"QuickOrder.Search.resultAvailable",srInstructions:"QuickOrder.Search.srInstructions",notificationValidationError:"QuickOrder.QuickOrderItem.notification.validationError",notificationBackendError:"QuickOrder.QuickOrderItem.notification.backendError",notificationSuccess:"QuickOrder.QuickOrderItem.notification.success",notificationPartialSuccess:"QuickOrder.QuickOrderItem.notification.partialSuccess",disabledMessage:"QuickOrder.QuickOrderItem.disabledMessage"}),{items:I,loading:E,removeItem:p,clearItems:O,updateItemQuantity:h,addToCart:B,isItemUpdating:Q,setDisabledCartButton:R,isDisabledButton:M,notification:q,dismissNotification:_}=Sr({getProductsData:r,handleAddToCart:n});v(()=>{q&&q.variant==="warning"&&c.current&&c.current.scrollIntoView({behavior:"smooth",block:"start"})},[q]);const x=L=>{const V=document.querySelector(`form[data-sku="${L}"]`);V&&V.scrollIntoView({behavior:"smooth",block:"center"})};return N("div",{className:G(["b2b-quick-order-quick-order-items",!o&&"b2b-quick-order-disabled",e]),"data-testid":"quick-order-items",style:{position:"relative"},children:[b("div",{ref:c,children:b(gr,{notification:q,onDismiss:_,onSkuClick:x,validationErrorText:S.notificationValidationError,backendErrorText:S.notificationBackendError,successText:S.notificationSuccess,partialSuccessText:S.notificationPartialSuccess})}),b(er,{isDisabled:!o,message:S.disabledMessage,children:b(nr,{t:S,items:I,onRemove:p,clearItems:O,onUpdateQuantity:h,handleAddToCart:B,isItemUpdating:Q,slots:t,loading:E,setDisabledCartButton:R,isDisabledButton:M,productsSearch:u,searchFilter:i})})]})};export{Nr as QuickOrderItems,Nr as default};
4
4
  //# sourceMappingURL=QuickOrderItems.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"QuickOrderItems.js","sources":["/@dropins/storefront-quick-order/src/lib/processFormOptions.ts","/@dropins/storefront-quick-order/src/lib/buildCartItem.ts","/@dropins/storefront-quick-order/src/configs/order-item.config.ts","/@dropins/storefront-quick-order/src/lib/mapProductsToOrderItems.ts","/@dropins/storefront-quick-order/src/lib/validateOrderItems.ts","/@dropins/storefront-quick-order/src/lib/getItemScope.ts","/@dropins/storefront-quick-order/src/lib/generateItemId.ts","/@dropins/storefront-quick-order/src/lib/findDuplicateItem.ts","/@dropins/storefront-quick-order/src/lib/mergeDuplicateItems.ts","/@dropins/storefront-quick-order/src/lib/replaceOrAddItems.ts","/@dropins/storefront-quick-order/src/lib/updateItemInList.ts","/@dropins/storefront-quick-order/src/lib/buildCartItemsFromForms.ts","/@dropins/storefront-quick-order/src/lib/productOptionsStorage.ts","/@dropins/storefront-quick-order/src/lib/isItemValid.ts","/@dropins/storefront-quick-order/src/hooks/useQuickOrderItems.tsx","/@dropins/storefront-quick-order/src/components/QuickOrderNotificationBanner/QuickOrderNotificationBanner.tsx","/@dropins/storefront-quick-order/src/containers/QuickOrderItems/QuickOrderItems.tsx"],"sourcesContent":["/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nconst STANDARD_FIELDS = [\n 'sku',\n 'parentSku',\n 'quantity',\n 'optionsUIDs',\n 'valid',\n 'productType',\n];\n\nexport interface ProcessedFormOptions {\n optionUIDs: string[];\n enteredOptions: { uid: string; value: string }[];\n}\n\n/**\n * Processes form data to extract product options\n * Separates base64-encoded configurable options (optionUIDs) from custom entered options\n */\nexport const processFormOptions = (\n formData: FormData\n): ProcessedFormOptions => {\n const optionUIDs: string[] = [];\n const enteredOptions: { uid: string; value: string }[] = [];\n\n formData.forEach((value, key) => {\n if (STANDARD_FIELDS.includes(key)) return;\n\n const valueStr = value as string;\n // Check if this is an option UID (base64 encoded configurable option)\n if (valueStr && valueStr.match(/^[A-Za-z0-9+/=]+$/)) {\n optionUIDs.push(valueStr);\n } else {\n enteredOptions.push({ uid: key, value: valueStr });\n }\n });\n\n return { optionUIDs, enteredOptions };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { processFormOptions } from './processFormOptions';\n\nexport interface CartItem {\n sku: string;\n quantity: number;\n parentSku?: string;\n optionsUIDs?: string[];\n enteredOptions?: { uid: string; value: string }[];\n}\n\n/**\n * Builds a cart item object from form data\n * Extracts SKU, quantity, parent SKU, and product options\n */\nexport const buildCartItem = (formData: FormData): CartItem => {\n const quantityValue = Number(formData.get('quantity'));\n const quantity = !quantityValue || quantityValue < 1 ? 1 : quantityValue;\n\n const cartItem: CartItem = {\n sku: formData.get('sku') as string,\n quantity,\n };\n\n const parentSku = formData.get('parentSku');\n if (parentSku) {\n cartItem.parentSku = parentSku as string;\n }\n\n const { optionUIDs, enteredOptions } = processFormOptions(formData);\n\n if (optionUIDs.length > 0) {\n cartItem.optionsUIDs = optionUIDs;\n }\n\n if (enteredOptions.length > 0) {\n cartItem.enteredOptions = enteredOptions;\n }\n\n return cartItem;\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types/quickOrderItems.types';\n\nexport const DEFAULT_QUICK_ORDER_ITEM: OrderItem = {\n sku: '',\n quantity: 1,\n name: '',\n images: [],\n inStock: false,\n addToCartAllowed: false,\n isBundle: false,\n prices: {} as any,\n attributes: [],\n options: [],\n url: '',\n urlKey: '',\n externalId: '',\n productType: 'simple',\n shortDescription: '',\n metaDescription: '',\n metaKeyword: '',\n metaTitle: '',\n description: '',\n} as OrderItem;\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem, OrderItemInput } from '@/b2b-quick-order/types';\nimport { DEFAULT_QUICK_ORDER_ITEM } from '@/b2b-quick-order/configs';\n\n/**\n * Maps fetched products to OrderItems\n * Creates error items for products not found in the response\n * @param requestedItems - Items that were requested\n * @param products - Products returned from API\n * @returns Array of OrderItems with proper quantity set\n */\nexport const mapProductsToOrderItems = (\n requestedItems: OrderItemInput[],\n products: OrderItem[]\n): OrderItem[] => {\n // Handle empty or undefined products array\n if (!products || !Array.isArray(products)) {\n return requestedItems.map((requestedItem) => ({\n ...DEFAULT_QUICK_ORDER_ITEM,\n sku: requestedItem.sku,\n quantity: requestedItem.quantity ?? 1,\n })) as OrderItem[];\n }\n\n return requestedItems.map((requestedItem) => {\n const foundProduct = products.find((p) => p?.sku === requestedItem?.sku);\n\n if (foundProduct) {\n return {\n ...foundProduct,\n ...(requestedItem.variantSku && {\n variantSku: requestedItem.variantSku,\n }),\n quantity: requestedItem.quantity ?? 1,\n };\n }\n\n // Product not found - create error item\n return {\n ...DEFAULT_QUICK_ORDER_ITEM,\n sku: requestedItem.sku,\n ...(requestedItem.variantSku && { variantSku: requestedItem.variantSku }),\n quantity: requestedItem.quantity ?? 1,\n } as OrderItem;\n });\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\n\n/**\n * Validates order items to determine if all items are ready for cart addition\n * @param items - Array of order items to validate\n * @returns true if all items are valid, false otherwise\n */\nexport const validateOrderItems = (items: OrderItem[]): boolean => {\n if (items.length === 0) {\n return false;\n }\n\n return items.every((item) => {\n const hasBasicData = (item.urlKey || item.url) && item.name;\n if (!hasBasicData) {\n return false;\n }\n\n if (item.inStock === false) {\n return false;\n }\n\n if (item.options && item.options.length > 0) {\n const hasRequiredOptions = item.options.some((opt) => opt.required);\n\n if (hasRequiredOptions) {\n // Required options: all must be selected\n return item.options.every((opt) => {\n if (!opt.required) return true;\n return opt.items?.some((optItem) => optItem.selected);\n });\n }\n\n // Optional options: at least one must be selected\n const hasSelectedOption = item.options.some(\n (option) =>\n option.items &&\n option.items.length > 0 &&\n option.items.some((optionItem) => optionItem.selected === true)\n );\n return hasSelectedOption;\n }\n\n return true;\n });\n};\n\n/**\n * Get items that are out of stock\n * @param items - Array of order items to check\n * @returns Array of out of stock items with their names\n */\nexport const getOutOfStockItems = (\n items: OrderItem[]\n): Array<{ sku: string; name: string }> => {\n return items\n .filter((item) => item.inStock === false)\n .map((item) => ({\n sku: item.sku,\n name: item.name,\n }));\n};\n\n/**\n * Get items with missing required options\n * @param items - Array of order items to check\n * @returns Array of items missing required options\n */\nexport const getItemsMissingOptions = (\n items: OrderItem[]\n): Array<{ sku: string; name: string }> => {\n return items\n .filter((item) => {\n if (!item.options || item.options.length === 0) {\n return false;\n }\n const hasSelectedOption = item.options.some(\n (option) =>\n option.items &&\n option.items.length > 0 &&\n option.items.some((optionItem) => optionItem.selected === true)\n );\n return !hasSelectedOption;\n })\n .map((item) => ({\n sku: item.sku,\n name: item.name,\n }));\n};\n\n/**\n * Get items with incomplete data\n * @param items - Array of order items to check\n * @returns Array of items with incomplete data\n */\nexport const getItemsWithIncompleteData = (\n items: OrderItem[]\n): Array<{ sku: string; name: string }> => {\n return items\n .filter((item) => {\n const hasBasicData = (item.urlKey || item.url) && item.name;\n return !hasBasicData;\n })\n .map((item) => ({\n sku: item.sku,\n name: item.name || 'Unknown',\n }));\n};\n\n/**\n * Get all items with validation errors\n * @param items - Array of order items to check\n * @returns Array of all items with validation errors and their SKUs\n */\nexport const getInvalidItems = (\n items: OrderItem[]\n): Array<{ sku: string; name: string; reason: string }> => {\n const invalidItems: Array<{ sku: string; name: string; reason: string }> = [];\n\n items.forEach((item) => {\n const hasBasicData = (item.urlKey || item.url) && item.name;\n\n if (!hasBasicData) {\n invalidItems.push({\n sku: item.sku,\n name: item.name || 'Unknown',\n reason: 'incomplete_data',\n });\n return;\n }\n\n if (item.inStock === false) {\n invalidItems.push({\n sku: item.sku,\n name: item.name,\n reason: 'out_of_stock',\n });\n return;\n }\n\n if (item.options && item.options.length > 0) {\n const hasRequiredOptions = item.options.some((opt) => opt.required);\n\n if (hasRequiredOptions) {\n // Required options: all must be selected\n const allRequiredSelected = item.options.every((opt) => {\n if (!opt.required) return true;\n return opt.items?.some((optItem) => optItem.selected);\n });\n\n if (!allRequiredSelected) {\n invalidItems.push({\n sku: item.sku,\n name: item.name,\n reason: 'missing_required_options',\n });\n }\n return;\n }\n\n // Optional options: at least one must be selected\n const hasSelectedOption = item.options.some(\n (option) =>\n option.items &&\n option.items.length > 0 &&\n option.items.some((optionItem) => optionItem.selected === true)\n );\n if (!hasSelectedOption) {\n invalidItems.push({\n sku: item.sku,\n name: item.name,\n reason: 'missing_options',\n });\n }\n }\n });\n\n return invalidItems;\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\n\n/**\n * Get unique scope identifier for an item\n * Uses unique id if available, otherwise falls back to variantSku or sku\n */\nexport const getItemScope = (item: OrderItem): string => {\n const scopeKey = item.id || item.variantSku || item.sku;\n return `quick-order-item-${scopeKey}`;\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\n/**\n * Generate unique ID for an item\n * Format: {sku}-{timestamp}-{random}\n */\nexport const generateItemId = (sku: string): string => {\n return `${sku}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\n\n/**\n * Find duplicate item in the list based on multiple comparison strategies\n * Returns the index of the duplicate item, or -1 if not found\n *\n * Strategies:\n * 1. Both have variantSku - compare variants\n * 2. Existing has variantSku, new has sku - compare them\n * 3. New has variantSku, existing has sku - compare them\n * 4. Neither has variantSku - compare base SKU\n */\nexport const findDuplicateItem = (\n items: OrderItem[],\n newItem: OrderItem\n): number => {\n return items.findIndex((existing) => {\n // Strategy 1: Both have variantSku - compare variants\n if (newItem.variantSku && existing.variantSku) {\n return existing.variantSku === newItem.variantSku;\n }\n\n // Strategy 2: Existing has variantSku, new has sku - compare them\n // (e.g., existing configured product vs search result variant)\n if (existing.variantSku && !newItem.variantSku && newItem.sku) {\n return existing.variantSku === newItem.sku;\n }\n\n // Strategy 3: New has variantSku, existing has sku - compare them\n // (opposite of strategy 2)\n if (newItem.variantSku && !existing.variantSku && existing.sku) {\n return existing.sku === newItem.variantSku;\n }\n\n // Strategy 4: Neither has variantSku - compare base sku\n if (!newItem.variantSku && !existing.variantSku) {\n return existing.sku === newItem.sku;\n }\n\n return false;\n });\n};\n\n/**\n * Find duplicate item excluding a specific item by ID\n * Used when checking for duplicates after an item update\n */\nexport const findDuplicateItemExcluding = (\n items: OrderItem[],\n updatedItem: OrderItem,\n excludeItemId: string\n): number => {\n return items.findIndex((existing) => {\n // Skip the item being updated\n if (existing.id === excludeItemId) return false;\n\n // Check if updatedItem's variantSku matches existing item\n if (updatedItem.variantSku && existing.variantSku) {\n return existing.variantSku === updatedItem.variantSku;\n }\n\n // Check if updatedItem's variantSku matches existing item's sku\n if (updatedItem.variantSku && !existing.variantSku && existing.sku) {\n return existing.sku === updatedItem.variantSku;\n }\n\n return false;\n });\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\n\n/**\n * Merge duplicate items by removing the item at removeIndex and\n * adding its quantity to the item at mergeIntoIndex\n */\nexport const mergeDuplicateItems = (\n items: OrderItem[],\n removeIndex: number,\n mergeIntoIndex: number,\n quantityToAdd: number = 1\n): OrderItem[] => {\n return items\n .map((item, index) => {\n if (index === mergeIntoIndex) {\n // Increase quantity of the duplicate\n return {\n ...item,\n quantity: item.quantity + quantityToAdd,\n };\n } else if (index === removeIndex) {\n // Remove the item being merged\n return null;\n }\n return item;\n })\n .filter(Boolean) as OrderItem[];\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem, OrderItemInput } from '@/b2b-quick-order/types';\nimport { findDuplicateItem } from './findDuplicateItem';\nimport { generateItemId } from './generateItemId';\n\nexport interface ReplaceOrAddItemsResult {\n updatedItems: OrderItem[];\n addedItems: OrderItem[];\n replacedItems: OrderItem[];\n mergedItems: OrderItem[];\n}\n\n/**\n * Replace, merge, or add items into existing list\n * Handles three scenarios:\n * 1. Replace: When inputItem has replaceItemSku, replace item at same position\n * - If new item already exists in list, collapse by removing replaced item and merging quantity\n * 2. Merge: When item exists, increase quantity\n * 3. Add: When item doesn't exist, add to end\n */\nexport const replaceOrAddItems = (\n existingItems: OrderItem[],\n newItems: OrderItem[],\n inputItems: OrderItemInput[]\n): ReplaceOrAddItemsResult => {\n const updatedItems = [...existingItems];\n const addedItems: OrderItem[] = [];\n const replacedItems: OrderItem[] = [];\n const mergedItems: OrderItem[] = [];\n\n newItems.forEach((newItem, index) => {\n const inputItem = inputItems[index];\n\n // Scenario 1: Replace existing item at same position\n if (inputItem?.replaceItemSku) {\n const replaceIndex = updatedItems.findIndex(\n (item) =>\n item.sku === inputItem.replaceItemSku ||\n item.id === inputItem.replaceItemSku\n );\n\n if (replaceIndex !== -1) {\n // Check if new item already exists elsewhere in the list (collapse case)\n const existingIndex = findDuplicateItem(updatedItems, newItem);\n\n if (existingIndex !== -1 && existingIndex !== replaceIndex) {\n // Item already exists - remove replaced item and merge quantity into existing\n updatedItems.splice(replaceIndex, 1);\n // Adjust index if existing item was after the removed one\n const adjustedIndex =\n existingIndex > replaceIndex ? existingIndex - 1 : existingIndex;\n updatedItems[adjustedIndex] = {\n ...updatedItems[adjustedIndex],\n quantity: updatedItems[adjustedIndex].quantity + newItem.quantity,\n };\n mergedItems.push(updatedItems[adjustedIndex]);\n } else {\n // Replace item at the same position\n const itemWithId = {\n ...newItem,\n id: generateItemId(newItem.sku),\n };\n updatedItems[replaceIndex] = itemWithId;\n replacedItems.push(itemWithId);\n }\n return;\n }\n // If item to replace not found, fall through to add logic\n }\n\n // Scenario 2 & 3: Merge or Add\n const existingIndex = findDuplicateItem(updatedItems, newItem);\n\n if (existingIndex !== -1) {\n // Item exists - merge by increasing quantity\n updatedItems[existingIndex] = {\n ...updatedItems[existingIndex],\n quantity: updatedItems[existingIndex].quantity + newItem.quantity,\n };\n mergedItems.push(updatedItems[existingIndex]);\n } else {\n // Item doesn't exist - add new with unique ID\n const itemWithId = {\n ...newItem,\n id: generateItemId(newItem.sku),\n };\n updatedItems.push(itemWithId);\n addedItems.push(itemWithId);\n }\n });\n\n return { updatedItems, addedItems, replacedItems, mergedItems };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\nimport { findDuplicateItemExcluding } from './findDuplicateItem';\nimport { mergeDuplicateItems } from './mergeDuplicateItems';\n\nexport interface UpdateItemResult {\n updatedItems: OrderItem[];\n wasMerged: boolean;\n mergedIntoIndex?: number;\n}\n\n/**\n * Update a specific item in the list and check for duplicates\n * If duplicate is found, merge the items\n */\nexport const updateItemInList = (\n items: OrderItem[],\n itemId: string,\n updatedItem: OrderItem,\n currentQuantity: number = 1\n): UpdateItemResult => {\n // Check if the updated item's variantSku matches another existing item\n const duplicateIndex = itemId\n ? findDuplicateItemExcluding(items, updatedItem, itemId)\n : -1;\n\n if (duplicateIndex !== -1) {\n // Find the index of the item being updated\n const removingIndex = items.findIndex((prevItem) => prevItem.id === itemId);\n\n // Duplicate found - merge items\n return {\n updatedItems: mergeDuplicateItems(\n items,\n removingIndex,\n duplicateIndex,\n currentQuantity\n ),\n wasMerged: true,\n mergedIntoIndex: duplicateIndex,\n };\n }\n\n // No duplicate - just update the item\n const updatedItems = items.map((prevItem) => {\n if (itemId && prevItem.id === itemId) {\n // Match by ID - update with preserved ID\n return {\n ...prevItem,\n ...updatedItem,\n id: itemId,\n };\n } else if (!itemId && prevItem.sku === updatedItem.sku) {\n // Fallback for items without ID (backward compatibility)\n return {\n ...prevItem,\n ...updatedItem,\n };\n }\n return prevItem;\n });\n\n return {\n updatedItems,\n wasMerged: false,\n };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\nimport { buildCartItem } from './buildCartItem';\n\n/**\n * Build cart items from forms for all order items\n * Only includes valid items (items with valid forms)\n */\nexport const buildCartItemsFromForms = (items: OrderItem[]) => {\n return items.map((item) => {\n const formId = item.id || item.sku;\n const form = document.forms[`form-${formId}` as any] as HTMLFormElement;\n if (!form) return null;\n\n const formData = new FormData(form);\n const isValid = formData.get('valid') === 'true';\n\n return isValid ? buildCartItem(formData) : null;\n });\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\n/**\n * Extract optionsUIDs from various data formats\n */\nexport const extractOptionsUIDs = (valuesData: any): string[] => {\n let optionsUIDs: string[] = [];\n\n if (valuesData && typeof valuesData === 'object') {\n if (valuesData.optionsUIDs && Array.isArray(valuesData.optionsUIDs)) {\n optionsUIDs = valuesData.optionsUIDs;\n } else if (Array.isArray(valuesData)) {\n optionsUIDs = valuesData;\n }\n } else if (typeof valuesData === 'string') {\n optionsUIDs = [valuesData];\n }\n\n return optionsUIDs;\n};\n\n/**\n * Get options from localStorage\n */\nexport const getOptionsFromStorage = (\n storageKey: string\n): Record<string, string[]> => {\n try {\n const stored = localStorage.getItem(storageKey);\n if (stored) {\n return JSON.parse(stored);\n }\n } catch (e) {\n console.error('Error reading from localStorage:', e);\n }\n return {};\n};\n\n/**\n * Save options to localStorage\n */\nexport const saveOptionsToStorage = (\n storageKey: string,\n itemId: string,\n optionsUIDs: string[]\n): void => {\n if (optionsUIDs.length === 0) {\n return;\n }\n\n try {\n const storageData = getOptionsFromStorage(storageKey);\n storageData[itemId] = optionsUIDs;\n localStorage.setItem(storageKey, JSON.stringify(storageData));\n } catch (e) {\n console.error('Error saving to localStorage:', e);\n }\n};\n\n/**\n * Enrich cart items with selected options from storage\n */\nexport const enrichCartItemsWithOptions = <T extends { sku: string }>(\n cartItems: T[],\n items: Array<{ id?: string; sku: string; variantSku?: string }>,\n storageData: Record<string, string[]>\n): Array<T & { optionsUIDs?: string[] }> => {\n return cartItems.map((cartItem) => {\n const item = items.find((i) => {\n return cartItem.sku === i.sku || cartItem.sku === i.variantSku;\n });\n\n if (item) {\n const itemId = item.id || item.sku;\n const selectedOptions = storageData[itemId];\n\n if (selectedOptions && selectedOptions.length > 0) {\n return {\n ...cartItem,\n optionsUIDs: selectedOptions,\n };\n }\n }\n\n return cartItem;\n });\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\n\n/**\n * Check if an item is valid for adding to cart\n * @param item - The order item to validate\n * @returns true if item is invalid (should stay in notification), false if valid\n */\nexport const isItemInvalid = (item: OrderItem): boolean => {\n const hasBasicIssues = !item.inStock || !item.addToCartAllowed;\n\n if (item.options && item.options.length > 0) {\n // Options must be loaded before validation\n const optionsNotReady = item.options.some(\n (opt) => !opt.items || opt.items.length === 0\n );\n\n if (optionsNotReady) {\n return true;\n }\n\n const hasRequiredOptions = item.options.some((opt) => opt.required);\n\n if (hasRequiredOptions) {\n // Required options: all must be selected\n const allRequiredSelected = item.options.every((opt) => {\n if (!opt.required) return true;\n return opt.items?.some((optItem) => optItem.selected);\n });\n return hasBasicIssues || !allRequiredSelected;\n }\n\n // Optional options: at least one must be selected\n const hasSelectedOption = item.options.some(\n (option) =>\n option.items &&\n option.items.length > 0 &&\n option.items.some((optionItem) => optionItem.selected === true)\n );\n return hasBasicIssues || !hasSelectedOption;\n }\n\n return hasBasicIssues;\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { useCallback, useEffect, useRef, useState } from 'preact/hooks';\nimport {\n OrderItemInput,\n OrderItem,\n UseQuickOrderItemsProps,\n UseQuickOrderItemsReturn,\n} from '@/b2b-quick-order/types';\nimport { events } from '@adobe-commerce/event-bus';\nimport { useText } from '@adobe-commerce/elsie/i18n';\nimport {\n mapProductsToOrderItems,\n validateOrderItems,\n getItemScope,\n replaceOrAddItems,\n updateItemInList,\n buildCartItemsFromForms,\n extractOptionsUIDs,\n saveOptionsToStorage,\n getOptionsFromStorage,\n enrichCartItemsWithOptions,\n getInvalidItems,\n isItemInvalid,\n} from '@/b2b-quick-order/lib';\n\nexport const useQuickOrderItems = ({\n getProductsData,\n handleAddToCart,\n}: UseQuickOrderItemsProps = {}): UseQuickOrderItemsReturn => {\n const [items, setItems] = useState<OrderItem[]>([]);\n const [loading, setLoading] = useState(false);\n const [updatingItems, setUpdatingItems] = useState<Set<string>>(new Set());\n const [isDisabledButton, setIsDisabledButton] = useState(false);\n const [notification, setNotification] = useState<{\n type: 'validation' | 'partial-success' | 'success' | 'backend-error';\n variant: 'success' | 'warning' | 'neutral' | 'brand';\n message: string;\n details?: string;\n count?: number;\n clickableSkus?: string[];\n } | null>(null);\n const [attemptedSkus, setAttemptedSkus] = useState<string[]>([]);\n const attemptedSkusRef = useRef<string[]>([]);\n\n const t = useText({\n validationError: 'QuickOrder.QuickOrderItem.notification.validationError',\n backendError: 'QuickOrder.QuickOrderItem.notification.backendError',\n success: 'QuickOrder.QuickOrderItem.notification.success',\n partialSuccess: 'QuickOrder.QuickOrderItem.notification.partialSuccess',\n unexpectedError: 'QuickOrder.QuickOrderItem.notification.unexpectedError',\n });\n\n const STORAGE_KEY = 'quick-order-selected-options';\n\n const dismissNotification = useCallback(() => {\n setNotification(null);\n }, []);\n\n const setDisabledCartButton = useCallback((disabled: boolean) => {\n setIsDisabledButton(disabled);\n }, []);\n\n useEffect(() => {\n const loadingEvent = events.on(\n 'quick-order/loading',\n (loadingState) => {\n setLoading(loadingState);\n },\n {\n eager: true,\n }\n );\n return () => {\n loadingEvent?.off();\n };\n }, []);\n\n useEffect(() => {\n const itemsEvent = events.on(\n 'quick-order/add-items',\n async (eventPayload: OrderItemInput[]) => {\n if (eventPayload && eventPayload.length > 0) {\n if (!getProductsData) {\n return;\n }\n\n setLoading(true);\n events.emit('quick-order/loading', true);\n const requestedSkus = eventPayload\n .map((item) => item.sku)\n .filter(Boolean);\n setUpdatingItems(\n (prev) => new Set([...Array.from(prev), ...requestedSkus])\n );\n\n try {\n let newItems: OrderItem[] = [];\n try {\n const fetchedProducts =\n (await getProductsData(eventPayload)) ?? [];\n setDisabledCartButton(\n eventPayload.length !== fetchedProducts.length\n );\n newItems = mapProductsToOrderItems(eventPayload, fetchedProducts);\n } catch (error) {\n console.error('Error fetching products data:', error);\n newItems = mapProductsToOrderItems(eventPayload, []);\n }\n\n const invalidNewItems = getInvalidItems(newItems);\n if (invalidNewItems.length > 0) {\n const invalidSkus = invalidNewItems.map((item) => item.sku);\n setNotification((prev) => {\n if (prev?.type === 'validation' && prev.clickableSkus) {\n // Merge with existing validation SKUs\n const mergedSkus = [\n ...new Set([...prev.clickableSkus, ...invalidSkus]),\n ];\n return {\n ...prev,\n clickableSkus: mergedSkus,\n };\n }\n return {\n type: 'validation',\n variant: 'warning',\n message: t.validationError,\n clickableSkus: invalidSkus,\n };\n });\n }\n\n setItems((prevItems) => {\n const { updatedItems, addedItems, mergedItems, replacedItems } =\n replaceOrAddItems(prevItems, newItems, eventPayload);\n\n replacedItems.forEach((item) => {\n const scope = getItemScope(item);\n events.emit(`${scope}/pdp/data`, item);\n });\n\n mergedItems.forEach((item) => {\n const scope = getItemScope(item);\n events.emit(`${scope}/pdp/data`, item);\n });\n\n addedItems.forEach((item) => {\n const scope = getItemScope(item);\n events.emit(`${scope}/pdp/data`, item);\n });\n\n return updatedItems;\n });\n } finally {\n setLoading(false);\n events.emit('quick-order/loading', false);\n setUpdatingItems(\n (prev) =>\n new Set(\n Array.from(prev).filter((sku) => !requestedSkus.includes(sku))\n )\n );\n }\n }\n },\n {\n eager: true,\n }\n );\n\n return () => {\n itemsEvent?.off();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [getProductsData, setDisabledCartButton]);\n\n useEffect(() => {\n const scopesList = items.map((item) => {\n const scope = getItemScope(item);\n const itemId = item.id; // Capture the specific item's ID for this listener\n\n return events.on(`${scope}/pdp/data`, (updatedItem: OrderItem) => {\n setItems((prevItems) => {\n const result = updateItemInList(\n prevItems,\n itemId || '',\n updatedItem,\n item.quantity || 1\n );\n return result.updatedItems;\n });\n });\n });\n\n return () => {\n scopesList?.forEach((scope) => {\n scope?.off();\n });\n };\n }, [items]);\n\n useEffect(() => {\n const isValid = validateOrderItems(items);\n setDisabledCartButton(!isValid);\n }, [items, setDisabledCartButton]);\n\n useEffect(() => {\n setNotification((prev) => {\n // Only process notifications with clickable SKUs\n if (!prev || !prev.clickableSkus || prev.clickableSkus.length === 0) {\n return prev;\n }\n\n const stillInvalidSkus = prev.clickableSkus.filter((sku) => {\n // Find ALL items with this SKU (could be multiple for configurable products)\n const matchingItems = items.filter(\n (i) => i.sku === sku || i.variantSku === sku\n );\n if (matchingItems.length === 0) return false; // Item removed\n\n // Keep SKU in notification if ANY matching item is invalid\n return matchingItems.some((item) => isItemInvalid(item));\n });\n\n // Clear notification only if all SKUs are valid\n if (stillInvalidSkus.length === 0) {\n return null;\n }\n\n // Update notification if SKUs changed\n if (stillInvalidSkus.length !== prev.clickableSkus.length) {\n return {\n ...prev,\n clickableSkus: stillInvalidSkus,\n };\n }\n\n return prev;\n });\n }, [items]);\n\n useEffect(() => {\n // If Add to Cart button is disabled and there are items,\n // but no validation notification is shown - display it\n if (!isDisabledButton || items.length === 0) {\n return;\n }\n\n setNotification((prev) => {\n // Don't override existing validation/partial-success notifications\n if (\n prev &&\n (prev.type === 'validation' || prev.type === 'partial-success')\n ) {\n return prev;\n }\n\n const invalidItems = getInvalidItems(items);\n if (invalidItems.length === 0) {\n return prev;\n }\n\n const invalidSkus = [...new Set(invalidItems.map((item) => item.sku))];\n\n // Only set notification if it doesn't already have the same SKUs\n const existingSkus = prev?.clickableSkus || [];\n const hasChanges =\n invalidSkus.length !== existingSkus.length ||\n !invalidSkus.every((sku) => existingSkus.includes(sku));\n\n if (hasChanges) {\n return {\n type: 'validation',\n variant: 'warning',\n message: t.validationError,\n clickableSkus: invalidSkus,\n };\n }\n\n return prev;\n });\n }, [isDisabledButton, items, t.validationError]);\n\n useEffect(() => {\n const eventsList = items.map((item) => {\n const scope = getItemScope(item);\n const itemId = item.id || item.sku;\n\n return events.on(`${scope}/pdp/values`, (valuesData: any) => {\n const optionsUIDs = extractOptionsUIDs(valuesData);\n saveOptionsToStorage(STORAGE_KEY, itemId, optionsUIDs);\n });\n });\n\n return () => {\n eventsList.forEach((event) => {\n event?.off();\n });\n };\n }, [items, STORAGE_KEY]);\n\n useEffect(() => {\n attemptedSkusRef.current = attemptedSkus;\n }, [attemptedSkus]);\n\n useEffect(() => {\n const successEvent = events.on('cart/product/added', (products: any[]) => {\n const addedCount = Array.isArray(products) ? products.length : 0;\n const addedSkus = Array.isArray(products)\n ? products.map((p: any) => p.sku).filter(Boolean)\n : [];\n\n if (attemptedSkus.length > 0) {\n const failedSkus = attemptedSkus.filter(\n (sku) => !addedSkus.includes(sku)\n );\n\n if (failedSkus.length > 0 && addedCount > 0) {\n setNotification({\n type: 'partial-success',\n variant: 'warning',\n message: t.partialSuccess,\n count: addedCount,\n clickableSkus: failedSkus,\n });\n setAttemptedSkus([]);\n }\n } else {\n // No tracking context - ignore event\n return;\n }\n });\n\n const errorEvent = events.on(\n 'quick-order/add-to-cart-error',\n (error: { message: string }) => {\n setNotification({\n type: 'backend-error',\n variant: 'warning',\n message: t.backendError,\n details: error.message,\n });\n setAttemptedSkus([]);\n }\n );\n\n return () => {\n successEvent?.off();\n errorEvent?.off();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [attemptedSkus]);\n\n useEffect(() => {\n const cartDataEvent = events.on(\n 'cart/data',\n (cartData: any) => {\n if (\n attemptedSkusRef.current.length === 0 ||\n !cartData?.items ||\n cartData.items.length === 0\n ) {\n return;\n }\n\n // For configurable products, check both variant SKU and parent SKU\n const cartSkus = cartData.items.flatMap((item: any) => {\n const skus = [];\n if (item.sku) skus.push(item.sku);\n if (item.product?.sku) skus.push(item.product.sku);\n return skus;\n });\n\n const addedSkus = attemptedSkusRef.current.filter((sku) =>\n cartSkus.includes(sku)\n );\n\n if (addedSkus.length === 0) {\n return;\n }\n\n setNotification({\n type: 'success',\n variant: 'success',\n message: t.success,\n count: addedSkus.length,\n });\n\n setAttemptedSkus([]);\n events.emit('quick-order/loading', false);\n },\n {\n eager: true,\n }\n );\n\n return () => {\n cartDataEvent?.off();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const removeItem = useCallback((identifier: string) => {\n setItems((prevItems) =>\n prevItems.filter(\n (item) => item.id !== identifier && item.sku !== identifier\n )\n );\n }, []);\n\n const clearItems = useCallback(() => {\n setItems([]);\n setNotification(null);\n }, []);\n\n const updateItemQuantity = useCallback((sku: string, quantity: number) => {\n setItems((prevItems) =>\n prevItems.map((item) => (item.sku === sku ? { ...item, quantity } : item))\n );\n }, []);\n\n const isItemUpdating = useCallback(\n (sku: string) => {\n return updatingItems.has(sku);\n },\n [updatingItems]\n );\n\n const addToCart = useCallback(() => {\n const cartItems = buildCartItemsFromForms(items).filter(\n (item): item is NonNullable<typeof item> => item !== null\n );\n\n if (items.length > 0) {\n const isValid = validateOrderItems(items);\n\n if (!isValid) {\n const invalidItems = getInvalidItems(items);\n const invalidSkus = invalidItems.map((item) => item.sku);\n\n setNotification({\n type: 'validation',\n variant: 'warning',\n message: t.validationError,\n clickableSkus: invalidSkus,\n });\n return;\n }\n }\n\n if (cartItems.length === 0) {\n // Only show validation error if we have items in state\n if (items.length > 0) {\n const invalidItems = getInvalidItems(items);\n const invalidSkus = invalidItems.map((item) => item.sku);\n\n setNotification({\n type: 'validation',\n variant: 'warning',\n message: t.validationError,\n clickableSkus: invalidSkus,\n });\n }\n return;\n }\n\n setNotification(null);\n\n // Only track SKUs from valid cart items that will actually be added\n const skusToAdd = cartItems\n .map((item) => item.sku)\n .filter((sku): sku is string => Boolean(sku));\n setAttemptedSkus(skusToAdd);\n\n const storageData = getOptionsFromStorage(STORAGE_KEY);\n const enrichedCartItems = enrichCartItemsWithOptions(\n cartItems,\n items,\n storageData\n );\n\n if (handleAddToCart) {\n events.emit('quick-order/loading', true);\n Promise.resolve(handleAddToCart(enrichedCartItems, clearItems))\n .then((errorMessage) => {\n if (errorMessage && typeof errorMessage === 'string') {\n setNotification({\n type: 'backend-error',\n variant: 'warning',\n message: t.backendError,\n details: errorMessage,\n });\n setAttemptedSkus([]);\n }\n })\n .catch((error) => {\n setNotification({\n type: 'backend-error',\n variant: 'warning',\n message: t.backendError,\n details: error.message || t.unexpectedError,\n });\n setAttemptedSkus([]);\n })\n .finally(() => {\n events.emit('quick-order/loading', false); // Emit loading event after add to cart process completes\n });\n } else {\n events.emit('quick-order/add-to-cart', enrichedCartItems);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [items, handleAddToCart, STORAGE_KEY]);\n\n return {\n items,\n loading,\n removeItem,\n clearItems,\n updateItemQuantity,\n addToCart,\n isItemUpdating,\n isDisabledButton,\n setDisabledCartButton,\n notification,\n dismissNotification,\n };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { FunctionComponent } from 'preact/compat';\nimport { AlertBanner } from '@adobe-commerce/elsie/components';\nimport { QuickOrderNotificationBannerProps } from '@/b2b-quick-order/types';\nimport '@/b2b-quick-order/components/QuickOrderNotificationBanner/QuickOrderNotificationBanner.css';\nimport { classes } from '@adobe-commerce/elsie/lib';\n\nexport const QuickOrderNotificationBanner: FunctionComponent<\n QuickOrderNotificationBannerProps\n> = ({\n notification,\n onDismiss,\n onSkuClick,\n validationErrorText,\n backendErrorText,\n successText,\n partialSuccessText,\n}) => {\n if (!notification) {\n return null;\n }\n\n const getMessage = () => {\n switch (notification.type) {\n case 'validation':\n return renderValidationMessage(\n validationErrorText,\n notification.clickableSkus,\n notification.details,\n onSkuClick\n );\n\n case 'partial-success':\n return renderPartialSuccessMessage(\n partialSuccessText,\n notification.message,\n notification.count,\n notification.clickableSkus,\n onSkuClick\n );\n\n case 'backend-error':\n return renderBackendErrorMessage(\n backendErrorText,\n notification.details\n );\n\n case 'success':\n return renderSuccessMessage(successText, notification.count);\n\n default:\n return <span>{notification.message}</span>;\n }\n };\n\n return (\n <div\n className={classes([\n 'b2b-quick-order-notification-banner',\n [\n `b2b-quick-order-notification-banner--${notification.variant}`,\n notification.variant,\n ],\n ])}\n >\n <AlertBanner\n variant={notification.variant}\n message={getMessage()}\n onDismiss={onDismiss}\n />\n </div>\n );\n};\n\nfunction renderClickableSkus(\n skus: string[],\n onSkuClick: (sku: string) => void\n) {\n return skus.map((sku, index) => (\n <span key={sku}>\n <a\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n onSkuClick(sku);\n }}\n style={{\n cursor: 'pointer',\n textDecoration: 'underline',\n color: 'white',\n }}\n >\n {sku}\n </a>\n {index < skus.length - 1 ? ', ' : ''}\n </span>\n ));\n}\n\nfunction renderValidationMessage(\n baseMessage: string,\n clickableSkus: string[] | undefined,\n details: string | undefined,\n onSkuClick?: (sku: string) => void\n) {\n if (clickableSkus?.length && onSkuClick) {\n return (\n <span>\n {baseMessage} - {renderClickableSkus(clickableSkus, onSkuClick)}\n </span>\n );\n }\n\n return (\n <span>\n {baseMessage} - {details}\n </span>\n );\n}\n\nfunction renderPartialSuccessMessage(\n partialSuccessText: string | undefined,\n message: string,\n count: number | undefined,\n clickableSkus: string[] | undefined,\n onSkuClick?: (sku: string) => void\n) {\n if (!partialSuccessText) {\n return <span>{message}</span>;\n }\n\n const partialMessage = partialSuccessText\n .replace('{count}', String(count || 0))\n .replace('{total}', String((count || 0) + (clickableSkus?.length || 0)));\n\n if (clickableSkus?.length && onSkuClick) {\n return (\n <span>\n {partialMessage}: {renderClickableSkus(clickableSkus, onSkuClick)}\n </span>\n );\n }\n\n return (\n <span>\n {partialMessage}: {clickableSkus?.join(', ') || 'Unknown'}\n </span>\n );\n}\n\nfunction renderBackendErrorMessage(\n backendErrorText: string,\n details: string | undefined\n) {\n return (\n <span>\n {backendErrorText}\n {details ? ` - ${details}` : ''}\n </span>\n );\n}\n\nfunction renderSuccessMessage(successText: string, count: number | undefined) {\n if (count !== undefined) {\n return <span>{successText.replace('{count}', String(count))}</span>;\n }\n return <span>{successText}</span>;\n}\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport {\n QuickOrderItemsList,\n QuickOrderNotificationBanner,\n QuickOrderDisabledOverlay,\n} from '@/b2b-quick-order/components';\nimport { useQuickOrderItems } from '@/b2b-quick-order/hooks';\nimport { QuickOrderItemsProps } from '@/b2b-quick-order/types';\nimport { config } from '@/b2b-quick-order/api/initialize';\nimport { useText } from '@adobe-commerce/elsie/i18n';\nimport { classes, Container } from '@adobe-commerce/elsie/lib';\nimport { useRef, useEffect } from 'preact/hooks';\n\nexport const QuickOrderItems: Container<QuickOrderItemsProps> = ({\n className,\n slots,\n getProductsData,\n handleAddToCart,\n productsSearch,\n searchFilter,\n}) => {\n const isQuickOrderActive = config.getConfig().quickOrderActive;\n const notificationRef = useRef<HTMLDivElement>(null);\n\n const t = useText({\n title: 'QuickOrder.QuickOrderItem.title',\n quantity: 'QuickOrder.QuickOrderItem.quantity',\n price: 'QuickOrder.QuickOrderItem.price',\n remove: 'QuickOrder.QuickOrderItem.remove',\n removeItem: 'QuickOrder.QuickOrderItem.removeItem',\n showOptions: 'QuickOrder.QuickOrderItem.showOptions',\n hideOptions: 'QuickOrder.QuickOrderItem.hideOptions',\n additionalOptions: 'QuickOrder.QuickOrderItem.additionalOptions',\n noAdditionalOptions: 'QuickOrder.QuickOrderItem.noAdditionalOptions',\n emptyList: 'QuickOrder.QuickOrderItem.emptyList',\n sku: 'QuickOrder.QuickOrderItem.sku',\n loading: 'QuickOrder.QuickOrderItem.loading',\n productNotFound: 'QuickOrder.QuickOrderItem.productNotFound',\n productNotFoundDescription:\n 'QuickOrder.QuickOrderItem.productNotFoundDescription',\n productOptions: 'QuickOrder.QuickOrderItem.productOptions',\n configurableProductError:\n 'QuickOrder.QuickOrderItem.configurableProductError',\n configurableProductErrorDescription:\n 'QuickOrder.QuickOrderItem.configurableProductErrorDescription',\n addAllToCart: 'QuickOrder.QuickOrderItem.addAllToCart',\n configurableOptionsWarning:\n 'QuickOrder.QuickOrderItem.configurableOptionsWarning',\n configurableOptionsWarningDescription:\n 'QuickOrder.QuickOrderItem.configurableOptionsWarningDescription',\n outOfStock: 'QuickOrder.QuickOrderItem.outOfStock',\n searchPlaceholder: 'QuickOrder.Search.placeholder',\n searchAriaLabel: 'QuickOrder.Search.ariaLabel',\n searchEmptyState: 'QuickOrder.Search.emptyState',\n resultsAvailable: 'QuickOrder.Search.resultsAvailable',\n resultAvailable: 'QuickOrder.Search.resultAvailable',\n srInstructions: 'QuickOrder.Search.srInstructions',\n notificationValidationError:\n 'QuickOrder.QuickOrderItem.notification.validationError',\n notificationBackendError:\n 'QuickOrder.QuickOrderItem.notification.backendError',\n notificationSuccess: 'QuickOrder.QuickOrderItem.notification.success',\n notificationPartialSuccess:\n 'QuickOrder.QuickOrderItem.notification.partialSuccess',\n disabledMessage: 'QuickOrder.QuickOrderItem.disabledMessage',\n });\n\n const {\n items,\n loading,\n removeItem,\n clearItems,\n updateItemQuantity,\n addToCart,\n isItemUpdating,\n setDisabledCartButton,\n isDisabledButton,\n notification,\n dismissNotification,\n } = useQuickOrderItems({\n getProductsData,\n handleAddToCart,\n });\n\n // Auto-scroll to notification banner when error appears\n useEffect(() => {\n if (\n notification &&\n notification.variant === 'warning' &&\n notificationRef.current\n ) {\n notificationRef.current.scrollIntoView({\n behavior: 'smooth',\n block: 'start',\n });\n }\n }, [notification]);\n\n const handleSkuClick = (sku: string) => {\n // Find the form element with matching data-sku attribute\n const formElement = document.querySelector(\n `form[data-sku=\"${sku}\"]`\n ) as HTMLElement;\n\n if (formElement) {\n // Scroll to the element with smooth behavior\n formElement.scrollIntoView({\n behavior: 'smooth',\n block: 'center',\n });\n }\n };\n\n return (\n <div\n className={classes([\n 'b2b-quick-order-quick-order-items',\n !isQuickOrderActive && 'b2b-quick-order-disabled',\n className,\n ])}\n data-testid=\"quick-order-items\"\n style={{ position: 'relative' }}\n >\n <div ref={notificationRef}>\n <QuickOrderNotificationBanner\n notification={notification}\n onDismiss={dismissNotification}\n onSkuClick={handleSkuClick}\n validationErrorText={t.notificationValidationError}\n backendErrorText={t.notificationBackendError}\n successText={t.notificationSuccess}\n partialSuccessText={t.notificationPartialSuccess}\n />\n </div>\n <QuickOrderDisabledOverlay\n isDisabled={!isQuickOrderActive}\n message={t.disabledMessage}\n >\n <QuickOrderItemsList\n t={t}\n items={items}\n onRemove={removeItem}\n clearItems={clearItems}\n onUpdateQuantity={updateItemQuantity}\n handleAddToCart={addToCart}\n isItemUpdating={isItemUpdating}\n slots={slots}\n loading={loading}\n setDisabledCartButton={setDisabledCartButton}\n isDisabledButton={isDisabledButton}\n productsSearch={productsSearch}\n searchFilter={searchFilter}\n />\n </QuickOrderDisabledOverlay>\n </div>\n );\n};\n"],"names":["STANDARD_FIELDS","processFormOptions","formData","optionUIDs","enteredOptions","value","key","valueStr","buildCartItem","quantityValue","quantity","cartItem","parentSku","DEFAULT_QUICK_ORDER_ITEM","mapProductsToOrderItems","requestedItems","products","requestedItem","foundProduct","p","validateOrderItems","items","item","opt","_a","optItem","option","optionItem","getInvalidItems","invalidItems","getItemScope","generateItemId","sku","findDuplicateItem","newItem","existing","findDuplicateItemExcluding","updatedItem","excludeItemId","mergeDuplicateItems","removeIndex","mergeIntoIndex","quantityToAdd","index","replaceOrAddItems","existingItems","newItems","inputItems","updatedItems","addedItems","replacedItems","mergedItems","inputItem","replaceIndex","existingIndex","adjustedIndex","itemWithId","updateItemInList","itemId","currentQuantity","duplicateIndex","removingIndex","prevItem","buildCartItemsFromForms","formId","form","extractOptionsUIDs","valuesData","optionsUIDs","getOptionsFromStorage","storageKey","stored","e","saveOptionsToStorage","storageData","enrichCartItemsWithOptions","cartItems","selectedOptions","isItemInvalid","hasBasicIssues","allRequiredSelected","hasSelectedOption","useQuickOrderItems","getProductsData","handleAddToCart","setItems","useState","loading","setLoading","updatingItems","setUpdatingItems","isDisabledButton","setIsDisabledButton","notification","setNotification","attemptedSkus","setAttemptedSkus","attemptedSkusRef","useRef","t","useText","STORAGE_KEY","dismissNotification","useCallback","setDisabledCartButton","disabled","useEffect","loadingEvent","events","loadingState","itemsEvent","eventPayload","requestedSkus","prev","fetchedProducts","error","invalidNewItems","invalidSkus","mergedSkus","prevItems","scope","scopesList","isValid","stillInvalidSkus","matchingItems","i","existingSkus","eventsList","event","successEvent","addedCount","addedSkus","failedSkus","errorEvent","cartDataEvent","cartData","cartSkus","skus","removeItem","identifier","clearItems","updateItemQuantity","isItemUpdating","addToCart","skusToAdd","enrichedCartItems","errorMessage","QuickOrderNotificationBanner","onDismiss","onSkuClick","validationErrorText","backendErrorText","successText","partialSuccessText","getMessage","renderValidationMessage","renderPartialSuccessMessage","renderBackendErrorMessage","renderSuccessMessage","jsx","classes","AlertBanner","renderClickableSkus","baseMessage","clickableSkus","details","message","count","partialMessage","QuickOrderItems","className","slots","productsSearch","searchFilter","isQuickOrderActive","config","notificationRef","handleSkuClick","formElement","jsxs","QuickOrderDisabledOverlay","QuickOrderItemsList"],"mappings":"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"}
1
+ {"version":3,"file":"QuickOrderItems.js","sources":["/@dropins/storefront-quick-order/src/lib/processFormOptions.ts","/@dropins/storefront-quick-order/src/lib/buildCartItem.ts","/@dropins/storefront-quick-order/src/configs/order-item.config.ts","/@dropins/storefront-quick-order/src/lib/mapProductsToOrderItems.ts","/@dropins/storefront-quick-order/src/lib/validateOrderItems.ts","/@dropins/storefront-quick-order/src/lib/getItemScope.ts","/@dropins/storefront-quick-order/src/lib/generateItemId.ts","/@dropins/storefront-quick-order/src/lib/findDuplicateItem.ts","/@dropins/storefront-quick-order/src/lib/mergeDuplicateItems.ts","/@dropins/storefront-quick-order/src/lib/replaceOrAddItems.ts","/@dropins/storefront-quick-order/src/lib/updateItemInList.ts","/@dropins/storefront-quick-order/src/lib/buildCartItemsFromForms.ts","/@dropins/storefront-quick-order/src/lib/productOptionsStorage.ts","/@dropins/storefront-quick-order/src/lib/isItemValid.ts","/@dropins/storefront-quick-order/src/hooks/useQuickOrderItems.tsx","/@dropins/storefront-quick-order/src/components/QuickOrderNotificationBanner/QuickOrderNotificationBanner.tsx","/@dropins/storefront-quick-order/src/containers/QuickOrderItems/QuickOrderItems.tsx"],"sourcesContent":["/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nconst STANDARD_FIELDS = [\n 'sku',\n 'parentSku',\n 'itemId',\n 'quantity',\n 'optionsUIDs',\n 'valid',\n 'productType',\n];\n\nexport interface ProcessedFormOptions {\n optionUIDs: string[];\n enteredOptions: { uid: string; value: string }[];\n}\n\n/**\n * Processes form data to extract product options\n * Separates base64-encoded configurable options (optionUIDs) from custom entered options\n */\nexport const processFormOptions = (\n formData: FormData\n): ProcessedFormOptions => {\n const optionUIDs: string[] = [];\n const enteredOptions: { uid: string; value: string }[] = [];\n\n formData.forEach((value, key) => {\n if (STANDARD_FIELDS.includes(key)) return;\n\n const valueStr = value as string;\n // Check if this is an option UID (base64 encoded configurable option)\n if (valueStr && valueStr.match(/^[A-Za-z0-9+/=]+$/)) {\n optionUIDs.push(valueStr);\n } else {\n enteredOptions.push({ uid: key, value: valueStr });\n }\n });\n\n return { optionUIDs, enteredOptions };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { processFormOptions } from './processFormOptions';\n\nexport interface CartItem {\n sku: string;\n quantity: number;\n itemId?: string;\n parentSku?: string;\n optionsUIDs?: string[];\n enteredOptions?: { uid: string; value: string }[];\n}\n\n/**\n * Builds a cart item object from form data\n * Extracts SKU, quantity, parent SKU, and product options\n */\nexport const buildCartItem = (formData: FormData): CartItem => {\n const quantityValue = Number(formData.get('quantity'));\n const quantity = !quantityValue || quantityValue < 1 ? 1 : quantityValue;\n\n const cartItem: CartItem = {\n sku: formData.get('sku') as string,\n quantity,\n };\n\n const itemId = formData.get('itemId');\n if (itemId) {\n cartItem.itemId = itemId as string;\n }\n\n const parentSku = formData.get('parentSku');\n if (parentSku) {\n cartItem.parentSku = parentSku as string;\n }\n\n const { optionUIDs, enteredOptions } = processFormOptions(formData);\n\n if (optionUIDs.length > 0) {\n cartItem.optionsUIDs = optionUIDs;\n }\n\n if (enteredOptions.length > 0) {\n cartItem.enteredOptions = enteredOptions;\n }\n\n return cartItem;\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types/quickOrderItems.types';\n\nexport const DEFAULT_QUICK_ORDER_ITEM: OrderItem = {\n sku: '',\n quantity: 1,\n name: '',\n images: [],\n inStock: false,\n addToCartAllowed: false,\n isBundle: false,\n prices: {} as any,\n attributes: [],\n options: [],\n url: '',\n urlKey: '',\n externalId: '',\n productType: 'simple',\n shortDescription: '',\n metaDescription: '',\n metaKeyword: '',\n metaTitle: '',\n description: '',\n} as OrderItem;\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem, OrderItemInput } from '@/b2b-quick-order/types';\nimport { DEFAULT_QUICK_ORDER_ITEM } from '@/b2b-quick-order/configs';\n\n/**\n * Maps fetched products to OrderItems\n * Creates error items for products not found in the response\n * @param requestedItems - Items that were requested\n * @param products - Products returned from API\n * @returns Array of OrderItems with proper quantity set\n */\nexport const mapProductsToOrderItems = (\n requestedItems: OrderItemInput[],\n products: OrderItem[]\n): OrderItem[] => {\n // Handle empty or undefined products array\n if (!products || !Array.isArray(products)) {\n return requestedItems.map((requestedItem) => ({\n ...DEFAULT_QUICK_ORDER_ITEM,\n sku: requestedItem.sku,\n quantity: requestedItem.quantity ?? 1,\n })) as OrderItem[];\n }\n\n return requestedItems.map((requestedItem) => {\n const foundProduct = products.find((p) => p?.sku === requestedItem?.sku);\n\n if (foundProduct) {\n // Check if this is a configurable product variant\n const hasVariant = requestedItem.variantSku || foundProduct.variantSku;\n \n return {\n ...foundProduct,\n ...(hasVariant && {\n variantSku: requestedItem.variantSku || foundProduct.variantSku,\n // Store parent SKU when product has a variant\n parentSku: foundProduct.sku,\n }),\n quantity: requestedItem.quantity ?? 1,\n };\n }\n\n // Product not found - create error item\n return {\n ...DEFAULT_QUICK_ORDER_ITEM,\n sku: requestedItem.sku,\n ...(requestedItem.variantSku && { \n variantSku: requestedItem.variantSku,\n parentSku: requestedItem.sku,\n }),\n quantity: requestedItem.quantity ?? 1,\n } as OrderItem;\n });\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\n\n/**\n * Validates order items to determine if all items are ready for cart addition\n * @param items - Array of order items to validate\n * @returns true if all items are valid, false otherwise\n */\nexport const validateOrderItems = (items: OrderItem[]): boolean => {\n if (items.length === 0) {\n return false;\n }\n\n return items.every((item) => {\n const hasBasicData = (item.urlKey || item.url) && item.name;\n if (!hasBasicData) {\n return false;\n }\n\n if (item.inStock === false) {\n return false;\n }\n\n if (item.options && item.options.length > 0) {\n const hasRequiredOptions = item.options.some((opt) => opt.required);\n\n if (hasRequiredOptions) {\n // Required options: all must be selected\n return item.options.every((opt) => {\n if (!opt.required) return true;\n return opt.items?.some((optItem) => optItem.selected);\n });\n }\n\n // Optional options: at least one must be selected\n const hasSelectedOption = item.options.some(\n (option) =>\n option.items &&\n option.items.length > 0 &&\n option.items.some((optionItem) => optionItem.selected === true)\n );\n return hasSelectedOption;\n }\n\n return true;\n });\n};\n\n/**\n * Get items that are out of stock\n * @param items - Array of order items to check\n * @returns Array of out of stock items with their names\n */\nexport const getOutOfStockItems = (\n items: OrderItem[]\n): Array<{ sku: string; name: string }> => {\n return items\n .filter((item) => item.inStock === false)\n .map((item) => ({\n sku: item.sku,\n name: item.name,\n }));\n};\n\n/**\n * Get items with missing required options\n * @param items - Array of order items to check\n * @returns Array of items missing required options\n */\nexport const getItemsMissingOptions = (\n items: OrderItem[]\n): Array<{ sku: string; name: string }> => {\n return items\n .filter((item) => {\n if (!item.options || item.options.length === 0) {\n return false;\n }\n const hasSelectedOption = item.options.some(\n (option) =>\n option.items &&\n option.items.length > 0 &&\n option.items.some((optionItem) => optionItem.selected === true)\n );\n return !hasSelectedOption;\n })\n .map((item) => ({\n sku: item.sku,\n name: item.name,\n }));\n};\n\n/**\n * Get items with incomplete data\n * @param items - Array of order items to check\n * @returns Array of items with incomplete data\n */\nexport const getItemsWithIncompleteData = (\n items: OrderItem[]\n): Array<{ sku: string; name: string }> => {\n return items\n .filter((item) => {\n const hasBasicData = (item.urlKey || item.url) && item.name;\n return !hasBasicData;\n })\n .map((item) => ({\n sku: item.sku,\n name: item.name || 'Unknown',\n }));\n};\n\n/**\n * Get all items with validation errors\n * @param items - Array of order items to check\n * @returns Array of all items with validation errors and their SKUs\n */\nexport const getInvalidItems = (\n items: OrderItem[]\n): Array<{ sku: string; name: string; reason: string }> => {\n const invalidItems: Array<{ sku: string; name: string; reason: string }> = [];\n\n items.forEach((item) => {\n const hasBasicData = (item.urlKey || item.url) && item.name;\n\n if (!hasBasicData) {\n invalidItems.push({\n sku: item.sku,\n name: item.name || 'Unknown',\n reason: 'incomplete_data',\n });\n return;\n }\n\n if (item.inStock === false) {\n invalidItems.push({\n sku: item.sku,\n name: item.name,\n reason: 'out_of_stock',\n });\n return;\n }\n\n if (item.options && item.options.length > 0) {\n const hasRequiredOptions = item.options.some((opt) => opt.required);\n\n if (hasRequiredOptions) {\n // Required options: all must be selected\n const allRequiredSelected = item.options.every((opt) => {\n if (!opt.required) return true;\n return opt.items?.some((optItem) => optItem.selected);\n });\n\n if (!allRequiredSelected) {\n invalidItems.push({\n sku: item.sku,\n name: item.name,\n reason: 'missing_required_options',\n });\n }\n return;\n }\n\n // Optional options: at least one must be selected\n const hasSelectedOption = item.options.some(\n (option) =>\n option.items &&\n option.items.length > 0 &&\n option.items.some((optionItem) => optionItem.selected === true)\n );\n if (!hasSelectedOption) {\n invalidItems.push({\n sku: item.sku,\n name: item.name,\n reason: 'missing_options',\n });\n }\n }\n });\n\n return invalidItems;\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\n\n/**\n * Get unique scope identifier for an item\n * Uses unique id if available, otherwise falls back to variantSku or sku\n */\nexport const getItemScope = (item: OrderItem): string => {\n const scopeKey = item.id || item.variantSku || item.sku;\n return `quick-order-item-${scopeKey}`;\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\n/**\n * Generate unique ID for an item\n * Format: {sku}-{timestamp}-{random}\n */\nexport const generateItemId = (sku: string): string => {\n return `${sku}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\n\n/**\n * Find duplicate item in the list based on multiple comparison strategies\n * Returns the index of the duplicate item, or -1 if not found\n *\n * Strategies:\n * 1. Both have variantSku - compare variants\n * 2. Existing has variantSku, new has sku - compare them\n * 3. New has variantSku, existing has sku - compare them\n * 4. Neither has variantSku - compare base SKU\n */\nexport const findDuplicateItem = (\n items: OrderItem[],\n newItem: OrderItem\n): number => {\n return items.findIndex((existing) => {\n // Strategy 1: Both have variantSku - compare variants\n if (newItem.variantSku && existing.variantSku) {\n return existing.variantSku === newItem.variantSku;\n }\n\n // Strategy 2: Existing has variantSku, new has sku - compare them\n // (e.g., existing configured product vs search result variant)\n if (existing.variantSku && !newItem.variantSku && newItem.sku) {\n return existing.variantSku === newItem.sku;\n }\n\n // Strategy 3: New has variantSku, existing has sku - compare them\n // (opposite of strategy 2)\n if (newItem.variantSku && !existing.variantSku && existing.sku) {\n return existing.sku === newItem.variantSku;\n }\n\n // Strategy 4: Neither has variantSku - compare base sku\n if (!newItem.variantSku && !existing.variantSku) {\n return existing.sku === newItem.sku;\n }\n\n return false;\n });\n};\n\n/**\n * Find duplicate item excluding a specific item by ID\n * Used when checking for duplicates after an item update\n */\nexport const findDuplicateItemExcluding = (\n items: OrderItem[],\n updatedItem: OrderItem,\n excludeItemId: string\n): number => {\n return items.findIndex((existing) => {\n // Skip the item being updated\n if (existing.id === excludeItemId) return false;\n\n // Check if updatedItem's variantSku matches existing item\n if (updatedItem.variantSku && existing.variantSku) {\n return existing.variantSku === updatedItem.variantSku;\n }\n\n // Check if updatedItem's variantSku matches existing item's sku\n if (updatedItem.variantSku && !existing.variantSku && existing.sku) {\n return existing.sku === updatedItem.variantSku;\n }\n\n return false;\n });\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\n\n/**\n * Merge duplicate items by removing the item at removeIndex and\n * adding its quantity to the item at mergeIntoIndex\n */\nexport const mergeDuplicateItems = (\n items: OrderItem[],\n removeIndex: number,\n mergeIntoIndex: number,\n quantityToAdd: number = 1\n): OrderItem[] => {\n const removedItem = items[removeIndex];\n \n return items\n .map((item, index) => {\n if (index === mergeIntoIndex) {\n // Increase quantity of the duplicate and preserve parentSku\n return {\n ...item,\n quantity: item.quantity + quantityToAdd,\n // Preserve parentSku from either item\n parentSku: item.parentSku || removedItem?.parentSku,\n };\n } else if (index === removeIndex) {\n // Remove the item being merged\n return null;\n }\n return item;\n })\n .filter(Boolean) as OrderItem[];\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem, OrderItemInput } from '@/b2b-quick-order/types';\nimport { findDuplicateItem } from './findDuplicateItem';\nimport { generateItemId } from './generateItemId';\n\nexport interface ReplaceOrAddItemsResult {\n updatedItems: OrderItem[];\n addedItems: OrderItem[];\n replacedItems: OrderItem[];\n mergedItems: OrderItem[];\n}\n\n/**\n * Replace, merge, or add items into existing list\n * Handles three scenarios:\n * 1. Replace: When inputItem has replaceItemSku, replace item at same position\n * - If new item already exists in list, collapse by removing replaced item and merging quantity\n * 2. Merge: When item exists, increase quantity\n * 3. Add: When item doesn't exist, add to end\n */\nexport const replaceOrAddItems = (\n existingItems: OrderItem[],\n newItems: OrderItem[],\n inputItems: OrderItemInput[]\n): ReplaceOrAddItemsResult => {\n const updatedItems = [...existingItems];\n const addedItems: OrderItem[] = [];\n const replacedItems: OrderItem[] = [];\n const mergedItems: OrderItem[] = [];\n\n newItems.forEach((newItem, index) => {\n const inputItem = inputItems[index];\n\n // Scenario 1: Replace existing item at same position\n if (inputItem?.replaceItemSku) {\n const replaceIndex = updatedItems.findIndex(\n (item) =>\n item.sku === inputItem.replaceItemSku ||\n item.id === inputItem.replaceItemSku\n );\n\n if (replaceIndex !== -1) {\n // Check if new item already exists elsewhere in the list (collapse case)\n const existingIndex = findDuplicateItem(updatedItems, newItem);\n\n if (existingIndex !== -1 && existingIndex !== replaceIndex) {\n // Item already exists - remove replaced item and merge quantity into existing\n updatedItems.splice(replaceIndex, 1);\n // Adjust index if existing item was after the removed one\n const adjustedIndex =\n existingIndex > replaceIndex ? existingIndex - 1 : existingIndex;\n updatedItems[adjustedIndex] = {\n ...updatedItems[adjustedIndex],\n quantity: updatedItems[adjustedIndex].quantity + newItem.quantity,\n // Preserve parentSku from either item\n parentSku: updatedItems[adjustedIndex].parentSku || newItem.parentSku,\n };\n mergedItems.push(updatedItems[adjustedIndex]);\n } else {\n // Replace item at the same position\n const itemWithId = {\n ...newItem,\n id: generateItemId(newItem.sku),\n };\n updatedItems[replaceIndex] = itemWithId;\n replacedItems.push(itemWithId);\n }\n return;\n }\n // If item to replace not found, fall through to add logic\n }\n\n // Scenario 2 & 3: Merge or Add\n const existingIndex = findDuplicateItem(updatedItems, newItem);\n\n if (existingIndex !== -1) {\n // Item exists - merge by increasing quantity\n updatedItems[existingIndex] = {\n ...updatedItems[existingIndex],\n quantity: updatedItems[existingIndex].quantity + newItem.quantity,\n // Preserve parentSku from either item\n parentSku: updatedItems[existingIndex].parentSku || newItem.parentSku,\n };\n mergedItems.push(updatedItems[existingIndex]);\n } else {\n // Item doesn't exist - add new with unique ID\n const itemWithId = {\n ...newItem,\n id: generateItemId(newItem.sku),\n };\n updatedItems.push(itemWithId);\n addedItems.push(itemWithId);\n }\n });\n\n return { updatedItems, addedItems, replacedItems, mergedItems };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\nimport { findDuplicateItemExcluding } from './findDuplicateItem';\nimport { mergeDuplicateItems } from './mergeDuplicateItems';\n\nexport interface UpdateItemResult {\n updatedItems: OrderItem[];\n wasMerged: boolean;\n mergedIntoIndex?: number;\n}\n\n/**\n * Update a specific item in the list and check for duplicates\n * If duplicate is found, merge the items\n */\nexport const updateItemInList = (\n items: OrderItem[],\n itemId: string,\n updatedItem: OrderItem,\n currentQuantity: number = 1\n): UpdateItemResult => {\n // Check if the updated item's variantSku matches another existing item\n const duplicateIndex = itemId\n ? findDuplicateItemExcluding(items, updatedItem, itemId)\n : -1;\n\n if (duplicateIndex !== -1) {\n // Find the index of the item being updated\n const removingIndex = items.findIndex((prevItem) => prevItem.id === itemId);\n\n // Duplicate found - merge items\n return {\n updatedItems: mergeDuplicateItems(\n items,\n removingIndex,\n duplicateIndex,\n currentQuantity\n ),\n wasMerged: true,\n mergedIntoIndex: duplicateIndex,\n };\n }\n\n // No duplicate - just update the item\n const updatedItems = items.map((prevItem) => {\n if (itemId && prevItem.id === itemId) {\n // Match by ID - update with preserved ID and parentSku\n return {\n ...prevItem,\n ...updatedItem,\n id: itemId,\n // Preserve or set parentSku:\n // - If updatedItem has parentSku, use it\n // - If prevItem has parentSku, keep it\n // - If updatedItem has variantSku but no parentSku, use prevItem.sku as parent\n parentSku: updatedItem.parentSku !== undefined \n ? updatedItem.parentSku \n : prevItem.parentSku || (updatedItem.variantSku ? prevItem.sku : undefined),\n };\n } else if (!itemId && prevItem.sku === updatedItem.sku) {\n // Fallback for items without ID (backward compatibility)\n return {\n ...prevItem,\n ...updatedItem,\n // Preserve or set parentSku (same logic as above)\n parentSku: updatedItem.parentSku !== undefined \n ? updatedItem.parentSku \n : prevItem.parentSku || (updatedItem.variantSku ? prevItem.sku : undefined),\n };\n }\n return prevItem;\n });\n\n return {\n updatedItems,\n wasMerged: false,\n };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\nimport { buildCartItem } from './buildCartItem';\n\n/**\n * Build cart items from forms for all order items\n * Only includes valid items (items with valid forms)\n */\nexport const buildCartItemsFromForms = (items: OrderItem[]) => {\n return items.map((item) => {\n const formId = item.id || item.sku;\n const form = document.forms[`form-${formId}` as any] as HTMLFormElement;\n if (!form) return null;\n\n const formData = new FormData(form);\n const isValid = formData.get('valid') === 'true';\n\n return isValid ? buildCartItem(formData) : null;\n });\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\n/**\n * Extract optionsUIDs from various data formats\n */\nexport const extractOptionsUIDs = (valuesData: any): string[] => {\n let optionsUIDs: string[] = [];\n\n if (valuesData && typeof valuesData === 'object') {\n if (valuesData.optionsUIDs && Array.isArray(valuesData.optionsUIDs)) {\n optionsUIDs = valuesData.optionsUIDs;\n } else if (Array.isArray(valuesData)) {\n optionsUIDs = valuesData;\n }\n } else if (typeof valuesData === 'string') {\n optionsUIDs = [valuesData];\n }\n\n return optionsUIDs;\n};\n\n/**\n * Get options from localStorage\n */\nexport const getOptionsFromStorage = (\n storageKey: string\n): Record<string, string[]> => {\n try {\n const stored = localStorage.getItem(storageKey);\n if (stored) {\n return JSON.parse(stored);\n }\n } catch (e) {\n console.error('Error reading from localStorage:', e);\n }\n return {};\n};\n\n/**\n * Save options to localStorage\n */\nexport const saveOptionsToStorage = (\n storageKey: string,\n itemId: string,\n optionsUIDs: string[]\n): void => {\n if (optionsUIDs.length === 0) {\n return;\n }\n\n try {\n const storageData = getOptionsFromStorage(storageKey);\n storageData[itemId] = optionsUIDs;\n localStorage.setItem(storageKey, JSON.stringify(storageData));\n } catch (e) {\n console.error('Error saving to localStorage:', e);\n }\n};\n\n/**\n * Remove options from localStorage for a specific item\n */\nexport const removeOptionsFromStorage = (\n storageKey: string,\n itemId: string\n): void => {\n try {\n const storageData = getOptionsFromStorage(storageKey);\n delete storageData[itemId];\n localStorage.setItem(storageKey, JSON.stringify(storageData));\n } catch (e) {\n console.error('Error removing from localStorage:', e);\n }\n};\n\n/**\n * Enrich cart items with selected options from storage\n */\nexport const enrichCartItemsWithOptions = <T extends { sku: string; itemId?: string }>(\n cartItems: T[],\n items: Array<{ id?: string; sku: string; variantSku?: string; parentSku?: string }>,\n storageData: Record<string, string[]>\n): Array<T & { optionsUIDs?: string[]; parentSku?: string }> => {\n return cartItems.map((cartItem) => {\n // First try to find by itemId (most reliable, doesn't change when variant changes)\n let item = cartItem.itemId \n ? items.find((i) => (i.id || i.sku) === cartItem.itemId)\n : undefined;\n \n // Fallback to SKU matching if itemId not available or not found\n if (!item) {\n item = items.find((i) => {\n return cartItem.sku === i.sku || cartItem.sku === i.variantSku;\n });\n }\n\n if (item) {\n const itemId = item.id || item.sku;\n const selectedOptions = storageData[itemId];\n\n const enrichedItem: T & { optionsUIDs?: string[]; parentSku?: string } = {\n ...cartItem,\n };\n\n if (selectedOptions && selectedOptions.length > 0) {\n enrichedItem.optionsUIDs = selectedOptions;\n }\n\n // Always add parentSku if available\n if (item.parentSku) {\n enrichedItem.parentSku = item.parentSku;\n }\n\n return enrichedItem;\n }\n\n return cartItem;\n });\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { OrderItem } from '@/b2b-quick-order/types';\n\n/**\n * Check if an item is valid for adding to cart\n * @param item - The order item to validate\n * @returns true if item is invalid (should stay in notification), false if valid\n */\nexport const isItemInvalid = (item: OrderItem): boolean => {\n const hasBasicIssues = !item.inStock || !item.addToCartAllowed;\n\n if (item.options && item.options.length > 0) {\n // Options must be loaded before validation\n const optionsNotReady = item.options.some(\n (opt) => !opt.items || opt.items.length === 0\n );\n\n if (optionsNotReady) {\n return true;\n }\n\n const hasRequiredOptions = item.options.some((opt) => opt.required);\n\n if (hasRequiredOptions) {\n // Required options: all must be selected\n const allRequiredSelected = item.options.every((opt) => {\n if (!opt.required) return true;\n return opt.items?.some((optItem) => optItem.selected);\n });\n return hasBasicIssues || !allRequiredSelected;\n }\n\n // Optional options: at least one must be selected\n const hasSelectedOption = item.options.some(\n (option) =>\n option.items &&\n option.items.length > 0 &&\n option.items.some((optionItem) => optionItem.selected === true)\n );\n return hasBasicIssues || !hasSelectedOption;\n }\n\n return hasBasicIssues;\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { useCallback, useEffect, useRef, useState } from 'preact/hooks';\nimport {\n OrderItemInput,\n OrderItem,\n UseQuickOrderItemsProps,\n UseQuickOrderItemsReturn,\n} from '@/b2b-quick-order/types';\nimport { events } from '@adobe-commerce/event-bus';\nimport { useText } from '@adobe-commerce/elsie/i18n';\nimport {\n mapProductsToOrderItems,\n validateOrderItems,\n getItemScope,\n replaceOrAddItems,\n updateItemInList,\n buildCartItemsFromForms,\n extractOptionsUIDs,\n saveOptionsToStorage,\n getOptionsFromStorage,\n enrichCartItemsWithOptions,\n getInvalidItems,\n isItemInvalid,\n} from '@/b2b-quick-order/lib';\n\nexport const useQuickOrderItems = ({\n getProductsData,\n handleAddToCart,\n}: UseQuickOrderItemsProps = {}): UseQuickOrderItemsReturn => {\n const [items, setItems] = useState<OrderItem[]>([]);\n const [loading, setLoading] = useState(false);\n const [updatingItems, setUpdatingItems] = useState<Set<string>>(new Set());\n const [isDisabledButton, setIsDisabledButton] = useState(false);\n const [notification, setNotification] = useState<{\n type: 'validation' | 'partial-success' | 'success' | 'backend-error';\n variant: 'success' | 'warning' | 'neutral' | 'brand';\n message: string;\n details?: string;\n count?: number;\n clickableSkus?: string[];\n } | null>(null);\n const [attemptedSkus, setAttemptedSkus] = useState<string[]>([]);\n const attemptedSkusRef = useRef<string[]>([]);\n\n const t = useText({\n validationError: 'QuickOrder.QuickOrderItem.notification.validationError',\n backendError: 'QuickOrder.QuickOrderItem.notification.backendError',\n success: 'QuickOrder.QuickOrderItem.notification.success',\n partialSuccess: 'QuickOrder.QuickOrderItem.notification.partialSuccess',\n unexpectedError: 'QuickOrder.QuickOrderItem.notification.unexpectedError',\n });\n\n const STORAGE_KEY = 'quick-order-selected-options';\n\n const dismissNotification = useCallback(() => {\n setNotification(null);\n }, []);\n\n const setDisabledCartButton = useCallback((disabled: boolean) => {\n setIsDisabledButton(disabled);\n }, []);\n\n useEffect(() => {\n const loadingEvent = events.on(\n 'quick-order/loading',\n (loadingState) => {\n setLoading(loadingState);\n },\n {\n eager: true,\n }\n );\n return () => {\n loadingEvent?.off();\n };\n }, []);\n\n useEffect(() => {\n const itemsEvent = events.on(\n 'quick-order/add-items',\n async (eventPayload: OrderItemInput[]) => {\n if (eventPayload && eventPayload.length > 0) {\n if (!getProductsData) {\n return;\n }\n\n setLoading(true);\n events.emit('quick-order/loading', true);\n const requestedSkus = eventPayload\n .map((item) => item.variantSku || item.sku)\n .filter(Boolean);\n setUpdatingItems(\n (prev) => new Set([...Array.from(prev), ...requestedSkus])\n );\n\n try {\n let newItems: OrderItem[] = [];\n try {\n const fetchedProducts =\n (await getProductsData(eventPayload)) ?? [];\n setDisabledCartButton(\n eventPayload.length !== fetchedProducts.length\n );\n newItems = mapProductsToOrderItems(eventPayload, fetchedProducts);\n } catch (error) {\n console.error('Error fetching products data:', error);\n newItems = mapProductsToOrderItems(eventPayload, []);\n }\n\n const invalidNewItems = getInvalidItems(newItems);\n if (invalidNewItems.length > 0) {\n const invalidSkus = invalidNewItems.map((item) => item.sku);\n setNotification((prev) => {\n if (prev?.type === 'validation' && prev.clickableSkus) {\n // Merge with existing validation SKUs\n const mergedSkus = [\n ...new Set([...prev.clickableSkus, ...invalidSkus]),\n ];\n return {\n ...prev,\n clickableSkus: mergedSkus,\n };\n }\n return {\n type: 'validation',\n variant: 'warning',\n message: t.validationError,\n clickableSkus: invalidSkus,\n };\n });\n }\n\n setItems((prevItems) => {\n const { updatedItems, addedItems, mergedItems, replacedItems } =\n replaceOrAddItems(prevItems, newItems, eventPayload);\n\n replacedItems.forEach((item) => {\n const scope = getItemScope(item);\n events.emit(`${scope}/pdp/data`, item);\n });\n\n mergedItems.forEach((item) => {\n const scope = getItemScope(item);\n events.emit(`${scope}/pdp/data`, item);\n });\n\n addedItems.forEach((item) => {\n const scope = getItemScope(item);\n events.emit(`${scope}/pdp/data`, item);\n });\n\n return updatedItems;\n });\n } finally {\n setLoading(false);\n events.emit('quick-order/loading', false);\n setUpdatingItems(\n (prev) =>\n new Set(\n Array.from(prev).filter((sku) => !requestedSkus.includes(sku))\n )\n );\n }\n }\n },\n {\n eager: true,\n }\n );\n\n return () => {\n itemsEvent?.off();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [getProductsData, setDisabledCartButton]);\n\n useEffect(() => {\n const scopesList = items.map((item) => {\n const scope = getItemScope(item);\n const itemId = item.id; // Capture the specific item's ID for this listener\n\n return events.on(`${scope}/pdp/data`, (updatedItem: OrderItem) => {\n setItems((prevItems) => {\n const result = updateItemInList(\n prevItems,\n itemId || '',\n updatedItem,\n item.quantity || 1\n );\n return result.updatedItems;\n });\n });\n });\n\n return () => {\n scopesList?.forEach((scope) => {\n scope?.off();\n });\n };\n }, [items, STORAGE_KEY]);\n\n useEffect(() => {\n const isValid = validateOrderItems(items);\n setDisabledCartButton(!isValid);\n }, [items, setDisabledCartButton]);\n\n useEffect(() => {\n setNotification((prev) => {\n // Only process notifications with clickable SKUs\n if (!prev || !prev.clickableSkus || prev.clickableSkus.length === 0) {\n return prev;\n }\n\n const stillInvalidSkus = prev.clickableSkus.filter((sku) => {\n // Find ALL items with this SKU (could be multiple for configurable products)\n const matchingItems = items.filter(\n (i) => i.sku === sku || i.variantSku === sku\n );\n if (matchingItems.length === 0) return false; // Item removed\n\n // Keep SKU in notification if ANY matching item is invalid\n return matchingItems.some((item) => isItemInvalid(item));\n });\n\n // Clear notification only if all SKUs are valid\n if (stillInvalidSkus.length === 0) {\n return null;\n }\n\n // Update notification if SKUs changed\n if (stillInvalidSkus.length !== prev.clickableSkus.length) {\n return {\n ...prev,\n clickableSkus: stillInvalidSkus,\n };\n }\n\n return prev;\n });\n }, [items]);\n\n useEffect(() => {\n // If Add to Cart button is disabled and there are items,\n // but no validation notification is shown - display it\n if (!isDisabledButton || items.length === 0) {\n return;\n }\n\n setNotification((prev) => {\n // Don't override existing validation/partial-success notifications\n if (\n prev &&\n (prev.type === 'validation' || prev.type === 'partial-success')\n ) {\n return prev;\n }\n\n const invalidItems = getInvalidItems(items);\n if (invalidItems.length === 0) {\n return prev;\n }\n\n const invalidSkus = [...new Set(invalidItems.map((item) => item.sku))];\n\n // Only set notification if it doesn't already have the same SKUs\n const existingSkus = prev?.clickableSkus || [];\n const hasChanges =\n invalidSkus.length !== existingSkus.length ||\n !invalidSkus.every((sku) => existingSkus.includes(sku));\n\n if (hasChanges) {\n return {\n type: 'validation',\n variant: 'warning',\n message: t.validationError,\n clickableSkus: invalidSkus,\n };\n }\n\n return prev;\n });\n }, [isDisabledButton, items, t.validationError]);\n\n useEffect(() => {\n const eventsList = items.map((item) => {\n const scope = getItemScope(item);\n const itemId = item.id || item.sku;\n\n return events.on(`${scope}/pdp/values`, (valuesData: any) => {\n const optionsUIDs = extractOptionsUIDs(valuesData);\n saveOptionsToStorage(STORAGE_KEY, itemId, optionsUIDs);\n });\n });\n\n return () => {\n eventsList.forEach((event) => {\n event?.off();\n });\n };\n }, [items, STORAGE_KEY]);\n\n useEffect(() => {\n attemptedSkusRef.current = attemptedSkus;\n }, [attemptedSkus]);\n\n useEffect(() => {\n const successEvent = events.on('cart/product/added', (products: any[]) => {\n const addedCount = Array.isArray(products) ? products.length : 0;\n const addedSkus = Array.isArray(products)\n ? products.map((p: any) => p.sku).filter(Boolean)\n : [];\n\n if (attemptedSkusRef.current.length > 0) {\n // Count occurrences of each SKU in attempted and added arrays\n const attemptedSkuCounts = attemptedSkusRef.current.reduce((acc, sku) => {\n acc[sku] = (acc[sku] || 0) + 1;\n return acc;\n }, {} as Record<string, number>);\n\n const addedSkuCounts = addedSkus.reduce((acc, sku) => {\n acc[sku] = (acc[sku] || 0) + 1;\n return acc;\n }, {} as Record<string, number>);\n\n // Find SKUs that weren't fully added (attempted count > added count)\n const failedSkus: string[] = [];\n Object.keys(attemptedSkuCounts).forEach((sku) => {\n const attempted = attemptedSkuCounts[sku];\n const added = addedSkuCounts[sku] || 0;\n const failedCount = attempted - added;\n \n // Add the SKU to failedSkus for each failed attempt\n for (let i = 0; i < failedCount; i++) {\n failedSkus.push(sku);\n }\n });\n\n if (failedSkus.length > 0 && addedCount > 0) {\n setNotification({\n type: 'partial-success',\n variant: 'warning',\n message: t.partialSuccess,\n count: addedCount,\n clickableSkus: failedSkus,\n });\n setAttemptedSkus([]);\n }\n } else {\n // No tracking context - ignore event\n return;\n }\n });\n\n const errorEvent = events.on(\n 'quick-order/add-to-cart-error',\n (error: { message: string }) => {\n setNotification({\n type: 'backend-error',\n variant: 'warning',\n message: t.backendError,\n details: error.message,\n });\n setAttemptedSkus([]);\n }\n );\n\n return () => {\n successEvent?.off();\n errorEvent?.off();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [attemptedSkus]);\n\n useEffect(() => {\n const cartDataEvent = events.on(\n 'cart/data',\n (cartData: any) => {\n if (\n attemptedSkusRef.current.length === 0 ||\n !cartData?.items ||\n cartData.items.length === 0\n ) {\n return;\n }\n\n // For configurable products, check both variant SKU and parent SKU\n const cartSkus = cartData.items.flatMap((item: any) => {\n const skus = [];\n if (item.sku) skus.push(item.sku);\n if (item.product?.sku) skus.push(item.product.sku);\n return skus;\n });\n\n const addedSkus = attemptedSkusRef.current.filter((sku) =>\n cartSkus.includes(sku)\n );\n\n if (addedSkus.length === 0) {\n return;\n }\n\n setNotification({\n type: 'success',\n variant: 'success',\n message: t.success,\n count: addedSkus.length,\n });\n\n setAttemptedSkus([]);\n events.emit('quick-order/loading', false);\n },\n {\n eager: true,\n }\n );\n\n return () => {\n cartDataEvent?.off();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const removeItem = useCallback((identifier: string) => {\n setItems((prevItems) =>\n prevItems.filter(\n (item) => item.id !== identifier && item.sku !== identifier\n )\n );\n }, []);\n\n const clearItems = useCallback(() => {\n setItems([]);\n setNotification(null);\n }, []);\n\n const updateItemQuantity = useCallback((sku: string, quantity: number) => {\n setItems((prevItems) =>\n prevItems.map((item) => {\n const itemCurrentSku = item.variantSku || item.sku;\n return itemCurrentSku === sku ? { ...item, quantity } : item;\n })\n );\n }, []);\n\n const isItemUpdating = useCallback(\n (sku: string) => {\n return updatingItems.has(sku);\n },\n [updatingItems]\n );\n\n const addToCart = useCallback(() => {\n const cartItems = buildCartItemsFromForms(items).filter(\n (item): item is NonNullable<typeof item> => item !== null\n );\n\n if (items.length > 0) {\n const isValid = validateOrderItems(items);\n\n if (!isValid) {\n const invalidItems = getInvalidItems(items);\n const invalidSkus = invalidItems.map((item) => item.sku);\n\n setNotification({\n type: 'validation',\n variant: 'warning',\n message: t.validationError,\n clickableSkus: invalidSkus,\n });\n return;\n }\n }\n\n if (cartItems.length === 0) {\n // Only show validation error if we have items in state\n if (items.length > 0) {\n const invalidItems = getInvalidItems(items);\n const invalidSkus = invalidItems.map((item) => item.sku);\n\n setNotification({\n type: 'validation',\n variant: 'warning',\n message: t.validationError,\n clickableSkus: invalidSkus,\n });\n }\n return;\n }\n\n setNotification(null);\n\n // Track SKUs with their count to handle duplicate SKUs correctly\n const skusToAdd = cartItems\n .map((item) => item.sku)\n .filter((sku): sku is string => Boolean(sku));\n setAttemptedSkus(skusToAdd);\n\n const storageData = getOptionsFromStorage(STORAGE_KEY);\n const enrichedCartItems = enrichCartItemsWithOptions(\n cartItems,\n items,\n storageData\n );\n\n if (handleAddToCart) {\n events.emit('quick-order/loading', true);\n Promise.resolve(handleAddToCart(enrichedCartItems, clearItems))\n .then((errorMessage) => {\n if (errorMessage && typeof errorMessage === 'string') {\n setNotification({\n type: 'backend-error',\n variant: 'warning',\n message: t.backendError,\n details: errorMessage,\n });\n setAttemptedSkus([]);\n } else {\n // Success - clear attempted SKUs to prevent false warnings from cart/product/added event\n setAttemptedSkus([]);\n }\n })\n .catch((error) => {\n setNotification({\n type: 'backend-error',\n variant: 'warning',\n message: t.backendError,\n details: error.message || t.unexpectedError,\n });\n setAttemptedSkus([]);\n })\n .finally(() => {\n events.emit('quick-order/loading', false); // Emit loading event after add to cart process completes\n });\n } else {\n events.emit('quick-order/add-to-cart', enrichedCartItems);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [items, handleAddToCart, STORAGE_KEY]);\n\n return {\n items,\n loading,\n removeItem,\n clearItems,\n updateItemQuantity,\n addToCart,\n isItemUpdating,\n isDisabledButton,\n setDisabledCartButton,\n notification,\n dismissNotification,\n };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { FunctionComponent } from 'preact/compat';\nimport { AlertBanner } from '@adobe-commerce/elsie/components';\nimport { QuickOrderNotificationBannerProps } from '@/b2b-quick-order/types';\nimport '@/b2b-quick-order/components/QuickOrderNotificationBanner/QuickOrderNotificationBanner.css';\nimport { classes } from '@adobe-commerce/elsie/lib';\n\nexport const QuickOrderNotificationBanner: FunctionComponent<\n QuickOrderNotificationBannerProps\n> = ({\n notification,\n onDismiss,\n onSkuClick,\n validationErrorText,\n backendErrorText,\n successText,\n partialSuccessText,\n}) => {\n if (!notification) {\n return null;\n }\n\n const getMessage = () => {\n switch (notification.type) {\n case 'validation':\n return renderValidationMessage(\n validationErrorText,\n notification.clickableSkus,\n notification.details,\n onSkuClick\n );\n\n case 'partial-success':\n return renderPartialSuccessMessage(\n partialSuccessText,\n notification.message,\n notification.count,\n notification.clickableSkus,\n onSkuClick\n );\n\n case 'backend-error':\n return renderBackendErrorMessage(\n backendErrorText,\n notification.details\n );\n\n case 'success':\n return renderSuccessMessage(successText, notification.count);\n\n default:\n return <span>{notification.message}</span>;\n }\n };\n\n return (\n <div\n className={classes([\n 'b2b-quick-order-notification-banner',\n [\n `b2b-quick-order-notification-banner--${notification.variant}`,\n notification.variant,\n ],\n ])}\n >\n <AlertBanner\n variant={notification.variant}\n message={getMessage()}\n onDismiss={onDismiss}\n />\n </div>\n );\n};\n\nfunction renderClickableSkus(\n skus: string[],\n onSkuClick: (sku: string) => void\n) {\n return skus.map((sku, index) => (\n <span key={sku}>\n <a\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n onSkuClick(sku);\n }}\n style={{\n cursor: 'pointer',\n textDecoration: 'underline',\n color: 'white',\n }}\n >\n {sku}\n </a>\n {index < skus.length - 1 ? ', ' : ''}\n </span>\n ));\n}\n\nfunction renderValidationMessage(\n baseMessage: string,\n clickableSkus: string[] | undefined,\n details: string | undefined,\n onSkuClick?: (sku: string) => void\n) {\n if (clickableSkus?.length && onSkuClick) {\n return (\n <span>\n {baseMessage} - {renderClickableSkus(clickableSkus, onSkuClick)}\n </span>\n );\n }\n\n return (\n <span>\n {baseMessage} - {details}\n </span>\n );\n}\n\nfunction renderPartialSuccessMessage(\n partialSuccessText: string | undefined,\n message: string,\n count: number | undefined,\n clickableSkus: string[] | undefined,\n onSkuClick?: (sku: string) => void\n) {\n if (!partialSuccessText) {\n return <span>{message}</span>;\n }\n\n const partialMessage = partialSuccessText\n .replace('{count}', String(count || 0))\n .replace('{total}', String((count || 0) + (clickableSkus?.length || 0)));\n\n if (clickableSkus?.length && onSkuClick) {\n return (\n <span>\n {partialMessage}: {renderClickableSkus(clickableSkus, onSkuClick)}\n </span>\n );\n }\n\n return (\n <span>\n {partialMessage}: {clickableSkus?.join(', ') || 'Unknown'}\n </span>\n );\n}\n\nfunction renderBackendErrorMessage(\n backendErrorText: string,\n details: string | undefined\n) {\n return (\n <span>\n {backendErrorText}\n {details ? ` - ${details}` : ''}\n </span>\n );\n}\n\nfunction renderSuccessMessage(successText: string, count: number | undefined) {\n if (count !== undefined) {\n return <span>{successText.replace('{count}', String(count))}</span>;\n }\n return <span>{successText}</span>;\n}\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport {\n QuickOrderItemsList,\n QuickOrderNotificationBanner,\n QuickOrderDisabledOverlay,\n} from '@/b2b-quick-order/components';\nimport { useQuickOrderItems } from '@/b2b-quick-order/hooks';\nimport { QuickOrderItemsProps } from '@/b2b-quick-order/types';\nimport { config } from '@/b2b-quick-order/api/initialize';\nimport { useText } from '@adobe-commerce/elsie/i18n';\nimport { classes, Container } from '@adobe-commerce/elsie/lib';\nimport { useRef, useEffect } from 'preact/hooks';\n\nexport const QuickOrderItems: Container<QuickOrderItemsProps> = ({\n className,\n slots,\n getProductsData,\n handleAddToCart,\n productsSearch,\n searchFilter,\n}) => {\n const isQuickOrderActive = config.getConfig().quickOrderActive;\n const notificationRef = useRef<HTMLDivElement>(null);\n\n const t = useText({\n title: 'QuickOrder.QuickOrderItem.title',\n quantity: 'QuickOrder.QuickOrderItem.quantity',\n price: 'QuickOrder.QuickOrderItem.price',\n remove: 'QuickOrder.QuickOrderItem.remove',\n removeItem: 'QuickOrder.QuickOrderItem.removeItem',\n showOptions: 'QuickOrder.QuickOrderItem.showOptions',\n hideOptions: 'QuickOrder.QuickOrderItem.hideOptions',\n additionalOptions: 'QuickOrder.QuickOrderItem.additionalOptions',\n noAdditionalOptions: 'QuickOrder.QuickOrderItem.noAdditionalOptions',\n emptyList: 'QuickOrder.QuickOrderItem.emptyList',\n sku: 'QuickOrder.QuickOrderItem.sku',\n loading: 'QuickOrder.QuickOrderItem.loading',\n productNotFound: 'QuickOrder.QuickOrderItem.productNotFound',\n productNotFoundDescription:\n 'QuickOrder.QuickOrderItem.productNotFoundDescription',\n productOptions: 'QuickOrder.QuickOrderItem.productOptions',\n configurableProductError:\n 'QuickOrder.QuickOrderItem.configurableProductError',\n configurableProductErrorDescription:\n 'QuickOrder.QuickOrderItem.configurableProductErrorDescription',\n addAllToCart: 'QuickOrder.QuickOrderItem.addAllToCart',\n configurableOptionsWarning:\n 'QuickOrder.QuickOrderItem.configurableOptionsWarning',\n configurableOptionsWarningDescription:\n 'QuickOrder.QuickOrderItem.configurableOptionsWarningDescription',\n outOfStock: 'QuickOrder.QuickOrderItem.outOfStock',\n searchPlaceholder: 'QuickOrder.Search.placeholder',\n searchAriaLabel: 'QuickOrder.Search.ariaLabel',\n searchEmptyState: 'QuickOrder.Search.emptyState',\n resultsAvailable: 'QuickOrder.Search.resultsAvailable',\n resultAvailable: 'QuickOrder.Search.resultAvailable',\n srInstructions: 'QuickOrder.Search.srInstructions',\n notificationValidationError:\n 'QuickOrder.QuickOrderItem.notification.validationError',\n notificationBackendError:\n 'QuickOrder.QuickOrderItem.notification.backendError',\n notificationSuccess: 'QuickOrder.QuickOrderItem.notification.success',\n notificationPartialSuccess:\n 'QuickOrder.QuickOrderItem.notification.partialSuccess',\n disabledMessage: 'QuickOrder.QuickOrderItem.disabledMessage',\n });\n\n const {\n items,\n loading,\n removeItem,\n clearItems,\n updateItemQuantity,\n addToCart,\n isItemUpdating,\n setDisabledCartButton,\n isDisabledButton,\n notification,\n dismissNotification,\n } = useQuickOrderItems({\n getProductsData,\n handleAddToCart,\n });\n\n // Auto-scroll to notification banner when error appears\n useEffect(() => {\n if (\n notification &&\n notification.variant === 'warning' &&\n notificationRef.current\n ) {\n notificationRef.current.scrollIntoView({\n behavior: 'smooth',\n block: 'start',\n });\n }\n }, [notification]);\n\n const handleSkuClick = (sku: string) => {\n // Find the form element with matching data-sku attribute\n const formElement = document.querySelector(\n `form[data-sku=\"${sku}\"]`\n ) as HTMLElement;\n\n if (formElement) {\n // Scroll to the element with smooth behavior\n formElement.scrollIntoView({\n behavior: 'smooth',\n block: 'center',\n });\n }\n };\n\n return (\n <div\n className={classes([\n 'b2b-quick-order-quick-order-items',\n !isQuickOrderActive && 'b2b-quick-order-disabled',\n className,\n ])}\n data-testid=\"quick-order-items\"\n style={{ position: 'relative' }}\n >\n <div ref={notificationRef}>\n <QuickOrderNotificationBanner\n notification={notification}\n onDismiss={dismissNotification}\n onSkuClick={handleSkuClick}\n validationErrorText={t.notificationValidationError}\n backendErrorText={t.notificationBackendError}\n successText={t.notificationSuccess}\n partialSuccessText={t.notificationPartialSuccess}\n />\n </div>\n <QuickOrderDisabledOverlay\n isDisabled={!isQuickOrderActive}\n message={t.disabledMessage}\n >\n <QuickOrderItemsList\n t={t}\n items={items}\n onRemove={removeItem}\n clearItems={clearItems}\n onUpdateQuantity={updateItemQuantity}\n handleAddToCart={addToCart}\n isItemUpdating={isItemUpdating}\n slots={slots}\n loading={loading}\n setDisabledCartButton={setDisabledCartButton}\n isDisabledButton={isDisabledButton}\n productsSearch={productsSearch}\n searchFilter={searchFilter}\n />\n </QuickOrderDisabledOverlay>\n </div>\n );\n};\n"],"names":["STANDARD_FIELDS","processFormOptions","formData","optionUIDs","enteredOptions","value","key","valueStr","buildCartItem","quantityValue","quantity","cartItem","itemId","parentSku","DEFAULT_QUICK_ORDER_ITEM","mapProductsToOrderItems","requestedItems","products","requestedItem","foundProduct","p","hasVariant","validateOrderItems","items","item","opt","_a","optItem","option","optionItem","getInvalidItems","invalidItems","getItemScope","generateItemId","sku","findDuplicateItem","newItem","existing","findDuplicateItemExcluding","updatedItem","excludeItemId","mergeDuplicateItems","removeIndex","mergeIntoIndex","quantityToAdd","removedItem","index","replaceOrAddItems","existingItems","newItems","inputItems","updatedItems","addedItems","replacedItems","mergedItems","inputItem","replaceIndex","existingIndex","adjustedIndex","itemWithId","updateItemInList","currentQuantity","duplicateIndex","removingIndex","prevItem","buildCartItemsFromForms","formId","form","extractOptionsUIDs","valuesData","optionsUIDs","getOptionsFromStorage","storageKey","stored","e","saveOptionsToStorage","storageData","enrichCartItemsWithOptions","cartItems","selectedOptions","enrichedItem","isItemInvalid","hasBasicIssues","allRequiredSelected","hasSelectedOption","useQuickOrderItems","getProductsData","handleAddToCart","setItems","useState","loading","setLoading","updatingItems","setUpdatingItems","isDisabledButton","setIsDisabledButton","notification","setNotification","attemptedSkus","setAttemptedSkus","attemptedSkusRef","useRef","t","useText","STORAGE_KEY","dismissNotification","useCallback","setDisabledCartButton","disabled","useEffect","loadingEvent","events","loadingState","itemsEvent","eventPayload","requestedSkus","prev","fetchedProducts","error","invalidNewItems","invalidSkus","mergedSkus","prevItems","scope","scopesList","isValid","stillInvalidSkus","matchingItems","i","existingSkus","eventsList","event","successEvent","addedCount","addedSkus","attemptedSkuCounts","acc","addedSkuCounts","failedSkus","attempted","added","failedCount","errorEvent","cartDataEvent","cartData","cartSkus","skus","removeItem","identifier","clearItems","updateItemQuantity","isItemUpdating","addToCart","skusToAdd","enrichedCartItems","errorMessage","QuickOrderNotificationBanner","onDismiss","onSkuClick","validationErrorText","backendErrorText","successText","partialSuccessText","getMessage","renderValidationMessage","renderPartialSuccessMessage","renderBackendErrorMessage","renderSuccessMessage","jsx","classes","AlertBanner","renderClickableSkus","baseMessage","clickableSkus","details","message","count","partialMessage","QuickOrderItems","className","slots","productsSearch","searchFilter","isQuickOrderActive","config","notificationRef","handleSkuClick","formElement","jsxs","QuickOrderDisabledOverlay","QuickOrderItemsList"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  /*! Copyright 2026 Adobe
2
2
  All Rights Reserved. */
3
- import{jsxs as j,jsx as D}from"@dropins/tools/preact-jsx-runtime.js";import{classes as U}from"@dropins/tools/lib.js";import{d as L,Q as $,a as W}from"../chunks/debounce.js";import{useState as x,useRef as w,useEffect as v,useMemo as R,useCallback as O}from"@dropins/tools/preact-hooks.js";import{events as g}from"@dropins/tools/event-bus.js";import{useText as N}from"@dropins/tools/i18n.js";import"@dropins/tools/preact-compat.js";import"@dropins/tools/components.js";const E=({initialVariants:s,onVariantsLoaded:l,onSelectedVariantsChange:k,debounceMs:Q=300,initialLoading:h=!0}={})=>{const[c,d]=x([]),a=w([]),[q,b]=x(h),m=w(!1),o=w(null);v(()=>{s&&s.length>0&&g.emit("quick-order/grid-ordering-variants",s)},[s]),v(()=>{const r=g.on("quick-order/grid-ordering-variants",e=>{if(!e||e.length===0)d([]),a.current=[],b(!1);else{const t=e.map(u=>({...u,quantity:0}));d(t),a.current=t,b(!1),g.emit("quick-order/grid-ordering-selected-variants",[]),l==null||l(t)}},{eager:!0});return()=>{r==null||r.off()}},[l]);const p=R(()=>L(r=>{const e=r.filter(t=>t.quantity>0).map(t=>{var u;return{sku:t.product.sku,name:t.product.name,inStock:t.product.inStock,attributes:t.product.attributes.reduce((n,i)=>(i.value&&(n[i.name]={label:i.label,value:i.value}),n),{}),price:t.product.price.final.amount.value,quantity:t.quantity,subtotal:t.product.price.final.amount.value*t.quantity,image:((u=t.product.images[0])==null?void 0:u.url)||""}});k&&k(e),g.emit("quick-order/grid-ordering-selected-variants",e)},Q),[k,Q]),G=O((r,e)=>{m.current||d(t=>{const u=t.map(n=>n.product.sku===r?n.product.inStock?{...n,quantity:Math.max(0,e)}:{...n,quantity:0}:n);return a.current=u,p(u),u})},[p]),y=O(()=>{o.current!==null&&clearTimeout(o.current),m.current=!0,d(r=>{const e=r.map(t=>({...t,quantity:0}));return a.current=e,p(e),e}),o.current=window.setTimeout(()=>{m.current=!1,o.current=null},200)},[p]);v(()=>{const r=g.on("quick-order/grid-ordering-reset-selected-variants",y,{eager:!0});return()=>{r==null||r.off()}},[y]),v(()=>()=>{o.current!==null&&clearTimeout(o.current)},[]);const T=O(()=>{const e=(a.current.length>0?a.current:c).filter(C=>C.quantity>0);if(e.length===0){console.warn("No variants with quantity to export");return}const t=`SKU,Quantity
4
- `,u=e.map(C=>`${C.product.sku},${C.quantity}`).join(`
5
- `),n=t+u,i=new Blob([n],{type:"text/csv;charset=utf-8;"}),f=document.createElement("a"),V=URL.createObjectURL(i),A=new Date().toISOString().split("T")[0];f.setAttribute("href",V),f.setAttribute("download",`product-variants-${A}.csv`),f.style.visibility="hidden",document.body.appendChild(f),f.click(),document.body.removeChild(f),URL.revokeObjectURL(V)},[c]),S=O(()=>(a.current.length>0?a.current:c).filter(t=>t.quantity>0).map(t=>{var u;return{sku:t.product.sku,name:t.product.name,inStock:t.product.inStock,attributes:t.product.attributes.reduce((n,i)=>(i.value&&i.value!==""&&(n[i.name]={label:i.label,value:i.value}),n),{}),price:t.product.price.final.amount.value,quantity:t.quantity,subtotal:t.product.price.final.amount.value*t.quantity,image:((u=t.product.images[0])==null?void 0:u.url)||""}}),[c]),B=R(()=>c.filter(r=>r.quantity>0).length,[c]);return{variants:c,loading:q,updateQuantity:G,clearAllQuantities:y,exportToCsv:T,collectTableData:S,variantsWithQuantity:B}},X=({className:s,initialVariants:l,onVariantsLoaded:k,onSelectedVariantsChange:Q,debounceMs:h=300,initialLoading:c,visibleVariantsLimit:d=10,columns:a,slots:q})=>{const b=N({imageColumn:"QuickOrder.VariantsGrid.imageColumn",skuColumn:"QuickOrder.VariantsGrid.skuColumn",availabilityColumn:"QuickOrder.VariantsGrid.availabilityColumn",priceColumn:"QuickOrder.VariantsGrid.priceColumn",quantityColumn:"QuickOrder.VariantsGrid.quantityColumn",subtotalColumn:"QuickOrder.VariantsGrid.subtotalColumn",clearButton:"QuickOrder.VariantsGrid.clearButton",saveToCsvButton:"QuickOrder.VariantsGrid.saveToCsvButton",collectDataButton:"QuickOrder.VariantsGrid.collectDataButton",inStock:"QuickOrder.VariantsGrid.inStock",outOfStock:"QuickOrder.VariantsGrid.outOfStock",quantityLabel:"QuickOrder.VariantsGrid.quantityLabel",showAll:"QuickOrder.VariantsGrid.showAll",showLess:"QuickOrder.VariantsGrid.showLess"}),{variants:m,loading:o,updateQuantity:p,clearAllQuantities:G,exportToCsv:y,collectTableData:T,variantsWithQuantity:S}=E({initialVariants:l,onVariantsLoaded:k,onSelectedVariantsChange:Q,debounceMs:h,initialLoading:c});return m.length===0&&!o?null:j("div",{className:U(["b2b-quick-order-variants-grid-container",s]),"data-testid":"variants-grid-container",children:[D($,{t:b,onClear:G,onSaveToCsv:y,onCollectData:T,isDisabled:o,variantsCount:S,slots:q}),D(W,{t:b,variants:m,loading:o,onQuantityChange:p,visibleVariantsLimit:d,columns:a,slots:q})]})};export{X as QuickOrderVariantsGrid,X as default};
3
+ import{jsxs as U,jsx as w}from"@dropins/tools/preact-jsx-runtime.js";import{classes as j}from"@dropins/tools/lib.js";import{d as L,Q as $,a as W}from"../chunks/debounce.js";import{useState as x,useRef as T,useEffect as O,useMemo as R,useCallback as v}from"@dropins/tools/preact-hooks.js";import{events as q}from"@dropins/tools/event-bus.js";import{useText as I}from"@dropins/tools/i18n.js";import"@dropins/tools/preact-compat.js";import"@dropins/tools/components.js";const N=l=>l.filter(t=>t.quantity>0).map(t=>{var d;const s={sku:t.product.sku,name:t.product.name,inStock:t.product.inStock,attributes:t.product.attributes.reduce((p,u)=>(u.value&&(p[u.name]={label:u.label,value:u.value}),p),{}),price:t.product.price.final.amount.value,quantity:t.quantity,subtotal:t.product.price.final.amount.value*t.quantity,image:((d=t.product.images[0])==null?void 0:d.url)||""};return t.selections&&t.selections.length>0&&(s.optionsUIDs=t.selections),t.parentSku&&(s.parentSku=t.parentSku),s}),E=({initialVariants:l,onVariantsLoaded:t,onSelectedVariantsChange:s,debounceMs:d=300,initialLoading:p=!0}={})=>{const[u,k]=x([]),i=T([]),[C,g]=x(p),f=T(!1),a=T(null);O(()=>{l&&l.length>0&&q.emit("quick-order/grid-ordering-variants",l)},[l]),O(()=>{const e=q.on("quick-order/grid-ordering-variants",n=>{if(!n||n.length===0)k([]),i.current=[],g(!1);else{const r=n.map(o=>({...o,quantity:0}));k(r),i.current=r,g(!1),q.emit("quick-order/grid-ordering-selected-variants",[]),t==null||t(r)}},{eager:!0});return()=>{e==null||e.off()}},[t]);const b=R(()=>L(e=>{const n=N(e);s&&s(n),q.emit("quick-order/grid-ordering-selected-variants",n)},d),[s,d]),G=v((e,n)=>{f.current||k(r=>{const o=r.map(c=>c.product.sku===e?c.product.inStock?{...c,quantity:Math.max(0,n)}:{...c,quantity:0}:c);return i.current=o,b(o),o})},[b]),Q=v(()=>{a.current!==null&&clearTimeout(a.current),f.current=!0,k(e=>{const n=e.map(r=>({...r,quantity:0}));return i.current=n,b(n),n}),a.current=window.setTimeout(()=>{f.current=!1,a.current=null},200)},[b]);O(()=>{const e=q.on("quick-order/grid-ordering-reset-selected-variants",Q,{eager:!0});return()=>{e==null||e.off()}},[Q]),O(()=>()=>{a.current!==null&&clearTimeout(a.current)},[]);const S=v(()=>{const n=(i.current.length>0?i.current:u).filter(h=>h.quantity>0);if(n.length===0){console.warn("No variants with quantity to export");return}const r=`SKU,Quantity
4
+ `,o=n.map(h=>`${h.product.sku},${h.quantity}`).join(`
5
+ `),c=r+o,m=new Blob([c],{type:"text/csv;charset=utf-8;"}),y=document.createElement("a"),V=URL.createObjectURL(m),A=new Date().toISOString().split("T")[0];y.setAttribute("href",V),y.setAttribute("download",`product-variants-${A}.csv`),y.style.visibility="hidden",document.body.appendChild(y),y.click(),document.body.removeChild(y),URL.revokeObjectURL(V)},[u]),D=v(()=>(i.current.length>0?i.current:u).filter(r=>r.quantity>0).map(r=>{var o;return{sku:r.product.sku,name:r.product.name,inStock:r.product.inStock,attributes:r.product.attributes.reduce((c,m)=>(m.value&&m.value!==""&&(c[m.name]={label:m.label,value:m.value}),c),{}),price:r.product.price.final.amount.value,quantity:r.quantity,subtotal:r.product.price.final.amount.value*r.quantity,image:((o=r.product.images[0])==null?void 0:o.url)||""}}),[u]),B=R(()=>u.filter(e=>e.quantity>0).length,[u]);return{variants:u,loading:C,updateQuantity:G,clearAllQuantities:Q,exportToCsv:S,collectTableData:D,variantsWithQuantity:B}},Y=({className:l,initialVariants:t,onVariantsLoaded:s,onSelectedVariantsChange:d,debounceMs:p=300,initialLoading:u,visibleVariantsLimit:k=10,columns:i,slots:C})=>{const g=I({imageColumn:"QuickOrder.VariantsGrid.imageColumn",skuColumn:"QuickOrder.VariantsGrid.skuColumn",availabilityColumn:"QuickOrder.VariantsGrid.availabilityColumn",priceColumn:"QuickOrder.VariantsGrid.priceColumn",quantityColumn:"QuickOrder.VariantsGrid.quantityColumn",subtotalColumn:"QuickOrder.VariantsGrid.subtotalColumn",clearButton:"QuickOrder.VariantsGrid.clearButton",saveToCsvButton:"QuickOrder.VariantsGrid.saveToCsvButton",collectDataButton:"QuickOrder.VariantsGrid.collectDataButton",inStock:"QuickOrder.VariantsGrid.inStock",outOfStock:"QuickOrder.VariantsGrid.outOfStock",quantityLabel:"QuickOrder.VariantsGrid.quantityLabel",showAll:"QuickOrder.VariantsGrid.showAll",showLess:"QuickOrder.VariantsGrid.showLess"}),{variants:f,loading:a,updateQuantity:b,clearAllQuantities:G,exportToCsv:Q,collectTableData:S,variantsWithQuantity:D}=E({initialVariants:t,onVariantsLoaded:s,onSelectedVariantsChange:d,debounceMs:p,initialLoading:u});return f.length===0&&!a?null:U("div",{className:j(["b2b-quick-order-variants-grid-container",l]),"data-testid":"variants-grid-container",children:[w($,{t:g,onClear:G,onSaveToCsv:Q,onCollectData:S,isDisabled:a,variantsCount:D,slots:C}),w(W,{t:g,variants:f,loading:a,onQuantityChange:b,visibleVariantsLimit:k,columns:i,slots:C})]})};export{Y as QuickOrderVariantsGrid,Y as default};
6
6
  //# sourceMappingURL=QuickOrderVariantsGrid.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"QuickOrderVariantsGrid.js","sources":["/@dropins/storefront-quick-order/src/hooks/useQuickOrderVariantsData.tsx","/@dropins/storefront-quick-order/src/containers/QuickOrderVariantsGrid/QuickOrderVariantsGrid.tsx"],"sourcesContent":["/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'preact/hooks';\nimport {\n VariantWithQuantity,\n ProductVariant,\n UseQuickOrderVariantsDataProps,\n UseQuickOrderVariantsDataReturn,\n} from '@/b2b-quick-order/types';\nimport { debounce } from '@adobe-commerce/elsie/lib/debounce';\nimport { events } from '@adobe-commerce/event-bus';\n\nexport const useQuickOrderVariantsData = ({\n initialVariants,\n onVariantsLoaded,\n onSelectedVariantsChange,\n debounceMs = 300,\n initialLoading = true,\n}: UseQuickOrderVariantsDataProps = {}): UseQuickOrderVariantsDataReturn => {\n const [variants, setVariants] = useState<VariantWithQuantity[]>([]);\n const variantsRef = useRef<VariantWithQuantity[]>([]);\n const [loading, setLoading] = useState(initialLoading);\n const isClearingRef = useRef(false);\n const clearTimeoutRef = useRef<number | null>(null);\n\n // Emit event when initialVariants prop is provided (e.g., from Storybook)\n useEffect(() => {\n if (initialVariants && initialVariants.length > 0) {\n events.emit('quick-order/grid-ordering-variants', initialVariants);\n }\n }, [initialVariants]);\n\n // Initializing event\n useEffect(() => {\n const variantsEvent = events.on(\n 'quick-order/grid-ordering-variants',\n (incomingVariants: ProductVariant[]) => {\n if (!incomingVariants || incomingVariants.length === 0) {\n setVariants([]);\n variantsRef.current = [];\n setLoading(false);\n } else {\n const variantsWithQuantity: VariantWithQuantity[] =\n incomingVariants.map((variant) => ({\n ...variant,\n quantity: 0,\n }));\n setVariants(variantsWithQuantity);\n variantsRef.current = variantsWithQuantity;\n setLoading(false);\n events.emit('quick-order/grid-ordering-selected-variants', []);\n onVariantsLoaded?.(variantsWithQuantity);\n }\n },\n {\n eager: true,\n }\n );\n\n return () => {\n variantsEvent?.off();\n };\n }, [onVariantsLoaded]);\n\n const debouncedSelectedVariantsChange = useMemo(\n () =>\n debounce((updatedVariants: VariantWithQuantity[]) => {\n const collectedData = updatedVariants\n .filter((v) => v.quantity > 0)\n .map((v) => ({\n sku: v.product.sku,\n name: v.product.name,\n inStock: v.product.inStock,\n attributes: v.product.attributes.reduce((acc, attr) => {\n if (attr.value) {\n acc[attr.name] = {\n label: attr.label,\n value: attr.value,\n };\n }\n return acc;\n }, {} as Record<string, { label: string; value: string | number }>),\n price: v.product.price.final.amount.value,\n quantity: v.quantity,\n subtotal: v.product.price.final.amount.value * v.quantity,\n image: v.product.images[0]?.url || '',\n }));\n\n if (onSelectedVariantsChange) {\n onSelectedVariantsChange(collectedData);\n }\n\n events.emit(\n 'quick-order/grid-ordering-selected-variants',\n collectedData\n );\n }, debounceMs),\n [onSelectedVariantsChange, debounceMs]\n );\n\n const updateQuantity = useCallback(\n (sku: string, quantity: number) => {\n // Block updateQuantity if clearing is in progress\n if (isClearingRef.current) {\n return;\n }\n\n setVariants((prevVariants) => {\n const updated = prevVariants.map((variant) => {\n if (variant.product.sku === sku) {\n if (!variant.product.inStock) {\n return { ...variant, quantity: 0 };\n }\n return { ...variant, quantity: Math.max(0, quantity) };\n }\n return variant;\n });\n\n variantsRef.current = updated;\n debouncedSelectedVariantsChange(updated);\n\n return updated;\n });\n },\n [debouncedSelectedVariantsChange]\n );\n\n const clearAllQuantities = useCallback(() => {\n // Clear previous timeout if exists\n if (clearTimeoutRef.current !== null) {\n clearTimeout(clearTimeoutRef.current);\n }\n\n isClearingRef.current = true;\n\n setVariants((prevVariants) => {\n const cleared = prevVariants.map((variant) => ({\n ...variant,\n quantity: 0,\n }));\n\n variantsRef.current = cleared;\n debouncedSelectedVariantsChange(cleared);\n return cleared;\n });\n\n // [USF-3838] Timeout required since an SDK Incrementer component using onBlur event timeout\n // We should ensure that a clear action will be executed after it\n clearTimeoutRef.current = window.setTimeout(() => {\n isClearingRef.current = false;\n clearTimeoutRef.current = null;\n }, 200);\n }, [debouncedSelectedVariantsChange]);\n\n useEffect(() => {\n const clearAllQuantitiesEvent = events.on(\n 'quick-order/grid-ordering-reset-selected-variants',\n clearAllQuantities,\n {\n eager: true,\n }\n );\n\n return () => {\n clearAllQuantitiesEvent?.off();\n };\n }, [clearAllQuantities]);\n\n // Cleanup timeout on component unmount\n useEffect(() => {\n return () => {\n if (clearTimeoutRef.current !== null) {\n clearTimeout(clearTimeoutRef.current);\n }\n };\n }, []);\n\n const exportToCsv = useCallback(() => {\n const currentVariants =\n variantsRef.current.length > 0 ? variantsRef.current : variants;\n const variantsToExport = currentVariants.filter((v) => v.quantity > 0);\n\n if (variantsToExport.length === 0) {\n console.warn('No variants with quantity to export');\n return;\n }\n\n const csvHeader = 'SKU,Quantity\\n';\n const csvRows = variantsToExport\n .map((v) => `${v.product.sku},${v.quantity}`)\n .join('\\n');\n const csvContent = csvHeader + csvRows;\n\n const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });\n const link = document.createElement('a');\n const url = URL.createObjectURL(blob);\n\n const timestamp = new Date().toISOString().split('T')[0];\n link.setAttribute('href', url);\n link.setAttribute('download', `product-variants-${timestamp}.csv`);\n link.style.visibility = 'hidden';\n\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n\n URL.revokeObjectURL(url);\n }, [variants]);\n\n const collectTableData = useCallback(() => {\n const currentVariants =\n variantsRef.current.length > 0 ? variantsRef.current : variants;\n const tableData = currentVariants\n .filter((v) => v.quantity > 0)\n .map((variant) => ({\n sku: variant.product.sku,\n name: variant.product.name,\n inStock: variant.product.inStock,\n attributes: variant.product.attributes.reduce((acc, attr) => {\n if (attr.value && attr.value !== '') {\n acc[attr.name] = {\n label: attr.label,\n value: attr.value,\n };\n }\n return acc;\n }, {} as Record<string, { label: string; value: string | number }>),\n price: variant.product.price.final.amount.value,\n quantity: variant.quantity,\n subtotal: variant.product.price.final.amount.value * variant.quantity,\n image: variant.product.images[0]?.url || '',\n }));\n\n return tableData;\n }, [variants]);\n\n const variantsWithQuantity = useMemo(\n () => variants.filter((v) => v.quantity > 0).length,\n [variants]\n );\n\n return {\n variants,\n loading,\n updateQuantity,\n clearAllQuantities,\n exportToCsv,\n collectTableData,\n variantsWithQuantity,\n };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { useText } from '@adobe-commerce/elsie/i18n';\nimport { classes, Container } from '@adobe-commerce/elsie/lib';\nimport { QuickOrderVariantsGrid as QuickOrderVariantsGridComponent } from '@/b2b-quick-order/components/QuickOrderVariantsGrid/QuickOrderVariantsGrid';\nimport { QuickOrderVariantsActions } from '@/b2b-quick-order/components/QuickOrderVariantsActions/QuickOrderVariantsActions';\nimport { useQuickOrderVariantsData } from '@/b2b-quick-order/hooks/useQuickOrderVariantsData';\nimport { QuickOrderVariantsGridProps } from '@/b2b-quick-order/types/quickOrderVariantsGrid.types';\n\nexport const QuickOrderVariantsGrid: Container<QuickOrderVariantsGridProps> = ({\n className,\n initialVariants,\n onVariantsLoaded,\n onSelectedVariantsChange,\n debounceMs = 300,\n initialLoading,\n visibleVariantsLimit = 10,\n columns,\n slots,\n}) => {\n const t = useText({\n imageColumn: 'QuickOrder.VariantsGrid.imageColumn',\n skuColumn: 'QuickOrder.VariantsGrid.skuColumn',\n availabilityColumn: 'QuickOrder.VariantsGrid.availabilityColumn',\n priceColumn: 'QuickOrder.VariantsGrid.priceColumn',\n quantityColumn: 'QuickOrder.VariantsGrid.quantityColumn',\n subtotalColumn: 'QuickOrder.VariantsGrid.subtotalColumn',\n clearButton: 'QuickOrder.VariantsGrid.clearButton',\n saveToCsvButton: 'QuickOrder.VariantsGrid.saveToCsvButton',\n collectDataButton: 'QuickOrder.VariantsGrid.collectDataButton',\n inStock: 'QuickOrder.VariantsGrid.inStock',\n outOfStock: 'QuickOrder.VariantsGrid.outOfStock',\n quantityLabel: 'QuickOrder.VariantsGrid.quantityLabel',\n showAll: 'QuickOrder.VariantsGrid.showAll',\n showLess: 'QuickOrder.VariantsGrid.showLess',\n });\n\n const {\n variants,\n loading,\n updateQuantity,\n clearAllQuantities,\n exportToCsv,\n collectTableData,\n variantsWithQuantity,\n } = useQuickOrderVariantsData({\n initialVariants,\n onVariantsLoaded,\n onSelectedVariantsChange,\n debounceMs,\n initialLoading,\n });\n\n if (variants.length === 0 && !loading) {\n return null;\n }\n\n return (\n <div\n className={classes([\n 'b2b-quick-order-variants-grid-container',\n className,\n ])}\n data-testid=\"variants-grid-container\"\n >\n <QuickOrderVariantsActions\n t={t}\n onClear={clearAllQuantities}\n onSaveToCsv={exportToCsv}\n onCollectData={collectTableData}\n isDisabled={loading}\n variantsCount={variantsWithQuantity}\n slots={slots}\n />\n\n <QuickOrderVariantsGridComponent\n t={t}\n variants={variants}\n loading={loading}\n onQuantityChange={updateQuantity}\n visibleVariantsLimit={visibleVariantsLimit}\n columns={columns}\n slots={slots}\n />\n </div>\n );\n};\n"],"names":["useQuickOrderVariantsData","initialVariants","onVariantsLoaded","onSelectedVariantsChange","debounceMs","initialLoading","variants","setVariants","useState","variantsRef","useRef","loading","setLoading","isClearingRef","clearTimeoutRef","useEffect","events","variantsEvent","incomingVariants","variantsWithQuantity","variant","debouncedSelectedVariantsChange","useMemo","debounce","updatedVariants","collectedData","v","acc","attr","_a","updateQuantity","useCallback","sku","quantity","prevVariants","updated","clearAllQuantities","cleared","clearAllQuantitiesEvent","exportToCsv","variantsToExport","csvHeader","csvRows","csvContent","blob","link","url","timestamp","collectTableData","QuickOrderVariantsGrid","className","visibleVariantsLimit","columns","slots","t","useText","jsxs","classes","jsx","QuickOrderVariantsActions","QuickOrderVariantsGridComponent"],"mappings":"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"}
1
+ {"version":3,"file":"QuickOrderVariantsGrid.js","sources":["/@dropins/storefront-quick-order/src/lib/collectVariantsData.ts","/@dropins/storefront-quick-order/src/hooks/useQuickOrderVariantsData.tsx","/@dropins/storefront-quick-order/src/containers/QuickOrderVariantsGrid/QuickOrderVariantsGrid.tsx"],"sourcesContent":["/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { VariantWithQuantity, VariantTableData } from '@/b2b-quick-order/types';\n\n/**\n * Collects and transforms variant data with quantities into table data format\n * @param variants - Array of variants with quantities\n * @returns Array of collected variant data with optional optionsUIDs and parentSku\n */\nexport const collectVariantsData = (\n variants: VariantWithQuantity[]\n): VariantTableData[] => {\n return variants\n .filter((v) => v.quantity > 0)\n .map((v) => {\n const baseData: VariantTableData = {\n sku: v.product.sku,\n name: v.product.name,\n inStock: v.product.inStock,\n attributes: v.product.attributes.reduce((acc, attr) => {\n if (attr.value) {\n acc[attr.name] = {\n label: attr.label,\n value: attr.value,\n };\n }\n return acc;\n }, {} as Record<string, { label: string; value: string | number }>),\n price: v.product.price.final.amount.value,\n quantity: v.quantity,\n subtotal: v.product.price.final.amount.value * v.quantity,\n image: v.product.images[0]?.url || '',\n };\n\n // Add optionsUIDs if selections are present (for configurable products)\n if (v.selections && v.selections.length > 0) {\n baseData.optionsUIDs = v.selections;\n }\n\n // Add parentSku if present (for configurable products)\n if (v.parentSku) {\n baseData.parentSku = v.parentSku;\n }\n\n return baseData;\n });\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'preact/hooks';\nimport {\n VariantWithQuantity,\n ProductVariant,\n UseQuickOrderVariantsDataProps,\n UseQuickOrderVariantsDataReturn,\n} from '@/b2b-quick-order/types';\nimport { debounce } from '@adobe-commerce/elsie/lib/debounce';\nimport { events } from '@adobe-commerce/event-bus';\nimport { collectVariantsData } from '@/b2b-quick-order/lib';\n\nexport const useQuickOrderVariantsData = ({\n initialVariants,\n onVariantsLoaded,\n onSelectedVariantsChange,\n debounceMs = 300,\n initialLoading = true,\n}: UseQuickOrderVariantsDataProps = {}): UseQuickOrderVariantsDataReturn => {\n const [variants, setVariants] = useState<VariantWithQuantity[]>([]);\n const variantsRef = useRef<VariantWithQuantity[]>([]);\n const [loading, setLoading] = useState(initialLoading);\n const isClearingRef = useRef(false);\n const clearTimeoutRef = useRef<number | null>(null);\n\n // Emit event when initialVariants prop is provided (e.g., from Storybook)\n useEffect(() => {\n if (initialVariants && initialVariants.length > 0) {\n events.emit('quick-order/grid-ordering-variants', initialVariants);\n }\n }, [initialVariants]);\n\n // Initializing event\n useEffect(() => {\n const variantsEvent = events.on(\n 'quick-order/grid-ordering-variants',\n (incomingVariants: ProductVariant[]) => {\n if (!incomingVariants || incomingVariants.length === 0) {\n setVariants([]);\n variantsRef.current = [];\n setLoading(false);\n } else {\n const variantsWithQuantity: VariantWithQuantity[] =\n incomingVariants.map((variant) => ({\n ...variant,\n quantity: 0,\n }));\n setVariants(variantsWithQuantity);\n variantsRef.current = variantsWithQuantity;\n setLoading(false);\n events.emit('quick-order/grid-ordering-selected-variants', []);\n onVariantsLoaded?.(variantsWithQuantity);\n }\n },\n {\n eager: true,\n }\n );\n\n return () => {\n variantsEvent?.off();\n };\n }, [onVariantsLoaded]);\n\n const debouncedSelectedVariantsChange = useMemo(\n () =>\n debounce((updatedVariants: VariantWithQuantity[]) => {\n const collectedData = collectVariantsData(updatedVariants);\n\n if (onSelectedVariantsChange) {\n onSelectedVariantsChange(collectedData);\n }\n events.emit(\n 'quick-order/grid-ordering-selected-variants',\n collectedData\n );\n }, debounceMs),\n [onSelectedVariantsChange, debounceMs]\n );\n\n const updateQuantity = useCallback(\n (sku: string, quantity: number) => {\n // Block updateQuantity if clearing is in progress\n if (isClearingRef.current) {\n return;\n }\n\n setVariants((prevVariants) => {\n const updated = prevVariants.map((variant) => {\n if (variant.product.sku === sku) {\n if (!variant.product.inStock) {\n return { ...variant, quantity: 0 };\n }\n return { ...variant, quantity: Math.max(0, quantity) };\n }\n return variant;\n });\n\n variantsRef.current = updated;\n debouncedSelectedVariantsChange(updated);\n\n return updated;\n });\n },\n [debouncedSelectedVariantsChange]\n );\n\n const clearAllQuantities = useCallback(() => {\n // Clear previous timeout if exists\n if (clearTimeoutRef.current !== null) {\n clearTimeout(clearTimeoutRef.current);\n }\n\n isClearingRef.current = true;\n\n setVariants((prevVariants) => {\n const cleared = prevVariants.map((variant) => ({\n ...variant,\n quantity: 0,\n }));\n\n variantsRef.current = cleared;\n debouncedSelectedVariantsChange(cleared);\n return cleared;\n });\n\n // [USF-3838] Timeout required since an SDK Incrementer component using onBlur event timeout\n // We should ensure that a clear action will be executed after it\n clearTimeoutRef.current = window.setTimeout(() => {\n isClearingRef.current = false;\n clearTimeoutRef.current = null;\n }, 200);\n }, [debouncedSelectedVariantsChange]);\n\n useEffect(() => {\n const clearAllQuantitiesEvent = events.on(\n 'quick-order/grid-ordering-reset-selected-variants',\n clearAllQuantities,\n {\n eager: true,\n }\n );\n\n return () => {\n clearAllQuantitiesEvent?.off();\n };\n }, [clearAllQuantities]);\n\n // Cleanup timeout on component unmount\n useEffect(() => {\n return () => {\n if (clearTimeoutRef.current !== null) {\n clearTimeout(clearTimeoutRef.current);\n }\n };\n }, []);\n\n const exportToCsv = useCallback(() => {\n const currentVariants =\n variantsRef.current.length > 0 ? variantsRef.current : variants;\n const variantsToExport = currentVariants.filter((v) => v.quantity > 0);\n\n if (variantsToExport.length === 0) {\n console.warn('No variants with quantity to export');\n return;\n }\n\n const csvHeader = 'SKU,Quantity\\n';\n const csvRows = variantsToExport\n .map((v) => `${v.product.sku},${v.quantity}`)\n .join('\\n');\n const csvContent = csvHeader + csvRows;\n\n const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });\n const link = document.createElement('a');\n const url = URL.createObjectURL(blob);\n\n const timestamp = new Date().toISOString().split('T')[0];\n link.setAttribute('href', url);\n link.setAttribute('download', `product-variants-${timestamp}.csv`);\n link.style.visibility = 'hidden';\n\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n\n URL.revokeObjectURL(url);\n }, [variants]);\n\n const collectTableData = useCallback(() => {\n const currentVariants =\n variantsRef.current.length > 0 ? variantsRef.current : variants;\n const tableData = currentVariants\n .filter((v) => v.quantity > 0)\n .map((variant) => ({\n sku: variant.product.sku,\n name: variant.product.name,\n inStock: variant.product.inStock,\n attributes: variant.product.attributes.reduce((acc, attr) => {\n if (attr.value && attr.value !== '') {\n acc[attr.name] = {\n label: attr.label,\n value: attr.value,\n };\n }\n return acc;\n }, {} as Record<string, { label: string; value: string | number }>),\n price: variant.product.price.final.amount.value,\n quantity: variant.quantity,\n subtotal: variant.product.price.final.amount.value * variant.quantity,\n image: variant.product.images[0]?.url || '',\n }));\n\n return tableData;\n }, [variants]);\n\n const variantsWithQuantity = useMemo(\n () => variants.filter((v) => v.quantity > 0).length,\n [variants]\n );\n\n return {\n variants,\n loading,\n updateQuantity,\n clearAllQuantities,\n exportToCsv,\n collectTableData,\n variantsWithQuantity,\n };\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: All information contained herein is, and remains\n * the property of Adobe and its suppliers, if any. The intellectual\n * and technical concepts contained herein are proprietary to Adobe\n * and its suppliers and are protected by all applicable intellectual\n * property laws, including trade secret and copyright laws.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Adobe.\n *******************************************************************/\n\nimport { useText } from '@adobe-commerce/elsie/i18n';\nimport { classes, Container } from '@adobe-commerce/elsie/lib';\nimport { QuickOrderVariantsGrid as QuickOrderVariantsGridComponent } from '@/b2b-quick-order/components/QuickOrderVariantsGrid/QuickOrderVariantsGrid';\nimport { QuickOrderVariantsActions } from '@/b2b-quick-order/components/QuickOrderVariantsActions/QuickOrderVariantsActions';\nimport { useQuickOrderVariantsData } from '@/b2b-quick-order/hooks/useQuickOrderVariantsData';\nimport { QuickOrderVariantsGridProps } from '@/b2b-quick-order/types/quickOrderVariantsGrid.types';\n\nexport const QuickOrderVariantsGrid: Container<QuickOrderVariantsGridProps> = ({\n className,\n initialVariants,\n onVariantsLoaded,\n onSelectedVariantsChange,\n debounceMs = 300,\n initialLoading,\n visibleVariantsLimit = 10,\n columns,\n slots,\n}) => {\n const t = useText({\n imageColumn: 'QuickOrder.VariantsGrid.imageColumn',\n skuColumn: 'QuickOrder.VariantsGrid.skuColumn',\n availabilityColumn: 'QuickOrder.VariantsGrid.availabilityColumn',\n priceColumn: 'QuickOrder.VariantsGrid.priceColumn',\n quantityColumn: 'QuickOrder.VariantsGrid.quantityColumn',\n subtotalColumn: 'QuickOrder.VariantsGrid.subtotalColumn',\n clearButton: 'QuickOrder.VariantsGrid.clearButton',\n saveToCsvButton: 'QuickOrder.VariantsGrid.saveToCsvButton',\n collectDataButton: 'QuickOrder.VariantsGrid.collectDataButton',\n inStock: 'QuickOrder.VariantsGrid.inStock',\n outOfStock: 'QuickOrder.VariantsGrid.outOfStock',\n quantityLabel: 'QuickOrder.VariantsGrid.quantityLabel',\n showAll: 'QuickOrder.VariantsGrid.showAll',\n showLess: 'QuickOrder.VariantsGrid.showLess',\n });\n\n const {\n variants,\n loading,\n updateQuantity,\n clearAllQuantities,\n exportToCsv,\n collectTableData,\n variantsWithQuantity,\n } = useQuickOrderVariantsData({\n initialVariants,\n onVariantsLoaded,\n onSelectedVariantsChange,\n debounceMs,\n initialLoading,\n });\n\n if (variants.length === 0 && !loading) {\n return null;\n }\n\n return (\n <div\n className={classes([\n 'b2b-quick-order-variants-grid-container',\n className,\n ])}\n data-testid=\"variants-grid-container\"\n >\n <QuickOrderVariantsActions\n t={t}\n onClear={clearAllQuantities}\n onSaveToCsv={exportToCsv}\n onCollectData={collectTableData}\n isDisabled={loading}\n variantsCount={variantsWithQuantity}\n slots={slots}\n />\n\n <QuickOrderVariantsGridComponent\n t={t}\n variants={variants}\n loading={loading}\n onQuantityChange={updateQuantity}\n visibleVariantsLimit={visibleVariantsLimit}\n columns={columns}\n slots={slots}\n />\n </div>\n );\n};\n"],"names":["collectVariantsData","variants","v","baseData","acc","attr","_a","useQuickOrderVariantsData","initialVariants","onVariantsLoaded","onSelectedVariantsChange","debounceMs","initialLoading","setVariants","useState","variantsRef","useRef","loading","setLoading","isClearingRef","clearTimeoutRef","useEffect","events","variantsEvent","incomingVariants","variantsWithQuantity","variant","debouncedSelectedVariantsChange","useMemo","debounce","updatedVariants","collectedData","updateQuantity","useCallback","sku","quantity","prevVariants","updated","clearAllQuantities","cleared","clearAllQuantitiesEvent","exportToCsv","variantsToExport","csvHeader","csvRows","csvContent","blob","link","url","timestamp","collectTableData","QuickOrderVariantsGrid","className","visibleVariantsLimit","columns","slots","t","useText","jsxs","classes","jsx","QuickOrderVariantsActions","QuickOrderVariantsGridComponent"],"mappings":"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"}
@@ -17,6 +17,7 @@
17
17
  export interface CartItem {
18
18
  sku: string;
19
19
  quantity: number;
20
+ itemId?: string;
20
21
  parentSku?: string;
21
22
  optionsUIDs?: string[];
22
23
  enteredOptions?: {
@@ -0,0 +1,9 @@
1
+ import { VariantWithQuantity, VariantTableData } from '../types';
2
+
3
+ /**
4
+ * Collects and transforms variant data with quantities into table data format
5
+ * @param variants - Array of variants with quantities
6
+ * @returns Array of collected variant data with optional optionsUIDs and parentSku
7
+ */
8
+ export declare const collectVariantsData: (variants: VariantWithQuantity[]) => VariantTableData[];
9
+ //# sourceMappingURL=collectVariantsData.d.ts.map
package/lib/index.d.ts CHANGED
@@ -27,6 +27,7 @@ export * from './removeReplacedItems';
27
27
  export * from './mergeDuplicateItems';
28
28
  export * from './addOrMergeItems';
29
29
  export * from './replaceOrAddItems';
30
+ export * from './collectVariantsData';
30
31
  export * from './updateItemInList';
31
32
  export * from './buildCartItemsFromForms';
32
33
  export * from './productOptionsStorage';
@@ -26,16 +26,23 @@ export declare const getOptionsFromStorage: (storageKey: string) => Record<strin
26
26
  * Save options to localStorage
27
27
  */
28
28
  export declare const saveOptionsToStorage: (storageKey: string, itemId: string, optionsUIDs: string[]) => void;
29
+ /**
30
+ * Remove options from localStorage for a specific item
31
+ */
32
+ export declare const removeOptionsFromStorage: (storageKey: string, itemId: string) => void;
29
33
  /**
30
34
  * Enrich cart items with selected options from storage
31
35
  */
32
36
  export declare const enrichCartItemsWithOptions: <T extends {
33
37
  sku: string;
38
+ itemId?: string | undefined;
34
39
  }>(cartItems: T[], items: Array<{
35
40
  id?: string;
36
41
  sku: string;
37
42
  variantSku?: string;
43
+ parentSku?: string;
38
44
  }>, storageData: Record<string, string[]>) => (T & {
39
45
  optionsUIDs?: string[] | undefined;
46
+ parentSku?: string | undefined;
40
47
  })[];
41
48
  //# sourceMappingURL=productOptionsStorage.d.ts.map
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name": "@dropins/storefront-quick-order", "version": "1.0.0", "@dropins/tools": "~1.7.0", "license": "SEE LICENSE IN LICENSE.md"}
1
+ {"name": "@dropins/storefront-quick-order", "version": "1.0.1", "@dropins/tools": "~1.7.0", "license": "SEE LICENSE IN LICENSE.md"}
package/render.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*! Copyright 2026 Adobe
2
2
  All Rights Reserved. */
3
3
  (function(t,i){try{if(typeof document<"u"){const r=document.createElement("style"),a=i.styleId;for(const e in i.attributes)r.setAttribute(e,i.attributes[e]);r.setAttribute("data-dropin",a),r.appendChild(document.createTextNode(t));const o=document.querySelector('style[data-dropin="sdk"]');if(o)o.after(r);else{const e=document.querySelector('link[rel="stylesheet"], style');e?e.before(r):document.head.append(r)}}}catch(r){console.error("dropin-styles (injectCodeFunction)",r)}})(`.b2b-quick-order-variants-grid{width:100%}.b2b-quick-order-variants-grid .dropin-table__header__row th{padding:var(--spacing-small) var(--spacing-xsmall)}.b2b-quick-order-variants-grid .dropin-table__body__cell{padding:var(--spacing-xsmall) var(--spacing-xsmall)}.b2b-quick-order-variants-grid__table{width:100%}.b2b-quick-order-variants-grid__image{width:64px;height:64px;object-fit:cover;border-radius:var(--shape-border-radius-1);display:block}.b2b-quick-order-variants-grid__variant{display:flex;flex-direction:column;gap:var(--spacing-xxsmall)}.b2b-quick-order-variants-grid__availability{width:fit-content;border-radius:var(--shape-border-radius-1)}.b2b-quick-order-variants-grid__availability--in-stock{color:var(--color-positive-800);background-color:var(--color-positive-200)}.b2b-quick-order-variants-grid__availability--out-of-stock{color:var(--color-warning-800);background-color:var(--color-warning-200)}.b2b-quick-order-variants-grid__quantity-input{width:min-content}.b2b-quick-order-variants-grid__footer{display:flex;justify-content:center;margin-top:var(--spacing-medium);padding-top:var(--spacing-medium);border-top:1px solid var(--color-neutral-500)}.b2b-quick-order-variants-grid__toggle-button{min-width:200px}@media (max-width: 600px){.b2b-quick-order-variants-grid__image{width:48px;height:48px}}.b2b-quick-order-variants-actions{display:flex;justify-content:flex-end;align-items:center;padding:var(--spacing-medium) 0;gap:var(--spacing-small)}.b2b-quick-order-variants-actions__buttons{display:flex;gap:var(--spacing-small)}@media (max-width: 600px){.b2b-quick-order-variants-actions{flex-direction:column;align-items:stretch}.b2b-quick-order-variants-actions__buttons{flex-direction:column;width:100%}}
4
- .b2b-quick-order-quick-order-multiple-sku{display:flex;flex-direction:column;gap:var(--grid-1-gutters)}.b2b-quick-order-sku-list-input__title{color:var(--color-neutral-800);font:var(--type-headline-2-font);letter-spacing:var(--type-headline-2-letter-spacing);margin-bottom:var(--spacing-small)}.b2b-quick-order-sku-list-input__textarea{margin-bottom:var(--spacing-xsmall)}.b2b-quick-order-sku-list-input__message{font:var(--type-details-caption-2-font);letter-spacing:var(--type-details-caption-2-letter-spacing);margin-bottom:var(--spacing-xsmall);text-align:left}.b2b-quick-order-csv-file-input{display:flex;flex-direction:column;gap:var(--grid-1-gutters)}.b2b-quick-order-csv-file-input__title{color:var(--color-neutral-800);font:var(--type-headline-2-font);letter-spacing:var(--type-headline-2-letter-spacing)}.b2b-quick-order-csv-file-input__helper{font:var(--type-details-caption-2-font);letter-spacing:var(--type-details-caption-2-letter-spacing);text-align:left}.b2b-quick-order-csv-file-input__download-link{color:var(--color-informational-800);text-decoration:underline;background:none;border:none;padding:0;cursor:pointer;font-size:inherit}.b2b-quick-order-csv-file-input__download-link:hover{color:var(--color-informational-500)}.b2b-quick-order-csv-file-input__input-wrapper{margin-top:var(--spacing-xsmall);width:max-content}.b2b-quick-order-csv-file-input__input{width:100%}.b2b-quick-order-csv-file-input__input-wrapper--disabled button,.b2b-quick-order-csv-file-input__input-wrapper--disabled label,.b2b-quick-order-csv-file-input__input-wrapper--disabled .dropin-button{background:var(--color-neutral-300) 0 0% no-repeat padding-box!important;color:var(--color-neutral-500)!important;fill:var(--color-neutral-300)!important;pointer-events:none;-webkit-user-select:none;user-select:none;cursor:not-allowed!important}.b2b-quick-order-csv-file-input__input:has(input:disabled) button,.b2b-quick-order-csv-file-input__input:has(input:disabled) label{background:var(--color-neutral-300) 0 0% no-repeat padding-box;color:var(--color-neutral-500);fill:var(--color-neutral-300);pointer-events:none;-webkit-user-select:none;user-select:none;cursor:not-allowed}.b2b-quick-order-csv-file-input__input--loading{cursor:not-allowed;opacity:.3}.b2b-quick-order-csv-file-input__file-name{font:var(--type-body-2-default-font);letter-spacing:var(--type-body-2-default-letter-spacing)}.b2b-quick-order-csv-file-input__error{font:var(--type-details-caption-2-font);letter-spacing:var(--type-details-caption-2-letter-spacing);padding-top:var(--spacing-xsmall);text-align:left;color:var(--color-alert-800)}.b2b-quick-order-form-quick-order-items-list{width:100%}.b2b-quick-order-form-quick-order-items-list__title{color:var(--color-neutral-800);font:var(--type-headline-2-font);letter-spacing:var(--type-headline-2-letter-spacing);margin-bottom:var(--spacing-small)}.b2b-quick-order-form-quick-order-items-list__empty{color:var(--color-neutral-600);font:var(--type-body-1-font);letter-spacing:var(--type-body-1-letter-spacing);text-align:center;padding:var(--spacing-large)}.b2b-quick-order-form-quick-order-items-list__actions{display:flex;justify-content:flex-start;margin-top:var(--spacing-medium)}.b2b-quick-order-form-quick-order-items-list__warning{background-color:var(--color-warning-200);border:1px solid var(--color-warning-500);border-radius:var(--shape-border-radius-2);padding:var(--spacing-medium);margin-bottom:var(--spacing-medium)}.b2b-quick-order-form-quick-order-items-list__warning-title{color:var(--color-warning-800, #e65100);font:var(--type-body-1-strong-font);letter-spacing:var(--type-body-1-strong-letter-spacing);margin-bottom:var(--spacing-xsmall)}.b2b-quick-order-form-quick-order-items-list__warning-description{color:var(--color-warning-700, #f57c00);font:var(--type-body-2-font);letter-spacing:var(--type-body-2-letter-spacing)}.b2b-quick-order-form-quick-order-items-list .dropin-divider--secondary{border-width:var(--shape-border-width-3);margin-top:0}@media screen and (max-width: 1285px){.b2b-quick-order-form-quick-order-items-list .dropin-divider--secondary{display:none}}.b2b-quick-order-form-quick-order-items-list__actions--disabled{background-color:red}.b2b-quick-order-form-quick-order-items__item-form{min-height:170px}.b2b-quick-order-form-quick-order-items__item-form .dropin-accordion-section__content-container{margin-bottom:0}.b2b-quick-order-form-quick-order-items__item-form:last-child{margin-bottom:var(--spacing-medium)}.b2b-quick-order-list-item__accordion .dropin-accordion-section__title{color:var(--color-neutral-800);font:var(--type-body-2-default-font);letter-spacing:var(--type-body-2-default-letter-spacing)}.b2b-quick-order-items__error{color:var(--color-alert-800);font:var(--type-details-caption-2-font);letter-spacing:var(--type-details-caption-2-letter-spacing)}.b2b-quick-order-form-quick-order-items__item-search{margin-bottom:var(--spacing-big)}.b2b-quick-order-items__configurable-error{color:var(--color-alert-500);font:var(--type-details-caption-2-font);letter-spacing:var(--type-details-caption-2-letter-spacing)}.b2b-quick-order-search{position:relative;width:100%}.b2b-quick-order-search__input{width:100%}.b2b-quick-order-search__results{position:absolute;top:100%;left:0;right:0;background-color:var(--color-neutral-50);border:var(--shape-border-width-1) solid var(--color-neutral-300);border-radius:var(--spacing-xxsmall);margin-top:var(--spacing-xxsmall);max-height:300px;overflow-y:auto;z-index:10;box-shadow:0 2px 8px #0000001a}.b2b-quick-order-search__result-item{padding:var(--spacing-xsmall) var(--spacing-small);cursor:pointer;transition:background-color .2s,outline .2s}.b2b-quick-order-search__result-item:hover{background-color:var(--color-neutral-100)}.b2b-quick-order-search__result-item--active,.b2b-quick-order-search__result-item[aria-selected=true]{background-color:var(--color-neutral-100);outline:2px solid var(--color-brand-500);outline-offset:-2px}.b2b-quick-order-search__result-item:not(:last-child){border-bottom:var(--shape-border-width-1) solid var(--color-neutral-200)}.b2b-quick-order-search__empty-state{position:absolute;top:100%;left:0;right:0;z-index:10;text-align:center;background-color:var(--color-neutral-50);border:var(--shape-border-width-1) solid var(--color-neutral-300);border-radius:var(--shape-border-radius-1);margin-top:var(--spacing-xxsmall);padding:var(--spacing-small);color:var(--color-neutral-600);box-shadow:0 2px 8px #0000001a}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.b2b-quick-order-notification-banner{margin-bottom:20px}.b2b-quick-order-notification-banner .dropin-alert-banner__message{max-width:500px}.b2b-quick-order-notification-banner--warning .dropin-alert-banner{background-color:var(--color-warning-500)}.b2b-quick-order-notification-banner--success .dropin-alert-banner{background-color:var(--color-positive-500)}.b2b-quick-order-notification-banner--neutral .dropin-alert-banner{background-color:var(--color-neutral-600)}.b2b-quick-order-notification-banner--brand .dropin-alert-banner{background-color:var(--color-brand-500)}.b2b-quick-order-disabled-overlay{position:relative}.b2b-quick-order-disabled-overlay__blur{position:absolute;top:0;right:0;bottom:0;left:0;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background-color:#ffffffb3;z-index:1}.b2b-quick-order-disabled-overlay__message{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:2;font:var(--type-body-1-default-font);color:var(--color-brand-500);text-align:center;padding:var(--spacing-medium)}`,{styleId:"b2b-quick-order"});
4
+ .b2b-quick-order-quick-order-multiple-sku{display:flex;flex-direction:column;gap:var(--grid-1-gutters)}.b2b-quick-order-sku-list-input__title{color:var(--color-neutral-800);font:var(--type-headline-2-font);letter-spacing:var(--type-headline-2-letter-spacing);margin-bottom:var(--spacing-small)}.b2b-quick-order-sku-list-input__textarea{margin-bottom:var(--spacing-xsmall)}.b2b-quick-order-sku-list-input__message{font:var(--type-details-caption-2-font);letter-spacing:var(--type-details-caption-2-letter-spacing);margin-bottom:var(--spacing-xsmall);text-align:left}.b2b-quick-order-csv-file-input{display:flex;flex-direction:column;gap:var(--grid-1-gutters)}.b2b-quick-order-csv-file-input__title{color:var(--color-neutral-800);font:var(--type-headline-2-font);letter-spacing:var(--type-headline-2-letter-spacing)}.b2b-quick-order-csv-file-input__helper{font:var(--type-details-caption-2-font);letter-spacing:var(--type-details-caption-2-letter-spacing);text-align:left}.b2b-quick-order-csv-file-input__download-link{color:var(--color-informational-800);text-decoration:underline;background:none;border:none;padding:0;cursor:pointer;font-size:inherit}.b2b-quick-order-csv-file-input__download-link:hover{color:var(--color-informational-500)}.b2b-quick-order-csv-file-input__input-wrapper{margin-top:var(--spacing-xsmall);width:max-content}.b2b-quick-order-csv-file-input__input{width:100%}.b2b-quick-order-csv-file-input__input-wrapper--disabled button,.b2b-quick-order-csv-file-input__input-wrapper--disabled label,.b2b-quick-order-csv-file-input__input-wrapper--disabled .dropin-button{background:var(--color-neutral-300) 0 0% no-repeat padding-box!important;color:var(--color-neutral-500)!important;fill:var(--color-neutral-300)!important;pointer-events:none;-webkit-user-select:none;user-select:none;cursor:not-allowed!important}.b2b-quick-order-csv-file-input__input:has(input:disabled) button,.b2b-quick-order-csv-file-input__input:has(input:disabled) label{background:var(--color-neutral-300) 0 0% no-repeat padding-box;color:var(--color-neutral-500);fill:var(--color-neutral-300);pointer-events:none;-webkit-user-select:none;user-select:none;cursor:not-allowed}.b2b-quick-order-csv-file-input__input--loading{cursor:not-allowed;opacity:.3}.b2b-quick-order-csv-file-input__file-name{font:var(--type-body-2-default-font);letter-spacing:var(--type-body-2-default-letter-spacing)}.b2b-quick-order-csv-file-input__error{font:var(--type-details-caption-2-font);letter-spacing:var(--type-details-caption-2-letter-spacing);padding-top:var(--spacing-xsmall);text-align:left;color:var(--color-alert-800)}.b2b-quick-order-form-quick-order-items-list{width:100%}.b2b-quick-order-form-quick-order-items-list__title{color:var(--color-neutral-800);font:var(--type-headline-2-font);letter-spacing:var(--type-headline-2-letter-spacing);margin-bottom:var(--spacing-small)}.b2b-quick-order-form-quick-order-items-list__empty{color:var(--color-neutral-600);font:var(--type-body-1-font);letter-spacing:var(--type-body-1-letter-spacing);text-align:center;padding:var(--spacing-large)}.b2b-quick-order-form-quick-order-items-list__actions{display:flex;justify-content:flex-start;margin-top:var(--spacing-medium)}.b2b-quick-order-form-quick-order-items-list__warning{background-color:var(--color-warning-200);border:1px solid var(--color-warning-500);border-radius:var(--shape-border-radius-2);padding:var(--spacing-medium);margin-bottom:var(--spacing-medium)}.b2b-quick-order-form-quick-order-items-list__warning-title{color:var(--color-warning-800, #e65100);font:var(--type-body-1-strong-font);letter-spacing:var(--type-body-1-strong-letter-spacing);margin-bottom:var(--spacing-xsmall)}.b2b-quick-order-form-quick-order-items-list__warning-description{color:var(--color-warning-700, #f57c00);font:var(--type-body-2-font);letter-spacing:var(--type-body-2-letter-spacing)}.b2b-quick-order-form-quick-order-items-list .dropin-divider--secondary{border-width:var(--shape-border-width-3);margin-top:0}@media screen and (max-width: 1285px){.b2b-quick-order-form-quick-order-items-list .dropin-divider--secondary{display:none}}.b2b-quick-order-form-quick-order-items-list__actions--disabled{background-color:red}.b2b-quick-order-form-quick-order-items__item-form{min-height:170px}.b2b-quick-order-form-quick-order-items__item-form .dropin-accordion-section__content-container{margin-bottom:0}.b2b-quick-order-form-quick-order-items__item-form:last-child{margin-bottom:var(--spacing-medium)}.b2b-quick-order-list-item__accordion .dropin-accordion-section__title{color:var(--color-neutral-800);font:var(--type-body-2-default-font);letter-spacing:var(--type-body-2-default-letter-spacing)}.b2b-quick-order-items__error{color:var(--color-alert-800);font:var(--type-details-caption-2-font);letter-spacing:var(--type-details-caption-2-letter-spacing)}.b2b-quick-order-form-quick-order-items__item-search{margin-bottom:var(--spacing-big)}.b2b-quick-order-items__configurable-error{color:var(--color-alert-500);font:var(--type-details-caption-2-font);letter-spacing:var(--type-details-caption-2-letter-spacing)}.b2b-quick-order-search{position:relative;width:100%}.b2b-quick-order-search__input{width:100%}.b2b-quick-order-search__results{position:absolute;top:100%;left:0;right:0;background-color:var(--color-neutral-50);border:var(--shape-border-width-1) solid var(--color-neutral-300);border-radius:var(--spacing-xxsmall);margin-top:var(--spacing-xxsmall);max-height:300px;overflow-y:auto;z-index:2;box-shadow:0 2px 8px #0000001a}.b2b-quick-order-search__result-item{padding:var(--spacing-xsmall) var(--spacing-small);cursor:pointer;transition:background-color .2s,outline .2s}.b2b-quick-order-search__result-item:hover{background-color:var(--color-neutral-100)}.b2b-quick-order-search__result-item--active,.b2b-quick-order-search__result-item[aria-selected=true]{background-color:var(--color-neutral-100);outline:2px solid var(--color-brand-500);outline-offset:-2px}.b2b-quick-order-search__result-item:not(:last-child){border-bottom:var(--shape-border-width-1) solid var(--color-neutral-200)}.b2b-quick-order-search__empty-state{position:absolute;top:100%;left:0;right:0;z-index:2;text-align:center;background-color:var(--color-neutral-50);border:var(--shape-border-width-1) solid var(--color-neutral-300);border-radius:var(--shape-border-radius-1);margin-top:var(--spacing-xxsmall);padding:var(--spacing-small);color:var(--color-neutral-600);box-shadow:0 2px 8px #0000001a}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.b2b-quick-order-notification-banner{margin-bottom:20px}.b2b-quick-order-notification-banner .dropin-alert-banner__message{max-width:500px}.b2b-quick-order-notification-banner--warning .dropin-alert-banner{background-color:var(--color-warning-500)}.b2b-quick-order-notification-banner--success .dropin-alert-banner{background-color:var(--color-positive-500)}.b2b-quick-order-notification-banner--neutral .dropin-alert-banner{background-color:var(--color-neutral-600)}.b2b-quick-order-notification-banner--brand .dropin-alert-banner{background-color:var(--color-brand-500)}.b2b-quick-order-disabled-overlay{position:relative}.b2b-quick-order-disabled-overlay__blur{position:absolute;top:0;right:0;bottom:0;left:0;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);background-color:#ffffffb3;z-index:1}.b2b-quick-order-disabled-overlay__message{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:2;font:var(--type-body-1-default-font);color:var(--color-brand-500);text-align:center;padding:var(--spacing-medium)}`,{styleId:"b2b-quick-order"});
5
5
  import{jsx as o}from"@dropins/tools/preact-jsx-runtime.js";import{deepmerge as d,Render as u}from"@dropins/tools/lib.js";import{useState as c,useEffect as p}from"@dropins/tools/preact-hooks.js";import{UIProvider as m}from"@dropins/tools/components.js";import{events as f}from"@dropins/tools/event-bus.js";import{c as S}from"./chunks/getStoreConfig.js";import"@dropins/tools/fetch-graphql.js";const b={Search:{placeholder:"Search by SKU...",ariaLabel:"Search for products by SKU",emptyState:"No results found",resultsAvailable:"results available",resultAvailable:"result available",srInstructions:"Use arrow keys or Tab to navigate, Enter or Space to select, Escape to close."},SkuListInput:{title:"Add Products by SKU",helperText:"Use commas or paragraphs to separate SKUs.",textArea:{label:"Enter Multiple SKUs",placeholder:"Enter SKUs here..."},button:"Add to List"},CsvFileInput:{title:"Add from File",helperText:'File must be in .csv format and include "SKU" and "QTY" columns ',downloadSample:"Download sample",inputLabel:"Choose File",selectedFile:"Selected file",uploadCSVErrors:{invalidFile:"Invalid CSV file",emptyFile:"File is empty",missingColumns:'Must contain "SKU" and "QTY" columns',extraColumns:'Must contain only "SKU" and "QTY" columns',maxRowsExceeded:"File exceeds maximum of {maxRows} rows",skuRequired:"Row {rowNumber}: SKU is required",invalidQuantity:"Row {rowNumber}: QTY must be a positive integer",noValidData:"File contains no valid data rows",onlyCSV:"Only CSV files are allowed",failedToRead:"Failed to read file",failedToParse:"Failed to parse CSV file"}},QuickOrderItem:{title:"Enter SKU or search by Product Name",quantity:"Quantity: ",price:"Price: ",sku:"SKU",remove:"Remove",removeItem:"Remove item",showOptions:"Show additional options",hideOptions:"Hide additional options",additionalOptions:"Additional options",noAdditionalOptions:"No additional options available",emptyList:"No products in the list",loading:"Loading...",productNotFound:"Product not found",productNotFoundDescription:"The product with SKU {sku} could not be found",configurableProductError:"Configuration required",configurableProductErrorDescription:"Use ProductOptions Slot in QuickOrderItems container to enable configurable product options.",configurableOptionsWarning:"Product configuration required",configurableOptionsWarningDescription:"Please select all required product options before adding to cart",productOptions:"Product Options",outOfStock:"Out of Stock",addAllToCart:"Add to Cart",disabledMessage:"Quick Order feature disabled",notification:{validationError:"Product(s) require(s) your attention",backendError:"An error occurred while adding products to the cart",success:"{count} product(s) successfully added to the cart",partialSuccess:"{count} of {total} products were added to the cart. Some products could not be added",unexpectedError:"An unexpected error has occurred"}},VariantsGrid:{imageColumn:"Image",attributesColumn:"Attributes",skuColumn:"SKU",availabilityColumn:"Availability",priceColumn:"Price",minOrderColumn:"Min Order / Pack Size",quantityColumn:"Quantity",subtotalColumn:"Subtotal",clearButton:"Clear",saveToCsvButton:"Save to CSV",collectDataButton:"Collect Data",inStock:"In Stock",outOfStock:"Out of Stock",tableCaption:"Product Variants Grid",quantityLabel:"Quantity for",showAll:"Show All Items",showLess:"Show Less"}},g={QuickOrder:b},h={default:g},C=({children:r})=>{var t;const[i,a]=c("en_US");p(()=>{const e=f.on("locale",l=>{a(l)},{eager:!0});return()=>{e==null||e.off()}},[]);const n=(t=S.getConfig())==null?void 0:t.langDefinitions,s=d(h,n??{});return o(m,{lang:i,langDefinitions:s,children:r})},A=new u(o(C,{}));export{A as render};
6
6
  //# sourceMappingURL=render.js.map
@@ -102,6 +102,7 @@ export interface OrderItemInput {
102
102
  export interface OrderItem extends ProductData {
103
103
  id?: string;
104
104
  variantSku?: string;
105
+ parentSku?: string;
105
106
  sku: string;
106
107
  quantity: number;
107
108
  }
@@ -19,6 +19,8 @@ export interface ProductVariantPrice {
19
19
  };
20
20
  }
21
21
  export interface ProductVariant {
22
+ selections?: string[];
23
+ parentSku?: string;
22
24
  product: {
23
25
  sku: string;
24
26
  name: string;
@@ -53,6 +55,8 @@ export interface VariantTableData {
53
55
  quantity: number;
54
56
  subtotal: number;
55
57
  image: string;
58
+ optionsUIDs?: string[];
59
+ parentSku?: string;
56
60
  }
57
61
  export type VariantActionsContext = {
58
62
  onClear: () => void;