frayerjj-frontend 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frayerjj-frontend",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "My base frontend for various projects",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -23,7 +23,6 @@
23
23
  "@popperjs/core": "^2.11.8",
24
24
  "bootstrap": "^5.3.8",
25
25
  "ckeditor5": "^47.6.1",
26
- "corejs-typeahead": "^1.3.4",
27
26
  "cropperjs": "^2.1.0",
28
27
  "flag-icons": "^7.5.0",
29
28
  "libphonenumber-js": "^1.12.39",
@@ -0,0 +1,70 @@
1
+ export const autocomplete = {
2
+ evalPattern: (pattern, item) => {
3
+ let result = pattern.replace(/\$\{(\w+)\}/g, (match, key) => {
4
+ return item[key] !== undefined && item[key] !== null ? item[key] : '';
5
+ });
6
+ result = result.replace(/\(\s*\)/g, '').trim();
7
+ return result.replace(/\s+/g, ' ');
8
+ },
9
+ init: () => {
10
+ document.querySelectorAll('input.autocomplete').forEach(el => {
11
+ const uri = el.getAttribute('data-uri');
12
+ const num_results = el.getAttribute('num-results') ?? 10;
13
+ const expire_length = el.getAttribute('expire-length') ?? 250;
14
+ const display_pattern = el.getAttribute('display-pattern') ?? '${name}';
15
+
16
+ const ul = document.createElement('ul');
17
+ ul.classList.add('autocomplete-dropdown');
18
+ ul.style.display = 'none';
19
+
20
+ el.parentElement.classList.add('position-relative')
21
+ el.parentElement.append(ul);
22
+
23
+ let timeout = null;
24
+
25
+ el.addEventListener('input', () => {
26
+ clearTimeout(timeout);
27
+
28
+ if (el.value.length < 3) {
29
+ ul.style.display = 'none';
30
+ return;
31
+ }
32
+
33
+ timeout = setTimeout(async () => {
34
+ try {
35
+ const response = await fetch(`${uri}?q=${el.value}&num_results=${num_results}`);
36
+ const data = await response.json();
37
+
38
+ ul.innerHTML = '';
39
+
40
+ if (data.length > 0) {
41
+ data.forEach(it => {
42
+ const li = document.createElement('li');
43
+ const label = autocomplete.evalPattern(display_pattern, it);
44
+ li.textContent = label;
45
+
46
+ li.addEventListener('click', () => {
47
+ el.value = label;
48
+ ul.innerHTML = '';
49
+ ul.style.display = 'none';
50
+ const selectedEvent = new Event('autocomplete.selected', { bubbles: true });
51
+ selectedEvent.selection = it;
52
+ el.dispatchEvent(selectedEvent);
53
+ });
54
+
55
+ ul.appendChild(li);
56
+ });
57
+ ul.style.display = 'block';
58
+ } else ul.style.display = 'none';
59
+ } catch (err) {
60
+ msg.error("Autocomplete fetch failed", err);
61
+ }
62
+ }, expire_length);
63
+ });
64
+
65
+ document.addEventListener('click', ev => {
66
+ if (!el.contains(ev.target) && !ul.contains(ev.target)) ul.style.display = 'none';
67
+ });
68
+ });
69
+ }
70
+ };
@@ -0,0 +1,24 @@
1
+ .autocomplete-dropdown {
2
+ position: absolute;
3
+ top: 100%;
4
+ left: 0;
5
+ right: 0;
6
+ background: white;
7
+ border: 1px solid #ccc;
8
+ border-top: none;
9
+ list-style: none;
10
+ padding: 0;
11
+ margin: 0;
12
+ z-index: 1000;
13
+ max-height: 200px;
14
+ overflow-y: auto;
15
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
16
+ li {
17
+ padding: 10px;
18
+ cursor: pointer;
19
+ border-bottom: 1px solid #eee;
20
+ &:hover {
21
+ background-color: #f0f7ff;
22
+ }
23
+ }
24
+ }
@@ -37,78 +37,6 @@ span.required {
37
37
  border-color: #dc3545;
38
38
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e");
39
39
  }
40
- .tt-query, .tt-hint {
41
- padding: 8px 12px;
42
- font-size: 17px;
43
- line-height: 30px;
44
- border: 2px solid $color-light-gray;
45
- border-radius: 8px;
46
- outline: none;
47
- }
48
- .tt-query {
49
- box-shadow: inset 0 1px 1px $color-light-gray;
50
- }
51
- .tt-hint {
52
- color: $color-white
53
- }
54
- .tt-dropdown-menu {
55
- width: 422px;
56
- margin-top: 12px;
57
- padding: 8px 0;
58
- background-color: $color-white;
59
- border: 1px solid $color-light-gray;
60
- border-radius: 8px;
61
- box-shadow: 0 5px 10px $color-light-gray;
62
- }
63
- .tt-suggestion {
64
- padding: 3px 20px;
65
- font-size: 18px;
66
- line-height: 24px;
67
- }
68
- .tt-suggestion.tt-is-under-cursor {
69
- color: $color-white;
70
- background-color: #0097cf;
71
- }
72
- .twitter-typeahead {
73
- display: block !important;
74
- }
75
- .tt-menu {
76
- background-color: $color-white;
77
- border: 1px solid $color-light-gray;
78
- border-radius: 4px;
79
- box-shadow: 0 6px 12px $color-light-gray;
80
- cursor: default;
81
- padding: .5em 0;
82
- top: 3.25em !important;
83
- &::before, &::after {
84
- border-bottom: 7px solid $color-light-gray;
85
- border-left: 7px solid transparent;
86
- border-right: 7px solid transparent;
87
- border-top: 0;
88
- box-sizing: border-box;
89
- content: '';
90
- display: inline-block;
91
- left: 6px;
92
- position: absolute;
93
- top: -7px;
94
- }
95
- &::after {
96
- border-bottom: 6px solid $color-white;
97
- border-left: 6px solid transparent;
98
- border-right: 6px solid transparent;
99
- border-top: 0;
100
- box-sizing: border-box;
101
- content: '';
102
- display: inline-block;
103
- left: 7px;
104
- position: absolute;
105
- top: -6px;
106
- }
107
- .tt-selectable:hover {
108
- background-color: $color-light-gray-background;
109
- cursor: pointer;
110
- }
111
- }
112
40
  .token {
113
41
  display: inline-block;
114
42
  background-color: $color-light-gray-background;
@@ -13,3 +13,4 @@
13
13
  @import 'loading';
14
14
  @import 'forms';
15
15
  @import 'wizard';
16
+ @import 'autocomplete';