@headless-adminapp/fluent 1.1.3 → 1.1.6

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 (45) 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 +16 -2
  6. package/PageEntityForm/StandardControl.js +10 -0
  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/TimeControl.d.ts +4 -0
  18. package/form/controls/TimeControl.js +89 -0
  19. package/form/controls/useLookupData.d.ts +12 -2
  20. package/form/controls/useLookupData.js +71 -20
  21. package/package.json +2 -2
  22. package/App/NavigationContainer.d.ts +0 -10
  23. package/App/NavigationContainer.js +0 -68
  24. package/App/utils.d.ts +0 -14
  25. package/App/utils.js +0 -26
  26. package/Insights/CommandBarContainer.d.ts +0 -1
  27. package/Insights/CommandBarContainer.js +0 -18
  28. package/Insights/FilterBarContainer.d.ts +0 -1
  29. package/Insights/FilterBarContainer.js +0 -99
  30. package/Insights/hooks/useQueriesData.d.ts +0 -7
  31. package/Insights/hooks/useQueriesData.js +0 -89
  32. package/Insights/hooks/useWidgetDetail.d.ts +0 -10
  33. package/Insights/hooks/useWidgetDetail.js +0 -39
  34. package/PageCalendar/baseEventAttributes.d.ts +0 -35
  35. package/PageCalendar/baseEventAttributes.js +0 -38
  36. package/PageCalendar/context.d.ts +0 -20
  37. package/PageCalendar/context.js +0 -5
  38. package/PageCalendar/hooks/index.d.ts +0 -1
  39. package/PageCalendar/hooks/index.js +0 -17
  40. package/PageCalendar/hooks/useConfig.d.ts +0 -3
  41. package/PageCalendar/hooks/useConfig.js +0 -8
  42. package/PageInsights/PageInsights.d.ts +0 -7
  43. package/PageInsights/PageInsights.js +0 -31
  44. package/PageInsights/index.d.ts +0 -1
  45. 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;
@@ -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,12 +22,14 @@ 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");
28
29
  const TelephoneControl_1 = require("../form/controls/TelephoneControl");
29
30
  const TextAreaControl_1 = require("../form/controls/TextAreaControl");
30
31
  const TextControl_1 = require("../form/controls/TextControl");
32
+ const TimeControl_1 = require("../form/controls/TimeControl");
31
33
  const UrlControl_1 = require("../form/controls/UrlControl");
32
34
  // Standard Control (Base control)
33
35
  // TextControl
@@ -109,6 +111,10 @@ const StandardControl = (props) => {
109
111
  const Control = componentStore_1.componentStore.getComponent('Form.DurationControl') ?? DurationControl_1.DurationControl;
110
112
  return ((0, jsx_runtime_1.jsx)(Control, { name: name, placeholder: placeholder, value: value, onChange: onChange, onBlur: onBlur, error: isError, disabled: isDisabled, readOnly: readOnly }));
111
113
  }
114
+ case 'time': {
115
+ const Control = componentStore_1.componentStore.getComponent('Form.TimeControl') ?? TimeControl_1.TimeControl;
116
+ return ((0, jsx_runtime_1.jsx)(Control, { name: name, placeholder: placeholder, value: value, onChange: onChange, onBlur: onBlur, error: isError, disabled: isDisabled, readOnly: readOnly }));
117
+ }
112
118
  default: {
113
119
  return (0, jsx_runtime_1.jsx)(react_1.Fragment, {});
114
120
  }
@@ -161,6 +167,10 @@ const StandardControl = (props) => {
161
167
  const Control = componentStore_1.componentStore.getComponent('Form.MultiSelectLookupControl') ?? MultiSelectLookupControl_1.MultiSelectLookupControl;
162
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 }));
163
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
+ }
164
174
  case 'boolean': {
165
175
  const Control = componentStore_1.componentStore.getComponent('Form.SwitchControl') ?? SwitchControl_1.SwitchControl;
166
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 metadata_1 = require("@headless-adminapp/app/metadata");
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, metadata_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
  }
@@ -0,0 +1,4 @@
1
+ import { ControlProps } from './types';
2
+ export interface TimeControlProps extends ControlProps<number> {
3
+ }
4
+ export declare function TimeControl({ value, onChange, id, name, onBlur, placeholder, disabled, readOnly, }: Readonly<TimeControlProps>): import("react/jsx-runtime").JSX.Element;