@pro6pp/infer-react 0.0.2-beta.8 → 0.0.2-beta.9
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 +3 -0
- package/dist/index.cjs +224 -69
- package/dist/index.d.cts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +224 -69
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -43,6 +43,9 @@ You can customize the appearance of the component via the following props:
|
|
|
43
43
|
| `renderItem` | A custom render function for suggestion items, receiving the `item` and `isActive` state. |
|
|
44
44
|
| `renderNoResults` | A custom render function for the empty state, receiving the current `state`. |
|
|
45
45
|
| `debounceMs` | Delay in ms before API search. Defaults to `150` (min `50`). |
|
|
46
|
+
| `maxRetries` | Maximum retry attempts for transient network errors. Valid range: `0` to `10`. |
|
|
47
|
+
| `showClearButton` | If `true`, displays a button to empty the input field. Defaults to `true`. |
|
|
48
|
+
| `loadMoreText` | The text to display on the pagination button. |
|
|
46
49
|
|
|
47
50
|
---
|
|
48
51
|
|
package/dist/index.cjs
CHANGED
|
@@ -41,9 +41,10 @@ var import_react = __toESM(require("react"), 1);
|
|
|
41
41
|
// ../core/src/core.ts
|
|
42
42
|
var DEFAULTS = {
|
|
43
43
|
API_URL: "https://api.pro6pp.nl/v2",
|
|
44
|
-
LIMIT:
|
|
44
|
+
LIMIT: 20,
|
|
45
45
|
DEBOUNCE_MS: 150,
|
|
46
|
-
MIN_DEBOUNCE_MS: 50
|
|
46
|
+
MIN_DEBOUNCE_MS: 50,
|
|
47
|
+
MAX_RETRIES: 0
|
|
47
48
|
};
|
|
48
49
|
var PATTERNS = {
|
|
49
50
|
DIGITS_1_3: /^[0-9]{1,3}$/
|
|
@@ -57,6 +58,7 @@ var INITIAL_STATE = {
|
|
|
57
58
|
isValid: false,
|
|
58
59
|
isError: false,
|
|
59
60
|
isLoading: false,
|
|
61
|
+
hasMore: false,
|
|
60
62
|
selectedSuggestionIndex: -1
|
|
61
63
|
};
|
|
62
64
|
var InferCore = class {
|
|
@@ -68,7 +70,9 @@ var InferCore = class {
|
|
|
68
70
|
__publicField(this, "country");
|
|
69
71
|
__publicField(this, "authKey");
|
|
70
72
|
__publicField(this, "apiUrl");
|
|
71
|
-
__publicField(this, "
|
|
73
|
+
__publicField(this, "baseLimit");
|
|
74
|
+
__publicField(this, "currentLimit");
|
|
75
|
+
__publicField(this, "maxRetries");
|
|
72
76
|
__publicField(this, "fetcher");
|
|
73
77
|
__publicField(this, "onStateChange");
|
|
74
78
|
__publicField(this, "onSelect");
|
|
@@ -83,7 +87,10 @@ var InferCore = class {
|
|
|
83
87
|
this.country = config.country;
|
|
84
88
|
this.authKey = config.authKey;
|
|
85
89
|
this.apiUrl = config.apiUrl || DEFAULTS.API_URL;
|
|
86
|
-
this.
|
|
90
|
+
this.baseLimit = config.limit || DEFAULTS.LIMIT;
|
|
91
|
+
this.currentLimit = this.baseLimit;
|
|
92
|
+
const configRetries = config.maxRetries !== void 0 ? config.maxRetries : DEFAULTS.MAX_RETRIES;
|
|
93
|
+
this.maxRetries = Math.max(0, Math.min(configRetries, 10));
|
|
87
94
|
this.fetcher = config.fetcher || ((url, init) => fetch(url, init));
|
|
88
95
|
this.onStateChange = config.onStateChange || (() => {
|
|
89
96
|
});
|
|
@@ -104,18 +111,29 @@ var InferCore = class {
|
|
|
104
111
|
this.isSelecting = false;
|
|
105
112
|
return;
|
|
106
113
|
}
|
|
114
|
+
this.currentLimit = this.baseLimit;
|
|
107
115
|
const isEditingFinal = this.state.stage === "final" && value !== this.state.query;
|
|
108
116
|
this.updateState({
|
|
109
117
|
query: value,
|
|
110
118
|
isValid: false,
|
|
111
119
|
isLoading: !!value.trim(),
|
|
112
|
-
selectedSuggestionIndex: -1
|
|
120
|
+
selectedSuggestionIndex: -1,
|
|
121
|
+
hasMore: false
|
|
113
122
|
});
|
|
114
123
|
if (isEditingFinal) {
|
|
115
124
|
this.onSelect(null);
|
|
116
125
|
}
|
|
117
126
|
this.debouncedFetch(value);
|
|
118
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Increases the current limit and re-fetches the query to show more results.
|
|
130
|
+
*/
|
|
131
|
+
loadMore() {
|
|
132
|
+
if (this.state.isLoading) return;
|
|
133
|
+
this.currentLimit += this.baseLimit;
|
|
134
|
+
this.updateState({ isLoading: true });
|
|
135
|
+
this.executeFetch(this.state.query);
|
|
136
|
+
}
|
|
119
137
|
/**
|
|
120
138
|
* Handles keyboard events for the input field.
|
|
121
139
|
* Supports:
|
|
@@ -214,7 +232,8 @@ var InferCore = class {
|
|
|
214
232
|
cities: [],
|
|
215
233
|
streets: [],
|
|
216
234
|
isValid: true,
|
|
217
|
-
stage: "final"
|
|
235
|
+
stage: "final",
|
|
236
|
+
hasMore: false
|
|
218
237
|
});
|
|
219
238
|
this.onSelect(value || label);
|
|
220
239
|
setTimeout(() => {
|
|
@@ -251,32 +270,53 @@ var InferCore = class {
|
|
|
251
270
|
}
|
|
252
271
|
this.updateQueryAndFetch(nextQuery);
|
|
253
272
|
}
|
|
254
|
-
executeFetch(val) {
|
|
273
|
+
executeFetch(val, attempt = 0) {
|
|
255
274
|
const text = (val || "").toString();
|
|
256
275
|
if (!text.trim()) {
|
|
257
276
|
this.abortController?.abort();
|
|
258
277
|
this.resetState();
|
|
259
278
|
return;
|
|
260
279
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
280
|
+
if (attempt === 0) {
|
|
281
|
+
this.updateState({ isError: false });
|
|
282
|
+
if (this.abortController) this.abortController.abort();
|
|
283
|
+
this.abortController = new AbortController();
|
|
284
|
+
}
|
|
285
|
+
const currentSignal = this.abortController?.signal;
|
|
264
286
|
const url = new URL(`${this.apiUrl}/infer/${this.country.toLowerCase()}`);
|
|
265
287
|
const params = {
|
|
266
288
|
authKey: this.authKey,
|
|
267
289
|
query: text,
|
|
268
|
-
limit: this.
|
|
290
|
+
limit: this.currentLimit.toString()
|
|
269
291
|
};
|
|
270
292
|
url.search = new URLSearchParams(params).toString();
|
|
271
|
-
this.fetcher(url.toString(), { signal:
|
|
272
|
-
if (!res.ok)
|
|
293
|
+
this.fetcher(url.toString(), { signal: currentSignal }).then((res) => {
|
|
294
|
+
if (!res.ok) {
|
|
295
|
+
if (attempt < this.maxRetries && (res.status >= 500 || res.status === 429)) {
|
|
296
|
+
return this.retry(val, attempt, currentSignal);
|
|
297
|
+
}
|
|
298
|
+
throw new Error("Network error");
|
|
299
|
+
}
|
|
273
300
|
return res.json();
|
|
274
|
-
}).then((data) =>
|
|
275
|
-
if (
|
|
276
|
-
|
|
301
|
+
}).then((data) => {
|
|
302
|
+
if (data) this.mapResponseToState(data);
|
|
303
|
+
}).catch((e) => {
|
|
304
|
+
if (e.name === "AbortError") return;
|
|
305
|
+
if (attempt < this.maxRetries) {
|
|
306
|
+
return this.retry(val, attempt, currentSignal);
|
|
277
307
|
}
|
|
308
|
+
this.updateState({ isError: true, isLoading: false });
|
|
278
309
|
});
|
|
279
310
|
}
|
|
311
|
+
retry(val, attempt, signal) {
|
|
312
|
+
if (signal?.aborted) return;
|
|
313
|
+
const delay = Math.pow(2, attempt) * 200;
|
|
314
|
+
setTimeout(() => {
|
|
315
|
+
if (!signal?.aborted) {
|
|
316
|
+
this.executeFetch(val, attempt + 1);
|
|
317
|
+
}
|
|
318
|
+
}, delay);
|
|
319
|
+
}
|
|
280
320
|
mapResponseToState(data) {
|
|
281
321
|
const newState = {
|
|
282
322
|
stage: data.stage,
|
|
@@ -294,6 +334,8 @@ var InferCore = class {
|
|
|
294
334
|
uniqueSuggestions.push(item);
|
|
295
335
|
}
|
|
296
336
|
}
|
|
337
|
+
const totalCount = uniqueSuggestions.length + (data.cities?.length || 0) + (data.streets?.length || 0);
|
|
338
|
+
newState.hasMore = totalCount >= this.currentLimit;
|
|
297
339
|
if (data.stage === "mixed") {
|
|
298
340
|
newState.cities = data.cities || [];
|
|
299
341
|
newState.streets = data.streets || [];
|
|
@@ -314,6 +356,7 @@ var InferCore = class {
|
|
|
314
356
|
newState.cities = [];
|
|
315
357
|
newState.streets = [];
|
|
316
358
|
newState.isValid = true;
|
|
359
|
+
newState.hasMore = false;
|
|
317
360
|
this.updateState(newState);
|
|
318
361
|
const val = typeof autoSelectItem.value === "object" ? autoSelectItem.value : autoSelectItem.label;
|
|
319
362
|
this.onSelect(val);
|
|
@@ -323,7 +366,7 @@ var InferCore = class {
|
|
|
323
366
|
}
|
|
324
367
|
updateQueryAndFetch(nextQuery) {
|
|
325
368
|
this.updateState({ query: nextQuery, suggestions: [], cities: [], streets: [] });
|
|
326
|
-
this.updateState({ isLoading: true, isValid: false });
|
|
369
|
+
this.updateState({ isLoading: true, isValid: false, hasMore: false });
|
|
327
370
|
this.debouncedFetch(nextQuery);
|
|
328
371
|
setTimeout(() => {
|
|
329
372
|
this.isSelecting = false;
|
|
@@ -378,6 +421,7 @@ var DEFAULT_STYLES = `
|
|
|
378
421
|
.pro6pp-input {
|
|
379
422
|
width: 100%;
|
|
380
423
|
padding: 10px 12px;
|
|
424
|
+
padding-right: 48px;
|
|
381
425
|
border: 1px solid #e0e0e0;
|
|
382
426
|
border-radius: 4px;
|
|
383
427
|
font-size: 16px;
|
|
@@ -389,6 +433,57 @@ var DEFAULT_STYLES = `
|
|
|
389
433
|
border-color: #3b82f6;
|
|
390
434
|
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
391
435
|
}
|
|
436
|
+
|
|
437
|
+
.pro6pp-input-addons {
|
|
438
|
+
position: absolute;
|
|
439
|
+
right: 6px;
|
|
440
|
+
top: 0;
|
|
441
|
+
bottom: 0;
|
|
442
|
+
display: flex;
|
|
443
|
+
align-items: center;
|
|
444
|
+
gap: 2px;
|
|
445
|
+
pointer-events: none;
|
|
446
|
+
}
|
|
447
|
+
.pro6pp-input-addons > * {
|
|
448
|
+
pointer-events: auto;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.pro6pp-clear-button {
|
|
452
|
+
background: none;
|
|
453
|
+
border: none;
|
|
454
|
+
width: 28px;
|
|
455
|
+
height: 28px;
|
|
456
|
+
cursor: pointer;
|
|
457
|
+
color: #a3a3a3;
|
|
458
|
+
display: flex;
|
|
459
|
+
align-items: center;
|
|
460
|
+
justify-content: center;
|
|
461
|
+
border-radius: 50%;
|
|
462
|
+
transition: color 0.2s, background-color 0.2s, transform 0.1s;
|
|
463
|
+
}
|
|
464
|
+
.pro6pp-clear-button:hover {
|
|
465
|
+
color: #1f2937;
|
|
466
|
+
background-color: #f3f4f6;
|
|
467
|
+
}
|
|
468
|
+
.pro6pp-clear-button:active {
|
|
469
|
+
transform: scale(0.92);
|
|
470
|
+
}
|
|
471
|
+
.pro6pp-clear-button svg {
|
|
472
|
+
width: 18px;
|
|
473
|
+
height: 18px;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.pro6pp-loader {
|
|
477
|
+
width: 18px;
|
|
478
|
+
height: 18px;
|
|
479
|
+
margin: 0 4px;
|
|
480
|
+
border: 2px solid #e0e0e0;
|
|
481
|
+
border-top-color: #6b7280;
|
|
482
|
+
border-radius: 50%;
|
|
483
|
+
animation: pro6pp-spin 0.6s linear infinite;
|
|
484
|
+
flex-shrink: 0;
|
|
485
|
+
}
|
|
486
|
+
|
|
392
487
|
.pro6pp-dropdown {
|
|
393
488
|
position: absolute;
|
|
394
489
|
top: 100%;
|
|
@@ -399,27 +494,32 @@ var DEFAULT_STYLES = `
|
|
|
399
494
|
background: white;
|
|
400
495
|
border: 1px solid #e0e0e0;
|
|
401
496
|
border-radius: 4px;
|
|
402
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.
|
|
497
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
403
498
|
max-height: 300px;
|
|
404
499
|
overflow-y: auto;
|
|
500
|
+
display: flex;
|
|
501
|
+
flex-direction: column;
|
|
502
|
+
}
|
|
503
|
+
.pro6pp-list {
|
|
405
504
|
list-style: none !important;
|
|
406
505
|
padding: 0 !important;
|
|
407
506
|
margin: 0 !important;
|
|
507
|
+
flex-grow: 1;
|
|
408
508
|
}
|
|
409
509
|
.pro6pp-item {
|
|
410
|
-
padding:
|
|
510
|
+
padding: 12px 16px;
|
|
411
511
|
cursor: pointer;
|
|
412
512
|
display: flex;
|
|
413
513
|
flex-direction: row;
|
|
414
514
|
align-items: center;
|
|
415
|
-
color: #
|
|
515
|
+
color: #111827;
|
|
416
516
|
font-size: 14px;
|
|
417
517
|
line-height: 1.2;
|
|
418
518
|
white-space: nowrap;
|
|
419
519
|
overflow: hidden;
|
|
420
520
|
}
|
|
421
521
|
.pro6pp-item:hover, .pro6pp-item--active {
|
|
422
|
-
background-color: #
|
|
522
|
+
background-color: #f9fafb;
|
|
423
523
|
}
|
|
424
524
|
.pro6pp-item__label {
|
|
425
525
|
font-weight: 500;
|
|
@@ -427,7 +527,7 @@ var DEFAULT_STYLES = `
|
|
|
427
527
|
}
|
|
428
528
|
.pro6pp-item__subtitle {
|
|
429
529
|
font-size: 14px;
|
|
430
|
-
color: #
|
|
530
|
+
color: #6b7280;
|
|
431
531
|
overflow: hidden;
|
|
432
532
|
text-overflow: ellipsis;
|
|
433
533
|
flex-shrink: 1;
|
|
@@ -436,32 +536,34 @@ var DEFAULT_STYLES = `
|
|
|
436
536
|
margin-left: auto;
|
|
437
537
|
display: flex;
|
|
438
538
|
align-items: center;
|
|
439
|
-
color: #
|
|
539
|
+
color: #9ca3af;
|
|
440
540
|
padding-left: 8px;
|
|
441
541
|
}
|
|
442
542
|
.pro6pp-no-results {
|
|
443
|
-
padding:
|
|
444
|
-
color: #
|
|
543
|
+
padding: 16px;
|
|
544
|
+
color: #6b7280;
|
|
445
545
|
font-size: 14px;
|
|
446
546
|
text-align: center;
|
|
447
|
-
user-select: none;
|
|
448
|
-
pointer-events: none;
|
|
449
547
|
}
|
|
450
|
-
.pro6pp-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
548
|
+
.pro6pp-load-more {
|
|
549
|
+
width: 100%;
|
|
550
|
+
padding: 10px;
|
|
551
|
+
background: #f9fafb;
|
|
552
|
+
border: none;
|
|
553
|
+
border-top: 1px solid #e0e0e0;
|
|
554
|
+
color: #3b82f6;
|
|
555
|
+
font-size: 13px;
|
|
556
|
+
font-weight: 600;
|
|
557
|
+
cursor: pointer;
|
|
558
|
+
transition: background-color 0.2s;
|
|
559
|
+
flex-shrink: 0;
|
|
462
560
|
}
|
|
561
|
+
.pro6pp-load-more:hover {
|
|
562
|
+
background-color: #f3f4f6;
|
|
563
|
+
}
|
|
564
|
+
|
|
463
565
|
@keyframes pro6pp-spin {
|
|
464
|
-
to { transform:
|
|
566
|
+
to { transform: rotate(360deg); }
|
|
465
567
|
}
|
|
466
568
|
`;
|
|
467
569
|
|
|
@@ -478,7 +580,7 @@ function useInfer(config) {
|
|
|
478
580
|
}
|
|
479
581
|
}
|
|
480
582
|
});
|
|
481
|
-
}, [config.country, config.authKey, config.limit, config.debounceMs]);
|
|
583
|
+
}, [config.country, config.authKey, config.limit, config.debounceMs, config.maxRetries]);
|
|
482
584
|
return {
|
|
483
585
|
/** The current UI state (suggestions, loading status, query, etc.). */
|
|
484
586
|
state,
|
|
@@ -491,7 +593,9 @@ function useInfer(config) {
|
|
|
491
593
|
onKeyDown: (e) => core.handleKeyDown(e)
|
|
492
594
|
},
|
|
493
595
|
/** Function to manually select a specific suggestion. */
|
|
494
|
-
selectItem: (item) => core.selectItem(item)
|
|
596
|
+
selectItem: (item) => core.selectItem(item),
|
|
597
|
+
/** Function to load more results. */
|
|
598
|
+
loadMore: () => core.loadMore()
|
|
495
599
|
};
|
|
496
600
|
}
|
|
497
601
|
var Pro6PPInfer = ({
|
|
@@ -502,10 +606,12 @@ var Pro6PPInfer = ({
|
|
|
502
606
|
renderItem,
|
|
503
607
|
disableDefaultStyles = false,
|
|
504
608
|
noResultsText = "No results found",
|
|
609
|
+
loadMoreText = "Show more results...",
|
|
505
610
|
renderNoResults,
|
|
611
|
+
showClearButton = true,
|
|
506
612
|
...config
|
|
507
613
|
}) => {
|
|
508
|
-
const { state, selectItem, inputProps: coreInputProps } = useInfer(config);
|
|
614
|
+
const { state, selectItem, loadMore, inputProps: coreInputProps, core } = useInfer(config);
|
|
509
615
|
const [isOpen, setIsOpen] = (0, import_react.useState)(false);
|
|
510
616
|
const inputRef = (0, import_react.useRef)(null);
|
|
511
617
|
const wrapperRef = (0, import_react.useRef)(null);
|
|
@@ -542,6 +648,12 @@ var Pro6PPInfer = ({
|
|
|
542
648
|
inputRef.current.focus();
|
|
543
649
|
}
|
|
544
650
|
};
|
|
651
|
+
const handleClear = () => {
|
|
652
|
+
core.handleInput("");
|
|
653
|
+
if (inputRef.current) {
|
|
654
|
+
inputRef.current.focus();
|
|
655
|
+
}
|
|
656
|
+
};
|
|
545
657
|
const hasResults = items.length > 0;
|
|
546
658
|
const showNoResults = !state.isLoading && !state.isError && state.query.length > 0 && !hasResults && !state.isValid;
|
|
547
659
|
const showDropdown = isOpen && (hasResults || showNoResults);
|
|
@@ -560,36 +672,79 @@ var Pro6PPInfer = ({
|
|
|
560
672
|
inputProps?.onFocus?.(e);
|
|
561
673
|
}
|
|
562
674
|
}
|
|
563
|
-
),
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
675
|
+
), /* @__PURE__ */ import_react.default.createElement("div", { className: "pro6pp-input-addons" }, state.isLoading && /* @__PURE__ */ import_react.default.createElement("div", { className: "pro6pp-loader" }), showClearButton && state.query.length > 0 && /* @__PURE__ */ import_react.default.createElement(
|
|
676
|
+
"button",
|
|
677
|
+
{
|
|
678
|
+
type: "button",
|
|
679
|
+
className: "pro6pp-clear-button",
|
|
680
|
+
onClick: handleClear,
|
|
681
|
+
"aria-label": "Clear input"
|
|
682
|
+
},
|
|
683
|
+
/* @__PURE__ */ import_react.default.createElement(
|
|
684
|
+
"svg",
|
|
569
685
|
{
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
"
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
686
|
+
width: "14",
|
|
687
|
+
height: "14",
|
|
688
|
+
viewBox: "0 0 24 24",
|
|
689
|
+
fill: "none",
|
|
690
|
+
stroke: "currentColor",
|
|
691
|
+
strokeWidth: "2",
|
|
692
|
+
strokeLinecap: "round",
|
|
693
|
+
strokeLinejoin: "round"
|
|
576
694
|
},
|
|
577
|
-
|
|
578
|
-
|
|
695
|
+
/* @__PURE__ */ import_react.default.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
696
|
+
/* @__PURE__ */ import_react.default.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
697
|
+
)
|
|
698
|
+
))), showDropdown && /* @__PURE__ */ import_react.default.createElement(
|
|
699
|
+
"div",
|
|
700
|
+
{
|
|
701
|
+
className: "pro6pp-dropdown",
|
|
702
|
+
onWheel: (e) => e.stopPropagation(),
|
|
703
|
+
onMouseDown: (e) => e.stopPropagation()
|
|
704
|
+
},
|
|
705
|
+
/* @__PURE__ */ import_react.default.createElement("ul", { className: "pro6pp-list", role: "listbox" }, hasResults ? items.map((item, index) => {
|
|
706
|
+
const isActive = index === state.selectedSuggestionIndex;
|
|
707
|
+
const secondaryText = item.subtitle || (item.count !== void 0 ? item.count : "");
|
|
708
|
+
const showChevron = item.value === void 0 || item.value === null;
|
|
709
|
+
return /* @__PURE__ */ import_react.default.createElement(
|
|
710
|
+
"li",
|
|
579
711
|
{
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
strokeLinecap: "round",
|
|
587
|
-
strokeLinejoin: "round"
|
|
712
|
+
key: `${item.label}-${index}`,
|
|
713
|
+
role: "option",
|
|
714
|
+
"aria-selected": isActive,
|
|
715
|
+
className: `pro6pp-item ${isActive ? "pro6pp-item--active" : ""}`,
|
|
716
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
717
|
+
onClick: () => handleSelect(item)
|
|
588
718
|
},
|
|
589
|
-
/* @__PURE__ */ import_react.default.createElement("
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
719
|
+
renderItem ? renderItem(item, isActive) : /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("span", { className: "pro6pp-item__label" }, item.label), secondaryText && /* @__PURE__ */ import_react.default.createElement("span", { className: "pro6pp-item__subtitle" }, ", ", secondaryText), showChevron && /* @__PURE__ */ import_react.default.createElement("div", { className: "pro6pp-item__chevron" }, /* @__PURE__ */ import_react.default.createElement(
|
|
720
|
+
"svg",
|
|
721
|
+
{
|
|
722
|
+
width: "16",
|
|
723
|
+
height: "16",
|
|
724
|
+
viewBox: "0 0 24 24",
|
|
725
|
+
fill: "none",
|
|
726
|
+
stroke: "currentColor",
|
|
727
|
+
strokeWidth: "2",
|
|
728
|
+
strokeLinecap: "round",
|
|
729
|
+
strokeLinejoin: "round"
|
|
730
|
+
},
|
|
731
|
+
/* @__PURE__ */ import_react.default.createElement("polyline", { points: "9 18 15 12 9 6" })
|
|
732
|
+
)))
|
|
733
|
+
);
|
|
734
|
+
}) : /* @__PURE__ */ import_react.default.createElement("li", { className: "pro6pp-no-results" }, renderNoResults ? renderNoResults(state) : noResultsText)),
|
|
735
|
+
state.hasMore && /* @__PURE__ */ import_react.default.createElement(
|
|
736
|
+
"button",
|
|
737
|
+
{
|
|
738
|
+
type: "button",
|
|
739
|
+
className: "pro6pp-load-more",
|
|
740
|
+
onClick: (e) => {
|
|
741
|
+
e.preventDefault();
|
|
742
|
+
loadMore();
|
|
743
|
+
}
|
|
744
|
+
},
|
|
745
|
+
loadMoreText
|
|
746
|
+
)
|
|
747
|
+
));
|
|
593
748
|
};
|
|
594
749
|
// Annotate the CommonJS export names for ESM import in node:
|
|
595
750
|
0 && (module.exports = {
|
package/dist/index.d.cts
CHANGED
|
@@ -20,6 +20,8 @@ declare function useInfer(config: InferConfig): {
|
|
|
20
20
|
};
|
|
21
21
|
/** Function to manually select a specific suggestion. */
|
|
22
22
|
selectItem: (item: InferResult | string) => void;
|
|
23
|
+
/** Function to load more results. */
|
|
24
|
+
loadMore: () => void;
|
|
23
25
|
};
|
|
24
26
|
/**
|
|
25
27
|
* Props for the Pro6PPInfer component.
|
|
@@ -45,8 +47,17 @@ interface Pro6PPInferProps extends InferConfig {
|
|
|
45
47
|
* @default 'No results found'
|
|
46
48
|
*/
|
|
47
49
|
noResultsText?: string;
|
|
50
|
+
/** * The text to show on the load more button.
|
|
51
|
+
* @default 'Show more results...'
|
|
52
|
+
*/
|
|
53
|
+
loadMoreText?: string;
|
|
48
54
|
/** A custom render function for the "no results" state. */
|
|
49
55
|
renderNoResults?: (state: InferState) => React.ReactNode;
|
|
56
|
+
/**
|
|
57
|
+
* If true, shows a clear button when the input is not empty.
|
|
58
|
+
* @default true
|
|
59
|
+
*/
|
|
60
|
+
showClearButton?: boolean;
|
|
50
61
|
}
|
|
51
62
|
/**
|
|
52
63
|
* A styled React component for Pro6PP Infer API.
|
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ declare function useInfer(config: InferConfig): {
|
|
|
20
20
|
};
|
|
21
21
|
/** Function to manually select a specific suggestion. */
|
|
22
22
|
selectItem: (item: InferResult | string) => void;
|
|
23
|
+
/** Function to load more results. */
|
|
24
|
+
loadMore: () => void;
|
|
23
25
|
};
|
|
24
26
|
/**
|
|
25
27
|
* Props for the Pro6PPInfer component.
|
|
@@ -45,8 +47,17 @@ interface Pro6PPInferProps extends InferConfig {
|
|
|
45
47
|
* @default 'No results found'
|
|
46
48
|
*/
|
|
47
49
|
noResultsText?: string;
|
|
50
|
+
/** * The text to show on the load more button.
|
|
51
|
+
* @default 'Show more results...'
|
|
52
|
+
*/
|
|
53
|
+
loadMoreText?: string;
|
|
48
54
|
/** A custom render function for the "no results" state. */
|
|
49
55
|
renderNoResults?: (state: InferState) => React.ReactNode;
|
|
56
|
+
/**
|
|
57
|
+
* If true, shows a clear button when the input is not empty.
|
|
58
|
+
* @default true
|
|
59
|
+
*/
|
|
60
|
+
showClearButton?: boolean;
|
|
50
61
|
}
|
|
51
62
|
/**
|
|
52
63
|
* A styled React component for Pro6PP Infer API.
|
package/dist/index.js
CHANGED
|
@@ -8,9 +8,10 @@ import React, { useState, useMemo, useEffect, useRef } from "react";
|
|
|
8
8
|
// ../core/src/core.ts
|
|
9
9
|
var DEFAULTS = {
|
|
10
10
|
API_URL: "https://api.pro6pp.nl/v2",
|
|
11
|
-
LIMIT:
|
|
11
|
+
LIMIT: 20,
|
|
12
12
|
DEBOUNCE_MS: 150,
|
|
13
|
-
MIN_DEBOUNCE_MS: 50
|
|
13
|
+
MIN_DEBOUNCE_MS: 50,
|
|
14
|
+
MAX_RETRIES: 0
|
|
14
15
|
};
|
|
15
16
|
var PATTERNS = {
|
|
16
17
|
DIGITS_1_3: /^[0-9]{1,3}$/
|
|
@@ -24,6 +25,7 @@ var INITIAL_STATE = {
|
|
|
24
25
|
isValid: false,
|
|
25
26
|
isError: false,
|
|
26
27
|
isLoading: false,
|
|
28
|
+
hasMore: false,
|
|
27
29
|
selectedSuggestionIndex: -1
|
|
28
30
|
};
|
|
29
31
|
var InferCore = class {
|
|
@@ -35,7 +37,9 @@ var InferCore = class {
|
|
|
35
37
|
__publicField(this, "country");
|
|
36
38
|
__publicField(this, "authKey");
|
|
37
39
|
__publicField(this, "apiUrl");
|
|
38
|
-
__publicField(this, "
|
|
40
|
+
__publicField(this, "baseLimit");
|
|
41
|
+
__publicField(this, "currentLimit");
|
|
42
|
+
__publicField(this, "maxRetries");
|
|
39
43
|
__publicField(this, "fetcher");
|
|
40
44
|
__publicField(this, "onStateChange");
|
|
41
45
|
__publicField(this, "onSelect");
|
|
@@ -50,7 +54,10 @@ var InferCore = class {
|
|
|
50
54
|
this.country = config.country;
|
|
51
55
|
this.authKey = config.authKey;
|
|
52
56
|
this.apiUrl = config.apiUrl || DEFAULTS.API_URL;
|
|
53
|
-
this.
|
|
57
|
+
this.baseLimit = config.limit || DEFAULTS.LIMIT;
|
|
58
|
+
this.currentLimit = this.baseLimit;
|
|
59
|
+
const configRetries = config.maxRetries !== void 0 ? config.maxRetries : DEFAULTS.MAX_RETRIES;
|
|
60
|
+
this.maxRetries = Math.max(0, Math.min(configRetries, 10));
|
|
54
61
|
this.fetcher = config.fetcher || ((url, init) => fetch(url, init));
|
|
55
62
|
this.onStateChange = config.onStateChange || (() => {
|
|
56
63
|
});
|
|
@@ -71,18 +78,29 @@ var InferCore = class {
|
|
|
71
78
|
this.isSelecting = false;
|
|
72
79
|
return;
|
|
73
80
|
}
|
|
81
|
+
this.currentLimit = this.baseLimit;
|
|
74
82
|
const isEditingFinal = this.state.stage === "final" && value !== this.state.query;
|
|
75
83
|
this.updateState({
|
|
76
84
|
query: value,
|
|
77
85
|
isValid: false,
|
|
78
86
|
isLoading: !!value.trim(),
|
|
79
|
-
selectedSuggestionIndex: -1
|
|
87
|
+
selectedSuggestionIndex: -1,
|
|
88
|
+
hasMore: false
|
|
80
89
|
});
|
|
81
90
|
if (isEditingFinal) {
|
|
82
91
|
this.onSelect(null);
|
|
83
92
|
}
|
|
84
93
|
this.debouncedFetch(value);
|
|
85
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Increases the current limit and re-fetches the query to show more results.
|
|
97
|
+
*/
|
|
98
|
+
loadMore() {
|
|
99
|
+
if (this.state.isLoading) return;
|
|
100
|
+
this.currentLimit += this.baseLimit;
|
|
101
|
+
this.updateState({ isLoading: true });
|
|
102
|
+
this.executeFetch(this.state.query);
|
|
103
|
+
}
|
|
86
104
|
/**
|
|
87
105
|
* Handles keyboard events for the input field.
|
|
88
106
|
* Supports:
|
|
@@ -181,7 +199,8 @@ var InferCore = class {
|
|
|
181
199
|
cities: [],
|
|
182
200
|
streets: [],
|
|
183
201
|
isValid: true,
|
|
184
|
-
stage: "final"
|
|
202
|
+
stage: "final",
|
|
203
|
+
hasMore: false
|
|
185
204
|
});
|
|
186
205
|
this.onSelect(value || label);
|
|
187
206
|
setTimeout(() => {
|
|
@@ -218,32 +237,53 @@ var InferCore = class {
|
|
|
218
237
|
}
|
|
219
238
|
this.updateQueryAndFetch(nextQuery);
|
|
220
239
|
}
|
|
221
|
-
executeFetch(val) {
|
|
240
|
+
executeFetch(val, attempt = 0) {
|
|
222
241
|
const text = (val || "").toString();
|
|
223
242
|
if (!text.trim()) {
|
|
224
243
|
this.abortController?.abort();
|
|
225
244
|
this.resetState();
|
|
226
245
|
return;
|
|
227
246
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
247
|
+
if (attempt === 0) {
|
|
248
|
+
this.updateState({ isError: false });
|
|
249
|
+
if (this.abortController) this.abortController.abort();
|
|
250
|
+
this.abortController = new AbortController();
|
|
251
|
+
}
|
|
252
|
+
const currentSignal = this.abortController?.signal;
|
|
231
253
|
const url = new URL(`${this.apiUrl}/infer/${this.country.toLowerCase()}`);
|
|
232
254
|
const params = {
|
|
233
255
|
authKey: this.authKey,
|
|
234
256
|
query: text,
|
|
235
|
-
limit: this.
|
|
257
|
+
limit: this.currentLimit.toString()
|
|
236
258
|
};
|
|
237
259
|
url.search = new URLSearchParams(params).toString();
|
|
238
|
-
this.fetcher(url.toString(), { signal:
|
|
239
|
-
if (!res.ok)
|
|
260
|
+
this.fetcher(url.toString(), { signal: currentSignal }).then((res) => {
|
|
261
|
+
if (!res.ok) {
|
|
262
|
+
if (attempt < this.maxRetries && (res.status >= 500 || res.status === 429)) {
|
|
263
|
+
return this.retry(val, attempt, currentSignal);
|
|
264
|
+
}
|
|
265
|
+
throw new Error("Network error");
|
|
266
|
+
}
|
|
240
267
|
return res.json();
|
|
241
|
-
}).then((data) =>
|
|
242
|
-
if (
|
|
243
|
-
|
|
268
|
+
}).then((data) => {
|
|
269
|
+
if (data) this.mapResponseToState(data);
|
|
270
|
+
}).catch((e) => {
|
|
271
|
+
if (e.name === "AbortError") return;
|
|
272
|
+
if (attempt < this.maxRetries) {
|
|
273
|
+
return this.retry(val, attempt, currentSignal);
|
|
244
274
|
}
|
|
275
|
+
this.updateState({ isError: true, isLoading: false });
|
|
245
276
|
});
|
|
246
277
|
}
|
|
278
|
+
retry(val, attempt, signal) {
|
|
279
|
+
if (signal?.aborted) return;
|
|
280
|
+
const delay = Math.pow(2, attempt) * 200;
|
|
281
|
+
setTimeout(() => {
|
|
282
|
+
if (!signal?.aborted) {
|
|
283
|
+
this.executeFetch(val, attempt + 1);
|
|
284
|
+
}
|
|
285
|
+
}, delay);
|
|
286
|
+
}
|
|
247
287
|
mapResponseToState(data) {
|
|
248
288
|
const newState = {
|
|
249
289
|
stage: data.stage,
|
|
@@ -261,6 +301,8 @@ var InferCore = class {
|
|
|
261
301
|
uniqueSuggestions.push(item);
|
|
262
302
|
}
|
|
263
303
|
}
|
|
304
|
+
const totalCount = uniqueSuggestions.length + (data.cities?.length || 0) + (data.streets?.length || 0);
|
|
305
|
+
newState.hasMore = totalCount >= this.currentLimit;
|
|
264
306
|
if (data.stage === "mixed") {
|
|
265
307
|
newState.cities = data.cities || [];
|
|
266
308
|
newState.streets = data.streets || [];
|
|
@@ -281,6 +323,7 @@ var InferCore = class {
|
|
|
281
323
|
newState.cities = [];
|
|
282
324
|
newState.streets = [];
|
|
283
325
|
newState.isValid = true;
|
|
326
|
+
newState.hasMore = false;
|
|
284
327
|
this.updateState(newState);
|
|
285
328
|
const val = typeof autoSelectItem.value === "object" ? autoSelectItem.value : autoSelectItem.label;
|
|
286
329
|
this.onSelect(val);
|
|
@@ -290,7 +333,7 @@ var InferCore = class {
|
|
|
290
333
|
}
|
|
291
334
|
updateQueryAndFetch(nextQuery) {
|
|
292
335
|
this.updateState({ query: nextQuery, suggestions: [], cities: [], streets: [] });
|
|
293
|
-
this.updateState({ isLoading: true, isValid: false });
|
|
336
|
+
this.updateState({ isLoading: true, isValid: false, hasMore: false });
|
|
294
337
|
this.debouncedFetch(nextQuery);
|
|
295
338
|
setTimeout(() => {
|
|
296
339
|
this.isSelecting = false;
|
|
@@ -345,6 +388,7 @@ var DEFAULT_STYLES = `
|
|
|
345
388
|
.pro6pp-input {
|
|
346
389
|
width: 100%;
|
|
347
390
|
padding: 10px 12px;
|
|
391
|
+
padding-right: 48px;
|
|
348
392
|
border: 1px solid #e0e0e0;
|
|
349
393
|
border-radius: 4px;
|
|
350
394
|
font-size: 16px;
|
|
@@ -356,6 +400,57 @@ var DEFAULT_STYLES = `
|
|
|
356
400
|
border-color: #3b82f6;
|
|
357
401
|
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
358
402
|
}
|
|
403
|
+
|
|
404
|
+
.pro6pp-input-addons {
|
|
405
|
+
position: absolute;
|
|
406
|
+
right: 6px;
|
|
407
|
+
top: 0;
|
|
408
|
+
bottom: 0;
|
|
409
|
+
display: flex;
|
|
410
|
+
align-items: center;
|
|
411
|
+
gap: 2px;
|
|
412
|
+
pointer-events: none;
|
|
413
|
+
}
|
|
414
|
+
.pro6pp-input-addons > * {
|
|
415
|
+
pointer-events: auto;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
.pro6pp-clear-button {
|
|
419
|
+
background: none;
|
|
420
|
+
border: none;
|
|
421
|
+
width: 28px;
|
|
422
|
+
height: 28px;
|
|
423
|
+
cursor: pointer;
|
|
424
|
+
color: #a3a3a3;
|
|
425
|
+
display: flex;
|
|
426
|
+
align-items: center;
|
|
427
|
+
justify-content: center;
|
|
428
|
+
border-radius: 50%;
|
|
429
|
+
transition: color 0.2s, background-color 0.2s, transform 0.1s;
|
|
430
|
+
}
|
|
431
|
+
.pro6pp-clear-button:hover {
|
|
432
|
+
color: #1f2937;
|
|
433
|
+
background-color: #f3f4f6;
|
|
434
|
+
}
|
|
435
|
+
.pro6pp-clear-button:active {
|
|
436
|
+
transform: scale(0.92);
|
|
437
|
+
}
|
|
438
|
+
.pro6pp-clear-button svg {
|
|
439
|
+
width: 18px;
|
|
440
|
+
height: 18px;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
.pro6pp-loader {
|
|
444
|
+
width: 18px;
|
|
445
|
+
height: 18px;
|
|
446
|
+
margin: 0 4px;
|
|
447
|
+
border: 2px solid #e0e0e0;
|
|
448
|
+
border-top-color: #6b7280;
|
|
449
|
+
border-radius: 50%;
|
|
450
|
+
animation: pro6pp-spin 0.6s linear infinite;
|
|
451
|
+
flex-shrink: 0;
|
|
452
|
+
}
|
|
453
|
+
|
|
359
454
|
.pro6pp-dropdown {
|
|
360
455
|
position: absolute;
|
|
361
456
|
top: 100%;
|
|
@@ -366,27 +461,32 @@ var DEFAULT_STYLES = `
|
|
|
366
461
|
background: white;
|
|
367
462
|
border: 1px solid #e0e0e0;
|
|
368
463
|
border-radius: 4px;
|
|
369
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.
|
|
464
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
370
465
|
max-height: 300px;
|
|
371
466
|
overflow-y: auto;
|
|
467
|
+
display: flex;
|
|
468
|
+
flex-direction: column;
|
|
469
|
+
}
|
|
470
|
+
.pro6pp-list {
|
|
372
471
|
list-style: none !important;
|
|
373
472
|
padding: 0 !important;
|
|
374
473
|
margin: 0 !important;
|
|
474
|
+
flex-grow: 1;
|
|
375
475
|
}
|
|
376
476
|
.pro6pp-item {
|
|
377
|
-
padding:
|
|
477
|
+
padding: 12px 16px;
|
|
378
478
|
cursor: pointer;
|
|
379
479
|
display: flex;
|
|
380
480
|
flex-direction: row;
|
|
381
481
|
align-items: center;
|
|
382
|
-
color: #
|
|
482
|
+
color: #111827;
|
|
383
483
|
font-size: 14px;
|
|
384
484
|
line-height: 1.2;
|
|
385
485
|
white-space: nowrap;
|
|
386
486
|
overflow: hidden;
|
|
387
487
|
}
|
|
388
488
|
.pro6pp-item:hover, .pro6pp-item--active {
|
|
389
|
-
background-color: #
|
|
489
|
+
background-color: #f9fafb;
|
|
390
490
|
}
|
|
391
491
|
.pro6pp-item__label {
|
|
392
492
|
font-weight: 500;
|
|
@@ -394,7 +494,7 @@ var DEFAULT_STYLES = `
|
|
|
394
494
|
}
|
|
395
495
|
.pro6pp-item__subtitle {
|
|
396
496
|
font-size: 14px;
|
|
397
|
-
color: #
|
|
497
|
+
color: #6b7280;
|
|
398
498
|
overflow: hidden;
|
|
399
499
|
text-overflow: ellipsis;
|
|
400
500
|
flex-shrink: 1;
|
|
@@ -403,32 +503,34 @@ var DEFAULT_STYLES = `
|
|
|
403
503
|
margin-left: auto;
|
|
404
504
|
display: flex;
|
|
405
505
|
align-items: center;
|
|
406
|
-
color: #
|
|
506
|
+
color: #9ca3af;
|
|
407
507
|
padding-left: 8px;
|
|
408
508
|
}
|
|
409
509
|
.pro6pp-no-results {
|
|
410
|
-
padding:
|
|
411
|
-
color: #
|
|
510
|
+
padding: 16px;
|
|
511
|
+
color: #6b7280;
|
|
412
512
|
font-size: 14px;
|
|
413
513
|
text-align: center;
|
|
414
|
-
user-select: none;
|
|
415
|
-
pointer-events: none;
|
|
416
514
|
}
|
|
417
|
-
.pro6pp-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
515
|
+
.pro6pp-load-more {
|
|
516
|
+
width: 100%;
|
|
517
|
+
padding: 10px;
|
|
518
|
+
background: #f9fafb;
|
|
519
|
+
border: none;
|
|
520
|
+
border-top: 1px solid #e0e0e0;
|
|
521
|
+
color: #3b82f6;
|
|
522
|
+
font-size: 13px;
|
|
523
|
+
font-weight: 600;
|
|
524
|
+
cursor: pointer;
|
|
525
|
+
transition: background-color 0.2s;
|
|
526
|
+
flex-shrink: 0;
|
|
429
527
|
}
|
|
528
|
+
.pro6pp-load-more:hover {
|
|
529
|
+
background-color: #f3f4f6;
|
|
530
|
+
}
|
|
531
|
+
|
|
430
532
|
@keyframes pro6pp-spin {
|
|
431
|
-
to { transform:
|
|
533
|
+
to { transform: rotate(360deg); }
|
|
432
534
|
}
|
|
433
535
|
`;
|
|
434
536
|
|
|
@@ -445,7 +547,7 @@ function useInfer(config) {
|
|
|
445
547
|
}
|
|
446
548
|
}
|
|
447
549
|
});
|
|
448
|
-
}, [config.country, config.authKey, config.limit, config.debounceMs]);
|
|
550
|
+
}, [config.country, config.authKey, config.limit, config.debounceMs, config.maxRetries]);
|
|
449
551
|
return {
|
|
450
552
|
/** The current UI state (suggestions, loading status, query, etc.). */
|
|
451
553
|
state,
|
|
@@ -458,7 +560,9 @@ function useInfer(config) {
|
|
|
458
560
|
onKeyDown: (e) => core.handleKeyDown(e)
|
|
459
561
|
},
|
|
460
562
|
/** Function to manually select a specific suggestion. */
|
|
461
|
-
selectItem: (item) => core.selectItem(item)
|
|
563
|
+
selectItem: (item) => core.selectItem(item),
|
|
564
|
+
/** Function to load more results. */
|
|
565
|
+
loadMore: () => core.loadMore()
|
|
462
566
|
};
|
|
463
567
|
}
|
|
464
568
|
var Pro6PPInfer = ({
|
|
@@ -469,10 +573,12 @@ var Pro6PPInfer = ({
|
|
|
469
573
|
renderItem,
|
|
470
574
|
disableDefaultStyles = false,
|
|
471
575
|
noResultsText = "No results found",
|
|
576
|
+
loadMoreText = "Show more results...",
|
|
472
577
|
renderNoResults,
|
|
578
|
+
showClearButton = true,
|
|
473
579
|
...config
|
|
474
580
|
}) => {
|
|
475
|
-
const { state, selectItem, inputProps: coreInputProps } = useInfer(config);
|
|
581
|
+
const { state, selectItem, loadMore, inputProps: coreInputProps, core } = useInfer(config);
|
|
476
582
|
const [isOpen, setIsOpen] = useState(false);
|
|
477
583
|
const inputRef = useRef(null);
|
|
478
584
|
const wrapperRef = useRef(null);
|
|
@@ -509,6 +615,12 @@ var Pro6PPInfer = ({
|
|
|
509
615
|
inputRef.current.focus();
|
|
510
616
|
}
|
|
511
617
|
};
|
|
618
|
+
const handleClear = () => {
|
|
619
|
+
core.handleInput("");
|
|
620
|
+
if (inputRef.current) {
|
|
621
|
+
inputRef.current.focus();
|
|
622
|
+
}
|
|
623
|
+
};
|
|
512
624
|
const hasResults = items.length > 0;
|
|
513
625
|
const showNoResults = !state.isLoading && !state.isError && state.query.length > 0 && !hasResults && !state.isValid;
|
|
514
626
|
const showDropdown = isOpen && (hasResults || showNoResults);
|
|
@@ -527,36 +639,79 @@ var Pro6PPInfer = ({
|
|
|
527
639
|
inputProps?.onFocus?.(e);
|
|
528
640
|
}
|
|
529
641
|
}
|
|
530
|
-
),
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
642
|
+
), /* @__PURE__ */ React.createElement("div", { className: "pro6pp-input-addons" }, state.isLoading && /* @__PURE__ */ React.createElement("div", { className: "pro6pp-loader" }), showClearButton && state.query.length > 0 && /* @__PURE__ */ React.createElement(
|
|
643
|
+
"button",
|
|
644
|
+
{
|
|
645
|
+
type: "button",
|
|
646
|
+
className: "pro6pp-clear-button",
|
|
647
|
+
onClick: handleClear,
|
|
648
|
+
"aria-label": "Clear input"
|
|
649
|
+
},
|
|
650
|
+
/* @__PURE__ */ React.createElement(
|
|
651
|
+
"svg",
|
|
536
652
|
{
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
"
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
653
|
+
width: "14",
|
|
654
|
+
height: "14",
|
|
655
|
+
viewBox: "0 0 24 24",
|
|
656
|
+
fill: "none",
|
|
657
|
+
stroke: "currentColor",
|
|
658
|
+
strokeWidth: "2",
|
|
659
|
+
strokeLinecap: "round",
|
|
660
|
+
strokeLinejoin: "round"
|
|
543
661
|
},
|
|
544
|
-
|
|
545
|
-
|
|
662
|
+
/* @__PURE__ */ React.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
663
|
+
/* @__PURE__ */ React.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
664
|
+
)
|
|
665
|
+
))), showDropdown && /* @__PURE__ */ React.createElement(
|
|
666
|
+
"div",
|
|
667
|
+
{
|
|
668
|
+
className: "pro6pp-dropdown",
|
|
669
|
+
onWheel: (e) => e.stopPropagation(),
|
|
670
|
+
onMouseDown: (e) => e.stopPropagation()
|
|
671
|
+
},
|
|
672
|
+
/* @__PURE__ */ React.createElement("ul", { className: "pro6pp-list", role: "listbox" }, hasResults ? items.map((item, index) => {
|
|
673
|
+
const isActive = index === state.selectedSuggestionIndex;
|
|
674
|
+
const secondaryText = item.subtitle || (item.count !== void 0 ? item.count : "");
|
|
675
|
+
const showChevron = item.value === void 0 || item.value === null;
|
|
676
|
+
return /* @__PURE__ */ React.createElement(
|
|
677
|
+
"li",
|
|
546
678
|
{
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
strokeLinecap: "round",
|
|
554
|
-
strokeLinejoin: "round"
|
|
679
|
+
key: `${item.label}-${index}`,
|
|
680
|
+
role: "option",
|
|
681
|
+
"aria-selected": isActive,
|
|
682
|
+
className: `pro6pp-item ${isActive ? "pro6pp-item--active" : ""}`,
|
|
683
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
684
|
+
onClick: () => handleSelect(item)
|
|
555
685
|
},
|
|
556
|
-
/* @__PURE__ */ React.createElement("
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
686
|
+
renderItem ? renderItem(item, isActive) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", { className: "pro6pp-item__label" }, item.label), secondaryText && /* @__PURE__ */ React.createElement("span", { className: "pro6pp-item__subtitle" }, ", ", secondaryText), showChevron && /* @__PURE__ */ React.createElement("div", { className: "pro6pp-item__chevron" }, /* @__PURE__ */ React.createElement(
|
|
687
|
+
"svg",
|
|
688
|
+
{
|
|
689
|
+
width: "16",
|
|
690
|
+
height: "16",
|
|
691
|
+
viewBox: "0 0 24 24",
|
|
692
|
+
fill: "none",
|
|
693
|
+
stroke: "currentColor",
|
|
694
|
+
strokeWidth: "2",
|
|
695
|
+
strokeLinecap: "round",
|
|
696
|
+
strokeLinejoin: "round"
|
|
697
|
+
},
|
|
698
|
+
/* @__PURE__ */ React.createElement("polyline", { points: "9 18 15 12 9 6" })
|
|
699
|
+
)))
|
|
700
|
+
);
|
|
701
|
+
}) : /* @__PURE__ */ React.createElement("li", { className: "pro6pp-no-results" }, renderNoResults ? renderNoResults(state) : noResultsText)),
|
|
702
|
+
state.hasMore && /* @__PURE__ */ React.createElement(
|
|
703
|
+
"button",
|
|
704
|
+
{
|
|
705
|
+
type: "button",
|
|
706
|
+
className: "pro6pp-load-more",
|
|
707
|
+
onClick: (e) => {
|
|
708
|
+
e.preventDefault();
|
|
709
|
+
loadMore();
|
|
710
|
+
}
|
|
711
|
+
},
|
|
712
|
+
loadMoreText
|
|
713
|
+
)
|
|
714
|
+
));
|
|
560
715
|
};
|
|
561
716
|
export {
|
|
562
717
|
Pro6PPInfer,
|
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.
|
|
23
|
+
"version": "0.0.2-beta.9",
|
|
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.
|
|
49
|
+
"@pro6pp/infer-core": "0.0.2-beta.7"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@testing-library/dom": "^10.4.1",
|