@pro6pp/infer-js 0.0.2-beta.8 → 0.1.0-beta.18
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 +49 -4
- package/dist/index.cjs +216 -0
- package/dist/{pro6pp-infer.d.mts → index.d.mts} +24 -7
- package/dist/{pro6pp-infer.d.ts → index.d.ts} +24 -7
- package/dist/index.global.js +216 -0
- package/dist/index.mjs +216 -0
- package/dist/styles.css +203 -0
- package/package.json +4 -3
- package/dist/pro6pp-infer.cjs +0 -167
- package/dist/pro6pp-infer.global.js +0 -167
- package/dist/pro6pp-infer.mjs +0 -167
package/README.md
CHANGED
|
@@ -70,7 +70,12 @@ const inputElement = document.getElementById('address-input');
|
|
|
70
70
|
attach(inputElement, {
|
|
71
71
|
authKey: 'YOUR_AUTH_KEY',
|
|
72
72
|
country: 'NL',
|
|
73
|
-
|
|
73
|
+
// triggered whenever the internal state changes
|
|
74
|
+
onStateChange: function (state) {
|
|
75
|
+
console.log('Current State:', state);
|
|
76
|
+
},
|
|
77
|
+
// triggered when the user selects a final address
|
|
78
|
+
onSelect: function (result) {
|
|
74
79
|
console.log('Selected Address:', result);
|
|
75
80
|
},
|
|
76
81
|
});
|
|
@@ -93,13 +98,52 @@ attach(inputElement, {
|
|
|
93
98
|
|
|
94
99
|
## Styling
|
|
95
100
|
|
|
96
|
-
By default, the SDK injects the necessary CSS for the dropdown.
|
|
101
|
+
By default, the SDK injects the necessary CSS for the dropdown. You have several options for styling:
|
|
102
|
+
|
|
103
|
+
Note: the JavaScript bundle still contains the default CSS as a fallback. Importing `@pro6pp/infer-js/styles.css` with `style: 'none'` disables runtime style injection, but does not provide a CSS-free JS bundle.
|
|
104
|
+
|
|
105
|
+
### Option 1: Use auto-injected styles (default)
|
|
106
|
+
|
|
107
|
+
No extra setup needed. The CSS is embedded in the JS bundle and injected automatically.
|
|
108
|
+
|
|
109
|
+
### Option 2: Import CSS separately
|
|
110
|
+
|
|
111
|
+
If you prefer to load the CSS as a separate file:
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
import { attach } from '@pro6pp/infer-js';
|
|
115
|
+
import '@pro6pp/infer-js/styles.css';
|
|
116
|
+
|
|
117
|
+
attach(inputElement, {
|
|
118
|
+
authKey: '...',
|
|
119
|
+
country: 'NL',
|
|
120
|
+
style: 'none', // disable auto-injection since we imported CSS separately
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Option 3: CDN with separate CSS
|
|
125
|
+
|
|
126
|
+
```html
|
|
127
|
+
<link rel="stylesheet" href="https://unpkg.com/@pro6pp/infer-js/dist/styles.css" />
|
|
128
|
+
<script src="https://unpkg.com/@pro6pp/infer-js"></script>
|
|
129
|
+
<script>
|
|
130
|
+
Pro6PP.attach('#address-input', {
|
|
131
|
+
authKey: 'YOUR_AUTH_KEY',
|
|
132
|
+
country: 'NL',
|
|
133
|
+
style: 'none', // disable auto-injection since we linked CSS separately
|
|
134
|
+
});
|
|
135
|
+
</script>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Option 4: Fully custom styles
|
|
139
|
+
|
|
140
|
+
If you want to control the styling entirely with your own CSS:
|
|
97
141
|
|
|
98
142
|
```js
|
|
99
143
|
attach(inputElement, {
|
|
100
144
|
authKey: '...',
|
|
101
145
|
country: 'NL',
|
|
102
|
-
style: 'none', // disables default
|
|
146
|
+
style: 'none', // disables default style injection
|
|
103
147
|
});
|
|
104
148
|
```
|
|
105
149
|
|
|
@@ -109,7 +153,6 @@ You can then target the following classes in your CSS:
|
|
|
109
153
|
| :----------------------- | :-------------------------------------------------------- |
|
|
110
154
|
| `.pro6pp-wrapper` | The container element wrapping the input and dropdown. |
|
|
111
155
|
| `.pro6pp-input` | The input element itself. |
|
|
112
|
-
| `.pro6pp-loader` | The loading spinner shown during API requests. |
|
|
113
156
|
| `.pro6pp-dropdown` | The `<ul>` list containing the suggestions. |
|
|
114
157
|
| `.pro6pp-item` | A single suggestion item (`<li>`). |
|
|
115
158
|
| `.pro6pp-item--active` | The currently highlighted item (for keyboard navigation). |
|
|
@@ -117,3 +160,5 @@ You can then target the following classes in your CSS:
|
|
|
117
160
|
| `.pro6pp-item__subtitle` | The secondary text (e.g., city or result count). |
|
|
118
161
|
| `.pro6pp-item__chevron` | The icon indicating a folder/expandable result. |
|
|
119
162
|
| `.pro6pp-no-results` | The message shown when no suggestions are found. |
|
|
163
|
+
| `.pro6pp-loader-item` | The list item containing the loading spinner and text. |
|
|
164
|
+
| `.pro6pp-mini-spinner` | The spinner icon inside the loader item. |
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";var y=Object.defineProperty,k=Object.defineProperties,$=Object.getOwnPropertyDescriptor,R=Object.getOwnPropertyDescriptors,F=Object.getOwnPropertyNames,L=Object.getOwnPropertySymbols;var T=Object.prototype.hasOwnProperty,H=Object.prototype.propertyIsEnumerable;var I=(o,e,t)=>e in o?y(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t,f=(o,e)=>{for(var t in e||(e={}))T.call(e,t)&&I(o,t,e[t]);if(L)for(var t of L(e))H.call(e,t)&&I(o,t,e[t]);return o},m=(o,e)=>k(o,R(e));var N=(o,e)=>{for(var t in e)y(o,t,{get:e[t],enumerable:!0})},B=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of F(e))!T.call(o,s)&&s!==t&&y(o,s,{get:()=>e[s],enumerable:!(n=$(e,s))||n.enumerable});return o};var O=o=>B(y({},"__esModule",{value:!0}),o);var K={};N(K,{InferJS:()=>v,attach:()=>q});module.exports=O(K);function _(o){return o.toLowerCase().trim()}function U(o){return o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function V(o,e){let t=_(o),n=_(e);if(n.includes(" "))return t.indexOf(n);let r=new RegExp(`(?:^|[,\\s])${U(n)}(?:$|[,\\s])`,"g").exec(t);if(r){let i=r.index,p=t[i];return p===","||p===" "?i+1:i}return-1}function P(o,e){let t=[],n=[];e.street&&n.push({value:e.street,type:"street"}),e.city&&n.push({value:e.city,type:"city"}),e.postcode&&n.push({value:e.postcode,type:"postcode"}),e.street_number!==void 0&&e.street_number!==null&&n.push({value:String(e.street_number),type:"street_number"}),e.addition&&n.push({value:e.addition,type:"addition"});for(let s of n){let r=V(o,s.value);r!==-1&&t.push({type:s.type,value:s.value,position:r})}return t.sort((s,r)=>s.position-r.position),t}function M(o,e){if(!e||!o)return"";let t=P(o,e),n=new Set(t.map(i=>i.type)),s=[];for(let i of t)s.push(i.value);let r=["street","street_number","addition","postcode","city"];for(let i of r){if(n.has(i))continue;let p;switch(i){case"street":p=e.street;break;case"city":p=e.city;break;case"street_number":p=e.street_number!==void 0?String(e.street_number):void 0;break;case"postcode":p=e.postcode;break;case"addition":p=e.addition;break}p&&s.push(p)}return s.join(", ")}var b={API_URL:"https://api.pro6pp.nl/v2",LIMIT:20,DEBOUNCE_MS:150,MIN_DEBOUNCE_MS:50,MAX_RETRIES:0},w={DIGITS_1_3:/^[0-9]{1,3}$/,STREET_NUMBER_PREFIX:/^(\d+)\s*,\s*$/},A={query:"",stage:null,cities:[],streets:[],suggestions:[],isValid:!1,value:null,isError:!1,isLoading:!1,hasMore:!1,selectedSuggestionIndex:-1},x=class{constructor(e){this.abortController=null;this.country=e.country,this.authKey=e.authKey,this.explicitApiUrl=e.apiUrl,this.baseLimit=e.limit||b.LIMIT,this.currentLimit=this.baseLimit,this.language=e.language;let t=e.maxRetries!==void 0?e.maxRetries:b.MAX_RETRIES;this.maxRetries=Math.max(0,Math.min(t,10)),this.fetcher=e.fetcher||((r,i)=>fetch(r,i)),this.onStateChange=e.onStateChange||(()=>{}),this.onSelect=e.onSelect||(()=>{}),this.state=f({},A);let n=e.debounceMs!==void 0?e.debounceMs:b.DEBOUNCE_MS,s=Math.max(n,b.MIN_DEBOUNCE_MS);this.debouncedFetch=this.debounce(r=>this.executeFetch(r),s)}handleInput(e){this.currentLimit=this.baseLimit;let t=this.state.stage==="final"&&e!==this.state.query;this.updateState({query:e,isValid:!1,value:null,isLoading:!!e.trim(),selectedSuggestionIndex:-1,hasMore:!1,stage:t?null:this.state.stage}),t&&this.onSelect(null),this.debouncedFetch(e)}loadMore(){this.state.isLoading||(this.currentLimit+=this.baseLimit,this.updateState({isLoading:!0}),this.executeFetch(this.state.query))}handleKeyDown(e){let t=e.target;if(!t)return;let n=this.state.cities.length+this.state.streets.length+this.state.suggestions.length;if(n>0){if(e.key==="ArrowDown"){e.preventDefault();let r=this.state.selectedSuggestionIndex+1;r>=n&&(r=0),this.updateState({selectedSuggestionIndex:r});return}if(e.key==="ArrowUp"){e.preventDefault();let r=this.state.selectedSuggestionIndex-1;r<0&&(r=n-1),this.updateState({selectedSuggestionIndex:r});return}if(e.key==="Enter"&&this.state.selectedSuggestionIndex>=0){e.preventDefault();let i=[...this.state.cities,...this.state.streets,...this.state.suggestions][this.state.selectedSuggestionIndex];i&&(this.selectItem(i),this.updateState({selectedSuggestionIndex:-1}));return}}let s=t.value;if(e.key===" "&&this.shouldAutoInsertComma(s)){e.preventDefault();let r=`${s.trim()}, `;this.updateQueryAndFetch(r)}}selectItem(e){this.debouncedFetch.cancel(),this.abortController&&this.abortController.abort();let t=typeof e=="string"?e:e.label,n=t;typeof e!="string"&&typeof e.value=="string"&&(n=e.value);let s=typeof e!="string"&&typeof e.value=="object"?e.value:void 0,r=!!s&&Object.keys(s).length>0;if(this.state.stage==="final"||r){let p=t;if(s&&Object.keys(s).length>0){let{street:u,street_number:a,postcode:c,city:l,addition:h}=s;if(u&&a&&l){let g=h?` ${h}`:"",d=c?`${c}, `:"";p=`${u}, ${a}${g}, ${d}${l}`}}return this.finishSelection(p,s),!0}let i=typeof e!="string"?e.subtitle:null;return this.processSelection(n,i),!1}shouldAutoInsertComma(e){if(!e.includes(",")&&w.DIGITS_1_3.test(e.trim()))return!0;if(this.state.stage==="street_number"){let n=this.getCurrentFragment(e);return w.DIGITS_1_3.test(n)}return!1}finishSelection(e,t){this.updateState({query:e,suggestions:[],cities:[],streets:[],isValid:!0,value:t||null,stage:"final",hasMore:!1}),this.onSelect(t||e)}processSelection(e,t){let{stage:n,query:s}=this.state,r=s;if(t&&(n==="city"||n==="street"||n==="mixed")){if(n==="city")r=`${t}, ${e}, `;else{let a=this.getQueryPrefix(s),c=!a||!a.includes(t),l=a;if(a&&t){let h=a.match(w.STREET_NUMBER_PREFIX);if(h){let g=h[1];t.startsWith(g)&&(l="")}}c?r=l?`${l} ${e}, ${t}, `:`${e}, ${t}, `:r=l?`${l} ${e}, `:`${e}, `}this.updateQueryAndFetch(r);return}if(n==="direct"||n==="addition"){this.finishSelection(e);return}!s.includes(",")&&(n==="city"||n==="street"||n==="street_number_first")?r=`${e}, `:(r=this.replaceLastSegment(s,e),n!=="street_number"&&(r+=", ")),this.updateQueryAndFetch(r)}executeFetch(e,t=0){var a,c;let n=(e||"").toString();if(!n.trim()){(a=this.abortController)==null||a.abort(),this.resetState();return}t===0&&(this.updateState({isError:!1}),this.abortController&&this.abortController.abort(),this.abortController=new AbortController);let s=(c=this.abortController)==null?void 0:c.signal,r=this.explicitApiUrl?this.explicitApiUrl:`${b.API_URL}/infer/${this.country.toLowerCase()}`,i=new URLSearchParams({query:n,limit:this.currentLimit.toString()});this.explicitApiUrl&&i.append("country",this.country.toLowerCase()),this.authKey&&i.set("authKey",this.authKey),this.language&&i.set("language",this.language);let p=r.includes("?")?"&":"?",u=`${r}${p}${i.toString()}`;this.fetcher(u,{signal:s}).then(l=>{if(!l.ok){if(t<this.maxRetries&&(l.status>=500||l.status===429))return this.retry(e,t,s);throw new Error("Network error")}return l.json()}).then(l=>{l&&this.mapResponseToState(l)}).catch(l=>{if(l.name!=="AbortError"){if(t<this.maxRetries)return this.retry(e,t,s);this.updateState({isError:!0,isLoading:!1})}})}retry(e,t,n){if(n!=null&&n.aborted)return;let s=Math.pow(2,t)*200;setTimeout(()=>{n!=null&&n.aborted||this.executeFetch(e,t+1)},s)}mapResponseToState(e){var p,u,a,c;let t={stage:e.stage,isLoading:!1},n=e.suggestions||[],s=[],r=new Set;for(let l of n){let h=`${l.label}|${l.subtitle||""}|${JSON.stringify(l.value||{})}`;if(!r.has(h)){r.add(h);let g=this.reformatSuggestionLabel(l);s.push(g)}}let i=s.length+(((p=e.cities)==null?void 0:p.length)||0)+(((u=e.streets)==null?void 0:u.length)||0);t.hasMore=i>=this.currentLimit,e.stage==="mixed"?(t.cities=e.cities||[],t.streets=e.streets||[],((a=t.cities)==null?void 0:a.length)===0&&((c=t.streets)==null?void 0:c.length)===0?t.suggestions=s:t.suggestions=[]):(t.suggestions=s,t.cities=[],t.streets=[]),t.isValid=e.stage==="final",this.updateState(t),t.isValid&&s.length===1&&this.selectItem(s[0])}reformatSuggestionLabel(e){if(!e.value||typeof e.value=="string")return e;let t=e.value;if(!t.street||!t.city)return e;let n=M(this.state.query,t);return n?m(f({},e),{label:n}):e}updateQueryAndFetch(e){this.updateState({query:e,suggestions:[],cities:[],streets:[],isValid:!1,value:null,isLoading:!0,hasMore:!1}),this.debouncedFetch(e)}replaceLastSegment(e,t){let n=e.lastIndexOf(",");return n===-1?t:`${e.slice(0,n+1)} ${t}`.trim()}getQueryPrefix(e){let t=e.lastIndexOf(",");return t===-1?"":e.slice(0,t+1).trimEnd()}getCurrentFragment(e){var t;return((t=e.split(",").slice(-1)[0])!=null?t:"").trim()}resetState(){this.updateState(m(f({},A),{query:this.state.query}))}updateState(e){this.state=f(f({},this.state),e),this.onStateChange(this.state)}debounce(e,t){let n,s=(...r)=>{n&&clearTimeout(n),n=setTimeout(()=>e.apply(this,r),t)};return s.cancel=()=>{n&&(clearTimeout(n),n=void 0)},s}};function z(o){if(o.length===0)return o;let e=[];for(let t of o){let n=e[e.length-1];n&&n.match===t.match?n.text+=t.text:e.push({text:t.text,match:t.match})}return e}function D(o,e){if(!e||!o)return[{text:o,match:!1}];let t=[],n=o.toLowerCase(),s=e.toLowerCase(),r=0,i=0;for(let a=0;a<o.length;a++){if(!(r<e.length&&n[a]===s[r]))continue;a>i&&t.push({text:o.slice(i,a),match:!1}),t.push({text:o[a],match:!0}),r++,i=a+1}return i<o.length&&t.push({text:o.slice(i),match:!1}),r===e.length?z(t):[{text:o,match:!1}]}var C=`
|
|
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
|
+
|
|
24
|
+
.pro6pp-input::placeholder {
|
|
25
|
+
font-size: 16px;
|
|
26
|
+
color: #a3a3a3;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.pro6pp-input:focus {
|
|
30
|
+
outline: none;
|
|
31
|
+
border-color: #3b82f6;
|
|
32
|
+
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.pro6pp-input-addons {
|
|
36
|
+
position: absolute;
|
|
37
|
+
right: 4px;
|
|
38
|
+
top: 0;
|
|
39
|
+
bottom: 0;
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
pointer-events: none;
|
|
43
|
+
}
|
|
44
|
+
.pro6pp-input-addons > * {
|
|
45
|
+
pointer-events: auto;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.pro6pp-clear-button {
|
|
49
|
+
background: none;
|
|
50
|
+
border: none;
|
|
51
|
+
width: 32px;
|
|
52
|
+
height: 32px;
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
color: #a3a3a3;
|
|
55
|
+
display: flex;
|
|
56
|
+
align-items: center;
|
|
57
|
+
justify-content: center;
|
|
58
|
+
border-radius: 50%;
|
|
59
|
+
transition: color 0.2s, background-color 0.2s;
|
|
60
|
+
touch-action: manipulation;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@media (hover: hover) {
|
|
64
|
+
.pro6pp-clear-button:hover {
|
|
65
|
+
color: #1f2937;
|
|
66
|
+
background-color: #f3f4f6;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.pro6pp-clear-button:active {
|
|
71
|
+
background-color: #f3f4f6;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.pro6pp-dropdown {
|
|
75
|
+
position: absolute;
|
|
76
|
+
top: 100%;
|
|
77
|
+
left: 0;
|
|
78
|
+
right: 0;
|
|
79
|
+
margin-top: 4px;
|
|
80
|
+
background: #ffffff;
|
|
81
|
+
border: 1px solid #e5e7eb;
|
|
82
|
+
border-radius: 6px;
|
|
83
|
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
84
|
+
z-index: 9999;
|
|
85
|
+
padding: 0;
|
|
86
|
+
max-height: 280px;
|
|
87
|
+
overflow-y: auto;
|
|
88
|
+
display: flex;
|
|
89
|
+
flex-direction: column;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@media (max-height: 500px) {
|
|
93
|
+
.pro6pp-dropdown {
|
|
94
|
+
max-height: 180px;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.pro6pp-list {
|
|
99
|
+
list-style: none;
|
|
100
|
+
margin: 0;
|
|
101
|
+
padding: 0;
|
|
102
|
+
width: 100%;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.pro6pp-item {
|
|
106
|
+
padding: 12px 14px;
|
|
107
|
+
cursor: pointer;
|
|
108
|
+
display: flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
font-size: 15px;
|
|
111
|
+
line-height: 1.4;
|
|
112
|
+
color: #374151;
|
|
113
|
+
border-bottom: 1px solid #f3f4f6;
|
|
114
|
+
transition: background-color 0.1s;
|
|
115
|
+
flex-shrink: 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.pro6pp-item:last-child {
|
|
119
|
+
border-bottom: none;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
@media (hover: hover) {
|
|
123
|
+
.pro6pp-item:hover, .pro6pp-item--active {
|
|
124
|
+
background-color: #f9fafb;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.pro6pp-item:active {
|
|
129
|
+
background-color: #f3f4f6;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.pro6pp-item__label {
|
|
133
|
+
font-weight: 400;
|
|
134
|
+
flex-shrink: 1;
|
|
135
|
+
overflow: hidden;
|
|
136
|
+
text-overflow: ellipsis;
|
|
137
|
+
white-space: nowrap;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.pro6pp-item__label--match {
|
|
141
|
+
font-weight: 520;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.pro6pp-item__label--unmatched {
|
|
145
|
+
font-weight: 400;
|
|
146
|
+
color: #4b5563;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.pro6pp-item__subtitle {
|
|
150
|
+
color: #6b7280;
|
|
151
|
+
flex-shrink: 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.pro6pp-item__chevron {
|
|
155
|
+
color: #d1d5db;
|
|
156
|
+
display: flex;
|
|
157
|
+
align-items: center;
|
|
158
|
+
margin-left: auto;
|
|
159
|
+
padding-left: 8px;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.pro6pp-no-results {
|
|
163
|
+
padding: 24px 16px;
|
|
164
|
+
color: #6b7280;
|
|
165
|
+
font-size: 15px;
|
|
166
|
+
text-align: center;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.pro6pp-loader-item {
|
|
170
|
+
padding: 10px 12px;
|
|
171
|
+
color: #6b7280;
|
|
172
|
+
font-size: 0.875rem;
|
|
173
|
+
display: flex;
|
|
174
|
+
align-items: center;
|
|
175
|
+
justify-content: center;
|
|
176
|
+
gap: 8px;
|
|
177
|
+
background-color: #f9fafb;
|
|
178
|
+
border-top: 1px solid #f3f4f6;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.pro6pp-mini-spinner {
|
|
182
|
+
width: 14px;
|
|
183
|
+
height: 14px;
|
|
184
|
+
border: 2px solid #e5e7eb;
|
|
185
|
+
border-top-color: #6b7280;
|
|
186
|
+
border-radius: 50%;
|
|
187
|
+
animation: pro6pp-spin 0.6s linear infinite;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@media (max-width: 640px) {
|
|
191
|
+
.pro6pp-input {
|
|
192
|
+
font-size: 16px;
|
|
193
|
+
padding: 10px 12px;
|
|
194
|
+
}
|
|
195
|
+
.pro6pp-item {
|
|
196
|
+
padding: 10px 12px;
|
|
197
|
+
font-size: 14px;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
@keyframes pro6pp-spin {
|
|
202
|
+
to { transform: rotate(360deg); }
|
|
203
|
+
}
|
|
204
|
+
`;var v=class{constructor(e,t){this.isOpen=!1;this.boundHandlers=null;this.isDestroyed=!1;var r;let n=typeof e=="string"?document.querySelector(e):e;if(!n)throw new Error("InferJS: Target element not found.");if(this.noResultsText=t.noResultsText||"No results found",this.loadingText=t.loadingText||"Loading more...",this.showClearButton=t.showClearButton!==!1,this.useDefaultStyles=t.style!=="none",this.useDefaultStyles&&this.injectStyles(),this.wrapper=document.createElement("div"),this.wrapper.className="pro6pp-wrapper",n instanceof HTMLInputElement?(this.input=n,(r=this.input.parentNode)==null||r.insertBefore(this.wrapper,this.input),this.wrapper.appendChild(this.input)):(n.appendChild(this.wrapper),this.input=document.createElement("input"),this.input.type="text",t.placeholder&&(this.input.placeholder=t.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.input.classList.add("pro6pp-input"),t.inputClass){let i=t.inputClass.split(" ");this.input.classList.add(...i)}let s=document.createElement("div");s.className="pro6pp-input-addons",this.wrapper.appendChild(s),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=`
|
|
205
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
206
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
207
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
208
|
+
</svg>
|
|
209
|
+
`,s.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.dropdownLoader=document.createElement("div"),this.dropdownLoader.className="pro6pp-loader-item",this.dropdownLoader.style.display="none",this.dropdownLoader.innerHTML=`
|
|
210
|
+
<div class="pro6pp-mini-spinner"></div>
|
|
211
|
+
<span>${this.loadingText}</span>
|
|
212
|
+
`,this.dropdown.appendChild(this.dropdownLoader),this.core=new x(m(f({},t),{onStateChange:i=>{this.render(i),t.onStateChange&&t.onStateChange(i)},onSelect:i=>{typeof i=="string"?this.input.value=i:i&&typeof i=="object"&&(this.input.value=this.core.state.query),t.onSelect&&t.onSelect(i)}})),this.observer=new IntersectionObserver(i=>{i[0].isIntersecting&&this.core.state.hasMore&&!this.core.state.isLoading&&this.core.loadMore()},{threshold:.1}),this.bindEvents()}get value(){return this.core.state.value||null}set value(e){if(!e)return;let t=e.addition?` ${e.addition}`:"",n=e.postcode?`${e.postcode}, `:"",s=`${e.street}, ${e.street_number}${t}, ${n}${e.city}`;this.core.selectItem({label:s,value:e})}destroy(){this.isDestroyed||(this.isDestroyed=!0,this.boundHandlers&&(this.input.removeEventListener("input",this.boundHandlers.onInput),this.input.removeEventListener("keydown",this.boundHandlers.onKeyDown),this.clearButton.removeEventListener("click",this.boundHandlers.onClearClick),document.removeEventListener("mousedown",this.boundHandlers.onDocumentMouseDown),this.input.removeEventListener("focus",this.boundHandlers.onFocus),this.boundHandlers=null),this.observer.disconnect(),this.wrapper.parentNode&&(this.wrapper.parentNode.insertBefore(this.input,this.wrapper),this.wrapper.remove()),this.input.classList.remove("pro6pp-input"),this.input.value="")}injectStyles(){let e="pro6pp-styles";if(!document.getElementById(e)){let t=document.createElement("style");t.id=e,t.textContent=C,document.head.appendChild(t)}}bindEvents(){this.boundHandlers={onInput:e=>{let t=e.target.value;this.isOpen=!0,this.core.handleInput(t)},onKeyDown:e=>{this.core.handleKeyDown(e)},onClearClick:()=>{this.core.handleInput(""),this.input.focus()},onDocumentMouseDown:e=>{this.wrapper.contains(e.target)||(this.isOpen=!1,this.dropdown.style.display="none")},onFocus:()=>{this.isOpen=!0,this.render(this.core.state)}},this.input.addEventListener("input",this.boundHandlers.onInput),this.input.addEventListener("keydown",this.boundHandlers.onKeyDown),this.clearButton.addEventListener("click",this.boundHandlers.onClearClick),document.addEventListener("mousedown",this.boundHandlers.onDocumentMouseDown),this.input.addEventListener("focus",this.boundHandlers.onFocus)}render(e){this.input.value!==e.query&&(this.input.value=e.query),this.showClearButton&&(this.clearButton.style.display=e.query.length>0?"flex":"none"),this.list.innerHTML="";let t=[...e.cities,...e.streets,...e.suggestions],n=t.length>0,s=!e.isLoading&&!e.isError&&e.query.length>0&&!n&&!e.isValid;if(!(this.isOpen&&(n||e.isLoading||s))){this.dropdown.style.display="none";return}if(this.dropdown.style.display="block",e.isLoading&&n?this.dropdownLoader.style.display="flex":this.dropdownLoader.style.display="none",e.isLoading&&!n){let i=document.createElement("li");i.className="pro6pp-no-results",i.textContent="Searching...",this.list.appendChild(i),this.dropdownLoader.style.display="none";return}if(s){let i=document.createElement("li");i.className="pro6pp-no-results",i.textContent=this.noResultsText,this.list.appendChild(i);return}if(t.forEach((i,p)=>{if(!i.label)return;let u=document.createElement("li");u.className="pro6pp-item",p===e.selectedSuggestionIndex&&u.classList.add("pro6pp-item--active"),u.setAttribute("role","option"),u.setAttribute("aria-selected",p===e.selectedSuggestionIndex?"true":"false");let a=document.createElement("span");a.className="pro6pp-item__label",D(i.label,e.query).forEach(({text:d,match:E})=>{let S=document.createElement("span");S.className=E?"pro6pp-item__label--match":"pro6pp-item__label--unmatched",S.textContent=d,a.appendChild(S)}),u.appendChild(a);let l=i.count!==void 0&&i.count!==null?i.count:"",h=i.subtitle||l;if(h!==""){let d=document.createElement("span");d.className="pro6pp-item__subtitle",d.textContent=`, ${h}`,u.appendChild(d)}if(i.value===void 0||i.value===null){let d=document.createElement("div");d.className="pro6pp-item__chevron",d.innerHTML=`
|
|
213
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
214
|
+
<polyline points="9 18 15 12 9 6"></polyline>
|
|
215
|
+
</svg>
|
|
216
|
+
`,u.appendChild(d)}u.onmousedown=d=>d.preventDefault(),u.onclick=d=>{d.stopPropagation(),this.core.selectItem(i)?(this.isOpen=!1,this.dropdown.style.display="none"):setTimeout(()=>this.input.focus(),0)},this.list.appendChild(u)}),e.hasMore&&!e.isLoading){let i=document.createElement("li");i.style.height="1px",i.style.opacity="0",this.list.appendChild(i),this.observer.observe(i)}}};function q(o,e){return new v(o,e)}0&&(module.exports={InferJS,attach});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InferConfig } from '@pro6pp/infer-core';
|
|
1
|
+
import { InferConfig, AddressValue } from '@pro6pp/infer-core';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Configuration options for the JS Infer SDK.
|
|
@@ -25,10 +25,10 @@ interface InferJSConfig extends InferConfig {
|
|
|
25
25
|
*/
|
|
26
26
|
noResultsText?: string;
|
|
27
27
|
/**
|
|
28
|
-
* The text to show on the
|
|
29
|
-
* @default '
|
|
28
|
+
* The text to show on the bottom loading indicator.
|
|
29
|
+
* @default 'Loading more...'
|
|
30
30
|
*/
|
|
31
|
-
|
|
31
|
+
loadingText?: string;
|
|
32
32
|
/**
|
|
33
33
|
* If true, shows a clear button when the input is not empty.
|
|
34
34
|
* @default true
|
|
@@ -45,20 +45,37 @@ declare class InferJS {
|
|
|
45
45
|
private list;
|
|
46
46
|
private dropdown;
|
|
47
47
|
private wrapper;
|
|
48
|
-
private
|
|
48
|
+
private dropdownLoader;
|
|
49
49
|
private clearButton;
|
|
50
|
-
private loadMoreButton;
|
|
51
50
|
private useDefaultStyles;
|
|
52
51
|
private noResultsText;
|
|
53
|
-
private
|
|
52
|
+
private loadingText;
|
|
54
53
|
private showClearButton;
|
|
55
54
|
private isOpen;
|
|
55
|
+
private observer;
|
|
56
|
+
private boundHandlers;
|
|
57
|
+
private isDestroyed;
|
|
56
58
|
/**
|
|
57
59
|
* Initializes the Infer logic on a target element.
|
|
58
60
|
* @param target Either a CSS selector string or a direct HTMLElement.
|
|
59
61
|
* @param config Configuration options for the API and UI.
|
|
60
62
|
*/
|
|
61
63
|
constructor(target: string | HTMLElement, config: InferJSConfig);
|
|
64
|
+
/**
|
|
65
|
+
* Retrieves the current selected address value if available.
|
|
66
|
+
* @returns The AddressValue object if valid, otherwise null.
|
|
67
|
+
*/
|
|
68
|
+
get value(): AddressValue | null;
|
|
69
|
+
/**
|
|
70
|
+
* Programmatically sets the address value.
|
|
71
|
+
* @param address The address object to set.
|
|
72
|
+
*/
|
|
73
|
+
set value(address: AddressValue);
|
|
74
|
+
/**
|
|
75
|
+
* Destroys the InferJS instance, removing all event listeners and DOM elements.
|
|
76
|
+
* Call this before creating a new instance on the same input element.
|
|
77
|
+
*/
|
|
78
|
+
destroy(): void;
|
|
62
79
|
private injectStyles;
|
|
63
80
|
private bindEvents;
|
|
64
81
|
private render;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InferConfig } from '@pro6pp/infer-core';
|
|
1
|
+
import { InferConfig, AddressValue } from '@pro6pp/infer-core';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Configuration options for the JS Infer SDK.
|
|
@@ -25,10 +25,10 @@ interface InferJSConfig extends InferConfig {
|
|
|
25
25
|
*/
|
|
26
26
|
noResultsText?: string;
|
|
27
27
|
/**
|
|
28
|
-
* The text to show on the
|
|
29
|
-
* @default '
|
|
28
|
+
* The text to show on the bottom loading indicator.
|
|
29
|
+
* @default 'Loading more...'
|
|
30
30
|
*/
|
|
31
|
-
|
|
31
|
+
loadingText?: string;
|
|
32
32
|
/**
|
|
33
33
|
* If true, shows a clear button when the input is not empty.
|
|
34
34
|
* @default true
|
|
@@ -45,20 +45,37 @@ declare class InferJS {
|
|
|
45
45
|
private list;
|
|
46
46
|
private dropdown;
|
|
47
47
|
private wrapper;
|
|
48
|
-
private
|
|
48
|
+
private dropdownLoader;
|
|
49
49
|
private clearButton;
|
|
50
|
-
private loadMoreButton;
|
|
51
50
|
private useDefaultStyles;
|
|
52
51
|
private noResultsText;
|
|
53
|
-
private
|
|
52
|
+
private loadingText;
|
|
54
53
|
private showClearButton;
|
|
55
54
|
private isOpen;
|
|
55
|
+
private observer;
|
|
56
|
+
private boundHandlers;
|
|
57
|
+
private isDestroyed;
|
|
56
58
|
/**
|
|
57
59
|
* Initializes the Infer logic on a target element.
|
|
58
60
|
* @param target Either a CSS selector string or a direct HTMLElement.
|
|
59
61
|
* @param config Configuration options for the API and UI.
|
|
60
62
|
*/
|
|
61
63
|
constructor(target: string | HTMLElement, config: InferJSConfig);
|
|
64
|
+
/**
|
|
65
|
+
* Retrieves the current selected address value if available.
|
|
66
|
+
* @returns The AddressValue object if valid, otherwise null.
|
|
67
|
+
*/
|
|
68
|
+
get value(): AddressValue | null;
|
|
69
|
+
/**
|
|
70
|
+
* Programmatically sets the address value.
|
|
71
|
+
* @param address The address object to set.
|
|
72
|
+
*/
|
|
73
|
+
set value(address: AddressValue);
|
|
74
|
+
/**
|
|
75
|
+
* Destroys the InferJS instance, removing all event listeners and DOM elements.
|
|
76
|
+
* Call this before creating a new instance on the same input element.
|
|
77
|
+
*/
|
|
78
|
+
destroy(): void;
|
|
62
79
|
private injectStyles;
|
|
63
80
|
private bindEvents;
|
|
64
81
|
private render;
|