Refactor types to remove unused types and add FullNameFieldInput (#2590)
This commit is contained in:
@ -9,29 +9,19 @@ import { isFieldLink } from '@/ui/object/field/types/guards/isFieldLink';
|
||||
import { isFieldUuid } from '@/ui/object/field/types/guards/isFieldUuid';
|
||||
|
||||
import { FieldContext } from '../contexts/FieldContext';
|
||||
import { ChipFieldDisplay } from '../meta-types/display/components/ChipFieldDisplay';
|
||||
import { CurrencyFieldDisplay } from '../meta-types/display/components/CurrencyFieldDisplay';
|
||||
import { DateFieldDisplay } from '../meta-types/display/components/DateFieldDisplay';
|
||||
import { DoubleTextChipFieldDisplay } from '../meta-types/display/components/DoubleTextChipFieldDisplay';
|
||||
import { EmailFieldDisplay } from '../meta-types/display/components/EmailFieldDisplay';
|
||||
import { EnumFieldDisplay } from '../meta-types/display/components/EnumFieldDisplay';
|
||||
import { MoneyFieldDisplay } from '../meta-types/display/components/MoneyFieldDisplay';
|
||||
import { NumberFieldDisplay } from '../meta-types/display/components/NumberFieldDisplay';
|
||||
import { PhoneFieldDisplay } from '../meta-types/display/components/PhoneFieldDisplay';
|
||||
import { TextFieldDisplay } from '../meta-types/display/components/TextFieldDisplay';
|
||||
import { URLFieldDisplay } from '../meta-types/display/components/URLFieldDisplay';
|
||||
import { isFieldChip } from '../types/guards/isFieldChip';
|
||||
import { isFieldCurrency } from '../types/guards/isFieldCurrency';
|
||||
import { isFieldDate } from '../types/guards/isFieldDate';
|
||||
import { isFieldDoubleTextChip } from '../types/guards/isFieldDoubleTextChip';
|
||||
import { isFieldEmail } from '../types/guards/isFieldEmail';
|
||||
import { isFieldEnum } from '../types/guards/isFieldEnum';
|
||||
import { isFieldMoney } from '../types/guards/isFieldMoney';
|
||||
import { isFieldNumber } from '../types/guards/isFieldNumber';
|
||||
import { isFieldPhone } from '../types/guards/isFieldPhone';
|
||||
import { isFieldRelation } from '../types/guards/isFieldRelation';
|
||||
import { isFieldText } from '../types/guards/isFieldText';
|
||||
import { isFieldURL } from '../types/guards/isFieldURL';
|
||||
|
||||
export const FieldDisplay = () => {
|
||||
const { fieldDefinition } = useContext(FieldContext);
|
||||
@ -50,10 +40,6 @@ export const FieldDisplay = () => {
|
||||
<DateFieldDisplay />
|
||||
) : isFieldNumber(fieldDefinition) ? (
|
||||
<NumberFieldDisplay />
|
||||
) : isFieldMoney(fieldDefinition) ? (
|
||||
<MoneyFieldDisplay />
|
||||
) : isFieldURL(fieldDefinition) ? (
|
||||
<URLFieldDisplay />
|
||||
) : isFieldLink(fieldDefinition) ? (
|
||||
<LinkFieldDisplay />
|
||||
) : isFieldCurrency(fieldDefinition) ? (
|
||||
@ -62,12 +48,6 @@ export const FieldDisplay = () => {
|
||||
<FullNameFieldDisplay />
|
||||
) : isFieldPhone(fieldDefinition) ? (
|
||||
<PhoneFieldDisplay />
|
||||
) : isFieldChip(fieldDefinition) ? (
|
||||
<ChipFieldDisplay />
|
||||
) : isFieldDoubleTextChip(fieldDefinition) ? (
|
||||
<DoubleTextChipFieldDisplay />
|
||||
) : isFieldEnum(fieldDefinition) ? (
|
||||
<EnumFieldDisplay />
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
|
||||
@ -1,37 +1,31 @@
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { FullNameFieldInput } from '@/ui/object/field/meta-types/input/components/FullNameFieldInput';
|
||||
import { isFieldFullName } from '@/ui/object/field/types/guards/isFieldFullName';
|
||||
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
|
||||
|
||||
import { FieldContext } from '../contexts/FieldContext';
|
||||
import { BooleanFieldInput } from '../meta-types/input/components/BooleanFieldInput';
|
||||
import { ChipFieldInput } from '../meta-types/input/components/ChipFieldInput';
|
||||
import { CurrencyFieldInput } from '../meta-types/input/components/CurrencyFieldInput';
|
||||
import { DateFieldInput } from '../meta-types/input/components/DateFieldInput';
|
||||
import { DoubleTextChipFieldInput } from '../meta-types/input/components/DoubleTextChipFieldInput';
|
||||
import { EmailFieldInput } from '../meta-types/input/components/EmailFieldInput';
|
||||
import { LinkFieldInput } from '../meta-types/input/components/LinkFieldInput';
|
||||
import { MoneyFieldInput } from '../meta-types/input/components/MoneyFieldInput';
|
||||
import { NumberFieldInput } from '../meta-types/input/components/NumberFieldInput';
|
||||
import { PhoneFieldInput } from '../meta-types/input/components/PhoneFieldInput';
|
||||
import { ProbabilityFieldInput } from '../meta-types/input/components/ProbabilityFieldInput';
|
||||
import { RelationFieldInput } from '../meta-types/input/components/RelationFieldInput';
|
||||
import { TextFieldInput } from '../meta-types/input/components/TextFieldInput';
|
||||
import { URLFieldInput } from '../meta-types/input/components/URLFieldInput';
|
||||
import { FieldInputEvent } from '../types/FieldInputEvent';
|
||||
import { isFieldBoolean } from '../types/guards/isFieldBoolean';
|
||||
import { isFieldChip } from '../types/guards/isFieldChip';
|
||||
import { isFieldCurrency } from '../types/guards/isFieldCurrency';
|
||||
import { isFieldDate } from '../types/guards/isFieldDate';
|
||||
import { isFieldDoubleTextChip } from '../types/guards/isFieldDoubleTextChip';
|
||||
import { isFieldEmail } from '../types/guards/isFieldEmail';
|
||||
import { isFieldLink } from '../types/guards/isFieldLink';
|
||||
import { isFieldMoney } from '../types/guards/isFieldMoney';
|
||||
import { isFieldNumber } from '../types/guards/isFieldNumber';
|
||||
import { isFieldPhone } from '../types/guards/isFieldPhone';
|
||||
import { isFieldProbability } from '../types/guards/isFieldProbability';
|
||||
import { isFieldRelation } from '../types/guards/isFieldRelation';
|
||||
import { isFieldText } from '../types/guards/isFieldText';
|
||||
import { isFieldURL } from '../types/guards/isFieldURL';
|
||||
|
||||
type FieldInputProps = {
|
||||
onSubmit?: FieldInputEvent;
|
||||
@ -76,6 +70,14 @@ export const FieldInput = ({
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
) : isFieldFullName(fieldDefinition) ? (
|
||||
<FullNameFieldInput
|
||||
onEnter={onEnter}
|
||||
onEscape={onEscape}
|
||||
onClickOutside={onClickOutside}
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
) : isFieldDate(fieldDefinition) ? (
|
||||
<DateFieldInput
|
||||
onEnter={onEnter}
|
||||
@ -92,14 +94,6 @@ export const FieldInput = ({
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
) : isFieldURL(fieldDefinition) ? (
|
||||
<URLFieldInput
|
||||
onEnter={onEnter}
|
||||
onEscape={onEscape}
|
||||
onClickOutside={onClickOutside}
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
) : isFieldLink(fieldDefinition) ? (
|
||||
<LinkFieldInput
|
||||
onEnter={onEnter}
|
||||
@ -128,30 +122,6 @@ export const FieldInput = ({
|
||||
<BooleanFieldInput onSubmit={onSubmit} />
|
||||
) : isFieldProbability(fieldDefinition) ? (
|
||||
<ProbabilityFieldInput onSubmit={onSubmit} />
|
||||
) : isFieldChip(fieldDefinition) ? (
|
||||
<ChipFieldInput
|
||||
onEnter={onEnter}
|
||||
onEscape={onEscape}
|
||||
onClickOutside={onClickOutside}
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
) : isFieldDoubleTextChip(fieldDefinition) ? (
|
||||
<DoubleTextChipFieldInput
|
||||
onEnter={onEnter}
|
||||
onEscape={onEscape}
|
||||
onClickOutside={onClickOutside}
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
) : isFieldMoney(fieldDefinition) ? (
|
||||
<MoneyFieldInput
|
||||
onEnter={onEnter}
|
||||
onEscape={onEscape}
|
||||
onClickOutside={onClickOutside}
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
|
||||
@ -5,9 +5,9 @@ import { IconComponent } from '@/ui/display/icon/types/IconComponent';
|
||||
|
||||
import { FieldContext } from '../contexts/FieldContext';
|
||||
import { isFieldEmail } from '../types/guards/isFieldEmail';
|
||||
import { isFieldLink } from '../types/guards/isFieldLink';
|
||||
import { isFieldPhone } from '../types/guards/isFieldPhone';
|
||||
import { isFieldRelation } from '../types/guards/isFieldRelation';
|
||||
import { isFieldURL } from '../types/guards/isFieldURL';
|
||||
|
||||
export const useGetButtonIcon = (): IconComponent | undefined => {
|
||||
const { fieldDefinition } = useContext(FieldContext);
|
||||
@ -15,7 +15,7 @@ export const useGetButtonIcon = (): IconComponent | undefined => {
|
||||
if (!fieldDefinition) return undefined;
|
||||
|
||||
if (
|
||||
isFieldURL(fieldDefinition) ||
|
||||
isFieldLink(fieldDefinition) ||
|
||||
isFieldEmail(fieldDefinition) ||
|
||||
isFieldPhone(fieldDefinition) ||
|
||||
isFieldRelation(fieldDefinition)
|
||||
|
||||
@ -11,8 +11,8 @@ export const useIsFieldEmpty = () => {
|
||||
isEntityFieldEmptyFamilySelector({
|
||||
fieldDefinition: {
|
||||
type: fieldDefinition.type,
|
||||
metadata: { ...fieldDefinition.metadata, mainIdentifierMapper: null },
|
||||
},
|
||||
fieldName: fieldDefinition.metadata.fieldName,
|
||||
entityId,
|
||||
}),
|
||||
);
|
||||
|
||||
@ -1,26 +1,21 @@
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { isFieldFullName } from '@/ui/object/field/types/guards/isFieldFullName';
|
||||
import { isFieldFullNameValue } from '@/ui/object/field/types/guards/isFieldFullNameValue';
|
||||
|
||||
import { FieldContext } from '../contexts/FieldContext';
|
||||
import { entityFieldsFamilySelector } from '../states/selectors/entityFieldsFamilySelector';
|
||||
import { isFieldBoolean } from '../types/guards/isFieldBoolean';
|
||||
import { isFieldBooleanValue } from '../types/guards/isFieldBooleanValue';
|
||||
import { isFieldChip } from '../types/guards/isFieldChip';
|
||||
import { isFieldChipValue } from '../types/guards/isFieldChipValue';
|
||||
import { isFieldCurrency } from '../types/guards/isFieldCurrency';
|
||||
import { isFieldCurrencyValue } from '../types/guards/isFieldCurrencyValue';
|
||||
import { isFieldDate } from '../types/guards/isFieldDate';
|
||||
import { isFieldDateValue } from '../types/guards/isFieldDateValue';
|
||||
import { isFieldDoubleText } from '../types/guards/isFieldDoubleText';
|
||||
import { isFieldDoubleTextChip } from '../types/guards/isFieldDoubleTextChip';
|
||||
import { isFieldDoubleTextChipValue } from '../types/guards/isFieldDoubleTextChipValue';
|
||||
import { isFieldDoubleTextValue } from '../types/guards/isFieldDoubleTextValue';
|
||||
import { isFieldEmail } from '../types/guards/isFieldEmail';
|
||||
import { isFieldEmailValue } from '../types/guards/isFieldEmailValue';
|
||||
import { isFieldLink } from '../types/guards/isFieldLink';
|
||||
import { isFieldLinkValue } from '../types/guards/isFieldLinkValue';
|
||||
import { isFieldMoney } from '../types/guards/isFieldMoney';
|
||||
import { isFieldMoneyValue } from '../types/guards/isFieldMoneyValue';
|
||||
import { isFieldNumber } from '../types/guards/isFieldNumber';
|
||||
import { isFieldNumberValue } from '../types/guards/isFieldNumberValue';
|
||||
import { isFieldPhone } from '../types/guards/isFieldPhone';
|
||||
@ -31,8 +26,6 @@ import { isFieldRelation } from '../types/guards/isFieldRelation';
|
||||
import { isFieldRelationValue } from '../types/guards/isFieldRelationValue';
|
||||
import { isFieldText } from '../types/guards/isFieldText';
|
||||
import { isFieldTextValue } from '../types/guards/isFieldTextValue';
|
||||
import { isFieldURL } from '../types/guards/isFieldURL';
|
||||
import { isFieldURLValue } from '../types/guards/isFieldURLValue';
|
||||
|
||||
export const usePersistField = () => {
|
||||
const {
|
||||
@ -50,17 +43,6 @@ export const usePersistField = () => {
|
||||
isFieldRelation(fieldDefinition) &&
|
||||
isFieldRelationValue(valueToPersist);
|
||||
|
||||
const fieldIsChip =
|
||||
isFieldChip(fieldDefinition) && isFieldChipValue(valueToPersist);
|
||||
|
||||
const fieldIsDoubleText =
|
||||
isFieldDoubleText(fieldDefinition) &&
|
||||
isFieldDoubleTextValue(valueToPersist);
|
||||
|
||||
const fieldIsDoubleTextChip =
|
||||
isFieldDoubleTextChip(fieldDefinition) &&
|
||||
isFieldDoubleTextChipValue(valueToPersist);
|
||||
|
||||
const fieldIsText =
|
||||
isFieldText(fieldDefinition) && isFieldTextValue(valueToPersist);
|
||||
|
||||
@ -70,9 +52,6 @@ export const usePersistField = () => {
|
||||
const fieldIsDate =
|
||||
isFieldDate(fieldDefinition) && isFieldDateValue(valueToPersist);
|
||||
|
||||
const fieldIsURL =
|
||||
isFieldURL(fieldDefinition) && isFieldURLValue(valueToPersist);
|
||||
|
||||
const fieldIsLink =
|
||||
isFieldLink(fieldDefinition) && isFieldLinkValue(valueToPersist);
|
||||
|
||||
@ -87,13 +66,14 @@ export const usePersistField = () => {
|
||||
const fieldIsNumber =
|
||||
isFieldNumber(fieldDefinition) && isFieldNumberValue(valueToPersist);
|
||||
|
||||
const fieldIsMoney =
|
||||
isFieldMoney(fieldDefinition) && isFieldMoneyValue(valueToPersist);
|
||||
|
||||
const fieldIsCurrency =
|
||||
isFieldCurrency(fieldDefinition) &&
|
||||
isFieldCurrencyValue(valueToPersist);
|
||||
|
||||
const fieldIsFullName =
|
||||
isFieldFullName(fieldDefinition) &&
|
||||
isFieldFullNameValue(valueToPersist);
|
||||
|
||||
const fieldIsPhone =
|
||||
isFieldPhone(fieldDefinition) && isFieldPhoneValue(valueToPersist);
|
||||
|
||||
@ -115,62 +95,17 @@ export const usePersistField = () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if (fieldIsChip) {
|
||||
const fieldName = fieldDefinition.metadata.contentFieldName;
|
||||
|
||||
set(
|
||||
entityFieldsFamilySelector({ entityId, fieldName }),
|
||||
valueToPersist,
|
||||
);
|
||||
|
||||
updateEntity?.({
|
||||
variables: {
|
||||
where: { id: entityId },
|
||||
data: {
|
||||
[fieldName]: valueToPersist,
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if (fieldIsDoubleText || fieldIsDoubleTextChip) {
|
||||
set(
|
||||
entityFieldsFamilySelector({
|
||||
entityId,
|
||||
fieldName: fieldDefinition.metadata.firstValueFieldName,
|
||||
}),
|
||||
valueToPersist.firstValue,
|
||||
);
|
||||
|
||||
set(
|
||||
entityFieldsFamilySelector({
|
||||
entityId,
|
||||
fieldName: fieldDefinition.metadata.secondValueFieldName,
|
||||
}),
|
||||
valueToPersist.secondValue,
|
||||
);
|
||||
|
||||
updateEntity?.({
|
||||
variables: {
|
||||
where: { id: entityId },
|
||||
data: {
|
||||
[fieldDefinition.metadata.firstValueFieldName]:
|
||||
valueToPersist.firstValue,
|
||||
[fieldDefinition.metadata.secondValueFieldName]:
|
||||
valueToPersist.secondValue,
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if (
|
||||
fieldIsText ||
|
||||
fieldIsBoolean ||
|
||||
fieldIsURL ||
|
||||
fieldIsEmail ||
|
||||
fieldIsProbability ||
|
||||
fieldIsNumber ||
|
||||
fieldIsMoney ||
|
||||
fieldIsDate ||
|
||||
fieldIsPhone ||
|
||||
fieldIsLink ||
|
||||
fieldIsCurrency
|
||||
fieldIsCurrency ||
|
||||
fieldIsFullName
|
||||
) {
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ export const useToggleEditOnlyInput = () => {
|
||||
});
|
||||
} else {
|
||||
throw new Error(
|
||||
`Invalid value to toggle for type : ${fieldDefinition.type}, type may not be implemented in useToggleEditOnlyInput.`,
|
||||
`Invalid value to toggle for type : ${fieldDefinition}, type may not be implemented in useToggleEditOnlyInput.`,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@ -1,14 +1,10 @@
|
||||
import { useChipField } from '../../hooks/useChipField';
|
||||
import { ChipDisplay } from '../content-display/components/ChipDisplay';
|
||||
|
||||
export const ChipFieldDisplay = () => {
|
||||
const { avatarFieldValue, contentFieldValue, entityId } = useChipField();
|
||||
|
||||
return (
|
||||
<ChipDisplay
|
||||
displayName={contentFieldValue}
|
||||
avatarUrlValue={avatarFieldValue}
|
||||
entityId={entityId}
|
||||
/>
|
||||
);
|
||||
// const { avatarFieldValue, contentFieldValue, entityId } = useChipField();
|
||||
// return (
|
||||
// <ChipDisplay
|
||||
// displayName={contentFieldValue}
|
||||
// avatarUrlValue={avatarFieldValue}
|
||||
// entityId={entityId}
|
||||
// />
|
||||
// );
|
||||
};
|
||||
|
||||
@ -1,17 +1,11 @@
|
||||
import { useDoubleTextChipField } from '../../hooks/useDoubleTextChipField';
|
||||
import { ChipDisplay } from '../content-display/components/ChipDisplay';
|
||||
|
||||
export const DoubleTextChipFieldDisplay = () => {
|
||||
const { avatarUrl, firstValue, secondValue, entityId } =
|
||||
useDoubleTextChipField();
|
||||
|
||||
const content = [firstValue, secondValue].filter(Boolean).join(' ');
|
||||
|
||||
return (
|
||||
<ChipDisplay
|
||||
displayName={content}
|
||||
avatarUrlValue={avatarUrl}
|
||||
entityId={entityId}
|
||||
/>
|
||||
);
|
||||
// const {} = useFullNameField();
|
||||
// const content = [firstValue, secondValue].filter(Boolean).join(' ');
|
||||
// return (
|
||||
// <ChipDisplay
|
||||
// displayName={content}
|
||||
// avatarUrlValue={avatarUrl}
|
||||
// entityId={entityId}
|
||||
// />
|
||||
// );
|
||||
};
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
|
||||
import { useEnumField } from '../../hooks/useEnumField';
|
||||
|
||||
export const EnumFieldDisplay = () => {
|
||||
const { fieldValue } = useEnumField();
|
||||
|
||||
return <Tag color={fieldValue.color} text={fieldValue.text} />;
|
||||
};
|
||||
@ -1,8 +0,0 @@
|
||||
import { useMoneyField } from '../../hooks/useMoneyField';
|
||||
import { MoneyDisplay } from '../content-display/components/MoneyDisplay';
|
||||
|
||||
export const MoneyFieldDisplay = () => {
|
||||
const { fieldValue } = useMoneyField();
|
||||
|
||||
return <MoneyDisplay value={fieldValue} />;
|
||||
};
|
||||
@ -1,9 +0,0 @@
|
||||
import { URLDisplay } from '@/ui/object/field/meta-types/display/content-display/components/URLDisplay';
|
||||
|
||||
import { useURLField } from '../../hooks/useURLField';
|
||||
|
||||
export const URLFieldDisplay = () => {
|
||||
const { fieldValue } = useURLField();
|
||||
|
||||
return <URLDisplay value={fieldValue} />;
|
||||
};
|
||||
@ -1,57 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||
|
||||
import { FieldContext } from '../../../../contexts/FieldContext';
|
||||
import { FieldEnumValue } from '../../../../types/FieldMetadata';
|
||||
import { useEnumField } from '../../../hooks/useEnumField';
|
||||
import { EnumFieldDisplay } from '../EnumFieldDisplay';
|
||||
|
||||
const EnumFieldValueSetterEffect = ({ value }: { value: FieldEnumValue }) => {
|
||||
const { setFieldValue } = useEnumField();
|
||||
|
||||
useEffect(() => {
|
||||
setFieldValue(value);
|
||||
}, [setFieldValue, value]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'UI/Data/Field/Display/EnumFieldDisplay',
|
||||
decorators: [
|
||||
(Story, { args }) => (
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
entityId: '',
|
||||
isMainIdentifier: false,
|
||||
fieldDefinition: {
|
||||
fieldMetadataId: 'enum',
|
||||
label: 'Enum',
|
||||
iconName: 'IconTag',
|
||||
type: 'ENUM',
|
||||
metadata: {
|
||||
fieldName: 'Enum',
|
||||
},
|
||||
},
|
||||
hotkeyScope: 'hotkey-scope',
|
||||
}}
|
||||
>
|
||||
<EnumFieldValueSetterEffect value={args.value} />
|
||||
<Story />
|
||||
</FieldContext.Provider>
|
||||
),
|
||||
ComponentDecorator,
|
||||
],
|
||||
component: EnumFieldDisplay,
|
||||
args: {
|
||||
value: { color: 'purple', text: 'Lorem ipsum' },
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof EnumFieldDisplay>;
|
||||
|
||||
export const Default: Story = {};
|
||||
@ -1,68 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||
|
||||
import { FieldContext } from '../../../../contexts/FieldContext';
|
||||
import { useMoneyField } from '../../../hooks/useMoneyField';
|
||||
import { MoneyFieldDisplay } from '../MoneyFieldDisplay';
|
||||
|
||||
const MoneyFieldValueSetterEffect = ({ value }: { value: number }) => {
|
||||
const { setFieldValue } = useMoneyField();
|
||||
|
||||
useEffect(() => {
|
||||
setFieldValue(value);
|
||||
}, [setFieldValue, value]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'UI/Data/Field/Display/MoneyFieldDisplay',
|
||||
decorators: [
|
||||
(Story, { args }) => (
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
entityId: '',
|
||||
isMainIdentifier: false,
|
||||
fieldDefinition: {
|
||||
fieldMetadataId: 'money',
|
||||
label: 'Money',
|
||||
type: 'MONEY_AMOUNT',
|
||||
iconName: 'Icon123',
|
||||
metadata: {
|
||||
fieldName: 'Amount',
|
||||
placeHolder: 'Amount',
|
||||
isPositive: true,
|
||||
},
|
||||
},
|
||||
hotkeyScope: 'hotkey-scope',
|
||||
useUpdateEntityMutation: () => [() => undefined, undefined],
|
||||
}}
|
||||
>
|
||||
<MoneyFieldValueSetterEffect value={args.value} />
|
||||
<Story />
|
||||
</FieldContext.Provider>
|
||||
),
|
||||
ComponentDecorator,
|
||||
],
|
||||
component: MoneyFieldDisplay,
|
||||
args: {
|
||||
value: 100,
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof MoneyFieldDisplay>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
export const Elipsis: Story = {
|
||||
args: {
|
||||
value: 1e100,
|
||||
},
|
||||
parameters: {
|
||||
container: { width: 100 },
|
||||
},
|
||||
};
|
||||
@ -1,66 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||
|
||||
import { FieldContext } from '../../../../contexts/FieldContext';
|
||||
import { useURLField } from '../../../hooks/useURLField';
|
||||
import { URLFieldDisplay } from '../URLFieldDisplay';
|
||||
|
||||
const URLFieldValueSetterEffect = ({ value }: { value: string }) => {
|
||||
const { setFieldValue } = useURLField();
|
||||
|
||||
useEffect(() => {
|
||||
setFieldValue(value);
|
||||
}, [setFieldValue, value]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'UI/Data/Field/Display/URLFieldDisplay',
|
||||
decorators: [
|
||||
(Story, { args }) => (
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
entityId: '',
|
||||
isMainIdentifier: false,
|
||||
fieldDefinition: {
|
||||
fieldMetadataId: 'URL',
|
||||
label: 'URL',
|
||||
type: 'URL',
|
||||
iconName: 'IconLink',
|
||||
metadata: {
|
||||
fieldName: 'URL',
|
||||
placeHolder: 'URL',
|
||||
},
|
||||
},
|
||||
hotkeyScope: 'hotkey-scope',
|
||||
}}
|
||||
>
|
||||
<MemoryRouter>
|
||||
<URLFieldValueSetterEffect value={args.value} />
|
||||
<Story />
|
||||
</MemoryRouter>
|
||||
</FieldContext.Provider>
|
||||
),
|
||||
ComponentDecorator,
|
||||
],
|
||||
component: URLFieldDisplay,
|
||||
args: {
|
||||
value: 'https://github.com/twentyhq',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof URLFieldDisplay>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
export const Elipsis: Story = {
|
||||
parameters: {
|
||||
container: { width: 200 },
|
||||
},
|
||||
};
|
||||
@ -1,55 +0,0 @@
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { FieldContext } from '../../contexts/FieldContext';
|
||||
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
|
||||
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
|
||||
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
|
||||
import { isFieldChip } from '../../types/guards/isFieldChip';
|
||||
|
||||
export const useChipField = () => {
|
||||
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
|
||||
|
||||
assertFieldMetadata('CHIP', isFieldChip, fieldDefinition);
|
||||
|
||||
const contentFieldName = fieldDefinition.metadata.contentFieldName;
|
||||
const avatarUrlFieldName = fieldDefinition.metadata.urlFieldName;
|
||||
|
||||
const [contentFieldValue, setContentFieldValue] = useRecoilState<string>(
|
||||
entityFieldsFamilySelector({
|
||||
entityId: entityId,
|
||||
fieldName: contentFieldName,
|
||||
}),
|
||||
);
|
||||
|
||||
const [avatarFieldValue, setAvatarFieldValue] = useRecoilState<string>(
|
||||
entityFieldsFamilySelector({
|
||||
entityId: entityId,
|
||||
fieldName: avatarUrlFieldName,
|
||||
}),
|
||||
);
|
||||
|
||||
const fieldInitialValue = useFieldInitialValue();
|
||||
|
||||
const initialContentValue = fieldInitialValue?.isEmpty
|
||||
? ''
|
||||
: fieldInitialValue?.value ?? contentFieldValue;
|
||||
|
||||
const initialAvatarValue = fieldInitialValue?.isEmpty
|
||||
? ''
|
||||
: fieldInitialValue?.value
|
||||
? ''
|
||||
: avatarFieldValue;
|
||||
|
||||
return {
|
||||
fieldDefinition,
|
||||
contentFieldValue,
|
||||
initialContentValue,
|
||||
setContentFieldValue,
|
||||
avatarFieldValue,
|
||||
initialAvatarValue,
|
||||
setAvatarFieldValue,
|
||||
entityId,
|
||||
hotkeyScope,
|
||||
};
|
||||
};
|
||||
@ -1,75 +0,0 @@
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { FieldContext } from '../../contexts/FieldContext';
|
||||
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
|
||||
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
|
||||
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
|
||||
import { isFieldDoubleTextChip } from '../../types/guards/isFieldDoubleTextChip';
|
||||
|
||||
export const useDoubleTextChipField = () => {
|
||||
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
|
||||
|
||||
assertFieldMetadata(
|
||||
'DOUBLE_TEXT_CHIP',
|
||||
isFieldDoubleTextChip,
|
||||
fieldDefinition,
|
||||
);
|
||||
|
||||
const [firstValue, setFirstValue] = useRecoilState<string>(
|
||||
entityFieldsFamilySelector({
|
||||
entityId: entityId,
|
||||
fieldName: fieldDefinition.metadata.firstValueFieldName,
|
||||
}),
|
||||
);
|
||||
|
||||
const [secondValue, setSecondValue] = useRecoilState<string>(
|
||||
entityFieldsFamilySelector({
|
||||
entityId: entityId,
|
||||
fieldName: fieldDefinition.metadata.secondValueFieldName,
|
||||
}),
|
||||
);
|
||||
|
||||
const [avatarUrl, setAvatarUrl] = useRecoilState<string>(
|
||||
entityFieldsFamilySelector({
|
||||
entityId: entityId,
|
||||
fieldName: fieldDefinition.metadata.avatarUrlFieldName,
|
||||
}),
|
||||
);
|
||||
|
||||
const fullValue = [firstValue, secondValue].filter(Boolean).join(' ');
|
||||
|
||||
const fieldInitialValue = useFieldInitialValue();
|
||||
|
||||
const initialFirstValue = fieldInitialValue?.isEmpty
|
||||
? ''
|
||||
: fieldInitialValue?.value ?? firstValue;
|
||||
|
||||
const initialSecondValue = fieldInitialValue?.isEmpty
|
||||
? ''
|
||||
: fieldInitialValue?.value
|
||||
? ''
|
||||
: secondValue;
|
||||
|
||||
const initialAvatarUrl = fieldInitialValue?.isEmpty
|
||||
? ''
|
||||
: fieldInitialValue?.value
|
||||
? ''
|
||||
: avatarUrl;
|
||||
|
||||
return {
|
||||
fieldDefinition,
|
||||
avatarUrl,
|
||||
setAvatarUrl,
|
||||
secondValue,
|
||||
setSecondValue,
|
||||
firstValue,
|
||||
setFirstValue,
|
||||
fullValue,
|
||||
entityId,
|
||||
hotkeyScope,
|
||||
initialAvatarUrl,
|
||||
initialFirstValue,
|
||||
initialSecondValue,
|
||||
};
|
||||
};
|
||||
@ -1,47 +0,0 @@
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { FieldEnumValue } from '@/ui/object/field/types/FieldMetadata';
|
||||
import { ThemeColor } from '@/ui/theme/constants/colors';
|
||||
|
||||
import { FieldContext } from '../../contexts/FieldContext';
|
||||
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
|
||||
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
|
||||
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
|
||||
import { isFieldEnum } from '../../types/guards/isFieldEnum';
|
||||
import { isFieldEnumValue } from '../../types/guards/isFieldEnumValue';
|
||||
|
||||
export const useEnumField = () => {
|
||||
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
|
||||
|
||||
assertFieldMetadata('ENUM', isFieldEnum, fieldDefinition);
|
||||
|
||||
const { fieldName } = fieldDefinition.metadata;
|
||||
|
||||
const [fieldValue, setFieldValue] = useRecoilState<FieldEnumValue>(
|
||||
entityFieldsFamilySelector({
|
||||
entityId: entityId,
|
||||
fieldName: fieldName,
|
||||
}),
|
||||
);
|
||||
const fieldEnumValue = isFieldEnumValue(fieldValue)
|
||||
? fieldValue
|
||||
: { color: 'green' as ThemeColor, text: '' };
|
||||
|
||||
const fieldInitialValue = useFieldInitialValue();
|
||||
|
||||
const initialValue = {
|
||||
color: 'green' as ThemeColor,
|
||||
text: fieldInitialValue?.isEmpty
|
||||
? ''
|
||||
: fieldInitialValue?.value ?? fieldEnumValue?.text ?? '',
|
||||
};
|
||||
|
||||
return {
|
||||
fieldDefinition,
|
||||
fieldValue: fieldEnumValue,
|
||||
initialValue,
|
||||
setFieldValue,
|
||||
hotkeyScope,
|
||||
};
|
||||
};
|
||||
@ -1,58 +0,0 @@
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import {
|
||||
canBeCastAsIntegerOrNull,
|
||||
castAsIntegerOrNull,
|
||||
} from '~/utils/cast-as-integer-or-null';
|
||||
|
||||
import { FieldContext } from '../../contexts/FieldContext';
|
||||
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
|
||||
import { usePersistField } from '../../hooks/usePersistField';
|
||||
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
|
||||
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
|
||||
import { isFieldMoney } from '../../types/guards/isFieldMoney';
|
||||
|
||||
export const useMoneyField = () => {
|
||||
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
|
||||
|
||||
assertFieldMetadata('MONEY_AMOUNT', isFieldMoney, fieldDefinition);
|
||||
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
|
||||
const [fieldValue, setFieldValue] = useRecoilState<number | null>(
|
||||
entityFieldsFamilySelector({
|
||||
entityId: entityId,
|
||||
fieldName: fieldName,
|
||||
}),
|
||||
);
|
||||
|
||||
const persistField = usePersistField();
|
||||
|
||||
const persistMoneyField = (newValue: string) => {
|
||||
if (!canBeCastAsIntegerOrNull(newValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const castedValue = castAsIntegerOrNull(newValue);
|
||||
|
||||
persistField(castedValue);
|
||||
};
|
||||
|
||||
const fieldInitialValue = useFieldInitialValue();
|
||||
|
||||
const initialValue = fieldInitialValue?.isEmpty
|
||||
? null
|
||||
: !isNaN(Number(fieldInitialValue?.value))
|
||||
? Number(fieldInitialValue?.value)
|
||||
: null ?? fieldValue;
|
||||
|
||||
return {
|
||||
fieldDefinition,
|
||||
fieldValue,
|
||||
initialValue,
|
||||
setFieldValue,
|
||||
hotkeyScope,
|
||||
persistMoneyField,
|
||||
};
|
||||
};
|
||||
@ -1,53 +0,0 @@
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { isURL } from '~/utils/is-url';
|
||||
|
||||
import { FieldContext } from '../../contexts/FieldContext';
|
||||
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
|
||||
import { usePersistField } from '../../hooks/usePersistField';
|
||||
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
|
||||
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
|
||||
import { isFieldURL } from '../../types/guards/isFieldURL';
|
||||
import { isFieldURLValue } from '../../types/guards/isFieldURLValue';
|
||||
|
||||
export const useURLField = () => {
|
||||
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
|
||||
|
||||
assertFieldMetadata('URL', isFieldURL, fieldDefinition);
|
||||
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
|
||||
const [fieldValue, setFieldValue] = useRecoilState<string>(
|
||||
entityFieldsFamilySelector({
|
||||
entityId: entityId,
|
||||
fieldName: fieldName,
|
||||
}),
|
||||
);
|
||||
const fieldUrlValue = isFieldURLValue(fieldValue) ? fieldValue : '';
|
||||
|
||||
const fieldInitialValue = useFieldInitialValue();
|
||||
|
||||
const initialValue = fieldInitialValue?.isEmpty
|
||||
? ''
|
||||
: fieldInitialValue?.value ?? fieldUrlValue;
|
||||
|
||||
const persistField = usePersistField();
|
||||
|
||||
const persistURLField = (newValue: string) => {
|
||||
if (!isURL(newValue) && newValue !== '') {
|
||||
return;
|
||||
}
|
||||
|
||||
persistField(newValue);
|
||||
};
|
||||
|
||||
return {
|
||||
fieldDefinition,
|
||||
fieldValue: fieldUrlValue,
|
||||
initialValue,
|
||||
setFieldValue,
|
||||
hotkeyScope,
|
||||
persistURLField,
|
||||
};
|
||||
};
|
||||
@ -1,66 +0,0 @@
|
||||
import { TextInput } from '@/ui/object/field/meta-types/input/components/internal/TextInput';
|
||||
|
||||
import { usePersistField } from '../../../hooks/usePersistField';
|
||||
import { useChipField } from '../../hooks/useChipField';
|
||||
|
||||
import { FieldInputOverlay } from './internal/FieldInputOverlay';
|
||||
import { FieldInputEvent } from './DateFieldInput';
|
||||
|
||||
export type ChipFieldInputProps = {
|
||||
onClickOutside?: FieldInputEvent;
|
||||
onEnter?: FieldInputEvent;
|
||||
onEscape?: FieldInputEvent;
|
||||
onTab?: FieldInputEvent;
|
||||
onShiftTab?: FieldInputEvent;
|
||||
};
|
||||
|
||||
export const ChipFieldInput = ({
|
||||
onEnter,
|
||||
onEscape,
|
||||
onClickOutside,
|
||||
onTab,
|
||||
onShiftTab,
|
||||
}: ChipFieldInputProps) => {
|
||||
const { fieldDefinition, initialContentValue, hotkeyScope } = useChipField();
|
||||
|
||||
const persistField = usePersistField();
|
||||
|
||||
const handleEnter = (newText: string) => {
|
||||
onEnter?.(() => persistField(newText));
|
||||
};
|
||||
|
||||
const handleEscape = (newText: string) => {
|
||||
onEscape?.(() => persistField(newText));
|
||||
};
|
||||
|
||||
const handleClickOutside = (
|
||||
event: MouseEvent | TouchEvent,
|
||||
newText: string,
|
||||
) => {
|
||||
onClickOutside?.(() => persistField(newText));
|
||||
};
|
||||
|
||||
const handleTab = (newText: string) => {
|
||||
onTab?.(() => persistField(newText));
|
||||
};
|
||||
|
||||
const handleShiftTab = (newText: string) => {
|
||||
onShiftTab?.(() => persistField(newText));
|
||||
};
|
||||
|
||||
return (
|
||||
<FieldInputOverlay>
|
||||
<TextInput
|
||||
placeholder={fieldDefinition.metadata.placeHolder}
|
||||
autoFocus
|
||||
value={initialContentValue}
|
||||
onClickOutside={handleClickOutside}
|
||||
onEnter={handleEnter}
|
||||
onEscape={handleEscape}
|
||||
onShiftTab={handleShiftTab}
|
||||
onTab={handleTab}
|
||||
hotkeyScope={hotkeyScope}
|
||||
/>
|
||||
</FieldInputOverlay>
|
||||
);
|
||||
};
|
||||
@ -1,13 +1,13 @@
|
||||
import { useFullNameField } from '@/ui/object/field/meta-types/hooks/useFullNameField';
|
||||
import { DoubleTextInput } from '@/ui/object/field/meta-types/input/components/internal/DoubleTextInput';
|
||||
import { FieldDoubleText } from '@/ui/object/field/types/FieldDoubleText';
|
||||
|
||||
import { usePersistField } from '../../../hooks/usePersistField';
|
||||
import { useDoubleTextChipField } from '../../hooks/useDoubleTextChipField';
|
||||
|
||||
import { FieldInputOverlay } from './internal/FieldInputOverlay';
|
||||
import { FieldInputEvent } from './DateFieldInput';
|
||||
|
||||
export type DoubleTextChipFieldInputProps = {
|
||||
export type FullNameFieldInputProps = {
|
||||
onClickOutside?: FieldInputEvent;
|
||||
onEnter?: FieldInputEvent;
|
||||
onEscape?: FieldInputEvent;
|
||||
@ -15,52 +15,53 @@ export type DoubleTextChipFieldInputProps = {
|
||||
onShiftTab?: FieldInputEvent;
|
||||
};
|
||||
|
||||
export const DoubleTextChipFieldInput = ({
|
||||
export const FullNameFieldInput = ({
|
||||
onEnter,
|
||||
onEscape,
|
||||
onClickOutside,
|
||||
onTab,
|
||||
onShiftTab,
|
||||
}: DoubleTextChipFieldInputProps) => {
|
||||
const {
|
||||
fieldDefinition,
|
||||
initialFirstValue,
|
||||
initialSecondValue,
|
||||
hotkeyScope,
|
||||
} = useDoubleTextChipField();
|
||||
}: FullNameFieldInputProps) => {
|
||||
const { hotkeyScope, initialValue } = useFullNameField();
|
||||
|
||||
const persistField = usePersistField();
|
||||
const convertToFullName = (newDoubleText: FieldDoubleText) => {
|
||||
return {
|
||||
firstName: newDoubleText.firstValue,
|
||||
lastName: newDoubleText.secondValue,
|
||||
};
|
||||
};
|
||||
|
||||
const handleEnter = (newDoubleText: FieldDoubleText) => {
|
||||
onEnter?.(() => persistField(newDoubleText));
|
||||
onEnter?.(() => persistField(convertToFullName(newDoubleText)));
|
||||
};
|
||||
|
||||
const handleEscape = (newDoubleText: FieldDoubleText) => {
|
||||
onEscape?.(() => persistField(newDoubleText));
|
||||
onEscape?.(() => persistField(convertToFullName(newDoubleText)));
|
||||
};
|
||||
|
||||
const handleClickOutside = (
|
||||
event: MouseEvent | TouchEvent,
|
||||
newDoubleText: FieldDoubleText,
|
||||
) => {
|
||||
onClickOutside?.(() => persistField(newDoubleText));
|
||||
onClickOutside?.(() => persistField(convertToFullName(newDoubleText)));
|
||||
};
|
||||
|
||||
const handleTab = (newDoubleText: FieldDoubleText) => {
|
||||
onTab?.(() => persistField(newDoubleText));
|
||||
onTab?.(() => persistField(convertToFullName(newDoubleText)));
|
||||
};
|
||||
|
||||
const handleShiftTab = (newDoubleText: FieldDoubleText) => {
|
||||
onShiftTab?.(() => persistField(newDoubleText));
|
||||
onShiftTab?.(() => persistField(convertToFullName(newDoubleText)));
|
||||
};
|
||||
|
||||
return (
|
||||
<FieldInputOverlay>
|
||||
<DoubleTextInput
|
||||
firstValue={initialFirstValue}
|
||||
secondValue={initialSecondValue}
|
||||
firstValuePlaceholder={fieldDefinition.metadata.firstValuePlaceholder}
|
||||
secondValuePlaceholder={fieldDefinition.metadata.secondValuePlaceholder}
|
||||
firstValue={initialValue.firstName}
|
||||
secondValue={initialValue.lastName}
|
||||
firstValuePlaceholder={'First name'}
|
||||
secondValuePlaceholder={'Last name'}
|
||||
onClickOutside={handleClickOutside}
|
||||
onEnter={handleEnter}
|
||||
onEscape={handleEscape}
|
||||
@ -1,65 +0,0 @@
|
||||
import { TextInput } from '@/ui/object/field/meta-types/input/components/internal/TextInput';
|
||||
|
||||
import { useMoneyField } from '../../hooks/useMoneyField';
|
||||
|
||||
import { FieldInputOverlay } from './internal/FieldInputOverlay';
|
||||
|
||||
export type FieldInputEvent = (persist: () => void) => void;
|
||||
|
||||
export type MoneyFieldInputProps = {
|
||||
onClickOutside?: FieldInputEvent;
|
||||
onEnter?: FieldInputEvent;
|
||||
onEscape?: FieldInputEvent;
|
||||
onTab?: FieldInputEvent;
|
||||
onShiftTab?: FieldInputEvent;
|
||||
};
|
||||
|
||||
export const MoneyFieldInput = ({
|
||||
onEnter,
|
||||
onEscape,
|
||||
onClickOutside,
|
||||
onTab,
|
||||
onShiftTab,
|
||||
}: MoneyFieldInputProps) => {
|
||||
const { fieldDefinition, hotkeyScope, persistMoneyField, initialValue } =
|
||||
useMoneyField();
|
||||
|
||||
const handleEnter = (newText: string) => {
|
||||
onEnter?.(() => persistMoneyField(newText));
|
||||
};
|
||||
|
||||
const handleEscape = (newText: string) => {
|
||||
onEscape?.(() => persistMoneyField(newText));
|
||||
};
|
||||
|
||||
const handleClickOutside = (
|
||||
event: MouseEvent | TouchEvent,
|
||||
newText: string,
|
||||
) => {
|
||||
onClickOutside?.(() => persistMoneyField(newText));
|
||||
};
|
||||
|
||||
const handleTab = (newText: string) => {
|
||||
onTab?.(() => persistMoneyField(newText));
|
||||
};
|
||||
|
||||
const handleShiftTab = (newText: string) => {
|
||||
onShiftTab?.(() => persistMoneyField(newText));
|
||||
};
|
||||
|
||||
return (
|
||||
<FieldInputOverlay>
|
||||
<TextInput
|
||||
placeholder={fieldDefinition.metadata.placeHolder}
|
||||
autoFocus
|
||||
value={initialValue?.toLocaleString() ?? ''}
|
||||
onClickOutside={handleClickOutside}
|
||||
onEnter={handleEnter}
|
||||
onEscape={handleEscape}
|
||||
onShiftTab={handleShiftTab}
|
||||
onTab={handleTab}
|
||||
hotkeyScope={hotkeyScope}
|
||||
/>
|
||||
</FieldInputOverlay>
|
||||
);
|
||||
};
|
||||
@ -1,64 +0,0 @@
|
||||
import { TextInput } from '@/ui/object/field/meta-types/input/components/internal/TextInput';
|
||||
|
||||
import { useURLField } from '../../hooks/useURLField';
|
||||
|
||||
import { FieldInputOverlay } from './internal/FieldInputOverlay';
|
||||
import { FieldInputEvent } from './DateFieldInput';
|
||||
|
||||
export type URLFieldInputProps = {
|
||||
onClickOutside?: FieldInputEvent;
|
||||
onEnter?: FieldInputEvent;
|
||||
onEscape?: FieldInputEvent;
|
||||
onTab?: FieldInputEvent;
|
||||
onShiftTab?: FieldInputEvent;
|
||||
};
|
||||
|
||||
export const URLFieldInput = ({
|
||||
onEnter,
|
||||
onEscape,
|
||||
onClickOutside,
|
||||
onTab,
|
||||
onShiftTab,
|
||||
}: URLFieldInputProps) => {
|
||||
const { fieldDefinition, initialValue, hotkeyScope, persistURLField } =
|
||||
useURLField();
|
||||
|
||||
const handleEnter = (newText: string) => {
|
||||
onEnter?.(() => persistURLField(newText));
|
||||
};
|
||||
|
||||
const handleEscape = (newText: string) => {
|
||||
onEscape?.(() => persistURLField(newText));
|
||||
};
|
||||
|
||||
const handleClickOutside = (
|
||||
event: MouseEvent | TouchEvent,
|
||||
newText: string,
|
||||
) => {
|
||||
onClickOutside?.(() => persistURLField(newText));
|
||||
};
|
||||
|
||||
const handleTab = (newText: string) => {
|
||||
onTab?.(() => persistURLField(newText));
|
||||
};
|
||||
|
||||
const handleShiftTab = (newText: string) => {
|
||||
onShiftTab?.(() => persistURLField(newText));
|
||||
};
|
||||
|
||||
return (
|
||||
<FieldInputOverlay>
|
||||
<TextInput
|
||||
placeholder={fieldDefinition.metadata.placeHolder}
|
||||
autoFocus
|
||||
value={initialValue}
|
||||
onClickOutside={handleClickOutside}
|
||||
onEnter={handleEnter}
|
||||
onEscape={handleEscape}
|
||||
onShiftTab={handleShiftTab}
|
||||
onTab={handleTab}
|
||||
hotkeyScope={hotkeyScope}
|
||||
/>
|
||||
</FieldInputOverlay>
|
||||
);
|
||||
};
|
||||
@ -1,176 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { expect, jest } from '@storybook/jest';
|
||||
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||
import { userEvent, waitFor, within } from '@storybook/testing-library';
|
||||
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
|
||||
import { FieldContextProvider } from '../../../__stories__/FieldContextProvider';
|
||||
import { useChipField } from '../../../hooks/useChipField';
|
||||
import { ChipFieldInput, ChipFieldInputProps } from '../ChipFieldInput';
|
||||
|
||||
const ChipFieldValueSetterEffect = ({ value }: { value: string }) => {
|
||||
const { setContentFieldValue } = useChipField();
|
||||
|
||||
useEffect(() => {
|
||||
setContentFieldValue(value);
|
||||
}, [setContentFieldValue, value]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
type ChipFieldInputWithContextProps = ChipFieldInputProps & {
|
||||
value: string;
|
||||
entityId?: string;
|
||||
};
|
||||
|
||||
const ChipFieldInputWithContext = ({
|
||||
entityId,
|
||||
value,
|
||||
onEnter,
|
||||
onEscape,
|
||||
onClickOutside,
|
||||
onTab,
|
||||
onShiftTab,
|
||||
}: ChipFieldInputWithContextProps) => {
|
||||
const setHotKeyScope = useSetHotkeyScope();
|
||||
|
||||
useEffect(() => {
|
||||
setHotKeyScope('hotkey-scope');
|
||||
}, [setHotKeyScope]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FieldContextProvider
|
||||
fieldDefinition={{
|
||||
fieldMetadataId: 'chip',
|
||||
label: 'Chip',
|
||||
type: 'CHIP',
|
||||
iconName: 'Icon123',
|
||||
metadata: {
|
||||
contentFieldName: 'name',
|
||||
urlFieldName: 'xURL',
|
||||
placeHolder: 'X URL',
|
||||
},
|
||||
}}
|
||||
entityId={entityId}
|
||||
>
|
||||
<ChipFieldValueSetterEffect value={value} />
|
||||
<ChipFieldInput
|
||||
onEnter={onEnter}
|
||||
onEscape={onEscape}
|
||||
onClickOutside={onClickOutside}
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
</FieldContextProvider>
|
||||
<div data-testid="data-field-input-click-outside-div" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const enterJestFn = jest.fn();
|
||||
const escapeJestfn = jest.fn();
|
||||
const clickOutsideJestFn = jest.fn();
|
||||
const tabJestFn = jest.fn();
|
||||
const shiftTabJestFn = jest.fn();
|
||||
|
||||
const clearMocksDecorator: Decorator = (Story, context) => {
|
||||
if (context.parameters.clearMocks) {
|
||||
enterJestFn.mockClear();
|
||||
escapeJestfn.mockClear();
|
||||
clickOutsideJestFn.mockClear();
|
||||
tabJestFn.mockClear();
|
||||
shiftTabJestFn.mockClear();
|
||||
}
|
||||
return <Story />;
|
||||
};
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'UI/Data/Field/Input/ChipFieldInput',
|
||||
component: ChipFieldInputWithContext,
|
||||
args: {
|
||||
value: 'chip',
|
||||
onEnter: enterJestFn,
|
||||
onEscape: escapeJestfn,
|
||||
onClickOutside: clickOutsideJestFn,
|
||||
onTab: tabJestFn,
|
||||
onShiftTab: shiftTabJestFn,
|
||||
},
|
||||
argTypes: {
|
||||
onEnter: { control: false },
|
||||
onEscape: { control: false },
|
||||
onClickOutside: { control: false },
|
||||
onTab: { control: false },
|
||||
onShiftTab: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
clearMocks: true,
|
||||
},
|
||||
decorators: [clearMocksDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof ChipFieldInputWithContext>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
export const Enter: Story = {
|
||||
play: async () => {
|
||||
expect(enterJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{enter}');
|
||||
expect(enterJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const Escape: Story = {
|
||||
play: async () => {
|
||||
expect(escapeJestfn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{esc}');
|
||||
expect(escapeJestfn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const ClickOutside: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
expect(clickOutsideJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
const emptyDiv = canvas.getByTestId('data-field-input-click-outside-div');
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.click(emptyDiv);
|
||||
expect(clickOutsideJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const Tab: Story = {
|
||||
play: async () => {
|
||||
expect(tabJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{tab}');
|
||||
expect(tabJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const ShiftTab: Story = {
|
||||
play: async () => {
|
||||
expect(shiftTabJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{shift>}{tab}');
|
||||
expect(shiftTabJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
@ -1,194 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { expect, jest } from '@storybook/jest';
|
||||
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||
import { userEvent, waitFor, within } from '@storybook/testing-library';
|
||||
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
|
||||
import { FieldContextProvider } from '../../../__stories__/FieldContextProvider';
|
||||
import { useDoubleTextChipField } from '../../../hooks/useDoubleTextChipField';
|
||||
import {
|
||||
DoubleTextChipFieldInput,
|
||||
DoubleTextChipFieldInputProps,
|
||||
} from '../DoubleTextChipFieldInput';
|
||||
|
||||
const DoubleTextChipFieldValueSetterEffect = ({
|
||||
firstValue,
|
||||
secondValue,
|
||||
}: {
|
||||
firstValue: string;
|
||||
secondValue: string;
|
||||
}) => {
|
||||
const { setFirstValue, setSecondValue } = useDoubleTextChipField();
|
||||
|
||||
useEffect(() => {
|
||||
setFirstValue(firstValue);
|
||||
setSecondValue(secondValue);
|
||||
}, [firstValue, secondValue, setFirstValue, setSecondValue]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
type DoubleTextChipFieldInputWithContextProps =
|
||||
DoubleTextChipFieldInputProps & {
|
||||
firstValue: string;
|
||||
secondValue: string;
|
||||
entityId?: string;
|
||||
};
|
||||
|
||||
const DoubleTextChipFieldInputWithContext = ({
|
||||
entityId,
|
||||
firstValue,
|
||||
secondValue,
|
||||
onClickOutside,
|
||||
onEnter,
|
||||
onEscape,
|
||||
onTab,
|
||||
onShiftTab,
|
||||
}: DoubleTextChipFieldInputWithContextProps) => {
|
||||
const setHotKeyScope = useSetHotkeyScope();
|
||||
|
||||
useEffect(() => {
|
||||
setHotKeyScope('hotkey-scope');
|
||||
}, [setHotKeyScope]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FieldContextProvider
|
||||
fieldDefinition={{
|
||||
fieldMetadataId: 'double-text-chip',
|
||||
label: 'Double-Text-Chip',
|
||||
type: 'DOUBLE_TEXT_CHIP',
|
||||
iconName: 'IconUser',
|
||||
metadata: {
|
||||
firstValueFieldName: 'First-text',
|
||||
firstValuePlaceholder: 'First-text',
|
||||
secondValueFieldName: 'Second-text',
|
||||
secondValuePlaceholder: 'Second-text',
|
||||
avatarUrlFieldName: 'avatarUrl',
|
||||
fieldName: '',
|
||||
},
|
||||
}}
|
||||
entityId={entityId}
|
||||
>
|
||||
<DoubleTextChipFieldValueSetterEffect
|
||||
{...{ firstValue, secondValue }}
|
||||
/>
|
||||
<DoubleTextChipFieldInput
|
||||
onEnter={onEnter}
|
||||
onEscape={onEscape}
|
||||
onClickOutside={onClickOutside}
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
</FieldContextProvider>
|
||||
<div data-testid="data-field-input-click-outside-div" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const enterJestFn = jest.fn();
|
||||
const escapeJestfn = jest.fn();
|
||||
const clickOutsideJestFn = jest.fn();
|
||||
const tabJestFn = jest.fn();
|
||||
const shiftTabJestFn = jest.fn();
|
||||
|
||||
const clearMocksDecorator: Decorator = (Story, context) => {
|
||||
if (context.parameters.clearMocks) {
|
||||
enterJestFn.mockClear();
|
||||
escapeJestfn.mockClear();
|
||||
clickOutsideJestFn.mockClear();
|
||||
tabJestFn.mockClear();
|
||||
shiftTabJestFn.mockClear();
|
||||
}
|
||||
return <Story />;
|
||||
};
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'UI/Data/Field/Input/DoubleTextChipFieldInput',
|
||||
component: DoubleTextChipFieldInputWithContext,
|
||||
args: {
|
||||
firstValue: 'first value',
|
||||
secondValue: 'second value',
|
||||
onEnter: enterJestFn,
|
||||
onEscape: escapeJestfn,
|
||||
onClickOutside: clickOutsideJestFn,
|
||||
onTab: tabJestFn,
|
||||
onShiftTab: shiftTabJestFn,
|
||||
},
|
||||
argTypes: {
|
||||
onEnter: { control: false },
|
||||
onEscape: { control: false },
|
||||
onClickOutside: { control: false },
|
||||
onTab: { control: false },
|
||||
onShiftTab: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
clearMocks: true,
|
||||
},
|
||||
decorators: [clearMocksDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof DoubleTextChipFieldInputWithContext>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
export const Enter: Story = {
|
||||
play: async () => {
|
||||
expect(enterJestFn).toHaveBeenCalledTimes(0);
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{enter}');
|
||||
expect(enterJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const Escape: Story = {
|
||||
play: async () => {
|
||||
expect(escapeJestfn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{esc}');
|
||||
expect(escapeJestfn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const ClickOutside: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
expect(clickOutsideJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
const emptyDiv = canvas.getByTestId('data-field-input-click-outside-div');
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.click(emptyDiv);
|
||||
expect(clickOutsideJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const Tab: Story = {
|
||||
play: async () => {
|
||||
expect(tabJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{tab}');
|
||||
expect(tabJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const ShiftTab: Story = {
|
||||
play: async () => {
|
||||
expect(shiftTabJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{shift>}{tab}');
|
||||
expect(shiftTabJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
@ -1,176 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { expect, jest } from '@storybook/jest';
|
||||
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||
import { userEvent, waitFor, within } from '@storybook/testing-library';
|
||||
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
|
||||
import { FieldContextProvider } from '../../../__stories__/FieldContextProvider';
|
||||
import { useMoneyField } from '../../../hooks/useMoneyField';
|
||||
import { MoneyFieldInput, MoneyFieldInputProps } from '../MoneyFieldInput';
|
||||
|
||||
const MoneyFieldValueSetterEffect = ({ value }: { value: number }) => {
|
||||
const { setFieldValue } = useMoneyField();
|
||||
|
||||
useEffect(() => {
|
||||
setFieldValue(value);
|
||||
}, [setFieldValue, value]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
type MoneyFieldInputWithContextProps = MoneyFieldInputProps & {
|
||||
value: number;
|
||||
entityId?: string;
|
||||
};
|
||||
|
||||
const MoneyFieldInputWithContext = ({
|
||||
entityId,
|
||||
value,
|
||||
onEnter,
|
||||
onEscape,
|
||||
onClickOutside,
|
||||
onTab,
|
||||
onShiftTab,
|
||||
}: MoneyFieldInputWithContextProps) => {
|
||||
const setHotKeyScope = useSetHotkeyScope();
|
||||
|
||||
useEffect(() => {
|
||||
setHotKeyScope('hotkey-scope');
|
||||
}, [setHotKeyScope]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FieldContextProvider
|
||||
fieldDefinition={{
|
||||
fieldMetadataId: 'moneyAmount',
|
||||
label: 'MoneyAmout',
|
||||
type: 'MONEY_AMOUNT',
|
||||
iconName: 'Icon123',
|
||||
metadata: {
|
||||
fieldName: 'moneyAmount',
|
||||
placeHolder: 'Enter Amount',
|
||||
},
|
||||
}}
|
||||
entityId={entityId}
|
||||
>
|
||||
<MoneyFieldValueSetterEffect value={value} />
|
||||
<MoneyFieldInput
|
||||
onEnter={onEnter}
|
||||
onEscape={onEscape}
|
||||
onClickOutside={onClickOutside}
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
</FieldContextProvider>
|
||||
<div data-testid="data-field-input-click-outside-div" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const enterJestFn = jest.fn();
|
||||
const escapeJestfn = jest.fn();
|
||||
const clickOutsideJestFn = jest.fn();
|
||||
const tabJestFn = jest.fn();
|
||||
const shiftTabJestFn = jest.fn();
|
||||
|
||||
const clearMocksDecorator: Decorator = (Story, context) => {
|
||||
if (context.parameters.clearMocks) {
|
||||
enterJestFn.mockClear();
|
||||
escapeJestfn.mockClear();
|
||||
clickOutsideJestFn.mockClear();
|
||||
tabJestFn.mockClear();
|
||||
shiftTabJestFn.mockClear();
|
||||
}
|
||||
return <Story />;
|
||||
};
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'UI/Data/Field/Input/MoneyFieldInput',
|
||||
component: MoneyFieldInputWithContext,
|
||||
args: {
|
||||
value: 1000,
|
||||
isPositive: true,
|
||||
onEnter: enterJestFn,
|
||||
onEscape: escapeJestfn,
|
||||
onClickOutside: clickOutsideJestFn,
|
||||
onTab: tabJestFn,
|
||||
onShiftTab: shiftTabJestFn,
|
||||
},
|
||||
argTypes: {
|
||||
onEnter: { control: false },
|
||||
onEscape: { control: false },
|
||||
onClickOutside: { control: false },
|
||||
onTab: { control: false },
|
||||
onShiftTab: { control: false },
|
||||
},
|
||||
decorators: [clearMocksDecorator],
|
||||
parameters: {
|
||||
clearMocks: true,
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof MoneyFieldInputWithContext>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
export const Enter: Story = {
|
||||
play: async () => {
|
||||
expect(enterJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{enter}');
|
||||
expect(enterJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const Escape: Story = {
|
||||
play: async () => {
|
||||
expect(escapeJestfn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{esc}');
|
||||
expect(escapeJestfn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const ClickOutside: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
expect(clickOutsideJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
const emptyDiv = canvas.getByTestId('data-field-input-click-outside-div');
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.click(emptyDiv);
|
||||
expect(clickOutsideJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const Tab: Story = {
|
||||
play: async () => {
|
||||
expect(tabJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{tab}');
|
||||
expect(tabJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const ShiftTab: Story = {
|
||||
play: async () => {
|
||||
expect(shiftTabJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{shift>}{tab}');
|
||||
expect(shiftTabJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
@ -1,175 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { expect, jest } from '@storybook/jest';
|
||||
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||
import { userEvent, waitFor, within } from '@storybook/testing-library';
|
||||
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
|
||||
import { FieldContextProvider } from '../../../__stories__/FieldContextProvider';
|
||||
import { useURLField } from '../../../hooks/useURLField';
|
||||
import { URLFieldInput, URLFieldInputProps } from '../URLFieldInput';
|
||||
|
||||
const URLFieldValueSetterEffect = ({ value }: { value: string }) => {
|
||||
const { setFieldValue } = useURLField();
|
||||
|
||||
useEffect(() => {
|
||||
setFieldValue(value);
|
||||
}, [setFieldValue, value]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
type URLFieldInputWithContextProps = URLFieldInputProps & {
|
||||
value: string;
|
||||
entityId?: string;
|
||||
};
|
||||
|
||||
const URLFieldInputWithContext = ({
|
||||
entityId,
|
||||
value,
|
||||
onEnter,
|
||||
onEscape,
|
||||
onClickOutside,
|
||||
onTab,
|
||||
onShiftTab,
|
||||
}: URLFieldInputWithContextProps) => {
|
||||
const setHotKeyScope = useSetHotkeyScope();
|
||||
|
||||
useEffect(() => {
|
||||
setHotKeyScope('hotkey-scope');
|
||||
}, [setHotKeyScope]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FieldContextProvider
|
||||
fieldDefinition={{
|
||||
fieldMetadataId: 'url',
|
||||
label: 'URL',
|
||||
type: 'URL',
|
||||
iconName: 'IconLink',
|
||||
metadata: {
|
||||
fieldName: 'URL',
|
||||
placeHolder: 'Enter URL',
|
||||
},
|
||||
}}
|
||||
entityId={entityId}
|
||||
>
|
||||
<URLFieldValueSetterEffect value={value} />
|
||||
<URLFieldInput
|
||||
onEnter={onEnter}
|
||||
onEscape={onEscape}
|
||||
onClickOutside={onClickOutside}
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
</FieldContextProvider>
|
||||
<div data-testid="data-field-input-click-outside-div" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const enterJestFn = jest.fn();
|
||||
const escapeJestfn = jest.fn();
|
||||
const clickOutsideJestFn = jest.fn();
|
||||
const tabJestFn = jest.fn();
|
||||
const shiftTabJestFn = jest.fn();
|
||||
|
||||
const clearMocksDecorator: Decorator = (Story, context) => {
|
||||
if (context.parameters.clearMocks) {
|
||||
enterJestFn.mockClear();
|
||||
escapeJestfn.mockClear();
|
||||
clickOutsideJestFn.mockClear();
|
||||
tabJestFn.mockClear();
|
||||
shiftTabJestFn.mockClear();
|
||||
}
|
||||
return <Story />;
|
||||
};
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'UI/Data/Field/Input/URLFieldInput',
|
||||
component: URLFieldInputWithContext,
|
||||
args: {
|
||||
value: 'https://username.domain',
|
||||
onEnter: enterJestFn,
|
||||
onEscape: escapeJestfn,
|
||||
onClickOutside: clickOutsideJestFn,
|
||||
onTab: tabJestFn,
|
||||
onShiftTab: shiftTabJestFn,
|
||||
},
|
||||
argTypes: {
|
||||
onEnter: { control: false },
|
||||
onEscape: { control: false },
|
||||
onClickOutside: { control: false },
|
||||
onTab: { control: false },
|
||||
onShiftTab: { control: false },
|
||||
},
|
||||
decorators: [clearMocksDecorator],
|
||||
parameters: {
|
||||
clearMocks: true,
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof URLFieldInputWithContext>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
export const Enter: Story = {
|
||||
play: async () => {
|
||||
expect(enterJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{enter}');
|
||||
expect(enterJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const Escape: Story = {
|
||||
play: async () => {
|
||||
expect(escapeJestfn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{esc}');
|
||||
expect(escapeJestfn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const ClickOutside: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
expect(clickOutsideJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
const emptyDiv = canvas.getByTestId('data-field-input-click-outside-div');
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.click(emptyDiv);
|
||||
expect(clickOutsideJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const Tab: Story = {
|
||||
play: async () => {
|
||||
expect(tabJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{tab}');
|
||||
expect(tabJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const ShiftTab: Story = {
|
||||
play: async () => {
|
||||
expect(shiftTabJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.keyboard('{shift>}{tab}');
|
||||
expect(shiftTabJestFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
},
|
||||
};
|
||||
@ -8,22 +8,18 @@ import { assertNotNull } from '~/utils/assert';
|
||||
import { FieldDefinition } from '../../types/FieldDefinition';
|
||||
import { FieldMetadata } from '../../types/FieldMetadata';
|
||||
import { isFieldBoolean } from '../../types/guards/isFieldBoolean';
|
||||
import { isFieldChip } from '../../types/guards/isFieldChip';
|
||||
import { isFieldCurrency } from '../../types/guards/isFieldCurrency';
|
||||
import { isFieldCurrencyValue } from '../../types/guards/isFieldCurrencyValue';
|
||||
import { isFieldDate } from '../../types/guards/isFieldDate';
|
||||
import { isFieldDoubleTextChip } from '../../types/guards/isFieldDoubleTextChip';
|
||||
import { isFieldEmail } from '../../types/guards/isFieldEmail';
|
||||
import { isFieldLink } from '../../types/guards/isFieldLink';
|
||||
import { isFieldLinkValue } from '../../types/guards/isFieldLinkValue';
|
||||
import { isFieldMoney } from '../../types/guards/isFieldMoney';
|
||||
import { isFieldNumber } from '../../types/guards/isFieldNumber';
|
||||
import { isFieldPhone } from '../../types/guards/isFieldPhone';
|
||||
import { isFieldProbability } from '../../types/guards/isFieldProbability';
|
||||
import { isFieldRelation } from '../../types/guards/isFieldRelation';
|
||||
import { isFieldRelationValue } from '../../types/guards/isFieldRelationValue';
|
||||
import { isFieldText } from '../../types/guards/isFieldText';
|
||||
import { isFieldURL } from '../../types/guards/isFieldURL';
|
||||
import { entityFieldsFamilyState } from '../entityFieldsFamilyState';
|
||||
|
||||
const isValueEmpty = (value: unknown) => !assertNotNull(value) || value === '';
|
||||
@ -32,27 +28,24 @@ export const isEntityFieldEmptyFamilySelector = selectorFamily({
|
||||
key: 'isEntityFieldEmptyFamilySelector',
|
||||
get: ({
|
||||
fieldDefinition,
|
||||
fieldName,
|
||||
entityId,
|
||||
}: {
|
||||
fieldDefinition: Pick<FieldDefinition<FieldMetadata>, 'type'> & {
|
||||
metadata: Omit<FieldMetadata, 'mainIdentifierMapper'>;
|
||||
};
|
||||
fieldDefinition: Pick<FieldDefinition<FieldMetadata>, 'type'>;
|
||||
fieldName: string;
|
||||
entityId: string;
|
||||
}) => {
|
||||
return ({ get }) => {
|
||||
if (
|
||||
isFieldUuid(fieldDefinition) ||
|
||||
isFieldText(fieldDefinition) ||
|
||||
isFieldURL(fieldDefinition) ||
|
||||
isFieldDate(fieldDefinition) ||
|
||||
isFieldNumber(fieldDefinition) ||
|
||||
isFieldProbability(fieldDefinition) ||
|
||||
isFieldMoney(fieldDefinition) ||
|
||||
isFieldEmail(fieldDefinition) ||
|
||||
isFieldBoolean(fieldDefinition) ||
|
||||
isFieldPhone(fieldDefinition)
|
||||
) {
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
const fieldValue = get(entityFieldsFamilyState(entityId))?.[
|
||||
fieldName
|
||||
] as string | number | boolean | null;
|
||||
@ -61,46 +54,12 @@ export const isEntityFieldEmptyFamilySelector = selectorFamily({
|
||||
}
|
||||
|
||||
if (isFieldRelation(fieldDefinition)) {
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
|
||||
const fieldValue = get(entityFieldsFamilyState(entityId))?.[fieldName];
|
||||
|
||||
return isFieldRelationValue(fieldValue) && isValueEmpty(fieldValue);
|
||||
}
|
||||
|
||||
if (isFieldChip(fieldDefinition)) {
|
||||
const contentFieldName = fieldDefinition.metadata.contentFieldName;
|
||||
|
||||
const contentFieldValue = get(entityFieldsFamilyState(entityId))?.[
|
||||
contentFieldName
|
||||
] as string | null;
|
||||
|
||||
return isValueEmpty(contentFieldValue);
|
||||
}
|
||||
|
||||
if (isFieldDoubleTextChip(fieldDefinition)) {
|
||||
const firstValueFieldName =
|
||||
fieldDefinition.metadata.firstValueFieldName;
|
||||
|
||||
const secondValueFieldName =
|
||||
fieldDefinition.metadata.secondValueFieldName;
|
||||
|
||||
const contentFieldFirstValue = get(entityFieldsFamilyState(entityId))?.[
|
||||
firstValueFieldName
|
||||
] as string | null;
|
||||
|
||||
const contentFieldSecondValue = get(
|
||||
entityFieldsFamilyState(entityId),
|
||||
)?.[secondValueFieldName] as string | null;
|
||||
|
||||
return (
|
||||
isValueEmpty(contentFieldFirstValue) &&
|
||||
isValueEmpty(contentFieldSecondValue)
|
||||
);
|
||||
}
|
||||
|
||||
if (isFieldCurrency(fieldDefinition)) {
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
const fieldValue = get(entityFieldsFamilyState(entityId))?.[fieldName];
|
||||
|
||||
return (
|
||||
@ -110,7 +69,6 @@ export const isEntityFieldEmptyFamilySelector = selectorFamily({
|
||||
}
|
||||
|
||||
if (isFieldFullName(fieldDefinition)) {
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
const fieldValue = get(entityFieldsFamilyState(entityId))?.[fieldName];
|
||||
|
||||
return (
|
||||
@ -120,7 +78,6 @@ export const isEntityFieldEmptyFamilySelector = selectorFamily({
|
||||
}
|
||||
|
||||
if (isFieldLink(fieldDefinition)) {
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
const fieldValue = get(entityFieldsFamilyState(entityId))?.[fieldName];
|
||||
|
||||
return !isFieldLinkValue(fieldValue) || isValueEmpty(fieldValue?.url);
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
|
||||
import { MainIdentifierMapper } from '@/ui/object/field/types/MainIdentifierMapper';
|
||||
import { ThemeColor } from '@/ui/theme/constants/colors';
|
||||
|
||||
export type FieldUuidMetadata = {
|
||||
placeHolder: string;
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldBooleanMetadata = {
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
@ -12,22 +14,8 @@ export type FieldTextMetadata = {
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldPhoneMetadata = {
|
||||
placeHolder: string;
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldURLMetadata = {
|
||||
placeHolder: string;
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldLinkMetadata = {
|
||||
placeHolder: string;
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldDateMetadata = {
|
||||
placeHolder: string;
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
@ -37,10 +25,9 @@ export type FieldNumberMetadata = {
|
||||
isPositive?: boolean;
|
||||
};
|
||||
|
||||
export type FieldMoneyMetadata = {
|
||||
fieldName: string;
|
||||
export type FieldLinkMetadata = {
|
||||
placeHolder: string;
|
||||
isPositive?: boolean;
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldCurrencyMetadata = {
|
||||
@ -49,13 +36,23 @@ export type FieldCurrencyMetadata = {
|
||||
isPositive?: boolean;
|
||||
};
|
||||
|
||||
export type FieldFullnameMetadata = {
|
||||
export type FieldFullNameMetadata = {
|
||||
placeHolder: string;
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldEmailMetadata = {
|
||||
fieldName: string;
|
||||
placeHolder: string;
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldPhoneMetadata = {
|
||||
placeHolder: string;
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldProbabilityMetadata = {
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldDefinitionRelationType =
|
||||
@ -74,85 +71,31 @@ export type FieldRelationMetadata = {
|
||||
objectMetadataNamePlural: string;
|
||||
};
|
||||
|
||||
export type FieldChipMetadata = {
|
||||
contentFieldName: string;
|
||||
urlFieldName: string;
|
||||
placeHolder: string;
|
||||
};
|
||||
|
||||
export type FieldDoubleTextMetadata = {
|
||||
firstValueFieldName: string;
|
||||
firstValuePlaceholder: string;
|
||||
secondValueFieldName: string;
|
||||
secondValuePlaceholder: string;
|
||||
};
|
||||
|
||||
export type FieldDoubleTextChipMetadata = {
|
||||
firstValueFieldName: string;
|
||||
firstValuePlaceholder: string;
|
||||
secondValueFieldName: string;
|
||||
secondValuePlaceholder: string;
|
||||
avatarUrlFieldName: string;
|
||||
};
|
||||
|
||||
export type FieldProbabilityMetadata = {
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldBooleanMetadata = {
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldEnumMetadata = {
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldMetadata =
|
||||
| FieldBooleanMetadata
|
||||
| FieldChipMetadata
|
||||
| FieldCurrencyMetadata
|
||||
| FieldDateMetadata
|
||||
| FieldDoubleTextChipMetadata
|
||||
| FieldDoubleTextMetadata
|
||||
| FieldEmailMetadata
|
||||
| FieldLinkMetadata
|
||||
| FieldMoneyMetadata
|
||||
| FieldNumberMetadata
|
||||
| FieldPhoneMetadata
|
||||
| FieldProbabilityMetadata
|
||||
| FieldEnumMetadata
|
||||
| FieldRelationMetadata
|
||||
| FieldDateMetadata
|
||||
| FieldTextMetadata
|
||||
| FieldURLMetadata
|
||||
| FieldUuidMetadata;
|
||||
| FieldUuidMetadata
|
||||
| FieldCurrencyMetadata
|
||||
| FieldLinkMetadata
|
||||
| FieldPhoneMetadata
|
||||
| FieldEmailMetadata
|
||||
| FieldProbabilityMetadata
|
||||
| FieldRelationMetadata
|
||||
| FieldFullNameMetadata;
|
||||
|
||||
export type FieldTextValue = string;
|
||||
export type FieldUUidValue = string;
|
||||
|
||||
export type FieldChipValue = string;
|
||||
export type FieldDateValue = string | null;
|
||||
export type FieldPhoneValue = string;
|
||||
export type FieldURLValue = string;
|
||||
export type FieldLinkValue = { url: string; label: string };
|
||||
export type FieldNumberValue = number | null;
|
||||
export type FieldMoneyValue = number | null;
|
||||
export type FieldCurrencyValue = { currencyCode: string; amountMicros: number };
|
||||
export type FieldFullNameValue = { firstName: string; lastName: string };
|
||||
|
||||
export type FieldEmailValue = string;
|
||||
export type FieldProbabilityValue = number;
|
||||
export type FieldBooleanValue = boolean;
|
||||
|
||||
export type FieldDoubleTextValue = {
|
||||
firstValue: string;
|
||||
secondValue: string;
|
||||
};
|
||||
|
||||
export type FieldDoubleTextChipValue = {
|
||||
firstValue: string;
|
||||
secondValue: string;
|
||||
};
|
||||
export type FieldPhoneValue = string;
|
||||
export type FieldEmailValue = string;
|
||||
export type FieldLinkValue = { url: string; label: string };
|
||||
export type FieldCurrencyValue = { currencyCode: string; amountMicros: number };
|
||||
export type FieldFullNameValue = { firstName: string; lastName: string };
|
||||
export type FieldProbabilityValue = number;
|
||||
|
||||
export type FieldRelationValue = EntityForSelect | null;
|
||||
|
||||
export type FieldEnumValue = { color: ThemeColor; text: string };
|
||||
|
||||
@ -1,23 +1,17 @@
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import {
|
||||
FieldBooleanMetadata,
|
||||
FieldChipMetadata,
|
||||
FieldCurrencyMetadata,
|
||||
FieldDateMetadata,
|
||||
FieldDoubleTextChipMetadata,
|
||||
FieldDoubleTextMetadata,
|
||||
FieldEmailMetadata,
|
||||
FieldEnumMetadata,
|
||||
FieldFullnameMetadata,
|
||||
FieldFullNameMetadata,
|
||||
FieldLinkMetadata,
|
||||
FieldMetadata,
|
||||
FieldMoneyMetadata,
|
||||
FieldNumberMetadata,
|
||||
FieldPhoneMetadata,
|
||||
FieldProbabilityMetadata,
|
||||
FieldRelationMetadata,
|
||||
FieldTextMetadata,
|
||||
FieldURLMetadata,
|
||||
FieldUuidMetadata,
|
||||
} from '../FieldMetadata';
|
||||
import { FieldType } from '../FieldType';
|
||||
@ -26,26 +20,16 @@ type AssertFieldMetadataFunction = <
|
||||
E extends FieldType,
|
||||
T extends E extends 'BOOLEAN'
|
||||
? FieldBooleanMetadata
|
||||
: E extends 'CHIP'
|
||||
? FieldChipMetadata
|
||||
: E extends 'CURRENCY'
|
||||
? FieldCurrencyMetadata
|
||||
: E extends 'FULL_NAME'
|
||||
? FieldFullnameMetadata
|
||||
? FieldFullNameMetadata
|
||||
: E extends 'DATE'
|
||||
? FieldDateMetadata
|
||||
: E extends 'DOUBLE_TEXT'
|
||||
? FieldDoubleTextMetadata
|
||||
: E extends 'DOUBLE_TEXT_CHIP'
|
||||
? FieldDoubleTextChipMetadata
|
||||
: E extends 'EMAIL'
|
||||
? FieldEmailMetadata
|
||||
: E extends 'LINK'
|
||||
? FieldLinkMetadata
|
||||
: E extends 'MONEY_AMOUNT'
|
||||
? FieldMoneyMetadata
|
||||
: E extends 'ENUM'
|
||||
? FieldEnumMetadata
|
||||
: E extends 'NUMBER'
|
||||
? FieldNumberMetadata
|
||||
: E extends 'PHONE'
|
||||
@ -56,8 +40,6 @@ type AssertFieldMetadataFunction = <
|
||||
? FieldRelationMetadata
|
||||
: E extends 'TEXT'
|
||||
? FieldTextMetadata
|
||||
: E extends 'URL'
|
||||
? FieldURLMetadata
|
||||
: E extends 'UUID'
|
||||
? FieldUuidMetadata
|
||||
: never,
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldChipMetadata, FieldMetadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldChip = (
|
||||
field: Pick<FieldDefinition<FieldMetadata>, 'type'>,
|
||||
): field is FieldDefinition<FieldChipMetadata> => field.type === 'CHIP';
|
||||
@ -1,8 +0,0 @@
|
||||
import { isString } from '@sniptt/guards';
|
||||
|
||||
import { FieldChipValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add zod
|
||||
export const isFieldChipValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldChipValue => isString(fieldValue);
|
||||
@ -1,7 +0,0 @@
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldDoubleTextMetadata, FieldMetadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldDoubleText = (
|
||||
field: Pick<FieldDefinition<FieldMetadata>, 'type'>,
|
||||
): field is FieldDefinition<FieldDoubleTextMetadata> =>
|
||||
field.type === 'DOUBLE_TEXT';
|
||||
@ -1,7 +0,0 @@
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldDoubleTextChipMetadata, FieldMetadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldDoubleTextChip = (
|
||||
field: Pick<FieldDefinition<FieldMetadata>, 'type'>,
|
||||
): field is FieldDefinition<FieldDoubleTextChipMetadata> =>
|
||||
field.type === 'DOUBLE_TEXT_CHIP';
|
||||
@ -1,9 +0,0 @@
|
||||
import { FieldDoubleTextChipValue } from '../FieldMetadata';
|
||||
import { DoubleTextTypeResolver } from '../resolvers/DoubleTextTypeResolver';
|
||||
|
||||
export const isFieldDoubleTextChipValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldDoubleTextChipValue =>
|
||||
fieldValue !== null &&
|
||||
fieldValue !== undefined &&
|
||||
DoubleTextTypeResolver.safeParse(fieldValue).success;
|
||||
@ -1,10 +0,0 @@
|
||||
import { FieldDoubleTextValue } from '../FieldMetadata';
|
||||
import { DoubleTextTypeResolver } from '../resolvers/DoubleTextTypeResolver';
|
||||
|
||||
// TODO: add zod
|
||||
export const isFieldDoubleTextValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldDoubleTextValue =>
|
||||
fieldValue !== null &&
|
||||
fieldValue !== undefined &&
|
||||
DoubleTextTypeResolver.safeParse(fieldValue).success;
|
||||
@ -1,6 +0,0 @@
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldEnumMetadata, FieldMetadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldEnum = (
|
||||
field: Pick<FieldDefinition<FieldMetadata>, 'type'>,
|
||||
): field is FieldDefinition<FieldEnumMetadata> => field.type === 'ENUM';
|
||||
@ -1,7 +1,7 @@
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldCurrencyMetadata, FieldMetadata } from '../FieldMetadata';
|
||||
import { FieldFullNameMetadata, FieldMetadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldFullName = (
|
||||
field: Pick<FieldDefinition<FieldMetadata>, 'type'>,
|
||||
): field is FieldDefinition<FieldCurrencyMetadata> =>
|
||||
): field is FieldDefinition<FieldFullNameMetadata> =>
|
||||
field.type === 'FULL_NAME';
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldMetadata, FieldMoneyMetadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldMoney = (
|
||||
field: Pick<FieldDefinition<FieldMetadata>, 'type'>,
|
||||
): field is FieldDefinition<FieldMoneyMetadata> =>
|
||||
field.type === 'MONEY_AMOUNT';
|
||||
@ -1,8 +0,0 @@
|
||||
import { isNull, isNumber } from '@sniptt/guards';
|
||||
|
||||
import { FieldMoneyValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add zod
|
||||
export const isFieldMoneyValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldMoneyValue => isNull(fieldValue) || isNumber(fieldValue);
|
||||
@ -1,6 +0,0 @@
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldMetadata, FieldURLMetadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldURL = (
|
||||
field: Pick<FieldDefinition<FieldMetadata>, 'type'>,
|
||||
): field is FieldDefinition<FieldURLMetadata> => field.type === 'URL';
|
||||
@ -1,8 +0,0 @@
|
||||
import { isString } from '@sniptt/guards';
|
||||
|
||||
import { FieldURLValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add zod
|
||||
export const isFieldURLValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldURLValue => isString(fieldValue);
|
||||
Reference in New Issue
Block a user