@headless-adminapp/fluent 1.1.4 → 1.1.7

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.
Files changed (48) hide show
  1. package/DataGrid/TableCell/TableCellChoice.js +2 -30
  2. package/DataGrid/useTableColumns.js +41 -2
  3. package/PageEntityForm/PageEntityForm.js +8 -0
  4. package/PageEntityForm/SectionContainer.d.ts +2 -2
  5. package/PageEntityForm/SectionContainer.js +18 -4
  6. package/PageEntityForm/StandardControl.js +7 -2
  7. package/components/ChoiceBadge.d.ts +9 -0
  8. package/components/ChoiceBadge.js +29 -0
  9. package/components/LoginForm.d.ts +8 -0
  10. package/components/LoginForm.js +4 -4
  11. package/components/PageLogin.d.ts +5 -0
  12. package/components/PageLogin.js +2 -1
  13. package/form/controls/RegardingControl.d.ts +25 -0
  14. package/form/controls/RegardingControl.js +202 -0
  15. package/form/controls/SelectControl.d.ts +1 -1
  16. package/form/controls/SelectControl.js +1 -3
  17. package/form/controls/TextAreaControl.d.ts +3 -1
  18. package/form/controls/TextAreaControl.js +33 -8
  19. package/form/controls/useLookupData.d.ts +12 -2
  20. package/form/controls/useLookupData.js +71 -20
  21. package/form/layout/FormSection/FormSection.js +9 -2
  22. package/form/layout/FormTab/FormTab.js +1 -0
  23. package/form/layout/FormTab/FormTabColumn.js +1 -0
  24. package/package.json +2 -2
  25. package/App/NavigationContainer.d.ts +0 -10
  26. package/App/NavigationContainer.js +0 -68
  27. package/App/utils.d.ts +0 -14
  28. package/App/utils.js +0 -26
  29. package/Insights/CommandBarContainer.d.ts +0 -1
  30. package/Insights/CommandBarContainer.js +0 -18
  31. package/Insights/FilterBarContainer.d.ts +0 -1
  32. package/Insights/FilterBarContainer.js +0 -99
  33. package/Insights/hooks/useQueriesData.d.ts +0 -7
  34. package/Insights/hooks/useQueriesData.js +0 -89
  35. package/Insights/hooks/useWidgetDetail.d.ts +0 -10
  36. package/Insights/hooks/useWidgetDetail.js +0 -39
  37. package/PageCalendar/baseEventAttributes.d.ts +0 -35
  38. package/PageCalendar/baseEventAttributes.js +0 -38
  39. package/PageCalendar/context.d.ts +0 -20
  40. package/PageCalendar/context.js +0 -5
  41. package/PageCalendar/hooks/index.d.ts +0 -1
  42. package/PageCalendar/hooks/index.js +0 -17
  43. package/PageCalendar/hooks/useConfig.d.ts +0 -3
  44. package/PageCalendar/hooks/useConfig.js +0 -8
  45. package/PageInsights/PageInsights.d.ts +0 -7
  46. package/PageInsights/PageInsights.js +0 -31
  47. package/PageInsights/index.d.ts +0 -1
  48. package/PageInsights/index.js +0 -5
@@ -2,33 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TableCellChoice = TableCellChoice;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const react_components_1 = require("@fluentui/react-components");
6
- const color_1 = require("@headless-adminapp/app/utils/color");
7
- const react_1 = require("react");
5
+ const ChoiceBadge_1 = require("../../components/ChoiceBadge");
8
6
  const TableCellBase_1 = require("./TableCellBase");
9
7
  function TableCellChoice(props) {
10
- const bgColor = (0, react_1.useMemo)(() => {
11
- if (!props.value || !props.attribute.options) {
12
- return;
13
- }
14
- return props.attribute.options.find((option) => option.value === props.value)?.color;
15
- }, [props.attribute.options, props.value]);
16
- const color = (0, react_1.useMemo)(() => {
17
- if (!bgColor) {
18
- return;
19
- }
20
- return (0, color_1.isColorDark)(bgColor) ? '#FFFFFF' : '#000000';
21
- }, [bgColor]);
22
- if (!props.formattedValue) {
23
- return ((0, jsx_runtime_1.jsx)(TableCellBase_1.TableCellBase, { style: {
24
- textOverflow: 'ellipsis',
25
- overflow: 'hidden',
26
- whiteSpace: 'nowrap',
27
- width: props.width,
28
- minWidth: props.width,
29
- maxWidth: props.width,
30
- } }));
31
- }
32
8
  return ((0, jsx_runtime_1.jsx)(TableCellBase_1.TableCellBase, { style: {
33
9
  textOverflow: 'ellipsis',
34
10
  overflow: 'hidden',
@@ -36,9 +12,5 @@ function TableCellChoice(props) {
36
12
  width: props.width,
37
13
  minWidth: props.width,
38
14
  maxWidth: props.width,
39
- }, children: (0, jsx_runtime_1.jsx)(react_components_1.Badge, { style: {
40
- backgroundColor: bgColor ?? react_components_1.tokens.colorNeutralBackground3,
41
- color: color ?? react_components_1.tokens.colorNeutralForeground2,
42
- fontWeight: react_components_1.tokens.fontWeightRegular,
43
- }, children: props.formattedValue }) }));
15
+ }, children: (0, jsx_runtime_1.jsx)(ChoiceBadge_1.ChoiceBadge, { attribute: props.attribute, formattedValue: props.formattedValue, value: props.value }) }));
44
16
  }
