marathi_typing 0.1.2 → 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: 48d1b5510e3ce8ed69245b076104f3865b6c74ad1d4ce07394c47f8c5b08d9aa
4
- data.tar.gz: 7e735d1d796b2c2cb26f2412a6136dd6fd75db772467279ff123d8cd9de8ef48
3
+ metadata.gz: 8f9141d8b16760161d8c02f9611f2b28faf4c51430bf02dc4c9ea958cd5aa2c6
4
+ data.tar.gz: d080cc2cdc1cd09aac409e3dee8d069205f3582950aefe0828787f96c08071ee
5
5
  SHA512:
6
- metadata.gz: acd0feff334b2e7edf6a3e2fae89d137a5c40ce9024b27f226da25448a1eb474fd11508b996ea3ef95346f734c231f1e8e4961533ab85c5e05129df6b318218f
7
- data.tar.gz: 3255f38a8ac16a26ce0595520c0f5b01f3ae0378012ebc4575d02fda7a90b726e517a7171efea4093a73a988548d8c9af6096d3514fe49abe2f3b61c8ce4232f
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,11 +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
 
38
+ document.addEventListener("click", this.handleClickOutside);
41
39
  }
42
40
 
43
41
  fetchSuggestions(event) {
@@ -46,14 +44,21 @@ export default class extends Controller {
46
44
 
47
45
  clearTimeout(this.timeout)
48
46
  this.timeout = setTimeout(() => {
49
- const lastWord = value.split(" ").pop()
50
47
 
51
- 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`)
52
57
  .then(res => res.json())
53
58
  .then(data => {
54
59
  if (data[0] === "SUCCESS") {
55
60
  const suggestions = data[1][0][1]
56
- this.showSuggestions(suggestions, lastWord)
61
+ this.showSuggestions(suggestions, currentWord)
57
62
  }
58
63
  })
59
64
  }, 300)
@@ -64,13 +69,12 @@ export default class extends Controller {
64
69
  const box = document.createElement("div")
65
70
  box.className = "marathi-suggestions";
66
71
  box.style.position = "absolute";
67
- box.style.background = "#fff";
72
+ box.style.background = "#808080";
68
73
  box.style.border = "0px solid #ccc";
69
74
  box.style.zIndex = "9999";
70
75
  box.style.padding = "0px";
71
76
  box.style.color = "black";
72
77
 
73
- // Get the position of the input field
74
78
  const rect = this.inputTarget.getBoundingClientRect();
75
79
  const scrollOffset = window.scrollY || window.pageYOffset;
76
80
 
@@ -83,10 +87,7 @@ export default class extends Controller {
83
87
  }
84
88
 
85
89
  showSuggestions(suggestions, lastWord) {
86
- this.suggestionsTarget.innerHTML = ""
87
- this.suggestionsTarget.style.border = "1px solid #ccc";
88
- this.suggestionsTarget.style.border = "4px";
89
-
90
+ this.showSuggestionsBox();
90
91
 
91
92
  suggestions.forEach(suggestion => {
92
93
  const option = document.createElement("div")
@@ -105,37 +106,112 @@ export default class extends Controller {
105
106
  this.suggestionsTarget.appendChild(originalOption);
106
107
  }
107
108
 
108
- selectFirstSuggestion() {
109
109
 
110
+
111
+ selectFirstSuggestion() {
110
112
  if (!this.suggestionsTarget || this.suggestionsTarget.children.length === 0) return;
111
113
 
112
114
  const firstOption = this.suggestionsTarget.querySelector(".marathi-suggestion");
113
115
 
114
116
  if (firstOption) {
115
117
  const suggestion = firstOption.textContent;
116
- const value = this.inputTarget.value.trim();
117
- const lastWord = value.split(" ").pop();
118
- 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);
119
135
  }
120
136
  }
121
137
 
138
+ selectSuggestion(selected, originalWord) {
139
+ const input = this.inputTarget;
140
+ const { wordStart, wordEnd } = this.getCurrentWordAtCursor(input);
141
+
142
+ if (wordStart == null || wordEnd == null) return;
122
143
 
123
- selectSuggestion(selected, lastWord) {
124
- let currentValue = this.inputTarget.value;
125
- const trailingSpace = currentValue.endsWith(" ") ? " " : "";
144
+ const value = input.value;
126
145
 
127
- // Remove trailing space temporarily
128
- currentValue = currentValue.trimEnd();
146
+ // Reconstruct the value with the selected word
147
+ const newValue = value.slice(0, wordStart) + selected + value.slice(wordEnd);
129
148
 
130
- // Replace the last word
131
- const newValue = currentValue.replace(new RegExp(`${lastWord}$`), selected);
149
+ // Update the input value and set caret after inserted suggestion
150
+ input.value = newValue;
132
151
 
133
- // Re-apply trailing space if needed
134
- this.inputTarget.value = newValue + trailingSpace;
152
+ // Move caret to after the inserted suggestion
153
+ const caretPos = wordStart + selected.length;
154
+ input.setSelectionRange(caretPos, caretPos);
135
155
 
156
+ this.hideSuggestions();
157
+
158
+ }
159
+
160
+ handleClickOutside = (event) => {
161
+ const isClickInsideInput = this.inputTarget.contains(event.target);
162
+ const isClickInsideSuggestions = this.suggestionsTarget?.contains(event.target);
163
+
164
+ if (!isClickInsideInput && !isClickInsideSuggestions) {
165
+ this.hideSuggestions();
166
+ }
167
+ };
168
+
169
+
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
+ }
202
+
203
+
204
+
205
+ hideSuggestions() {
136
206
  this.suggestionsTarget.innerHTML = "";
137
207
  this.suggestionsTarget.style.border = "0";
138
208
  this.suggestionsTarget.style.padding = "0";
139
209
  }
140
210
 
211
+ showSuggestionsBox() {
212
+ this.suggestionsTarget.innerHTML = "";
213
+ this.suggestionsTarget.style.border = "1px solid #0a0a0a";
214
+ this.suggestionsTarget.style.padding = "4px";
215
+ }
216
+
141
217
  }
@@ -1,3 +1,3 @@
1
1
  module MarathiTyping
2
- VERSION = '0.1.2'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marathi_typing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ajit Dhanje
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-14 00:00:00.000000000 Z
11
+ date: 2025-04-15 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: