Skip to content

Commit 8a14810

Browse files
committed
chore: Add Integer Annotation Type
1 parent 9fb1a50 commit 8a14810

3 files changed

Lines changed: 65 additions & 24 deletions

File tree

src/components/shared/ReactFlow/FlowCanvas/TaskNode/AnnotationsEditor/AnnotationsInput.tsx

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { type ChangeEvent, useCallback, useEffect, useState } from "react";
1+
import {
2+
type ChangeEvent,
3+
type KeyboardEvent,
4+
useCallback,
5+
useEffect,
6+
useState,
7+
} from "react";
28

39
import { MultilineTextInputDialog } from "@/components/shared/Dialogs/MultilineTextInputDialog";
410
import { Button } from "@/components/ui/button";
@@ -48,6 +54,8 @@ export const AnnotationsInput = ({
4854
const inputType = config?.type ?? "string";
4955
const placeholder = config?.label ?? "";
5056

57+
const isNumericType = inputType === "number" || inputType === "integer";
58+
5159
const handleExpand = useCallback(() => {
5260
setIsDialogOpen(true);
5361
}, []);
@@ -88,6 +96,36 @@ export const AnnotationsInput = ({
8896
}
8997
}, []);
9098

99+
const handleNumericInputChange = useCallback(
100+
(e: ChangeEvent<HTMLInputElement>) => {
101+
let newValue = e.target.value;
102+
103+
if (inputType === "integer") {
104+
newValue = newValue.replace(/[.,]/g, "");
105+
}
106+
107+
if (newValue === "") {
108+
setInputValue(newValue);
109+
return;
110+
}
111+
112+
const numericValue = Number(newValue);
113+
if (!isNaN(numericValue)) {
114+
setInputValue(newValue);
115+
}
116+
},
117+
[],
118+
);
119+
120+
const handleNumericInputKeyDown = useCallback(
121+
(e: KeyboardEvent<HTMLInputElement>) => {
122+
if (inputType === "integer" && (e.key === "." || e.key === ",")) {
123+
e.preventDefault();
124+
}
125+
},
126+
[inputType],
127+
);
128+
91129
const handleQuantityKeyInputChange = useCallback(
92130
(e: ChangeEvent<HTMLInputElement>) => {
93131
if (!config?.annotation) return;
@@ -186,12 +224,12 @@ export const AnnotationsInput = ({
186224

187225
if (onBlur && lastSavedValue !== inputValue && !isInvalid) {
188226
let value = inputValue;
189-
if (
190-
config?.type === "number" &&
191-
!isNaN(Number(inputValue)) &&
192-
inputValue !== ""
193-
) {
194-
value = clamp(Number(inputValue), config.min, config.max).toString();
227+
if (isNumericType && !isNaN(Number(inputValue)) && inputValue !== "") {
228+
value = clamp(Number(inputValue), config?.min, config?.max).toString();
229+
230+
if (inputType === "integer") {
231+
value = Math.floor(Number(value)).toString();
232+
}
195233
}
196234

197235
onBlur(value);
@@ -201,6 +239,8 @@ export const AnnotationsInput = ({
201239
onBlur,
202240
shouldSaveQuantityField,
203241
isInvalid,
242+
isNumericType,
243+
inputType,
204244
lastSavedValue,
205245
inputValue,
206246
config,
@@ -261,15 +301,16 @@ export const AnnotationsInput = ({
261301
className={className}
262302
/>
263303
);
264-
} else if (inputType === "number") {
304+
} else if (isNumericType) {
265305
inputElement = (
266306
<InlineStack gap="2" wrap="nowrap" className="grow">
267307
<Input
268308
type="number"
269309
value={inputValue}
270310
min={config?.min}
271311
max={config?.max}
272-
onChange={(e) => setInputValue(e.target.value)}
312+
onChange={handleNumericInputChange}
313+
onKeyDown={handleNumericInputKeyDown}
273314
onBlur={handleBlur}
274315
autoFocus={autoFocus}
275316
className={className}
@@ -353,20 +394,18 @@ export const AnnotationsInput = ({
353394
)}
354395
</InlineStack>
355396

356-
{inputType !== "boolean" &&
357-
inputType !== "number" &&
358-
!config?.options && (
359-
<MultilineTextInputDialog
360-
title={dialogTitle}
361-
description="Enter a value for this annotation."
362-
placeholder={placeholder}
363-
initialValue={inputValue}
364-
open={isDialogOpen}
365-
onCancel={handleDialogCancel}
366-
onConfirm={handleDialogConfirm}
367-
maxLength={config?.max}
368-
/>
369-
)}
397+
{inputType !== "boolean" && !isNumericType && !config?.options && (
398+
<MultilineTextInputDialog
399+
title={dialogTitle}
400+
description="Enter a value for this annotation."
401+
placeholder={placeholder}
402+
initialValue={inputValue}
403+
open={isDialogOpen}
404+
onCancel={handleDialogCancel}
405+
onConfirm={handleDialogConfirm}
406+
maxLength={config?.max}
407+
/>
408+
)}
370409
</>
371410
);
372411
};

src/components/shared/ReactFlow/FlowCanvas/TaskNode/AnnotationsEditor/utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ export function parseSchemaToAnnotationConfig(
8484
config.type = "json";
8585
} else if (property.type === "number") {
8686
config.type = "number";
87+
} else if (property.type === "integer") {
88+
config.type = "integer";
8789
} else if (property.type === "boolean") {
8890
config.type = "boolean";
8991
} else if (property.type === "string") {

src/types/annotations.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export type AnnotationConfig = {
1212
append?: string;
1313
options?: AnnotationOption[];
1414
enableQuantity?: boolean;
15-
type?: "string" | "number" | "boolean" | "json";
15+
type?: "string" | "number" | "integer" | "boolean" | "json";
1616
min?: number;
1717
max?: number;
1818
hidden?: boolean;

0 commit comments

Comments
 (0)