@pro6pp/infer-react 0.0.2-beta.13 → 0.0.2-beta.15

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/dist/index.cjs CHANGED
@@ -47,7 +47,8 @@ var DEFAULTS = {
47
47
  MAX_RETRIES: 0
48
48
  };
49
49
  var PATTERNS = {
50
- DIGITS_1_3: /^[0-9]{1,3}$/
50
+ DIGITS_1_3: /^[0-9]{1,3}$/,
51
+ STREET_NUMBER_PREFIX: /^(\d+)\s*,\s*$/
51
52
  };
52
53
  var INITIAL_STATE = {
53
54
  query: "",
@@ -56,6 +57,7 @@ var INITIAL_STATE = {
56
57
  streets: [],
57
58
  suggestions: [],
58
59
  isValid: false,
60
+ value: null,
59
61
  isError: false,
60
62
  isLoading: false,
61
63
  hasMore: false,
@@ -111,9 +113,11 @@ var InferCore = class {
111
113
  this.updateState({
112
114
  query: value,
113
115
  isValid: false,
116
+ value: null,
114
117
  isLoading: !!value.trim(),
115
118
  selectedSuggestionIndex: -1,
116
- hasMore: false
119
+ hasMore: false,
120
+ stage: isEditingFinal ? null : this.state.stage
117
121
  });
118
122
  if (isEditingFinal) {
119
123
  this.onSelect(null);
@@ -228,6 +232,7 @@ var InferCore = class {
228
232
  cities: [],
229
233
  streets: [],
230
234
  isValid: true,
235
+ value: value || null,
231
236
  stage: "final",
232
237
  hasMore: false
233
238
  });
@@ -243,10 +248,20 @@ var InferCore = class {
243
248
  } else {
244
249
  const prefix = this.getQueryPrefix(query);
245
250
  const shouldAddSubtitle = !prefix || !prefix.includes(subtitle);
251
+ let effectivePrefix = prefix;
252
+ if (prefix && subtitle) {
253
+ const prefixNumMatch = prefix.match(PATTERNS.STREET_NUMBER_PREFIX);
254
+ if (prefixNumMatch) {
255
+ const num = prefixNumMatch[1];
256
+ if (subtitle.startsWith(num)) {
257
+ effectivePrefix = "";
258
+ }
259
+ }
260
+ }
246
261
  if (shouldAddSubtitle) {
247
- nextQuery = prefix ? `${prefix} ${text}, ${subtitle}, ` : `${text}, ${subtitle}, `;
262
+ nextQuery = effectivePrefix ? `${effectivePrefix} ${text}, ${subtitle}, ` : `${text}, ${subtitle}, `;
248
263
  } else {
249
- nextQuery = prefix ? `${prefix} ${text}, ` : `${text}, `;
264
+ nextQuery = effectivePrefix ? `${effectivePrefix} ${text}, ` : `${text}, `;
250
265
  }
251
266
  }
252
267
  this.updateQueryAndFetch(nextQuery);
@@ -283,10 +298,12 @@ var InferCore = class {
283
298
  const currentSignal = this.abortController?.signal;
284
299
  const baseUrl = this.explicitApiUrl ? this.explicitApiUrl : `${DEFAULTS.API_URL}/infer/${this.country.toLowerCase()}`;
285
300
  const params = new URLSearchParams({
286
- country: this.country.toLowerCase(),
287
301
  query: text,
288
302
  limit: this.currentLimit.toString()
289
303
  });
304
+ if (this.explicitApiUrl) {
305
+ params.append("country", this.country.toLowerCase());
306
+ }
290
307
  if (this.authKey) {
291
308
  params.set("authKey", this.authKey);
292
309
  }
@@ -339,7 +356,11 @@ var InferCore = class {
339
356
  if (data.stage === "mixed") {
340
357
  newState.cities = data.cities || [];
341
358
  newState.streets = data.streets || [];
342
- newState.suggestions = [];
359
+ if (newState.cities?.length === 0 && newState.streets?.length === 0) {
360
+ newState.suggestions = uniqueSuggestions;
361
+ } else {
362
+ newState.suggestions = [];
363
+ }
343
364
  } else {
344
365
  newState.suggestions = uniqueSuggestions;
345
366
  newState.cities = [];
@@ -352,8 +373,16 @@ var InferCore = class {
352
373
  }
353
374
  }
354
375
  updateQueryAndFetch(nextQuery) {
355
- this.updateState({ query: nextQuery, suggestions: [], cities: [], streets: [] });
356
- this.updateState({ isLoading: true, isValid: false, hasMore: false });
376
+ this.updateState({
377
+ query: nextQuery,
378
+ suggestions: [],
379
+ cities: [],
380
+ streets: [],
381
+ isValid: false,
382
+ value: null,
383
+ isLoading: true,
384
+ hasMore: false
385
+ });
357
386
  this.debouncedFetch(nextQuery);
358
387
  }
359
388
  replaceLastSegment(fullText, newSegment) {
@@ -642,7 +671,18 @@ var HighlightedText = ({ text, query }) => {
642
671
  ));
643
672
  };
644
673
  function useInfer(config) {
645
- const [state, setState] = (0, import_react.useState)(INITIAL_STATE);
674
+ const [state, setState] = (0, import_react.useState)(() => {
675
+ if (config.initialValue) {
676
+ return {
677
+ ...INITIAL_STATE,
678
+ value: config.initialValue,
679
+ query: `${config.initialValue.street} ${config.initialValue.street_number}, ${config.initialValue.city}`,
680
+ isValid: true,
681
+ stage: "final"
682
+ };
683
+ }
684
+ return INITIAL_STATE;
685
+ });
646
686
  const callbacksRef = (0, import_react.useRef)({
647
687
  onStateChange: config.onStateChange,
648
688
  onSelect: config.onSelect
@@ -654,7 +694,7 @@ function useInfer(config) {
654
694
  };
655
695
  }, [config.onStateChange, config.onSelect]);
656
696
  const core = (0, import_react.useMemo)(() => {
657
- return new InferCore({
697
+ const instance = new InferCore({
658
698
  ...config,
659
699
  onStateChange: (newState) => {
660
700
  setState({ ...newState });
@@ -664,6 +704,12 @@ function useInfer(config) {
664
704
  callbacksRef.current.onSelect?.(selection);
665
705
  }
666
706
  });
707
+ if (config.initialValue) {
708
+ const address = config.initialValue;
709
+ const label = `${address.street} ${address.street_number}, ${address.city}`;
710
+ instance.selectItem({ label, value: address });
711
+ }
712
+ return instance;
667
713
  }, [
668
714
  config.country,
669
715
  config.authKey,
@@ -671,10 +717,16 @@ function useInfer(config) {
671
717
  config.fetcher,
672
718
  config.limit,
673
719
  config.debounceMs,
674
- config.maxRetries
720
+ config.maxRetries,
721
+ config.initialValue
675
722
  ]);
723
+ const setValue = (address) => {
724
+ if (!address) return;
725
+ const label = `${address.street} ${address.street_number}, ${address.city}`;
726
+ core.selectItem({ label, value: address });
727
+ };
676
728
  return {
677
- /** The current UI state (suggestions, loading status, query, etc.). */
729
+ /** The current UI state (suggestions, loading status, query, value, etc.). */
678
730
  state,
679
731
  /** The raw InferCore instance for manual control. */
680
732
  core,
@@ -684,9 +736,11 @@ function useInfer(config) {
684
736
  onChange: (e) => core.handleInput(e.target.value),
685
737
  onKeyDown: (e) => core.handleKeyDown(e)
686
738
  },
687
- /** Function to manually select a specific suggestion. */
739
+ /** Manually select a specific suggestion. */
688
740
  selectItem: (item) => core.selectItem(item),
689
- /** Function to load more results. */
741
+ /** Programmatically set the address value. */
742
+ setValue,
743
+ /** Load more results. */
690
744
  loadMore: () => core.loadMore()
691
745
  };
692
746
  }
package/dist/index.d.cts CHANGED
@@ -1,14 +1,23 @@
1
1
  import React from 'react';
2
- import { InferConfig, InferState, InferCore, InferResult } from '@pro6pp/infer-core';
2
+ import { InferConfig, AddressValue, InferState, InferCore, InferResult } from '@pro6pp/infer-core';
3
3
  export { AddressValue, CountryCode, Fetcher, InferConfig, InferResult, InferState, Stage } from '@pro6pp/infer-core';
4
4
 
5
+ /**
6
+ * Extended configuration for the React hook.
7
+ */
8
+ interface UseInferConfig extends InferConfig {
9
+ /**
10
+ * Initial address value to pre-fill the state with.
11
+ */
12
+ initialValue?: AddressValue;
13
+ }
5
14
  /**
6
15
  * A headless React hook that provides the logic for address search using the Infer API.
7
16
  * @param config The engine configuration (authKey, country, etc.).
8
17
  * @returns An object containing the current state, the core instance, and pre-bound input props.
9
18
  */
10
- declare function useInfer(config: InferConfig): {
11
- /** The current UI state (suggestions, loading status, query, etc.). */
19
+ declare function useInfer(config: UseInferConfig): {
20
+ /** The current UI state (suggestions, loading status, query, value, etc.). */
12
21
  state: InferState;
13
22
  /** The raw InferCore instance for manual control. */
14
23
  core: InferCore;
@@ -18,15 +27,17 @@ declare function useInfer(config: InferConfig): {
18
27
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
19
28
  onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;
20
29
  };
21
- /** Function to manually select a specific suggestion. */
30
+ /** Manually select a specific suggestion. */
22
31
  selectItem: (item: InferResult | string) => boolean;
23
- /** Function to load more results. */
32
+ /** Programmatically set the address value. */
33
+ setValue: (address: AddressValue) => void;
34
+ /** Load more results. */
24
35
  loadMore: () => void;
25
36
  };
26
37
  /**
27
38
  * Props for the Pro6PPInfer component.
28
39
  */
29
- interface Pro6PPInferProps extends InferConfig {
40
+ interface Pro6PPInferProps extends UseInferConfig {
30
41
  /** Optional CSS class for the wrapper div. */
31
42
  className?: string;
32
43
  /** Optional inline styles for the wrapper div. */
@@ -65,4 +76,4 @@ interface Pro6PPInferProps extends InferConfig {
65
76
  */
66
77
  declare const Pro6PPInfer: React.ForwardRefExoticComponent<Pro6PPInferProps & React.RefAttributes<HTMLInputElement>>;
67
78
 
68
- export { Pro6PPInfer, type Pro6PPInferProps, useInfer };
79
+ export { Pro6PPInfer, type Pro6PPInferProps, type UseInferConfig, useInfer };
package/dist/index.d.ts CHANGED
@@ -1,14 +1,23 @@
1
1
  import React from 'react';
2
- import { InferConfig, InferState, InferCore, InferResult } from '@pro6pp/infer-core';
2
+ import { InferConfig, AddressValue, InferState, InferCore, InferResult } from '@pro6pp/infer-core';
3
3
  export { AddressValue, CountryCode, Fetcher, InferConfig, InferResult, InferState, Stage } from '@pro6pp/infer-core';
4
4
 
5
+ /**
6
+ * Extended configuration for the React hook.
7
+ */
8
+ interface UseInferConfig extends InferConfig {
9
+ /**
10
+ * Initial address value to pre-fill the state with.
11
+ */
12
+ initialValue?: AddressValue;
13
+ }
5
14
  /**
6
15
  * A headless React hook that provides the logic for address search using the Infer API.
7
16
  * @param config The engine configuration (authKey, country, etc.).
8
17
  * @returns An object containing the current state, the core instance, and pre-bound input props.
9
18
  */
10
- declare function useInfer(config: InferConfig): {
11
- /** The current UI state (suggestions, loading status, query, etc.). */
19
+ declare function useInfer(config: UseInferConfig): {
20
+ /** The current UI state (suggestions, loading status, query, value, etc.). */
12
21
  state: InferState;
13
22
  /** The raw InferCore instance for manual control. */
14
23
  core: InferCore;
@@ -18,15 +27,17 @@ declare function useInfer(config: InferConfig): {
18
27
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
19
28
  onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;
20
29
  };
21
- /** Function to manually select a specific suggestion. */
30
+ /** Manually select a specific suggestion. */
22
31
  selectItem: (item: InferResult | string) => boolean;
23
- /** Function to load more results. */
32
+ /** Programmatically set the address value. */
33
+ setValue: (address: AddressValue) => void;
34
+ /** Load more results. */
24
35
  loadMore: () => void;
25
36
  };
26
37
  /**
27
38
  * Props for the Pro6PPInfer component.
28
39
  */
29
- interface Pro6PPInferProps extends InferConfig {
40
+ interface Pro6PPInferProps extends UseInferConfig {
30
41
  /** Optional CSS class for the wrapper div. */
31
42
  className?: string;
32
43
  /** Optional inline styles for the wrapper div. */
@@ -65,4 +76,4 @@ interface Pro6PPInferProps extends InferConfig {
65
76
  */
66
77
  declare const Pro6PPInfer: React.ForwardRefExoticComponent<Pro6PPInferProps & React.RefAttributes<HTMLInputElement>>;
67
78
 
68
- export { Pro6PPInfer, type Pro6PPInferProps, useInfer };
79
+ export { Pro6PPInfer, type Pro6PPInferProps, type UseInferConfig, useInfer };
package/dist/index.js CHANGED
@@ -21,7 +21,8 @@ var DEFAULTS = {
21
21
  MAX_RETRIES: 0
22
22
  };
23
23
  var PATTERNS = {
24
- DIGITS_1_3: /^[0-9]{1,3}$/
24
+ DIGITS_1_3: /^[0-9]{1,3}$/,
25
+ STREET_NUMBER_PREFIX: /^(\d+)\s*,\s*$/
25
26
  };
26
27
  var INITIAL_STATE = {
27
28
  query: "",
@@ -30,6 +31,7 @@ var INITIAL_STATE = {
30
31
  streets: [],
31
32
  suggestions: [],
32
33
  isValid: false,
34
+ value: null,
33
35
  isError: false,
34
36
  isLoading: false,
35
37
  hasMore: false,
@@ -85,9 +87,11 @@ var InferCore = class {
85
87
  this.updateState({
86
88
  query: value,
87
89
  isValid: false,
90
+ value: null,
88
91
  isLoading: !!value.trim(),
89
92
  selectedSuggestionIndex: -1,
90
- hasMore: false
93
+ hasMore: false,
94
+ stage: isEditingFinal ? null : this.state.stage
91
95
  });
92
96
  if (isEditingFinal) {
93
97
  this.onSelect(null);
@@ -202,6 +206,7 @@ var InferCore = class {
202
206
  cities: [],
203
207
  streets: [],
204
208
  isValid: true,
209
+ value: value || null,
205
210
  stage: "final",
206
211
  hasMore: false
207
212
  });
@@ -217,10 +222,20 @@ var InferCore = class {
217
222
  } else {
218
223
  const prefix = this.getQueryPrefix(query);
219
224
  const shouldAddSubtitle = !prefix || !prefix.includes(subtitle);
225
+ let effectivePrefix = prefix;
226
+ if (prefix && subtitle) {
227
+ const prefixNumMatch = prefix.match(PATTERNS.STREET_NUMBER_PREFIX);
228
+ if (prefixNumMatch) {
229
+ const num = prefixNumMatch[1];
230
+ if (subtitle.startsWith(num)) {
231
+ effectivePrefix = "";
232
+ }
233
+ }
234
+ }
220
235
  if (shouldAddSubtitle) {
221
- nextQuery = prefix ? `${prefix} ${text}, ${subtitle}, ` : `${text}, ${subtitle}, `;
236
+ nextQuery = effectivePrefix ? `${effectivePrefix} ${text}, ${subtitle}, ` : `${text}, ${subtitle}, `;
222
237
  } else {
223
- nextQuery = prefix ? `${prefix} ${text}, ` : `${text}, `;
238
+ nextQuery = effectivePrefix ? `${effectivePrefix} ${text}, ` : `${text}, `;
224
239
  }
225
240
  }
226
241
  this.updateQueryAndFetch(nextQuery);
@@ -257,10 +272,12 @@ var InferCore = class {
257
272
  const currentSignal = this.abortController?.signal;
258
273
  const baseUrl = this.explicitApiUrl ? this.explicitApiUrl : `${DEFAULTS.API_URL}/infer/${this.country.toLowerCase()}`;
259
274
  const params = new URLSearchParams({
260
- country: this.country.toLowerCase(),
261
275
  query: text,
262
276
  limit: this.currentLimit.toString()
263
277
  });
278
+ if (this.explicitApiUrl) {
279
+ params.append("country", this.country.toLowerCase());
280
+ }
264
281
  if (this.authKey) {
265
282
  params.set("authKey", this.authKey);
266
283
  }
@@ -313,7 +330,11 @@ var InferCore = class {
313
330
  if (data.stage === "mixed") {
314
331
  newState.cities = data.cities || [];
315
332
  newState.streets = data.streets || [];
316
- newState.suggestions = [];
333
+ if (newState.cities?.length === 0 && newState.streets?.length === 0) {
334
+ newState.suggestions = uniqueSuggestions;
335
+ } else {
336
+ newState.suggestions = [];
337
+ }
317
338
  } else {
318
339
  newState.suggestions = uniqueSuggestions;
319
340
  newState.cities = [];
@@ -326,8 +347,16 @@ var InferCore = class {
326
347
  }
327
348
  }
328
349
  updateQueryAndFetch(nextQuery) {
329
- this.updateState({ query: nextQuery, suggestions: [], cities: [], streets: [] });
330
- this.updateState({ isLoading: true, isValid: false, hasMore: false });
350
+ this.updateState({
351
+ query: nextQuery,
352
+ suggestions: [],
353
+ cities: [],
354
+ streets: [],
355
+ isValid: false,
356
+ value: null,
357
+ isLoading: true,
358
+ hasMore: false
359
+ });
331
360
  this.debouncedFetch(nextQuery);
332
361
  }
333
362
  replaceLastSegment(fullText, newSegment) {
@@ -616,7 +645,18 @@ var HighlightedText = ({ text, query }) => {
616
645
  ));
617
646
  };
618
647
  function useInfer(config) {
619
- const [state, setState] = useState(INITIAL_STATE);
648
+ const [state, setState] = useState(() => {
649
+ if (config.initialValue) {
650
+ return {
651
+ ...INITIAL_STATE,
652
+ value: config.initialValue,
653
+ query: `${config.initialValue.street} ${config.initialValue.street_number}, ${config.initialValue.city}`,
654
+ isValid: true,
655
+ stage: "final"
656
+ };
657
+ }
658
+ return INITIAL_STATE;
659
+ });
620
660
  const callbacksRef = useRef({
621
661
  onStateChange: config.onStateChange,
622
662
  onSelect: config.onSelect
@@ -628,7 +668,7 @@ function useInfer(config) {
628
668
  };
629
669
  }, [config.onStateChange, config.onSelect]);
630
670
  const core = useMemo(() => {
631
- return new InferCore({
671
+ const instance = new InferCore({
632
672
  ...config,
633
673
  onStateChange: (newState) => {
634
674
  setState({ ...newState });
@@ -638,6 +678,12 @@ function useInfer(config) {
638
678
  callbacksRef.current.onSelect?.(selection);
639
679
  }
640
680
  });
681
+ if (config.initialValue) {
682
+ const address = config.initialValue;
683
+ const label = `${address.street} ${address.street_number}, ${address.city}`;
684
+ instance.selectItem({ label, value: address });
685
+ }
686
+ return instance;
641
687
  }, [
642
688
  config.country,
643
689
  config.authKey,
@@ -645,10 +691,16 @@ function useInfer(config) {
645
691
  config.fetcher,
646
692
  config.limit,
647
693
  config.debounceMs,
648
- config.maxRetries
694
+ config.maxRetries,
695
+ config.initialValue
649
696
  ]);
697
+ const setValue = (address) => {
698
+ if (!address) return;
699
+ const label = `${address.street} ${address.street_number}, ${address.city}`;
700
+ core.selectItem({ label, value: address });
701
+ };
650
702
  return {
651
- /** The current UI state (suggestions, loading status, query, etc.). */
703
+ /** The current UI state (suggestions, loading status, query, value, etc.). */
652
704
  state,
653
705
  /** The raw InferCore instance for manual control. */
654
706
  core,
@@ -658,9 +710,11 @@ function useInfer(config) {
658
710
  onChange: (e) => core.handleInput(e.target.value),
659
711
  onKeyDown: (e) => core.handleKeyDown(e)
660
712
  },
661
- /** Function to manually select a specific suggestion. */
713
+ /** Manually select a specific suggestion. */
662
714
  selectItem: (item) => core.selectItem(item),
663
- /** Function to load more results. */
715
+ /** Programmatically set the address value. */
716
+ setValue,
717
+ /** Load more results. */
664
718
  loadMore: () => core.loadMore()
665
719
  };
666
720
  }
package/package.json CHANGED
@@ -20,7 +20,7 @@
20
20
  "url": "https://github.com/pro6pp/infer-sdk/issues"
21
21
  },
22
22
  "sideEffects": false,
23
- "version": "0.0.2-beta.13",
23
+ "version": "0.0.2-beta.15",
24
24
  "main": "./dist/index.cjs",
25
25
  "module": "./dist/index.js",
26
26
  "types": "./dist/index.d.ts",
@@ -46,7 +46,7 @@
46
46
  "react": ">=16"
47
47
  },
48
48
  "dependencies": {
49
- "@pro6pp/infer-core": "0.0.2-beta.11"
49
+ "@pro6pp/infer-core": "0.0.2-beta.13"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@testing-library/dom": "^10.4.1",