-
Notifications
You must be signed in to change notification settings - Fork 1
/
handleFieldMouseDown.ts
125 lines (111 loc) · 3.58 KB
/
handleFieldMouseDown.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { throttle } from "lodash-es";
import { sendFieldEvent } from "../generators/generateOverlay";
import {
ALLOWED_INLINE_EDITABLE_FIELD,
VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY,
numericInputRegex,
} from "./constants";
import { FieldDataType } from "./types/index.types";
import { VisualBuilderPostMessageEvents } from "./types/postMessage.types";
import { insertSpaceAtCursor } from "./insertSpaceAtCursor";
export function handleFieldInput(e: Event): void {
const event = e as InputEvent;
const targetElement = event.target as HTMLElement;
const fieldType = targetElement.getAttribute(
VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY
) as FieldDataType | null;
if (
event.type === "input" &&
ALLOWED_INLINE_EDITABLE_FIELD.includes(fieldType as FieldDataType)
) {
throttledFieldSync();
}
}
const throttledFieldSync = throttle(() => {
try {
const visualBuilderContainer = document.querySelector(
".visual-builder__container"
) as HTMLElement;
if (!visualBuilderContainer) return;
sendFieldEvent({
visualBuilderContainer,
eventType: VisualBuilderPostMessageEvents.SYNC_FIELD,
});
} catch (error) {
console.error("Error in throttledFieldSync", error);
}
}, 300);
export function handleFieldKeyDown(e: Event): void {
const event = e as KeyboardEvent;
const targetElement = event.target as HTMLElement;
const fieldType = targetElement.getAttribute(
VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY
) as FieldDataType | null;
if (targetElement.tagName === "BUTTON") {
handleKeyDownOnButton(event);
}
if (fieldType === FieldDataType.NUMBER) {
handleNumericFieldKeyDown(event);
} else if (fieldType === FieldDataType.SINGLELINE) {
handleSingleLineFieldKeyDown(event);
}
}
// spaces do not work inside a button content-editable
// this adds a space and moves the cursor ahead, the
// button press event is also prevented
function handleKeyDownOnButton(e: KeyboardEvent) {
if (e.code === "Space" && e.target) {
e.preventDefault();
insertSpaceAtCursor(e.target as HTMLElement);
}
}
function handleSingleLineFieldKeyDown(e: KeyboardEvent) {
if (e.code === "Enter") {
e.preventDefault();
}
}
function handleNumericFieldKeyDown(event: KeyboardEvent): void {
const targetElement = event.target as HTMLElement;
const allowedKeys = [
"Backspace",
"Tab",
"Enter",
"End",
"Home",
"ArrowLeft",
"ArrowRight",
"Delete",
];
if (
event.ctrlKey ||
event.metaKey ||
event.altKey ||
allowedKeys.includes(event.code)
) {
// Allow Ctrl, Cmd, Alt, and special keys
return;
}
if (event.code.includes("Digit")) {
return;
}
const nonNumericAllowedCharacters = ["-", ".", "e", "E"];
if (!nonNumericAllowedCharacters.includes(event.key)) {
event.preventDefault();
return;
}
const selection = {
startOffset: window.getSelection()?.getRangeAt(0).startOffset || 0,
endOffset: window.getSelection()?.getRangeAt(0).endOffset || 0,
};
const existingInput = targetElement.textContent || "";
const currentOutputArr = existingInput.split("");
currentOutputArr.splice(
selection.startOffset,
selection.endOffset - selection.startOffset,
event.key
);
const currentInput = currentOutputArr.join("");
if (!numericInputRegex.test(currentInput)) {
event.preventDefault();
}
}