@pure-ds/core 0.7.1 → 0.7.3

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 (44) hide show
  1. package/.cursorrules +38 -1
  2. package/.github/copilot-instructions.md +32 -0
  3. package/custom-elements.json +77 -46
  4. package/dist/types/public/assets/js/pds-manager.d.ts +1 -1
  5. package/dist/types/public/assets/js/pds-manager.d.ts.map +1 -1
  6. package/dist/types/public/assets/js/pds.d.ts.map +1 -1
  7. package/dist/types/src/js/pds-core/pds-live.d.ts.map +1 -1
  8. package/dist/types/src/js/pds-core/pds-start-helpers.d.ts.map +1 -1
  9. package/package.json +1 -1
  10. package/packages/pds-cli/bin/pds-static.js +13 -2
  11. package/packages/pds-cli/bin/sync-assets.js +34 -0
  12. package/public/assets/js/app.js +1543 -4
  13. package/public/assets/js/app.js.map +7 -0
  14. package/public/assets/js/lit.js +1078 -3
  15. package/public/assets/js/lit.js.map +7 -0
  16. package/public/assets/js/pds-ask.js +239 -9
  17. package/public/assets/js/pds-ask.js.map +7 -0
  18. package/public/assets/js/pds-auto-definer.js +306 -1
  19. package/public/assets/js/pds-autocomplete.js +590 -7
  20. package/public/assets/js/pds-autocomplete.js.map +7 -0
  21. package/public/assets/js/pds-enhancers.js +689 -1
  22. package/public/assets/js/pds-enhancers.js.map +7 -0
  23. package/public/assets/js/pds-manager.js +15914 -3101
  24. package/public/assets/js/pds-manager.js.map +7 -0
  25. package/public/assets/js/pds-toast.js +30 -1
  26. package/public/assets/js/pds-toast.js.map +7 -0
  27. package/public/assets/js/pds.js +1409 -2
  28. package/public/assets/js/pds.js.map +7 -0
  29. package/public/assets/pds/components/pds-scrollrow.js +2 -4
  30. package/public/assets/pds/core/pds-ask.js +239 -9
  31. package/public/assets/pds/core/pds-auto-definer.js +306 -1
  32. package/public/assets/pds/core/pds-autocomplete.js +590 -7
  33. package/public/assets/pds/core/pds-enhancers.js +689 -1
  34. package/public/assets/pds/core/pds-manager.js +15914 -3101
  35. package/public/assets/pds/core/pds-toast.js +30 -1
  36. package/public/assets/pds/core.js +1409 -2
  37. package/public/assets/pds/custom-elements.json +77 -46
  38. package/public/assets/pds/external/lit.js +1078 -3
  39. package/public/assets/pds/pds-css-complete.json +2 -2
  40. package/public/assets/pds/pds.css-data.json +1 -1
  41. package/public/assets/pds/vscode-custom-data.json +5 -13
  42. package/src/js/pds-core/pds-live.js +0 -3
  43. package/src/js/pds-core/pds-start-helpers.js +13 -25
  44. package/src/js/pds.js +0 -4
