dictate-button 1.2.0 → 1.3.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.
- package/README.md +48 -3
- package/dist/dictate-button.js +1 -1
- package/dist/inject-exclusive.d.ts +1 -1
- package/dist/inject-exclusive.js +6 -62
- package/dist/inject-inclusive.d.ts +1 -1
- package/dist/inject-inclusive.js +6 -62
- package/dist/libs/index.d.ts +2 -0
- package/dist/libs/injectDictateButton.d.ts +20 -0
- package/dist/libs/injectDictateButton.js +81 -0
- package/dist/libs/injectDictateButtonOnLoad.d.ts +20 -0
- package/dist/libs/injectDictateButtonOnLoad.js +12 -0
- package/dist/libs.d.ts +2 -0
- package/dist/libs.js +6 -0
- package/package.json +17 -2
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ Developed for [dictate-button.io](https://dictate-button.io).
|
|
|
22
22
|
- textarea
|
|
23
23
|
- input[type="text"]
|
|
24
24
|
- input[type="search"]
|
|
25
|
-
- input
|
|
25
|
+
- input (without a type; defaults to text)
|
|
26
26
|
|
|
27
27
|
## Usage
|
|
28
28
|
|
|
@@ -35,6 +35,11 @@ Choose the auto-inject mode that best suits your needs:
|
|
|
35
35
|
| Exclusive | Enables for text fields with the `data-dictate-button-on` attribute only. | `inject-exclusive.js` |
|
|
36
36
|
| Inclusive | Enables for text fields without the `data-dictate-button-off` attribute. | `inject-inclusive.js` |
|
|
37
37
|
|
|
38
|
+
Both auto-inject modes:
|
|
39
|
+
- Automatically run on DOMContentLoaded (or immediately if the DOM is already loaded).
|
|
40
|
+
- Watch for DOM changes to apply the dictate button to newly added elements.
|
|
41
|
+
- Set the button’s language from `document.documentElement.lang` (if present). Long codes like `en-GB` are normalized to `en`.
|
|
42
|
+
|
|
38
43
|
### From CDN
|
|
39
44
|
|
|
40
45
|
#### Option 1: Using the exclusive auto-inject script
|
|
@@ -46,11 +51,13 @@ In your HTML `<head>` tag, add the following script tags:
|
|
|
46
51
|
<script type="module" crossorigin src="https://cdn.dictate-button.io/inject-exclusive.js"></script>
|
|
47
52
|
```
|
|
48
53
|
|
|
49
|
-
Add the `data-dictate-button-on` attribute to any `textarea
|
|
54
|
+
Add the `data-dictate-button-on` attribute to any `textarea`, `input[type="text"]`, `input[type="search"]`, or `input` without a `type` attribute:
|
|
50
55
|
|
|
51
56
|
```html
|
|
52
57
|
<textarea data-dictate-button-on></textarea>
|
|
53
58
|
<input type="text" data-dictate-button-on />
|
|
59
|
+
<input type="search" data-dictate-button-on />
|
|
60
|
+
<input data-dictate-button-on />
|
|
54
61
|
```
|
|
55
62
|
|
|
56
63
|
#### Option 2: Using the inclusive auto-inject script
|
|
@@ -62,13 +69,15 @@ In your HTML `<head>` tag, add the following script tags:
|
|
|
62
69
|
<script type="module" crossorigin src="https://cdn.dictate-button.io/inject-inclusive.js"></script>
|
|
63
70
|
```
|
|
64
71
|
|
|
65
|
-
All `textarea
|
|
72
|
+
All `textarea`, `input[type="text"]`, `input[type="search"]`, and `input` elements without a `type` attribute that lack `data-dictate-button-off` will be automatically enhanced by default.
|
|
66
73
|
|
|
67
74
|
To disable that for a specific field, add the `data-dictate-button-off` attribute to it this way:
|
|
68
75
|
|
|
69
76
|
```html
|
|
70
77
|
<textarea data-dictate-button-off></textarea>
|
|
71
78
|
<input type="text" data-dictate-button-off />
|
|
79
|
+
<input type="search" data-dictate-button-off />
|
|
80
|
+
<input data-dictate-button-off />
|
|
72
81
|
```
|
|
73
82
|
|
|
74
83
|
#### Option 3: Manual integration
|
|
@@ -102,6 +111,42 @@ import 'dictate-button/inject-inclusive'
|
|
|
102
111
|
|
|
103
112
|
To choose between **exclusive** and **inclusive** auto-inject modes, see the [Auto-inject modes](#auto-inject-modes) section.
|
|
104
113
|
|
|
114
|
+
### Advanced usage with library functions
|
|
115
|
+
|
|
116
|
+
If you need more control over when and how the dictate buttons are injected, you can use the library functions directly:
|
|
117
|
+
|
|
118
|
+
Tip: You can also import from subpaths (e.g., 'dictate-button/libs/injectDictateButton')
|
|
119
|
+
for smaller bundles, if your bundler resolves package subpath exports.
|
|
120
|
+
|
|
121
|
+
```js
|
|
122
|
+
import { injectDictateButton, injectDictateButtonOnLoad } from 'dictate-button/libs'
|
|
123
|
+
|
|
124
|
+
// Inject dictate buttons immediately to matching elements
|
|
125
|
+
injectDictateButton(
|
|
126
|
+
'textarea.custom-selector', // CSS selector for target elements
|
|
127
|
+
{
|
|
128
|
+
buttonSize: 30, // Button size in pixels (optional; default: 30)
|
|
129
|
+
verbose: false, // Log events to console (optional; default: false)
|
|
130
|
+
customApiEndpoint: 'https://api.example.com/transcribe' // Optional custom API endpoint
|
|
131
|
+
}
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
// Inject on DOM load with mutation observer to catch dynamically added elements
|
|
135
|
+
injectDictateButtonOnLoad(
|
|
136
|
+
'input.custom-selector', // CSS selector for target elements
|
|
137
|
+
{
|
|
138
|
+
buttonSize: 30, // Button size in pixels (optional; default: 30)
|
|
139
|
+
watchDomChanges: true, // Watch for DOM changes (optional; default: false)
|
|
140
|
+
verbose: false, // Log events to console (optional; default: false)
|
|
141
|
+
customApiEndpoint: 'https://api.example.com/transcribe' // Optional custom API endpoint
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Note: the injector mirrors the target field’s display/margins into the wrapper,
|
|
147
|
+
sets wrapper width to 100% for block-level fields, and adds padding to avoid the button overlapping text.
|
|
148
|
+
The wrapper also has the `dictate-button-wrapper` class for easy styling.
|
|
149
|
+
|
|
105
150
|
## Events
|
|
106
151
|
|
|
107
152
|
The dictate-button component emits the following events:
|
package/dist/dictate-button.js
CHANGED
|
@@ -605,7 +605,7 @@ const Vt = `
|
|
|
605
605
|
}
|
|
606
606
|
`;
|
|
607
607
|
var qt = /* @__PURE__ */ O('<div part=container class=dictate-button__container><style></style><div aria-live=polite class=dictate-button__status-announcer style="position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0"></div><button part=button class=dictate-button__button>'), Ht = /* @__PURE__ */ O('<svg part=icon class="dictate-button__icon dictate-button__icon--idle"fill=none viewBox="0 0 24 24"stroke-width=1.5 stroke=currentColor role=img aria-hidden=true><path stroke-linecap=round stroke-linejoin=round d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z">'), Gt = /* @__PURE__ */ O('<svg part=icon class="dictate-button__icon dictate-button__icon--recording"viewBox="0 0 24 24"fill=currentColor role=img aria-hidden=true><circle cx=12 cy=12 r=10>'), Wt = /* @__PURE__ */ O('<svg part=icon class="dictate-button__icon dictate-button__icon--processing"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round role=img aria-hidden=true><path d="M12 2v4"></path><path d="m16.2 7.8 2.9-2.9"></path><path d="M18 12h4"></path><path d="m16.2 16.2 2.9 2.9"></path><path d="M12 18v4"></path><path d="m4.9 19.1 2.9-2.9"></path><path d="M2 12h4"></path><path d="m4.9 4.9 2.9 2.9">'), Xt = /* @__PURE__ */ O('<svg part=icon class="dictate-button__icon dictate-button__icon--error"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=4 stroke-linecap=round stroke-linejoin=round role=img aria-hidden=true><line x1=12 x2=12 y1=4 y2=14></line><line x1=12 x2=12.01 y1=20 y2=20>');
|
|
608
|
-
console.debug("dictate-button version:", "1.
|
|
608
|
+
console.debug("dictate-button version:", "1.3.0");
|
|
609
609
|
const Jt = "https://api.dictate-button.io/transcribe", v = "dictate-button.io", H = -70, ot = -10, it = 0, Zt = 4, Qt = 0.25, Yt = 0.05;
|
|
610
610
|
zt("dictate-button", {
|
|
611
611
|
size: 30,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {}
|
|
1
|
+
export {};
|
package/dist/inject-exclusive.js
CHANGED
|
@@ -1,68 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import { injectDictateButtonOnLoad as t } from "./libs/injectDictateButtonOnLoad.js";
|
|
2
|
+
const a = 30, n = !0, e = !1, o = [
|
|
2
3
|
"textarea[data-dictate-button-on]:not([data-dictate-button-enabled])",
|
|
3
4
|
'input[type="text"][data-dictate-button-on]:not([data-dictate-button-enabled])',
|
|
4
5
|
'input[type="search"][data-dictate-button-on]:not([data-dictate-button-enabled])',
|
|
5
6
|
"input[data-dictate-button-on]:not([type]):not([data-dictate-button-enabled])"
|
|
6
7
|
].join(",");
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
a.style.position = "relative", a.style.display = "inline-block", a.style.width = "auto", a.style.color = "inherit", n.parentNode.insertBefore(a, n), n.setAttribute("data-dictate-button-enabled", ""), a.appendChild(n), n.style.boxSizing = "border-box";
|
|
12
|
-
const e = document.createElement("dictate-button");
|
|
13
|
-
e.size = 30, e.style.position = "absolute", e.style.right = "0", e.style.top = T(a, n) + "px", e.style.margin = "10px";
|
|
14
|
-
const s = document.documentElement.lang;
|
|
15
|
-
s && s.length >= 2 && (e.language = s), e.addEventListener("recording:started", (o) => {
|
|
16
|
-
console.log("recording:started", o);
|
|
17
|
-
}), e.addEventListener("recording:stopped", (o) => {
|
|
18
|
-
console.log("recording:stopped", o);
|
|
19
|
-
}), e.addEventListener("recording:failed", (o) => {
|
|
20
|
-
console.log("recording:failed", o), i(n);
|
|
21
|
-
}), e.addEventListener("transcribing:started", (o) => {
|
|
22
|
-
console.log("transcribing:started", o);
|
|
23
|
-
}), e.addEventListener("transcribing:finished", (o) => {
|
|
24
|
-
console.log("transcribing:finished", o);
|
|
25
|
-
const c = o.detail;
|
|
26
|
-
f(n, c);
|
|
27
|
-
}), e.addEventListener("transcribing:failed", (o) => {
|
|
28
|
-
console.log("transcribing:failed", o), i(n);
|
|
29
|
-
}), a.appendChild(e);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
function T(t, n) {
|
|
33
|
-
if (n.tagName.toLowerCase() === "textarea")
|
|
34
|
-
return 0;
|
|
35
|
-
const a = Math.round(
|
|
36
|
-
t.clientHeight / 2 - 30 / 2 - 10
|
|
37
|
-
);
|
|
38
|
-
return Math.max(0, a);
|
|
39
|
-
}
|
|
40
|
-
function f(t, n) {
|
|
41
|
-
const a = typeof n == "string" ? n.trim() : String(n ?? "").trim();
|
|
42
|
-
if (a.length === 0)
|
|
43
|
-
return;
|
|
44
|
-
const e = t.selectionStart || 0, s = t.selectionEnd || 0, o = e > 0 ? t.value.charAt(e - 1) : "", d = o && !/\s/.test(o), c = s < t.value.length ? t.value.charAt(s) : "", p = c && !/\s/.test(c), r = (d ? " " : "") + a + (p ? " " : ""), l = e + r.length, u = typeof t.scrollTop == "number" ? t.scrollTop : null;
|
|
45
|
-
if (typeof t.setRangeText == "function")
|
|
46
|
-
t.setRangeText(r, e, s, "end");
|
|
47
|
-
else {
|
|
48
|
-
t.value = t.value.substring(0, e) + r + t.value.substring(s);
|
|
49
|
-
try {
|
|
50
|
-
t.selectionStart = l, t.selectionEnd = l;
|
|
51
|
-
} catch {
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
u !== null && (t.scrollTop = u), t.dispatchEvent(new Event("input", { bubbles: !0, composed: !0 })), i(t);
|
|
55
|
-
}
|
|
56
|
-
function i(t) {
|
|
57
|
-
try {
|
|
58
|
-
t.focus({ preventScroll: !0 });
|
|
59
|
-
} catch {
|
|
60
|
-
t.focus();
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
64
|
-
g(), new MutationObserver(g).observe(document.body, {
|
|
65
|
-
childList: !0,
|
|
66
|
-
subtree: !0
|
|
67
|
-
});
|
|
8
|
+
t(o, {
|
|
9
|
+
buttonSize: a,
|
|
10
|
+
watchDomChanges: n,
|
|
11
|
+
verbose: e
|
|
68
12
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {}
|
|
1
|
+
export {};
|
package/dist/inject-inclusive.js
CHANGED
|
@@ -1,68 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import { injectDictateButtonOnLoad as t } from "./libs/injectDictateButtonOnLoad.js";
|
|
2
|
+
const a = 30, n = !0, o = !1, e = [
|
|
2
3
|
"textarea:not([data-dictate-button-off]):not([data-dictate-button-enabled])",
|
|
3
4
|
'input[type="text"]:not([data-dictate-button-off]):not([data-dictate-button-enabled])',
|
|
4
5
|
'input[type="search"]:not([data-dictate-button-off]):not([data-dictate-button-enabled])',
|
|
5
6
|
"input:not([type]):not([data-dictate-button-off]):not([data-dictate-button-enabled])"
|
|
6
7
|
].join(",");
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
a.style.position = "relative", a.style.display = "inline-block", a.style.width = "auto", a.style.color = "inherit", n.parentNode.insertBefore(a, n), n.setAttribute("data-dictate-button-enabled", ""), a.appendChild(n), n.style.boxSizing = "border-box";
|
|
12
|
-
const e = document.createElement("dictate-button");
|
|
13
|
-
e.size = 30, e.style.position = "absolute", e.style.right = "0", e.style.top = f(a, n) + "px", e.style.margin = "10px";
|
|
14
|
-
const s = document.documentElement.lang;
|
|
15
|
-
s && s.length >= 2 && (e.language = s), e.addEventListener("recording:started", (o) => {
|
|
16
|
-
console.log("recording:started", o);
|
|
17
|
-
}), e.addEventListener("recording:stopped", (o) => {
|
|
18
|
-
console.log("recording:stopped", o);
|
|
19
|
-
}), e.addEventListener("recording:failed", (o) => {
|
|
20
|
-
console.log("recording:failed", o), i(n);
|
|
21
|
-
}), e.addEventListener("transcribing:started", (o) => {
|
|
22
|
-
console.log("transcribing:started", o);
|
|
23
|
-
}), e.addEventListener("transcribing:finished", (o) => {
|
|
24
|
-
console.log("transcribing:finished", o);
|
|
25
|
-
const c = o.detail;
|
|
26
|
-
T(n, c);
|
|
27
|
-
}), e.addEventListener("transcribing:failed", (o) => {
|
|
28
|
-
console.log("transcribing:failed", o), i(n);
|
|
29
|
-
}), a.appendChild(e);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
function f(t, n) {
|
|
33
|
-
if (n.tagName.toLowerCase() === "textarea")
|
|
34
|
-
return 0;
|
|
35
|
-
const a = Math.round(
|
|
36
|
-
t.clientHeight / 2 - 30 / 2 - 10
|
|
37
|
-
);
|
|
38
|
-
return Math.max(0, a);
|
|
39
|
-
}
|
|
40
|
-
function T(t, n) {
|
|
41
|
-
const a = typeof n == "string" ? n.trim() : String(n ?? "").trim();
|
|
42
|
-
if (a.length === 0)
|
|
43
|
-
return;
|
|
44
|
-
const e = t.selectionStart || 0, s = t.selectionEnd || 0, o = e > 0 ? t.value.charAt(e - 1) : "", d = o && !/\s/.test(o), c = s < t.value.length ? t.value.charAt(s) : "", p = c && !/\s/.test(c), r = (d ? " " : "") + a + (p ? " " : ""), l = e + r.length, u = typeof t.scrollTop == "number" ? t.scrollTop : null;
|
|
45
|
-
if (typeof t.setRangeText == "function")
|
|
46
|
-
t.setRangeText(r, e, s, "end");
|
|
47
|
-
else {
|
|
48
|
-
t.value = t.value.substring(0, e) + r + t.value.substring(s);
|
|
49
|
-
try {
|
|
50
|
-
t.selectionStart = l, t.selectionEnd = l;
|
|
51
|
-
} catch {
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
u !== null && (t.scrollTop = u), t.dispatchEvent(new Event("input", { bubbles: !0, composed: !0 })), i(t);
|
|
55
|
-
}
|
|
56
|
-
function i(t) {
|
|
57
|
-
try {
|
|
58
|
-
t.focus({ preventScroll: !0 });
|
|
59
|
-
} catch {
|
|
60
|
-
t.focus();
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
64
|
-
g(), new MutationObserver(g).observe(document.body, {
|
|
65
|
-
childList: !0,
|
|
66
|
-
subtree: !0
|
|
67
|
-
});
|
|
8
|
+
t(e, {
|
|
9
|
+
buttonSize: a,
|
|
10
|
+
watchDomChanges: n,
|
|
11
|
+
verbose: o
|
|
68
12
|
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for the dictate button injection.
|
|
3
|
+
*/
|
|
4
|
+
export interface InjectDictateButtonOptions {
|
|
5
|
+
/** Size of the button in pixels; defaults to 30 */
|
|
6
|
+
buttonSize?: number;
|
|
7
|
+
/** Whether to log events to console */
|
|
8
|
+
verbose?: boolean;
|
|
9
|
+
/** Optional custom API endpoint */
|
|
10
|
+
customApiEndpoint?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Inject the dictate-button component to text fields.
|
|
14
|
+
*
|
|
15
|
+
* Optionally log button events to the console (verbose mode).
|
|
16
|
+
*
|
|
17
|
+
* @param {string} textFieldSelector - CSS selector for text fields to enhance
|
|
18
|
+
* @param {InjectDictateButtonOptions} options - Configuration options
|
|
19
|
+
*/
|
|
20
|
+
export declare function injectDictateButton(textFieldSelector: string, options?: InjectDictateButtonOptions): void;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
function y(t, c = {}) {
|
|
2
|
+
const { buttonSize: i = 30, verbose: o = !1, customApiEndpoint: r } = c, p = document.querySelectorAll(t);
|
|
3
|
+
for (const n of p) {
|
|
4
|
+
if (n.hasAttribute("data-dictate-button-enabled")) continue;
|
|
5
|
+
const d = n.parentNode;
|
|
6
|
+
if (!n.isConnected || !d) {
|
|
7
|
+
o && console.debug("injectDictateButton: skipping detached field", n);
|
|
8
|
+
continue;
|
|
9
|
+
}
|
|
10
|
+
n.setAttribute("data-dictate-button-enabled", "");
|
|
11
|
+
const s = document.createElement("div");
|
|
12
|
+
s.style.position = "relative";
|
|
13
|
+
const l = getComputedStyle(n), u = l.display === "block";
|
|
14
|
+
s.style.display = u ? "block" : "inline-block", s.style.width = u ? "100%" : "auto", s.style.color = "inherit", s.classList.add("dictate-button-wrapper"), d.insertBefore(s, n), s.appendChild(n), s.style.margin = l.margin, n.style.margin = "0", n.style.boxSizing = "border-box";
|
|
15
|
+
const g = parseFloat(
|
|
16
|
+
l.paddingRight || "10px"
|
|
17
|
+
);
|
|
18
|
+
n.style.paddingRight = `${i + g * 2}px`;
|
|
19
|
+
const e = document.createElement("dictate-button");
|
|
20
|
+
e.size = i, e.style.position = "absolute", e.style.right = "0", e.style.top = m(
|
|
21
|
+
s,
|
|
22
|
+
n,
|
|
23
|
+
i
|
|
24
|
+
), e.style.marginRight = e.style.marginLeft = `${g}px`, e.style.marginTop = "0", e.style.marginBottom = "0", r && (e.apiEndpoint = r), e.language = h(), e.addEventListener("recording:started", (a) => {
|
|
25
|
+
o && console.debug("recording:started", a);
|
|
26
|
+
}), e.addEventListener("recording:stopped", (a) => {
|
|
27
|
+
o && console.debug("recording:stopped", a);
|
|
28
|
+
}), e.addEventListener("recording:failed", (a) => {
|
|
29
|
+
o && console.debug("recording:failed", a), f(n);
|
|
30
|
+
}), e.addEventListener("transcribing:started", (a) => {
|
|
31
|
+
o && console.debug("transcribing:started", a);
|
|
32
|
+
}), e.addEventListener("transcribing:finished", (a) => {
|
|
33
|
+
o && console.debug("transcribing:finished", a);
|
|
34
|
+
const b = a.detail;
|
|
35
|
+
T(n, b);
|
|
36
|
+
}), e.addEventListener("transcribing:failed", (a) => {
|
|
37
|
+
o && console.debug("transcribing:failed", a), f(n);
|
|
38
|
+
}), s.appendChild(e);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function h() {
|
|
42
|
+
const t = document.documentElement.lang;
|
|
43
|
+
if (t && t.length >= 2)
|
|
44
|
+
try {
|
|
45
|
+
return (Intl?.Locale ? new Intl.Locale(t) : null)?.language ?? t.split(/[-_]/)[0].toLowerCase();
|
|
46
|
+
} catch {
|
|
47
|
+
return t.split(/[-_]/)[0].toLowerCase();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function m(t, c, i) {
|
|
51
|
+
if (c.tagName.toLowerCase() === "textarea")
|
|
52
|
+
return getComputedStyle(c).paddingTop || "10px";
|
|
53
|
+
const o = Math.round(t.clientHeight / 2 - i / 2);
|
|
54
|
+
return `${Math.max(0, o)}px`;
|
|
55
|
+
}
|
|
56
|
+
function T(t, c) {
|
|
57
|
+
const i = typeof c == "string" ? c.trim() : String(c ?? "").trim();
|
|
58
|
+
if (i.length === 0)
|
|
59
|
+
return;
|
|
60
|
+
const o = t.selectionStart ?? 0, r = t.selectionEnd ?? 0, p = o > 0 ? t.value.charAt(o - 1) : "", n = p && !/\s/.test(p), d = r < t.value.length ? t.value.charAt(r) : "", s = d && !/\s/.test(d), l = (n ? " " : "") + i + (s ? " " : ""), u = o + l.length, g = typeof t.scrollTop == "number" ? t.scrollTop : null;
|
|
61
|
+
if (typeof t.setRangeText == "function")
|
|
62
|
+
t.setRangeText(l, o, r, "end");
|
|
63
|
+
else {
|
|
64
|
+
t.value = t.value.substring(0, o) + l + t.value.substring(r);
|
|
65
|
+
try {
|
|
66
|
+
t.selectionStart = u, t.selectionEnd = u;
|
|
67
|
+
} catch {
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
g !== null && (t.scrollTop = g), t.dispatchEvent(new Event("input", { bubbles: !0, composed: !0 })), f(t);
|
|
71
|
+
}
|
|
72
|
+
function f(t) {
|
|
73
|
+
try {
|
|
74
|
+
t.focus({ preventScroll: !0 });
|
|
75
|
+
} catch {
|
|
76
|
+
t.focus();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
y as injectDictateButton
|
|
81
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { InjectDictateButtonOptions } from './injectDictateButton';
|
|
2
|
+
/**
|
|
3
|
+
* Options for injecting the dictate button on load, extends the base options.
|
|
4
|
+
*/
|
|
5
|
+
export interface InjectDictateButtonOnLoadOptions extends InjectDictateButtonOptions {
|
|
6
|
+
/** Whether to watch for DOM changes and re-inject the component */
|
|
7
|
+
watchDomChanges?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Add a DOMContentLoaded event listener which injects the dictate-button component to text fields
|
|
11
|
+
* or run it immediately if DOM is already loaded.
|
|
12
|
+
*
|
|
13
|
+
* Optionally watch for DOM changes to re-inject the component.
|
|
14
|
+
*
|
|
15
|
+
* Optionally log button events to the console (verbose mode).
|
|
16
|
+
*
|
|
17
|
+
* @param {string} textFieldSelector - CSS selector for text fields to enhance
|
|
18
|
+
* @param {InjectDictateButtonOnLoadOptions} options - Configuration options
|
|
19
|
+
*/
|
|
20
|
+
export declare function injectDictateButtonOnLoad(textFieldSelector: string, options?: InjectDictateButtonOnLoadOptions): void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { injectDictateButton as o } from "./injectDictateButton.js";
|
|
2
|
+
function u(t, e = {}) {
|
|
3
|
+
const { watchDomChanges: r = !1 } = e, n = () => {
|
|
4
|
+
o(t, e), r && document.body && new MutationObserver(() => {
|
|
5
|
+
o(t, e);
|
|
6
|
+
}).observe(document.body, { childList: !0, subtree: !0 });
|
|
7
|
+
};
|
|
8
|
+
document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", n, { once: !0 }) : n();
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
u as injectDictateButtonOnLoad
|
|
12
|
+
};
|
package/dist/libs.d.ts
ADDED
package/dist/libs.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dictate-button",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Dictate Button (Web Component)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"custom-element",
|
|
@@ -25,6 +25,21 @@
|
|
|
25
25
|
"import": "./dist/dictate-button.js",
|
|
26
26
|
"default": "./dist/dictate-button.js"
|
|
27
27
|
},
|
|
28
|
+
"./libs": {
|
|
29
|
+
"types": "./dist/libs/index.d.ts",
|
|
30
|
+
"import": "./dist/libs/index.js",
|
|
31
|
+
"default": "./dist/libs/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./libs/injectDictateButton": {
|
|
34
|
+
"types": "./dist/libs/injectDictateButton.d.ts",
|
|
35
|
+
"import": "./dist/libs/injectDictateButton.js",
|
|
36
|
+
"default": "./dist/libs/injectDictateButton.js"
|
|
37
|
+
},
|
|
38
|
+
"./libs/injectDictateButtonOnLoad": {
|
|
39
|
+
"types": "./dist/libs/injectDictateButtonOnLoad.d.ts",
|
|
40
|
+
"import": "./dist/libs/injectDictateButtonOnLoad.js",
|
|
41
|
+
"default": "./dist/libs/injectDictateButtonOnLoad.js"
|
|
42
|
+
},
|
|
28
43
|
"./inject-exclusive": {
|
|
29
44
|
"types": "./dist/inject-exclusive.d.ts",
|
|
30
45
|
"import": "./dist/inject-exclusive.js",
|
|
@@ -50,7 +65,7 @@
|
|
|
50
65
|
"devDependencies": {
|
|
51
66
|
"prettier": "^3.6.2",
|
|
52
67
|
"typescript": "^5.9.2",
|
|
53
|
-
"vite": "^7.1.
|
|
68
|
+
"vite": "^7.1.4",
|
|
54
69
|
"vite-plugin-dts": "^4.5.4",
|
|
55
70
|
"vite-plugin-solid": "^2.11.8",
|
|
56
71
|
"vite-plugin-static-copy": "^3.1.2"
|