@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.
@@ -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(GridField, Object.assign({}, baseProps, { onRemove: onRemoveImage, onUpload: (files) => handleFilesUpload({ id, files }), children: children }))] }, id));
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,2 @@
1
+ import { AIGridFieldI } from '../../../../interfaces';
2
+ export declare const AIGridField: ({ children, onAISend, onRemove, onUpload, }: AIGridFieldI) => import("react/jsx-runtime").JSX.Element;
@@ -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: "1", align: "center", flex: "auto1", children: [_jsx(MobileFileUploader, { handleInputChange: handleInputChange, "aria-label": "upload image" }), value && (_jsxs(Box, { position: "relative", w: "66px", 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" }) })] }))] }));
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,3 +1,4 @@
1
+ export * from './AIGridField';
1
2
  export * from './CheckboxAgreement';
2
3
  export * from './CheckboxGroupField';
3
4
  export * from './CurrencyField';
@@ -1,3 +1,4 @@
1
+ export * from './AIGridField';
1
2
  export * from './CheckboxAgreement';
2
3
  export * from './CheckboxGroupField';
3
4
  export * from './CurrencyField';
@@ -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;
@@ -19,6 +19,8 @@ export default {
19
19
  faker.image.urlPicsumPhotos(),
20
20
  faker.image.urlPicsumPhotos(),
21
21
  ],
22
+ onAISend: action('onAiSend'),
23
+ onRemoveImage: action('onRemoveImage'),
22
24
  onUpload: action('onUpload'),
23
25
  menuItems: menuMock,
24
26
  socialLinks: socialLinksMock,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homefile/components-v2",
3
- "version": "2.10.0",
3
+ "version": "2.11.1",
4
4
  "author": "Homefile",
5
5
  "license": "UNLICENSED",
6
6
  "typings": "dist/index.d.ts",
@@ -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
- <Text fontFamily="secondary">{description}</Text>
147
- <GridField
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
- </GridField>
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="1" align="center" flex="auto1">
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" w="66px">
31
+ <Box position="relative" minW="30px">
31
32
  <IconButton
32
33
  variant="ghost"
33
34
  aria-label="close"
@@ -1,3 +1,4 @@
1
+ export * from './AIGridField'
1
2
  export * from './CheckboxAgreement'
2
3
  export * from './CheckboxGroupField'
3
4
  export * from './CurrencyField'
@@ -1,4 +1,10 @@
1
- import { FolderFileI, MenuItemI, PartnerFooterI, TileCtaI } from '@/interfaces'
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 (