@@ -320,6 +320,19 @@ function renderCellContent({ info, column, schema, schemaStore, locale, routeRes
320
320
  formattedValue,
321
321
  });
322
322
  }
323
+ case 'regarding': {
324
+ return renderRegardingAttribute({
325
+ info,
326
+ column,
327
+ schemaStore,
328
+ routeResolver,
329
+ recordSetSetter,
330
+ router,
331
+ value,
332
+ attribute,
333
+ formattedValue,
334
+ });
335
+ }
323
336
  case 'attachment': {
324
337
  const url = value?.url;
325
338
  if (!url) {
@@ -346,7 +359,7 @@ function renderCellContent({ info, column, schema, schemaStore, locale, routeRes
346
359
  }
347
360
  function renderPrimaryAttribute({ info, column, schema, routeResolver, openRecord, value, }) {
348
361
  const path = routeResolver({
349
- logicalName: schema.logicalName,
362
+ logicalName: info.row.original.$entity,
350
363
  type: app_1.PageType.EntityForm,
351
364
  id: info.row.original[schema.idAttribute],
352
365
  });
@@ -355,7 +368,7 @@ function renderPrimaryAttribute({ info, column, schema, routeResolver, openRecor
355
368
  schema,
356
369
  value,
357
370
  }), value] }), width: info.column.getSize(), href: path, onClick: () => {
358
- openRecord(info.row.original[schema.idAttribute]);
371
+ openRecord(info.row.original[schema.idAttribute], info.row.original.$entity);
359
372
  } }, column.id));
360
373
  }
361
374
  function renderPrimaryAttributeAvatar({ info, schema, value, }) {
@@ -396,3 +409,29 @@ function renderLookupAttribute({ value, info, column, schemaStore, routeResolver
396
409
  router.push(path);
397
410
  } }, column.id));
398
411
  }
412
+ function renderRegardingAttribute({ value, info, column, schemaStore, routeResolver, recordSetSetter, router, formattedValue, }) {
413
+ if (!value) {
414
+ return ((0, jsx_runtime_1.jsx)(TableCell_1.TableCellText, { value: "", width: info.column.getSize() }, column.id));
415
+ }
416
+ const hasSchema = schemaStore.hasSchema(value.logicalName);
417
+ if (!hasSchema) {
418
+ return ((0, jsx_runtime_1.jsx)(TableCell_1.TableCellText, { value: "", width: info.column.getSize() }, column.id));
419
+ }
420
+ const logicalName = value.logicalName;
421
+ const lookupSchema = schemaStore.getSchema(logicalName);
422
+ const path = routeResolver({
423
+ logicalName,
424
+ type: app_1.PageType.EntityForm,
425
+ id: value.id,
426
+ });
427
+ return ((0, jsx_runtime_1.jsx)(TableCellLink_1.TableCellLink, { value: (0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [!!lookupSchema.avatarAttribute && ((0, jsx_runtime_1.jsx)(react_components_1.Avatar, { style: {
428
+ width: 24,
429
+ height: 24,
430
+ fontSize: react_components_1.tokens.fontSizeBase100,
431
+ }, name: formattedValue, color: (0, avatar_1.getAvatarColor)(formattedValue), image: {
432
+ src: value.avatar,
433
+ } })), formattedValue] }), width: info.column.getSize(), href: path, onClick: () => {
434
+ recordSetSetter('', []);
435
+ router.push(path);
436
+ } }, column.id));
437
+ }
@@ -19,6 +19,14 @@ const PageEntityForm = ({ logicalName, formId, recordId, }) => {
19
19
  return ((0, jsx_runtime_1.jsx)(PageBroken_1.PageBroken, { Icon: icons_1.Icons.Error, title: result.title, message: result.message }));
20
20
  }
21
21
  const { schema, form, commands } = result;