@@ -1,7 +1,590 @@
1
- function m(o){return new DOMParser().parseFromString(o,"text/html").body.childNodes}function y(o,t=100){let e;return function(...i){let r=()=>{clearTimeout(e),o(...i)};clearTimeout(e),e=setTimeout(r,t)}}function p(o){setTimeout(o,0)}function b(o){try{if(typeof o!="string"||o.indexOf(`
2
- `)!==-1||o.indexOf(" ")!==-1||o.startsWith("#/"))return!1;let t=new URL(o,window.location.origin);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function x(o,t,e){let s=window.screen.width/2-t/2,i=window.screen.height/2-e/2;return window.open(o,"",`toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width=${t}, height=${e}, top=${i}, left=${s}`)}var g={result:"ac-suggestion",item:"ac-itm"},f=class o extends EventTarget{constructor(t,e,s){super(),this.settings={emptyResultsText:"",...s},this.container=t,this.input=e,this.input.setAttribute("autocomplete","off"),this.categories=s.categories||{},this.caches=new Map,p(this.attach.bind(this))}static connect(t,e){let s=t.target;if(!s._autoComplete){if(!e?.categories)throw Error("Missing autocomplete settings");s._autoComplete=new o(s.parentNode,s,e),t.type==="focus"&&setTimeout(()=>{s._autoComplete.focusHandler(t)},100)}return s._autoComplete}on(t,e){return this.input.addEventListener(t,e),this}attach(){this.resultsDiv=document.createElement("div"),this.resultsDiv.title="",this.resultsDiv.classList.add(g.result),this.container.offsetWidth>100&&(this.resultsDiv.style.width=this.container.offsetWidth),this.resultsDiv.addEventListener("mousedown",this.resultClick.bind(this)),this.container.classList.add("ac-container"),this.input.classList.add("ac-input");let t=getComputedStyle(this.input);this.container.style.setProperty("--ac-bg-default",t.backgroundColor),this.container.style.setProperty("--ac-color-default",t.color);let e=getComputedStyle(this.input).accentColor;e!=="auto"&&this.container.style.setProperty("--ac-accent-color",e),(this.container?.shadowRoot??this.container).appendChild(this.resultsDiv),this.controller().clear("attach"),this.on("input",y(this.inputHandler.bind(this),this.settings.throttleInputMs??300)).on("focus",this.focusHandler.bind(this)).on("focusout",this.blurHandler.bind(this)).on("keyup",this.keyUpHandler.bind(this)).on("keydown",this.keyDownHandler.bind(this))}controller(){let t=this.internalController();return typeof this.settings.controller=="function"&&(t=this.settings.controller(this)??t),t}internalController(){return{show:this.show.bind(this),hide:this.hide.bind(this),clear:this.clear.bind(this),empty:()=>{}}}moveResult(t){this.controller().show();let e=this.acItems.length;this.rowIndex=this.rowIndex+t,this.rowIndex<=0?this.rowIndex=0:this.rowIndex>e-1&&(this.rowIndex=0);for(let i of this.acItems)i.classList.remove("selected");let s=this.getSelectedDiv();s?(s.classList.add("selected"),s.scrollIntoView({behavior:"smooth",block:"end",inline:"nearest"})):this.focusHandler({target:this.input})}getSelectedDiv(){return this.resultsDiv.querySelector(`div:nth-child(${this.rowIndex+1})`)}selectResult(t){if(t=t||this.getSelectedDiv(),t){let e=parseInt(t.getAttribute("data-index"));this.resultClicked=!0;let s=this.results[e],i=this.categories[s.category]??{};i.action=i.action??this.setText.bind(this),i.newTab&&(this.tabWindow=x("about:blank"));let r={...s,search:this.input.value};t.classList.add("ac-active"),setTimeout(()=>{this.controller().hide("result-selected"),r.action?r.action(r):(i.action(r),i.newTab&&(r.url?this.tabWindow.location.href=r.url:this.tabWindow.close()));var n=new Event("change",{bubbles:!0});this.input.dispatchEvent(n),this.controller().clear("result-selected");let u=new Event("result-selected");u.detail=r,this.input.dispatchEvent(u)},0)}}setText(t){let e=!1;this.input?(this.input.value=t.text,e=!0):this.container?.autoCompleteInput?(this.container.autoCompleteInput.value=t.text,e=!0):"value"in this.container&&(this.container.value=t.text,e=!0),e&&this.input&&this.input.dispatchEvent(new Event("input",{bubbles:!0})),this.controller().hide("settext")}resultClick(t){this.selectResult(t.target.closest(`.${g.item}`))}blurHandler(){setTimeout(()=>{this.resultClicked||this.controller().clear("blurred"),this.resultClicked=!1},100)}clear(){this.settings.debug||this.resultsDiv&&(this.resultsDiv.innerHTML="",this.controller().hide("clear"),this.cacheTmr&&clearTimeout(this.cacheTmr),this.cacheTmr=setTimeout(()=>{this.caches.clear()},60*1e3*5))}show(){if(!this.resultsDiv.classList.contains("ac-active")){let t=this.getViewBounds();this.resultsDiv.style.position="absolute",t.rect.width>100&&(this.resultsDiv.style.width=`${t.rect.width}px`),this.settings.direction=this.settings.direction??t.suggestedDirection,this.resultsDiv.setAttribute("data-direction",this.settings.direction),this.settings.direction==="up"?(this.resultsDiv.style.top="unset",this.resultsDiv.style.bottom=`${t.rect.height+20}px`,this.rowIndex=this.acItems.length):(this.resultsDiv.style.bottom="unset",this.resultsDiv.style.top=`${t.rect.height}px`,this.rowIndex=-1),this.resultsDiv.style.maxWidth="unset",this.resultsDiv.classList.toggle("ac-active",!0)}}getViewBounds(){let t=this.input.getBoundingClientRect();return{rect:t,suggestedDirection:t.top+t.height+500>window.innerHeight?"up":"down"}}hide(){this.resultsDiv.classList.toggle("ac-active",!1)}empty(){this.resultsDiv.innerHTML=`<div class="ac-empty">${this.settings.emptyResultsText}</div>`,this.controller().show()}inputHandler(t){this.cacheTmr&&clearTimeout(this.cacheTmr);let e={search:t.target.value,categories:this.categories};this.container.classList.add("search-running"),this.getItems(e,t).then(s=>{this.controller().clear("new-results"),this.resultsHandler(s,e),this.container.classList.remove("search-running")})}keyDownHandler(t){switch(t.key){case"Enter":t.stopPropagation(),t.preventDefault();break;case"ArrowDown":p(this.moveResult(1));break;case"ArrowUp":p(this.moveResult(-1));break}}keyUpHandler(t){switch(t.key){case"Escape":this.controller().hide("escape");break;case"Enter":this.getSelectedDiv()&&(this.container.preventEnter=!0,t.stopPropagation(),t.preventDefault(),this.selectResult(),setTimeout(()=>{this.container.preventEnter=!1},10));break;default:break}}focusHandler(t){this.controller().clear("focus");let e=t.target.value;this.suggest(e,t)}suggest(t,e){this.input.focus();let s={suggest:!0,search:t||"",categories:this.categories};this.getItems(s,e).then(i=>{this.input.dispatchEvent(new CustomEvent("show-results",{detail:{results:i}})),this.resultsHandler(i,s)})}sort(t,e){return t.sort((s,i)=>{let r=e.categories[s.category],n=e.categories[i.category],u=typeof r.sortIndex=="function"?r.sortIndex(e):r.sortIndex??0;return(typeof n.sortIndex=="function"?n.sortIndex(e):n.sortIndex??0)>u?1:-1})}resultsHandler(t,e){this.results=t,this.rowIndex=-1;let s=0,i=(r,n)=>`
3
- <div title="${n.tooltip||""}" data-index="${s}" class="${`${g.item} cat-${n.category} ${n.class??""}`.trim()}"${n.style?` style="${n.style}"`:""}>
4
- ${this.handleImageOrIcon(n)}
5
- <span class="text">${this.formatResultItem(n,e,r)}</span>
6
- ${this.settings.hideCategory?"":`<span class="category">${n.category||""}</span>`}
7
- </div>`;t.forEach(r=>{let n=e.categories[r.category]||{};r.element?this.resultsDiv.appendChild(r.element):(r=typeof r=="string"?{text:r}:r,this.resultsDiv.appendChild(m(i(n,r))[0])),s++}),t.length?(this.acItems=this.resultsDiv.querySelectorAll(".ac-itm"),this.controller().show()):e.search.length&&this.controller().empty()}handleImageOrIcon(t){return t.image?`<img src="${t.image}"/>`:typeof this.settings.iconHandler=="function"?this.settings.iconHandler(t):`<svg-icon icon="${t.icon}"></svg-icon>`}formatResultItem(t,e,s){let i=typeof t=="string"?{text:t}:t,r=i.text;return e.search&&(r=r.replace("%search%",e.search),i.description=i.description?.replace("%search%",e.search)),r=this.highlight(r,e.search),i.description&&(r=`<div>${r}</div><small>${i.description}</small>`),s.format&&(r=s.format({item:i,result:r,options:e})),r}highlight(t,e){var s=new RegExp("("+e+")","gi");return t.replace(s,'<span class="txt-hl">$1</span>')}async getItems(t,e){this.aborter&&this.aborter.abort();let s=this.caches.get(t.search);if(s)return s;let i=this.settings.map,r=a=>(typeof a=="string"&&(a={text:a}),a),n=a=>i?a.map(h=>({text:h[i]})):a.map(h=>r(h)),u=a=>(this.settings.max&&this.settings.max>0&&(a.length=this.settings.max),a);return this.aborter=new AbortController,this.aborterSignal=this.aborter.signal,new Promise(a=>{let h=l=>{l=this.sort(l,t),this.settings.cache!==!1&&this.caches.set(t.search,l),a(l)};if(b(this.items)){if(this.settings.minlength>0&&(!t.search||t.search.length<this.settings.minlength)){h([]);return}let l=this.formatSearch(this.items,t);fetch(l).then(c=>{if(c.status===200){c.json().then(d=>{d=n(d),h(u(d.filter(w=>this.isMatch(t,w))))});return}throw Error(`HTTP error ${c.status} - ${l}`)})}else if(Array.isArray(this.items)){let l=!0;this.items=this.items.map(c=>typeof c=="string"?{text:c}:(l=!1,c)),l&&this.container.classList.add("simple"),h(u(n(this.items)))}else if(typeof this.items=="function")t.control=this.container,Promise.resolve(this.items(t,e)).then(c=>{c=c.map(d=>r(d)),c=n(c),h(c)});else return h(Promise.resolve(this.items.apply(this,t)))})}async items(t){let e=[];t.results=[],t.signal=this.aborterSignal;for(var s in t.categories){let i=t.categories[s];if(i.trigger=i.trigger??(()=>!0),t.results=e,i.trigger(t)){let r=[];try{r=await i.getItems(t)}catch(n){console.warn(`Error loading items for omniBox category '${s}'.`,n)}e=e.concat(r.map(n=>(n.category=s,n)))}}return e}formatSearch(t,e){return t.indexOf("%search%")?t.replace("%search%",e.search||""):t+"?"+this.createQueryParam(e)}createQueryParam(t){let e=t.suggest?"&suggest=true":"";return`q=${t.text}${e}`}isMatch(t,e){return e.text?.indexOf("%search%")>=0?!0:t.search?e.text?.toLowerCase().indexOf(t.search.toLowerCase())>=0:t.suggest}static textFilter(t,e){return function(s){if(!t.search)return!0;if(s.hidden)return!1;let r=(e?s[e]:s).match(new RegExp(t.search,"gi"));if(r)return r;if(s.config?.tags)return s.config.tags.some(n=>n.match(new RegExp(t.search,"gi")))}}};export{f as AutoComplete};
1
+ // node_modules/pure-web/src/js/common.js
2
+ function parseHTML(html) {
3
+ return new DOMParser().parseFromString(html, "text/html").body.childNodes;
4
+ }
5
+ function throttle(fn, timeoutMs = 100) {
6
+ let handle;
7
+ return function executedFunction(...args) {
8
+ const fire = () => {
9
+ clearTimeout(handle);
10
+ fn(...args);
11
+ };
12
+ clearTimeout(handle);
13
+ handle = setTimeout(fire, timeoutMs);
14
+ };
15
+ }
16
+ function enQueue(fn) {
17
+ setTimeout(fn, 0);
18
+ }
19
+ function isUrl(str) {
20
+ try {
21
+ if (typeof str !== "string")
22
+ return false;
23
+ if (str.indexOf("\n") !== -1 || str.indexOf(" ") !== -1)
24
+ return false;
25
+ if (str.startsWith("#/"))
26
+ return false;
27
+ const newUrl = new URL(str, window.location.origin);
28
+ return newUrl.protocol === "http:" || newUrl.protocol === "https:";
29
+ } catch {
30
+ return false;
31
+ }
32
+ }
33
+ function openCenteredWindow(url, width, height) {
34
+ const left = window.screen.width / 2 - width / 2;
35
+ const top = window.screen.height / 2 - height / 2;
36
+ return window.open(
37
+ url,
38
+ "",
39
+ `toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width=${width}, height=${height}, top=${top}, left=${left}`
40
+ );
41
+ }
42
+
43
+ // node_modules/pure-web/src/js/autocomplete.js
44
+ var cssClasses = {
45
+ result: "ac-suggestion",
46
+ item: "ac-itm"
47
+ };
48
+ var AutoComplete = class _AutoComplete extends EventTarget {
49
+ constructor(parent, textInput, settings) {
50
+ super();
51
+ this.settings = {
52
+ emptyResultsText: "",
53
+ ...settings
54
+ };
55
+ this.container = parent;
56
+ this.input = textInput;
57
+ this.input.setAttribute("autocomplete", "off");
58
+ this.categories = settings.categories || {};
59
+ this.caches = /* @__PURE__ */ new Map();
60
+ enQueue(this.attach.bind(this));
61
+ }
62
+ /**
63
+ * Connector logic to call on @focus events.
64
+ * Lit example:
65
+ * <input type="search" @focus=${(e) => {AutoComplete.connect(e, this.autoComplete); }} />
66
+ *
67
+ * @param {*} event focus event
68
+ * @param {*} options AutoComplete options
69
+ */
70
+ static connect(event, options) {
71
+ const input = event.target;
72
+ if (!input._autoComplete) {
73
+ if (!options?.categories)
74
+ throw Error("Missing autocomplete settings");
75
+ input._autoComplete = new _AutoComplete(input.parentNode, input, options);
76
+ if (event.type === "focus") {
77
+ setTimeout(() => {
78
+ input._autoComplete.focusHandler(event);
79
+ }, 100);
80
+ }
81
+ }
82
+ return input._autoComplete;
83
+ }
84
+ on(a, b) {
85
+ this.input.addEventListener(a, b);
86
+ return this;
87
+ }
88
+ attach() {
89
+ this.resultsDiv = document.createElement("div");
90
+ this.resultsDiv.title = "";
91
+ this.resultsDiv.classList.add(cssClasses.result);
92
+ if (this.container.offsetWidth > 100)
93
+ this.resultsDiv.style.width = this.container.offsetWidth;
94
+ this.resultsDiv.addEventListener("mousedown", this.resultClick.bind(this));
95
+ this.container.classList.add("ac-container");
96
+ this.input.classList.add("ac-input");
97
+ const inputStyle = getComputedStyle(this.input);
98
+ this.container.style.setProperty(
99
+ "--ac-bg-default",
100
+ inputStyle.backgroundColor
101
+ );
102
+ this.container.style.setProperty("--ac-color-default", inputStyle.color);
103
+ const acc = getComputedStyle(this.input).accentColor;
104
+ if (acc !== "auto")
105
+ this.container.style.setProperty("--ac-accent-color", acc);
106
+ (this.container?.shadowRoot ?? this.container).appendChild(this.resultsDiv);
107
+ this.controller().clear("attach");
108
+ this.on(
109
+ "input",
110
+ throttle(
111
+ this.inputHandler.bind(this),
112
+ this.settings.throttleInputMs ?? 300
113
+ )
114
+ ).on("focus", this.focusHandler.bind(this)).on("focusout", this.blurHandler.bind(this)).on("keyup", this.keyUpHandler.bind(this)).on("keydown", this.keyDownHandler.bind(this));
115
+ }
116
+ controller() {
117
+ let c = this.internalController();
118
+ if (typeof this.settings.controller === "function")
119
+ c = this.settings.controller(this) ?? c;
120
+ return c;
121
+ }
122
+ internalController() {
123
+ return {
124
+ show: this.show.bind(this),
125
+ hide: this.hide.bind(this),
126
+ clear: this.clear.bind(this),
127
+ empty: () => {
128
+ }
129
+ };
130
+ }
131
+ moveResult(add) {
132
+ this.controller().show();
133
+ let length = this.acItems.length;
134
+ this.rowIndex = this.rowIndex + add;
135
+ if (this.rowIndex <= 0) {
136
+ this.rowIndex = 0;
137
+ } else if (this.rowIndex > length - 1) {
138
+ this.rowIndex = 0;
139
+ }
140
+ for (const r of this.acItems) {
141
+ r.classList.remove("selected");
142
+ }
143
+ let div = this.getSelectedDiv();
144
+ if (div) {
145
+ div.classList.add("selected");
146
+ div.scrollIntoView({
147
+ behavior: "smooth",
148
+ block: "end",
149
+ inline: "nearest"
150
+ });
151
+ } else {
152
+ this.focusHandler({
153
+ target: this.input
154
+ });
155
+ }
156
+ }
157
+ getSelectedDiv() {
158
+ return this.resultsDiv.querySelector(`div:nth-child(${this.rowIndex + 1})`);
159
+ }
160
+ // execute action
161
+ selectResult(div) {
162
+ div = div || this.getSelectedDiv();
163
+ if (div) {
164
+ let index = parseInt(div.getAttribute("data-index"));
165
+ this.resultClicked = true;
166
+ let result = this.results[index];
167
+ let handlingCategory = this.categories[result.category] ?? {};
168
+ handlingCategory.action = handlingCategory.action ?? this.setText.bind(this);
169
+ if (handlingCategory.newTab) {
170
+ this.tabWindow = openCenteredWindow("about:blank");
171
+ }
172
+ let options = {
173
+ ...result,
174
+ search: this.input.value
175
+ };
176
+ div.classList.add("ac-active");
177
+ setTimeout(() => {
178
+ this.controller().hide("result-selected");
179
+ if (options.action) {
180
+ options.action(options);
181
+ } else {
182
+ handlingCategory.action(options);
183
+ if (handlingCategory.newTab) {
184
+ if (options.url) {
185
+ this.tabWindow.location.href = options.url;
186
+ } else {
187
+ this.tabWindow.close();
188
+ }
189
+ }
190
+ }
191
+ var event = new Event("change", { bubbles: true });
192
+ this.input.dispatchEvent(event);
193
+ this.controller().clear("result-selected");
194
+ const ev = new Event("result-selected");
195
+ ev.detail = options;
196
+ this.input.dispatchEvent(ev);
197
+ }, 0);
198
+ }
199
+ }
200
+ setText(options) {
201
+ let valueSet = false;
202
+ if (this.input) {
203
+ this.input.value = options.text;
204
+ valueSet = true;
205
+ } else if (this.container?.autoCompleteInput) {
206
+ this.container.autoCompleteInput.value = options.text;
207
+ valueSet = true;
208
+ } else if ("value" in this.container) {
209
+ this.container.value = options.text;
210
+ valueSet = true;
211
+ }
212
+ if (valueSet && this.input) {
213
+ this.input.dispatchEvent(new Event("input", { bubbles: true }));
214
+ }
215
+ this.controller().hide("settext");
216
+ }
217
+ resultClick(event) {
218
+ this.selectResult(event.target.closest(`.${cssClasses.item}`));
219
+ }
220
+ blurHandler() {
221
+ setTimeout(() => {
222
+ if (!this.resultClicked)
223
+ this.controller().clear("blurred");
224
+ this.resultClicked = false;
225
+ }, 100);
226
+ }
227
+ clear() {
228
+ if (this.settings.debug)
229
+ return;
230
+ if (!this.resultsDiv)
231
+ return;
232
+ this.resultsDiv.innerHTML = "";
233
+ this.controller().hide("clear");
234
+ if (this.cacheTmr)
235
+ clearTimeout(this.cacheTmr);
236
+ this.cacheTmr = setTimeout(() => {
237
+ this.caches.clear();
238
+ }, 60 * 1e3 * 5);
239
+ }
240
+ show() {
241
+ if (!this.resultsDiv.classList.contains("ac-active")) {
242
+ const viewBounds = this.getViewBounds();
243
+ this.resultsDiv.style.position = "absolute";
244
+ if (viewBounds.rect.width > 100)
245
+ this.resultsDiv.style.width = `${viewBounds.rect.width}px`;
246
+ this.settings.direction = this.settings.direction ?? viewBounds.suggestedDirection;
247
+ this.resultsDiv.setAttribute("data-direction", this.settings.direction);
248
+ if (this.settings.direction === "up") {
249
+ this.resultsDiv.style.top = "unset";
250
+ this.resultsDiv.style.bottom = `${viewBounds.rect.height + 20}px`;
251
+ this.rowIndex = this.acItems.length;
252
+ } else {
253
+ this.resultsDiv.style.bottom = "unset";
254
+ this.resultsDiv.style.top = `${viewBounds.rect.height}px`;
255
+ this.rowIndex = -1;
256
+ }
257
+ this.resultsDiv.style.maxWidth = "unset";
258
+ this.resultsDiv.classList.toggle("ac-active", true);
259
+ }
260
+ }
261
+ getViewBounds() {
262
+ const rect = this.input.getBoundingClientRect();
263
+ return {
264
+ rect,
265
+ suggestedDirection: rect.top + rect.height + 500 > window.innerHeight ? "up" : "down"
266
+ };
267
+ }
268
+ hide() {
269
+ this.resultsDiv.classList.toggle("ac-active", false);
270
+ }
271
+ empty() {
272
+ this.resultsDiv.innerHTML = `<div class="ac-empty">${this.settings.emptyResultsText}</div>`;
273
+ this.controller().show();
274
+ }
275
+ inputHandler(e) {
276
+ if (this.cacheTmr)
277
+ clearTimeout(this.cacheTmr);
278
+ let options = {
279
+ search: e.target.value,
280
+ categories: this.categories
281
+ };
282
+ this.container.classList.add("search-running");
283
+ this.getItems(options, e).then((r) => {
284
+ this.controller().clear("new-results");
285
+ this.resultsHandler(r, options);
286
+ this.container.classList.remove("search-running");
287
+ });
288
+ }
289
+ keyDownHandler(e) {
290
+ switch (e.key) {
291
+ case "Enter":
292
+ e.stopPropagation();
293
+ e.preventDefault();
294
+ break;
295
+ case "ArrowDown":
296
+ enQueue(this.moveResult(1));
297
+ break;
298
+ case "ArrowUp":
299
+ enQueue(this.moveResult(-1));
300
+ break;
301
+ }
302
+ }
303
+ keyUpHandler(e) {
304
+ switch (e.key) {
305
+ case "Escape":
306
+ this.controller().hide("escape");
307
+ break;
308
+ case "Enter":
309
+ if (this.getSelectedDiv()) {
310
+ this.container.preventEnter = true;
311
+ e.stopPropagation();
312
+ e.preventDefault();
313
+ this.selectResult();
314
+ setTimeout(() => {
315
+ this.container.preventEnter = false;
316
+ }, 10);
317
+ }
318
+ break;
319
+ default:
320
+ break;
321
+ }
322
+ }
323
+ focusHandler(e) {
324
+ this.controller().clear("focus");
325
+ let value = e.target.value;
326
+ this.suggest(value, e);
327
+ }
328
+ /**
329
+ * Shows suggestion box
330
+ * @param {string} value - String to suggest results for
331
+ */
332
+ suggest(value, e) {
333
+ this.input.focus();
334
+ const options = {
335
+ suggest: true,
336
+ search: value || "",
337
+ categories: this.categories
338
+ };
339
+ this.getItems(options, e).then((r) => {
340
+ this.input.dispatchEvent(
341
+ new CustomEvent("show-results", {
342
+ detail: {
343
+ results: r
344
+ }
345
+ })
346
+ );
347
+ this.resultsHandler(r, options);
348
+ });
349
+ }
350
+ // Sort results based on static (integer) or dynamic (function) sortIndex in category.
351
+ sort(r, options) {
352
+ return r.sort((a, b) => {
353
+ const aCat = options.categories[a.category];
354
+ const bCat = options.categories[b.category];
355
+ const aIndex = typeof aCat.sortIndex === "function" ? aCat.sortIndex(options) : aCat.sortIndex ?? 0;
356
+ const bIndex = typeof bCat.sortIndex === "function" ? bCat.sortIndex(options) : bCat.sortIndex ?? 0;
357
+ return bIndex > aIndex ? 1 : -1;
358
+ });
359
+ }
360
+ resultsHandler(r, options) {
361
+ this.results = r;
362
+ this.rowIndex = -1;
363
+ let index = 0;
364
+ const singleItemTemplate = (catHandler, i) => {
365
+ return (
366
+ /*html*/
367
+ `
368
+ <div title="${i.tooltip || ""}" data-index="${index}" class="${`${cssClasses.item} cat-${i.category} ${i.class ?? ""}`.trim()}"${i.style ? ` style="${i.style}"` : ""}>
369
+ ${this.handleImageOrIcon(i)}
370
+ <span class="text">${this.formatResultItem(
371
+ i,
372
+ options,
373
+ catHandler
374
+ )}</span>
375
+ ${!this.settings.hideCategory ? `<span class="category">${i.category || ""}</span>` : ""}
376
+ </div>`
377
+ );
378
+ };
379
+ r.forEach((i) => {
380
+ let catHandler = options.categories[i.category] || {};
381
+ if (i.element) {
382
+ this.resultsDiv.appendChild(i.element);
383
+ } else {
384
+ i = typeof i === "string" ? { text: i } : i;
385
+ this.resultsDiv.appendChild(
386
+ parseHTML(singleItemTemplate(catHandler, i))[0]
387
+ );
388
+ }
389
+ index++;
390
+ });
391
+ if (r.length) {
392
+ this.acItems = this.resultsDiv.querySelectorAll(".ac-itm");
393
+ this.controller().show();
394
+ } else if (options.search.length)
395
+ this.controller().empty();
396
+ }
397
+ handleImageOrIcon(i) {
398
+ if (i.image) {
399
+ return (
400
+ /*html*/
401
+ `<img src="${i.image}"/>`
402
+ );
403
+ }
404
+ if (typeof this.settings.iconHandler === "function")
405
+ return this.settings.iconHandler(i);
406
+ return (
407
+ /*html*/
408
+ `<svg-icon icon="${i.icon}"></svg-icon>`
409
+ );
410
+ }
411
+ formatResultItem(item, options, catHandler) {
412
+ const i = typeof item === "string" ? { text: item } : item;
413
+ let result = i.text;
414
+ if (options.search) {
415
+ result = result.replace("%search%", options.search);
416
+ i.description = i.description?.replace("%search%", options.search);
417
+ }
418
+ result = this.highlight(result, options.search);
419
+ if (i.description) {
420
+ result = `<div>${result}</div><small>${i.description}</small>`;
421
+ }
422
+ if (catHandler.format) {
423
+ result = catHandler.format({
424
+ item: i,
425
+ result,
426
+ options
427
+ });
428
+ }
429
+ return result;
430
+ }
431
+ highlight(str, find) {
432
+ var reg = new RegExp("(" + find + ")", "gi");
433
+ return str.replace(reg, '<span class="txt-hl">$1</span>');
434
+ }
435
+ async getItems(options, e) {
436
+ if (this.aborter) {
437
+ this.aborter.abort();
438
+ }
439
+ let cache = this.caches.get(options.search);
440
+ if (cache)
441
+ return cache;
442
+ const prop = this.settings.map;
443
+ const normalizeItem = (i) => {
444
+ if (typeof i === "string")
445
+ i = { text: i };
446
+ return i;
447
+ };
448
+ const map = (list) => {
449
+ if (!prop) {
450
+ return list.map((i) => {
451
+ return normalizeItem(i);
452
+ });
453
+ }
454
+ return list.map((i) => {
455
+ return { text: i[prop] };
456
+ });
457
+ };
458
+ const max = (list) => {
459
+ if (this.settings.max && this.settings.max > 0) {
460
+ list.length = this.settings.max;
461
+ }
462
+ return list;
463
+ };
464
+ this.aborter = new AbortController();
465
+ this.aborterSignal = this.aborter.signal;
466
+ return new Promise((resolve) => {
467
+ const internalResolve = (data) => {
468
+ data = this.sort(data, options);
469
+ if (this.settings.cache !== false)
470
+ this.caches.set(options.search, data);
471
+ resolve(data);
472
+ };
473
+ if (isUrl(this.items)) {
474
+ if (this.settings.minlength > 0) {
475
+ if (!options.search || options.search.length < this.settings.minlength) {
476
+ internalResolve([]);
477
+ return;
478
+ }
479
+ }
480
+ let url = this.formatSearch(this.items, options);
481
+ fetch(url).then((x) => {
482
+ if (x.status === 200) {
483
+ x.json().then((items) => {
484
+ items = map(items);
485
+ internalResolve(
486
+ max(
487
+ items.filter((i) => {
488
+ return this.isMatch(options, i);
489
+ })
490
+ )
491
+ );
492
+ });
493
+ return;
494
+ }
495
+ throw Error(`HTTP error ${x.status} - ${url}`);
496
+ });
497
+ } else if (Array.isArray(this.items)) {
498
+ let simple = true;
499
+ this.items = this.items.map((i) => {
500
+ if (typeof i === "string") {
501
+ return { text: i };
502
+ }
503
+ simple = false;
504
+ return i;
505
+ });
506
+ if (simple) {
507
+ this.container.classList.add("simple");
508
+ }
509
+ internalResolve(max(map(this.items)));
510
+ } else if (typeof this.items === "function") {
511
+ options.control = this.container;
512
+ let ar = Promise.resolve(this.items(options, e));
513
+ ar.then((ar2) => {
514
+ ar2 = ar2.map((i) => {
515
+ return normalizeItem(i);
516
+ });
517
+ ar2 = map(ar2);
518
+ internalResolve(ar2);
519
+ });
520
+ } else {
521
+ return internalResolve(
522
+ Promise.resolve(this.items.apply(this, options))
523
+ );
524
+ }
525
+ });
526
+ }
527
+ async items(options) {
528
+ let arr = [];
529
+ options.results = [];
530
+ options.signal = this.aborterSignal;
531
+ for (var c in options.categories) {
532
+ let catHandler = options.categories[c];
533
+ catHandler.trigger = catHandler.trigger ?? (() => {
534
+ return true;
535
+ });
536
+ options.results = arr;
537
+ if (catHandler.trigger(options)) {
538
+ let catResults = [];
539
+ try {
540
+ catResults = await catHandler.getItems(options);
541
+ } catch (ex) {
542
+ console.warn(`Error loading items for omniBox category '${c}'.`, ex);
543
+ }
544
+ arr = arr.concat(
545
+ catResults.map((i) => {
546
+ i.category = c;
547
+ return i;
548
+ })
549
+ );
550
+ }
551
+ }
552
+ return arr;
553
+ }
554
+ formatSearch(url, options) {
555
+ if (url.indexOf("%search%")) {
556
+ return url.replace("%search%", options.search || "");
557
+ }
558
+ return url + "?" + this.createQueryParam(options);
559
+ }
560
+ createQueryParam(options) {
561
+ let suggest = options.suggest ? "&suggest=true" : "";
562
+ return `q=${options.text}${suggest}`;
563
+ }
564
+ isMatch(options, i) {
565
+ if (i.text?.indexOf("%search%") >= 0)
566
+ return true;
567
+ return options.search ? i.text?.toLowerCase().indexOf(options.search.toLowerCase()) >= 0 : options.suggest;
568
+ }
569
+ static textFilter(options, propertyName) {
570
+ return function(i) {
571
+ if (!options.search)
572
+ return true;
573
+ if (i.hidden)
574
+ return false;
575
+ const prop = propertyName ? i[propertyName] : i;
576
+ const isMatch = prop.match(new RegExp(options.search, "gi"));
577
+ if (isMatch)
578
+ return isMatch;
579
+ if (i.config?.tags) {
580
+ return i.config.tags.some((tag) => {
581
+ return tag.match(new RegExp(options.search, "gi"));
582
+ });
583
+ }
584
+ };
585
+ }
586
+ };
587
+ export {
588
+ AutoComplete
589
+ };
590
+ //# sourceMappingURL=pds-autocomplete.js.map