@kws3/ui 1.9.2 → 1.9.3
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/CHANGELOG.mdx +3 -0
- package/forms/AutoComplete.svelte +15 -9
- package/forms/select/MultiSelect.svelte +12 -6
- package/package.json +2 -2
- package/utils/fuzzy.js +64 -65
- package/utils/fuzzysearch.js +2 -3
package/CHANGELOG.mdx
CHANGED
|
@@ -100,7 +100,7 @@ Default value: `<span>{option.label}</span>`
|
|
|
100
100
|
import { debounce } from "@kws3/ui/utils";
|
|
101
101
|
import { createEventDispatcher, onMount, tick } from "svelte";
|
|
102
102
|
import { createPopper } from "@popperjs/core";
|
|
103
|
-
import {
|
|
103
|
+
import { fuzzysearch } from "../utils/fuzzysearch";
|
|
104
104
|
|
|
105
105
|
const sameWidthPopperModifier = {
|
|
106
106
|
name: "sameWidth",
|
|
@@ -225,7 +225,8 @@ Default value: `<span>{option.label}</span>`
|
|
|
225
225
|
filtered_options = [], //list of options filtered by search query
|
|
226
226
|
normalised_options = [], //list of options normalised
|
|
227
227
|
options_loading = false, //indictaes whether async search function is running
|
|
228
|
-
mounted = false
|
|
228
|
+
mounted = false, //indicates whether component is mounted
|
|
229
|
+
fuzzyOpts = {}; // fuzzy.js lib options
|
|
229
230
|
|
|
230
231
|
let list_text_size = {
|
|
231
232
|
small: "7",
|
|
@@ -300,14 +301,18 @@ Default value: `<span>{option.label}</span>`
|
|
|
300
301
|
modifiers: [sameWidthPopperModifier],
|
|
301
302
|
});
|
|
302
303
|
|
|
303
|
-
if (allow_fuzzy_match
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
304
|
+
if (allow_fuzzy_match) {
|
|
305
|
+
fuzzyOpts = {
|
|
306
|
+
analyzeSubTerms: true,
|
|
307
|
+
analyzeSubTermDepth: 10,
|
|
308
|
+
highlighting: {
|
|
309
|
+
after: "",
|
|
310
|
+
before: "",
|
|
311
|
+
},
|
|
312
|
+
};
|
|
308
313
|
if (highlighted_results) {
|
|
309
|
-
|
|
310
|
-
|
|
314
|
+
fuzzyOpts.highlighting.before = `<span class="h">`;
|
|
315
|
+
fuzzyOpts.highlighting.after = "</span>";
|
|
311
316
|
}
|
|
312
317
|
}
|
|
313
318
|
|
|
@@ -431,6 +436,7 @@ Default value: `<span>{option.label}</span>`
|
|
|
431
436
|
let result = fuzzysearch(word, options, {
|
|
432
437
|
search_key: "label",
|
|
433
438
|
scoreThreshold,
|
|
439
|
+
fuzzyOpts,
|
|
434
440
|
});
|
|
435
441
|
opts = result;
|
|
436
442
|
}
|
|
@@ -164,7 +164,7 @@ Default value: `<span>{option[search_key] || option}</span>`
|
|
|
164
164
|
import { debounce } from "@kws3/ui/utils";
|
|
165
165
|
import { createEventDispatcher, onMount, tick } from "svelte";
|
|
166
166
|
import { createPopper } from "@popperjs/core";
|
|
167
|
-
import {
|
|
167
|
+
import { fuzzysearch } from "../../utils/fuzzysearch";
|
|
168
168
|
|
|
169
169
|
const sameWidthPopperModifier = {
|
|
170
170
|
name: "sameWidth",
|
|
@@ -326,6 +326,7 @@ Default value: `<span>{option[search_key] || option}</span>`
|
|
|
326
326
|
searchText = "",
|
|
327
327
|
searching = false,
|
|
328
328
|
showOptions = false,
|
|
329
|
+
fuzzyOpts = {}, // fuzzy.js lib options
|
|
329
330
|
filteredOptions = [], //list of options filtered by search query
|
|
330
331
|
normalisedOptions = [], //list of options normalised
|
|
331
332
|
selectedOptions = [], //list of options that are selected
|
|
@@ -485,11 +486,15 @@ Default value: `<span>{option[search_key] || option}</span>`
|
|
|
485
486
|
modifiers: [sameWidthPopperModifier],
|
|
486
487
|
});
|
|
487
488
|
|
|
488
|
-
if (allow_fuzzy_match
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
489
|
+
if (allow_fuzzy_match) {
|
|
490
|
+
fuzzyOpts = {
|
|
491
|
+
analyzeSubTerms: true,
|
|
492
|
+
analyzeSubTermDepth: 10,
|
|
493
|
+
highlighting: {
|
|
494
|
+
after: "",
|
|
495
|
+
before: "",
|
|
496
|
+
},
|
|
497
|
+
};
|
|
493
498
|
}
|
|
494
499
|
|
|
495
500
|
//normalize value for single versus multiselect
|
|
@@ -733,6 +738,7 @@ Default value: `<span>{option[search_key] || option}</span>`
|
|
|
733
738
|
let result = fuzzysearch(filter, options, {
|
|
734
739
|
search_key: used_search_key,
|
|
735
740
|
scoreThreshold,
|
|
741
|
+
fuzzyOpts,
|
|
736
742
|
});
|
|
737
743
|
filteredOptions = result;
|
|
738
744
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kws3/ui",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.3",
|
|
4
4
|
"description": "UI components for use with Svelte v3 applications.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"text-mask-core": "^5.1.2",
|
|
30
30
|
"tippy.js": "^6.3.1"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "c6a60f59d36f7bb3a6e4475c6c727c036d235581"
|
|
33
33
|
}
|
package/utils/fuzzy.js
CHANGED
|
@@ -2,20 +2,59 @@
|
|
|
2
2
|
* fuzzy.js v0.1.0
|
|
3
3
|
* (c) 2016 Ben Ripkens
|
|
4
4
|
* @license: MIT
|
|
5
|
+
* @params
|
|
6
|
+
* term : haystack
|
|
7
|
+
* query : needle
|
|
8
|
+
* opts: {
|
|
9
|
+
* analyzeSubTerms,
|
|
10
|
+
* analyzeSubTermDepth
|
|
11
|
+
* highlighting
|
|
12
|
+
* }
|
|
5
13
|
*/
|
|
6
14
|
/**
|
|
7
15
|
*
|
|
8
16
|
* Adapted from fuzzy.js for @kws3/ui to work with vite prebundling
|
|
9
17
|
*/
|
|
10
18
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
19
|
+
/*
|
|
20
|
+
* Whether or not fuzzy.js should analyze sub-terms, i.e. also
|
|
21
|
+
* check term starting positions != 0.
|
|
22
|
+
*
|
|
23
|
+
* Example:
|
|
24
|
+
* Given the term 'Halleluja' and query 'luja'
|
|
25
|
+
*
|
|
26
|
+
* Fuzzy.js scores this combination with an 8, when analyzeSubTerms is
|
|
27
|
+
* set to false, as the following matching string will be calculated:
|
|
28
|
+
* Ha[l]lel[uja]
|
|
29
|
+
*
|
|
30
|
+
* If you activate sub temr analysis though, the query will reach a score
|
|
31
|
+
* of 10, as the matching string looks as following:
|
|
32
|
+
* Halle[luja]
|
|
33
|
+
*
|
|
34
|
+
* Naturally, the second version is more expensive than the first one.
|
|
35
|
+
* You should therefore configure how many sub terms you which to analyse.
|
|
36
|
+
* This can be configured through opts.analyzeSubTermDepth = 10.
|
|
37
|
+
*/
|
|
14
38
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
39
|
+
export default function fuzzy(term, query, opts = {}) {
|
|
40
|
+
let analyzeSubTerms = opts.analyzeSubTerms ? opts.analyzeSubTerms : false;
|
|
41
|
+
let analyzeSubTermDepth = opts.analyzeSubTermDepth
|
|
42
|
+
? opts.analyzeSubTermDepth
|
|
43
|
+
: 10;
|
|
44
|
+
let highlighting = opts.highlighting
|
|
45
|
+
? opts.highlighting
|
|
46
|
+
: {
|
|
47
|
+
before: "<em>",
|
|
48
|
+
after: "</em>",
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
let max = calcFuzzyScore(term, query, highlighting);
|
|
52
|
+
let termLength = term.length;
|
|
53
|
+
|
|
54
|
+
if (analyzeSubTerms) {
|
|
55
|
+
for (let i = 1; i < termLength && i < analyzeSubTermDepth; i++) {
|
|
56
|
+
let subTerm = term.substring(i);
|
|
57
|
+
let score = calcFuzzyScore(subTerm, query, highlighting);
|
|
19
58
|
if (score.score > max.score) {
|
|
20
59
|
// we need to correct 'term' and 'matchedTerm', as calcFuzzyScore
|
|
21
60
|
// does not now that it operates on a substring. Doing it only for
|
|
@@ -28,26 +67,26 @@ var fuzzy = function fuzzy(term, query) {
|
|
|
28
67
|
}
|
|
29
68
|
|
|
30
69
|
return max;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function calcFuzzyScore(term, query, highlighting) {
|
|
73
|
+
let score = 0;
|
|
74
|
+
let termLength = term.length;
|
|
75
|
+
let queryLength = query.length;
|
|
76
|
+
let _highlighting = "";
|
|
77
|
+
let ti = 0;
|
|
39
78
|
// -1 would not work as this would break the calculations of bonus
|
|
40
79
|
// points for subsequent character matches. Something like
|
|
41
80
|
// Number.MIN_VALUE would be more appropriate, but unfortunately
|
|
42
81
|
// Number.MIN_VALUE + 1 equals 1...
|
|
43
|
-
|
|
82
|
+
let previousMatchingCharacter = -2;
|
|
44
83
|
|
|
45
|
-
for (
|
|
46
|
-
|
|
47
|
-
|
|
84
|
+
for (let qi = 0; qi < queryLength && ti < termLength; qi++) {
|
|
85
|
+
let qc = query.charAt(qi);
|
|
86
|
+
let lowerQc = qc.toLowerCase();
|
|
48
87
|
|
|
49
88
|
for (; ti < termLength; ti++) {
|
|
50
|
-
|
|
89
|
+
let tc = term.charAt(ti);
|
|
51
90
|
|
|
52
91
|
if (lowerQc === tc.toLowerCase()) {
|
|
53
92
|
score++;
|
|
@@ -56,62 +95,22 @@ var calcFuzzyScore = function calcFuzzyScore(term, query) {
|
|
|
56
95
|
score += 2;
|
|
57
96
|
}
|
|
58
97
|
|
|
59
|
-
highlighting
|
|
60
|
-
fuzzy.highlighting.before + tc + fuzzy.highlighting.after;
|
|
98
|
+
_highlighting += highlighting.before + tc + highlighting.after;
|
|
61
99
|
previousMatchingCharacter = ti;
|
|
62
100
|
ti++;
|
|
63
101
|
break;
|
|
64
102
|
} else {
|
|
65
|
-
|
|
103
|
+
_highlighting += tc;
|
|
66
104
|
}
|
|
67
105
|
}
|
|
68
106
|
}
|
|
69
107
|
|
|
70
|
-
|
|
108
|
+
_highlighting += term.substring(ti, term.length);
|
|
71
109
|
|
|
72
110
|
return {
|
|
73
111
|
score: score,
|
|
74
112
|
term: term,
|
|
75
113
|
query: query,
|
|
76
|
-
highlightedTerm:
|
|
114
|
+
highlightedTerm: _highlighting,
|
|
77
115
|
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
fuzzy.matchComparator = function matchComparator(m1, m2) {
|
|
81
|
-
return m2.score - m1.score !== 0
|
|
82
|
-
? m2.score - m1.score
|
|
83
|
-
: m1.term.length - m2.term.length;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
/*
|
|
87
|
-
* Whether or not fuzzy.js should analyze sub-terms, i.e. also
|
|
88
|
-
* check term starting positions != 0.
|
|
89
|
-
*
|
|
90
|
-
* Example:
|
|
91
|
-
* Given the term 'Halleluja' and query 'luja'
|
|
92
|
-
*
|
|
93
|
-
* Fuzzy.js scores this combination with an 8, when analyzeSubTerms is
|
|
94
|
-
* set to false, as the following matching string will be calculated:
|
|
95
|
-
* Ha[l]lel[uja]
|
|
96
|
-
*
|
|
97
|
-
* If you activate sub temr analysis though, the query will reach a score
|
|
98
|
-
* of 10, as the matching string looks as following:
|
|
99
|
-
* Halle[luja]
|
|
100
|
-
*
|
|
101
|
-
* Naturally, the second version is more expensive than the first one.
|
|
102
|
-
* You should therefore configure how many sub terms you which to analyse.
|
|
103
|
-
* This can be configured through fuzzy.analyzeSubTermDepth = 10.
|
|
104
|
-
*/
|
|
105
|
-
fuzzy.analyzeSubTerms = false;
|
|
106
|
-
|
|
107
|
-
/*
|
|
108
|
-
* How many sub terms should be analyzed.
|
|
109
|
-
*/
|
|
110
|
-
fuzzy.analyzeSubTermDepth = 10;
|
|
111
|
-
|
|
112
|
-
fuzzy.highlighting = {
|
|
113
|
-
before: "<em>",
|
|
114
|
-
after: "</em>",
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
export default fuzzy;
|
|
116
|
+
}
|
package/utils/fuzzysearch.js
CHANGED
|
@@ -3,6 +3,7 @@ import fuzzy from "./fuzzy.js";
|
|
|
3
3
|
export function fuzzysearch(needle, haystack, opts) {
|
|
4
4
|
let search_key = defaultValue(opts, "search_key", "value");
|
|
5
5
|
let scoreThreshold = defaultValue(opts, "scoreThreshold", 5);
|
|
6
|
+
let fuzzyOpts = opts.fuzzyOpts ? opts.fuzzyOpts : {};
|
|
6
7
|
|
|
7
8
|
let OPTS = haystack.map((option) => {
|
|
8
9
|
let item = { ...option };
|
|
@@ -14,7 +15,7 @@ export function fuzzysearch(needle, haystack, opts) {
|
|
|
14
15
|
|
|
15
16
|
search_key.forEach((s_key) => {
|
|
16
17
|
if (`${s_key}` in item) {
|
|
17
|
-
let output = fuzzy(option[s_key], needle);
|
|
18
|
+
let output = fuzzy(option[s_key], needle, fuzzyOpts);
|
|
18
19
|
item.original[s_key] = output.highlightedTerm;
|
|
19
20
|
item.score =
|
|
20
21
|
!item.score || (item.score && item.score < output.score)
|
|
@@ -38,5 +39,3 @@ export function fuzzysearch(needle, haystack, opts) {
|
|
|
38
39
|
function defaultValue(opts, key, value) {
|
|
39
40
|
return opts && opts[key] ? opts[key] : value;
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
-
export { fuzzy };
|