@headless-adminapp/fluent 1.4.23 → 1.4.24

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.
@@ -60,6 +60,7 @@ const NavActions = () => {
60
60
  const logout = (0, hooks_1.useLogout)();
61
61
  const strings = (0, AppStringContext_1.useAppStrings)();
62
62
  const { language } = (0, locale_1.useLocale)();
63
+ const [accountMenuOpen, setAccountMenuOpen] = (0, react_1.useState)(false);
63
64
  const initials = (0, react_1.useMemo)(() => {
64
65
  return authSession?.fullName
65
66
  .toUpperCase()
@@ -81,7 +82,7 @@ const NavActions = () => {
81
82
  return (0, jsx_runtime_1.jsx)(item.Component, {}, item.__key);
82
83
  }
83
84
  return ((0, jsx_runtime_1.jsx)(QuickActionItem_1.QuickActionItem, { Icon: item.icon, label: item.localizedLabel?.[language] ?? item.label, onClick: () => item.onClick?.(), link: item.link }, item.__key));
84
- }) }), (!isSkipAuthCheck || !!accountMenuItems?.length) && ((0, jsx_runtime_1.jsxs)(react_components_1.Popover, { children: [(0, jsx_runtime_1.jsx)(react_components_1.PopoverTrigger, { disableButtonEnhancement: true, children: (0, jsx_runtime_1.jsx)(react_components_1.Avatar, { initials: initials, color: "neutral", style: { cursor: 'pointer' }, image: {
85
+ }) }), (!isSkipAuthCheck || !!accountMenuItems?.length) && ((0, jsx_runtime_1.jsxs)(react_components_1.Popover, { open: accountMenuOpen, onOpenChange: (e, data) => setAccountMenuOpen(data.open), children: [(0, jsx_runtime_1.jsx)(react_components_1.PopoverTrigger, { disableButtonEnhancement: true, children: (0, jsx_runtime_1.jsx)(react_components_1.Avatar, { initials: initials, color: "neutral", style: { cursor: 'pointer' }, image: {
85
86
  src: authSession?.profilePicture,
86
87
  } }) }), (0, jsx_runtime_1.jsxs)(react_components_1.PopoverSurface, { tabIndex: -1, style: { padding: 0 }, children: [!isSkipAuthCheck && ((0, jsx_runtime_1.jsxs)("div", { style: {
87
88
  display: 'flex',
@@ -99,6 +100,7 @@ const NavActions = () => {
99
100
  }, children: [(0, jsx_runtime_1.jsx)(react_components_1.Caption1Strong, { children: authSession?.fullName }), (0, jsx_runtime_1.jsx)(react_components_1.Caption1, { style: { textOverflow: 'ellipsis', overflow: 'hidden' }, children: authSession?.email })] })] })), !isSkipAuthCheck && (0, jsx_runtime_1.jsx)(react_components_1.MenuDivider, { style: { marginInline: 0 } }), (0, jsx_runtime_1.jsxs)(react_components_1.MenuList, { style: { width: 200, marginBottom: 4 }, children: [accountMenuItems?.map((item) => {
100
101
  const Icon = item.icon;
101
102
  return ((0, jsx_runtime_1.jsx)(react_components_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(Icon, { size: "inherit" }), onClick: async () => {
103
+ setAccountMenuOpen(false);
102
104
  if (item.onClick) {
103
105
  item.onClick();
104
106
  }
@@ -1,5 +1,6 @@
1
- import { InternalRouteResolver, RouterInstance } from '@headless-adminapp/app/route/context';
1
+ import { InternalRouteResolver } from '@headless-adminapp/app/route/context';
2
2
  import { LookupAttribute } from '@headless-adminapp/core/attributes';
3
+ import { RouterInstance } from '@headless-adminapp/core/navigation';
3
4
  import { ISchemaStore } from '@headless-adminapp/core/store';
4
5
  import { UniqueRecord } from './types';
5
6
  export declare function useTableColumns({ disableSelection, disableContextMenu, disableColumnResize, disableColumnFilter, disableColumnSort, tableWrapperRef, }: {
@@ -134,7 +134,12 @@ function useTableColumns({ disableSelection, disableContextMenu, disableColumnRe
134
134
  maxSize: 32,
135
135
  }),
136
136
  ];
137
- }, [disableContextMenu, mutableContextCommandState, schema.idAttribute]);
137
+ }, [
138
+ disableContextMenu,
139
+ mutableContextCommandState,
140
+ schema.idAttribute,
141
+ setValue,
142
+ ]);
138
143
  const selectionColumns = (0, react_1.useMemo)(() => {
139
144
  if (disableSelection)
140
145
  return [];
@@ -410,8 +415,8 @@ function renderLookupAttribute({ value, schemaStore, routeResolver, router, attr
410
415
  type: app_1.PageType.EntityForm,
411
416
  id: value.id,
412
417
  });
413
- return ((0, jsx_runtime_1.jsx)(TableCellLink_1.TableCellLinkContent, { href: path, onClick: () => {
414
- router.push(path);
418
+ return ((0, jsx_runtime_1.jsx)(TableCellLink_1.TableCellLinkContent, { href: path, onClick: async () => {
419
+ await router.push(path);
415
420
  }, children: (0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [!!lookupSchema.avatarAttribute && ((0, jsx_runtime_1.jsx)(react_components_1.Avatar, { style: {
416
421
  width: 24,
417
422
  height: 24,
@@ -435,8 +440,8 @@ function renderRegardingAttribute({ value, schemaStore, routeResolver, router, f
435
440
  type: app_1.PageType.EntityForm,
436
441
  id: value.id,
437
442
  });
438
- return ((0, jsx_runtime_1.jsx)(TableCellLink_1.TableCellLinkContent, { href: path, onClick: () => {
439
- router.push(path);
443
+ return ((0, jsx_runtime_1.jsx)(TableCellLink_1.TableCellLinkContent, { href: path, onClick: async () => {
444
+ await router.push(path);
440
445
  }, children: (0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [!!lookupSchema.avatarAttribute && ((0, jsx_runtime_1.jsx)(react_components_1.Avatar, { style: {
441
446
  width: 24,
442
447
  height: 24,
@@ -1,7 +1,5 @@
1
- import { FormValidationStringSet } from '@headless-adminapp/app/form';
2
1
  import { PromptDialogOptions } from '@headless-adminapp/core/experience/dialog';
3
2
  import { SchemaAttributes } from '@headless-adminapp/core/schema';
4
- import * as yup from 'yup';
5
3
  interface PromptDialogProps<SA extends SchemaAttributes = SchemaAttributes> {
6
4
  open: boolean;
7
5
  title?: PromptDialogOptions<SA>['title'];
@@ -15,24 +13,4 @@ interface PromptDialogProps<SA extends SchemaAttributes = SchemaAttributes> {
15
13
  onDismiss?: PromptDialogOptions<SA>['onDismiss'];
16
14
  }
17
15
  export declare function PromptDialog(props: Readonly<PromptDialogProps>): import("react/jsx-runtime").JSX.Element;
18
- export declare const formValidator: (<A extends SchemaAttributes = SchemaAttributes>({ attributes, language, strings, region, }: {
19
- attributes: A;
20
- language: string;
21
- strings: FormValidationStringSet;
22
- region: string;
23
- }) => (values: Record<string, any>, context: any, options: any) => Promise<import("react-hook-form").ResolverResult<{
24
- [x: string]: any;
25
- [x: number]: any;
26
- [x: symbol]: any;
27
- }>>) & import("lodash").MemoizedFunction;
28
- export declare const generateValidationSchema: (<A extends SchemaAttributes = SchemaAttributes>({ attributes, language, strings, region, }: {
29
- attributes: A;
30
- language: string;
31
- strings: FormValidationStringSet;
32
- region: string;
33
- }) => yup.ObjectSchema<{
34
- [x: string]: any;
35
- }, yup.AnyObject, {
36
- [x: string]: any;
37
- }, "">) & import("lodash").MemoizedFunction;
38
16
  export {};
@@ -1,39 +1,12 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.generateValidationSchema = exports.formValidator = void 0;
27
3
  exports.PromptDialog = PromptDialog;
28
4
  const jsx_runtime_1 = require("react/jsx-runtime");
29
5
  const react_components_1 = require("@fluentui/react-components");
30
6
  const utils_1 = require("@headless-adminapp/app/dataform/utils");
31
7
  const form_1 = require("@headless-adminapp/app/form");
32
8
  const locale_1 = require("@headless-adminapp/app/locale");
33
- const yup_1 = require("@hookform/resolvers/yup");
34
- const lodash_1 = require("lodash");
35
9
  const react_hook_form_1 = require("react-hook-form");
36
- const yup = __importStar(require("yup"));
37
10
  const SectionControl_1 = require("../DataForm/SectionControl");
38
11
  const StandardControl_1 = require("../PageEntityForm/StandardControl");
39
12
  function PromptDialog(props) {
@@ -43,7 +16,7 @@ function PromptDialog(props) {
43
16
  mode: 'all',
44
17
  defaultValues: props.defaultValues,
45
18
  shouldUnregister: false,
46
- resolver: (0, exports.formValidator)({
19
+ resolver: (0, utils_1.attributesFormValidator)({
47
20
  attributes: props.attributes,
48
21
  language,
49
22
  strings: formValidationStrings,
@@ -75,29 +48,3 @@ function PromptDialog(props) {
75
48
  })();
76
49
  }, children: props.confirmText ?? 'Confirm' })] })] }) }) }));
77
50
  }
78
- exports.formValidator = (0, lodash_1.memoize)(function formValidator({ attributes, language, strings, region, }) {
79
- return async (values, context, options) => {
80
- const validator = (0, exports.generateValidationSchema)({
81
- attributes,
82
- language,
83
- strings,
84
- region,
85
- });
86
- const resolver = (0, yup_1.yupResolver)(validator);
87
- const result = await resolver(values, context, options);
88
- return result;
89
- };
90
- }, (options) => JSON.stringify(options));
91
- exports.generateValidationSchema = (0, lodash_1.memoize)(function generateValidationSchema({ attributes, language, strings, region, }) {
92
- const columns = Object.keys(attributes);
93
- return yup.object().shape({
94
- ...columns.reduce((acc, column) => {
95
- const attribute = attributes[column];
96
- const validationSchema = (0, utils_1.generateAttributeValidationSchema)(attribute, language, strings, region);
97
- return {
98
- ...acc,
99
- [column]: validationSchema,
100
- };
101
- }, {}),
102
- });
103
- }, (options) => JSON.stringify(options));
@@ -4,6 +4,7 @@ exports.EventFormBody = EventFormBody;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_components_1 = require("@fluentui/react-components");
6
6
  const baseEventAttributes_1 = require("@headless-adminapp/app/calendar/baseEventAttributes");
7
+ const dataform_1 = require("@headless-adminapp/app/dataform");
7
8
  const saveRecord_1 = require("@headless-adminapp/app/dataform/utils/saveRecord");
8
9
  const form_1 = require("@headless-adminapp/app/form");
9
10
  const locale_1 = require("@headless-adminapp/app/locale");
@@ -12,7 +13,6 @@ const react_1 = require("react");
12
13
  const react_hook_form_1 = require("react-hook-form");
13
14
  const BodyLoading_1 = require("../../components/BodyLoading");
14
15
  const EventFormContent_1 = require("./EventFormContent");
15
- const utils_1 = require("./utils");
16
16
  function EventFormBody(props) {
17
17
  const { language, region } = (0, locale_1.useLocale)();
18
18
  const formValidationStrings = (0, form_1.useFormValidationStrings)();
@@ -29,7 +29,7 @@ function EventFormBody(props) {
29
29
  mode: 'all',
30
30
  defaultValues: props.values,
31
31
  shouldUnregister: false,
32
- resolver: (0, utils_1.formValidator)({
32
+ resolver: (0, dataform_1.attributesFormValidator)({
33
33
  attributes: baseEventAttributes_1.baseEventAttributes,
34
34
  language,
35
35
  strings: formValidationStrings,
@@ -0,0 +1,7 @@
1
+ import { SectionQuickViewControl } from '@headless-adminapp/core/experience/form/SectionControl';
2
+ interface QuickViewControlProps {
3
+ labelPosition?: 'top' | 'left';
4
+ control: SectionQuickViewControl;
5
+ }
6
+ export declare function QuickViewControl({ control, labelPosition, }: Readonly<QuickViewControlProps>): import("react/jsx-runtime").JSX.Element | null;
7
+ export {};
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QuickViewControl = QuickViewControl;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_components_1 = require("@fluentui/react-components");
6
+ const dataform_1 = require("@headless-adminapp/app/dataform");
7
+ const hooks_1 = require("@headless-adminapp/app/hooks");
8
+ const metadata_1 = require("@headless-adminapp/app/metadata");
9
+ const transport_1 = require("@headless-adminapp/app/transport");
10
+ const react_query_1 = require("@tanstack/react-query");
11
+ const SectionControl_1 = require("../../DataForm/SectionControl");
12
+ const StandardControl_1 = require("../StandardControl");
13
+ function QuickViewControl({ control, labelPosition, }) {
14
+ const schema = (0, dataform_1.useDataFormSchema)();
15
+ const formInstance = (0, dataform_1.useFormInstance)();
16
+ const { schemaStore } = (0, metadata_1.useMetadata)();
17
+ const attribute = schema.attributes[control.attributeName];
18
+ if (!attribute) {
19
+ console.warn(`Attribute ${control.attributeName} not found in schema`);
20
+ return null;
21
+ }
22
+ if (attribute.type !== 'lookup') {
23
+ console.warn(`Attribute ${control.attributeName} is not a lookup field, skipping QuickViewControl.`);
24
+ return null;
25
+ }
26
+ const targetSchema = schemaStore.getSchema(attribute.entity);
27
+ const value = formInstance.watch(control.attributeName);
28
+ if (!value?.id) {
29
+ return null;
30
+ }
31
+ return ((0, jsx_runtime_1.jsx)(QuickViewControlInternal, { control: control, labelPosition: labelPosition, targetRecordId: value.id, targetSchema: targetSchema }));
32
+ }
33
+ function QuickViewControlInternal({ labelPosition, control, targetRecordId, targetSchema, }) {
34
+ const isMobile = (0, hooks_1.useIsMobile)();
35
+ const dataService = (0, transport_1.useDataService)();
36
+ const { data, isPending } = (0, react_query_1.useQuery)({
37
+ queryKey: [
38
+ 'data',
39
+ 'retriveRecord',
40
+ targetSchema.logicalName,
41
+ targetRecordId,
42
+ control.form.attributes,
43
+ ],
44
+ queryFn: async () => {
45
+ if (!targetRecordId) {
46
+ return null;
47
+ }
48
+ const record = await dataService.retriveRecord(targetSchema.logicalName, targetRecordId, control.form.attributes);
49
+ return record;
50
+ },
51
+ placeholderData: react_query_1.keepPreviousData,
52
+ staleTime: 1000 * 60 * 5, // 5 minutes
53
+ });
54
+ return ((0, jsx_runtime_1.jsx)("div", { style: {
55
+ display: 'flex',
56
+ flexDirection: 'column',
57
+ gap: react_components_1.tokens.spacingVerticalM,
58
+ }, children: control.form.attributes.map((attributeName) => {
59
+ const attribute = targetSchema.attributes[attributeName];
60
+ if (!attribute) {
61
+ return null;
62
+ }
63
+ return ((0, jsx_runtime_1.jsx)(SectionControl_1.SectionControlWrapper, { label: attribute.label, labelPosition: isMobile ? 'top' : labelPosition, children: (0, jsx_runtime_1.jsx)(StandardControl_1.StandardControl, { attribute: attribute, name: attributeName, value: data?.[attributeName] ?? null, onChange: () => {
64
+ // do nothing
65
+ }, readOnly: true, label: attribute.label, placeholder: attribute.label, allowNavigation: true, allowNewRecord: false, skeleton: isPending }) }, attributeName));
66
+ }) }));
67
+ }
@@ -19,6 +19,7 @@ const componentStore_1 = require("../componentStore");
19
19
  const SectionControl_1 = require("../DataForm/SectionControl");
20
20
  const layout_1 = require("../form/layout");
21
21
  const EditableGridControl_1 = require("./EditableGridControl/EditableGridControl");
22
+ const QuickViewControl_1 = require("./QuickViewControl");
22
23
  const StandardControl_1 = require("./StandardControl");
23
24
  const SubgridControl_1 = require("./SubgridControl");
24
25
  function SectionContainer({ section, skeleton, }) {
@@ -113,7 +114,7 @@ function SectionContainer({ section, skeleton, }) {
113
114
  return ((0, jsx_runtime_1.jsx)(EditableGridControl_1.EditableGridControl, { readOnly: disabled, control: control }));
114
115
  }
115
116
  case 'quickview':
116
- return null;
117
+ return ((0, jsx_runtime_1.jsx)(QuickViewControl_1.QuickViewControl, { control: control, labelPosition: section.labelPosition }));
117
118
  case 'subgrid': {
118
119
  let ContainerComponent = null;
119
120
  if (control.component) {
@@ -83,7 +83,7 @@ const StandardControl = (props) => {
83
83
  switch (attribute.format) {
84
84
  case 'text': {
85
85
  const Control = componentStore_1.componentStore.getComponent('Form.TextControl') ?? TextControl_1.TextControl;
86
- return ((0, jsx_runtime_1.jsx)(Control, { ...controlProps, textTransform: attribute.textTransform }));
86
+ return ((0, jsx_runtime_1.jsx)(Control, { ...controlProps, textTransform: attribute.textTransform, suggestions: attribute.suggestions }));
87
87
  }
88
88
  case 'email': {
89
89
  const Control = componentStore_1.componentStore.getComponent('Form.EmailControl') ?? EmailControl_1.EmailControl;
@@ -1,5 +1,18 @@
1
1
  import { InputProps } from '@fluentui/react-components';
2
+ import { SuggestionOptions } from '@headless-adminapp/core/attributes/StringAttribute';
3
+ import { FC } from 'react';
2
4
  import { ControlProps } from './types';
5
+ export declare function useSuggestions({ searchText, readOnly, }: {
6
+ searchText: string;
7
+ readOnly: boolean;
8
+ }): {
9
+ data: string[];
10
+ open: boolean;
11
+ setOpen: import("react").Dispatch<import("react").SetStateAction<boolean>>;
12
+ onData: (data: string[]) => void;
13
+ lookupEnabled: boolean;
14
+ debouncedSearchText: string;
15
+ };
3
16
  export interface TextControlProps extends ControlProps<string> {
4
17
  autoComplete?: string;
5
18
  autoCapitalize?: string;
@@ -7,5 +20,19 @@ export interface TextControlProps extends ControlProps<string> {
7
20
  textTransform?: 'capitalize' | 'uppercase' | 'lowercase' | 'none';
8
21
  appearance?: InputProps['appearance'];
9
22
  maxLength?: number;
23
+ suggestions?: SuggestionOptions;
10
24
  }
11
- export declare function TextControl({ value, onChange, id, name, onBlur, onFocus, placeholder, disabled, autoComplete, autoFocus, autoCapitalize, autoCorrect, textTransform, readOnly, appearance, maxLength, skeleton, }: Readonly<TextControlProps>): import("react/jsx-runtime").JSX.Element;
25
+ export declare function TextControl({ value, onChange, id, name, onBlur, onFocus, placeholder, disabled, autoComplete, autoFocus, autoCapitalize, autoCorrect, textTransform, readOnly, appearance, maxLength, skeleton, suggestions, }: Readonly<TextControlProps>): import("react/jsx-runtime").JSX.Element;
26
+ export declare const DynamicSuggestionLoader: FC<{
27
+ entity: string;
28
+ field: string;
29
+ searchText: string;
30
+ disabled?: boolean;
31
+ onData: (data: string[]) => void;
32
+ }>;
33
+ export declare const StaticSuggestionLoader: FC<{
34
+ values: string[];
35
+ searchText: string;
36
+ disabled?: boolean;
37
+ onData: (data: string[]) => void;
38
+ }>;
@@ -1,20 +1,44 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StaticSuggestionLoader = exports.DynamicSuggestionLoader = void 0;
4
+ exports.useSuggestions = useSuggestions;
3
5
  exports.TextControl = TextControl;
4
6
  const jsx_runtime_1 = require("react/jsx-runtime");
5
7
  const react_components_1 = require("@fluentui/react-components");
8
+ const hooks_1 = require("@headless-adminapp/app/hooks");
9
+ const metadata_1 = require("@headless-adminapp/app/metadata");
10
+ const useRetriveRecords_1 = require("@headless-adminapp/app/transport/hooks/useRetriveRecords");
11
+ const lodash_1 = require("lodash");
12
+ const react_1 = require("react");
6
13
  const SkeletonControl_1 = require("./SkeletonControl");
14
+ function useSuggestions({ searchText, readOnly, }) {
15
+ const [debouncedSearchText] = (0, hooks_1.useDebouncedValue)(searchText, 500);
16
+ const [data, setData] = (0, react_1.useState)([]);
17
+ const [open, setOpen] = (0, react_1.useState)(false);
18
+ const [lookupEnabled, setLookupEnabled] = (0, react_1.useState)(false);
19
+ const onData = (0, react_1.useCallback)((data) => {
20
+ setData(data);
21
+ }, []);
22
+ (0, react_1.useEffect)(() => {
23
+ if (open && !readOnly)
24
+ setLookupEnabled(true);
25
+ }, [open, readOnly]);
26
+ return { data, open, setOpen, onData, lookupEnabled, debouncedSearchText };
27
+ }
7
28
  function TextControl({ value, onChange, id, name, onBlur, onFocus,
8
29
  // error,
9
30
  placeholder, disabled, autoComplete, autoFocus, autoCapitalize, autoCorrect, textTransform,
10
31
  // borderOnFocusOnly,
11
- readOnly, appearance = 'filled-darker', maxLength, skeleton, }) {
32
+ readOnly, appearance = 'filled-darker', maxLength, skeleton, suggestions, }) {
12
33
  const readonly = disabled || readOnly;
34
+ const { data, open, setOpen, lookupEnabled, onData, debouncedSearchText } = useSuggestions({
35
+ searchText: value ?? '',
36
+ readOnly: !!readonly,
37
+ });
13
38
  if (skeleton) {
14
39
  return (0, jsx_runtime_1.jsx)(SkeletonControl_1.SkeletonControl, {});
15
40
  }
16
- const handleOnChange = (e) => {
17
- let value = e.target.value;
41
+ const handleOnChange = (value) => {
18
42
  if (textTransform === 'uppercase') {
19
43
  value = value.toUpperCase();
20
44
  }
@@ -23,7 +47,19 @@ readOnly, appearance = 'filled-darker', maxLength, skeleton, }) {
23
47
  }
24
48
  onChange?.(value);
25
49
  };
26
- return ((0, jsx_runtime_1.jsx)(react_components_1.Input, { placeholder: placeholder, id: id, name: name, autoFocus: autoFocus, appearance: appearance, value: value ?? '', onChange: handleOnChange, onBlur: () => onBlur?.(), onFocus: () => onFocus?.(),
50
+ if (suggestions) {
51
+ return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_components_1.Combobox, { autoCapitalize: "none", autoCorrect: "off", placeholder: placeholder, appearance: "filled-darker", spellCheck: false, autoComplete: "off", freeform: true, id: id, name: name, autoFocus: autoFocus, maxLength: maxLength, style: { width: '100%', minWidth: 'unset' }, input: { style: { width: '100%' } }, expandIcon: null, open: open && !!data.length && !readOnly, onOpenChange: (e, data) => {
52
+ if (!data.open) {
53
+ setOpen(data.open);
54
+ }
55
+ }, value: value ?? '', onChange: (e) => {
56
+ handleOnChange(e.target.value);
57
+ setOpen(true);
58
+ }, onBlur: () => onBlur?.(), onFocus: () => onFocus?.(), onOptionSelect: (e, item) => {
59
+ onChange?.(item.optionText ?? '');
60
+ }, children: data.map((item) => ((0, jsx_runtime_1.jsx)(react_components_1.Option, { value: item, checkIcon: null, children: item }, item))) }), suggestions?.type === 'static' && ((0, jsx_runtime_1.jsx)(exports.StaticSuggestionLoader, { values: suggestions.values, disabled: !lookupEnabled, onData: onData, searchText: debouncedSearchText })), suggestions?.type === 'dynamic' && ((0, jsx_runtime_1.jsx)(exports.DynamicSuggestionLoader, { entity: suggestions.entity, field: suggestions.field, disabled: !lookupEnabled, searchText: debouncedSearchText, onData: onData }))] }));
61
+ }
62
+ return ((0, jsx_runtime_1.jsx)(react_components_1.Input, { placeholder: placeholder, id: id, name: name, autoFocus: autoFocus, appearance: appearance, value: value ?? '', onChange: (e) => handleOnChange(e.target.value), onBlur: () => onBlur?.(), onFocus: () => onFocus?.(),
27
63
  // invalid={error}
28
64
  // readOnly={readOnly || disabled}
29
65
  readOnly: readonly, autoComplete: autoComplete, autoCorrect: autoCorrect, autoCapitalize: autoCapitalize, className: (0, react_components_1.mergeClasses)(readonly && 'TextControl_readonly'), style: {
@@ -34,3 +70,53 @@ readOnly, appearance = 'filled-darker', maxLength, skeleton, }) {
34
70
  },
35
71
  } }));
36
72
  }
73
+ const DynamicSuggestionLoader = ({ entity, field, searchText, disabled, onData }) => {
74
+ const { schemaStore } = (0, metadata_1.useMetadata)();
75
+ const schema = schemaStore.getSchema(entity);
76
+ const { data } = (0, useRetriveRecords_1.useRetriveRecords)({
77
+ schema,
78
+ columns: [field],
79
+ disabled: disabled || !searchText,
80
+ maxRecords: 5,
81
+ sorting: [{ field: field, order: 'asc' }],
82
+ filter: {
83
+ type: 'and',
84
+ conditions: [
85
+ {
86
+ field,
87
+ operator: 'like',
88
+ value: searchText,
89
+ },
90
+ ],
91
+ },
92
+ });
93
+ const onDataRef = (0, react_1.useRef)(onData);
94
+ onDataRef.current = onData;
95
+ (0, react_1.useEffect)(() => {
96
+ if (!searchText) {
97
+ onDataRef.current([]);
98
+ return;
99
+ }
100
+ if (data) {
101
+ onDataRef.current((0, lodash_1.uniq)(data.records.map((item) => item[field])));
102
+ }
103
+ }, [searchText, data, field]);
104
+ return null;
105
+ };
106
+ exports.DynamicSuggestionLoader = DynamicSuggestionLoader;
107
+ const StaticSuggestionLoader = ({ values, searchText, disabled, onData }) => {
108
+ const onDataRef = (0, react_1.useRef)(onData);
109
+ onDataRef.current = onData;
110
+ (0, react_1.useEffect)(() => {
111
+ if (!searchText || disabled) {
112
+ onDataRef.current([]);
113
+ return;
114
+ }
115
+ const filtered = values.filter((item) => item.toLowerCase().includes(searchText.toLowerCase()));
116
+ if (filtered.length) {
117
+ onDataRef.current((0, lodash_1.uniq)(filtered));
118
+ }
119
+ }, [searchText, disabled, values]);
120
+ return null;
121
+ };
122
+ exports.StaticSuggestionLoader = StaticSuggestionLoader;
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useFormForAttributes = useFormForAttributes;
4
+ const dataform_1 = require("@headless-adminapp/app/dataform");
4
5
  const form_1 = require("@headless-adminapp/app/form");
5
6
  const locale_1 = require("@headless-adminapp/app/locale");
6
7
  const react_hook_form_1 = require("react-hook-form");
7
- const PromptDialog_1 = require("../DialogContainer/PromptDialog");
8
8
  function useFormForAttributes(props) {
9
9
  const { language, region } = (0, locale_1.useLocale)();
10
10
  const formValidationStrings = (0, form_1.useFormValidationStrings)();
@@ -12,7 +12,7 @@ function useFormForAttributes(props) {
12
12
  mode: 'all',
13
13
  defaultValues: props.defaultValues,
14
14
  shouldUnregister: false,
15
- resolver: (0, PromptDialog_1.formValidator)({
15
+ resolver: (0, dataform_1.attributesFormValidator)({
16
16
  attributes: props.attributes,
17
17
  language,
18
18
  strings: formValidationStrings,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@headless-adminapp/fluent",
3
- "version": "1.4.23",
3
+ "version": "1.4.24",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -51,5 +51,8 @@
51
51
  "uuid": "11.0.3",
52
52
  "yup": "^1.4.0"
53
53
  },
54
- "gitHead": "1e2ade4328e5b2cfe223ab23318da6f456cb9de1"
54
+ "devDependencies": {
55
+ "@types/lodash": "4.17.20"
56
+ },
57
+ "gitHead": "3a4c06f1e18f8ac7861647b82d4a4f8cd8f0141c"
55
58
  }
@@ -1,23 +0,0 @@
1
- import { FormValidationStringSet } from '@headless-adminapp/app/form';
2
- import { SchemaAttributes } from '@headless-adminapp/core/schema';
3
- import * as yup from 'yup';
4
- export declare const formValidator: (<A extends SchemaAttributes = SchemaAttributes>({ attributes, language, strings, region, }: {
5
- attributes: A;
6
- language: string;
7
- strings: FormValidationStringSet;
8
- region: string;
9
- }) => (values: Record<string, any>, context: any, options: any) => Promise<import("react-hook-form").ResolverResult<{
10
- [x: string]: any;
11
- [x: number]: any;
12
- [x: symbol]: any;
13
- }>>) & import("lodash").MemoizedFunction;
14
- export declare const generateValidationSchema: (<A extends SchemaAttributes = SchemaAttributes>({ attributes, language, strings, region, }: {
15
- attributes: A;
16
- language: string;
17
- strings: FormValidationStringSet;
18
- region: string;
19
- }) => yup.ObjectSchema<{
20
- [x: string]: any;
21
- }, yup.AnyObject, {
22
- [x: string]: any;
23
- }, "">) & import("lodash").MemoizedFunction;
@@ -1,57 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.generateValidationSchema = exports.formValidator = void 0;
27
- const utils_1 = require("@headless-adminapp/app/dataform/utils");
28
- const yup_1 = require("@hookform/resolvers/yup");
29
- const lodash_1 = require("lodash");
30
- const yup = __importStar(require("yup"));
31
- // TODO: refactor duplicate code
32
- exports.formValidator = (0, lodash_1.memoize)(function formValidator({ attributes, language, strings, region, }) {
33
- return async (values, context, options) => {
34
- const validator = (0, exports.generateValidationSchema)({
35
- attributes,
36
- language,
37
- strings,
38
- region,
39
- });
40
- const resolver = (0, yup_1.yupResolver)(validator);
41
- const result = await resolver(values, context, options);
42
- return result;
43
- };
44
- }, (options) => JSON.stringify(options));
45
- exports.generateValidationSchema = (0, lodash_1.memoize)(function generateValidationSchema({ attributes, language, strings, region, }) {
46
- const columns = Object.keys(attributes);
47
- return yup.object().shape({
48
- ...columns.reduce((acc, column) => {
49
- const attribute = attributes[column];
50
- const validationSchema = (0, utils_1.generateAttributeValidationSchema)(attribute, language, strings, region);
51
- return {
52
- ...acc,
53
- [column]: validationSchema,
54
- };
55
- }, {}),
56
- });
57
- }, (options) => JSON.stringify(options));