@pro6pp/infer-react 0.0.2-beta.16 → 0.0.2-beta.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.cjs +149 -35
  2. package/dist/index.js +149 -35
  3. package/package.json +2 -2
package/dist/index.cjs CHANGED
@@ -38,6 +38,100 @@ __export(index_exports, {
38
38
  module.exports = __toCommonJS(index_exports);
39
39
  var import_react = __toESM(require("react"), 1);
40
40
 
41
+ // ../core/src/label-formatter.ts
42
+ function normalize(str) {
43
+ return str.toLowerCase().trim();
44
+ }
45
+ function escapeRegex(str) {
46
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
47
+ }
48
+ function findWordPosition(query, value) {
49
+ const normalizedQuery = normalize(query);
50
+ const normalizedValue = normalize(value);
51
+ if (normalizedValue.includes(" ")) {
52
+ return normalizedQuery.indexOf(normalizedValue);
53
+ }
54
+ const pattern = new RegExp(`(?:^|[,\\s])${escapeRegex(normalizedValue)}(?:$|[,\\s])`, "g");
55
+ const match = pattern.exec(normalizedQuery);
56
+ if (match) {
57
+ const matchStart = match.index;
58
+ const firstChar = normalizedQuery[matchStart];
59
+ if (firstChar === "," || firstChar === " ") {
60
+ return matchStart + 1;
61
+ }
62
+ return matchStart;
63
+ }
64
+ return -1;
65
+ }
66
+ function detectComponentOrder(query, value) {
67
+ const detected = [];
68
+ const componentMap = [];
69
+ if (value.street) {
70
+ componentMap.push({ value: value.street, type: "street" });
71
+ }
72
+ if (value.city) {
73
+ componentMap.push({ value: value.city, type: "city" });
74
+ }
75
+ if (value.postcode) {
76
+ componentMap.push({ value: value.postcode, type: "postcode" });
77
+ }
78
+ if (value.street_number !== void 0 && value.street_number !== null) {
79
+ componentMap.push({ value: String(value.street_number), type: "street_number" });
80
+ }
81
+ if (value.addition) {
82
+ componentMap.push({ value: value.addition, type: "addition" });
83
+ }
84
+ for (const comp of componentMap) {
85
+ const position = findWordPosition(query, comp.value);
86
+ if (position !== -1) {
87
+ detected.push({
88
+ type: comp.type,
89
+ value: comp.value,
90
+ position
91
+ });
92
+ }
93
+ }
94
+ detected.sort((a, b) => a.position - b.position);
95
+ return detected;
96
+ }
97
+ function formatLabelByInputOrder(query, value) {
98
+ if (!value || !query) {
99
+ return "";
100
+ }
101
+ const detectedOrder = detectComponentOrder(query, value);
102
+ const detectedTypes = new Set(detectedOrder.map((d) => d.type));
103
+ const parts = [];
104
+ for (const detected of detectedOrder) {
105
+ parts.push(detected.value);
106
+ }
107
+ const defaultOrder = ["street", "street_number", "addition", "postcode", "city"];
108
+ for (const type of defaultOrder) {
109
+ if (detectedTypes.has(type)) continue;
110
+ let val;
111
+ switch (type) {
112
+ case "street":
113
+ val = value.street;
114
+ break;
115
+ case "city":
116
+ val = value.city;
117
+ break;
118
+ case "street_number":
119
+ val = value.street_number !== void 0 ? String(value.street_number) : void 0;
120
+ break;
121
+ case "postcode":
122
+ val = value.postcode;
123
+ break;
124
+ case "addition":
125
+ val = value.addition;
126
+ break;
127
+ }
128
+ if (val) {
129
+ parts.push(val);
130
+ }
131
+ }
132
+ return parts.join(", ");
133
+ }
134
+
41
135
  // ../core/src/core.ts
42
136
  var DEFAULTS = {
43
137
  API_URL: "https://api.pro6pp.nl/v2",
@@ -203,10 +297,11 @@ var InferCore = class {
203
297
  if (this.state.stage === "final" || isFullResult) {
204
298
  let finalQuery = label;
205
299
  if (valueObj && Object.keys(valueObj).length > 0) {
206
- const { street, street_number, city, addition } = valueObj;
300
+ const { street, street_number, postcode, city, addition } = valueObj;
207
301
  if (street && street_number && city) {
208
302
  const suffix = addition ? ` ${addition}` : "";
209
- finalQuery = `${street} ${street_number}${suffix}, ${city}`;
303
+ const postcodeStr = postcode ? `${postcode}, ` : "";
304
+ finalQuery = `${street} ${street_number}${suffix}, ${postcodeStr}${city}`;
210
305
  }
211
306
  }
212
307
  this.finishSelection(finalQuery, valueObj);
@@ -348,7 +443,8 @@ var InferCore = class {
348
443
  const key = `${item.label}|${item.subtitle || ""}|${JSON.stringify(item.value || {})}`;
349
444
  if (!seen.has(key)) {
350
445
  seen.add(key);
351
- uniqueSuggestions.push(item);
446
+ const reformattedItem = this.reformatSuggestionLabel(item);
447
+ uniqueSuggestions.push(reformattedItem);
352
448
  }
353
449
  }
354
450
  const totalCount = uniqueSuggestions.length + (data.cities?.length || 0) + (data.streets?.length || 0);
@@ -372,6 +468,25 @@ var InferCore = class {
372
468
  this.selectItem(uniqueSuggestions[0]);
373
469
  }
374
470
  }
471
+ /**
472
+ * Reformats a suggestion's label based on the user's input order.
473
+ * If the suggestion has a structured value object, we reorder the label
474
+ * to match how the user typed the components.
475
+ */
476
+ reformatSuggestionLabel(item) {
477
+ if (!item.value || typeof item.value === "string") {
478
+ return item;
479
+ }
480
+ const addressValue = item.value;
481
+ if (!addressValue.street || !addressValue.city) {
482
+ return item;
483
+ }
484
+ const reformattedLabel = formatLabelByInputOrder(this.state.query, addressValue);
485
+ if (reformattedLabel) {
486
+ return { ...item, label: reformattedLabel };
487
+ }
488
+ return item;
489
+ }
375
490
  updateQueryAndFetch(nextQuery) {
376
491
  this.updateState({
377
492
  query: nextQuery,
@@ -421,6 +536,19 @@ var InferCore = class {
421
536
  };
422
537
 
423
538
  // ../core/src/highlight.ts
539
+ function mergeSegments(segments) {
540
+ if (segments.length === 0) return segments;
541
+ const merged = [];
542
+ for (const seg of segments) {
543
+ const last = merged[merged.length - 1];
544
+ if (last && last.match === seg.match) {
545
+ last.text += seg.text;
546
+ } else {
547
+ merged.push({ text: seg.text, match: seg.match });
548
+ }
549
+ }
550
+ return merged;
551
+ }
424
552
  function getHighlightSegments(text, query) {
425
553
  if (!query || !text) return [{ text, match: false }];
426
554
  const segments = [];
@@ -447,7 +575,7 @@ function getHighlightSegments(text, query) {
447
575
  if (!isFullMatch) {
448
576
  return [{ text, match: false }];
449
577
  }
450
- return segments;
578
+ return mergeSegments(segments);
451
579
  }
452
580
 
453
581
  // ../core/src/default-styles.ts
@@ -583,15 +711,23 @@ var DEFAULT_STYLES = `
583
711
  }
584
712
 
585
713
  .pro6pp-item__label {
586
- font-weight: 500;
714
+ font-weight: 400;
587
715
  flex-shrink: 1;
588
716
  overflow: hidden;
589
717
  text-overflow: ellipsis;
590
718
  white-space: nowrap;
591
719
  }
592
720
 
721
+ .pro6pp-item__label--match {
722
+ font-weight: 520;
723
+ }
724
+
725
+ .pro6pp-item__label--unmatched {
726
+ font-weight: 400;
727
+ color: #4b5563;
728
+ }
729
+
593
730
  .pro6pp-item__subtitle {
594
- font-size: 13px;
595
731
  color: #6b7280;
596
732
  flex-shrink: 0;
597
733
  }
@@ -611,20 +747,6 @@ var DEFAULT_STYLES = `
611
747
  text-align: center;
612
748
  }
613
749
 
614
- .pro6pp-load-more {
615
- width: 100%;
616
- padding: 14px;
617
- background: #f9fafb;
618
- border: none;
619
- border-top: 1px solid #e0e0e0;
620
- color: #3b82f6;
621
- font-size: 14px;
622
- font-weight: 600;
623
- cursor: pointer;
624
- flex-shrink: 0;
625
- touch-action: manipulation;
626
- }
627
-
628
750
  .pro6pp-loader-item {
629
751
  padding: 10px 12px;
630
752
  color: #6b7280;
@@ -655,17 +777,6 @@ var DEFAULT_STYLES = `
655
777
  padding: 10px 12px;
656
778
  font-size: 14px;
657
779
  }
658
- .pro6pp-item__subtitle {
659
- font-size: 12px;
660
- }
661
- .pro6pp-load-more {
662
- padding: 12px;
663
- font-size: 13px;
664
- }
665
- }
666
-
667
- .pro6pp-load-more:active {
668
- background-color: #f3f4f6;
669
780
  }
670
781
 
671
782
  @keyframes pro6pp-spin {
@@ -677,16 +788,17 @@ var DEFAULT_STYLES = `
677
788
  var HighlightedText = ({ text, query }) => {
678
789
  const segments = (0, import_react.useMemo)(() => getHighlightSegments(text, query), [text, query]);
679
790
  return /* @__PURE__ */ import_react.default.createElement("span", { className: "pro6pp-item__label" }, segments.map(
680
- (seg, i) => seg.match ? /* @__PURE__ */ import_react.default.createElement("strong", { key: i, className: "pro6pp-item__label--match" }, seg.text) : seg.text
791
+ (seg, i) => seg.match ? /* @__PURE__ */ import_react.default.createElement("span", { key: i, className: "pro6pp-item__label--match" }, seg.text) : /* @__PURE__ */ import_react.default.createElement("span", { key: i, className: "pro6pp-item__label--unmatched" }, seg.text)
681
792
  ));
682
793
  };
683
794
  function useInfer(config) {
684
795
  const [state, setState] = (0, import_react.useState)(() => {
685
796
  if (config.initialValue) {
797
+ const postcodeStr = config.initialValue.postcode ? `${config.initialValue.postcode}, ` : "";
686
798
  return {
687
799
  ...INITIAL_STATE,
688
800
  value: config.initialValue,
689
- query: `${config.initialValue.street} ${config.initialValue.street_number}, ${config.initialValue.city}`,
801
+ query: `${config.initialValue.street} ${config.initialValue.street_number}, ${postcodeStr}${config.initialValue.city}`,
690
802
  isValid: true,
691
803
  stage: "final"
692
804
  };
@@ -716,7 +828,8 @@ function useInfer(config) {
716
828
  });
717
829
  if (config.initialValue) {
718
830
  const address = config.initialValue;
719
- const label = `${address.street} ${address.street_number}, ${address.city}`;
831
+ const postcodeStr = address.postcode ? `${address.postcode}, ` : "";
832
+ const label = `${address.street} ${address.street_number}, ${postcodeStr}${address.city}`;
720
833
  instance.selectItem({ label, value: address });
721
834
  }
722
835
  return instance;
@@ -732,7 +845,8 @@ function useInfer(config) {
732
845
  ]);
733
846
  const setValue = (address) => {
734
847
  if (!address) return;
735
- const label = `${address.street} ${address.street_number}, ${address.city}`;
848
+ const postcodeStr = address.postcode ? `${address.postcode}, ` : "";
849
+ const label = `${address.street} ${address.street_number}, ${postcodeStr}${address.city}`;
736
850
  core.selectItem({ label, value: address });
737
851
  };
738
852
  return {
package/dist/index.js CHANGED
@@ -12,6 +12,100 @@ import React, {
12
12
  useImperativeHandle
13
13
  } from "react";
14
14
 
15
+ // ../core/src/label-formatter.ts
16
+ function normalize(str) {
17
+ return str.toLowerCase().trim();
18
+ }
19
+ function escapeRegex(str) {
20
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
21
+ }
22
+ function findWordPosition(query, value) {
23
+ const normalizedQuery = normalize(query);
24
+ const normalizedValue = normalize(value);
25
+ if (normalizedValue.includes(" ")) {
26
+ return normalizedQuery.indexOf(normalizedValue);
27
+ }
28
+ const pattern = new RegExp(`(?:^|[,\\s])${escapeRegex(normalizedValue)}(?:$|[,\\s])`, "g");
29
+ const match = pattern.exec(normalizedQuery);
30
+ if (match) {
31
+ const matchStart = match.index;
32
+ const firstChar = normalizedQuery[matchStart];
33
+ if (firstChar === "," || firstChar === " ") {
34
+ return matchStart + 1;
35
+ }
36
+ return matchStart;
37
+ }
38
+ return -1;
39
+ }
40
+ function detectComponentOrder(query, value) {
41
+ const detected = [];
42
+ const componentMap = [];
43
+ if (value.street) {
44
+ componentMap.push({ value: value.street, type: "street" });
45
+ }
46
+ if (value.city) {
47
+ componentMap.push({ value: value.city, type: "city" });
48
+ }
49
+ if (value.postcode) {
50
+ componentMap.push({ value: value.postcode, type: "postcode" });
51
+ }
52
+ if (value.street_number !== void 0 && value.street_number !== null) {
53
+ componentMap.push({ value: String(value.street_number), type: "street_number" });
54
+ }
55
+ if (value.addition) {
56
+ componentMap.push({ value: value.addition, type: "addition" });
57
+ }
58
+ for (const comp of componentMap) {
59
+ const position = findWordPosition(query, comp.value);
60
+ if (position !== -1) {
61
+ detected.push({
62
+ type: comp.type,
63
+ value: comp.value,
64
+ position
65
+ });
66
+ }
67
+ }
68
+ detected.sort((a, b) => a.position - b.position);
69
+ return detected;
70
+ }
71
+ function formatLabelByInputOrder(query, value) {
72
+ if (!value || !query) {
73
+ return "";
74
+ }
75
+ const detectedOrder = detectComponentOrder(query, value);
76
+ const detectedTypes = new Set(detectedOrder.map((d) => d.type));
77
+ const parts = [];
78
+ for (const detected of detectedOrder) {
79
+ parts.push(detected.value);
80
+ }
81
+ const defaultOrder = ["street", "street_number", "addition", "postcode", "city"];
82
+ for (const type of defaultOrder) {
83
+ if (detectedTypes.has(type)) continue;
84
+ let val;
85
+ switch (type) {
86
+ case "street":
87
+ val = value.street;
88
+ break;
89
+ case "city":
90
+ val = value.city;
91
+ break;
92
+ case "street_number":
93
+ val = value.street_number !== void 0 ? String(value.street_number) : void 0;
94
+ break;
95
+ case "postcode":
96
+ val = value.postcode;
97
+ break;
98
+ case "addition":
99
+ val = value.addition;
100
+ break;
101
+ }
102
+ if (val) {
103
+ parts.push(val);
104
+ }
105
+ }
106
+ return parts.join(", ");
107
+ }
108
+
15
109
  // ../core/src/core.ts
16
110
  var DEFAULTS = {
17
111
  API_URL: "https://api.pro6pp.nl/v2",
@@ -177,10 +271,11 @@ var InferCore = class {
177
271
  if (this.state.stage === "final" || isFullResult) {
178
272
  let finalQuery = label;
179
273
  if (valueObj && Object.keys(valueObj).length > 0) {
180
- const { street, street_number, city, addition } = valueObj;
274
+ const { street, street_number, postcode, city, addition } = valueObj;
181
275
  if (street && street_number && city) {
182
276
  const suffix = addition ? ` ${addition}` : "";
183
- finalQuery = `${street} ${street_number}${suffix}, ${city}`;
277
+ const postcodeStr = postcode ? `${postcode}, ` : "";
278
+ finalQuery = `${street} ${street_number}${suffix}, ${postcodeStr}${city}`;
184
279
  }
185
280
  }
186
281
  this.finishSelection(finalQuery, valueObj);
@@ -322,7 +417,8 @@ var InferCore = class {
322
417
  const key = `${item.label}|${item.subtitle || ""}|${JSON.stringify(item.value || {})}`;
323
418
  if (!seen.has(key)) {
324
419
  seen.add(key);
325
- uniqueSuggestions.push(item);
420
+ const reformattedItem = this.reformatSuggestionLabel(item);
421
+ uniqueSuggestions.push(reformattedItem);
326
422
  }
327
423
  }
328
424
  const totalCount = uniqueSuggestions.length + (data.cities?.length || 0) + (data.streets?.length || 0);
@@ -346,6 +442,25 @@ var InferCore = class {
346
442
  this.selectItem(uniqueSuggestions[0]);
347
443
  }
348
444
  }
445
+ /**
446
+ * Reformats a suggestion's label based on the user's input order.
447
+ * If the suggestion has a structured value object, we reorder the label
448
+ * to match how the user typed the components.
449
+ */
450
+ reformatSuggestionLabel(item) {
451
+ if (!item.value || typeof item.value === "string") {
452
+ return item;
453
+ }
454
+ const addressValue = item.value;
455
+ if (!addressValue.street || !addressValue.city) {
456
+ return item;
457
+ }
458
+ const reformattedLabel = formatLabelByInputOrder(this.state.query, addressValue);
459
+ if (reformattedLabel) {
460
+ return { ...item, label: reformattedLabel };
461
+ }
462
+ return item;
463
+ }
349
464
  updateQueryAndFetch(nextQuery) {
350
465
  this.updateState({
351
466
  query: nextQuery,
@@ -395,6 +510,19 @@ var InferCore = class {
395
510
  };
396
511
 
397
512
  // ../core/src/highlight.ts
513
+ function mergeSegments(segments) {
514
+ if (segments.length === 0) return segments;
515
+ const merged = [];
516
+ for (const seg of segments) {
517
+ const last = merged[merged.length - 1];
518
+ if (last && last.match === seg.match) {
519
+ last.text += seg.text;
520
+ } else {
521
+ merged.push({ text: seg.text, match: seg.match });
522
+ }
523
+ }
524
+ return merged;
525
+ }
398
526
  function getHighlightSegments(text, query) {
399
527
  if (!query || !text) return [{ text, match: false }];
400
528
  const segments = [];
@@ -421,7 +549,7 @@ function getHighlightSegments(text, query) {
421
549
  if (!isFullMatch) {
422
550
  return [{ text, match: false }];
423
551
  }
424
- return segments;
552
+ return mergeSegments(segments);
425
553
  }
426
554
 
427
555
  // ../core/src/default-styles.ts
@@ -557,15 +685,23 @@ var DEFAULT_STYLES = `
557
685
  }
558
686
 
559
687
  .pro6pp-item__label {
560
- font-weight: 500;
688
+ font-weight: 400;
561
689
  flex-shrink: 1;
562
690
  overflow: hidden;
563
691
  text-overflow: ellipsis;
564
692
  white-space: nowrap;
565
693
  }
566
694
 
695
+ .pro6pp-item__label--match {
696
+ font-weight: 520;
697
+ }
698
+
699
+ .pro6pp-item__label--unmatched {
700
+ font-weight: 400;
701
+ color: #4b5563;
702
+ }
703
+
567
704
  .pro6pp-item__subtitle {
568
- font-size: 13px;
569
705
  color: #6b7280;
570
706
  flex-shrink: 0;
571
707
  }
@@ -585,20 +721,6 @@ var DEFAULT_STYLES = `
585
721
  text-align: center;
586
722
  }
587
723
 
588
- .pro6pp-load-more {
589
- width: 100%;
590
- padding: 14px;
591
- background: #f9fafb;
592
- border: none;
593
- border-top: 1px solid #e0e0e0;
594
- color: #3b82f6;
595
- font-size: 14px;
596
- font-weight: 600;
597
- cursor: pointer;
598
- flex-shrink: 0;
599
- touch-action: manipulation;
600
- }
601
-
602
724
  .pro6pp-loader-item {
603
725
  padding: 10px 12px;
604
726
  color: #6b7280;
@@ -629,17 +751,6 @@ var DEFAULT_STYLES = `
629
751
  padding: 10px 12px;
630
752
  font-size: 14px;
631
753
  }
632
- .pro6pp-item__subtitle {
633
- font-size: 12px;
634
- }
635
- .pro6pp-load-more {
636
- padding: 12px;
637
- font-size: 13px;
638
- }
639
- }
640
-
641
- .pro6pp-load-more:active {
642
- background-color: #f3f4f6;
643
754
  }
644
755
 
645
756
  @keyframes pro6pp-spin {
@@ -651,16 +762,17 @@ var DEFAULT_STYLES = `
651
762
  var HighlightedText = ({ text, query }) => {
652
763
  const segments = useMemo(() => getHighlightSegments(text, query), [text, query]);
653
764
  return /* @__PURE__ */ React.createElement("span", { className: "pro6pp-item__label" }, segments.map(
654
- (seg, i) => seg.match ? /* @__PURE__ */ React.createElement("strong", { key: i, className: "pro6pp-item__label--match" }, seg.text) : seg.text
765
+ (seg, i) => seg.match ? /* @__PURE__ */ React.createElement("span", { key: i, className: "pro6pp-item__label--match" }, seg.text) : /* @__PURE__ */ React.createElement("span", { key: i, className: "pro6pp-item__label--unmatched" }, seg.text)
655
766
  ));
656
767
  };
657
768
  function useInfer(config) {
658
769
  const [state, setState] = useState(() => {
659
770
  if (config.initialValue) {
771
+ const postcodeStr = config.initialValue.postcode ? `${config.initialValue.postcode}, ` : "";
660
772
  return {
661
773
  ...INITIAL_STATE,
662
774
  value: config.initialValue,
663
- query: `${config.initialValue.street} ${config.initialValue.street_number}, ${config.initialValue.city}`,
775
+ query: `${config.initialValue.street} ${config.initialValue.street_number}, ${postcodeStr}${config.initialValue.city}`,
664
776
  isValid: true,
665
777
  stage: "final"
666
778
  };
@@ -690,7 +802,8 @@ function useInfer(config) {
690
802
  });
691
803
  if (config.initialValue) {
692
804
  const address = config.initialValue;
693
- const label = `${address.street} ${address.street_number}, ${address.city}`;
805
+ const postcodeStr = address.postcode ? `${address.postcode}, ` : "";
806
+ const label = `${address.street} ${address.street_number}, ${postcodeStr}${address.city}`;
694
807
  instance.selectItem({ label, value: address });
695
808
  }
696
809
  return instance;
@@ -706,7 +819,8 @@ function useInfer(config) {
706
819
  ]);
707
820
  const setValue = (address) => {
708
821
  if (!address) return;
709
- const label = `${address.street} ${address.street_number}, ${address.city}`;
822
+ const postcodeStr = address.postcode ? `${address.postcode}, ` : "";
823
+ const label = `${address.street} ${address.street_number}, ${postcodeStr}${address.city}`;
710
824
  core.selectItem({ label, value: address });
711
825
  };
712
826
  return {
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.16",
23
+ "version": "0.0.2-beta.17",
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.14"
49
+ "@pro6pp/infer-core": "0.0.2-beta.15"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@testing-library/dom": "^10.4.1",