import * as React from "react"; import { Flex, Input, FormLabel, Stack, NumberInput, NumberInputField, NumberInputStepper, NumberIncrementStepper, NumberDecrementStepper, Checkbox, Textarea, Select, } from "@chakra-ui/react"; import { AdvancedItemStateProps, JSONSchema7, } from "../../JsonSchemaEditor.types"; import { none, useState } from "@hookstate/core"; import { StringFormat } from "../utils"; export const AdvancedString: React.FunctionComponent<AdvancedItemStateProps> = ( props: React.PropsWithChildren<AdvancedItemStateProps> ) => { const { itemStateProp } = props; const changeEnumOtherValue = (value: string): string[] | null => { const array = value.split("\n"); if (array.length === 0 || (array.length === 1 && !array[0])) { return null; } return array; }; const itemState = useState(itemStateProp); const isEnumChecked = (itemState.value as JSONSchema7).enum !== undefined; const enumData = (itemState.value as JSONSchema7).enum ? (itemState.enum.value as string[]) : []; const enumValue = enumData?.join("\n"); return ( <Flex direction="column" wrap="nowrap"> <Stack isInline alignItems="center" justifyContent="center" alignContent="center" m={1} > <FormLabel mr={2}>Default: </FormLabel> <Input id="default" placeholder="Default value" value={(itemState.default.value as string) ?? ""} onChange={(evt: React.ChangeEvent<HTMLInputElement>) => { itemState.default.set(evt.target.value); }} /> </Stack> <Stack isInline alignItems="center" justifyContent="center" alignContent="center" m={1} > <FormLabel mr={2}>Min Length: </FormLabel> <NumberInput size="sm" defaultValue={Number(itemState.minLength.value)} onChange={(value: number | string) => { itemState.minLength.set(Number(value)); }} > <NumberInputField value={Number(itemState.minLength.value)} /> <NumberInputStepper> <NumberIncrementStepper /> <NumberDecrementStepper /> </NumberInputStepper> </NumberInput> <FormLabel mr={2}>Max Length: </FormLabel> <NumberInput size="sm" defaultValue={Number(itemState.maxLength.value)} onChange={(value: number | string) => { itemState.maxLength.set(Number(value)); }} > <NumberInputField value={Number(itemState.maxLength.value)} /> <NumberInputStepper> <NumberIncrementStepper /> <NumberDecrementStepper /> </NumberInputStepper> </NumberInput> </Stack> <Stack isInline alignItems="center" justifyContent="center" alignContent="center" m={1} > <FormLabel mr={2} htmlFor="pattern"> Pattern:{" "} </FormLabel> <Input id="pattern" placeholder="MUST be a valid regular expression." value={itemState.pattern.value ?? ""} onChange={(evt: React.ChangeEvent<HTMLInputElement>) => { itemState.pattern.set(evt.target.value); }} /> </Stack> <Stack isInline alignItems="center" justifyContent="center" alignContent="center" m={1} > <FormLabel mr={2}>Enum: </FormLabel> <Checkbox isChecked={isEnumChecked} onChange={(evt: React.ChangeEvent<HTMLInputElement>) => { if (!evt.target.checked) { itemState.enum.set(none); } else { itemState.enum.set(Array<string>()); } }} /> <Textarea value={enumValue || ""} isDisabled={!isEnumChecked} placeholder="ENUM Values - One Entry Per Line" onChange={(evt: React.ChangeEvent<HTMLTextAreaElement>) => { const update = changeEnumOtherValue(evt.target.value); if (update === null) { itemState.enum.set(none); } else { itemState.enum.set(update as string[]); } }} /> </Stack> <Stack isInline alignItems="center" justifyContent="center" alignContent="center" m={1} > <FormLabel mr={2} htmlFor="format"> Format:{" "} </FormLabel> <Select variant="outline" value={itemState.format.value ?? ""} size="sm" margin={2} placeholder="Choose data type" onChange={(evt: React.ChangeEvent<HTMLSelectElement>) => { if (evt.target.value === "") { itemState.format.set(none); } else { itemState.format.set(evt.target.value); } }} > {StringFormat.map((item, index) => { return ( <option key={String(index)} value={item.name}> {item.name} </option> ); })} </Select> </Stack> </Flex> ); };