@pro6pp/infer-js 0.0.2-beta.0 → 0.0.2-beta.10
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.
- package/README.md +70 -55
- package/dist/index.cjs +189 -0
- package/dist/index.d.mts +57 -3
- package/dist/index.d.ts +57 -3
- package/dist/index.global.js +159 -336
- package/dist/index.mjs +161 -128
- package/package.json +35 -6
package/README.md
CHANGED
|
@@ -1,104 +1,119 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Pro6PP Infer JS SDK
|
|
2
2
|
|
|
3
3
|
The official Vanilla JS SDK for the [Pro6PP Infer API](https://www.pro6pp.com/developer/infer/nl/parameters).
|
|
4
4
|
A library that adds address autocompletion to any HTML input field.
|
|
5
5
|
|
|
6
6
|
## Installation
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
#### Option 1: CDN
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Add this script to your HTML file. It exposes a global `Pro6PP` variable.
|
|
11
11
|
|
|
12
12
|
```html
|
|
13
|
-
|
|
14
|
-
<script src=""></script>
|
|
13
|
+
<script src="https://unpkg.com/@pro6pp/infer-js"></script>
|
|
15
14
|
```
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
#### Option 2: NPM
|
|
18
17
|
|
|
19
|
-
If you are using Webpack
|
|
18
|
+
If you are using a build tool like Webpack or Vite, but not a framework like React.
|
|
20
19
|
|
|
21
20
|
```bash
|
|
22
21
|
npm install @pro6pp/infer-js
|
|
23
22
|
```
|
|
24
23
|
|
|
25
|
-
> **Note:** If you are using React, use [`@pro6pp/infer-react`](
|
|
24
|
+
> **Note:** If you are using React, use [`@pro6pp/infer-react`](https://www.npmjs.com/package/@pro6pp/infer-react) instead.
|
|
25
|
+
|
|
26
|
+
#### Option 3: Direct download
|
|
27
|
+
|
|
28
|
+
You can also [download](https://unpkg.com/@pro6pp/infer-js@latest/dist/index.global.js) the latest `index.global.js` and place it in your project.
|
|
26
29
|
|
|
27
30
|
## Usage
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
#### Option 1: CDN
|
|
30
33
|
|
|
31
34
|
1. Add the script to your page.
|
|
32
35
|
2. Create an input field.
|
|
33
36
|
3. Attach the core logic to that input using `Pro6PP.attach()`.
|
|
34
37
|
|
|
35
38
|
```html
|
|
36
|
-
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
country: 'NL',
|
|
51
|
-
onSelect: function (result) {
|
|
52
|
-
console.log('Selected Address:', result);
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
</script>
|
|
56
|
-
</body>
|
|
57
|
-
</html>
|
|
39
|
+
<label>Address:</label>
|
|
40
|
+
<input id="address-input" type="text" />
|
|
41
|
+
|
|
42
|
+
<!-- Inject the CDN -->
|
|
43
|
+
<script src="https://unpkg.com/@pro6pp/infer-js"></script>
|
|
44
|
+
<script>
|
|
45
|
+
Pro6PP.attach('#address-input', {
|
|
46
|
+
authKey: 'YOUR_AUTH_KEY',
|
|
47
|
+
country: 'NL',
|
|
48
|
+
onSelect: function (result) {
|
|
49
|
+
console.log('Selected Address:', result);
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
</script>
|
|
58
53
|
```
|
|
59
54
|
|
|
60
|
-
|
|
55
|
+
#### Option 2: NPM
|
|
56
|
+
|
|
57
|
+
1. Create an input field.
|
|
58
|
+
2. Import the `attach` function.
|
|
59
|
+
3. Initialize the autocomplete on the input.
|
|
60
|
+
|
|
61
|
+
```html
|
|
62
|
+
<input id="address-input" name="address" />
|
|
63
|
+
```
|
|
61
64
|
|
|
62
65
|
```javascript
|
|
63
66
|
import { attach } from '@pro6pp/infer-js';
|
|
64
67
|
|
|
65
|
-
|
|
66
|
-
const inputElement = document.querySelector('input[name="address"]');
|
|
68
|
+
const inputElement = document.getElementById('address-input');
|
|
67
69
|
|
|
68
70
|
attach(inputElement, {
|
|
69
71
|
authKey: 'YOUR_AUTH_KEY',
|
|
70
72
|
country: 'NL',
|
|
71
73
|
onSelect: (result) => {
|
|
72
|
-
console.log(result);
|
|
74
|
+
console.log('Selected Address:', result);
|
|
73
75
|
},
|
|
74
76
|
});
|
|
75
77
|
```
|
|
76
78
|
|
|
77
|
-
|
|
79
|
+
#### Option 3: Direct download
|
|
78
80
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
HTML created by the SDK:
|
|
81
|
+
1. [Download](https://unpkg.com/@pro6pp/infer-js@latest/dist/index.global.js) the latest `index.global.js`.
|
|
82
|
+
2. Place it in your project and include it directly in your HTML.
|
|
82
83
|
|
|
83
84
|
```html
|
|
84
|
-
<
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
</
|
|
85
|
+
<script src="path/to/index.global.js"></script>
|
|
86
|
+
<script>
|
|
87
|
+
const instance = Pro6PP.attach('#my-input', {
|
|
88
|
+
authKey: 'YOUR_AUTH_KEY',
|
|
89
|
+
country: 'NL',
|
|
90
|
+
});
|
|
91
|
+
</script>
|
|
91
92
|
```
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
## Styling
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
.pro6pp-results {
|
|
97
|
-
background: white;
|
|
98
|
-
border: 1px solid #ccc;
|
|
99
|
-
}
|
|
96
|
+
By default, the SDK injects the necessary CSS for the dropdown. If you want to control the styling with your own styles, set `style: 'none'` in the config:
|
|
100
97
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
```js
|
|
99
|
+
attach(inputElement, {
|
|
100
|
+
authKey: '...',
|
|
101
|
+
country: 'NL',
|
|
102
|
+
style: 'none', // disables default styles
|
|
103
|
+
});
|
|
104
104
|
```
|
|
105
|
+
|
|
106
|
+
You can then target the following classes in your CSS:
|
|
107
|
+
|
|
108
|
+
| Class | Description |
|
|
109
|
+
| :----------------------- | :-------------------------------------------------------- |
|
|
110
|
+
| `.pro6pp-wrapper` | The container element wrapping the input and dropdown. |
|
|
111
|
+
| `.pro6pp-input` | The input element itself. |
|
|
112
|
+
| `.pro6pp-loader` | The loading spinner shown during API requests. |
|
|
113
|
+
| `.pro6pp-dropdown` | The `<ul>` list containing the suggestions. |
|
|
114
|
+
| `.pro6pp-item` | A single suggestion item (`<li>`). |
|
|
115
|
+
| `.pro6pp-item--active` | The currently highlighted item (for keyboard navigation). |
|
|
116
|
+
| `.pro6pp-item__label` | The main text/label of a suggestion. |
|
|
117
|
+
| `.pro6pp-item__subtitle` | The secondary text (e.g., city or result count). |
|
|
118
|
+
| `.pro6pp-item__chevron` | The icon indicating a folder/expandable result. |
|
|
119
|
+
| `.pro6pp-no-results` | The message shown when no suggestions are found. |
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";var g=Object.defineProperty,k=Object.defineProperties,A=Object.getOwnPropertyDescriptor,_=Object.getOwnPropertyDescriptors,B=Object.getOwnPropertyNames,w=Object.getOwnPropertySymbols;var I=Object.prototype.hasOwnProperty,D=Object.prototype.propertyIsEnumerable;var E=(o,t,e)=>t in o?g(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e,c=(o,t)=>{for(var e in t||(t={}))I.call(t,e)&&E(o,e,t[e]);if(w)for(var e of w(t))D.call(t,e)&&E(o,e,t[e]);return o},m=(o,t)=>k(o,_(t));var F=(o,t)=>{for(var e in t)g(o,e,{get:t[e],enumerable:!0})},R=(o,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of B(t))!I.call(o,n)&&n!==e&&g(o,n,{get:()=>t[n],enumerable:!(i=A(t,n))||i.enumerable});return o};var N=o=>R(g({},"__esModule",{value:!0}),o);var U={};F(U,{InferJS:()=>x,attach:()=>$});module.exports=N(U);var f={API_URL:"https://api.pro6pp.nl/v2",LIMIT:20,DEBOUNCE_MS:150,MIN_DEBOUNCE_MS:50,MAX_RETRIES:0},L={DIGITS_1_3:/^[0-9]{1,3}$/},T={query:"",stage:null,cities:[],streets:[],suggestions:[],isValid:!1,isError:!1,isLoading:!1,hasMore:!1,selectedSuggestionIndex:-1},b=class{constructor(t){this.abortController=null;this.country=t.country,this.authKey=t.authKey,this.explicitApiUrl=t.apiUrl,this.baseLimit=t.limit||f.LIMIT,this.currentLimit=this.baseLimit;let e=t.maxRetries!==void 0?t.maxRetries:f.MAX_RETRIES;this.maxRetries=Math.max(0,Math.min(e,10)),this.fetcher=t.fetcher||((r,s)=>fetch(r,s)),this.onStateChange=t.onStateChange||(()=>{}),this.onSelect=t.onSelect||(()=>{}),this.state=c({},T);let i=t.debounceMs!==void 0?t.debounceMs:f.DEBOUNCE_MS,n=Math.max(i,f.MIN_DEBOUNCE_MS);this.debouncedFetch=this.debounce(r=>this.executeFetch(r),n)}handleInput(t){this.currentLimit=this.baseLimit;let e=this.state.stage==="final"&&t!==this.state.query;this.updateState({query:t,isValid:!1,isLoading:!!t.trim(),selectedSuggestionIndex:-1,hasMore:!1}),e&&this.onSelect(null),this.debouncedFetch(t)}loadMore(){this.state.isLoading||(this.currentLimit+=this.baseLimit,this.updateState({isLoading:!0}),this.executeFetch(this.state.query))}handleKeyDown(t){let e=t.target;if(!e)return;let i=this.state.cities.length+this.state.streets.length+this.state.suggestions.length;if(i>0){if(t.key==="ArrowDown"){t.preventDefault();let r=this.state.selectedSuggestionIndex+1;r>=i&&(r=0),this.updateState({selectedSuggestionIndex:r});return}if(t.key==="ArrowUp"){t.preventDefault();let r=this.state.selectedSuggestionIndex-1;r<0&&(r=i-1),this.updateState({selectedSuggestionIndex:r});return}if(t.key==="Enter"&&this.state.selectedSuggestionIndex>=0){t.preventDefault();let s=[...this.state.cities,...this.state.streets,...this.state.suggestions][this.state.selectedSuggestionIndex];s&&(this.selectItem(s),this.updateState({selectedSuggestionIndex:-1}));return}}let n=e.value;if(t.key===" "&&this.shouldAutoInsertComma(n)){t.preventDefault();let r=`${n.trim()}, `;this.updateQueryAndFetch(r)}}selectItem(t){this.debouncedFetch.cancel(),this.abortController&&this.abortController.abort();let e=typeof t=="string"?t:t.label,i=e;typeof t!="string"&&typeof t.value=="string"&&(i=t.value);let n=typeof t!="string"&&typeof t.value=="object"?t.value:void 0,r=!!n&&Object.keys(n).length>0;if(this.state.stage==="final"||r){let u=e;if(n&&Object.keys(n).length>0){let{street:l,street_number:a,city:h}=n;l&&a&&h&&(u=`${l} ${a}, ${h}`)}return this.finishSelection(u,n),!0}let s=typeof t!="string"?t.subtitle:null;return this.processSelection(i,s),!1}shouldAutoInsertComma(t){if(!t.includes(",")&&L.DIGITS_1_3.test(t.trim()))return!0;if(this.state.stage==="street_number"){let i=this.getCurrentFragment(t);return L.DIGITS_1_3.test(i)}return!1}finishSelection(t,e){this.updateState({query:t,suggestions:[],cities:[],streets:[],isValid:!0,stage:"final",hasMore:!1}),this.onSelect(e||t)}processSelection(t,e){let{stage:i,query:n}=this.state,r=n;if(e&&(i==="city"||i==="street"||i==="mixed")){if(i==="city")r=`${e}, ${t}, `;else{let a=this.getQueryPrefix(n);r=a?`${a} ${t}, ${e}, `:`${t}, ${e}, `}this.updateQueryAndFetch(r);return}if(i==="direct"||i==="addition"){this.finishSelection(t);return}!n.includes(",")&&(i==="city"||i==="street"||i==="street_number_first")?r=`${t}, `:(r=this.replaceLastSegment(n,t),i!=="street_number"&&(r+=", ")),this.updateQueryAndFetch(r)}executeFetch(t,e=0){var a,h;let i=(t||"").toString();if(!i.trim()){(a=this.abortController)==null||a.abort(),this.resetState();return}e===0&&(this.updateState({isError:!1}),this.abortController&&this.abortController.abort(),this.abortController=new AbortController);let n=(h=this.abortController)==null?void 0:h.signal,r=this.explicitApiUrl?this.explicitApiUrl:`${f.API_URL}/infer/${this.country.toLowerCase()}`,s=new URLSearchParams({country:this.country.toLowerCase(),query:i,limit:this.currentLimit.toString()});this.authKey&&s.set("authKey",this.authKey);let u=r.includes("?")?"&":"?",l=`${r}${u}${s.toString()}`;this.fetcher(l,{signal:n}).then(d=>{if(!d.ok){if(e<this.maxRetries&&(d.status>=500||d.status===429))return this.retry(t,e,n);throw new Error("Network error")}return d.json()}).then(d=>{d&&this.mapResponseToState(d)}).catch(d=>{if(d.name!=="AbortError"){if(e<this.maxRetries)return this.retry(t,e,n);this.updateState({isError:!0,isLoading:!1})}})}retry(t,e,i){if(i!=null&&i.aborted)return;let n=Math.pow(2,e)*200;setTimeout(()=>{i!=null&&i.aborted||this.executeFetch(t,e+1)},n)}mapResponseToState(t){var u,l;let e={stage:t.stage,isLoading:!1},i=t.suggestions||[],n=[],r=new Set;for(let a of i){let h=`${a.label}|${a.subtitle||""}|${JSON.stringify(a.value||{})}`;r.has(h)||(r.add(h),n.push(a))}let s=n.length+(((u=t.cities)==null?void 0:u.length)||0)+(((l=t.streets)==null?void 0:l.length)||0);e.hasMore=s>=this.currentLimit,t.stage==="mixed"?(e.cities=t.cities||[],e.streets=t.streets||[],e.suggestions=[]):(e.suggestions=n,e.cities=[],e.streets=[]),e.isValid=t.stage==="final",this.updateState(e)}updateQueryAndFetch(t){this.updateState({query:t,suggestions:[],cities:[],streets:[]}),this.updateState({isLoading:!0,isValid:!1,hasMore:!1}),this.debouncedFetch(t)}replaceLastSegment(t,e){let i=t.lastIndexOf(",");return i===-1?e:`${t.slice(0,i+1)} ${e}`.trim()}getQueryPrefix(t){let e=t.lastIndexOf(",");return e===-1?"":t.slice(0,e+1).trimEnd()}getCurrentFragment(t){var e;return((e=t.split(",").slice(-1)[0])!=null?e:"").trim()}resetState(){this.updateState(m(c({},T),{query:this.state.query}))}updateState(t){this.state=c(c({},this.state),t),this.onStateChange(this.state)}debounce(t,e){let i,n=(...r)=>{i&&clearTimeout(i),i=setTimeout(()=>t.apply(this,r),e)};return n.cancel=()=>{i&&(clearTimeout(i),i=void 0)},n}};function M(o,t){if(!t||!o)return[{text:o,match:!1}];let e=[],i=o.toLowerCase(),n=t.toLowerCase(),r=0,s=0;for(let a=0;a<o.length;a++){if(!(r<t.length&&i[a]===n[r]))continue;a>s&&e.push({text:o.slice(s,a),match:!1}),e.push({text:o[a],match:!0}),r++,s=a+1}return s<o.length&&e.push({text:o.slice(s),match:!1}),r===t.length?e:[{text:o,match:!1}]}var v=`
|
|
2
|
+
.pro6pp-wrapper {
|
|
3
|
+
position: relative;
|
|
4
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
width: 100%;
|
|
7
|
+
-webkit-tap-highlight-color: transparent;
|
|
8
|
+
}
|
|
9
|
+
.pro6pp-wrapper * {
|
|
10
|
+
box-sizing: border-box;
|
|
11
|
+
}
|
|
12
|
+
.pro6pp-input {
|
|
13
|
+
width: 100%;
|
|
14
|
+
padding: 12px 14px;
|
|
15
|
+
padding-right: 48px;
|
|
16
|
+
border: 1px solid #e0e0e0;
|
|
17
|
+
border-radius: 8px;
|
|
18
|
+
font-size: 16px;
|
|
19
|
+
line-height: 1.5;
|
|
20
|
+
appearance: none;
|
|
21
|
+
transition: border-color 0.2s, box-shadow 0.2s;
|
|
22
|
+
}
|
|
23
|
+
.pro6pp-input:focus {
|
|
24
|
+
outline: none;
|
|
25
|
+
border-color: #3b82f6;
|
|
26
|
+
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.pro6pp-input-addons {
|
|
30
|
+
position: absolute;
|
|
31
|
+
right: 4px;
|
|
32
|
+
top: 0;
|
|
33
|
+
bottom: 0;
|
|
34
|
+
display: flex;
|
|
35
|
+
align-items: center;
|
|
36
|
+
pointer-events: none;
|
|
37
|
+
}
|
|
38
|
+
.pro6pp-input-addons > * {
|
|
39
|
+
pointer-events: auto;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.pro6pp-clear-button {
|
|
43
|
+
background: none;
|
|
44
|
+
border: none;
|
|
45
|
+
width: 40px;
|
|
46
|
+
height: 40px;
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
color: #a3a3a3;
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
border-radius: 50%;
|
|
53
|
+
transition: color 0.2s, background-color 0.2s;
|
|
54
|
+
touch-action: manipulation;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@media (hover: hover) {
|
|
58
|
+
.pro6pp-clear-button:hover {
|
|
59
|
+
color: #1f2937;
|
|
60
|
+
background-color: #f3f4f6;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.pro6pp-clear-button:active {
|
|
65
|
+
background-color: #f3f4f6;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.pro6pp-loader {
|
|
69
|
+
width: 20px;
|
|
70
|
+
height: 20px;
|
|
71
|
+
margin: 0 8px;
|
|
72
|
+
border: 2px solid #e0e0e0;
|
|
73
|
+
border-top-color: #6b7280;
|
|
74
|
+
border-radius: 50%;
|
|
75
|
+
animation: pro6pp-spin 0.6s linear infinite;
|
|
76
|
+
flex-shrink: 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.pro6pp-dropdown {
|
|
80
|
+
position: absolute;
|
|
81
|
+
top: 100%;
|
|
82
|
+
left: 0;
|
|
83
|
+
right: 0;
|
|
84
|
+
margin-top: 4px;
|
|
85
|
+
background: #ffffff;
|
|
86
|
+
border: 1px solid #e5e7eb;
|
|
87
|
+
border-radius: 6px;
|
|
88
|
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
89
|
+
z-index: 9999;
|
|
90
|
+
padding: 0;
|
|
91
|
+
max-height: 260px;
|
|
92
|
+
overflow-y: auto;
|
|
93
|
+
display: flex;
|
|
94
|
+
flex-direction: column;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@media (max-height: 500px) {
|
|
98
|
+
.pro6pp-dropdown {
|
|
99
|
+
max-height: 140px;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.pro6pp-list {
|
|
104
|
+
list-style: none;
|
|
105
|
+
margin: 0;
|
|
106
|
+
padding: 0;
|
|
107
|
+
width: 100%;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.pro6pp-item {
|
|
111
|
+
padding: 12px 14px;
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
display: flex;
|
|
114
|
+
align-items: center;
|
|
115
|
+
font-size: 14px;
|
|
116
|
+
color: #374151;
|
|
117
|
+
border-bottom: 1px solid #f3f4f6;
|
|
118
|
+
transition: background-color 0.1s;
|
|
119
|
+
flex-shrink: 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.pro6pp-item:last-child {
|
|
123
|
+
border-bottom: none;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@media (hover: hover) {
|
|
127
|
+
.pro6pp-item:hover, .pro6pp-item--active {
|
|
128
|
+
background-color: #f9fafb;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.pro6pp-item:active {
|
|
133
|
+
background-color: #f3f4f6;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.pro6pp-item__label {
|
|
137
|
+
font-weight: 500;
|
|
138
|
+
flex-shrink: 0;
|
|
139
|
+
}
|
|
140
|
+
.pro6pp-item__subtitle {
|
|
141
|
+
font-size: 14px;
|
|
142
|
+
color: #6b7280;
|
|
143
|
+
flex-grow: 1;
|
|
144
|
+
}
|
|
145
|
+
.pro6pp-item__chevron {
|
|
146
|
+
color: #d1d5db;
|
|
147
|
+
display: flex;
|
|
148
|
+
align-items: center;
|
|
149
|
+
margin-left: auto;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.pro6pp-no-results {
|
|
153
|
+
padding: 24px 16px;
|
|
154
|
+
color: #6b7280;
|
|
155
|
+
font-size: 15px;
|
|
156
|
+
text-align: center;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.pro6pp-load-more {
|
|
160
|
+
width: 100%;
|
|
161
|
+
padding: 14px;
|
|
162
|
+
background: #f9fafb;
|
|
163
|
+
border: none;
|
|
164
|
+
border-top: 1px solid #e0e0e0;
|
|
165
|
+
color: #3b82f6;
|
|
166
|
+
font-size: 14px;
|
|
167
|
+
font-weight: 600;
|
|
168
|
+
cursor: pointer;
|
|
169
|
+
flex-shrink: 0;
|
|
170
|
+
touch-action: manipulation;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.pro6pp-load-more:active {
|
|
174
|
+
background-color: #f3f4f6;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@keyframes pro6pp-spin {
|
|
178
|
+
to { transform: rotate(360deg); }
|
|
179
|
+
}
|
|
180
|
+
`;var x=class{constructor(t,e){this.isOpen=!1;var r;let i=typeof t=="string"?document.querySelector(t):t;if(!i)throw new Error("InferJS: Target element not found.");if(this.noResultsText=e.noResultsText||"No results found",this.loadMoreText=e.loadMoreText||"Show more results...",this.showClearButton=e.showClearButton!==!1,this.useDefaultStyles=e.style!=="none",this.useDefaultStyles&&this.injectStyles(),this.wrapper=document.createElement("div"),this.wrapper.className="pro6pp-wrapper",i instanceof HTMLInputElement?(this.input=i,(r=this.input.parentNode)==null||r.insertBefore(this.wrapper,this.input),this.wrapper.appendChild(this.input)):(i.appendChild(this.wrapper),this.input=document.createElement("input"),this.input.type="text",e.placeholder&&(this.input.placeholder=e.placeholder),this.wrapper.appendChild(this.input)),this.input.setAttribute("autocomplete","off"),this.input.setAttribute("autocorrect","off"),this.input.setAttribute("autocapitalize","none"),this.input.setAttribute("spellcheck","false"),this.input.setAttribute("inputmode","search"),this.input.setAttribute("enterkeyhint","search"),this.useDefaultStyles&&this.input.classList.add("pro6pp-input"),e.inputClass){let s=e.inputClass.split(" ");this.input.classList.add(...s)}let n=document.createElement("div");n.className="pro6pp-input-addons",this.wrapper.appendChild(n),this.loader=document.createElement("div"),this.loader.className="pro6pp-loader",this.loader.style.display="none",n.appendChild(this.loader),this.clearButton=document.createElement("button"),this.clearButton.type="button",this.clearButton.className="pro6pp-clear-button",this.clearButton.setAttribute("aria-label","Clear input"),this.clearButton.style.display="none",this.clearButton.innerHTML=`
|
|
181
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
182
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
183
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
184
|
+
</svg>
|
|
185
|
+
`,n.appendChild(this.clearButton),this.dropdown=document.createElement("div"),this.dropdown.className="pro6pp-dropdown",this.dropdown.style.display="none",this.wrapper.appendChild(this.dropdown),this.list=document.createElement("ul"),this.list.className="pro6pp-list",this.list.setAttribute("role","listbox"),this.dropdown.appendChild(this.list),this.loadMoreButton=document.createElement("button"),this.loadMoreButton.type="button",this.loadMoreButton.className="pro6pp-load-more",this.loadMoreButton.textContent=this.loadMoreText,this.loadMoreButton.style.display="none",this.dropdown.appendChild(this.loadMoreButton),this.core=new b(m(c({},e),{onStateChange:s=>{this.render(s),e.onStateChange&&e.onStateChange(s)},onSelect:s=>{typeof s=="string"?this.input.value=s:s&&typeof s=="object"&&(this.input.value=this.core.state.query),e.onSelect&&e.onSelect(s)}})),this.bindEvents()}injectStyles(){let t="pro6pp-styles";if(!document.getElementById(t)){let e=document.createElement("style");e.id=t,e.textContent=v,document.head.appendChild(e)}}bindEvents(){this.input.addEventListener("input",t=>{let e=t.target.value;this.isOpen=!0,this.core.handleInput(e)}),this.input.addEventListener("keydown",t=>{this.core.handleKeyDown(t)}),this.clearButton.addEventListener("click",()=>{this.core.handleInput(""),this.input.focus()}),this.loadMoreButton.addEventListener("click",t=>{t.preventDefault(),this.core.loadMore()}),document.addEventListener("mousedown",t=>{this.wrapper.contains(t.target)||(this.isOpen=!1,this.dropdown.style.display="none")}),this.input.addEventListener("focus",()=>{this.isOpen=!0,this.render(this.core.state)})}render(t){this.input.value!==t.query&&(this.input.value=t.query),this.loader.style.display=t.isLoading?"block":"none",this.showClearButton&&(this.clearButton.style.display=t.query.length>0?"flex":"none"),this.list.innerHTML="";let e=[...t.cities,...t.streets,...t.suggestions],i=e.length>0,n=!t.isLoading&&!t.isError&&t.query.length>0&&!i&&!t.isValid;if(!(this.isOpen&&(i||t.isLoading||n))){this.dropdown.style.display="none";return}if(this.dropdown.style.display="block",this.loadMoreButton.style.display=t.hasMore?"block":"none",t.isLoading&&!i){let s=document.createElement("li");s.className="pro6pp-no-results",s.textContent="Loading suggestions...",this.list.appendChild(s);return}if(n){let s=document.createElement("li");s.className="pro6pp-no-results",s.textContent=this.noResultsText,this.list.appendChild(s);return}e.forEach((s,u)=>{if(!s.label)return;let l=document.createElement("li");l.className="pro6pp-item",u===t.selectedSuggestionIndex&&l.classList.add("pro6pp-item--active"),l.setAttribute("role","option"),l.setAttribute("aria-selected",u===t.selectedSuggestionIndex?"true":"false");let a=document.createElement("span");a.className="pro6pp-item__label",M(s.label,t.query).forEach(({text:p,match:C})=>{if(C){let y=document.createElement("strong");y.className="pro6pp-item__label--match",y.textContent=p,a.appendChild(y)}else a.appendChild(document.createTextNode(p))}),l.appendChild(a);let d=s.count!==void 0&&s.count!==null?s.count:"",S=s.subtitle||d;if(S!==""){let p=document.createElement("span");p.className="pro6pp-item__subtitle",p.textContent=`, ${S}`,l.appendChild(p)}if(s.value===void 0||s.value===null){let p=document.createElement("div");p.className="pro6pp-item__chevron",p.innerHTML=`
|
|
186
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
187
|
+
<polyline points="9 18 15 12 9 6"></polyline>
|
|
188
|
+
</svg>
|
|
189
|
+
`,l.appendChild(p)}l.onmousedown=p=>p.preventDefault(),l.onclick=p=>{p.stopPropagation(),this.core.selectItem(s)?(this.isOpen=!1,this.dropdown.style.display="none"):setTimeout(()=>this.input.focus(),0)},this.list.appendChild(l)})}};function $(o,t){return new x(o,t)}0&&(module.exports={InferJS,attach});
|
package/dist/index.d.mts
CHANGED
|
@@ -1,20 +1,74 @@
|
|
|
1
1
|
import { InferConfig } from '@pro6pp/infer-core';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the JS Infer SDK.
|
|
5
|
+
*/
|
|
3
6
|
interface InferJSConfig extends InferConfig {
|
|
7
|
+
/**
|
|
8
|
+
* The styling theme to apply.
|
|
9
|
+
* - `default`: Injects the standard Pro6PP CSS theme.
|
|
10
|
+
* - `none`: No styles are applied, allowing for custom CSS.
|
|
11
|
+
* @default 'default'
|
|
12
|
+
*/
|
|
4
13
|
style?: 'default' | 'none';
|
|
14
|
+
/**
|
|
15
|
+
* Custom placeholder text for the input field.
|
|
16
|
+
*/
|
|
17
|
+
placeholder?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Additional CSS classes to add to the input element.
|
|
20
|
+
*/
|
|
21
|
+
inputClass?: string;
|
|
22
|
+
/**
|
|
23
|
+
* The text to display when no suggestions are found.
|
|
24
|
+
* @default 'No results found'
|
|
25
|
+
*/
|
|
26
|
+
noResultsText?: string;
|
|
27
|
+
/**
|
|
28
|
+
* The text to show on the load more button.
|
|
29
|
+
* @default 'Show more results...'
|
|
30
|
+
*/
|
|
31
|
+
loadMoreText?: string;
|
|
32
|
+
/**
|
|
33
|
+
* If true, shows a clear button when the input is not empty.
|
|
34
|
+
* @default true
|
|
35
|
+
*/
|
|
36
|
+
showClearButton?: boolean;
|
|
5
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* The JS implementation of the Pro6PP Infer SDK.
|
|
40
|
+
* This class manages the DOM elements, event listeners, and rendering for the autocomplete UI.
|
|
41
|
+
*/
|
|
6
42
|
declare class InferJS {
|
|
7
43
|
private core;
|
|
8
44
|
private input;
|
|
9
45
|
private list;
|
|
46
|
+
private dropdown;
|
|
10
47
|
private wrapper;
|
|
48
|
+
private loader;
|
|
49
|
+
private clearButton;
|
|
50
|
+
private loadMoreButton;
|
|
11
51
|
private useDefaultStyles;
|
|
12
|
-
|
|
52
|
+
private noResultsText;
|
|
53
|
+
private loadMoreText;
|
|
54
|
+
private showClearButton;
|
|
55
|
+
private isOpen;
|
|
56
|
+
/**
|
|
57
|
+
* Initializes the Infer logic on a target element.
|
|
58
|
+
* @param target Either a CSS selector string or a direct HTMLElement.
|
|
59
|
+
* @param config Configuration options for the API and UI.
|
|
60
|
+
*/
|
|
61
|
+
constructor(target: string | HTMLElement, config: InferJSConfig);
|
|
13
62
|
private injectStyles;
|
|
14
|
-
private setupDOM;
|
|
15
63
|
private bindEvents;
|
|
16
64
|
private render;
|
|
17
65
|
}
|
|
18
|
-
|
|
66
|
+
/**
|
|
67
|
+
* A helper to initialize the Pro6PP Infer SDK on a target element.
|
|
68
|
+
* @param target A CSS selector string or HTMLElement.
|
|
69
|
+
* @param config Configuration for the SDK.
|
|
70
|
+
* @returns An instance of InferJS.
|
|
71
|
+
*/
|
|
72
|
+
declare function attach(target: string | HTMLElement, config: InferJSConfig): InferJS;
|
|
19
73
|
|
|
20
74
|
export { InferJS, type InferJSConfig, attach };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,20 +1,74 @@
|
|
|
1
1
|
import { InferConfig } from '@pro6pp/infer-core';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the JS Infer SDK.
|
|
5
|
+
*/
|
|
3
6
|
interface InferJSConfig extends InferConfig {
|
|
7
|
+
/**
|
|
8
|
+
* The styling theme to apply.
|
|
9
|
+
* - `default`: Injects the standard Pro6PP CSS theme.
|
|
10
|
+
* - `none`: No styles are applied, allowing for custom CSS.
|
|
11
|
+
* @default 'default'
|
|
12
|
+
*/
|
|
4
13
|
style?: 'default' | 'none';
|
|
14
|
+
/**
|
|
15
|
+
* Custom placeholder text for the input field.
|
|
16
|
+
*/
|
|
17
|
+
placeholder?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Additional CSS classes to add to the input element.
|
|
20
|
+
*/
|
|
21
|
+
inputClass?: string;
|
|
22
|
+
/**
|
|
23
|
+
* The text to display when no suggestions are found.
|
|
24
|
+
* @default 'No results found'
|
|
25
|
+
*/
|
|
26
|
+
noResultsText?: string;
|
|
27
|
+
/**
|
|
28
|
+
* The text to show on the load more button.
|
|
29
|
+
* @default 'Show more results...'
|
|
30
|
+
*/
|
|
31
|
+
loadMoreText?: string;
|
|
32
|
+
/**
|
|
33
|
+
* If true, shows a clear button when the input is not empty.
|
|
34
|
+
* @default true
|
|
35
|
+
*/
|
|
36
|
+
showClearButton?: boolean;
|
|
5
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* The JS implementation of the Pro6PP Infer SDK.
|
|
40
|
+
* This class manages the DOM elements, event listeners, and rendering for the autocomplete UI.
|
|
41
|
+
*/
|
|
6
42
|
declare class InferJS {
|
|
7
43
|
private core;
|
|
8
44
|
private input;
|
|
9
45
|
private list;
|
|
46
|
+
private dropdown;
|
|
10
47
|
private wrapper;
|
|
48
|
+
private loader;
|
|
49
|
+
private clearButton;
|
|
50
|
+
private loadMoreButton;
|
|
11
51
|
private useDefaultStyles;
|
|
12
|
-
|
|
52
|
+
private noResultsText;
|
|
53
|
+
private loadMoreText;
|
|
54
|
+
private showClearButton;
|
|
55
|
+
private isOpen;
|
|
56
|
+
/**
|
|
57
|
+
* Initializes the Infer logic on a target element.
|
|
58
|
+
* @param target Either a CSS selector string or a direct HTMLElement.
|
|
59
|
+
* @param config Configuration options for the API and UI.
|
|
60
|
+
*/
|
|
61
|
+
constructor(target: string | HTMLElement, config: InferJSConfig);
|
|
13
62
|
private injectStyles;
|
|
14
|
-
private setupDOM;
|
|
15
63
|
private bindEvents;
|
|
16
64
|
private render;
|
|
17
65
|
}
|
|
18
|
-
|
|
66
|
+
/**
|
|
67
|
+
* A helper to initialize the Pro6PP Infer SDK on a target element.
|
|
68
|
+
* @param target A CSS selector string or HTMLElement.
|
|
69
|
+
* @param config Configuration for the SDK.
|
|
70
|
+
* @returns An instance of InferJS.
|
|
71
|
+
*/
|
|
72
|
+
declare function attach(target: string | HTMLElement, config: InferJSConfig): InferJS;
|
|
19
73
|
|
|
20
74
|
export { InferJS, type InferJSConfig, attach };
|