nurseitaly-components 0.0.6 → 0.0.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.
@@ -16,7 +16,7 @@ export default function Avatar({ src, className, size = 'large', title, onClick,
16
16
  placeholder: usePlaceholder,
17
17
  });
18
18
  useEffect(() => {
19
- !src && setUsePlaceholder(true);
19
+ setUsePlaceholder(!src);
20
20
  }, [src]);
21
21
  return (_jsx("div", { className: getClassNames, children: usePlaceholder ? (_jsx(Icon, { name: "account_circle", size: size, filled: true, onClick: onClick })) : (_jsx("img", { src: src, onError: () => {
22
22
  setUsePlaceholder(true);
@@ -10,7 +10,6 @@ type Props<TFieldValues extends FieldValues = FieldValues, TContext = any, TTran
10
10
  onBlurFunctions?: Record<string, () => void>;
11
11
  runtimeOptions?: Record<string, any[]>;
12
12
  runtimeLoadOptions?: Record<string, (query: string) => Promise<SelectItem[]>>;
13
- twoColumns?: boolean;
14
13
  };
15
- export default function AppForm<TFieldValues extends FieldValues = FieldValues, TContext = any, TTransformedValues = TFieldValues>({ fields, form, prefix, onChangeFunctions, onBlurFunctions, runtimeOptions, runtimeLoadOptions, twoColumns, }: Props<TFieldValues, TContext, TTransformedValues>): import("react").JSX.Element;
14
+ export default function AppForm<TFieldValues extends FieldValues = FieldValues, TContext = any, TTransformedValues = TFieldValues>({ fields, form, prefix, onChangeFunctions, onBlurFunctions, runtimeOptions, runtimeLoadOptions, }: Props<TFieldValues, TContext, TTransformedValues>): import("react").JSX.Element;
16
15
  export {};
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { AsyncSelectField, CheckboxField, DatePickerField, SelectField, SelectMultipleField, SwitchField, TextField, } from '../../basic';
3
3
  import FormColorField from './FormColorField';
4
+ import { getFieldFlexStyle, groupFieldsIntoRows } from './groupFieldsIntoRows';
4
5
  import './style.scss';
5
6
  const convertList = (values, labelAttr, valueAttr) => {
6
7
  if (!values)
@@ -11,7 +12,7 @@ const convertList = (values, labelAttr, valueAttr) => {
11
12
  });
12
13
  return fields;
13
14
  };
14
- export default function AppForm({ fields, form, prefix, onChangeFunctions = {}, onBlurFunctions = {}, runtimeOptions = {}, runtimeLoadOptions = {}, twoColumns = false, }) {
15
+ export default function AppForm({ fields, form, prefix, onChangeFunctions = {}, onBlurFunctions = {}, runtimeOptions = {}, runtimeLoadOptions = {}, }) {
15
16
  const getOnChangeFn = (attr) => onChangeFunctions[attr];
16
17
  const getOnBlurFn = (attr) => onBlurFunctions[attr];
17
18
  const getOptions = (attr) => {
@@ -19,49 +20,50 @@ export default function AppForm({ fields, form, prefix, onChangeFunctions = {},
19
20
  return undefined;
20
21
  return convertList(runtimeOptions[attr], 'name', 'uid');
21
22
  };
22
- return (_jsx("div", { className: `app-form-container ${twoColumns ? 'two-columns' : ''}`, children: fields.map((field) => {
23
- const name = prefix ? `${prefix}.${field.attr}` : field.attr;
24
- const handleChange = getOnChangeFn(field.attr);
25
- if (field.type === 'autocomplete') {
26
- const loadOptions = runtimeLoadOptions[field.attr];
27
- if (!loadOptions)
28
- return null;
29
- return (_jsx(AsyncSelectField, { attr: name, label: field.name, createdForm: form, disabled: field.disabled, required: field.required, multiple: field.multiple, freeSolo: field.freeSolo, minQueryLength: field.minQueryLength, loadOptions: loadOptions, placeholder: field.title, noOptionsText: field.translation, onChange: (_attr, value) => handleChange?.(value) }, name));
30
- }
31
- if (field.type === 'select') {
32
- const selectOptions = getOptions(field.attr) || field.options || [];
33
- const selectProps = {
34
- attr: name,
35
- label: field.name,
36
- createdForm: form,
37
- options: selectOptions,
38
- disabled: field.disabled,
39
- required: field.required,
40
- onChange: (value) => handleChange?.(value),
41
- showEndAdornment: false,
42
- };
43
- if (field.multiple) {
44
- return _jsx(SelectMultipleField, { ...selectProps }, name);
45
- }
46
- return _jsx(SelectField, { ...selectProps }, name);
47
- }
48
- if (field.type === 'check') {
49
- return (_jsx(CheckboxField, { attr: name, label: field.name, createdForm: form, disabled: field.disabled }, name));
50
- }
51
- if (field.type === 'switch') {
52
- return (_jsx(SwitchField, { attr: name, label: field.name, createdForm: form, disabled: field.disabled, onChange: (value) => handleChange?.(value) }, name));
53
- }
54
- if (field.type === 'datepicker') {
55
- const handleBlur = getOnBlurFn(field.attr);
56
- return (_jsx(DatePickerField, { attr: name, label: field.size === 'small' ? undefined : field.name, createdForm: form, disabled: field.disabled, required: field.required, onChange: (_attr, value) => handleChange?.(value), onBlur: handleBlur, height: field.size === 'small' ? '32px' : undefined }, name));
57
- }
58
- if (field.type === 'textarea') {
59
- return (_jsx(TextField, { attr: name, label: field.name, createdForm: form, disabled: field.disabled, required: field.required, onChange: (value) => handleChange?.(value), multiline: true, rows: field.rows, height: "100%", infoText: field.infoText, defaultEndAdornments: field.infoText ? ['info'] : ['close'] }, name));
60
- }
61
- if (field.type === 'color') {
62
- return (_jsx(FormColorField, { attr: name, label: field.name, form: form, disabled: field.disabled, tooltipText: field.tooltipText, onChange: (value) => handleChange?.(value) }, name));
23
+ const renderField = (field) => {
24
+ const name = prefix ? `${prefix}.${field.attr}` : field.attr;
25
+ const handleChange = getOnChangeFn(field.attr);
26
+ if (field.type === 'autocomplete') {
27
+ const loadOptions = runtimeLoadOptions[field.attr];
28
+ if (!loadOptions)
29
+ return null;
30
+ return (_jsx(AsyncSelectField, { attr: name, label: field.name, createdForm: form, disabled: field.disabled, required: field.required, multiple: field.multiple, freeSolo: field.freeSolo, minQueryLength: field.minQueryLength, loadOptions: loadOptions, placeholder: field.title, noOptionsText: field.translation, onChange: (_attr, value) => handleChange?.(value) }, name));
31
+ }
32
+ if (field.type === 'select') {
33
+ const selectOptions = getOptions(field.attr) || field.options || [];
34
+ const selectProps = {
35
+ attr: name,
36
+ label: field.name,
37
+ createdForm: form,
38
+ options: selectOptions,
39
+ disabled: field.disabled,
40
+ required: field.required,
41
+ onChange: (value) => handleChange?.(value),
42
+ showEndAdornment: false,
43
+ };
44
+ if (field.multiple) {
45
+ return _jsx(SelectMultipleField, { ...selectProps }, name);
63
46
  }
47
+ return _jsx(SelectField, { ...selectProps }, name);
48
+ }
49
+ if (field.type === 'check') {
50
+ return (_jsx(CheckboxField, { attr: name, label: field.name, createdForm: form, disabled: field.disabled }, name));
51
+ }
52
+ if (field.type === 'switch') {
53
+ return (_jsx(SwitchField, { attr: name, label: field.name, createdForm: form, disabled: field.disabled, onChange: (value) => handleChange?.(value) }, name));
54
+ }
55
+ if (field.type === 'datepicker') {
64
56
  const handleBlur = getOnBlurFn(field.attr);
65
- return (_jsx(TextField, { attr: name, label: field.size === 'small' ? undefined : field.name, placeholder: field.size === 'small' ? field.name : undefined, createdForm: form, mask: field.mask, blurMask: field.blurMask, disabled: field.disabled, required: field.required, onChange: (value) => handleChange?.(value), height: field.size === 'small' ? '32px' : undefined, onBlur: handleBlur, infoText: field.infoText, defaultEndAdornments: field.infoText ? ['info'] : ['close'] }, name));
66
- }) }));
57
+ return (_jsx(DatePickerField, { attr: name, label: field.size === 'small' ? undefined : field.name, createdForm: form, disabled: field.disabled, required: field.required, onChange: (_attr, value) => handleChange?.(value), onBlur: handleBlur, height: field.size === 'small' ? '32px' : undefined }, name));
58
+ }
59
+ if (field.type === 'textarea') {
60
+ return (_jsx(TextField, { attr: name, label: field.name, createdForm: form, disabled: field.disabled, required: field.required, onChange: (value) => handleChange?.(value), multiline: true, rows: field.rows, height: "100%", infoText: field.infoText, defaultEndAdornments: field.infoText ? ['info'] : ['close'] }, name));
61
+ }
62
+ if (field.type === 'color') {
63
+ return (_jsx(FormColorField, { attr: name, label: field.name, form: form, disabled: field.disabled, tooltipText: field.tooltipText, onChange: (value) => handleChange?.(value) }, name));
64
+ }
65
+ const handleBlur = getOnBlurFn(field.attr);
66
+ return (_jsx(TextField, { attr: name, label: field.size === 'small' ? undefined : field.name, placeholder: field.size === 'small' ? field.name : undefined, createdForm: form, mask: field.mask, blurMask: field.blurMask, disabled: field.disabled, required: field.required, onChange: (value) => handleChange?.(value), height: field.size === 'small' ? '32px' : undefined, onBlur: handleBlur, infoText: field.infoText, defaultEndAdornments: field.infoText ? ['info'] : ['close'] }, name));
67
+ };
68
+ return (_jsx("div", { className: "app-form-container", children: groupFieldsIntoRows(fields).map((row, rowIdx) => (_jsx("div", { className: "app-form-row", children: row.map((field) => (_jsx("div", { className: "app-form-field", style: getFieldFlexStyle(field), children: renderField(field) }, field.attr))) }, rowIdx))) }));
67
69
  }
@@ -34,4 +34,10 @@ export type AppFormField = {
34
34
  display?: DisplayFunction;
35
35
  copyToClipboard?: boolean;
36
36
  truncate?: number;
37
+ /** Flex-grow weight when sharing a row with adjacent flex fields. Omit for full-width. */
38
+ flexGrow?: number;
39
+ /** Optional flex-basis (default: 0 for even ratio distribution). */
40
+ flexBasis?: number | string;
41
+ /** Force a new row before this field (even if it has flexGrow). */
42
+ breakBefore?: boolean;
37
43
  };
@@ -1,6 +1,7 @@
1
1
  import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useTranslation } from 'react-i18next';
3
3
  import { formatSwitchFieldValue } from './AppFormField';
4
+ import { getFieldFlexStyle, groupFieldsIntoRows } from './groupFieldsIntoRows';
4
5
  import './style.scss';
5
6
  import { Icon } from '../../basic';
6
7
  import UsabilityUtils from '../../functions/UsabilityUtils';
@@ -37,9 +38,7 @@ function getFieldDisplayContent(field, raw, t) {
37
38
  }
38
39
  export default function AppFormInfo({ fields, data }) {
39
40
  const { t } = useTranslation('common');
40
- return (_jsx("div", { className: "app-form-info-container", children: fields.map((field, idx) => {
41
- return (_jsxs("div", { className: "item", ...(field.title && { title: field.title }), children: [_jsxs("span", { className: "label", children: [field.name, ":"] }), _jsx("span", { className: "value", children: getFieldDisplayContent(field, data[field.attr], t) }), field.copyToClipboard && (_jsx(Icon, { name: "content_copy", size: "small", className: "ds-copy-icon", filled: true, onClick: () => {
42
- UsabilityUtils.copy(data[field.attr]);
43
- } }))] }, idx));
44
- }) }));
41
+ return (_jsx("div", { className: "app-form-info-container", children: groupFieldsIntoRows(fields).map((row, rowIdx) => (_jsx("div", { className: "app-form-row", children: row.map((field, idx) => (_jsx("div", { className: "app-form-field", style: getFieldFlexStyle(field), children: _jsxs("div", { className: "item", ...(field.title && { title: field.title }), children: [_jsxs("span", { className: "label", children: [field.name, ":"] }), _jsx("span", { className: "value", children: getFieldDisplayContent(field, data[field.attr], t) }), field.copyToClipboard && (_jsx(Icon, { name: "content_copy", size: "small", className: "ds-copy-icon", filled: true, onClick: () => {
42
+ UsabilityUtils.copy(data[field.attr]);
43
+ } }))] }) }, field.attr ?? idx))) }, rowIdx))) }));
45
44
  }
@@ -0,0 +1,4 @@
1
+ import { CSSProperties } from 'react';
2
+ import { AppFormField } from './AppFormField';
3
+ export declare function groupFieldsIntoRows(fields: AppFormField[]): AppFormField[][];
4
+ export declare function getFieldFlexStyle(field: AppFormField): CSSProperties | undefined;
@@ -0,0 +1,30 @@
1
+ export function groupFieldsIntoRows(fields) {
2
+ const rows = [];
3
+ let currentRow = [];
4
+ const flush = () => {
5
+ if (currentRow.length) {
6
+ rows.push(currentRow);
7
+ currentRow = [];
8
+ }
9
+ };
10
+ for (const field of fields) {
11
+ if (field.breakBefore)
12
+ flush();
13
+ if (field.flexGrow != null) {
14
+ currentRow.push(field);
15
+ }
16
+ else {
17
+ flush();
18
+ rows.push([field]);
19
+ }
20
+ }
21
+ flush();
22
+ return rows;
23
+ }
24
+ export function getFieldFlexStyle(field) {
25
+ if (field.flexGrow == null)
26
+ return undefined;
27
+ return {
28
+ flex: `${field.flexGrow} ${field.flexGrow} ${field.flexBasis ?? 0}`,
29
+ };
30
+ }
@@ -8,10 +8,6 @@
8
8
  align-items: center;
9
9
  gap: 4px;
10
10
 
11
- &.full-width {
12
- grid-column: 1 / -1;
13
- }
14
-
15
11
  .label {
16
12
  @include label-medium-2;
17
13
  color: var(--text-primary);
@@ -33,11 +29,26 @@
33
29
  display: flex;
34
30
  flex-direction: column;
35
31
  gap: 16px;
32
+ }
33
+
34
+ .app-form-row {
35
+ display: flex;
36
+ gap: 16px;
37
+ align-items: flex-start;
38
+ width: 100%;
39
+ }
40
+
41
+ .app-form-field {
42
+ min-width: 0;
43
+
44
+ &:only-child {
45
+ flex: 1 1 100%;
46
+ }
47
+ }
36
48
 
37
- &.two-columns {
38
- display: grid;
39
- grid-template-columns: repeat(2, 1fr);
40
- gap: 16px;
49
+ @media (max-width: 768px) {
50
+ .app-form-row {
51
+ flex-direction: column;
41
52
  }
42
53
  }
43
54
 
@@ -20,7 +20,7 @@ export default function AppToast() {
20
20
  return;
21
21
  dispatch(messageAction(EMPTY_TOAST));
22
22
  };
23
- const getLoading = () => (_jsxs("div", { className: "d-flex", children: [_jsx(ReactLoading, { type: "spinningBubbles", color: "blue", height: 24, width: 24 }), _jsx("span", { className: "ms-3", children: state.toastLoadingText ?? t('generic.loading') })] }));
23
+ const getLoading = () => (_jsxs("div", { className: "d-flex", children: [_jsx(ReactLoading, { type: "spinningBubbles", color: "blue", height: 24, width: 24 }), _jsx("span", { className: "ms-3", children: state.toastLoadingText ?? t('generic.loading', { defaultValue: 'Loading...' }) })] }));
24
24
  useEffect(() => {
25
25
  const closeOnEscape = (e) => {
26
26
  if (e.key === 'Escape')
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nurseitaly-components",
3
3
  "private": false,
4
- "version": "0.0.6",
4
+ "version": "0.0.7",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {