@pro6pp/infer-js 0.0.2-beta.0 → 0.0.2-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @pro6pp/infer-js
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.
@@ -7,22 +7,21 @@ A library that adds address autocompletion to any HTML input field.
7
7
 
8
8
  ### Option 1: CDN
9
9
 
10
- Simply add this script to your HTML file. It exposes a global `Pro6PP` variable.
10
+ Add this script to your HTML file. It exposes a global `Pro6PP` variable.
11
11
 
12
12
  ```html
13
- // TODO: add CDN src
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, Vite, or Rollup but not a framework like React.
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`](../react) instead.
24
+ > **Note:** If you are using React, use [`@pro6pp/infer-react`](https://www.npmjs.com/package/@pro6pp/infer-react) instead.
26
25
 
27
26
  ## Usage
28
27
 
@@ -41,9 +40,7 @@ npm install @pro6pp/infer-js
41
40
  </head>
42
41
  <body>
43
42
  <label>Address:</label>
44
- // TODO: add CDN src
45
- <script src=""></script>
46
-
43
+ <script src="https://unpkg.com/@pro6pp/infer-js"></script>
47
44
  <script>
48
45
  Pro6PP.attach('#my-address-input', {
49
46
  authKey: 'YOUR_AUTH_KEY',
@@ -59,10 +56,19 @@ npm install @pro6pp/infer-js
59
56
 
60
57
  ### Option 2: NPM
61
58
 
59
+ 1. Create an input field.
60
+ 2. Import the `attach` function.
61
+ 3. Initialize the autocomplete on the input.
62
+
63
+ ```html
64
+ <label for="address-input">Address</label>
65
+ <input id="address-input" name="address" type="text" placeholder="Type address..." />
66
+ ```
67
+
62
68
  ```javascript
63
69
  import { attach } from '@pro6pp/infer-js';
70
+ import '@pro6pp/infer-js/dist/style.css';
64
71
 
65
- // attach to an input element directly
66
72
  const inputElement = document.querySelector('input[name="address"]');
67
73
 
68
74
  attach(inputElement, {
@@ -76,7 +82,16 @@ attach(inputElement, {
76
82
 
77
83
  ## Styling
78
84
 
79
- By default, the SDK injects a small CSS block to make the dropdown look decent. If you want to control the styling with your own CSS, set `style: 'none'` in the config.
85
+ By default, the SDK injects a small CSS block to make the dropdown look decent. If you want to control the styling with your own CSS, set `style: 'none'` in the config:
86
+
87
+ ```js
88
+ attach(inputElement, {
89
+ authKey: 'YOUR_AUTH_KEY',
90
+ country: 'NL',
91
+ style: 'none', // disables default styles
92
+ // ...
93
+ });
94
+ ```
80
95
 
81
96
  HTML created by the SDK:
82
97
 
@@ -96,9 +111,18 @@ You can target these classes in your CSS:
96
111
  .pro6pp-results {
97
112
  background: white;
98
113
  border: 1px solid #ccc;
114
+ list-style: none;
115
+ padding: 0;
116
+ margin: 0;
117
+ }
118
+
119
+ .pro6pp-item {
120
+ padding: 8px;
121
+ cursor: pointer;
99
122
  }
100
123
 
101
- .pro6pp-item:hover {
124
+ .pro6pp-item:hover,
125
+ .pro6pp-item.pro6pp-selected {
102
126
  background: #f0f0f0;
103
127
  }
104
128
  ```
@@ -1,218 +1,4 @@
1
- "use strict";
2
- var Pro6PP = (() => {
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, { get: all[name], enumerable: true });
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
-
21
- // src/index.ts
22
- var index_exports = {};
23
- __export(index_exports, {
24
- InferJS: () => InferJS,
25
- attach: () => attach
26
- });
27
-
28
- // ../core/src/core.ts
29
- var DEFAULTS = {
30
- API_URL: "https://api.pro6pp.nl/v2",
31
- LIMIT: 1e3,
32
- DEBOUNCE_MS: 300
33
- };
34
- var PATTERNS = {
35
- DIGITS_1_3: /^[0-9]{1,3}$/
36
- };
37
- var INITIAL_STATE = {
38
- query: "",
39
- stage: null,
40
- cities: [],
41
- streets: [],
42
- suggestions: [],
43
- isValid: false,
44
- isError: false,
45
- isLoading: false
46
- };
47
- var InferCore = class {
48
- constructor(config) {
49
- this.abortController = null;
50
- this.country = config.country;
51
- this.authKey = config.authKey;
52
- this.apiUrl = config.apiUrl || DEFAULTS.API_URL;
53
- this.limit = config.limit || DEFAULTS.LIMIT;
54
- this.fetcher = config.fetcher || ((url, init) => fetch(url, init));
55
- this.onStateChange = config.onStateChange || (() => {
56
- });
57
- this.onSelect = config.onSelect || (() => {
58
- });
59
- this.state = { ...INITIAL_STATE };
60
- this.debouncedFetch = this.debounce(
61
- (val) => this.executeFetch(val),
62
- DEFAULTS.DEBOUNCE_MS
63
- );
64
- }
65
- handleInput(value) {
66
- this.updateState({
67
- query: value,
68
- isValid: false,
69
- isLoading: !!value.trim()
70
- });
71
- if (this.state.stage === "final") {
72
- this.onSelect(null);
73
- }
74
- this.debouncedFetch(value);
75
- }
76
- handleKeyDown(event) {
77
- const target = event.target;
78
- const val = target.value;
79
- if (event.key === " " && this.shouldAutoInsertComma(val)) {
80
- event.preventDefault();
81
- const next = `${val.trim()}, `;
82
- this.updateQueryAndFetch(next);
83
- }
84
- }
85
- selectItem(item) {
86
- const label = typeof item === "string" ? item : item.label;
87
- const value = typeof item !== "string" ? item.value : void 0;
88
- const subtitle = typeof item !== "string" ? item.subtitle : null;
89
- if (this.state.stage === "final") {
90
- this.finishSelection(label, value);
91
- return;
92
- }
93
- this.processSelection(label, subtitle);
94
- }
95
- shouldAutoInsertComma(currentVal) {
96
- const isStartOfSegmentAndNumeric = !currentVal.includes(",") && PATTERNS.DIGITS_1_3.test(currentVal.trim());
97
- if (isStartOfSegmentAndNumeric) return true;
98
- if (this.state.stage === "house_number") {
99
- const currentFragment = this.getCurrentFragment(currentVal);
100
- return PATTERNS.DIGITS_1_3.test(currentFragment);
101
- }
102
- return false;
103
- }
104
- finishSelection(label, value) {
105
- this.updateState({ query: label, suggestions: [], cities: [], streets: [], isValid: true });
106
- this.onSelect(value || label);
107
- }
108
- processSelection(label, subtitle) {
109
- const { stage, query } = this.state;
110
- let nextQuery = query;
111
- const isContextualSelection = subtitle && (stage === "city" || stage === "street" || stage === "mixed");
112
- if (isContextualSelection) {
113
- if (stage === "city") {
114
- nextQuery = `${subtitle}, ${label}, `;
115
- } else {
116
- const prefix = this.getQueryPrefix(query);
117
- nextQuery = prefix ? `${prefix} ${label}, ${subtitle}, ` : `${label}, ${subtitle}, `;
118
- }
119
- this.updateQueryAndFetch(nextQuery);
120
- return;
121
- }
122
- if (stage === "direct" || stage === "addition") {
123
- this.finishSelection(label);
124
- this.handleInput(label);
125
- return;
126
- }
127
- const hasComma = query.includes(",");
128
- const isFirstSegment = !hasComma && (stage === "city" || stage === "street" || stage === "house_number_first");
129
- if (isFirstSegment) {
130
- nextQuery = `${label}, `;
131
- } else {
132
- nextQuery = this.replaceLastSegment(query, label);
133
- if (stage !== "house_number") {
134
- nextQuery += ", ";
135
- }
136
- }
137
- this.updateQueryAndFetch(nextQuery);
138
- }
139
- executeFetch(val) {
140
- const text = (val || "").toString();
141
- if (!text.trim()) {
142
- this.abortController?.abort();
143
- this.resetState();
144
- return;
145
- }
146
- this.updateState({ isError: false });
147
- if (this.abortController) this.abortController.abort();
148
- this.abortController = new AbortController();
149
- const url = new URL(`${this.apiUrl}/infer/${this.country.toLowerCase()}`);
150
- const params = {
151
- authKey: this.authKey,
152
- query: text,
153
- limit: this.limit.toString()
154
- };
155
- url.search = new URLSearchParams(params).toString();
156
- this.fetcher(url.toString(), { signal: this.abortController.signal }).then((res) => {
157
- if (!res.ok) throw new Error("Network error");
158
- return res.json();
159
- }).then((data) => this.mapResponseToState(data)).catch((e) => {
160
- if (e.name !== "AbortError") {
161
- this.updateState({ isError: true, isLoading: false });
162
- }
163
- });
164
- }
165
- mapResponseToState(data) {
166
- const newState = {
167
- stage: data.stage,
168
- isLoading: false
169
- };
170
- if (data.stage === "mixed") {
171
- newState.cities = data.cities || [];
172
- newState.streets = data.streets || [];
173
- newState.suggestions = [];
174
- } else {
175
- newState.suggestions = data.suggestions || [];
176
- newState.cities = [];
177
- newState.streets = [];
178
- }
179
- newState.isValid = data.stage === "final";
180
- this.updateState(newState);
181
- }
182
- updateQueryAndFetch(nextQuery) {
183
- this.updateState({ query: nextQuery, suggestions: [], cities: [], streets: [] });
184
- this.handleInput(nextQuery);
185
- }
186
- replaceLastSegment(fullText, newSegment) {
187
- const lastCommaIndex = fullText.lastIndexOf(",");
188
- if (lastCommaIndex === -1) return newSegment;
189
- return `${fullText.slice(0, lastCommaIndex + 1)} ${newSegment}`.trim();
190
- }
191
- getQueryPrefix(q) {
192
- const lastComma = q.lastIndexOf(",");
193
- return lastComma === -1 ? "" : q.slice(0, lastComma + 1).trimEnd();
194
- }
195
- getCurrentFragment(q) {
196
- return (q.split(",").slice(-1)[0] ?? "").trim();
197
- }
198
- resetState() {
199
- this.updateState({ ...INITIAL_STATE, query: this.state.query });
200
- }
201
- updateState(updates) {
202
- this.state = { ...this.state, ...updates };
203
- this.onStateChange(this.state);
204
- }
205
- debounce(func, wait) {
206
- let timeout;
207
- return (...args) => {
208
- if (timeout) clearTimeout(timeout);
209
- timeout = setTimeout(() => func.apply(this, args), wait);
210
- };
211
- }
212
- };
213
-
214
- // src/index.ts
215
- var DEFAULT_STYLES = `
1
+ "use strict";var Pro6PP=(()=>{var l=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var y=(n,t)=>{for(var e in t)l(n,e,{get:t[e],enumerable:!0})},S=(n,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of m(t))!g.call(n,s)&&s!==e&&l(n,s,{get:()=>t[s],enumerable:!(i=f(t,s))||i.enumerable});return n};var v=n=>S(l({},"__esModule",{value:!0}),n);var C={};y(C,{InferJS:()=>p,attach:()=>b});var u={API_URL:"https://api.pro6pp.nl/v2",LIMIT:1e3,DEBOUNCE_MS:300},c={DIGITS_1_3:/^[0-9]{1,3}$/},d={query:"",stage:null,cities:[],streets:[],suggestions:[],isValid:!1,isError:!1,isLoading:!1},a=class{constructor(t){this.abortController=null;this.country=t.country,this.authKey=t.authKey,this.apiUrl=t.apiUrl||u.API_URL,this.limit=t.limit||u.LIMIT,this.fetcher=t.fetcher||((e,i)=>fetch(e,i)),this.onStateChange=t.onStateChange||(()=>{}),this.onSelect=t.onSelect||(()=>{}),this.state={...d},this.debouncedFetch=this.debounce(e=>this.executeFetch(e),u.DEBOUNCE_MS)}handleInput(t){this.updateState({query:t,isValid:!1,isLoading:!!t.trim()}),this.state.stage==="final"&&this.onSelect(null),this.debouncedFetch(t)}handleKeyDown(t){let i=t.target.value;if(t.key===" "&&this.shouldAutoInsertComma(i)){t.preventDefault();let s=`${i.trim()}, `;this.updateQueryAndFetch(s)}}selectItem(t){let e=typeof t=="string"?t:t.label,i=typeof t!="string"?t.value:void 0,s=typeof t!="string"?t.subtitle:null;if(this.state.stage==="final"){this.finishSelection(e,i);return}this.processSelection(e,s)}shouldAutoInsertComma(t){if(!t.includes(",")&&c.DIGITS_1_3.test(t.trim()))return!0;if(this.state.stage==="house_number"){let i=this.getCurrentFragment(t);return c.DIGITS_1_3.test(i)}return!1}finishSelection(t,e){this.updateState({query:t,suggestions:[],cities:[],streets:[],isValid:!0}),this.onSelect(e||t)}processSelection(t,e){let{stage:i,query:s}=this.state,r=s;if(e&&(i==="city"||i==="street"||i==="mixed")){if(i==="city")r=`${e}, ${t}, `;else{let h=this.getQueryPrefix(s);r=h?`${h} ${t}, ${e}, `:`${t}, ${e}, `}this.updateQueryAndFetch(r);return}if(i==="direct"||i==="addition"){this.finishSelection(t),this.handleInput(t);return}!s.includes(",")&&(i==="city"||i==="street"||i==="house_number_first")?r=`${t}, `:(r=this.replaceLastSegment(s,t),i!=="house_number"&&(r+=", ")),this.updateQueryAndFetch(r)}executeFetch(t){let e=(t||"").toString();if(!e.trim()){this.abortController?.abort(),this.resetState();return}this.updateState({isError:!1}),this.abortController&&this.abortController.abort(),this.abortController=new AbortController;let i=new URL(`${this.apiUrl}/infer/${this.country.toLowerCase()}`),s={authKey:this.authKey,query:e,limit:this.limit.toString()};i.search=new URLSearchParams(s).toString(),this.fetcher(i.toString(),{signal:this.abortController.signal}).then(r=>{if(!r.ok)throw new Error("Network error");return r.json()}).then(r=>this.mapResponseToState(r)).catch(r=>{r.name!=="AbortError"&&this.updateState({isError:!0,isLoading:!1})})}mapResponseToState(t){let e={stage:t.stage,isLoading:!1};t.stage==="mixed"?(e.cities=t.cities||[],e.streets=t.streets||[],e.suggestions=[]):(e.suggestions=t.suggestions||[],e.cities=[],e.streets=[]),e.isValid=t.stage==="final",this.updateState(e)}updateQueryAndFetch(t){this.updateState({query:t,suggestions:[],cities:[],streets:[]}),this.handleInput(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){return(t.split(",").slice(-1)[0]??"").trim()}resetState(){this.updateState({...d,query:this.state.query})}updateState(t){this.state={...this.state,...t},this.onStateChange(this.state)}debounce(t,e){let i;return(...s)=>{i&&clearTimeout(i),i=setTimeout(()=>t.apply(this,s),e)}}};var I=`
216
2
  .pro6pp-wrapper {
217
3
  position: relative;
218
4
  display: block;
@@ -262,105 +48,4 @@ var Pro6PP = (() => {
262
48
  color: #64748b;
263
49
  margin-top: 2px;
264
50
  }
265
- `;
266
- var InferJS = class {
267
- constructor(target, config) {
268
- const el = typeof target === "string" ? document.querySelector(target) : target;
269
- if (!el || !(el instanceof HTMLInputElement)) {
270
- throw new Error(`InferJS: Target element not found or is not an input.`);
271
- }
272
- this.input = el;
273
- this.useDefaultStyles = config.style !== "none";
274
- if (this.useDefaultStyles) {
275
- this.injectStyles();
276
- }
277
- this.core = new InferCore({
278
- ...config,
279
- onStateChange: (state) => this.render(state),
280
- onSelect: (selection) => {
281
- if (typeof selection === "string") {
282
- this.input.value = selection;
283
- } else if (selection && typeof selection === "object") {
284
- this.input.value = this.core.state.query;
285
- }
286
- if (config.onSelect) config.onSelect(selection);
287
- }
288
- });
289
- this.setupDOM();
290
- this.bindEvents();
291
- }
292
- injectStyles() {
293
- const styleId = "pro6pp-infer-styles";
294
- if (!document.getElementById(styleId)) {
295
- const styleEl = document.createElement("style");
296
- styleEl.id = styleId;
297
- styleEl.textContent = DEFAULT_STYLES;
298
- document.head.appendChild(styleEl);
299
- }
300
- }
301
- setupDOM() {
302
- this.wrapper = document.createElement("div");
303
- this.wrapper.className = "pro6pp-wrapper";
304
- this.input.parentNode?.insertBefore(this.wrapper, this.input);
305
- this.wrapper.appendChild(this.input);
306
- this.list = document.createElement("ul");
307
- this.list.className = "pro6pp-dropdown";
308
- this.list.style.display = "none";
309
- this.wrapper.appendChild(this.list);
310
- }
311
- bindEvents() {
312
- this.input.addEventListener("input", (e) => {
313
- const val = e.target.value;
314
- this.core.handleInput(val);
315
- });
316
- this.input.addEventListener("keydown", (e) => {
317
- this.core.handleKeyDown(e);
318
- });
319
- document.addEventListener("click", (e) => {
320
- if (!this.wrapper.contains(e.target)) {
321
- this.list.style.display = "none";
322
- }
323
- });
324
- }
325
- render(state) {
326
- if (this.input.value !== state.query) {
327
- this.input.value = state.query;
328
- }
329
- this.list.innerHTML = "";
330
- const items = [
331
- ...state.cities.map((c) => ({ item: c, type: "city" })),
332
- ...state.streets.map((s) => ({ item: s, type: "street" })),
333
- ...state.suggestions.map((s) => ({ item: s, type: "suggestion" }))
334
- ];
335
- if (items.length === 0) {
336
- this.list.style.display = "none";
337
- return;
338
- }
339
- this.list.style.display = "block";
340
- items.forEach(({ item }) => {
341
- const li = document.createElement("li");
342
- li.className = "pro6pp-item";
343
- li.setAttribute("role", "option");
344
- const labelSpan = document.createElement("span");
345
- labelSpan.className = "pro6pp-item__label";
346
- labelSpan.textContent = item.label;
347
- li.appendChild(labelSpan);
348
- if (item.subtitle) {
349
- const subSpan = document.createElement("span");
350
- subSpan.className = "pro6pp-item__subtitle";
351
- subSpan.textContent = item.subtitle;
352
- li.appendChild(subSpan);
353
- }
354
- li.onclick = (e) => {
355
- e.stopPropagation();
356
- this.core.selectItem(item);
357
- };
358
- this.list.appendChild(li);
359
- });
360
- }
361
- };
362
- function attach(target, config) {
363
- return new InferJS(target, config);
364
- }
365
- return __toCommonJS(index_exports);
366
- })();
51
+ `,p=class{constructor(t,e){let i=typeof t=="string"?document.querySelector(t):t;if(!i||!(i instanceof HTMLInputElement))throw new Error("InferJS: Target element not found or is not an input.");this.input=i,this.useDefaultStyles=e.style!=="none",this.useDefaultStyles&&this.injectStyles(),this.core=new a({...e,onStateChange:s=>this.render(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.setupDOM(),this.bindEvents()}injectStyles(){let t="pro6pp-infer-styles";if(!document.getElementById(t)){let e=document.createElement("style");e.id=t,e.textContent=I,document.head.appendChild(e)}}setupDOM(){this.wrapper=document.createElement("div"),this.wrapper.className="pro6pp-wrapper",this.input.parentNode?.insertBefore(this.wrapper,this.input),this.wrapper.appendChild(this.input),this.list=document.createElement("ul"),this.list.className="pro6pp-dropdown",this.list.style.display="none",this.wrapper.appendChild(this.list)}bindEvents(){this.input.addEventListener("input",t=>{let e=t.target.value;this.core.handleInput(e)}),this.input.addEventListener("keydown",t=>{this.core.handleKeyDown(t)}),document.addEventListener("click",t=>{this.wrapper.contains(t.target)||(this.list.style.display="none")})}render(t){this.input.value!==t.query&&(this.input.value=t.query),this.list.innerHTML="";let e=[...t.cities.map(i=>({item:i,type:"city"})),...t.streets.map(i=>({item:i,type:"street"})),...t.suggestions.map(i=>({item:i,type:"suggestion"}))];if(e.length===0){this.list.style.display="none";return}this.list.style.display="block",e.forEach(({item:i})=>{let s=document.createElement("li");s.className="pro6pp-item",s.setAttribute("role","option");let r=document.createElement("span");if(r.className="pro6pp-item__label",r.textContent=i.label,s.appendChild(r),i.subtitle){let o=document.createElement("span");o.className="pro6pp-item__subtitle",o.textContent=i.subtitle,s.appendChild(o)}s.onclick=o=>{o.stopPropagation(),this.core.selectItem(i)},this.list.appendChild(s)})}};function b(n,t){return new p(n,t)}return v(C);})();
package/dist/index.js ADDED
@@ -0,0 +1,51 @@
1
+ "use strict";var l=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var u=Object.prototype.hasOwnProperty;var h=(p,e)=>{for(var n in e)l(p,n,{get:e[n],enumerable:!0})},f=(p,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of c(e))!u.call(p,t)&&t!==n&&l(p,t,{get:()=>e[t],enumerable:!(i=d(e,t))||i.enumerable});return p};var m=p=>f(l({},"__esModule",{value:!0}),p);var g={};h(g,{InferJS:()=>o,attach:()=>b});module.exports=m(g);var a=require("@pro6pp/infer-core"),y=`
2
+ .pro6pp-wrapper {
3
+ position: relative;
4
+ display: block;
5
+ width: 100%;
6
+ }
7
+
8
+ .pro6pp-dropdown {
9
+ position: absolute;
10
+ top: 100%;
11
+ left: 0;
12
+ right: 0;
13
+ z-index: 10000;
14
+ background-color: #ffffff;
15
+ border: 1px solid #e2e8f0;
16
+ border-radius: 0 0 4px 4px;
17
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
18
+ list-style: none;
19
+ margin: 0;
20
+ padding: 0;
21
+ max-height: 250px;
22
+ overflow-y: auto;
23
+ }
24
+
25
+ .pro6pp-item {
26
+ padding: 10px 12px;
27
+ cursor: pointer;
28
+ border-bottom: 1px solid #f1f5f9;
29
+ font-family: inherit;
30
+ font-size: 14px;
31
+ line-height: 1.4;
32
+ color: #1e293b;
33
+ transition: background-color 0.15s ease;
34
+ }
35
+
36
+ .pro6pp-item:last-child {
37
+ border-bottom: none;
38
+ }
39
+
40
+ .pro6pp-item:hover, .pro6pp-item--active {
41
+ background-color: #f8fafc;
42
+ color: #0f172a;
43
+ }
44
+
45
+ .pro6pp-item__subtitle {
46
+ display: block;
47
+ font-size: 0.85em;
48
+ color: #64748b;
49
+ margin-top: 2px;
50
+ }
51
+ `,o=class{constructor(e,n){let i=typeof e=="string"?document.querySelector(e):e;if(!i||!(i instanceof HTMLInputElement))throw new Error("InferJS: Target element not found or is not an input.");this.input=i,this.useDefaultStyles=n.style!=="none",this.useDefaultStyles&&this.injectStyles(),this.core=new a.InferCore({...n,onStateChange:t=>this.render(t),onSelect:t=>{typeof t=="string"?this.input.value=t:t&&typeof t=="object"&&(this.input.value=this.core.state.query),n.onSelect&&n.onSelect(t)}}),this.setupDOM(),this.bindEvents()}injectStyles(){let e="pro6pp-infer-styles";if(!document.getElementById(e)){let n=document.createElement("style");n.id=e,n.textContent=y,document.head.appendChild(n)}}setupDOM(){this.wrapper=document.createElement("div"),this.wrapper.className="pro6pp-wrapper",this.input.parentNode?.insertBefore(this.wrapper,this.input),this.wrapper.appendChild(this.input),this.list=document.createElement("ul"),this.list.className="pro6pp-dropdown",this.list.style.display="none",this.wrapper.appendChild(this.list)}bindEvents(){this.input.addEventListener("input",e=>{let n=e.target.value;this.core.handleInput(n)}),this.input.addEventListener("keydown",e=>{this.core.handleKeyDown(e)}),document.addEventListener("click",e=>{this.wrapper.contains(e.target)||(this.list.style.display="none")})}render(e){this.input.value!==e.query&&(this.input.value=e.query),this.list.innerHTML="";let n=[...e.cities.map(i=>({item:i,type:"city"})),...e.streets.map(i=>({item:i,type:"street"})),...e.suggestions.map(i=>({item:i,type:"suggestion"}))];if(n.length===0){this.list.style.display="none";return}this.list.style.display="block",n.forEach(({item:i})=>{let t=document.createElement("li");t.className="pro6pp-item",t.setAttribute("role","option");let r=document.createElement("span");if(r.className="pro6pp-item__label",r.textContent=i.label,t.appendChild(r),i.subtitle){let s=document.createElement("span");s.className="pro6pp-item__subtitle",s.textContent=i.subtitle,t.appendChild(s)}t.onclick=s=>{s.stopPropagation(),this.core.selectItem(i)},this.list.appendChild(t)})}};function b(p,e){return new o(p,e)}0&&(module.exports={InferJS,attach});
package/dist/index.mjs CHANGED
@@ -1,6 +1,4 @@
1
- // src/index.ts
2
- import { InferCore } from "@pro6pp/infer-core";
3
- var DEFAULT_STYLES = `
1
+ import{InferCore as l}from"@pro6pp/infer-core";var a=`
4
2
  .pro6pp-wrapper {
5
3
  position: relative;
6
4
  display: block;
@@ -50,107 +48,4 @@ var DEFAULT_STYLES = `
50
48
  color: #64748b;
51
49
  margin-top: 2px;
52
50
  }
53
- `;
54
- var InferJS = class {
55
- constructor(target, config) {
56
- const el = typeof target === "string" ? document.querySelector(target) : target;
57
- if (!el || !(el instanceof HTMLInputElement)) {
58
- throw new Error(`InferJS: Target element not found or is not an input.`);
59
- }
60
- this.input = el;
61
- this.useDefaultStyles = config.style !== "none";
62
- if (this.useDefaultStyles) {
63
- this.injectStyles();
64
- }
65
- this.core = new InferCore({
66
- ...config,
67
- onStateChange: (state) => this.render(state),
68
- onSelect: (selection) => {
69
- if (typeof selection === "string") {
70
- this.input.value = selection;
71
- } else if (selection && typeof selection === "object") {
72
- this.input.value = this.core.state.query;
73
- }
74
- if (config.onSelect) config.onSelect(selection);
75
- }
76
- });
77
- this.setupDOM();
78
- this.bindEvents();
79
- }
80
- injectStyles() {
81
- const styleId = "pro6pp-infer-styles";
82
- if (!document.getElementById(styleId)) {
83
- const styleEl = document.createElement("style");
84
- styleEl.id = styleId;
85
- styleEl.textContent = DEFAULT_STYLES;
86
- document.head.appendChild(styleEl);
87
- }
88
- }
89
- setupDOM() {
90
- this.wrapper = document.createElement("div");
91
- this.wrapper.className = "pro6pp-wrapper";
92
- this.input.parentNode?.insertBefore(this.wrapper, this.input);
93
- this.wrapper.appendChild(this.input);
94
- this.list = document.createElement("ul");
95
- this.list.className = "pro6pp-dropdown";
96
- this.list.style.display = "none";
97
- this.wrapper.appendChild(this.list);
98
- }
99
- bindEvents() {
100
- this.input.addEventListener("input", (e) => {
101
- const val = e.target.value;
102
- this.core.handleInput(val);
103
- });
104
- this.input.addEventListener("keydown", (e) => {
105
- this.core.handleKeyDown(e);
106
- });
107
- document.addEventListener("click", (e) => {
108
- if (!this.wrapper.contains(e.target)) {
109
- this.list.style.display = "none";
110
- }
111
- });
112
- }
113
- render(state) {
114
- if (this.input.value !== state.query) {
115
- this.input.value = state.query;
116
- }
117
- this.list.innerHTML = "";
118
- const items = [
119
- ...state.cities.map((c) => ({ item: c, type: "city" })),
120
- ...state.streets.map((s) => ({ item: s, type: "street" })),
121
- ...state.suggestions.map((s) => ({ item: s, type: "suggestion" }))
122
- ];
123
- if (items.length === 0) {
124
- this.list.style.display = "none";
125
- return;
126
- }
127
- this.list.style.display = "block";
128
- items.forEach(({ item }) => {
129
- const li = document.createElement("li");
130
- li.className = "pro6pp-item";
131
- li.setAttribute("role", "option");
132
- const labelSpan = document.createElement("span");
133
- labelSpan.className = "pro6pp-item__label";
134
- labelSpan.textContent = item.label;
135
- li.appendChild(labelSpan);
136
- if (item.subtitle) {
137
- const subSpan = document.createElement("span");
138
- subSpan.className = "pro6pp-item__subtitle";
139
- subSpan.textContent = item.subtitle;
140
- li.appendChild(subSpan);
141
- }
142
- li.onclick = (e) => {
143
- e.stopPropagation();
144
- this.core.selectItem(item);
145
- };
146
- this.list.appendChild(li);
147
- });
148
- }
149
- };
150
- function attach(target, config) {
151
- return new InferJS(target, config);
152
- }
153
- export {
154
- InferJS,
155
- attach
156
- };
51
+ `,o=class{constructor(e,i){let t=typeof e=="string"?document.querySelector(e):e;if(!t||!(t instanceof HTMLInputElement))throw new Error("InferJS: Target element not found or is not an input.");this.input=t,this.useDefaultStyles=i.style!=="none",this.useDefaultStyles&&this.injectStyles(),this.core=new l({...i,onStateChange:n=>this.render(n),onSelect:n=>{typeof n=="string"?this.input.value=n:n&&typeof n=="object"&&(this.input.value=this.core.state.query),i.onSelect&&i.onSelect(n)}}),this.setupDOM(),this.bindEvents()}injectStyles(){let e="pro6pp-infer-styles";if(!document.getElementById(e)){let i=document.createElement("style");i.id=e,i.textContent=a,document.head.appendChild(i)}}setupDOM(){this.wrapper=document.createElement("div"),this.wrapper.className="pro6pp-wrapper",this.input.parentNode?.insertBefore(this.wrapper,this.input),this.wrapper.appendChild(this.input),this.list=document.createElement("ul"),this.list.className="pro6pp-dropdown",this.list.style.display="none",this.wrapper.appendChild(this.list)}bindEvents(){this.input.addEventListener("input",e=>{let i=e.target.value;this.core.handleInput(i)}),this.input.addEventListener("keydown",e=>{this.core.handleKeyDown(e)}),document.addEventListener("click",e=>{this.wrapper.contains(e.target)||(this.list.style.display="none")})}render(e){this.input.value!==e.query&&(this.input.value=e.query),this.list.innerHTML="";let i=[...e.cities.map(t=>({item:t,type:"city"})),...e.streets.map(t=>({item:t,type:"street"})),...e.suggestions.map(t=>({item:t,type:"suggestion"}))];if(i.length===0){this.list.style.display="none";return}this.list.style.display="block",i.forEach(({item:t})=>{let n=document.createElement("li");n.className="pro6pp-item",n.setAttribute("role","option");let s=document.createElement("span");if(s.className="pro6pp-item__label",s.textContent=t.label,n.appendChild(s),t.subtitle){let p=document.createElement("span");p.className="pro6pp-item__subtitle",p.textContent=t.subtitle,n.appendChild(p)}n.onclick=p=>{p.stopPropagation(),this.core.selectItem(t)},this.list.appendChild(n)})}};function h(r,e){return new o(r,e)}export{o as InferJS,h as attach};
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@pro6pp/infer-js",
3
- "version": "0.0.2-beta.0",
3
+ "description": "Framework-agnostic JavaScript SDK for the Pro6PP Infer API.",
4
+ "version": "0.0.2-beta.1",
4
5
  "main": "./dist/index.js",
5
6
  "module": "./dist/index.mjs",
6
7
  "types": "./dist/index.d.ts",
@@ -11,12 +12,12 @@
11
12
  "README.md"
12
13
  ],
13
14
  "scripts": {
14
- "build": "tsup src/index.ts --format iife,esm --dts --global-name Pro6PP --clean",
15
- "dev": "tsup src/index.ts --format iife,esm --dts --watch --global-name Pro6PP",
15
+ "build": "tsup",
16
+ "dev": "tsup --watch",
16
17
  "type-check": "tsc --noEmit"
17
18
  },
18
19
  "dependencies": {
19
- "@pro6pp/infer-core": "0.0.2-beta.0"
20
+ "@pro6pp/infer-core": "0.0.2-beta.1"
20
21
  },
21
22
  "devDependencies": {
22
23
  "tsup": "^8.0.0",
@@ -28,6 +29,7 @@
28
29
  "license": "MIT",
29
30
  "repository": {
30
31
  "type": "git",
31
- "url": "https://gitlab.d-centralize.nl/dc/pro6pp/pro6pp-infer-sdk"
32
+ "url": "https://github.com/pro6pp/infer-sdk",
33
+ "directory": "packages/js"
32
34
  }
33
35
  }