marathi_typing 0.1.3 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f7da6deb5a3d1bd52b560302e0e92b442c5932f73894c966381c7241125c18e
4
- data.tar.gz: c56dbcc87be46f67e6d35107ecfb148280422903a86f1dd76b453cef6bd4f99f
3
+ metadata.gz: 8f9141d8b16760161d8c02f9611f2b28faf4c51430bf02dc4c9ea958cd5aa2c6
4
+ data.tar.gz: d080cc2cdc1cd09aac409e3dee8d069205f3582950aefe0828787f96c08071ee
5
5
  SHA512:
6
- metadata.gz: 74094b83da6d95f2706932319064aa9381b6dc8cdd50b792ed434f0d3826e40589ad94a3b0a4623aac0840a780929c3a0a5ea3ccfa14c10148b78dd82421dee4
7
- data.tar.gz: 5acfb3c4a6dcd827865956863229ea4c147663e01123e9f47964486438d43735d99b175c479126047e05732aefc00a36253a8b9e9cef5e44c267ceb068fd033f
6
+ metadata.gz: d0cbb74bb7d19520fdd564cc6eeaecca4504d96cbcf0638e4c50f9c13f94cb627bb600d7afa5e13dd28e69790dc6a765dbf81dfe6fd3db79e964101b8d7ba4ed
7
+ data.tar.gz: 37d6525b0e2d1e04152d79e710666f18fd5feb208e18852e0de93dd9c55a0b46f44437ea475974f0b03cbc6b470b61e3748c96810ce905231ea50cab9b4e48f1
@@ -1,7 +1,8 @@
1
1
  import { Controller } from "@hotwired/stimulus"
2
2
 