22
+ if (!recordId) {
23
+ if (schema.virtual) {
24
+ return ((0, jsx_runtime_1.jsx)(PageBroken_1.PageBroken, { Icon: icons_1.Icons.Error, title: "Virtual Schema", message: "This schema is virtual and cannot be used in this context." }));
25
+ }
26
+ if (schema.restrictions?.disableCreate) {
27
+ return ((0, jsx_runtime_1.jsx)(PageBroken_1.PageBroken, { Icon: icons_1.Icons.Error, title: "Creating is disabled", message: "Creating records is disabled for this entity." }));
28
+ }
29
+ }
22
30
  return ((0, jsx_runtime_1.jsx)(PageEntityFormProvider_1.PageEntityFormProvider, { schema: schema, form: form, recordId: recordId, commands: commands, children: (0, jsx_runtime_1.jsxs)("div", { style: {
23
31
  display: 'flex',
24
32
  flex: 1,
@@ -1,6 +1,6 @@
1
1
  import { Section } from '@headless-adminapp/core/experience/form';
2
2
  import type { SchemaAttributes } from '@headless-adminapp/core/schema';
3
- export declare function SectionContainer<S extends SchemaAttributes = SchemaAttributes>({ section }: {
3
+ export declare function SectionContainer<S extends SchemaAttributes = SchemaAttributes>({ section }: Readonly<{
4
4
  section: Section<S>;
5
5
  readOnly: boolean;
6
- }): import("react/jsx-runtime").JSX.Element | null;
6
+ }>): import("react/jsx-runtime").JSX.Element | null;
@@ -39,7 +39,7 @@ function SectionContainer({ section }) {
39
39
  if (hiddenSections[section.name] || visibleControls.length === 0) {
40
40
  return null;
41
41
  }
42
- return ((0, jsx_runtime_1.jsx)(layout_1.FormSection, { title: (0, utils_2.localizedLabel)(language, section), columnCount: section.columnCount, labelPosition: section.labelPosition, noPadding: section.noPadding, hideLabel: section.hideLabel, children: visibleControls.map((control, index) => {
42
+ return ((0, jsx_runtime_1.jsx)(layout_1.FormSection, { title: (0, utils_2.localizedLabel)(language, section), columnCount: section.columnCount, labelPosition: section.labelPosition, noPadding: section.noPadding, hideLabel: section.hideLabel, fullHeight: section.fullHeight, children: visibleControls.map((control, index) => {
43
43
  switch (control.type) {
44
44
  case 'standard': {
45
45
  const attribute = schema.attributes[control.attributeName];
@@ -94,7 +94,7 @@ function SectionContainer({ section }) {
94
94
  recordId,
95
95
  attributeName: control.attributeName,
96
96
  logicalName: schema.logicalName,
97
- } }) }));
97
+ }, autoHeight: control.autoHeight, maxHeight: control.maxHeight }) }));
98
98
  } }, control.attributeName) }, control.attributeName));
99
99
  }
100
100
  case 'editablegrid': {
@@ -120,12 +120,26 @@ function SectionContainer({ section }) {
120
120
  refAttributeName: control.associatedAttribute,
121
121
  } }, index));
122
122
  }
123
+ case 'component': {
124
+ const Component = control.component === 'string'
125
+ ? componentStore_1.componentStore.getComponent(control.component)
126
+ : control.component;
127
+ if (!Component) {
128
+ console.warn(`Component ${control.component} not found for control ${control.key}`);
129
+ return null;
130
+ }
131
+ return ((0, jsx_runtime_1.jsx)("div", { style: {
132
+ gridColumn: control.span
133
+ ? `var(--section-item-span-${control.span ?? 1})`
134
+ : undefined,
135
+ display: 'flex',
136
+ }, children: (0, jsx_runtime_1.jsx)(Component, { ...control.componentProps }) }, index));
137
+ }
123
138
  case 'spacer':
124
139
  return ((0, jsx_runtime_1.jsx)("div", { style: {
125
140
  gridColumn: control.span
126
- ? `var(--section-item-span-${control.span})`
141
+ ? `var(--section-item-span-${control.span ?? 1})`
127
142
  : undefined,
128
- display: `var(--section-item-spacer-${control.span ?? 1})`,
129
143
  } }, index));
130
144
  default:
131
145
  return null;
@@ -22,6 +22,7 @@ const IntegerControl_1 = require("../form/controls/IntegerControl");
22
22
  const LookupControl_1 = require("../form/controls/LookupControl");
23
23
  const MultiSelectControl_1 = __importDefault(require("../form/controls/MultiSelectControl"));
24
24
  const MultiSelectLookupControl_1 = require("../form/controls/MultiSelectLookupControl");
25
+ const RegardingControl_1 = require("../form/controls/RegardingControl");
25
26
  const RichTextControl_1 = require("../form/controls/RichTextControl");
26
27
  const SelectControl_1 = __importDefault(require("../form/controls/SelectControl"));
27
28
  const SwitchControl_1 = require("../form/controls/SwitchControl");
@@ -43,7 +44,7 @@ const StandardControl = (props) => {
43
44
  // hideLabel,
44
45
  hidePlaceholder, readOnly,
45
46
  // quickViewControl,
46
- allowNavigation, allowNewRecord, } = props;
47
+ allowNavigation, allowNewRecord, autoHeight, maxHeight, } = props;
47
48
  const isDisabled = readOnly;
48
49
  // const label = hideLabel ? undefined : _label ?? attribute.label;
49
50
  const placeholder = hidePlaceholder
@@ -86,7 +87,7 @@ const StandardControl = (props) => {
86
87
  }
87
88
  case 'textarea': {
88
89
  const Control = componentStore_1.componentStore.getComponent('Form.TextAreaControl') ?? TextAreaControl_1.TextAreaControl;
89
- return (0, jsx_runtime_1.jsx)(Control, { ...controlProps });
90
+ return ((0, jsx_runtime_1.jsx)(Control, { ...controlProps, autoHeight: autoHeight, maxHeight: maxHeight }));
90
91
  }
