@remit/ui 0.0.135 → 0.0.137

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": "@remit/ui",
3
- "version": "0.0.135",
3
+ "version": "0.0.137",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src"
@@ -140,7 +140,7 @@ export const ComposeAddressField = ({
140
140
  }, [commitInput, suggest.dismiss]);
141
141
 
142
142
  return (
143
- <div className="relative">
143
+ <div className="relative" data-address-field={label}>
144
144
  <div className="flex items-start gap-2">
145
145
  <label
146
146
  htmlFor={`address-field-${label}`}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * `isWritingElsewhere` against a real focused element (#839) — mounted on jsdom
3
+ * rather than a stub, so the `type` fallback is the platform's own and not one
4
+ * the test agrees with.
5
+ */
6
+ import "@remit/test-dom";
7
+ import assert from "node:assert/strict";
8
+ import { afterEach, describe, it } from "node:test";
9
+ import { isWritingElsewhere } from "./editor-focus.js";
10
+
11
+ const editor = document.createElement("div");
12
+
13
+ const focusInput = (type: string | null): void => {
14
+ const input = document.createElement("input");
15
+ if (type !== null) input.setAttribute("type", type);
16
+ document.body.append(input);
17
+ input.focus();
18
+ };
19
+
20
+ afterEach(() => {
21
+ document.body.replaceChildren();
22
+ });
23
+
24
+ describe("isWritingElsewhere", () => {
25
+ it("reads an input the platform renders as text as writing", () => {
26
+ for (const type of [
27
+ "text",
28
+ "search",
29
+ "email",
30
+ "url",
31
+ "tel",
32
+ "password",
33
+ "number",
34
+ "date",
35
+ "datetime-local",
36
+ "month",
37
+ "time",
38
+ "week",
39
+ ]) {
40
+ document.body.replaceChildren();
41
+ focusInput(type);
42
+ assert.equal(isWritingElsewhere(editor), true, type);
43
+ }
44
+ });
45
+
46
+ it("reads an empty type as writing", () => {
47
+ // HTML falls back to a text field, so the reader may be mid-sentence in it.
48
+ focusInput("");
49
+ assert.equal(isWritingElsewhere(editor), true);
50
+ });
51
+
52
+ it("reads an unrecognised type as writing", () => {
53
+ focusInput("wibble");
54
+ assert.equal(isWritingElsewhere(editor), true);
55
+ });
56
+
57
+ it("reads a missing type as writing", () => {
58
+ focusInput(null);
59
+ assert.equal(isWritingElsewhere(editor), true);
60
+ });
61
+
62
+ it("leaves the controls alone", () => {
63
+ for (const type of [
64
+ "button",
65
+ "checkbox",
66
+ "color",
67
+ "file",
68
+ "image",
69
+ "radio",
70
+ "range",
71
+ "reset",
72
+ "submit",
73
+ ]) {
74
+ document.body.replaceChildren();
75
+ focusInput(type);
76
+ assert.equal(isWritingElsewhere(editor), false, type);
77
+ }
78
+ });
79
+
80
+ it("ignores the case the type is written in", () => {
81
+ focusInput("CheckBox");
82
+ assert.equal(isWritingElsewhere(editor), false);
83
+ });
84
+
85
+ it("is not writing elsewhere when nothing holds the caret", () => {
86
+ assert.equal(isWritingElsewhere(editor), false);
87
+ });
88
+ });
@@ -13,23 +13,26 @@
13
13
  */
14
14
 
15
15
  /**
16
- * The types an `<input>` accepts prose in. Everything else it can be — a
17
- * checkbox, a radio, a button, a file or colour picker is a control the
18
- * reader clicks, not one they are mid-word in.
16
+ * The types an `<input>` is a control rather than a writing surface in — a
17
+ * checkbox, a radio, a button, a file or colour picker, something the reader
18
+ * clicks and is never mid-word in.
19
+ *
20
+ * Named the other way round on purpose. An `<input>` with an empty or
21
+ * unrecognised `type` renders as a text field, so listing the ones that accept
22
+ * prose would read every new or misspelt type as a control and take the caret
23
+ * out of a field the reader is typing in.
19
24
  */
20
- const TEXT_INPUT_TYPES = new Set([
21
- "text",
22
- "search",
23
- "email",
24
- "url",
25
- "tel",
26
- "password",
27
- "number",
28
- "date",
29
- "datetime-local",
30
- "month",
31
- "time",
32
- "week",
25
+ const NON_TEXT_INPUT_TYPES = new Set([
26
+ "button",
27
+ "checkbox",
28
+ "color",
29
+ "file",
30
+ "hidden",
31
+ "image",
32
+ "radio",
33
+ "range",
34
+ "reset",
35
+ "submit",
33
36
  ]);
34
37
 
35
38
  /**
@@ -59,7 +62,7 @@ const takesTyping = (element: Element): boolean => {
59
62
  if (tag === "SELECT") return true;
60
63
  if (tag === "INPUT") {
61
64
  const type = (element.getAttribute("type") ?? "text").toLowerCase();
62
- return TEXT_INPUT_TYPES.has(type);
65
+ return !NON_TEXT_INPUT_TYPES.has(type);
63
66
  }
64
67
  // The attribute as well as the property: `isContentEditable` is computed by
65
68
  // the engine, and a document that never lays out does not answer for it.