-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathenableInlineEditing.ts
More file actions
108 lines (93 loc) · 4.13 KB
/
enableInlineEditing.ts
File metadata and controls
108 lines (93 loc) · 4.13 KB
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
import { throttle } from "lodash-es";
import { VisualBuilder } from "../index";
import {
isEllipsisActive,
generatePseudoEditableElement,
} from "../generators/generatePseudoEditableField";
import { VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY } from "./constants";
import { getMultilinePlaintext } from "./getMultilinePlaintext";
import { handleFieldInput, handleFieldKeyDown } from "./handleFieldMouseDown";
import { FieldDataType, VisualBuilderEditContext } from "./types/index.types";
import { updateFocussedState } from "./updateFocussedState";
import { pasteAsPlainText } from "./pasteAsPlainText";
export function enableInlineEditing({
expectedFieldData,
editableElement,
fieldType,
elements,
}: {
expectedFieldData: any;
editableElement: HTMLElement;
fieldType: FieldDataType;
elements: VisualBuilderEditContext;
}) {
const { visualBuilderContainer, resizeObserver } = elements;
let actualEditableField = editableElement as HTMLElement;
VisualBuilder.VisualBuilderGlobalState.value.focusFieldValue =
actualEditableField?.innerText;
const elementComputedDisplay =
window.getComputedStyle(actualEditableField).display;
let textContent =
(editableElement as HTMLElement).innerText ||
editableElement.textContent ||
"";
if (fieldType === FieldDataType.MULTILINE) {
textContent = getMultilinePlaintext(actualEditableField);
actualEditableField.addEventListener("paste", pasteAsPlainText);
}
const expectedTextContent = expectedFieldData;
const isFieldLastEdited = document.querySelector("[data-cs-last-edited]") === editableElement;
if (
(expectedTextContent && textContent !== expectedTextContent) ||
isEllipsisActive(editableElement as HTMLElement) ||
isFieldLastEdited
) {
// TODO: Testing will be done in the E2E.
const pseudoEditableField = generatePseudoEditableElement(
{ editableElement: editableElement as HTMLElement },
{ textContent: expectedFieldData }
);
// Hide original element immediately, disabling any transitions/animations
const originalElement = editableElement as HTMLElement;
originalElement.style.visibility = "hidden";
originalElement.style.transition = "none";
originalElement.style.animation = "none";
// set field type attribute to the pseudo editable field
// ensures proper keydown handling similar to the actual editable field
pseudoEditableField.setAttribute(
VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY,
fieldType
);
visualBuilderContainer.appendChild(pseudoEditableField);
actualEditableField = pseudoEditableField;
if (fieldType === FieldDataType.MULTILINE)
actualEditableField.addEventListener("paste", pasteAsPlainText);
// we will unobserve this in hideOverlay
elements.resizeObserver.observe(pseudoEditableField);
} else if (elementComputedDisplay === "inline") {
// if the editable field is inline
const onInlineElementInput = throttle(() => {
const overlayWrapper = visualBuilderContainer.querySelector(
".visual-builder__overlay__wrapper"
) as HTMLDivElement;
const focusedToolbar = visualBuilderContainer.querySelector(
".visual-builder__focused-toolbar"
) as HTMLDivElement;
updateFocussedState({
editableElement: actualEditableField,
visualBuilderContainer,
overlayWrapper,
focusedToolbar,
resizeObserver,
});
}, 200);
actualEditableField.addEventListener("input", onInlineElementInput);
}
actualEditableField.setAttribute("contenteditable", "true");
actualEditableField.addEventListener("input", handleFieldInput);
actualEditableField.addEventListener("keydown", handleFieldKeyDown);
editableElement.setAttribute("data-cs-last-edited", "true");
// focus on the contenteditable element to start accepting input
actualEditableField.focus();
return;
}