@dropins/storefront-product-discovery 0.8.0-alpha.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.
Files changed (92) hide show
  1. package/LICENSE.md +127 -0
  2. package/api/attributeMetadata/attributeMetadata.d.ts +4 -0
  3. package/api/attributeMetadata/graphql/attributeMetadata.graphql.d.ts +17 -0
  4. package/api/attributeMetadata/index.d.ts +10 -0
  5. package/api/fetch-graphql/fetch-graphql.d.ts +16 -0
  6. package/api/fetch-graphql/index.d.ts +10 -0
  7. package/api/graphql/fragments.graphql.d.ts +13 -0
  8. package/api/index.d.ts +13 -0
  9. package/api/initialize/index.d.ts +10 -0
  10. package/api/initialize/initialize.d.ts +10 -0
  11. package/api/productSearch/graphql/productSearch.graphql.d.ts +11 -0
  12. package/api/productSearch/index.d.ts +10 -0
  13. package/api/productSearch/productSearch.d.ts +4 -0
  14. package/api.d.ts +1 -0
  15. package/api.js +4 -0
  16. package/api.js.map +1 -0
  17. package/chunks/acdlEvents.js +4 -0
  18. package/chunks/acdlEvents.js.map +1 -0
  19. package/chunks/attributeMetadata.js +19 -0
  20. package/chunks/attributeMetadata.js.map +1 -0
  21. package/chunks/productSearch.js +152 -0
  22. package/chunks/productSearch.js.map +1 -0
  23. package/components/Facet/Facet.d.ts +10 -0
  24. package/components/Facet/index.d.ts +19 -0
  25. package/components/FacetList/FacetList.d.ts +9 -0
  26. package/components/FacetList/index.d.ts +19 -0
  27. package/components/ProductItem/ProductItem.d.ts +12 -0
  28. package/components/ProductItem/index.d.ts +11 -0
  29. package/components/ProductList/ProductList.d.ts +10 -0
  30. package/components/ProductList/index.d.ts +11 -0
  31. package/components/ResultsInfo/ResultsInfo.d.ts +9 -0
  32. package/components/ResultsInfo/index.d.ts +19 -0
  33. package/components/SearchAlertMessage/SearchAlertMessage.d.ts +8 -0
  34. package/components/SearchAlertMessage/index.d.ts +11 -0
  35. package/components/SearchBarInput/SearchBarInput.d.ts +15 -0
  36. package/components/SearchBarInput/index.d.ts +11 -0
  37. package/components/SearchBarResults/SearchBarResults.d.ts +10 -0
  38. package/components/SearchBarResults/index.d.ts +11 -0
  39. package/components/index.d.ts +17 -0
  40. package/containers/Facets/Facets.d.ts +12 -0
  41. package/containers/Facets/index.d.ts +19 -0
  42. package/containers/Facets/utils/facetUtils.d.ts +17 -0
  43. package/containers/Facets.d.ts +3 -0
  44. package/containers/Facets.js +4 -0
  45. package/containers/Facets.js.map +1 -0
  46. package/containers/ProductList/ProductList.d.ts +19 -0
  47. package/containers/ProductList/index.d.ts +11 -0
  48. package/containers/ProductList/utils/getAttributeMetadata.d.ts +10 -0
  49. package/containers/ProductList/utils/getProductSearch.d.ts +4 -0
  50. package/containers/ProductList/utils/sortUtils.d.ts +9 -0
  51. package/containers/ProductList/utils/urlUtils.d.ts +16 -0
  52. package/containers/ProductList.d.ts +3 -0
  53. package/containers/ProductList.js +4 -0
  54. package/containers/ProductList.js.map +1 -0
  55. package/containers/ResultsInfo/ResultsInfo.d.ts +11 -0
  56. package/containers/ResultsInfo/index.d.ts +19 -0
  57. package/containers/ResultsInfo.d.ts +3 -0
  58. package/containers/ResultsInfo.js +4 -0
  59. package/containers/ResultsInfo.js.map +1 -0
  60. package/containers/SearchBarInput/SearchBarInput.d.ts +16 -0
  61. package/containers/SearchBarInput/index.d.ts +11 -0
  62. package/containers/SearchBarInput/utils/getSearchBarInputSearch.d.ts +4 -0
  63. package/containers/SearchBarInput.d.ts +3 -0
  64. package/containers/SearchBarInput.js +4 -0
  65. package/containers/SearchBarInput.js.map +1 -0
  66. package/containers/SearchBarResults/SearchBarResults.d.ts +15 -0
  67. package/containers/SearchBarResults/index.d.ts +11 -0
  68. package/containers/SearchBarResults.d.ts +3 -0
  69. package/containers/SearchBarResults.js +5 -0
  70. package/containers/SearchBarResults.js.map +1 -0
  71. package/containers/index.d.ts +14 -0
  72. package/data/models/acdl.d.ts +86 -0
  73. package/data/models/api.d.ts +72 -0
  74. package/data/models/index.d.ts +2 -0
  75. package/data/models/product.d.ts +56 -0
  76. package/data/transforms/api.d.ts +11 -0
  77. package/data/transforms/index.d.ts +11 -0
  78. package/data/transforms/product.d.ts +4 -0
  79. package/i18n/en_US.json.d.ts +40 -0
  80. package/package.json +1 -0
  81. package/render/Provider.d.ts +8 -0
  82. package/render/index.d.ts +10 -0
  83. package/render/render.d.ts +4 -0
  84. package/render.d.ts +1 -0
  85. package/render.js +9 -0
  86. package/render.js.map +1 -0
  87. package/types/api/attributeMetadata.d.ts +12 -0
  88. package/types/api/index.d.ts +3 -0
  89. package/types/api/productSearch.d.ts +11 -0
  90. package/types/index.d.ts +2 -0
  91. package/utils/acdlEvents.d.ts +14 -0
  92. package/utils/htmlStringDecode.d.ts +11 -0