91
92
  case 'richtext': {
92
93
  const Control = componentStore_1.componentStore.getComponent('Form.RichTextControl') ?? RichTextControl_1.RichTextControl;
@@ -166,6 +167,10 @@ const StandardControl = (props) => {
166
167
  const Control = componentStore_1.componentStore.getComponent('Form.MultiSelectLookupControl') ?? MultiSelectLookupControl_1.MultiSelectLookupControl;
167
168
  return ((0, jsx_runtime_1.jsx)(Control, { name: name, value: value, onChange: onChange, onBlur: onBlur, placeholder: placeholder, disabled: isDisabled, dataService: dataService, schema: schemaStore.getSchema(attribute.entity), experienceStore: experienceStore, allowNavigation: allowNavigation, allowNewRecord: allowNewRecord }));
168
169
  }
170
+ case 'regarding': {
171
+ const Control = componentStore_1.componentStore.getComponent('Form.RegardingControl') ?? RegardingControl_1.RegardingControl;
172
+ return ((0, jsx_runtime_1.jsx)(Control, { name: name, value: value, onChange: onChange, onBlur: onBlur, placeholder: placeholder, disabled: isDisabled, dataService: dataService, entities: attribute.entities, schemaStore: schemaStore, experienceStore: experienceStore, allowNavigation: allowNavigation, allowNewRecord: allowNewRecord }));
173
+ }
169
174
  case 'boolean': {
170
175
  const Control = componentStore_1.componentStore.getComponent('Form.SwitchControl') ?? SwitchControl_1.SwitchControl;
171
176
  return ((0, jsx_runtime_1.jsx)(Control, { name: name, value: value, onChange: onChange, onBlur: onBlur, error: isError, disabled: isDisabled, readOnly: readOnly }));
@@ -0,0 +1,9 @@
1
+ import { ChoiceAttribute } from '@headless-adminapp/core/attributes';
2
+ interface ChoiceBadgeProps {
3
+ value: unknown;
4
+ attribute: ChoiceAttribute<string | number>;
5
+ formattedValue: string | null;
6
+ size?: 'small' | 'medium';
7
+ }
8
+ export declare function ChoiceBadge(props: Readonly<ChoiceBadgeProps>): import("react/jsx-runtime").JSX.Element | null;
9
+ export {};
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChoiceBadge = ChoiceBadge;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_components_1 = require("@fluentui/react-components");
6
+ const color_1 = require("@headless-adminapp/app/utils/color");
7
+ const react_1 = require("react");
8
+ function ChoiceBadge(props) {
9
+ const bgColor = (0, react_1.useMemo)(() => {
10
+ if (!props.value || !props.attribute.options) {
11
+ return;
12
+ }
13
+ return props.attribute.options.find((option) => option.value === props.value)?.color;
14
+ }, [props.attribute.options, props.value]);
15
+ const color = (0, react_1.useMemo)(() => {
16
+ if (!bgColor) {
17
+ return;
18
+ }
19
+ return (0, color_1.isColorDark)(bgColor) ? '#FFFFFF' : '#000000';
20
+ }, [bgColor]);
21
+ if (!props.formattedValue) {
22
+ return null;
23
+ }
24
+ return ((0, jsx_runtime_1.jsx)(react_components_1.Badge, { style: {
25
+ backgroundColor: bgColor ?? react_components_1.tokens.colorNeutralBackground3,
26
+ color: color ?? react_components_1.tokens.colorNeutralForeground2,
27
+ fontWeight: react_components_1.tokens.fontWeightRegular,
28
+ }, size: props.size, children: props.formattedValue }));
29
+ }
@@ -1,6 +1,14 @@
1
+ export interface LoginFormData {
2
+ username: string;
3
+ password: string;
4
+ }
1
5
  interface LoginFormProps {
2
6
  logoImageUrl?: string;
3
7
  onLogin: (username: string, password: string) => Promise<void>;
8
+ beforeLoginContent?: React.ReactNode;
9
+ afterLoginContent?: React.ReactNode;
10
+ subtitle?: string;
11
+ defaultValues?: LoginFormData;
4
12
  }
5
13
  export declare function LoginForm(props: LoginFormProps): import("react/jsx-runtime").JSX.Element;
6
14
  export {};
@@ -44,7 +44,7 @@ const initialValues = {
44
44
  };
45
45
  function LoginForm(props) {
46
46
  const form = (0, react_hook_form_1.useForm)({
47
- defaultValues: initialValues,
47
+ defaultValues: props.defaultValues ?? initialValues,
48
48
  resolver: (0, yup_1.yupResolver)(validationSchema),
49
49
  });
50
50
  const handleOnSubmit = async (values) => {
@@ -72,14 +72,14 @@ function LoginForm(props) {
72
72
  width: 80,
73
73
  height: 80,
74
74
  aspectRatio: 'auto 80 / 80',
75
- }, alt: "logo" })) }), (0, jsx_runtime_1.jsx)(react_components_1.Subtitle1, { children: "Log in to your account" }), (0, jsx_runtime_1.jsxs)("div", { style: {
75
+ }, alt: "logo" })) }), (0, jsx_runtime_1.jsx)(react_components_1.Subtitle1, { children: "Log in to your account" }), props.subtitle && (0, jsx_runtime_1.jsx)(react_components_1.Body1, { children: props.subtitle }), (0, jsx_runtime_1.jsxs)("div", { style: {
76
76
  display: 'flex',
77
77
  flexDirection: 'column',
78
78
  alignItems: 'stretch',
79
79
  justifyContent: 'flex-start',
80
80
  gap: 16,
81
- }, children: [(0, jsx_runtime_1.jsx)(react_hook_form_1.Controller, { control: form.control, name: "username", render: ({ field, fieldState, formState }) => ((0, jsx_runtime_1.jsx)(SectionControl_1.SectionControlWrapper, { label: "Username", labelPosition: "top", required: true, isError: !!fieldState.error?.message && formState.isSubmitted, errorMessage: fieldState.error?.message, children: (0, jsx_runtime_1.jsx)(TextControl_1.TextControl, { placeholder: "Username", appearance: "outline", name: field.name, value: field.value, onChange: field.onChange, onBlur: field.onBlur, autoCapitalize: "none", autoCorrect: "off", error: !!fieldState.error?.message && formState.isSubmitted }) })) }), (0, jsx_runtime_1.jsx)(react_hook_form_1.Controller, { control: form.control, name: "password", render: ({ field, fieldState, formState }) => ((0, jsx_runtime_1.jsx)(SectionControl_1.SectionControlWrapper, { label: "Password", labelPosition: "top", required: true, isError: !!fieldState.error?.message && formState.isSubmitted, errorMessage: fieldState.error?.message, children: (0, jsx_runtime_1.jsx)(PasswordControl_1.PasswordControl, { placeholder: "Password", name: field.name, appearance: "outline", error: !!fieldState.error?.message && formState.isSubmitted, value: field.value, onChange: field.onChange, onBlur: field.onBlur }) })) }), !!form.formState.errors.root && ((0, jsx_runtime_1.jsx)(react_components_1.MessageBar, { intent: "error", children: (0, jsx_runtime_1.jsx)(react_components_1.MessageBarBody, { children: form.formState.errors.root.message }) })), (0, jsx_runtime_1.jsxs)(react_components_1.Button, { appearance: "primary", type: "submit", style: {
81
+ }, children: [(0, jsx_runtime_1.jsx)(react_hook_form_1.Controller, { control: form.control, name: "username", render: ({ field, fieldState, formState }) => ((0, jsx_runtime_1.jsx)(SectionControl_1.SectionControlWrapper, { label: "Username", labelPosition: "top", required: true, isError: !!fieldState.error?.message && formState.isSubmitted, errorMessage: fieldState.error?.message, children: (0, jsx_runtime_1.jsx)(TextControl_1.TextControl, { placeholder: "Username", appearance: "outline", name: field.name, value: field.value, onChange: field.onChange, onBlur: field.onBlur, autoCapitalize: "none", autoCorrect: "off", error: !!fieldState.error?.message && formState.isSubmitted }) })) }), (0, jsx_runtime_1.jsx)(react_hook_form_1.Controller, { control: form.control, name: "password", render: ({ field, fieldState, formState }) => ((0, jsx_runtime_1.jsx)(SectionControl_1.SectionControlWrapper, { label: "Password", labelPosition: "top", required: true, isError: !!fieldState.error?.message && formState.isSubmitted, errorMessage: fieldState.error?.message, children: (0, jsx_runtime_1.jsx)(PasswordControl_1.PasswordControl, { placeholder: "Password", name: field.name, appearance: "outline", error: !!fieldState.error?.message && formState.isSubmitted, value: field.value, onChange: field.onChange, onBlur: field.onBlur }) })) }), props.beforeLoginContent, !!form.formState.errors.root && ((0, jsx_runtime_1.jsx)(react_components_1.MessageBar, { intent: "error", children: (0, jsx_runtime_1.jsx)(react_components_1.MessageBarBody, { children: form.formState.errors.root.message }) })), (0, jsx_runtime_1.jsxs)(react_components_1.Button, { appearance: "primary", type: "submit", style: {
82
82
  marginTop: 8,
83
83
  pointerEvents: form.formState.isSubmitting ? 'none' : 'auto',
84
- }, children: [form.formState.isSubmitting && ((0, jsx_runtime_1.jsx)(react_components_1.Spinner, { size: "extra-tiny", appearance: "inverted", style: { marginRight: 4 } })), "Login"] })] }), (0, jsx_runtime_1.jsx)("div", { style: { height: 80 } })] }) }));
84
+ }, children: [form.formState.isSubmitting && ((0, jsx_runtime_1.jsx)(react_components_1.Spinner, { size: "extra-tiny", appearance: "inverted", style: { marginRight: 4 } })), "Login"] }), props.afterLoginContent] }), (0, jsx_runtime_1.jsx)("div", { style: { height: 80 } })] }) }));
85
85
  }
