-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Expand file tree
/
Copy pathCommandMenuItemTextInput.tsx
More file actions
112 lines (99 loc) · 3.03 KB
/
CommandMenuItemTextInput.tsx
File metadata and controls
112 lines (99 loc) · 3.03 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
109
110
111
112
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
import { useRegisterInputEvents } from '@/object-record/record-field/ui/meta-types/input/hooks/useRegisterInputEvents';
import { TextInput } from '@/ui/input/components/TextInput';
import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack';
import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById';
import { currentFocusIdSelector } from '@/ui/utilities/focus/states/currentFocusIdSelector';
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import styled from '@emotion/styled';
import { useStore } from 'jotai';
import { useRef, useState } from 'react';
import { type IconComponent } from 'twenty-ui/display';
type CommandMenuItemTextInputProps = {
id: string;
label: string;
Icon?: IconComponent;
value: string;
onChange: (value: string) => void;
placeholder?: string;
};
const StyledRightAlignedTextInput = styled(TextInput)`
input {
text-align: right;
}
`;
export const CommandMenuItemTextInput = ({
id,
label,
Icon,
value,
onChange,
placeholder,
}: CommandMenuItemTextInputProps) => {
const inputRef = useRef<HTMLInputElement>(null);
const focusId = `${id}-input`;
const [draftValue, setDraftValue] = useState(value);
const store = useStore();
const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
const { removeFocusItemFromFocusStackById } =
useRemoveFocusItemFromFocusStackById();
const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {
event.target.select();
pushFocusItemToFocusStack({
focusId,
component: {
type: FocusComponentType.TEXT_INPUT,
instanceId: focusId,
},
globalHotkeysConfig: {
enableGlobalHotkeysConflictingWithKeyboard: false,
},
});
};
const handleBlur = () => {
const isInputStillFocused =
store.get(currentFocusIdSelector.atom) === focusId;
if (isInputStillFocused && draftValue !== value) {
onChange(draftValue);
}
removeFocusItemFromFocusStackById({ focusId });
};
const handleEscape = () => {
removeFocusItemFromFocusStackById({ focusId });
setDraftValue(value);
inputRef.current?.blur();
};
const handleEnter = () => {
inputRef.current?.blur();
};
useRegisterInputEvents<string>({
focusId,
inputRef: inputRef,
inputValue: draftValue,
onEscape: handleEscape,
onEnter: handleEnter,
});
const focusInput = () => {
inputRef.current?.focus();
};
return (
<CommandMenuItem
id={id}
label={label}
Icon={Icon}
onClick={focusInput}
RightComponent={
<StyledRightAlignedTextInput
ref={inputRef}
value={draftValue}
sizeVariant="sm"
onChange={setDraftValue}
onFocus={handleFocus}
onBlur={handleBlur}
placeholder={placeholder}
textClickOutsideId={focusId}
/>
}
/>
);
};