@@ -0,0 +1,11 @@
1
+ import { HTMLAttributes } from 'preact/compat';
2
+ import { Container, SlotProps } from '@dropins/tools/types/elsie/src/lib';
3
+
4
+ export interface ResultsInfoProps extends HTMLAttributes<HTMLDivElement> {
5
+ slots?: {
6
+ SearchPhrase?: SlotProps;
7
+ TotalCount?: SlotProps;
8
+ };
9
+ }
10
+ export declare const ResultsInfo: Container<ResultsInfoProps>;
11
+ //# sourceMappingURL=ResultsInfo.d.ts.map
@@ -0,0 +1,19 @@
1
+ /********************************************************************
2
+ * ADOBE CONFIDENTIAL
3
+ * __________________
4
+ *
5
+ * Copyright 2025 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: All information contained herein is, and remains
9
+ * the property of Adobe and its suppliers, if any. The intellectual
10
+ * and technical concepts contained herein are proprietary to Adobe
11
+ * and its suppliers and are protected by all applicable intellectual
12
+ * property laws, including trade secret and copyright laws.
13
+ * Dissemination of this information or reproduction of this material
14
+ * is strictly forbidden unless prior written permission is obtained
15
+ * from Adobe.
16
+ *******************************************************************/
17
+ export * from './ResultsInfo';
18
+ export { ResultsInfo as default } from './ResultsInfo';
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ export * from './ResultsInfo/index'
2
+ import _default from './ResultsInfo/index'
3
+ export default _default
@@ -0,0 +1,4 @@
1
+ /*! Copyright 2025 Adobe
2
+ All Rights Reserved. */
3
+ import{jsxs as i,jsx as s}from"@dropins/tools/preact-jsx-runtime.js";import{useState as n,useCallback as x,useEffect as N}from"@dropins/tools/preact-compat.js";import{classes as P,VComponent as h,Slot as p}from"@dropins/tools/lib.js";import{events as I}from"@dropins/tools/event-bus.js";/* empty css */import{useText as T}from"@dropins/tools/i18n.js";const _=({searchPhrase:e,totalCount:r,className:o=""})=>i("div",{className:P(["plp-results-info",o]),children:[e&&s(h,{className:"plp-results-info__search-phrase",node:e}),r&&s(h,{className:"plp-results-info__total-count",node:r})]}),q=({slots:e})=>{const r=T({resultsFor:"Search.ResultsInfo.resultsFor",products:"Search.ResultsInfo.products"}),[o,d]=n(""),[a,f]=n(),[c,m]=n(),S=x(t=>{var u,l;d(((u=t.request)==null?void 0:u.phrase)||""),f((l=t.result)==null?void 0:l.totalCount),m(t)},[]);N(()=>{const t=I.on("search/result",S);return()=>{t==null||t.off()}},[]);const C=s(p,{name:"SearchPhrase",slot:e==null?void 0:e.SearchPhrase,context:{searchResult:c},children:o&&i("span",{"data-testid":"search-phrase",children:[r.resultsFor," ",s("strong",{children:`"${o}"`})]})}),R=s(p,{name:"TotalCount",slot:e==null?void 0:e.TotalCount,context:{searchResult:c},children:a&&s("span",{"data-testid":"total-count",children:`${a} ${r.products}`})});return s(_,{searchPhrase:C,totalCount:R})};export{q as ResultsInfo,q as default};
4
+ //# sourceMappingURL=ResultsInfo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResultsInfo.js","sources":["/@dropins/storefront-product-discovery/src/components/ResultsInfo/ResultsInfo.tsx","/@dropins/storefront-product-discovery/src/containers/ResultsInfo/ResultsInfo.tsx"],"sourcesContent":["/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2025 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, VNode } from 'preact';\nimport { HTMLAttributes } from 'preact/compat';\nimport { classes, VComponent } from '@adobe-commerce/elsie/lib';\nimport '@/plp/components/ResultsInfo/ResultsInfo.css';\n\nexport interface ResultsInfoProps extends HTMLAttributes<HTMLDivElement> {\n searchPhrase?: VNode;\n totalCount?: VNode;\n}\n\nexport const ResultsInfo: FunctionComponent<ResultsInfoProps> = ({ searchPhrase, totalCount, className = '' }) => {\n return (\n <div className={classes(['plp-results-info', className])}>\n {searchPhrase && <VComponent className=\"plp-results-info__search-phrase\" node={searchPhrase} />}\n {totalCount && <VComponent className=\"plp-results-info__total-count\" node={totalCount} />}\n </div>\n );\n};\n","/********************************************************************\n * ADOBE CONFIDENTIAL\n * __________________\n *\n * Copyright 2025 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 { HTMLAttributes, useCallback, useEffect, useState } from 'preact/compat';\nimport { Container, Slot, SlotProps } from '@adobe-commerce/elsie/lib';\nimport { ProductSearchResult, SearchVariables } from '@/plp/data/models/api';\nimport { events } from '@adobe-commerce/event-bus';\nimport { useText } from '@adobe-commerce/elsie/i18n';\nimport { ResultsInfo as ResultsInfoComponent } from '@/plp/components/ResultsInfo/ResultsInfo';\n\nexport interface ResultsInfoProps extends HTMLAttributes<HTMLDivElement> {\n slots?: {\n SearchPhrase?: SlotProps;\n TotalCount?: SlotProps;\n };\n}\n\nexport const ResultsInfo: Container<ResultsInfoProps> = ({ slots }) => {\n const translations = useText({\n resultsFor: 'Search.ResultsInfo.resultsFor',\n products: 'Search.ResultsInfo.products',\n });\n const [searchPhrase, setSearchPhrase] = useState<string>('');\n const [totalCount, setTotalCount] = useState<number | undefined>();\n const [searchResult, setSearchResult] = useState<\n { result?: ProductSearchResult; request?: SearchVariables } | undefined\n >();\n\n const handleSearchResult = useCallback(\n (payload: { result?: ProductSearchResult; request?: SearchVariables }): void => {\n setSearchPhrase(payload.request?.phrase || '');\n setTotalCount(payload.result?.totalCount);\n setSearchResult(payload);\n },\n [],\n );\n\n // Listen for search result events\n useEffect(() => {\n const resultEvent = events.on('search/result', handleSearchResult);\n return () => {\n resultEvent?.off();\n };\n }, []);\n\n const searchPhraseNode = (\n <Slot name=\"SearchPhrase\" slot={slots?.SearchPhrase} context={{ searchResult }}>\n {searchPhrase && (\n <span data-testid=\"search-phrase\">\n {translations.resultsFor} <strong>{`\"${searchPhrase}\"`}</strong>\n </span>\n )}\n </Slot>\n );\n\n const totalCountNode = (\n <Slot name=\"TotalCount\" slot={slots?.TotalCount} context={{ searchResult }}>\n {totalCount && <span data-testid=\"total-count\">{`${totalCount} ${translations.products}`}</span>}\n </Slot>\n );\n\n return <ResultsInfoComponent searchPhrase={searchPhraseNode} totalCount={totalCountNode} />;\n};\n"],"names":["ResultsInfo","searchPhrase","totalCount","className","jsxs","classes","jsx","VComponent","slots","translations","useText","setSearchPhrase","useState","setTotalCount","searchResult","setSearchResult","handleSearchResult","useCallback","payload","_a","_b","useEffect","resultEvent","events","searchPhraseNode","Slot","totalCountNode","ResultsInfoComponent"],"mappings":"iXA2BO,MAAMA,EAAmD,CAAC,CAAE,aAAAC,EAAc,WAAAC,EAAY,UAAAC,EAAY,MAErGC,EAAC,OAAI,UAAWC,EAAQ,CAAC,mBAAoBF,CAAS,CAAC,EACpD,SAAA,CAAAF,GAAiBK,EAAAC,EAAA,CAAW,UAAU,kCAAkC,KAAMN,EAAc,EAC5FC,GAAeI,EAAAC,EAAA,CAAW,UAAU,gCAAgC,KAAML,CAAY,CAAA,CAAA,EACzF,ECDSF,EAA2C,CAAC,CAAE,MAAAQ,KAAY,CACrE,MAAMC,EAAeC,EAAQ,CAC3B,WAAY,gCACZ,SAAU,6BAAA,CACX,EACK,CAACT,EAAcU,CAAe,EAAIC,EAAiB,EAAE,EACrD,CAACV,EAAYW,CAAa,EAAID,EAA6B,EAC3D,CAACE,EAAcC,CAAe,EAAIH,EAEtC,EAEII,EAAqBC,EACxBC,GAA+E,SAC9DP,IAAAQ,EAAAD,EAAQ,UAAR,YAAAC,EAAiB,SAAU,EAAE,EAC/BN,GAAAO,EAAAF,EAAQ,SAAR,YAAAE,EAAgB,UAAU,EACxCL,EAAgBG,CAAO,CACzB,EACA,CAAA,CACF,EAGAG,EAAU,IAAM,CACd,MAAMC,EAAcC,EAAO,GAAG,gBAAiBP,CAAkB,EACjE,MAAO,IAAM,CACXM,GAAA,MAAAA,EAAa,KACf,CACF,EAAG,EAAE,EAEL,MAAME,EACHlB,EAAAmB,EAAA,CAAK,KAAK,eAAe,KAAMjB,GAAA,YAAAA,EAAO,aAAc,QAAS,CAAE,aAAAM,CAC7D,EAAA,SAAAb,GACEG,EAAA,OAAA,CAAK,cAAY,gBACf,SAAA,CAAaK,EAAA,WAAW,IAAEH,EAAA,SAAA,CAAQ,SAAI,IAAAL,CAAY,GAAI,CAAA,CAAA,CAAA,CACzD,CAEJ,CAAA,EAGIyB,IACHD,EAAK,CAAA,KAAK,aAAa,KAAMjB,GAAA,YAAAA,EAAO,WAAY,QAAS,CAAE,aAAAM,GACzD,SAAcZ,GAAAI,EAAC,OAAK,CAAA,cAAY,cAAe,SAAA,GAAGJ,CAAU,IAAIO,EAAa,QAAQ,EAAA,CAAG,CAC3F,CAAA,EAGF,OAAQH,EAAAqB,EAAA,CAAqB,aAAcH,EAAkB,WAAYE,EAAgB,CAC3F"}
@@ -0,0 +1,16 @@
1
+ import { HTMLAttributes } from 'preact/compat';
2
+ import { Container, SlotProps } from '@dropins/tools/types/elsie/src/lib';
3
+
4
+ export interface SearchBarInputProps extends HTMLAttributes<HTMLDivElement> {
5
+ searchQuery?: string;
6
+ minimumQueryLength?: number;
7
+ debounceDelay?: number;
8
+ defaultQueryPlaceholder?: string;
9
+ routeSearch?: (searchQuery: string) => void;
10
+ slots?: {
11
+ InputForm?: SlotProps;
12
+ SearchIcon?: SlotProps;
13
+ };
14
+ }
15
+ export declare const SearchBarInput: Container<SearchBarInputProps>;
16
+ //# sourceMappingURL=SearchBarInput.d.ts.map
@@ -0,0 +1,11 @@
1
+ /********************************************************************
2
+ * Copyright 2025 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+ export * from './SearchBarInput';
10
+ export { SearchBarInput as default } from './SearchBarInput';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,4 @@
1
+ import { Product } from '../../../data/models/product';
2
+
3
+ export declare const getSearchBarInputSearch: (query: string) => Promise<Product[]>;
4
+ //# sourceMappingURL=getSearchBarInputSearch.d.ts.map
@@ -0,0 +1,3 @@
1
+ export * from './SearchBarInput/index'
2
+ import _default from './SearchBarInput/index'
3
+ export default _default
@@ -0,0 +1,4 @@
1
+ /*! Copyright 2025 Adobe
2
+ All Rights Reserved. */
3
+ import{jsx as u,Fragment as x}from"@dropins/tools/preact-jsx-runtime.js";import{useMemo as R,useState as v,useCallback as S,useEffect as T}from"@dropins/tools/preact-hooks.js";import{Input as b,Icon as B}from"@dropins/tools/components.js";import{classes as F,VComponent as k,Slot as _,debounce as L}from"@dropins/tools/lib.js";import{events as E}from"@dropins/tools/event-bus.js";/* empty css */import{useText as A}from"@dropins/tools/i18n.js";import{p as N}from"../chunks/productSearch.js";import{t as y,u as D,S as I,s as U,a as j,b as z,c as K}from"../chunks/acdlEvents.js";import*as m from"@dropins/tools/preact-compat.js";import"@dropins/tools/fetch-graphql.js";const M=r=>m.createElement("svg",{id:"Icon_Search_Base","data-name":"Icon \\u2013 Search \\u2013 Base",xmlns:"http://www.w3.org/2000/svg",width:24,height:24,fill:"none",viewBox:"0 0 24 24",...r},m.createElement("g",{id:"Large"},m.createElement("rect",{id:"Placement_area","data-name":"Placement area",width:24,height:24,fill:"#fff",opacity:0}),m.createElement("g",{id:"Search_icon","data-name":"Search icon",transform:"translate(3.75 3.75)"},m.createElement("circle",{vectorEffect:"non-scaling-stroke",id:"Ellipse_186","data-name":"Ellipse 186",cx:6,cy:6,r:6,fill:"none",stroke:"currentColor"}),m.createElement("line",{vectorEffect:"non-scaling-stroke",id:"Line_556","data-name":"Line 556",x2:6,y2:6,transform:"translate(10.5 10.5)",fill:"none",stroke:"currentColor"})))),C={ENTER:"Enter",ESCAPE:"Escape"},O=({searchQuery:r="",defaultQueryPlaceholder:e,searchIcon:a,onQueryInput:o,onExecuteSearch:n,onClose:t})=>{const h=A({placeholder:"Search.SearchInput.placeholder"}),p=s=>{var f,c;const{key:i}=s,d=((c=(f=s.currentTarget)==null?void 0:f.value)==null?void 0:c.trim())||"";i===C.ENTER&&d?n==null||n(d):i===C.ESCAPE&&(t==null||t())},l=s=>{var i;o==null||o(((i=s.currentTarget)==null?void 0:i.value)||"")};return u("div",{className:F(["product-discovery--search-bar-input__container"]),children:u(b,{id:"search-bar-input-form",role:"searchbox","aria-label":"Search Input",value:r,placeholder:e||h.placeholder,icon:a?u(k,{className:"product-discovery--search-bar-input__form",node:a}):void 0,onKeyDown:p,onChange:l})})},V={attribute:"visibility",in:["Search","Catalog, Search"]},w=(r,e)=>{console.error(`Error collecting ${e}:`,r)},Y=r=>({currentPage:1,pageSize:r,totalPages:1,totalItems:r}),$=r=>{let e="";try{e=self.crypto.randomUUID(),D(I,e,r.phrase||"",r.filter||[],r.pageSize||0,r.currentPage||0,r.sort||[]),U(I)}catch(a){w(a,"search input context")}return e},H=(r,e,a)=>{try{j(I,r,{items:Array.isArray(e)?e:[],facets:[],pageInfo:Y((e==null?void 0:e.length)||0),totalCount:(e==null?void 0:e.length)||0}),z(I),a&&K(I)}catch(o){w(o,"search input data")}},G=r=>{const e=structuredClone(r);return e.filter||(e.filter=[]),e.filter.push(V),e},J=r=>{if(!(r!=null&&r.trim()))return Promise.resolve([]);const e={phrase:r.trim()},a=$(e),o=G(e);return N(o).then(n=>{const t=(y(n)||[]).slice(0,8);return H(a,t,!!e.phrase),t}).catch(n=>{throw console.error("SearchInput query failed:",n),new Error("Error fetching search input data.")})},W=(r,e,a)=>{const[o,n]=v(!1),[t,h]=v(null),p=S(async c=>{n(!0),h(null);try{E.emit("search-input/request",{phrase:c});const g=await J(c);E.emit("search-input/result",{result:g,request:{phrase:c}})}catch(g){const P=g instanceof Error?g.message:"Search Input failed";h(P)}finally{n(!1)}},[]),l=R(()=>L(p,e),[p,e]);T(()=>()=>{l.cancel&&l.cancel()},[l]);const s=S(()=>{E.emit("search-input/result",{result:[],request:{phrase:""}})},[]),i=S(c=>{if(t&&h(null),c.length<1){s();return}c.length>=r&&l(c)},[r,l,t,s]),d=S(c=>{a&&a(c),E.emit("search/request",{phrase:c})},[a]),f=S(()=>{h(null),n(!1),s()},[s]);return{isLoading:o,error:t,handleQueryInput:i,handleExecuteSearch:d,handleClose:f}},oe=({searchQuery:r,minimumQueryLength:e=3,debounceDelay:a=300,defaultQueryPlaceholder:o,routeSearch:n=()=>{},slots:t})=>{const{isLoading:h,error:p,handleQueryInput:l,handleExecuteSearch:s,handleClose:i}=W(e,a,n),d=R(()=>u(_,{name:"InputFormSearchIcon",slot:t==null?void 0:t.SearchIcon,children:u(B,{source:M,size:"24"})}),[t==null?void 0:t.SearchIcon]),f=R(()=>u(_,{name:"InputForm",slot:t==null?void 0:t.InputForm,children:u(O,{searchQuery:r,defaultQueryPlaceholder:o,searchIcon:d,onQueryInput:l,onExecuteSearch:s,onClose:i,isLoading:h,error:p})}),[r,o,d,l,s,i,h,p,t==null?void 0:t.InputForm]);return u(x,{children:f})};export{oe as SearchBarInput,oe as default};
4
+ //# sourceMappingURL=SearchBarInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchBarInput.js","sources":["../../node_modules/@adobe-commerce/elsie/src/icons/Search.svg","/@dropins/storefront-product-discovery/src/components/SearchBarInput/SearchBarInput.tsx","/@dropins/storefront-product-discovery/src/containers/SearchBarInput/utils/getSearchBarInputSearch.ts","/@dropins/storefront-product-discovery/src/containers/SearchBarInput/SearchBarInput.tsx"],"sourcesContent":["import * as React from \"react\";\nconst SvgSearch = (props) => /* @__PURE__ */ React.createElement(\"svg\", { id: \"Icon_Search_Base\", \"data-name\": \"Icon \\\\u2013 Search \\\\u2013 Base\", xmlns: \"http://www.w3.org/2000/svg\", width: 24, height: 24, fill: \"none\", viewBox: \"0 0 24 24\", ...props }, /* @__PURE__ */ React.createElement(\"g\", { id: \"Large\" }, /* @__PURE__ */ React.createElement(\"rect\", { id: \"Placement_area\", \"data-name\": \"Placement area\", width: 24, height: 24, fill: \"#fff\", opacity: 0 }), /* @__PURE__ */ React.createElement(\"g\", { id: \"Search_icon\", \"data-name\": \"Search icon\", transform: \"translate(3.75 3.75)\" }, /* @__PURE__ */ React.createElement(\"circle\", { vectorEffect: \"non-scaling-stroke\", id: \"Ellipse_186\", \"data-name\": \"Ellipse 186\", cx: 6, cy: 6, r: 6, fill: \"none\", stroke: \"currentColor\" }), /* @__PURE__ */ React.createElement(\"line\", { vectorEffect: \"non-scaling-stroke\", id: \"Line_556\", \"data-name\": \"Line 556\", x2: 6, y2: 6, transform: \"translate(10.5 10.5)\", fill: \"none\", stroke: \"currentColor\" }))));\nexport default SvgSearch;\n","/********************************************************************\n * Copyright 2025 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport { FunctionComponent, VNode } from 'preact';\nimport { HTMLAttributes, TargetedEvent } from 'preact/compat';\nimport { Input } from '@adobe-commerce/elsie/components';\nimport { useText } from '@adobe-commerce/elsie/i18n';\nimport { classes, VComponent } from '@adobe-commerce/elsie/lib';\n\nimport '@/plp/components/SearchBarInput/SearchBarInput.css';\n\nconst KEY_PRESS_EVENTS = {\n ENTER: 'Enter',\n ESCAPE: 'Escape',\n} as const;\n\nexport interface SearchBarInputProps extends HTMLAttributes<HTMLDivElement> {\n searchIcon?: VNode;\n searchQuery?: string;\n defaultQueryPlaceholder?: string;\n isLoading?: boolean;\n error?: string | null;\n onQueryInput?: (query: string) => void;\n onExecuteSearch?: (query: string) => void;\n onClose?: () => void;\n}\n\nexport const SearchBarInput: FunctionComponent<SearchBarInputProps> = ({\n searchQuery = '',\n defaultQueryPlaceholder,\n searchIcon,\n onQueryInput,\n onExecuteSearch,\n onClose,\n}) => {\n const translations = useText({ placeholder: 'Search.SearchInput.placeholder' });\n\n const handleKeyPress = (event: TargetedEvent<HTMLInputElement, KeyboardEvent>) => {\n const { key } = event;\n const inputValue = event.currentTarget?.value?.trim() || '';\n\n if (key === KEY_PRESS_EVENTS.ENTER && inputValue) {\n onExecuteSearch?.(inputValue);\n } else if (key === KEY_PRESS_EVENTS.ESCAPE) {\n onClose?.();\n }\n };\n\n const handleQueryInput = (event: TargetedEvent<HTMLInputElement, Event>) => {\n onQueryInput?.(event.currentTarget?.value || '');\n };\n\n return (\n <div className={classes(['product-discovery--search-bar-input__container'])}>\n <Input\n id=\"search-bar-input-form\"\n role=\"searchbox\"\n aria-label=\"Search Input\"\n value={searchQuery}\n placeholder={defaultQueryPlaceholder || translations.placeholder}\n icon={\n searchIcon ? (\n <VComponent className=\"product-discovery--search-bar-input__form\" node={searchIcon} />\n ) : undefined\n }\n onKeyDown={handleKeyPress}\n onChange={handleQueryInput}\n />\n </div>\n );\n};\n","/********************************************************************\n * Copyright 2025 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport { productSearch as productSearchQuery } from '@/plp/api';\nimport { SearchVariables } from '@/plp/data/models';\nimport { Product } from '@/plp/data/models/product';\nimport { transformSearchResultProducts } from '@/plp/data/transforms';\nimport {\n SEARCH_UNIT_ID,\n searchRequestSent,\n searchResponseReceived,\n searchResultsView,\n updateSearchInputCtx,\n updateSearchResultsCtx,\n} from '@/plp/utils/acdlEvents';\n\n// Constants\nconst DEFAULT_VISIBILITY_FILTER = {\n attribute: 'visibility',\n in: ['Search', 'Catalog, Search'],\n};\n\ninterface PageInfo {\n currentPage: number;\n pageSize: number;\n totalPages: number;\n totalItems: number;\n}\n\nconst handleDataCollectionError = (error: any, context: string): void => {\n console.error(`Error collecting ${context}:`, error);\n};\n\nconst createPageInfo = (itemsLength: number): PageInfo => ({\n currentPage: 1,\n pageSize: itemsLength,\n totalPages: 1,\n totalItems: itemsLength,\n});\n\nconst trackSearchRequest = (searchRequestVariable: SearchVariables): string => {\n let searchRequestId = '';\n\n try {\n searchRequestId = self.crypto.randomUUID();\n updateSearchInputCtx(\n SEARCH_UNIT_ID,\n searchRequestId,\n searchRequestVariable.phrase || '',\n searchRequestVariable.filter || [],\n searchRequestVariable.pageSize || 0,\n searchRequestVariable.currentPage || 0,\n searchRequestVariable.sort || [],\n );\n searchRequestSent(SEARCH_UNIT_ID);\n } catch (e) {\n handleDataCollectionError(e, 'search input context');\n }\n\n return searchRequestId;\n};\n\nconst updateSearchResults = (searchRequestId: string, items: Product[], hasPhrase: boolean): void => {\n try {\n updateSearchResultsCtx(SEARCH_UNIT_ID, searchRequestId, {\n items: Array.isArray(items) ? items : [],\n facets: [],\n pageInfo: createPageInfo(items?.length || 0),\n totalCount: items?.length || 0,\n });\n searchResponseReceived(SEARCH_UNIT_ID);\n\n if (hasPhrase) {\n searchResultsView(SEARCH_UNIT_ID);\n }\n } catch (e) {\n handleDataCollectionError(e, 'search input data');\n }\n};\n\nconst prepareSearchRequest = (searchRequestVariable: SearchVariables): SearchVariables => {\n const searchRequestObject = structuredClone(searchRequestVariable);\n\n if (!searchRequestObject.filter) {\n searchRequestObject.filter = [];\n }\n searchRequestObject.filter.push(DEFAULT_VISIBILITY_FILTER);\n\n return searchRequestObject;\n};\n\nexport const getSearchBarInputSearch = (query: string): Promise<Product[]> => {\n if (!query?.trim()) {\n return Promise.resolve([]);\n }\n\n const searchRequestVariable: SearchVariables = { phrase: query.trim() };\n const searchRequestId = trackSearchRequest(searchRequestVariable);\n const searchRequestObject = prepareSearchRequest(searchRequestVariable);\n\n return productSearchQuery(searchRequestObject)\n .then((response: any | null) => {\n const transformedItems = (transformSearchResultProducts(response) || []).slice(0, 8);\n\n updateSearchResults(searchRequestId, transformedItems, !!searchRequestVariable.phrase);\n\n return transformedItems;\n })\n .catch((error: any) => {\n console.error('SearchInput query failed:', error);\n throw new Error('Error fetching search input data.');\n });\n};\n","/********************************************************************\n * Copyright 2025 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport { HTMLAttributes } from 'preact/compat';\nimport { useCallback, useEffect, useMemo, useState } from 'preact/hooks';\nimport { Icon } from '@adobe-commerce/elsie/components';\nimport { Search } from '@adobe-commerce/elsie/icons';\nimport { Container, Slot, SlotProps, debounce } from '@adobe-commerce/elsie/lib';\nimport { events } from '@adobe-commerce/event-bus';\n\nimport { SearchBarInput as SearchBarInputComponent } from '@/plp/components/SearchBarInput';\nimport { Product, SearchInputRequest, SearchInputResult } from '@/plp/data/models/product';\n\nimport { getSearchBarInputSearch } from './utils/getSearchBarInputSearch';\n\nexport interface SearchBarInputProps extends HTMLAttributes<HTMLDivElement> {\n searchQuery?: string;\n minimumQueryLength?: number;\n debounceDelay?: number;\n defaultQueryPlaceholder?: string;\n routeSearch?: (searchQuery: string) => void;\n slots?: {\n InputForm?: SlotProps;\n SearchIcon?: SlotProps;\n };\n}\n\n// debounced function type helper method\ntype DebouncedFunction<T extends (...args: any[]) => any> = T & {\n cancel?: () => void;\n};\n\nconst useSearchBarInput = (\n minimumQueryLength: number,\n debounceDelay: number,\n routeSearch: (searchQuery: string) => void,\n) => {\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const handleSearch = useCallback(async (query: string) => {\n setIsLoading(true);\n setError(null);\n\n try {\n events.emit('search-input/request', { phrase: query });\n const searchInputResults = await getSearchBarInputSearch(query);\n events.emit('search-input/result', {\n result: searchInputResults as Product[],\n request: { phrase: query },\n } as SearchInputResult);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Search Input failed';\n setError(errorMessage);\n // may need to emit an error event here?\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n // the adobe elsie debounce function *should* have a cancel, but it doesnt seem to be typed correctly\n const debouncedSearch = useMemo(\n () => debounce(handleSearch, debounceDelay) as DebouncedFunction<typeof handleSearch>,\n [handleSearch, debounceDelay],\n );\n\n // need to cancel any pending debounced calls when component unmounts or debouncedSearch changes\n useEffect(() => {\n return () => {\n if (debouncedSearch.cancel) {\n debouncedSearch.cancel();\n }\n };\n }, [debouncedSearch]);\n\n const clearSearchResults = useCallback(() => {\n events.emit('search-input/result', {\n result: [],\n request: { phrase: '' },\n } as SearchInputResult);\n }, []);\n\n const handleQueryInput = useCallback(\n (query: string) => {\n if (error) {\n setError(null);\n }\n\n if (query.length < 1) {\n clearSearchResults();\n return;\n }\n\n if (query.length >= minimumQueryLength) {\n debouncedSearch(query);\n }\n },\n [minimumQueryLength, debouncedSearch, error, clearSearchResults],\n );\n\n const handleExecuteSearch = useCallback(\n (query: string) => {\n // if a `routeSearch` cb function is provided, use it to handle any navigation\n routeSearch && routeSearch(query);\n events.emit('search/request', { phrase: query } as SearchInputRequest);\n },\n [routeSearch],\n );\n\n const handleClose = useCallback(() => {\n setError(null);\n setIsLoading(false);\n clearSearchResults();\n }, [clearSearchResults]);\n\n return {\n isLoading,\n error,\n handleQueryInput,\n handleExecuteSearch,\n handleClose,\n };\n};\n\nexport const SearchBarInput: Container<SearchBarInputProps> = ({\n searchQuery,\n minimumQueryLength = 3,\n debounceDelay = 300,\n defaultQueryPlaceholder,\n routeSearch = () => {},\n slots,\n}) => {\n const { isLoading, error, handleQueryInput, handleExecuteSearch, handleClose } = useSearchBarInput(\n minimumQueryLength,\n debounceDelay,\n routeSearch,\n );\n\n const searchIcon = useMemo(\n () => (\n <Slot name=\"InputFormSearchIcon\" slot={slots?.SearchIcon}>\n <Icon source={Search} size=\"24\" />\n </Slot>\n ),\n [slots?.SearchIcon],\n );\n\n const inputForm = useMemo(\n () => (\n <Slot name=\"InputForm\" slot={slots?.InputForm}>\n <SearchBarInputComponent\n searchQuery={searchQuery}\n defaultQueryPlaceholder={defaultQueryPlaceholder}\n searchIcon={searchIcon}\n onQueryInput={handleQueryInput}\n onExecuteSearch={handleExecuteSearch}\n onClose={handleClose}\n isLoading={isLoading}\n error={error}\n />\n </Slot>\n ),\n [\n searchQuery,\n defaultQueryPlaceholder,\n searchIcon,\n handleQueryInput,\n handleExecuteSearch,\n handleClose,\n isLoading,\n error,\n slots?.InputForm,\n ],\n );\n\n return <>{inputForm}</>;\n};\n"],"names":["SvgSearch","props","React","KEY_PRESS_EVENTS","SearchBarInput","searchQuery","defaultQueryPlaceholder","searchIcon","onQueryInput","onExecuteSearch","onClose","translations","useText","handleKeyPress","event","key","inputValue","_b","_a","handleQueryInput","classes","jsx","Input","VComponent","DEFAULT_VISIBILITY_FILTER","handleDataCollectionError","error","context","createPageInfo","itemsLength","trackSearchRequest","searchRequestVariable","searchRequestId","updateSearchInputCtx","SEARCH_UNIT_ID","searchRequestSent","e","updateSearchResults","items","hasPhrase","updateSearchResultsCtx","searchResponseReceived","searchResultsView","prepareSearchRequest","searchRequestObject","getSearchBarInputSearch","query","productSearchQuery","response","transformedItems","transformSearchResultProducts","useSearchBarInput","minimumQueryLength","debounceDelay","routeSearch","isLoading","setIsLoading","useState","setError","handleSearch","useCallback","events","searchInputResults","err","errorMessage","debouncedSearch","useMemo","debounce","useEffect","clearSearchResults","handleExecuteSearch","handleClose","slots","Slot","Icon","Search","inputForm","SearchBarInputComponent"],"mappings":"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","x_google_ignoreList":[0]}
@@ -0,0 +1,15 @@
1
+ import { HTMLAttributes } from 'preact/compat';
2
+ import { Container, SlotProps } from '@dropins/tools/types/elsie/src/lib';
3
+ import { Product } from '../../data/models/product';
4
+
5
+ export interface SearchBarResultsProps extends HTMLAttributes<HTMLDivElement> {
6
+ products?: Product[];
7
+ routeSearch?: (searchQuery: string) => void;
8
+ slots?: {
9
+ ProductImage?: SlotProps;
10
+ ProductName?: SlotProps;
11
+ ProductPrice?: SlotProps;
12
+ };
13
+ }
14
+ export declare const SearchBarResults: Container<SearchBarResultsProps>;
15
+ //# sourceMappingURL=SearchBarResults.d.ts.map
@@ -0,0 +1,11 @@
1
+ /********************************************************************
2
+ * Copyright 2025 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+ export * from './SearchBarResults';
10
+ export { SearchBarResults as default } from './SearchBarResults';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ export * from './SearchBarResults/index'
2
+ import _default from './SearchBarResults/index'
3
+ export default _default
@@ -0,0 +1,5 @@
1
+ /*! Copyright 2025 Adobe
2
+ All Rights Reserved. */
3
+ import{jsx as n,jsxs as y}from"@dropins/tools/preact-jsx-runtime.js";import{useRef as T,useCallback as P,useEffect as x,useMemo as j,useState as f}from"@dropins/tools/preact-compat.js";import{Button as $,Price as q,Image as D}from"@dropins/tools/components.js";import{VComponent as v,Slot as g}from"@dropins/tools/lib.js";import{events as p}from"@dropins/tools/event-bus.js";/* empty css */import{useText as K}from"@dropins/tools/i18n.js";const O=({productList:a,viewAllButton:i,onClose:r,...s})=>{const o=a&&a.length>0,t=T(null),u=P(c=>{t.current&&!t.current.contains(c.target)&&(r==null||r())},[r]),l=P(c=>{c.key==="Escape"&&(r==null||r())},[r]);return x(()=>{if(o)return document.addEventListener("mousedown",u),document.addEventListener("keydown",l),()=>{document.removeEventListener("mousedown",u),document.removeEventListener("keydown",l)}},[o,u,l]),o?n("div",{className:"product-discovery--search-bar-results",...s,children:y("div",{className:"product-discovery--search-bar-results__popover",ref:t,role:"region","aria-label":"Search results","aria-live":"polite",children:[n("div",{className:"product-discovery--search-bar-results__grid",role:"list","aria-label":`${(a==null?void 0:a.length)||0} search results`,children:a==null?void 0:a.map((c,m)=>n("div",{role:"listitem",children:c},m))}),i&&n("div",{className:"product-discovery--search-bar-results__view-all-wrapper",children:n(v,{className:"product-discovery--search-bar-results__view-all-button",node:i})})]})}):null},Q=({productItem:a,productImage:i,productName:r,productPrice:s,...o})=>{const t=j(()=>{const{name:u="",sku:l="",url:c=""}=a||{};return{tooltipText:[u,l&&`SKU: ${l}`].filter(Boolean).join(`
4
+ `),url:c}},[a]);return y("a",{className:"product-discovery--product-item",href:t.url,target:"_blank",rel:"noopener noreferrer",title:t.tooltipText,...o,children:[n("div",{className:"product-discovery--product-item__image",children:n(v,{node:i})}),y("div",{className:"product-discovery--product-item__details",children:[n(v,{node:r}),n(v,{node:s})]})]})},W=({products:a=[],routeSearch:i=()=>{},slots:r})=>{const[s,o]=f(a),[t,u]=f(""),[l,c]=f(a.length>0),m=K({viewAllButton:"Search.SearchInput.viewAllButton"});x(()=>{const e=p.on("search-input/result",B);return()=>{e==null||e.off()}},[]);const B=({result:e=[],request:d={}})=>{const{phrase:h=""}=d;o(e),u(h),c(e.length>0&&h.length>0)},w=P(()=>{i&&i(t),p.emit("search/request",{phrase:t}),p.emit("search-input/result",{result:[],request:{phrase:""}}),c(!1)},[i,t]),R=e=>{var d,h;return n(g,{name:"ProductImage",slot:r==null?void 0:r.ProductImage,context:{productItem:e},children:n(D,{src:((h=(d=e==null?void 0:e.images)==null?void 0:d[0])==null?void 0:h.url)||""})})},S=e=>n(g,{name:"ProductName",slot:r==null?void 0:r.ProductName,context:{productItem:e},children:(e==null?void 0:e.name)||""}),k=e=>{var _,N,b;const{value:d,currency:h}=((b=(N=(_=e==null?void 0:e.priceRange)==null?void 0:_.minimum)==null?void 0:N.final)==null?void 0:b.amount)||{};return n(g,{name:"ProductPrice",slot:r==null?void 0:r.ProductPrice,context:{productItem:e},children:n(q,{amount:typeof d=="number"?d:void 0,currency:h})})},E=e=>n(Q,{productItem:e,productImage:R(e),productName:S(e),productPrice:k(e)}),A=()=>n($,{variant:"tertiary",onClick:()=>{w()},children:m.viewAllButton});return n("div",{children:s.length>0&&l&&n(O,{productList:s==null?void 0:s.map(e=>E(e)),viewAllButton:A(),onClose:w})})};export{W as SearchBarResults,W as default};
5
+ //# sourceMappingURL=SearchBarResults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchBarResults.js","sources":["/@dropins/storefront-product-discovery/src/components/SearchBarResults/SearchBarResults.tsx","/@dropins/storefront-product-discovery/src/components/ProductItem/ProductItem.tsx","/@dropins/storefront-product-discovery/src/containers/SearchBarResults/SearchBarResults.tsx"],"sourcesContent":["/********************************************************************\n * Copyright 2025 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport { FunctionComponent, VNode } from 'preact';\nimport { HTMLAttributes, useEffect, useRef, useCallback } from 'preact/compat';\nimport { VComponent } from '@adobe-commerce/elsie/lib';\n\nimport '@/plp/components/SearchBarResults/SearchBarResults.css';\n\nexport interface SearchBarResultsProps extends HTMLAttributes<HTMLDivElement> {\n productList?: VNode[];\n viewAllButton?: VNode;\n onClose?: () => void;\n}\n\nexport const SearchBarResults: FunctionComponent<SearchBarResultsProps> = ({\n productList,\n viewAllButton,\n onClose,\n ...props\n}) => {\n const hasData = productList && productList.length > 0;\n const popoverRef = useRef<HTMLDivElement>(null);\n\n const handleClickOutside = useCallback(\n (event: MouseEvent) => {\n if (popoverRef.current && !popoverRef.current.contains(event.target as Node)) {\n onClose?.();\n }\n },\n [onClose],\n );\n\n const handleEscapeKey = useCallback(\n (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose?.();\n }\n },\n [onClose],\n );\n\n useEffect(() => {\n if (!hasData) return;\n\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('keydown', handleEscapeKey);\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('keydown', handleEscapeKey);\n };\n }, [hasData, handleClickOutside, handleEscapeKey]);\n\n if (!hasData) return null;\n\n return (\n <div className=\"product-discovery--search-bar-results\" {...props}>\n <div\n className=\"product-discovery--search-bar-results__popover\"\n ref={popoverRef}\n role=\"region\"\n aria-label=\"Search results\"\n aria-live=\"polite\"\n >\n <div\n className=\"product-discovery--search-bar-results__grid\"\n role=\"list\"\n aria-label={`${productList?.length || 0} search results`}\n >\n {productList?.map((item, index) => (\n <div key={index} role=\"listitem\">\n {item}\n </div>\n ))}\n </div>\n {viewAllButton && (\n <div className=\"product-discovery--search-bar-results__view-all-wrapper\">\n <VComponent className=\"product-discovery--search-bar-results__view-all-button\" node={viewAllButton} />\n </div>\n )}\n </div>\n </div>\n );\n};\n","/********************************************************************\n * Copyright 2025 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n ***************************************************************************/\n\nimport { FunctionComponent, VNode } from 'preact';\nimport { HTMLAttributes, useMemo } from 'preact/compat';\nimport { VComponent } from '@adobe-commerce/elsie/lib';\nimport { Product } from '@/plp/data/models/product';\n\nimport '@/plp/components/ProductItem/ProductItem.css';\n\nexport interface ProductItemProps extends HTMLAttributes<HTMLDivElement> {\n productItem: Product;\n productImage?: VNode;\n productName?: VNode;\n productPrice?: VNode;\n}\n\nexport const ProductItem: FunctionComponent<ProductItemProps> = ({\n productItem,\n productImage,\n productName,\n productPrice,\n ...props\n}) => {\n const productData = useMemo(() => {\n const { name = '', sku = '', url = '' } = productItem || {};\n\n // create tooltip text depending on available data\n const tooltipText = [name, sku && `SKU: ${sku}`].filter(Boolean).join('\\n');\n\n return { tooltipText, url };\n }, [productItem]);\n\n return (\n <a\n className=\"product-discovery--product-item\"\n href={productData.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title={productData.tooltipText}\n {...props}\n >\n <div className=\"product-discovery--product-item__image\">\n <VComponent node={productImage} />\n </div>\n <div className=\"product-discovery--product-item__details\">\n <VComponent node={productName} />\n <VComponent node={productPrice} />\n </div>\n </a>\n );\n};\n","/********************************************************************\n * Copyright 2025 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport { HTMLAttributes, useState, useEffect, useCallback } from 'preact/compat';\nimport { Button, Image, Price } from '@adobe-commerce/elsie/components';\nimport { useText } from '@adobe-commerce/elsie/i18n';\nimport { Container, Slot, SlotProps } from '@adobe-commerce/elsie/lib';\nimport { events } from '@adobe-commerce/event-bus';\n\nimport { Product, SearchInputRequest, SearchInputResult } from '@/plp/data/models/product';\nimport { SearchVariables } from '@/plp/data/models/api';\nimport { SearchBarResults as SearchBarResultsComponent } from '@/plp/components/SearchBarResults';\nimport { ProductItem as ProductItemComponent } from '@/plp/components/ProductItem';\n\nexport interface SearchBarResultsProps extends HTMLAttributes<HTMLDivElement> {\n products?: Product[];\n routeSearch?: (searchQuery: string) => void;\n slots?: {\n ProductImage?: SlotProps;\n ProductName?: SlotProps;\n ProductPrice?: SlotProps;\n };\n}\n\nexport const SearchBarResults: Container<SearchBarResultsProps> = ({\n products = [],\n routeSearch = () => {},\n slots,\n}) => {\n const [searchResults, setSearchResults] = useState<Product[]>(products);\n const [searchQuery, setSearchQuery] = useState('');\n const [showResults, setShowResults] = useState(products.length > 0);\n\n const translations = useText({ viewAllButton: 'Search.SearchInput.viewAllButton' });\n\n useEffect(() => {\n const searchInputEvent = events.on('search-input/result', handleSearchInputResult);\n\n return () => {\n searchInputEvent?.off();\n };\n }, []);\n\n const handleSearchInputResult = ({\n result = [],\n request = {},\n }: {\n result?: Product[];\n request?: Pick<SearchVariables, 'phrase'>;\n }) => {\n const { phrase = '' } = request;\n setSearchResults(result);\n setSearchQuery(phrase);\n setShowResults(result.length > 0 && phrase.length > 0);\n };\n\n const handleOnClose = useCallback(() => {\n // if a `routeSearch` cb function is provided, use it to handle any navigation needed\n routeSearch && routeSearch(searchQuery);\n\n // emit \"search/request\" event to trigger listeners of the search event\n events.emit('search/request', { phrase: searchQuery } as SearchInputRequest);\n\n // emit \"search-input/result\" event with empty payloads to clear anything listening for that\n events.emit('search-input/result', {\n result: [],\n request: { phrase: '' },\n } as SearchInputResult);\n\n setShowResults(false);\n }, [routeSearch, searchQuery]);\n\n const getProductImage = (productItem: Product) => (\n <Slot name=\"ProductImage\" slot={slots?.ProductImage} context={{ productItem }}>\n <Image src={productItem?.images?.[0]?.url || ''} />\n </Slot>\n );\n\n const getProductName = (productItem: Product) => (\n <Slot name=\"ProductName\" slot={slots?.ProductName} context={{ productItem }}>\n {productItem?.name || ''}\n </Slot>\n );\n\n const getProductPrice = (productItem: Product) => {\n const { value, currency } = productItem?.priceRange?.minimum?.final?.amount || {};\n return (\n <Slot name=\"ProductPrice\" slot={slots?.ProductPrice} context={{ productItem }}>\n <Price amount={typeof value === 'number' ? value : undefined} currency={currency} />\n </Slot>\n );\n };\n\n const productContainer = (productItem: Product) => (\n <ProductItemComponent\n productItem={productItem}\n productImage={getProductImage(productItem)}\n productName={getProductName(productItem)}\n productPrice={getProductPrice(productItem)}\n />\n );\n\n const viewAllButton = () => (\n <Button\n variant=\"tertiary\"\n onClick={() => {\n handleOnClose();\n }}\n >\n {translations.viewAllButton}\n </Button>\n );\n\n const searchBarResultsContainer = () =>\n searchResults.length > 0 &&\n showResults && (\n <SearchBarResultsComponent\n productList={searchResults?.map((product) => productContainer(product))}\n viewAllButton={viewAllButton()}\n onClose={handleOnClose}\n />\n );\n\n return <div>{searchBarResultsContainer()}</div>;\n};\n"],"names":["SearchBarResults","productList","viewAllButton","onClose","props","hasData","popoverRef","useRef","handleClickOutside","useCallback","event","handleEscapeKey","useEffect","jsx","jsxs","item","index","VComponent","ProductItem","productItem","productImage","productName","productPrice","productData","useMemo","name","sku","url","products","routeSearch","slots","searchResults","setSearchResults","useState","searchQuery","setSearchQuery","showResults","setShowResults","translations","useText","searchInputEvent","events","handleSearchInputResult","result","request","phrase","handleOnClose","getProductImage","Slot","Image","_b","_a","getProductName","getProductPrice","value","currency","_c","Price","productContainer","ProductItemComponent","Button","SearchBarResultsComponent","product"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /********************************************************************
2
+ * Copyright 2025 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+ export * from './ProductList';
10
+ export * from './Facets';
11
+ export * from './ResultsInfo';
12
+ export * from './SearchBarInput';
13
+ export * from './SearchBarResults';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,86 @@
1
+ export interface SearchInput {
2
+ units: Array<SearchInputUnit>;
3
+ }
4
+ export interface SearchInputUnit {
5
+ searchUnitId: string;
6
+ searchRequestId: string;
7
+ queryTypes: Array<'products' | 'suggestions' | 'categories'>;
8
+ phrase: string;
9
+ pageSize: number;
10
+ currentPage: number;
11
+ filter: Array<SearchFilter>;
12
+ sort: Array<SearchSort>;
13
+ context?: QueryContextInput;
14
+ }
15
+ export interface QueryContextInput {
16
+ customerGroup: string;
17
+ }
18
+ export interface SearchFilter {
19
+ attribute: string;
20
+ eq?: string;
21
+ in?: Array<string>;
22
+ range?: {
23
+ from?: number;
24
+ to?: number;
25
+ };
26
+ }
27
+ export interface SearchSort {
28
+ attribute: string;
29
+ direction: 'ASC' | 'DESC';
30
+ }
31
+ export interface SearchResults {
32
+ units: Array<SearchResultUnit>;
33
+ }
34
+ export interface SearchResultUnit {
35
+ searchUnitId: string;
36
+ searchRequestId: string;
37
+ rankingType?: string;
38
+ trendingWindow?: string;
39
+ executionTime?: number;
40
+ products: Array<SearchResultProduct>;
41
+ categories: Array<SearchResultCategory>;
42
+ suggestions: Array<SearchResultSuggestion>;
43
+ page: number;
44
+ perPage: number;
45
+ facets: Array<SearchFacetContext> | null;
46
+ }
47
+ export interface SearchResultProduct {
48
+ name: string;
49
+ sku: string;
50
+ url: string;
51
+ imageUrl: string;
52
+ price?: number;
53
+ rank: number;
54
+ }
55
+ export interface SearchResultCategory {
56
+ name: string;
57
+ url: string;
58
+ rank: number;
59
+ }
60
+ export interface SearchResultSuggestion {
61
+ suggestion: string;
62
+ rank: number;
63
+ }
64
+ export interface SearchFacetContext {
65
+ attribute: string;
66
+ buckets: Array<SearchBucket>;
67
+ title: string;
68
+ type?: 'PINNED' | 'INTELLIGENT' | 'POPULAR';
69
+ }
70
+ export type SearchBucket = RangeBucket | ScalarBucket | StatsBucket;
71
+ export interface RangeBucket {
72
+ count: number;
73
+ from: number;
74
+ title: string;
75
+ to?: number;
76
+ }
77
+ export interface ScalarBucket {
78
+ count: number;
79
+ title: string;
80
+ }
81
+ export interface StatsBucket {
82
+ min: number;
83
+ max: number;
84
+ title: string;
85
+ }
86
+ //# sourceMappingURL=acdl.d.ts.map
@@ -0,0 +1,72 @@
1
+ import { Product } from './product';
2
+
3
+ export interface SearchVariables {
4
+ phrase?: string;
5
+ filter?: SearchFilter[];
6
+ sort?: SortOrder[];
7
+ currentPage?: number;
8
+ pageSize?: number;
9
+ context?: SearchContext;
10
+ }
11
+ export interface SearchContext {
12
+ customerGroup?: string;
13
+ userViewHistory?: ViewHistoryRecord[];
14
+ }
15
+ export interface ViewHistoryRecord {
16
+ sku: string;
17
+ dateTime: string;
18
+ }
19
+ export interface SearchFilter {
20
+ attribute: string;
21
+ in?: string[];
22
+ eq?: string;
23
+ range?: {
24
+ from: number;
25
+ to: number;
26
+ };
27
+ }
28
+ export interface SortOrder {
29
+ attribute: string;
30
+ direction: 'ASC' | 'DESC';
31
+ }
32
+ export interface RefineOption {
33
+ label: string;
34
+ attribute: string;
35
+ numeric: boolean;
36
+ }
37
+ export interface ProductSearchResponse {
38
+ productSearch: ProductSearchResult;
39
+ }
40
+ export interface ProductSearchResult {
41
+ facets: SearchFacet[];
42
+ items: Product[];
43
+ pageInfo: {
44
+ currentPage: number;
45
+ totalPages: number;
46
+ totalItems: number;
47
+ pageSize: number;
48
+ };
49
+ suggestions?: string[];
50
+ totalCount: number;
51
+ }
52
+ export interface SearchFacet {
53
+ title: string;
54
+ attribute: string;
55
+ buckets: FacetBucket[];
56
+ }
57
+ export interface FacetBucket {
58
+ title: string;
59
+ count: number;
60
+ __typename: string;
61
+ from?: number;
62
+ to?: number;
63
+ selected?: boolean;
64
+ }
65
+ export interface AttributeMetadataResponse {
66
+ attributeMetadata: AttributeMetadata;
67
+ }
68
+ export interface AttributeMetadata {
69
+ sortable: RefineOption[];
70
+ filterableInSearch: RefineOption[];
71
+ }
72
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1,2 @@
1
+ export * from './api';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,56 @@
1
+ import { SearchInputUnit } from './acdl';
2
+
3
+ export interface Product {
4
+ id: string;
5
+ name: string;
6
+ sku: string;
7
+ shortDescription: string;
8
+ url: string;
9
+ urlKey: string;
10
+ metaTitle: string;
11
+ metaKeywords: string;
12
+ metaDescription: string;
13
+ lowStock: boolean;
14
+ links: any[];
15
+ images: ProductImage[];
16
+ description: string;
17
+ externalId: string;
18
+ inputOptions: any[];
19
+ addToCartAllowed: boolean;
20
+ price?: ProductViewPrice;
21
+ priceRange?: {
22
+ minimum: ProductViewPrice;
23
+ maximum: ProductViewPrice;
24
+ };
25
+ inStock: boolean;
26
+ typename: string;
27
+ initialized?: boolean;
28
+ }
29
+ export interface ProductViewPrice {
30
+ final: ProductPrice;
31
+ regular: ProductPrice;
32
+ roles?: string[];
33
+ }
34
+ export interface ProductPrice {
35
+ amount: {
36
+ value: number;
37
+ currency: string;
38
+ };
39
+ }
40
+ export interface ProductImage {
41
+ label: string;
42
+ roles: string[];
43
+ url: string;
44
+ }
45
+ export interface SearchInputRequest {
46
+ phrase: SearchInputUnit['phrase'];
47
+ }
48
+ export interface SearchInputResult {
49
+ result: Product[];
50
+ request: SearchInputRequest;
51
+ }
52
+ export interface SearchInputError {
53
+ error: Error;
54
+ request: SearchInputRequest;
55
+ }
56
+ //# sourceMappingURL=product.d.ts.map
@@ -0,0 +1,11 @@
1
+ import { ProductSearchResult } from '../models';
2
+ import { Product } from '../models/product';
3
+
4
+ export declare function transformProductSearchResponse(data: any): ProductSearchResult;
5
+ export declare function transformAttributeMetadata(data: any): any;
6
+ export declare const transformSearchResultProducts: (searchResponse: {
7
+ productSearch: {
8
+ items: any[];
9
+ };
10
+ }) => Product[];
11
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1,11 @@
1
+ /********************************************************************
2
+ * Copyright 2025 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+ export * from './product';
10
+ export * from './api';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,4 @@
1
+ import { Product } from '../models/product';
2
+
3
+ export declare const transformProduct: (data: any) => Product | null;
4
+ //# sourceMappingURL=product.d.ts.map
@@ -0,0 +1,40 @@
1
+ declare const _default: {
2
+ "Search": {
3
+ "PLP": {
4
+ "Warning": {
5
+ "minQueryLength": "Your search term {SEARCH_PHRASE} has not reached the minimum of {{minQueryLength}} characters.",
6
+ "noResults": "Your search returned no results.",
7
+ "searchError": "An error occurred while searching."
8
+ },
9
+ "SortDropdown": {
10
+ "title": "Sort by",
11
+ "option": "Sort by: {{selectedOption}}",
12
+ "relevanceLabel": "Most Relevant",
13
+ "positionLabel": "Position",
14
+ "sortAttributeASC": "{{label}}: Low to High",
15
+ "sortAttributeDESC": "{{label}}: High to Low",
16
+ "sortASC": "Price: Low to High",
17
+ "sortDESC": "Price: High to Low",
18
+ "productName": "Product Name",
19
+ "productInStock": "In Stock",
20
+ "productLowStock": "Low Stock"
21
+ }
22
+ },
23
+ "Facet": {
24
+ "showMore": "Show more",
25
+ "showLess": "Show less",
26
+ "clearAll": "Clear all"
27
+ },
28
+ "ResultsInfo": {
29
+ "resultsFor": "Results for",
30
+ "products": "products"
31
+ },
32
+ "SearchInput": {
33
+ "placeholder": "Search",
34
+ "viewAllButton": "View All"
35
+ }
36
+ }
37
+ }
38
+ ;
39
+
40
+ export default _default;
package/package.json ADDED
@@ -0,0 +1 @@
1
+ {"name": "@dropins/storefront-product-discovery", "version": "0.8.0-alpha.1", "@dropins/tools": "^1.3.0-beta1", "license": "SEE LICENSE IN LICENSE.md"}
@@ -0,0 +1,8 @@
1
+ import { FunctionComponent } from 'preact';
2
+
3
+ interface CartProviderProps {
4
+ children?: any;
5
+ }
6
+ export declare const Provider: FunctionComponent<CartProviderProps>;
7
+ export {};
8
+ //# sourceMappingURL=Provider.d.ts.map
@@ -0,0 +1,10 @@
1
+ /********************************************************************
2
+ * Copyright 2025 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+ export * from './render';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,4 @@
1
+ import { Render } from '@dropins/tools/types/elsie/src/lib';
2
+
3
+ export declare const render: Render;
4
+ //# sourceMappingURL=render.d.ts.map
package/render.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './render/index'
package/render.js ADDED
@@ -0,0 +1,9 @@
1
+ /*! Copyright 2025 Adobe
2
+ All Rights Reserved. */
3
+ (function(a,t){try{if(typeof document<"u"){const r=document.createElement("style"),o=t.styleId;for(const e in t.attributes)r.setAttribute(e,t.attributes[e]);r.setAttribute("data-dropin",o),r.appendChild(document.createTextNode(a));const i=document.querySelector('style[data-dropin="sdk"]');if(i)i.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)}})(`.dropin-product-item-card__skeleton{gap:var(--spacing-small)}.dropin-product-item-card__skeleton__image{height:375px}.dropin-product-item-card__skeleton__content{grid-column:1/-1}.dropin-product-item-card{display:grid;position:relative;grid-auto-flow:row;background:var(--color-neutral-50);border:1px solid var(--color-neutral-400);color:var(--color-neutral-800);font:var(--type-body-1-default-font);letter-spacing:var(--type-body-1-default-letter-spacing);margin:var(--spacing-small);width:300px}.dropin-product-item-card__image-container{overflow:hidden;width:100%;height:auto}.dropin-product-item-card__image img{width:100%;max-height:375px}.dropin-product-item-card__content{display:grid;grid-template-columns:1fr 1fr;padding:var(--spacing-small);gap:var(--spacing-xxsmall);align-items:center;color:var(--color-neutral-800)}.dropin-product-item-card__title,.dropin-product-item-card__sku,.dropin-product-item-card__price,.dropin-product-item-card__swatches,.dropin-product-item-card__action{grid-column:1/3}.dropin-product-item-card__title{font:var(--type-body-1-strong-font);letter-spacing:var(--type-body-1-strong-letter-spacing)}.dropin-product-item-card__sku,.dropin-product-item-card__price{font:var(--type-body-1-default-font);letter-spacing:var(--type-body-1-default-letter-spacing)}.dropin-product-item-card__swatches{margin-top:var(--spacing-xsmall)}.dropin-product-item-card__action{margin-top:var(--spacing-xsmall);width:100%}
4
+ .plp-product-list,.plp-product-list__container{display:flex;flex-direction:column;width:100%}.plp-product-list__grid{display:grid;grid-template-columns:1fr 1fr;margin-top:var(--spacing-small)}.plp-product-list__grid .dropin-product-item-card{text-align:left;border:1px solid transparent;width:200px}.plp-product-list__grid .dropin-product-item-card:hover{border:1px solid var(--color-neutral-400);box-shadow:0 0 var(--spacing-xsmall) 0 #a9a9a9;padding:none}.plp-product-list__grid .dropin-product-item-card a:hover{text-decoration:none;color:var(--color-neutral-800)}.plp-product-list__header{display:flex;flex-direction:row-reverse;width:100%}.plp-product-list__picker{width:15.625rem;display:inline-block}.plp-product-item__image{min-height:250px}@media only screen and (min-width: 768px){.plp-product-list__grid{grid-template-columns:repeat(3,1fr)}}@media only screen and (min-width: 1366px){.plp-product-list__grid{grid-template-columns:repeat(4,1fr)}}.plp-search-alert-message__wrapper{display:flex;flex-direction:column;justify-content:center;width:100%;min-height:300px}.plp-search-alert-message__content{display:flex;justify-content:center}.plp-facet__bucket .dropin-price-range .dropin-price--small.dropin-price--bold{font:var(--type-body-2-default-font)}.plp-facet__bucket .dropin-radio-button__label:before{margin-right:var(--spacing-xsmall)}.plp-facet-list{display:flex;flex-direction:column;width:100%}.plp-facet-list__selected-filters{display:flex;flex-direction:row;flex-wrap:wrap;row-gap:var(--spacing-xxsmall);padding:0 0 var(--spacing-xxsmall) 0}.plp-facet-list__selected-filters button{padding:0 var(--spacing-xxsmall);margin:0 var(--spacing-xxsmall);border-radius:var(--shape-border-radius-2)}.plp-facet-list__selected-filters .dropin-price-range .dropin-price--small.dropin-price--bold{font:var(--type-button-2-font)}.plp-facet-list__facet-options{text-align:left}.plp-facet-list__facet-options button{padding:0}.plp-facet-list__facet-options .dropin-radio-button{padding:var(--spacing-xxsmall) 0}.plp-facet-list__facet-options--hidden{display:none}.plp-facet-list__show-filters-button{display:flex;margin:0 0 var(--spacing-xsmall) 0}.plp-facet-list .dropin-divider{margin:var(--spacing-xsmall) 0 var(--spacing-xsmall) 0}@media only screen and (min-width: 768px){.plp-facet-list{min-width:13.12rem}.plp-facet-list__facet-options{display:flex;flex-direction:column}.plp-facet-list__show-filters-button{display:none}}
5
+ .product-discovery--search-bar-results{position:absolute;top:100%;left:0;right:0;z-index:1000;display:flex;align-items:flex-start;justify-content:flex-end;padding-top:8px;pointer-events:none}.product-discovery--search-bar-results__popover{position:relative;background:var(--color-neutral-50, #fff);border-radius:var(--shape-border-radius-3, 8px);box-shadow:0 10px 25px -3px #0000001a,0 4px 6px -2px #0000000d,0 0 0 1px #0000000d;width:100%;overflow:hidden;z-index:1001;animation:popoverSlideIn .2s ease-out;pointer-events:auto;display:flex;flex-direction:column;height:100%;min-height:0}@keyframes popoverSlideIn{0%{opacity:0;transform:translateY(-10px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.product-discovery--search-bar-results__grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--spacing-small, 1rem);overflow-y:auto;flex:1;min-height:0}.product-discovery--search-bar-results__grid>*{min-width:0;overflow:hidden}.product-discovery--search-bar-results__view-all-wrapper{flex-shrink:0;border-top:1px solid var(--color-neutral-200, #e5e5e5);background:var(--color-neutral-300)}.product-discovery--search-bar-results__view-all-button{display:flex;justify-content:center;width:100%}.product-discovery--search-bar-results__grid::-webkit-scrollbar{width:8px}.product-discovery--search-bar-results__grid::-webkit-scrollbar-track{background:var(--color-neutral-100, #f5f5f5);border-radius:4px}.product-discovery--search-bar-results__grid::-webkit-scrollbar-thumb{background:var(--color-neutral-400, #d4d4d4);border-radius:4px}.product-discovery--search-bar-results__grid::-webkit-scrollbar-thumb:hover{background:var(--color-neutral-500, #a3a3a3)}@media only screen and (min-width: 768px){.product-discovery--search-bar-results{padding-top:12px}.product-discovery--search-bar-results__popover{max-width:600px}.product-discovery--search-bar-results__grid{gap:var(--spacing-medium, 1.5rem);padding:var(--spacing-medium, 1.5rem)}}@media only screen and (min-width: 1024px){.product-discovery--search-bar-results__popover{max-width:700px}}.product-discovery--product-item{display:flex;flex-flow:row nowrap;gap:var(--spacing-small);width:auto;align-items:normal;cursor:pointer;text-decoration:none;color:inherit}.product-discovery--product-item:hover,.product-discovery--product-item:focus{box-shadow:0 2px 8px #0000001a;text-decoration:none}.product-discovery--product-item__image .dropin-image{width:3rem;height:3rem;max-width:3rem;max-height:3rem;object-fit:cover;border-radius:var(--shape-border-radius-2, 4px)}.product-discovery--product-item__details{display:flex;flex-flow:column nowrap;justify-content:space-between;width:100%}.product-discovery--product-item__details [data-slot=ProductPrice]{text-align:right}
6
+ .product-discovery--search-bar-input__container{display:flex;align-items:center;width:100%}.product-discovery--search-bar-input__form{display:flex;align-items:center}
7
+ .plp-results-info{display:none}@media only screen and (min-width: 768px){.plp-results-info{display:flex;flex-direction:row;gap:var(--spacing-xsmall);width:100%;padding:var(--spacing-xsmall);text-align:center}}`,{styleId:"storefront-product-discovery"});
8
+ import{jsx as o}from"@dropins/tools/preact-jsx-runtime.js";import{Render as c}from"@dropins/tools/lib.js";import{useState as i,useEffect as a}from"@dropins/tools/preact-hooks.js";import{UIProvider as l}from"@dropins/tools/components.js";import{events as u}from"@dropins/tools/event-bus.js";const h={PLP:{Warning:{minQueryLength:"Your search term {SEARCH_PHRASE} has not reached the minimum of {{minQueryLength}} characters.",noResults:"Your search returned no results.",searchError:"An error occurred while searching."},SortDropdown:{title:"Sort by",option:"Sort by: {{selectedOption}}",relevanceLabel:"Most Relevant",positionLabel:"Position",sortAttributeASC:"{{label}}: Low to High",sortAttributeDESC:"{{label}}: High to Low",sortASC:"Price: Low to High",sortDESC:"Price: High to Low",productName:"Product Name",productInStock:"In Stock",productLowStock:"Low Stock"}},Facet:{showMore:"Show more",showLess:"Show less",clearAll:"Clear all"},ResultsInfo:{resultsFor:"Results for",products:"products"},SearchInput:{placeholder:"Search",viewAllButton:"View All"}},S={Search:h},m={default:S},d=({children:r})=>{const[t,n]=i("en_US");return a(()=>{const e=u.on("locale",s=>{n(s)},{eager:!0});return()=>{e==null||e.off()}},[]),o(l,{lang:t,langDefinitions:m,children:r})},A=new c(o(d,{}));export{A as render};
9
+ //# sourceMappingURL=render.js.map