3
3
  export default class extends Controller {
4
- static targets = ["input"]
4
+ static targets = ["input"];
5
+
5
6
  timeout = null
6
7
 
7
8
 
@@ -14,16 +15,13 @@ export default class extends Controller {
14
15
  this.suggestionsTarget = this.buildSuggestionsBox()
15
16
 
16
17
  input.addEventListener("keydown", (e) => {
17
-
18
18
  if (e.key === " ") {
19
19
  this.skipNextSuggestionFetch = true;
20
20
  }
21
21
  });
22
22
 
23
23
  input.addEventListener("input", (e) => {
24
-
25
24
  if (this.skipNextSuggestionFetch) {
26
-
27
25
  this.skipNextSuggestionFetch = false;
28
26
  return;
29
27
  }
@@ -33,13 +31,11 @@ export default class extends Controller {
33
31
  input.addEventListener("keyup", (e) => {
34
32
 
35
33
  if (e.key === " ") {
36
-
37
34
  this.selectFirstSuggestion();
38
35
  }
39
36
  });
40
37
 
41
38
  document.addEventListener("click", this.handleClickOutside);
42
-
43
39
  }
44
40
 
45
41
  fetchSuggestions(event) {
@@ -48,14 +44,21 @@ export default class extends Controller {
48
44
 
49
45
  clearTimeout(this.timeout)
50
46
  this.timeout = setTimeout(() => {
51
- const lastWord = value.split(" ").pop()
52
47
 
53
- fetch(`${this.apiUrl}?text=${lastWord}&itc=mr-t-i0-und&num=5&cp=0&cs=1&ie=utf-8&oe=utf-8&app=demopage`)
48
+ const { word: currentWord } = this.getCurrentWordAtCursor(this.inputTarget);
49
+
50
+ console.log("currentWord: ", currentWord)
51
+
52
+ if (!currentWord || !/^[a-zA-Z]+$/.test(currentWord)) return;
53
+ // if (!currentWord) return;
54
+
55
+
56
+ fetch(`${this.apiUrl}?text=${currentWord}&itc=mr-t-i0-und&num=5&cp=0&cs=1&ie=utf-8&oe=utf-8&app=demopage`)
54
57
  .then(res => res.json())
55
58
  .then(data => {
56
59
  if (data[0] === "SUCCESS") {
57
60
  const suggestions = data[1][0][1]
58
- this.showSuggestions(suggestions, lastWord)
61
+ this.showSuggestions(suggestions, currentWord)
59
62
  }
60
63
  })
61
64
  }, 300)
@@ -66,13 +69,12 @@ export default class extends Controller {
66
69
  const box = document.createElement("div")
67
70
  box.className = "marathi-suggestions";
68
71
  box.style.position = "absolute";
69
- box.style.background = "#fff";
72
+ box.style.background = "#808080";
70
73
  box.style.border = "0px solid #ccc";
71
74
  box.style.zIndex = "9999";
72
75
  box.style.padding = "0px";
73
76
  box.style.color = "black";
74
77
 
75
- // Get the position of the input field
76
78
  const rect = this.inputTarget.getBoundingClientRect();
77
79
  const scrollOffset = window.scrollY || window.pageYOffset;
78
80
 
@@ -85,10 +87,7 @@ export default class extends Controller {
85
87
  }
86
88
 
87
89
  showSuggestions(suggestions, lastWord) {
88
- this.suggestionsTarget.innerHTML = ""
89
- this.suggestionsTarget.style.border = "1px solid #ccc";
90
- this.suggestionsTarget.style.border = "4px";
91
-
90
+ this.showSuggestionsBox();
92
91
 
93
92
  suggestions.forEach(suggestion => {
94
93
  const option = document.createElement("div")
@@ -107,37 +106,55 @@ export default class extends Controller {
107
106
  this.suggestionsTarget.appendChild(originalOption);
108
107
  }
109
108
 
110
- selectFirstSuggestion() {
111
109
 
110
+
111
+ selectFirstSuggestion() {
112
112
  if (!this.suggestionsTarget || this.suggestionsTarget.children.length === 0) return;
113
113
 
114
114
  const firstOption = this.suggestionsTarget.querySelector(".marathi-suggestion");
115
115
 
116
116
  if (firstOption) {
117
117
  const suggestion = firstOption.textContent;
118
- const value = this.inputTarget.value.trim();
119
- const lastWord = value.split(" ").pop();
120
- this.selectSuggestion(suggestion, lastWord);
118
+ const input = this.inputTarget;
119
+ let { word: currentWord } = this.getCurrentWordAtCursor(input);
120
+
121
+ // If space was pressed, caret is after the space => no current word
122
+ if (!currentWord) {
123
+ const valueBeforeCursor = input.value.slice(0, input.selectionStart).trimEnd();
124
+ const words = valueBeforeCursor.split(/\s+/);
125
+ currentWord = words[words.length - 1] || "";
126
+ }
127
+
128
+
129
+ if (!currentWord) return;
130
+
131
+ console.log("currentWord:", currentWord, " suggestion:", suggestion);
132
+
133
+
134
+ this.selectSuggestion(suggestion, currentWord);
121
135
  }
122
136
  }
123
137
 
138
+ selectSuggestion(selected, originalWord) {
139
+ const input = this.inputTarget;
140
+ const { wordStart, wordEnd } = this.getCurrentWordAtCursor(input);
124
141
 
125
- selectSuggestion(selected, lastWord) {
126
- let currentValue = this.inputTarget.value;
127
- const trailingSpace = currentValue.endsWith(" ") ? " " : "";
142
+ if (wordStart == null || wordEnd == null) return;
128
143
 
129
- // Remove trailing space temporarily
130
- currentValue = currentValue.trimEnd();
144
+ const value = input.value;
131
145
 
132
- // Replace the last word
133
- const newValue = currentValue.replace(new RegExp(`${lastWord}$`), selected);
146
+ // Reconstruct the value with the selected word
147
+ const newValue = value.slice(0, wordStart) + selected + value.slice(wordEnd);
134
148
 
135
- // Re-apply trailing space if needed
136
- this.inputTarget.value = newValue + trailingSpace;
149
+ // Update the input value and set caret after inserted suggestion
150
+ input.value = newValue;
151
+
152
+ // Move caret to after the inserted suggestion
153
+ const caretPos = wordStart + selected.length;
154
+ input.setSelectionRange(caretPos, caretPos);
155
+
156
+ this.hideSuggestions();
137
157
 
138
- this.suggestionsTarget.innerHTML = "";
139
- this.suggestionsTarget.style.border = "0";
140
- this.suggestionsTarget.style.padding = "0";
141
158
  }
142
159
 
143
160
  handleClickOutside = (event) => {
@@ -145,12 +162,56 @@ export default class extends Controller {
145
162
  const isClickInsideSuggestions = this.suggestionsTarget?.contains(event.target);
146
163
 
147
164
  if (!isClickInsideInput && !isClickInsideSuggestions) {
148
- this.suggestionsTarget.innerHTML = "";
149
- this.suggestionsTarget.style.border = "0";
150
- this.suggestionsTarget.style.padding = "0";
165
+ this.hideSuggestions();
151
166
  }
152
167
  };
153
168
 
154
169
 
155
- }
170
+ getCurrentWordAtCursor(input) {
171
+ const value = input.value;
172
+ let cursorPos = input.selectionStart;
173
+
174
+ // If cursor is just after a space, move it back to find previous word
175
+ if (cursorPos > 0 && value[cursorPos - 1] === " ") {
176
+ cursorPos--;
177
+ }
178
+
179
+ // Skip any Devanagari characters while going backwards
180
+ let wordStart = cursorPos;
181
+ while (
182
+ wordStart > 0 &&
183
+ value[wordStart - 1].match(/[a-zA-Z0-9]/) // Only count English letters and numbers
184
+ ) {
185
+ wordStart--;
186
+ }
187
+
188
+ // Skip Devanagari going forward too
189
+ let wordEnd = cursorPos;
190
+ while (
191
+ wordEnd < value.length &&
192
+ value[wordEnd].match(/[a-zA-Z0-9]/)
193
+ ) {
194
+ wordEnd++;
195
+ }
196
+
197
+
198
+ let word = value.slice(wordStart, wordEnd);
199
+
200
+ return { word, wordStart, wordEnd };
201
+ }
156
202
 
203
+
204
+
205
+ hideSuggestions() {
206
+ this.suggestionsTarget.innerHTML = "";
207
+ this.suggestionsTarget.style.border = "0";
208
+ this.suggestionsTarget.style.padding = "0";
209
+ }
210
+
211
+ showSuggestionsBox() {
212
+ this.suggestionsTarget.innerHTML = "";
213
+ this.suggestionsTarget.style.border = "1px solid #0a0a0a";
214
+ this.suggestionsTarget.style.padding = "4px";
215
+ }
216
+
217
+ }
@@ -1,3 +1,3 @@
1
1
  module MarathiTyping
2
- VERSION = '0.1.3'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marathi_typing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ajit Dhanje