@homefile/components-v2 2.10.0 → 2.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/forms/dynamicForm/DynamicForm.d.ts +1 -1
- package/dist/components/forms/dynamicForm/DynamicForm.js +3 -3
- package/dist/components/forms/dynamicForm/fields/AIGridField.d.ts +2 -0
- package/dist/components/forms/dynamicForm/fields/AIGridField.js +40 -0
- package/dist/components/forms/dynamicForm/fields/SingleImage.js +1 -1
- package/dist/components/forms/dynamicForm/fields/index.d.ts +1 -0
- package/dist/components/forms/dynamicForm/fields/index.js +1 -0
- package/dist/interfaces/forms/dynamicForm/DynamicForm.interface.d.ts +2 -1
- package/dist/interfaces/forms/dynamicForm/fields/GridField.interface.d.ts +7 -0
- package/dist/stories/forms/dynamicForm/DynamicForm.stories.d.ts +1 -1
- package/dist/stories/forms/dynamicForm/DynamicForm.stories.js +2 -0
- package/package.json +1 -1
- package/src/components/forms/dynamicForm/DynamicForm.tsx +8 -3
- package/src/components/forms/dynamicForm/fields/AIGridField.tsx +75 -0
- package/src/components/forms/dynamicForm/fields/SingleImage.tsx +3 -2
- package/src/components/forms/dynamicForm/fields/index.ts +1 -0
- package/src/interfaces/forms/dynamicForm/DynamicForm.interface.ts +8 -1
- package/src/interfaces/forms/dynamicForm/fields/GridField.interface.ts +9 -0
- package/src/stories/forms/dynamicForm/DynamicForm.stories.tsx +3 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { DynamicFormI } from '../../../interfaces';
|
|
2
|
-
export declare const DynamicForm: ({ callback, displayImages, form: fields, menuItems, onRemoveImage, onUpload, showTitle, title, uploadingFieldId, ...props }: DynamicFormI) => import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare const DynamicForm: ({ callback, displayImages, form: fields, menuItems, onAISend, onRemoveImage, onUpload, showTitle, title, uploadingFieldId, ...props }: DynamicFormI) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -14,11 +14,11 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
14
14
|
import { FormProvider } from 'react-hook-form';
|
|
15
15
|
import { t } from 'i18next';
|
|
16
16
|
import { Box, Stack, Text } from '@chakra-ui/react';
|
|
17
|
-
import { HiddenFieldSection, GroupField, TextField, TextAreaField, SelectField, RatingField, GridField, FieldWithDelete, FileField, SwitchField, DateField, NumberField, CurrencyField, TileBody, CheckboxGroupField, CheckboxAgreement, } from '../..';
|
|
17
|
+
import { HiddenFieldSection, GroupField, TextField, TextAreaField, SelectField, RatingField, GridField, FieldWithDelete, FileField, SwitchField, DateField, NumberField, CurrencyField, TileBody, CheckboxGroupField, CheckboxAgreement, AIGridField, } from '../..';
|
|
18
18
|
import { useDynamicForm } from '../../../hooks';
|
|
19
19
|
import { fieldIcons } from '../../../helpers';
|
|
20
20
|
export const DynamicForm = (_a) => {
|
|
21
|
-
var { callback, displayImages, form: fields, menuItems, onRemoveImage, onUpload, showTitle = true, title, uploadingFieldId } = _a, props = __rest(_a, ["callback", "displayImages", "form", "menuItems", "onRemoveImage", "onUpload", "showTitle", "title", "uploadingFieldId"]);
|
|
21
|
+
var { callback, displayImages, form: fields, menuItems, onAISend, onRemoveImage, onUpload, showTitle = true, title, uploadingFieldId } = _a, props = __rest(_a, ["callback", "displayImages", "form", "menuItems", "onAISend", "onRemoveImage", "onUpload", "showTitle", "title", "uploadingFieldId"]);
|
|
22
22
|
const { form, visibleFields, hiddenFields, handleAddAll, handleAdd, handleFilesUpload, handleRemove, } = useDynamicForm({ fields, onUpload });
|
|
23
23
|
return (_jsxs(Stack, { bg: "lightBlue.1", spacing: "0", h: "full", overflowX: "hidden", children: [showTitle && (_jsx(Box, { px: "base", pt: "4", pb: "2", borderBottom: "1px dashed", borderColor: "lightBlue.6", children: _jsx(Text, { fontFamily: "secondary", children: title !== null && title !== void 0 ? title : t('forms.itemDetails') }) })), _jsx(FormProvider, Object.assign({}, form, { children: _jsx(_Fragment, { children: visibleFields === null || visibleFields === void 0 ? void 0 : visibleFields.map((field) => {
|
|
24
24
|
const { canBeHidden, children, description, icon, id, name, options, type, value, } = field;
|
|
@@ -63,7 +63,7 @@ export const DynamicForm = (_a) => {
|
|
|
63
63
|
return (_createElement(FieldWithDelete, Object.assign({}, fieldWithDeleteBaseProps, { key: id }),
|
|
64
64
|
_jsx(RatingField, Object.assign({}, baseProps))));
|
|
65
65
|
case 'ai-grid':
|
|
66
|
-
return (_jsxs(Stack, { p: "base", spacing: "base", bg: "lightBlue.2", children: [_jsx(Text, { fontFamily: "secondary", children: description }), _jsx(
|
|
66
|
+
return (_jsxs(Stack, { p: "base", spacing: "base", bg: "lightBlue.2", children: [description && (_jsx(Text, { fontFamily: "secondary", children: description })), _jsx(AIGridField, Object.assign({}, baseProps, { onRemove: onRemoveImage, onUpload: (files) => handleFilesUpload({ id, files }), onAISend: onAISend, children: children }))] }, id));
|
|
67
67
|
case 'grid':
|
|
68
68
|
return (_createElement(FieldWithDelete, Object.assign({}, fieldWithDeleteBaseProps, { key: id }),
|
|
69
69
|
_jsx(GridField, Object.assign({}, baseProps, { children: children }))));
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useFormContext } from 'react-hook-form';
|
|
3
|
+
import { Flex, IconButton, Text } from '@chakra-ui/react';
|
|
4
|
+
import { TextField, SingleImage, Plus } from '../../..';
|
|
5
|
+
import { fieldIcons } from '../../../../helpers';
|
|
6
|
+
import { colors } from '../../../../theme/colors';
|
|
7
|
+
export const AIGridField = ({ children, onAISend, onRemove, onUpload, }) => {
|
|
8
|
+
var _a, _b, _c, _d, _e, _f;
|
|
9
|
+
const { watch } = useFormContext();
|
|
10
|
+
const textChild = children === null || children === void 0 ? void 0 : children.find(({ type }) => type === 'text' || type === 'string');
|
|
11
|
+
const textProps = {
|
|
12
|
+
id: (_a = textChild === null || textChild === void 0 ? void 0 : textChild.id) !== null && _a !== void 0 ? _a : '',
|
|
13
|
+
value: (_b = textChild === null || textChild === void 0 ? void 0 : textChild.value) !== null && _b !== void 0 ? _b : '',
|
|
14
|
+
placeholder: (_c = textChild === null || textChild === void 0 ? void 0 : textChild.name) !== null && _c !== void 0 ? _c : textChild === null || textChild === void 0 ? void 0 : textChild.description,
|
|
15
|
+
icon: (textChild === null || textChild === void 0 ? void 0 : textChild.icon)
|
|
16
|
+
? fieldIcons[textChild.icon]
|
|
17
|
+
: undefined,
|
|
18
|
+
};
|
|
19
|
+
const imageField = children === null || children === void 0 ? void 0 : children.find(({ type }) => type === 'ai-image');
|
|
20
|
+
const imageProps = {
|
|
21
|
+
id: (_d = imageField === null || imageField === void 0 ? void 0 : imageField.id) !== null && _d !== void 0 ? _d : '',
|
|
22
|
+
value: (_e = imageField === null || imageField === void 0 ? void 0 : imageField.value) !== null && _e !== void 0 ? _e : '',
|
|
23
|
+
placeholder: (_f = imageField === null || imageField === void 0 ? void 0 : imageField.name) !== null && _f !== void 0 ? _f : imageField === null || imageField === void 0 ? void 0 : imageField.description,
|
|
24
|
+
icon: (imageField === null || imageField === void 0 ? void 0 : imageField.icon)
|
|
25
|
+
? fieldIcons[imageField.icon]
|
|
26
|
+
: undefined,
|
|
27
|
+
};
|
|
28
|
+
const code = watch(String(textChild === null || textChild === void 0 ? void 0 : textChild.id));
|
|
29
|
+
const handleAISend = () => {
|
|
30
|
+
const form = {};
|
|
31
|
+
if (code) {
|
|
32
|
+
form.code = code;
|
|
33
|
+
}
|
|
34
|
+
else if (imageField === null || imageField === void 0 ? void 0 : imageField.value) {
|
|
35
|
+
form.image = imageField.value;
|
|
36
|
+
}
|
|
37
|
+
onAISend === null || onAISend === void 0 ? void 0 : onAISend(form);
|
|
38
|
+
};
|
|
39
|
+
return (_jsxs(Flex, { align: "center", gap: "base", children: [_jsx(SingleImage, Object.assign({}, imageProps, { onUpload: onUpload, onRemove: onRemove, value: imageField === null || imageField === void 0 ? void 0 : imageField.value })), _jsx(Text, { fontFamily: "secondary", textAlign: "center", children: "OR" }), _jsx(TextField, Object.assign({}, textProps)), _jsx(IconButton, { "aria-label": "Add new address line", variant: "iconOutlined", icon: _jsx(Plus, { size: 28, stroke: colors.blue[3] }), onClick: handleAISend, h: "input.md", disabled: !(code === null || code === void 0 ? void 0 : code.length) && !(imageField === null || imageField === void 0 ? void 0 : imageField.value) })] }));
|
|
40
|
+
};
|
|
@@ -13,5 +13,5 @@ export const SingleImage = ({ onRemove, onUpload, uploading = false, value, }) =
|
|
|
13
13
|
onUpload === null || onUpload === void 0 ? void 0 : onUpload(selectedFiles);
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
|
-
return (_jsxs(Flex, { gap: "
|
|
16
|
+
return (_jsxs(Flex, { gap: "2", align: "center", h: "input.md", children: [_jsx(MobileFileUploader, { handleInputChange: handleInputChange, "aria-label": "upload image", minW: "72px" }), value && (_jsxs(Box, { position: "relative", minW: "30px", children: [_jsx(IconButton, { variant: "ghost", "aria-label": "close", maxW: "fit-content", onClick: () => onRemove === null || onRemove === void 0 ? void 0 : onRemove(value), icon: _jsx(Close, { size: 11, stroke: colors.error['2'] }), disabled: uploading, position: "absolute", bg: "neutral.white", p: "0.5", borderRadius: "full", top: "-2", right: "-2", zIndex: "1" }), _jsx(AspectRatio, { maxW: "100%", ratio: 1, children: _jsx(Image, { src: value, objectFit: "cover", alt: "image" }) })] }))] }));
|
|
17
17
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FolderFileI, MenuItemI, PartnerFooterI, TileCtaI } from '../..';
|
|
1
|
+
import { AIGridFieldI, FolderFileI, MenuItemI, PartnerFooterI, TileCtaI } from '../..';
|
|
2
2
|
export type KindTypes = 'ai-image' | 'ai-grid' | 'checkbox' | 'checkbox-agreement' | 'checkbox-group' | 'currency' | 'date' | 'email' | 'file' | 'grid' | 'group' | 'hidden' | 'notes' | 'number' | 'radio' | 'rating' | 'select' | 'string' | 'switch' | 'telephone' | 'text' | 'textarea' | 'default' | UIKindTypes | HomeItemTypes;
|
|
3
3
|
export type UIKindTypes = 'tile-body' | 'tile-body-logo' | 'tile-body-header' | 'tile-body-section' | 'tile-body-section-grid' | 'tile-form' | 'tile-body-action' | 'vertical-icon' | 'primary-cta' | 'secondary-cta';
|
|
4
4
|
export type HomeItemTypes = 'appliances' | 'images' | 'guidelines' | 'item-related' | 'item-icon-btn';
|
|
@@ -25,6 +25,7 @@ export interface DynamicFormI extends Partial<PartnerFooterI> {
|
|
|
25
25
|
displayImages?: string[];
|
|
26
26
|
form: ReportI[];
|
|
27
27
|
menuItems?: MenuItemI[];
|
|
28
|
+
onAISend?: AIGridFieldI['onAISend'];
|
|
28
29
|
onRemoveImage?: (file: string) => void;
|
|
29
30
|
onUpload?: (filesByFieldId: Record<string, FolderFileI[]>) => void;
|
|
30
31
|
showTitle?: boolean;
|
|
@@ -4,3 +4,10 @@ export interface GridFieldI {
|
|
|
4
4
|
onRemove?: (file: string) => void;
|
|
5
5
|
onUpload?: (files: FolderFileI[]) => void;
|
|
6
6
|
}
|
|
7
|
+
export interface AIGridFieldI extends GridFieldI {
|
|
8
|
+
onAISend?: (form?: AIFormI) => void;
|
|
9
|
+
}
|
|
10
|
+
export interface AIFormI {
|
|
11
|
+
code?: string;
|
|
12
|
+
image?: string;
|
|
13
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Meta } from '@storybook/react';
|
|
2
2
|
import { DynamicFormI } from '../../../interfaces';
|
|
3
|
-
declare const _default: Meta
|
|
3
|
+
declare const _default: Meta<DynamicFormI>;
|
|
4
4
|
export default _default;
|
|
5
5
|
export declare const DynamicFormComponent: (args: DynamicFormI) => import("react/jsx-runtime").JSX.Element;
|
|
6
6
|
export declare const DynamicUIFormComponent: (args: DynamicFormI) => import("react/jsx-runtime").JSX.Element;
|
package/package.json
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
TileBody,
|
|
20
20
|
CheckboxGroupField,
|
|
21
21
|
CheckboxAgreement,
|
|
22
|
+
AIGridField,
|
|
22
23
|
} from '@/components'
|
|
23
24
|
import { useDynamicForm } from '@/hooks'
|
|
24
25
|
import { fieldIcons } from '@/helpers'
|
|
@@ -28,6 +29,7 @@ export const DynamicForm = ({
|
|
|
28
29
|
displayImages,
|
|
29
30
|
form: fields,
|
|
30
31
|
menuItems,
|
|
32
|
+
onAISend,
|
|
31
33
|
onRemoveImage,
|
|
32
34
|
onUpload,
|
|
33
35
|
showTitle = true,
|
|
@@ -143,14 +145,17 @@ export const DynamicForm = ({
|
|
|
143
145
|
case 'ai-grid':
|
|
144
146
|
return (
|
|
145
147
|
<Stack key={id} p="base" spacing="base" bg="lightBlue.2">
|
|
146
|
-
|
|
147
|
-
|
|
148
|
+
{description && (
|
|
149
|
+
<Text fontFamily="secondary">{description}</Text>
|
|
150
|
+
)}
|
|
151
|
+
<AIGridField
|
|
148
152
|
{...baseProps}
|
|
149
153
|
onRemove={onRemoveImage}
|
|
150
154
|
onUpload={(files) => handleFilesUpload({ id, files })}
|
|
155
|
+
onAISend={onAISend}
|
|
151
156
|
>
|
|
152
157
|
{children}
|
|
153
|
-
</
|
|
158
|
+
</AIGridField>
|
|
154
159
|
</Stack>
|
|
155
160
|
)
|
|
156
161
|
case 'grid':
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { useFormContext } from 'react-hook-form'
|
|
2
|
+
import { Flex, IconButton, Text } from '@chakra-ui/react'
|
|
3
|
+
import { IconTypes, AIGridFieldI, AIFormI } from '@/interfaces'
|
|
4
|
+
import { TextField, SingleImage, Plus } from '@/components'
|
|
5
|
+
import { fieldIcons } from '@/helpers'
|
|
6
|
+
import { colors } from '@/theme/colors'
|
|
7
|
+
|
|
8
|
+
export const AIGridField = ({
|
|
9
|
+
children,
|
|
10
|
+
onAISend,
|
|
11
|
+
onRemove,
|
|
12
|
+
onUpload,
|
|
13
|
+
}: AIGridFieldI) => {
|
|
14
|
+
const { watch } = useFormContext()
|
|
15
|
+
|
|
16
|
+
const textChild = children?.find(
|
|
17
|
+
({ type }) => type === 'text' || type === 'string'
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
const textProps = {
|
|
21
|
+
id: textChild?.id ?? '',
|
|
22
|
+
value: textChild?.value ?? '',
|
|
23
|
+
placeholder: textChild?.name ?? textChild?.description,
|
|
24
|
+
icon: textChild?.icon
|
|
25
|
+
? (fieldIcons[textChild.icon] as IconTypes)
|
|
26
|
+
: undefined,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const imageField = children?.find(({ type }) => type === 'ai-image')
|
|
30
|
+
|
|
31
|
+
const imageProps = {
|
|
32
|
+
id: imageField?.id ?? '',
|
|
33
|
+
value: imageField?.value ?? '',
|
|
34
|
+
placeholder: imageField?.name ?? imageField?.description,
|
|
35
|
+
icon: imageField?.icon
|
|
36
|
+
? (fieldIcons[imageField.icon] as IconTypes)
|
|
37
|
+
: undefined,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const code = watch(String(textChild?.id))
|
|
41
|
+
|
|
42
|
+
const handleAISend = () => {
|
|
43
|
+
const form: AIFormI = {}
|
|
44
|
+
|
|
45
|
+
if (code) {
|
|
46
|
+
form.code = code
|
|
47
|
+
} else if (imageField?.value) {
|
|
48
|
+
form.image = imageField.value as string
|
|
49
|
+
}
|
|
50
|
+
onAISend?.(form)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Flex align="center" gap="base">
|
|
55
|
+
<SingleImage
|
|
56
|
+
{...imageProps}
|
|
57
|
+
onUpload={onUpload}
|
|
58
|
+
onRemove={onRemove}
|
|
59
|
+
value={imageField?.value as string}
|
|
60
|
+
/>
|
|
61
|
+
<Text fontFamily="secondary" textAlign="center">
|
|
62
|
+
OR
|
|
63
|
+
</Text>
|
|
64
|
+
<TextField {...textProps} />
|
|
65
|
+
<IconButton
|
|
66
|
+
aria-label="Add new address line"
|
|
67
|
+
variant="iconOutlined"
|
|
68
|
+
icon={<Plus size={28} stroke={colors.blue[3]} />}
|
|
69
|
+
onClick={handleAISend}
|
|
70
|
+
h="input.md"
|
|
71
|
+
disabled={!code?.length && !imageField?.value}
|
|
72
|
+
/>
|
|
73
|
+
</Flex>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
@@ -21,13 +21,14 @@ export const SingleImage = ({
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
|
-
<Flex gap="
|
|
24
|
+
<Flex gap="2" align="center" h="input.md">
|
|
25
25
|
<MobileFileUploader
|
|
26
26
|
handleInputChange={handleInputChange}
|
|
27
27
|
aria-label="upload image"
|
|
28
|
+
minW="72px"
|
|
28
29
|
/>
|
|
29
30
|
{value && (
|
|
30
|
-
<Box position="relative"
|
|
31
|
+
<Box position="relative" minW="30px">
|
|
31
32
|
<IconButton
|
|
32
33
|
variant="ghost"
|
|
33
34
|
aria-label="close"
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AIGridFieldI,
|
|
3
|
+
FolderFileI,
|
|
4
|
+
MenuItemI,
|
|
5
|
+
PartnerFooterI,
|
|
6
|
+
TileCtaI,
|
|
7
|
+
} from '@/interfaces'
|
|
2
8
|
|
|
3
9
|
export type KindTypes =
|
|
4
10
|
| 'ai-image'
|
|
@@ -127,6 +133,7 @@ export interface DynamicFormI extends Partial<PartnerFooterI> {
|
|
|
127
133
|
displayImages?: string[]
|
|
128
134
|
form: ReportI[]
|
|
129
135
|
menuItems?: MenuItemI[]
|
|
136
|
+
onAISend?: AIGridFieldI['onAISend']
|
|
130
137
|
onRemoveImage?: (file: string) => void
|
|
131
138
|
onUpload?: (filesByFieldId: Record<string, FolderFileI[]>) => void
|
|
132
139
|
showTitle?: boolean
|
|
@@ -5,3 +5,12 @@ export interface GridFieldI {
|
|
|
5
5
|
onRemove?: (file: string) => void
|
|
6
6
|
onUpload?: (files: FolderFileI[]) => void
|
|
7
7
|
}
|
|
8
|
+
|
|
9
|
+
export interface AIGridFieldI extends GridFieldI {
|
|
10
|
+
onAISend?: (form?: AIFormI) => void
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface AIFormI {
|
|
14
|
+
code?: string
|
|
15
|
+
image?: string
|
|
16
|
+
}
|
|
@@ -21,12 +21,14 @@ export default {
|
|
|
21
21
|
faker.image.urlPicsumPhotos(),
|
|
22
22
|
faker.image.urlPicsumPhotos(),
|
|
23
23
|
],
|
|
24
|
+
onAISend: action('onAiSend'),
|
|
25
|
+
onRemoveImage: action('onRemoveImage'),
|
|
24
26
|
onUpload: action('onUpload'),
|
|
25
27
|
menuItems: menuMock,
|
|
26
28
|
socialLinks: socialLinksMock,
|
|
27
29
|
websiteUrl: 'http://www.audreyscheckdesign.com',
|
|
28
30
|
},
|
|
29
|
-
} as Meta
|
|
31
|
+
} as Meta<DynamicFormI>
|
|
30
32
|
|
|
31
33
|
export const DynamicFormComponent = (args: DynamicFormI) => {
|
|
32
34
|
return (
|