@@ -1,7 +1,12 @@
1
+ import { LoginFormData } from './LoginForm';
1
2
  interface LoginPageProps {
2
3
  logoImageUrl?: string;
3
4
  illustrationImageUrl?: string;
4
5
  onLogin: (username: string, password: string) => Promise<void>;
6
+ beforeLoginContent?: React.ReactNode;
7
+ afterLoginContent?: React.ReactNode;
8
+ subtitle?: string;
9
+ defaultValues?: LoginFormData;
5
10
  }
6
11
  export declare function PageLogin(props: LoginPageProps): import("react/jsx-runtime").JSX.Element;
7
12
  export {};
@@ -33,7 +33,8 @@ function PageLogin(props) {
33
33
  justifyContent: 'flex-start',
34
34
  gap: 16,
35
35
  minWidth: 300,
36
- }, children: (0, jsx_runtime_1.jsx)(LoginForm_1.LoginForm, { logoImageUrl: props.logoImageUrl, onLogin: props.onLogin }) }) }), (0, jsx_runtime_1.jsx)("div", { style: {
36
+ maxWidth: 300,
37
+ }, children: (0, jsx_runtime_1.jsx)(LoginForm_1.LoginForm, { logoImageUrl: props.logoImageUrl, onLogin: props.onLogin, defaultValues: props.defaultValues, beforeLoginContent: props.beforeLoginContent, afterLoginContent: props.afterLoginContent, subtitle: props.subtitle }) }) }), (0, jsx_runtime_1.jsx)("div", { style: {
37
38
  display: 'flex',
38
39
  flexDirection: 'column',
39
40
  gap: 16,
@@ -0,0 +1,25 @@
1
+ import { ISchemaExperienceStore, ISchemaStore } from '@headless-adminapp/core/store';
2
+ import { IDataService } from '@headless-adminapp/core/transport';
3
+ import { ControlProps } from './types';
4
+ export interface LookupOption {
5
+ limit: number;
6
+ search: string;
7
+ enabled?: boolean;
8
+ }
9
+ export type DataLookup = {
10
+ id: string;
11
+ name: string;
12
+ logicalName: string;
13
+ avatar?: string;
14
+ };
15
+ export type RegardingControlProps = ControlProps<DataLookup> & {
16
+ lookupKey?: string;
17
+ dataService: IDataService;
18
+ entities: string[];
19
+ schemaStore: ISchemaStore;
20
+ experienceStore: ISchemaExperienceStore;
21
+ viewId?: string;
22
+ allowNavigation?: boolean;
23
+ allowNewRecord?: boolean;
24
+ };
25
+ export declare function RegardingControl(props: RegardingControlProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RegardingControl = RegardingControl;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_components_1 = require("@fluentui/react-components");
6
+ const app_1 = require("@headless-adminapp/app/app");
7
+ const hooks_1 = require("@headless-adminapp/app/hooks");
8
+ const useMetadata_1 = require("@headless-adminapp/app/metadata/hooks/useMetadata");
9
+ const hooks_2 = require("@headless-adminapp/app/route/hooks");
10
+ const app_2 = require("@headless-adminapp/core/experience/app");
11
+ const icons_1 = require("@headless-adminapp/icons");
12
+ const react_query_1 = require("@tanstack/react-query");
13
+ const react_1 = require("react");
14
+ const AppStringContext_1 = require("../../App/AppStringContext");
15
+ const RecordCard_1 = require("../../PageEntityForm/RecordCard");
16
+ const avatar_1 = require("../../utils/avatar");
17
+ const useLookupData_1 = require("./useLookupData");
18
+ function RegardingControl(props) {
19
+ const Control = LookupControlMd;
20
+ return (0, jsx_runtime_1.jsx)(Control, { ...props });
21
+ }
22
+ const useStyles = (0, react_components_1.makeStyles)({
23
+ option: {
24
+ padding: 0,
25
+ '& .fui-Option__checkIcon': {
26
+ display: 'none',
27
+ },
28
+ '&[data-activedescendant-focusvisible]': {
29
+ background: react_components_1.tokens.colorNeutralBackground1Hover,
30
+ '&:after': {
31
+ border: 'none !important',
32
+ // background: tokens.colorNeutralBackground1Hover,
33
+ },
34
+ },
35
+ },
36
+ });
37
+ const LookupControlMd = ({ value, onChange, id, name, onBlur, onFocus, placeholder, disabled, autoFocus, readOnly, dataService, entities, schemaStore, allowNavigation, }) => {
38
+ const [lookupEnabled, setLookupEnabled] = (0, react_1.useState)(false);
39
+ const [open, setOpen] = (0, react_1.useState)(false);
40
+ const [searchText, setSearchText] = (0, react_1.useState)('');
41
+ const { loockupStrings } = (0, AppStringContext_1.useAppStrings)();
42
+ const routeResolver = (0, hooks_2.useRouteResolver)();
43
+ const router = (0, hooks_2.useRouter)();
44
+ const path = (0, react_1.useMemo)(() => {
45
+ if (!value) {
46
+ return '';
47
+ }
48
+ if (!allowNavigation) {
49
+ return '';
50
+ }
51
+ return routeResolver({
52
+ logicalName: value.logicalName,
53
+ type: app_2.PageType.EntityForm,
54
+ id: value.id,
55
+ });
56
+ }, [allowNavigation, routeResolver, value]);
57
+ const handleOpenRecord = (0, react_1.useCallback)((event) => {
58
+ event.preventDefault();
59
+ event.stopPropagation();
60
+ if (!path) {
61
+ return;
62
+ }
63
+ router.push(path);
64
+ }, [path, router]);
65
+ (0, react_1.useEffect)(() => {
66
+ if (open)
67
+ setLookupEnabled(true);
68
+ }, [open]);
69
+ const [debouncedSearchText] = (0, hooks_1.useDebouncedValue)(searchText, 500);
70
+ const styles = useStyles();
71
+ const { experienceStore } = (0, useMetadata_1.useMetadata)();
72
+ const { isFetching: isConfigFetching, data: configs } = (0, react_query_1.useQuery)({
73
+ queryKey: ['data', 'getLookupViews', entities, undefined],
74
+ queryFn: async () => {
75
+ return Promise.all(entities.map(async (name) => {
76
+ const schema = schemaStore.getSchema(name);
77
+ const view = await experienceStore.getViewLookupV2(name);
78
+ return {
79
+ schema,
80
+ view: view?.experience,
81
+ };
82
+ }));
83
+ },
84
+ throwOnError: true,
85
+ initialData: [],
86
+ });
87
+ const result = (0, useLookupData_1.useLookupDatas)({
88
+ dataService,
89
+ searchText: debouncedSearchText,
90
+ enabled: lookupEnabled && !isConfigFetching && !value && !readOnly && !disabled,
91
+ items: configs,
92
+ });
93
+ const isLoading = result.some((item) => item.isFetching);
94
+ (0, react_1.useEffect)(() => {
95
+ if (value) {
96
+ setSearchText(value.name);
97
+ }
98
+ else {
99
+ setSearchText('');
100
+ }
101
+ }, [value]);
102
+ const handleChange = (value) => {
103
+ setSearchText('');
104
+ if (!value) {
105
+ return onChange?.(null);
106
+ }
107
+ else {
108
+ const schema = schemaStore.getSchema(value.$entity);
109
+ return onChange?.({
110
+ id: value[schema.idAttribute],
111
+ name: value[schema.primaryAttribute],
112
+ logicalName: schema.logicalName,
113
+ });
114
+ }
115
+ };
116
+ const valueSchema = (0, react_1.useMemo)(() => {
117
+ if (!value) {
118
+ return null;
119
+ }
120
+ return schemaStore.getSchema(value?.logicalName);
121
+ }, [schemaStore, value]);
122
+ return ((0, jsx_runtime_1.jsxs)("div", { style: { position: 'relative', width: '100%' }, children: [(0, jsx_runtime_1.jsxs)(react_components_1.Combobox, { name: name, appearance: "filled-darker", expandIcon: readOnly || disabled ? null : isLoading ? ((0, jsx_runtime_1.jsx)(react_components_1.Spinner, { size: "extra-tiny" })) : ((0, jsx_runtime_1.jsx)(icons_1.Icons.Search, { size: 18 })), placeholder: !value ? placeholder : '', inputMode: "search", style: { width: '100%', minWidth: 'unset' }, autoComplete: "off", readOnly: readOnly || disabled,
123
+ // disabled={disabled}
124
+ open: open && !value && !readOnly && !disabled, value: !value ? searchText : '', onOpenChange: (e, data) => setOpen(data.open), onChange: (e) => {
125
+ setSearchText(e.target.value);
126
+ }, onOptionSelect: (e, item) => {
127
+ const _item = result
128
+ .map((group, index) => {
129
+ const schema = configs[index].schema;
130
+ if (!schema) {
131
+ return null;
132
+ }
133
+ const data = group.data;
134
+ const record = data?.records.find((x) => String(x[schema.idAttribute]) === String(item.optionValue));
135
+ return record;
136
+ })
137
+ .filter(Boolean)[0];
138
+ handleChange(_item ?? null);
139
+ }, disableAutoFocus: true, onBlur: onBlur, onFocus: onFocus, id: id, autoFocus: autoFocus, children: [result.map((group, index) => {
140
+ const schema = configs[index].schema;
141
+ const view = configs[index].view;
142
+ const data = group.data;
143
+ if (!data?.records.length) {
144
+ return null;
145
+ }
146
+ return ((0, jsx_runtime_1.jsx)(react_components_1.OptionGroup, { label: schema.label, children: data?.records.map((item) => {
147
+ return ((0, jsx_runtime_1.jsx)(react_components_1.Option, { value: item[schema.idAttribute], className: (0, react_components_1.mergeClasses)(styles.option), text: item[schema.primaryAttribute], children: view?.card ? ((0, jsx_runtime_1.jsx)(RecordCard_1.RecordCard, { cardView: view.card, record: item, schema: schema })) : item[schema.primaryAttribute] }, item[schema.idAttribute]));
148
+ }) }, schema.logicalName));
149
+ }), !isLoading &&
150
+ result.every((item) => !item.data?.records.length) && ((0, jsx_runtime_1.jsx)("div", { style: {
151
+ paddingInline: react_components_1.tokens.spacingHorizontalL,
152
+ paddingBlock: react_components_1.tokens.spacingVerticalS,
153
+ }, children: (0, jsx_runtime_1.jsx)(react_components_1.Body1, { children: loockupStrings.noRecordsFound }) }))] }), !!value && ((0, jsx_runtime_1.jsx)("div", { style: {
154
+ position: 'absolute',
155
+ inset: 0,
156
+ alignItems: 'center',
157
+ paddingInline: 4,
158
+ display: 'flex',
159
+ }, children: (0, jsx_runtime_1.jsx)(react_components_1.TagGroup, { as: "div", children: (0, jsx_runtime_1.jsx)(react_components_1.Tag, { as: "span", appearance: "brand", size: "small", dismissible: !disabled && !readOnly, value: value.id, style: {
160
+ paddingRight: !disabled && !readOnly ? 0 : 5,
161
+ background: react_components_1.tokens.colorNeutralBackground6,
162
+ }, dismissIcon: (0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', cursor: 'pointer' }, onClick: () => {
163
+ onChange?.(null);
164
+ }, children: (0, jsx_runtime_1.jsx)(icons_1.Icons.Close, { size: 16 }) }), primaryText: {
165
+ style: {
166
+ paddingBottom: 0,
167
+ },
168
+ }, children: allowNavigation && path ? ((0, jsx_runtime_1.jsxs)(react_components_1.Link, { href: path, onClick: handleOpenRecord, style: {
169
+ display: 'flex',
170
+ alignItems: 'center',
171
+ gap: react_components_1.tokens.spacingHorizontalXS,
172
+ }, children: [!!valueSchema && ((0, jsx_runtime_1.jsx)(LookupAvatar, { schema: valueSchema, logicalName: valueSchema.logicalName, value: value })), (0, jsx_runtime_1.jsx)(react_components_1.Body1, { style: {
173
+ overflow: 'hidden',
174
+ textOverflow: 'ellipsis',
175
+ whiteSpace: 'nowrap',
176
+ }, children: value?.name })] })) : ((0, jsx_runtime_1.jsx)(react_components_1.Body1, { style: { overflow: 'hidden', textOverflow: 'ellipsis' }, children: value?.name })) }) }) }))] }));
177
+ };
178
+ const LookupAvatar = ({ logicalName, schema, value, }) => {
179
+ const { schemaMetadataDic } = (0, app_1.useAppContext)();
180
+ if (!schema.avatarAttribute) {
181
+ const experienceSchema = schemaMetadataDic[logicalName];
182
+ const Icon = experienceSchema.Icon ?? icons_1.Icons.Entity ?? icons_1.IconPlaceholder;
183
+ return ((0, jsx_runtime_1.jsx)(react_components_1.Avatar, { style: {
184
+ width: 20,
185
+ height: 20,
186
+ }, icon: {
187
+ style: {
188
+ background: 'transparent',
189
+ color: 'inherit',
190
+ },
191
+ children: (0, jsx_runtime_1.jsx)(Icon, { size: 20 }),
192
+ } }));
193
+ }
194
+ return ((0, jsx_runtime_1.jsx)(react_components_1.Avatar, { style: {
195
+ width: 20,
196
+ height: 20,
197
+ fontSize: react_components_1.tokens.fontSizeBase100,
198
+ backgroundColor: 'transparent',
199
+ }, name: value?.name, color: (0, avatar_1.getAvatarColor)(value?.name), image: {
200
+ src: value?.avatar,
201
+ } }));
202
+ };
@@ -6,4 +6,4 @@ export interface Lookup<T = string> {
6
6
  export interface SelectControlProps<T> extends ControlProps<T> {
7
7
  options: Lookup<T>[];
8
8
  }
9
- export default function SelectControl<T extends string | number>({ value, onChange, options, id, name, disabled, onBlur, onFocus, placeholder, }: SelectControlProps<T>): import("react/jsx-runtime").JSX.Element;
9
+ export default function SelectControl<T extends string | number>({ value, onChange, options, id, name, disabled, onBlur, onFocus, placeholder, }: Readonly<SelectControlProps<T>>): import("react/jsx-runtime").JSX.Element;
@@ -22,7 +22,5 @@ function SelectControl({ value, onChange, options, id, name, disabled, onBlur, o
22
22
  // onChange={(e, v) => handleChange(v as string)}
23
23
  selectedOptions: value ? [String(value)] : [], onOptionSelect: (event, data) => {
24
24
  handleChange(data.optionValue);
25
- }, onBlur: () => onBlur?.(), onFocus: () => onFocus?.(),
26
- // error={error}
27
- disabled: disabled, children: transformedOptions.map((x) => ((0, jsx_runtime_1.jsx)(react_components_1.Option, { value: x.value, children: x.label }, x.value))) }));
25
+ }, onBlur: () => onBlur?.(), onFocus: () => onFocus?.(), style: { pointerEvents: disabled ? 'none' : undefined }, children: transformedOptions.map((x) => ((0, jsx_runtime_1.jsx)(react_components_1.Option, { value: x.value, children: x.label }, x.value))) }));
28
26
  }
@@ -2,5 +2,7 @@ import { ControlProps } from './types';
2
2
  export interface TextAreaControlProps extends ControlProps<string> {
3
3
  rows?: number;
4
4
  textTransform?: 'capitalize' | 'uppercase' | 'lowercase' | 'none';
5
+ autoHeight?: boolean;
6
+ maxHeight?: number;
5
7
  }
6
- export declare function TextAreaControl({ value, onChange, id, name, placeholder, onBlur, onFocus, disabled, readOnly, rows, textTransform, }: TextAreaControlProps): import("react/jsx-runtime").JSX.Element;
8
+ export declare function TextAreaControl({ value, onChange, id, name, placeholder, onBlur, onFocus, disabled, readOnly, rows, textTransform, autoHeight, maxHeight, }: TextAreaControlProps): import("react/jsx-runtime").JSX.Element;