@nosto/search-js 3.4.1 → 3.6.0

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 (76) hide show
  1. package/dist/AutocompletePageProvider-BoV4iLil.js +29 -0
  2. package/dist/AutocompletePageProvider-DPTHPXyz.cjs +1 -0
  3. package/dist/BaseElement-DgwqyaY8.cjs +1 -0
  4. package/dist/BaseElement-iXMoOyxY.js +23 -0
  5. package/dist/CategoryPageProvider-CkeR1heA.cjs +1 -0
  6. package/dist/CategoryPageProvider-Dzcbnz1W.js +26 -0
  7. package/dist/{InfiniteScrollWithObserver-DfQ4cqvs.js → InfiniteScrollWithObserver-Dh_gZaQ6.js} +1 -1
  8. package/dist/{InfiniteScrollWithObserver-DEmjpb8o.cjs → InfiniteScrollWithObserver-MCgxQ06X.cjs} +1 -1
  9. package/dist/SerpPageProvider-CCPCHjKU.cjs +1 -0
  10. package/dist/SerpPageProvider-Ca6ZoAOq.js +26 -0
  11. package/dist/{baseConfig-CR4INhSV.cjs → baseConfig-0GdMC5Qa.cjs} +1 -1
  12. package/dist/{baseConfig-BG_h7eA6.js → baseConfig-CvAG6x_p.js} +3 -3
  13. package/dist/bindInput-BnKvCky1.cjs +1 -0
  14. package/dist/bindInput-CCx0Fhsg.js +27 -0
  15. package/dist/core/core.cjs.js +1 -1
  16. package/dist/core/core.es.js +1 -1
  17. package/dist/isBot-Lnmft0Z0.js +20 -0
  18. package/dist/isBot-iyBlT_oq.cjs +1 -0
  19. package/dist/preact/autocomplete/autocomplete.cjs.js +1 -1
  20. package/dist/preact/autocomplete/autocomplete.d.ts +1 -0
  21. package/dist/preact/autocomplete/autocomplete.es.js +37 -42
  22. package/dist/preact/autocomplete/src/AutocompleteConfig.d.ts +25 -1
  23. package/dist/preact/autocomplete/src/components/HistoryElement.d.ts +23 -0
  24. package/dist/preact/category/category.cjs.js +1 -1
  25. package/dist/preact/category/category.es.js +2 -23
  26. package/dist/preact/common/common.cjs.js +1 -1
  27. package/dist/preact/common/common.es.js +4 -4
  28. package/dist/preact/common/src/components/BaseElement.d.ts +2 -1
  29. package/dist/preact/common/src/store/store.d.ts +1 -0
  30. package/dist/preact/common/src/store/storeContext.d.ts +1 -0
  31. package/dist/preact/common/src/store/storeExtensions.d.ts +1 -0
  32. package/dist/preact/hooks/hooks.cjs.js +1 -1
  33. package/dist/preact/hooks/hooks.es.js +3 -3
  34. package/dist/preact/inject/inject.cjs.js +1 -0
  35. package/dist/preact/inject/inject.d.ts +3 -0
  36. package/dist/preact/inject/inject.es.js +350 -0
  37. package/dist/preact/inject/src/components/ErrorBoundary.d.ts +8 -0
  38. package/dist/preact/inject/src/config.d.ts +117 -0
  39. package/dist/preact/inject/src/helpers/dom.d.ts +12 -0
  40. package/dist/preact/inject/src/init/autocomplete/AutocompleteContext.d.ts +12 -0
  41. package/dist/preact/inject/src/init/autocomplete/components/AutocompleteDropdown.d.ts +14 -0
  42. package/dist/preact/inject/src/init/autocomplete/components/AutocompleteHistory.d.ts +16 -0
  43. package/dist/preact/inject/src/init/autocomplete/components/createComponent.d.ts +13 -0
  44. package/dist/preact/inject/src/init/autocomplete/events/onClick.d.ts +2 -0
  45. package/dist/preact/inject/src/init/autocomplete/events/onFocus.d.ts +2 -0
  46. package/dist/preact/inject/src/init/autocomplete/events/onInput.d.ts +2 -0
  47. package/dist/preact/inject/src/init/autocomplete/events/onKeyDown.d.ts +5 -0
  48. package/dist/preact/inject/src/init/autocomplete/events/onSubmit.d.ts +2 -0
  49. package/dist/preact/inject/src/init/injectAutocomplete.d.ts +15 -0
  50. package/dist/preact/inject/src/init/injectCategory.d.ts +3 -0
  51. package/dist/preact/inject/src/init/injectComponent.d.ts +9 -0
  52. package/dist/preact/inject/src/init/injectSerp.d.ts +3 -0
  53. package/dist/preact/inject/src/init.d.ts +2 -0
  54. package/dist/preact/inject/src/resolveCssSelector.d.ts +8 -0
  55. package/dist/preact/inject/src/wait.d.ts +32 -0
  56. package/dist/preact/legacy/legacy.cjs.js +1 -1
  57. package/dist/preact/legacy/legacy.es.js +3 -3
  58. package/dist/preact/serp/serp.cjs.js +1 -1
  59. package/dist/preact/serp/serp.es.js +15 -34
  60. package/dist/search-DTqo1D6Y.cjs +1 -0
  61. package/dist/search-sC5QgJmw.js +170 -0
  62. package/dist/{useActions-BOhorGOy.js → useActions-Cd7V2qfb.js} +51 -42
  63. package/dist/useActions-yB4RkNMW.cjs +1 -0
  64. package/dist/{useLoadMore-D0TMnfNk.cjs → useLoadMore-DMhtg639.cjs} +1 -1
  65. package/dist/{useLoadMore-DGGR76Vv.js → useLoadMore-vgH5ApBL.js} +2 -2
  66. package/dist/utils/src/debounce.d.ts +1 -0
  67. package/dist/utils/utils.cjs.js +1 -1
  68. package/dist/utils/utils.es.js +18 -39
  69. package/package.json +21 -15
  70. package/dist/BaseElement-Ds4INJSy.cjs +0 -1
  71. package/dist/BaseElement-fZSwbg09.js +0 -17
  72. package/dist/isBot-CLCqH-df.cjs +0 -1
  73. package/dist/isBot-DfEzHKzJ.js +0 -20
  74. package/dist/search-DTLQih9k.cjs +0 -1
  75. package/dist/search-Iwwxc0Yj.js +0 -162
  76. package/dist/useActions-CDUotElR.cjs +0 -1
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("../../AutocompletePageProvider-DPTHPXyz.cjs"),L=require("../../CategoryPageProvider-CkeR1heA.cjs"),m=require("../../useActions-yB4RkNMW.cjs"),x=require("../../SerpPageProvider-CCPCHjKU.cjs"),u=require("../../jsxRuntime.module-B3sGoTIU.cjs"),A=require("../../bindInput-BnKvCky1.cjs"),P=require("../../unique-BXXNictB.cjs"),g=require("preact"),b=require("../../logger-Boh_C6Bz.cjs"),O=require("preact/hooks"),B=require("../../index.es-Dp6Iaxz3.cjs"),y=require("../../search-DTqo1D6Y.cjs");function F(e){let t;return n=>{t&&clearTimeout(t),t=setTimeout(n,e)}}function p({children:e}){const[t]=O.useErrorBoundary();return t&&b.logger.error("Error caught in ErrorBoundary",t),u.u(g.Fragment,{children:e})}function C(e,t){return(typeof e=="string"?Array.from(document.querySelectorAll(e)):[e]).filter(o=>!0)}function H(e,t){let n=[];return C(e).forEach(o=>{const r=o.parentNode;r!==document&&r instanceof Element&&(n.push(r),n=n.concat(H(r)))}),n.filter(o=>t===void 0)}function I([e,t],n){const o=r=>{const s=r.target;s instanceof HTMLElement&&e&&s!==e&&s!==t&&!H(s).includes(e)&&n()};return document.addEventListener("click",o),{destroy:()=>{document.removeEventListener("click",o)}}}function T(e,t){e.tabIndex=0,e.addEventListener("blur",t)}function E(e){return typeof e=="string"?{selector:e,position:"last"}:{position:"last",...e}}function N({selector:e,timeout:t=500}){return new Promise(n=>{const o=C(e);if(o.length>0)return n(o);const r=new MutationObserver(()=>{const i=C(e);i.length>0&&(r.disconnect(),clearTimeout(s),n(i))}),s=setTimeout(()=>{r.disconnect(),b.logger.warn(`Timed out (${t}) while waiting for element ${e}`),n([])},t);r.observe(document.body,{childList:!0,subtree:!0})})}const k=g.createContext({reportProductClick:()=>{},reportKeywordClick:()=>{},handleSubmit:()=>{},highlightedElementIndex:-1});function $(e,t){const{dropdown:n,history:o,store:r,input:s,onNavigateToSearch:i}=e,a=(c,h)=>{n.hide(),o.hide(),c&&(o.add(c),r.updateState({historyItems:o.get()}),h&&B.s(l=>l.recordSearchSubmit(c)),s.value=c)};return{reportProductClick:c=>{a(c.name,!1)},reportKeywordClick:c=>{a(c.keyword,!0)},handleSubmit:c=>{a(c.query,!1),i?.(c)},highlightedElementIndex:t.highlightedIndex()}}function v(e,t,n){t.style.display="none";const o=(()=>{if(e.parentElement&&e.parentElement.classList.contains("nosto-autocomplete-wrapper"))return e.parentElement;const l=document.createElement("div");return l.className="nosto-autocomplete-wrapper",e.parentNode?.insertBefore(l,e.nextSibling),l.appendChild(e),l})(),r=E(n),s=r&&document.querySelector(r.selector);if(s){const l=document.createElement("form");l.className="nosto-dropdown-form",l.appendChild(t),r.position==="first"?s.prepend(l):s.appendChild(l)}else o.appendChild(t);const i={index:-1,onChangeListeners:[]},a=(l,d)=>{const f=l.length;f===0&&(d=-1),i.index=d>=0?d%f:f-1,i.onChangeListeners.forEach(D=>D())},c=()=>{i.index=-1,i.onChangeListeners.forEach(l=>l())},h=()=>i.index;return{element:t,hide:()=>{t.style.display="none",c()},show:()=>{t.style.display="inherit"},isOpen:()=>t.style.display!=="none",goDown:()=>{const l=Array.from(t.getElementsByClassName("ns-autocomplete-element")),d=h();a(l,d+1)},goUp:()=>{const l=Array.from(t.getElementsByClassName("ns-autocomplete-element")),d=h();a(l,d-1)},highlight:a,highlightedIndex:h,submitHighlightedItem:l=>{Array.from(t.querySelectorAll(".ns-autocomplete-element"))[l]?.click()},onHighlightChange:l=>{i.onChangeListeners.push(l)}}}function K(e,t){const n=document.createElement("div");return n.className="nosto-autocomplete-dropdown",{...v(e,n,t),element:n}}const w="nosto:search-js:history";function Q(e,t,n){const o=document.createElement("div");return o.className="nosto-autocomplete-history",{...v(e,o,t),element:o,add:s=>{const a=(y.getLocalStorageItem(w)??[]).filter(c=>c!==s).slice(n?-n:0);a.push(s),y.setLocalStorageItem(w,a)},get:()=>(y.getLocalStorageItem(w)??[]).reverse().filter(i=>!!i)}}async function M(e,{config:t,dropdown:n,history:o,renderHistory:r,store:s}){const{historyEnabled:i,minQueryLength:a}=t;if(e.length<a&&i&&r&&!o.isOpen()){o.show();return}if(e.length<a)return;n.hide();const c=s.getState()?.query?.query;c&&c!==e&&await m.newSearch({config:t,store:s},{query:e}),n.show()}async function U(e,t){const{config:n,renderHistory:o,history:r}=t,{historyEnabled:s,minQueryLength:i}=n;if(!o||e.length>=i||!s||r.isOpen())return;const a=R(t,r);r.onHighlightChange(()=>{a(o,r.element)}),r.show();const c=P.measure("renderHistory");a(o,r.element),c()}async function _(e,{config:t,dropdown:n,history:o,store:r,debouncer:s}){const{minQueryLength:i,historyEnabled:a}=t;if(e.length<i&&!a){n.hide(),o.hide();return}if(e.length<i&&a){n.hide(),o.show();return}o.hide(),s(async()=>{m.newSearch({config:t,store:r},{query:e}),n.show()})}function z(e,t,n){const{config:o,debouncer:r}=n;if(r(()=>{}),e.length>=o.minQueryLength)return q(t,n.dropdown,n.history);if(o.historyEnabled)return q(t,n.history,n.dropdown)}function q(e,t,n){if(!t.isOpen()&&e==="ArrowDown"){t.show(),n.hide();return}if(e==="Escape"&&t.hide(),!!t.isOpen()){if(e==="ArrowDown")t.goDown();else if(e==="ArrowUp")t.goUp();else if(e==="Enter"){const o=t.highlightedIndex();return o>=0&&t.submitHighlightedItem(o),t.hide(),o>=0}}}function G(e,{config:t,dropdown:n,history:o,onNavigateToSearch:r,store:s}){n.hide(),o.hide(),!(e.length<t.minQueryLength)&&(o.add(e),s.updateState({historyItems:o.get()}),r?.({query:e}))}async function J(e,t){const{inputCssSelector:n,timeout:o}=e,r=E(n).selector,s=await N({selector:r,timeout:o});if(s.length===0)throw new Error(`No elements found for selector: ${r}`);s.forEach(i=>{V(i,e,t)})}async function V(e,t,n){const{config:o,dropdownCssSelector:r}=t,s=K(e,r),i=Q(e,r,o.historySize),a={...t,input:e,dropdown:s,history:i,store:n,debouncer:F(o.debounceDelay)};X(a),e.setAttribute("data-nosto-element","search-input"),n.updateState({historyItems:i.get()}),A.disableNativeAutocomplete(e),n.onInit(()=>{W(a)}),A.bindInput(e,{onInput:c=>_(c,a),onFocus:c=>U(c,a),onClick:c=>M(c,a),onSubmit:c=>G(c,a),onKeyDown:(c,h)=>z(c,h,a)}),T(i.element,i.hide),T(s.element,s.hide),I([i.element,e],i.hide),I([s.element,e],s.hide)}function W(e){const{dropdown:t,renderAutocomplete:n}=e;if(!n)return;const o=R(e,t);t.onHighlightChange(()=>{o(n,t.element)});const r=P.measure("renderAutocomplete");o(n,t.element),r()}async function X(e){const{input:t,renderSpeechToText:n,config:o,store:r}=e;if(!n)return;const s="ns-autocomplete-voice-position";if(!!t.parentElement?.querySelector(`.${s}`))return;const a=document.createElement("div");a.className=s,t.insertAdjacentElement("afterend",a);const c=await n();g.render(u.u(p,{children:u.u(S.AutocompletePageProvider,{config:o,store:r,children:c})}),a)}function R(e,t){const{config:n,store:o}=e,r=$(e,t);return t.onHighlightChange(()=>{r.highlightedElementIndex=t.highlightedIndex()}),(s,i)=>g.render(u.u(p,{children:u.u(S.AutocompletePageProvider,{config:n,store:o,children:u.u(k,{value:r,children:s()})})}),i)}async function j({cssSelector:e,timeout:t,renderComponent:n}){const o=E(e).selector,r=await N({selector:o,timeout:t??100});if(r.length===0)throw new Error(`No elements found for selector: ${o}`);r.length>1&&b.logger.warn(`Multiple (${r.length}) elements found for selector: ${o}`),g.render(n(),r[0])}async function Y(e,t){const{render:n}=e,o=await n();j({...e,renderComponent:()=>u.u(p,{children:u.u(L.CategoryPageProvider,{store:t,config:e.config,children:o})})})}async function Z(e,t){const{render:n}=e,o=await n();j({...e,renderComponent:()=>u.u(p,{children:u.u(x.SearchPageProvider,{store:t,config:e.config,children:o})})})}async function ee(e){e.autocomplete&&await J({...e.autocomplete,config:S.makeAutocompleteConfig(e.autocomplete.config)},m.createStore({query:e.autocomplete.query})),e.category&&await Y({...e.category,config:L.makeCategoryConfig(e.category.config)},m.createStore()),e.serp&&await Z({...e.serp,config:x.makeSerpConfig(e.serp.config)},m.createStore())}exports.AutocompleteContext=k;exports.init=ee;
@@ -0,0 +1,3 @@
1
+ /** @module preact/inject */
2
+ export * from './src/init';
3
+ export { AutocompleteContext } from './src/init/autocomplete/AutocompleteContext';
@@ -0,0 +1,350 @@
1
+ import { A as T, m as R } from "../../AutocompletePageProvider-BoV4iLil.js";
2
+ import { C as B, m as F } from "../../CategoryPageProvider-Dzcbnz1W.js";
3
+ import { n as L, c as f } from "../../useActions-Cd7V2qfb.js";
4
+ import { S as O, m as $ } from "../../SerpPageProvider-Ca6ZoAOq.js";
5
+ import { u as d } from "../../jsxRuntime.module-Bzuv3cXw.js";
6
+ import { d as j, b as v } from "../../bindInput-CCx0Fhsg.js";
7
+ import { a as x } from "../../unique-Cv2g464w.js";
8
+ import { Fragment as K, createContext as Q, render as w } from "preact";
9
+ import { l as C } from "../../logger-_fg_Za9y.js";
10
+ import { useErrorBoundary as U } from "preact/hooks";
11
+ import { s as M } from "../../index.es-XNBESE3P.js";
12
+ import { g as b, a as z } from "../../search-sC5QgJmw.js";
13
+ function G(e) {
14
+ let t;
15
+ return (n) => {
16
+ t && clearTimeout(t), t = setTimeout(n, e);
17
+ };
18
+ }
19
+ function h({ children: e }) {
20
+ const [t] = U();
21
+ return t && C.error("Error caught in ErrorBoundary", t), /* @__PURE__ */ d(K, { children: e });
22
+ }
23
+ function y(e, t) {
24
+ return (typeof e == "string" ? Array.from(document.querySelectorAll(e)) : [e]).filter((o) => !0);
25
+ }
26
+ function H(e, t) {
27
+ let n = [];
28
+ return y(e).forEach((o) => {
29
+ const r = o.parentNode;
30
+ r !== document && r instanceof Element && (n.push(r), n = n.concat(H(r)));
31
+ }), n.filter((o) => t === void 0);
32
+ }
33
+ function E([e, t], n) {
34
+ const o = (r) => {
35
+ const s = r.target;
36
+ s instanceof HTMLElement && e && s !== e && s !== t && !H(s).includes(e) && n();
37
+ };
38
+ return document.addEventListener("click", o), {
39
+ destroy: () => {
40
+ document.removeEventListener("click", o);
41
+ }
42
+ };
43
+ }
44
+ function A(e, t) {
45
+ e.tabIndex = 0, e.addEventListener("blur", t);
46
+ }
47
+ function S(e) {
48
+ return typeof e == "string" ? {
49
+ selector: e,
50
+ position: "last"
51
+ } : {
52
+ position: "last",
53
+ ...e
54
+ };
55
+ }
56
+ function N({ selector: e, timeout: t = 500 }) {
57
+ return new Promise((n) => {
58
+ const o = y(e);
59
+ if (o.length > 0)
60
+ return n(o);
61
+ const r = new MutationObserver(() => {
62
+ const i = y(e);
63
+ i.length > 0 && (r.disconnect(), clearTimeout(s), n(i));
64
+ }), s = setTimeout(() => {
65
+ r.disconnect(), C.warn(`Timed out (${t}) while waiting for element ${e}`), n([]);
66
+ }, t);
67
+ r.observe(document.body, {
68
+ childList: !0,
69
+ subtree: !0
70
+ });
71
+ });
72
+ }
73
+ const J = Q({
74
+ reportProductClick: () => {
75
+ },
76
+ reportKeywordClick: () => {
77
+ },
78
+ handleSubmit: () => {
79
+ },
80
+ highlightedElementIndex: -1
81
+ });
82
+ function V(e, t) {
83
+ const { dropdown: n, history: o, store: r, input: s, onNavigateToSearch: i } = e, a = (c, u) => {
84
+ n.hide(), o.hide(), c && (o.add(c), r.updateState({
85
+ historyItems: o.get()
86
+ }), u && M((l) => l.recordSearchSubmit(c)), s.value = c);
87
+ };
88
+ return {
89
+ reportProductClick: (c) => {
90
+ a(c.name, !1);
91
+ },
92
+ reportKeywordClick: (c) => {
93
+ a(c.keyword, !0);
94
+ },
95
+ handleSubmit: (c) => {
96
+ a(c.query, !1), i?.(c);
97
+ },
98
+ highlightedElementIndex: t.highlightedIndex()
99
+ };
100
+ }
101
+ function k(e, t, n) {
102
+ t.style.display = "none";
103
+ const o = (() => {
104
+ if (e.parentElement && e.parentElement.classList.contains("nosto-autocomplete-wrapper"))
105
+ return e.parentElement;
106
+ const l = document.createElement("div");
107
+ return l.className = "nosto-autocomplete-wrapper", e.parentNode?.insertBefore(l, e.nextSibling), l.appendChild(e), l;
108
+ })(), r = S(n), s = r && document.querySelector(r.selector);
109
+ if (s) {
110
+ const l = document.createElement("form");
111
+ l.className = "nosto-dropdown-form", l.appendChild(t), r.position === "first" ? s.prepend(l) : s.appendChild(l);
112
+ } else
113
+ o.appendChild(t);
114
+ const i = {
115
+ index: -1,
116
+ onChangeListeners: []
117
+ }, a = (l, m) => {
118
+ const p = l.length;
119
+ p === 0 && (m = -1), i.index = m >= 0 ? m % p : p - 1, i.onChangeListeners.forEach((D) => D());
120
+ }, c = () => {
121
+ i.index = -1, i.onChangeListeners.forEach((l) => l());
122
+ }, u = () => i.index;
123
+ return {
124
+ element: t,
125
+ hide: () => {
126
+ t.style.display = "none", c();
127
+ },
128
+ show: () => {
129
+ t.style.display = "inherit";
130
+ },
131
+ isOpen: () => t.style.display !== "none",
132
+ goDown: () => {
133
+ const l = Array.from(t.getElementsByClassName("ns-autocomplete-element")), m = u();
134
+ a(l, m + 1);
135
+ },
136
+ goUp: () => {
137
+ const l = Array.from(t.getElementsByClassName("ns-autocomplete-element")), m = u();
138
+ a(l, m - 1);
139
+ },
140
+ highlight: a,
141
+ highlightedIndex: u,
142
+ submitHighlightedItem: (l) => {
143
+ Array.from(t.querySelectorAll(".ns-autocomplete-element"))[l]?.click();
144
+ },
145
+ onHighlightChange: (l) => {
146
+ i.onChangeListeners.push(l);
147
+ }
148
+ };
149
+ }
150
+ function W(e, t) {
151
+ const n = document.createElement("div");
152
+ return n.className = "nosto-autocomplete-dropdown", {
153
+ ...k(e, n, t),
154
+ element: n
155
+ };
156
+ }
157
+ const g = "nosto:search-js:history";
158
+ function X(e, t, n) {
159
+ const o = document.createElement("div");
160
+ return o.className = "nosto-autocomplete-history", {
161
+ ...k(e, o, t),
162
+ element: o,
163
+ add: (s) => {
164
+ const a = (b(g) ?? []).filter((c) => c !== s).slice(n ? -n : 0);
165
+ a.push(s), z(g, a);
166
+ },
167
+ get: () => (b(g) ?? []).reverse().filter((i) => !!i)
168
+ };
169
+ }
170
+ async function Y(e, { config: t, dropdown: n, history: o, renderHistory: r, store: s }) {
171
+ const { historyEnabled: i, minQueryLength: a } = t;
172
+ if (e.length < a && i && r && !o.isOpen()) {
173
+ o.show();
174
+ return;
175
+ }
176
+ if (e.length < a)
177
+ return;
178
+ n.hide();
179
+ const c = s.getState()?.query?.query;
180
+ c && c !== e && await L({ config: t, store: s }, { query: e }), n.show();
181
+ }
182
+ async function Z(e, t) {
183
+ const { config: n, renderHistory: o, history: r } = t, { historyEnabled: s, minQueryLength: i } = n;
184
+ if (!o || e.length >= i || !s || r.isOpen())
185
+ return;
186
+ const a = P(t, r);
187
+ r.onHighlightChange(() => {
188
+ a(o, r.element);
189
+ }), r.show();
190
+ const c = x("renderHistory");
191
+ a(o, r.element), c();
192
+ }
193
+ async function _(e, { config: t, dropdown: n, history: o, store: r, debouncer: s }) {
194
+ const { minQueryLength: i, historyEnabled: a } = t;
195
+ if (e.length < i && !a) {
196
+ n.hide(), o.hide();
197
+ return;
198
+ }
199
+ if (e.length < i && a) {
200
+ n.hide(), o.show();
201
+ return;
202
+ }
203
+ o.hide(), s(async () => {
204
+ L({ config: t, store: r }, { query: e }), n.show();
205
+ });
206
+ }
207
+ function ee(e, t, n) {
208
+ const { config: o, debouncer: r } = n;
209
+ if (r(() => {
210
+ }), e.length >= o.minQueryLength)
211
+ return I(t, n.dropdown, n.history);
212
+ if (o.historyEnabled)
213
+ return I(t, n.history, n.dropdown);
214
+ }
215
+ function I(e, t, n) {
216
+ if (!t.isOpen() && e === "ArrowDown") {
217
+ t.show(), n.hide();
218
+ return;
219
+ }
220
+ if (e === "Escape" && t.hide(), !!t.isOpen()) {
221
+ if (e === "ArrowDown")
222
+ t.goDown();
223
+ else if (e === "ArrowUp")
224
+ t.goUp();
225
+ else if (e === "Enter") {
226
+ const o = t.highlightedIndex();
227
+ return o >= 0 && t.submitHighlightedItem(o), t.hide(), o >= 0;
228
+ }
229
+ }
230
+ }
231
+ function te(e, { config: t, dropdown: n, history: o, onNavigateToSearch: r, store: s }) {
232
+ n.hide(), o.hide(), !(e.length < t.minQueryLength) && (o.add(e), s.updateState({
233
+ historyItems: o.get()
234
+ }), r?.({
235
+ query: e
236
+ }));
237
+ }
238
+ async function ne(e, t) {
239
+ const { inputCssSelector: n, timeout: o } = e, r = S(n).selector, s = await N({
240
+ selector: r,
241
+ timeout: o
242
+ });
243
+ if (s.length === 0)
244
+ throw new Error(`No elements found for selector: ${r}`);
245
+ s.forEach((i) => {
246
+ oe(i, e, t);
247
+ });
248
+ }
249
+ async function oe(e, t, n) {
250
+ const { config: o, dropdownCssSelector: r } = t, s = W(e, r), i = X(e, r, o.historySize), a = {
251
+ ...t,
252
+ input: e,
253
+ dropdown: s,
254
+ history: i,
255
+ store: n,
256
+ debouncer: G(o.debounceDelay)
257
+ };
258
+ se(a), e.setAttribute("data-nosto-element", "search-input"), n.updateState({
259
+ historyItems: i.get()
260
+ }), j(e), n.onInit(() => {
261
+ re(a);
262
+ }), v(e, {
263
+ onInput: (c) => _(c, a),
264
+ onFocus: (c) => Z(c, a),
265
+ onClick: (c) => Y(c, a),
266
+ onSubmit: (c) => te(c, a),
267
+ onKeyDown: (c, u) => ee(c, u, a)
268
+ }), A(i.element, i.hide), A(s.element, s.hide), E([i.element, e], i.hide), E([s.element, e], s.hide);
269
+ }
270
+ function re(e) {
271
+ const { dropdown: t, renderAutocomplete: n } = e;
272
+ if (!n)
273
+ return;
274
+ const o = P(e, t);
275
+ t.onHighlightChange(() => {
276
+ o(n, t.element);
277
+ });
278
+ const r = x("renderAutocomplete");
279
+ o(n, t.element), r();
280
+ }
281
+ async function se(e) {
282
+ const { input: t, renderSpeechToText: n, config: o, store: r } = e;
283
+ if (!n) return;
284
+ const s = "ns-autocomplete-voice-position";
285
+ if (!!t.parentElement?.querySelector(`.${s}`)) return;
286
+ const a = document.createElement("div");
287
+ a.className = s, t.insertAdjacentElement("afterend", a);
288
+ const c = await n();
289
+ w(
290
+ /* @__PURE__ */ d(h, { children: /* @__PURE__ */ d(T, { config: o, store: r, children: c }) }),
291
+ a
292
+ );
293
+ }
294
+ function P(e, t) {
295
+ const { config: n, store: o } = e, r = V(e, t);
296
+ return t.onHighlightChange(() => {
297
+ r.highlightedElementIndex = t.highlightedIndex();
298
+ }), (s, i) => w(
299
+ /* @__PURE__ */ d(h, { children: /* @__PURE__ */ d(T, { config: n, store: o, children: /* @__PURE__ */ d(J, { value: r, children: s() }) }) }),
300
+ i
301
+ );
302
+ }
303
+ async function q({ cssSelector: e, timeout: t, renderComponent: n }) {
304
+ const o = S(e).selector, r = await N({
305
+ selector: o,
306
+ timeout: t ?? 100
307
+ });
308
+ if (r.length === 0)
309
+ throw new Error(`No elements found for selector: ${o}`);
310
+ r.length > 1 && C.warn(`Multiple (${r.length}) elements found for selector: ${o}`), w(n(), r[0]);
311
+ }
312
+ async function ie(e, t) {
313
+ const { render: n } = e, o = await n();
314
+ q({
315
+ ...e,
316
+ renderComponent: () => /* @__PURE__ */ d(h, { children: /* @__PURE__ */ d(B, { store: t, config: e.config, children: o }) })
317
+ });
318
+ }
319
+ async function ce(e, t) {
320
+ const { render: n } = e, o = await n();
321
+ q({
322
+ ...e,
323
+ renderComponent: () => /* @__PURE__ */ d(h, { children: /* @__PURE__ */ d(O, { store: t, config: e.config, children: o }) })
324
+ });
325
+ }
326
+ async function Se(e) {
327
+ e.autocomplete && await ne(
328
+ {
329
+ ...e.autocomplete,
330
+ config: R(e.autocomplete.config)
331
+ },
332
+ f({ query: e.autocomplete.query })
333
+ ), e.category && await ie(
334
+ {
335
+ ...e.category,
336
+ config: F(e.category.config)
337
+ },
338
+ f()
339
+ ), e.serp && await ce(
340
+ {
341
+ ...e.serp,
342
+ config: $(e.serp.config)
343
+ },
344
+ f()
345
+ );
346
+ }
347
+ export {
348
+ J as AutocompleteContext,
349
+ Se as init
350
+ };
@@ -0,0 +1,8 @@
1
+ import { ComponentChildren } from 'preact';
2
+ /**
3
+ * Error boundary component to log UI level errors
4
+ * @group Components
5
+ */
6
+ export default function ErrorBoundary({ children }: {
7
+ children: ComponentChildren;
8
+ }): import("preact").JSX.Element;
@@ -0,0 +1,117 @@
1
+ import { SearchQuery } from '@nosto/nosto-js/client';
2
+ import { AutocompleteConfig, PublicAutocompleteConfig } from '../../autocomplete/src/AutocompleteConfig';
3
+ import { CategoryConfig, PublicCategoryConfig } from '../../category/src/CategoryConfig';
4
+ import { PublicSerpConfig, SerpConfig } from '../../serp/src/SerpConfig';
5
+ import { VNode } from 'preact';
6
+ import { CssSelector } from './resolveCssSelector';
7
+ export type PublicAutocompleteInjectConfig = {
8
+ /**
9
+ * Configuration passthrough.
10
+ */
11
+ config: PublicAutocompleteConfig;
12
+ /**
13
+ * Query to be used for autocomplete.
14
+ */
15
+ query?: SearchQuery;
16
+ /**
17
+ * Maximum time (in milliseconds) to wait for the DOM to be available.
18
+ * If a selector is unable to find any elements after the timeout, an error will be thrown.
19
+ * @default 100
20
+ */
21
+ timeout?: number;
22
+ /**
23
+ * CSS selector for the form element to bind search events like form submit.
24
+ */
25
+ formCssSelector: CssSelector;
26
+ /**
27
+ * CSS selector for each input element to bind search events like input change and form submit.
28
+ */
29
+ inputCssSelector: CssSelector;
30
+ /**
31
+ * CSS selector for autocomplete dropdown render.
32
+ * Leave undefined for default use (After input element)
33
+ */
34
+ dropdownCssSelector: CssSelector;
35
+ /**
36
+ * Render function for autocomplete component.
37
+ */
38
+ renderAutocomplete?: () => VNode | Promise<VNode>;
39
+ /**
40
+ * Render function for autocomplete history component.
41
+ */
42
+ renderHistory?: () => VNode | Promise<VNode>;
43
+ /**
44
+ * Render function for speech to text component.
45
+ */
46
+ renderSpeechToText?: () => VNode | Promise<VNode>;
47
+ /**
48
+ * If provided, will be called on search submit or "show all products" click.
49
+ */
50
+ onNavigateToSearch?: (query: SearchQuery) => void;
51
+ };
52
+ export type AutocompleteInjectConfig = PublicAutocompleteInjectConfig & {
53
+ config: AutocompleteConfig;
54
+ };
55
+ export type PublicCategoryInjectConfig = {
56
+ /**
57
+ * Configuration passthrough.
58
+ */
59
+ config: PublicCategoryConfig;
60
+ /**
61
+ * Maximum time (in milliseconds) to wait for the DOM to be available.
62
+ * If a selector is unable to find any elements after the timeout, an error will be thrown.
63
+ * @default 100
64
+ */
65
+ timeout?: number;
66
+ /**
67
+ * CSS selector for category content rendering.
68
+ */
69
+ cssSelector: CssSelector;
70
+ /**
71
+ * Render function for category content.
72
+ */
73
+ render: () => VNode | Promise<VNode>;
74
+ };
75
+ export type CategoryInjectConfig = PublicCategoryInjectConfig & {
76
+ config: CategoryConfig;
77
+ };
78
+ export type PublicSerpInjectConfig = {
79
+ /**
80
+ * Configuration passthrough.
81
+ */
82
+ config: PublicSerpConfig;
83
+ /**
84
+ * Maximum time (in milliseconds) to wait for the DOM to be available.
85
+ * If a selector is unable to find any elements after the timeout, an error will be thrown.
86
+ * @default 100
87
+ */
88
+ timeout?: number;
89
+ /**
90
+ * CSS selector for search page rendering.
91
+ */
92
+ cssSelector: CssSelector;
93
+ /**
94
+ * Render function for search page content.
95
+ */
96
+ render: () => VNode | Promise<VNode>;
97
+ };
98
+ export type SerpInjectConfig = PublicSerpInjectConfig & {
99
+ config: SerpConfig;
100
+ };
101
+ export type InitConfig = {
102
+ /**
103
+ * Autocomplete injection config.
104
+ * If present, the autocomplete dropdown will be injected into the page.
105
+ */
106
+ autocomplete?: PublicAutocompleteInjectConfig;
107
+ /**
108
+ * Category injection config.
109
+ * If present, the category page will be injected.
110
+ */
111
+ category?: PublicCategoryInjectConfig;
112
+ /**
113
+ * Serp injection config.
114
+ * If present, the search result page will be injected.
115
+ */
116
+ serp?: PublicSerpInjectConfig;
117
+ };
@@ -0,0 +1,12 @@
1
+ export type DOMTarget = string | Element;
2
+ export declare function findAll<T extends Element>(selector: DOMTarget, filterType?: {
3
+ new (): T;
4
+ }): T[];
5
+ export declare function DOMReady(): Promise<void>;
6
+ export declare function cloneNode<T extends Node>(node: T, deep: boolean): T;
7
+ export declare function parents(target: DOMTarget, selector?: string): Element[];
8
+ export declare function matches(target: DOMTarget, selector: string): boolean;
9
+ export declare function bindClickOutside([element, input]: HTMLElement[], callback: () => void): {
10
+ destroy: () => void;
11
+ };
12
+ export declare function bindBlur(element: HTMLElement, callback: () => void): void;
@@ -0,0 +1,12 @@
1
+ import { SearchKeyword, SearchProduct, SearchQuery } from '@nosto/nosto-js/client';
2
+ import { AutocompleteInjectContext } from '../injectAutocomplete';
3
+ import { AutocompleteDropdown } from './components/AutocompleteDropdown';
4
+ import { AutocompleteHistory } from './components/AutocompleteHistory';
5
+ export type AutocompleteUserContext = {
6
+ reportProductClick: (product: SearchProduct) => void;
7
+ reportKeywordClick: (keyword: SearchKeyword) => void;
8
+ handleSubmit: (query: SearchQuery) => void;
9
+ highlightedElementIndex: number;
10
+ };
11
+ export declare const AutocompleteContext: import('preact').Context<AutocompleteUserContext>;
12
+ export declare function createContextHandle(context: AutocompleteInjectContext, element: AutocompleteDropdown | AutocompleteHistory): AutocompleteUserContext;
@@ -0,0 +1,14 @@
1
+ import { CssSelector } from '../../../resolveCssSelector';
2
+ export type AutocompleteDropdown = ReturnType<typeof createDropdownComponent>;
3
+ export declare function createDropdownComponent(input: HTMLInputElement, dropdownSelector: CssSelector): {
4
+ element: HTMLDivElement;
5
+ hide: () => void;
6
+ show: () => void;
7
+ isOpen: () => boolean;
8
+ goDown: () => void;
9
+ goUp: () => void;
10
+ highlight: (elements: Element[], highlightIndex: number) => void;
11
+ highlightedIndex: () => number;
12
+ submitHighlightedItem: (highlightedIndex: number) => void;
13
+ onHighlightChange: (callback: () => void) => void;
14
+ };
@@ -0,0 +1,16 @@
1
+ import { CssSelector } from '../../../resolveCssSelector';
2
+ export type AutocompleteHistory = ReturnType<typeof createHistoryComponent>;
3
+ export declare function createHistoryComponent(input: HTMLInputElement, dropdownSelector: CssSelector, historySize: number): {
4
+ element: HTMLDivElement;
5
+ add: (value: string) => void;
6
+ get: () => string[];
7
+ hide: () => void;
8
+ show: () => void;
9
+ isOpen: () => boolean;
10
+ goDown: () => void;
11
+ goUp: () => void;
12
+ highlight: (elements: Element[], highlightIndex: number) => void;
13
+ highlightedIndex: () => number;
14
+ submitHighlightedItem: (highlightedIndex: number) => void;
15
+ onHighlightChange: (callback: () => void) => void;
16
+ };
@@ -0,0 +1,13 @@
1
+ import { CssSelector } from '../../../resolveCssSelector';
2
+ export declare function createComponent(input: HTMLInputElement, dropdown: HTMLDivElement, dropdownSelector: CssSelector): {
3
+ element: HTMLDivElement;
4
+ hide: () => void;
5
+ show: () => void;
6
+ isOpen: () => boolean;
7
+ goDown: () => void;
8
+ goUp: () => void;
9
+ highlight: (elements: Element[], highlightIndex: number) => void;
10
+ highlightedIndex: () => number;
11
+ submitHighlightedItem: (highlightedIndex: number) => void;
12
+ onHighlightChange: (callback: () => void) => void;
13
+ };
@@ -0,0 +1,2 @@
1
+ import { AutocompleteInjectContext } from '../../injectAutocomplete';
2
+ export declare function onClick(value: string, { config, dropdown, history, renderHistory, store }: AutocompleteInjectContext): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import { AutocompleteInjectContext } from '../../injectAutocomplete';
2
+ export declare function onFocus(value: string, context: AutocompleteInjectContext): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import { AutocompleteInjectContext } from '../../injectAutocomplete';
2
+ export declare function onInput(value: string, { config, dropdown, history, store, debouncer }: AutocompleteInjectContext): Promise<void>;
@@ -0,0 +1,5 @@
1
+ import { AutocompleteInjectContext } from '../../injectAutocomplete';
2
+ import { AutocompleteDropdown } from '../components/AutocompleteDropdown';
3
+ import { AutocompleteHistory } from '../components/AutocompleteHistory';
4
+ export declare function onKeyDown(value: string, key: string, context: AutocompleteInjectContext): boolean | undefined;
5
+ export declare function elementControls(key: string, activeElement: AutocompleteDropdown | AutocompleteHistory, inactiveElement: AutocompleteDropdown | AutocompleteHistory): boolean | undefined;
@@ -0,0 +1,2 @@
1
+ import { AutocompleteInjectContext } from '../../injectAutocomplete';
2
+ export declare function onSubmit(value: string, { config, dropdown, history, onNavigateToSearch, store }: AutocompleteInjectContext): void;
@@ -0,0 +1,15 @@
1
+ import { Store } from '../../../common/src/store/store';
2
+ import { debounce } from '../../../../utils/src/debounce';
3
+ import { VNode } from 'preact';
4
+ import { AutocompleteInjectConfig } from '../config';
5
+ import { AutocompleteDropdown } from './autocomplete/components/AutocompleteDropdown';
6
+ import { AutocompleteHistory } from './autocomplete/components/AutocompleteHistory';
7
+ export declare function injectAutocomplete(config: AutocompleteInjectConfig, store: Store): Promise<void>;
8
+ export type AutocompleteInjectContext = AutocompleteInjectConfig & {
9
+ input: HTMLInputElement;
10
+ dropdown: AutocompleteDropdown;
11
+ history: AutocompleteHistory;
12
+ store: Store;
13
+ debouncer: ReturnType<typeof debounce>;
14
+ };
15
+ export declare function createUserComponentRenderer(injectContext: AutocompleteInjectContext, element: AutocompleteDropdown | AutocompleteHistory): (renderer: () => VNode | Promise<VNode>, target: HTMLDivElement) => void;
@@ -0,0 +1,3 @@
1
+ import { Store } from '../../../common/src/store/store';
2
+ import { CategoryInjectConfig } from '../config';
3
+ export declare function injectCategory(config: CategoryInjectConfig, store: Store): Promise<void>;
@@ -0,0 +1,9 @@
1
+ import { JSX } from 'preact/jsx-runtime';
2
+ import { CssSelector } from '../resolveCssSelector';
3
+ type Props = {
4
+ cssSelector: CssSelector;
5
+ timeout?: number;
6
+ renderComponent: () => JSX.Element;
7
+ };
8
+ export declare function injectComponent({ cssSelector, timeout, renderComponent }: Props): Promise<void>;
9
+ export {};
@@ -0,0 +1,3 @@
1
+ import { Store } from '../../../common/src/store/store';
2
+ import { SerpInjectConfig } from '../config';
3
+ export declare function injectSerp(config: SerpInjectConfig, store: Store): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import { InitConfig } from './config';
2
+ export declare function init(initConfig: InitConfig): Promise<void>;
@@ -0,0 +1,8 @@
1
+ export type CssSelector = string | {
2
+ selector: string;
3
+ position?: "first" | "last";
4
+ };
5
+ export declare function resolveCssSelector(selector: CssSelector): {
6
+ selector: string;
7
+ position: string;
8
+ };