@rio-cloud/rio-uikit 0.16.4-beta.23 → 0.16.4-beta.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.
Files changed (31) hide show
  1. package/components/autosuggest/AutoSuggest.d.ts +16 -0
  2. package/components/autosuggest/AutoSuggest.js +17 -4
  3. package/components/button/Button.js +3 -2
  4. package/components/datepicker/DatePicker.d.ts +4 -4
  5. package/components/datepicker/DatePicker.js +13 -7
  6. package/components/dialog/Dialog.d.ts +4 -4
  7. package/components/dialog/Dialog.js +6 -4
  8. package/components/dropdown/ButtonDropdown.js +2 -2
  9. package/components/dropdown/DropdownToggleButton.d.ts +2 -1
  10. package/components/dropdown/DropdownToggleButton.js +2 -2
  11. package/components/editableContent/EditableContent.d.ts +2 -0
  12. package/components/editableContent/EditableContent.js +6 -5
  13. package/components/menuItems/MenuItem.js +1 -3
  14. package/components/menuItems/MenuItems.js +2 -2
  15. package/lib/es/components/autosuggest/AutoSuggest.d.ts +16 -0
  16. package/lib/es/components/autosuggest/AutoSuggest.js +17 -4
  17. package/lib/es/components/button/Button.js +3 -2
  18. package/lib/es/components/datepicker/DatePicker.d.ts +4 -4
  19. package/lib/es/components/datepicker/DatePicker.js +13 -7
  20. package/lib/es/components/dialog/Dialog.d.ts +4 -4
  21. package/lib/es/components/dialog/Dialog.js +6 -4
  22. package/lib/es/components/dropdown/ButtonDropdown.js +2 -2
  23. package/lib/es/components/dropdown/DropdownToggleButton.d.ts +2 -1
  24. package/lib/es/components/dropdown/DropdownToggleButton.js +2 -2
  25. package/lib/es/components/editableContent/EditableContent.d.ts +2 -0
  26. package/lib/es/components/editableContent/EditableContent.js +6 -5
  27. package/lib/es/components/menuItems/MenuItem.js +1 -3
  28. package/lib/es/components/menuItems/MenuItems.js +2 -2
  29. package/lib/es/version.json +1 -1
  30. package/package.json +29 -29
  31. package/version.json +1 -1
@@ -1,7 +1,23 @@
1
1
  import React from 'react';
2
2
  export type AutoSuggestSuggestion = {
3
+ /**
4
+ * The text label for a suggestion item. If present, this will be returned when selecting the suggestion.
5
+ */
3
6
  label?: string;
7
+ /**
8
+ * Set to disable the suggestion and disallow selecting it.
9
+ *
10
+ * @default false
11
+ */
4
12
  disabled?: boolean;
13
+ /**
14
+ * Optional custom suggestion node that will be rendered as given. Example, this is used by the TagManager
15
+ * to render a placeholder with an icon next to it.
16
+ */
17
+ customSuggestion?: React.ReactNode;
18
+ /**
19
+ * Additional key-value pairs that are not relevant for rendering but may be handled on your side.
20
+ */
5
21
  [name: string]: string | React.ReactNode;
6
22
  };
7
23
  export type SelectedSuggestion = {
@@ -15,7 +15,7 @@ import AutoSuggestAddons from './AutoSuggestAddons';
15
15
  import DropdownSpinner from './DropdownSpinner';
16
16
  import NoItemMessage from './NoItemMessage';
17
17
  export const AutoSuggest = (props) => {
18
- const { id, onSuggestionSelected = noop, onSuggestionsFetchRequested = noop, onSuggestionHighlighted = noop, renderSuggestion = (suggestion) => suggestion.label, customSuggestionKey, getSuggestionValue = (suggestion) => { var _a; return (_a = suggestion.label) !== null && _a !== void 0 ? _a : suggestion === null || suggestion === void 0 ? void 0 : suggestion.customSuggestionKey; }, suggestions = [], autoDropDirection = true, pullRight = false, dropup = false, isLoading = false, openOnFocus = false, closeOnSelect = true, showSelectedItemsInInput = true, autoComplete = 'off', inputProps = {
18
+ const { id, onSuggestionSelected = noop, onSuggestionsFetchRequested = noop, onSuggestionHighlighted = noop, renderSuggestion, customSuggestionKey, getSuggestionValue, suggestions = [], autoDropDirection = true, pullRight = false, dropup = false, isLoading = false, openOnFocus = false, closeOnSelect = true, showSelectedItemsInInput = true, autoComplete = 'off', inputProps = {
19
19
  id,
20
20
  disabled: false,
21
21
  onChange: noop,
@@ -158,12 +158,18 @@ export const AutoSuggest = (props) => {
158
158
  inputProps.onClear(event);
159
159
  }
160
160
  };
161
+ const getDefaultSuggestionValue = (suggestion) => {
162
+ var _a, _b;
163
+ return (_b = (_a = suggestion.label) !== null && _a !== void 0 ? _a : suggestion[customSuggestionKey !== null && customSuggestionKey !== void 0 ? customSuggestionKey : '']) !== null && _b !== void 0 ? _b : '';
164
+ };
161
165
  const onSuggestionClicked = (event, suggestion) => {
162
- updateInputValue(getSuggestionValue(suggestion), event, closeOnSelect);
166
+ const getSuggestionValueFunction = getSuggestionValue ? getSuggestionValue : getDefaultSuggestionValue;
167
+ const suggestionValue = getSuggestionValueFunction(suggestion);
168
+ updateInputValue(suggestionValue, event, closeOnSelect);
163
169
  // fire callback with the selected item
164
170
  onSuggestionSelected(event, {
165
171
  suggestion,
166
- suggestionValue: getSuggestionValue(suggestion),
172
+ suggestionValue,
167
173
  });
168
174
  };
169
175
  const onMouseEnter = (event) => {
@@ -182,6 +188,7 @@ export const AutoSuggest = (props) => {
182
188
  }
183
189
  return input;
184
190
  };
191
+ const renderDefaultSuggestion = (suggestion) => suggestion.label;
185
192
  const renderDropdownMenu = () => {
186
193
  const dropdownMenuClasses = classNames('dropdown-menu', dropDirection.pullRight && 'pull-right', dropdownClassName);
187
194
  if (isLoading) {
@@ -193,11 +200,17 @@ export const AutoSuggest = (props) => {
193
200
  }
194
201
  return (_jsxs("ul", Object.assign({ role: 'menu', className: dropdownMenuClasses, ref: dropdownMenuRef }, { children: [hasNoSuggestions && noItemMessage && _jsx(NoItemMessage, { message: noItemMessage }, 'NoItemMessage'), suggestions.map((suggestion, index) => {
195
202
  var _a;
203
+ // In case a custom renderer is used but the customSuggestionKey is not set, throw an error
204
+ if (renderSuggestion && !suggestion.label && !customSuggestionKey) {
205
+ throw new Error('The "customSuggestionKey" need to be set when using a custom renderer ' +
206
+ 'and not using the "label" prop for suggestions');
207
+ }
196
208
  const key = `index-${(_a = suggestion.label) !== null && _a !== void 0 ? _a : suggestion[customSuggestionKey !== null && customSuggestionKey !== void 0 ? customSuggestionKey : '']}`;
197
209
  if (suggestion.header && suggestion.label) {
198
210
  return _jsx(DropdownHeader, { label: suggestion.label }, key);
199
211
  }
200
- return (_jsx(MenuItem, { active: index === highlightedItemIndex, disabled: suggestion.disabled, value: suggestion.customSuggestion ? suggestion.customSuggestion : renderSuggestion(suggestion), onSelect: (_, event) => onSuggestionClicked(event, suggestion), index: index, onMouseEnter: onMouseEnter }, key));
212
+ const renderFunction = renderSuggestion ? renderSuggestion : renderDefaultSuggestion;
213
+ return (_jsx(MenuItem, { active: index === highlightedItemIndex, disabled: suggestion.disabled, value: suggestion.customSuggestion ? suggestion.customSuggestion : renderFunction(suggestion), onSelect: (_, event) => onSuggestionClicked(event, suggestion), index: index, onMouseEnter: onMouseEnter }, key));
201
214
  })] })));
202
215
  };
203
216
  const classes = classNames('AutoSuggest', 'dropdown', isOpen && 'open', dropDirection.dropup && 'dropup', className);
@@ -5,7 +5,6 @@ import classNames from 'classnames';
5
5
  import noop from 'lodash/fp/noop';
6
6
  import { createButtonRipple } from '../../utils/buttonEffect';
7
7
  import useMergeRefs from '../../hooks/useMergeRefs';
8
- import usePrevious from '../../hooks/usePrevious';
9
8
  export const STYLES_MAP = {
10
9
  DEFAULT: 'default',
11
10
  PRIMARY: 'primary',
@@ -34,9 +33,11 @@ const Button = React.forwardRef((props, ref) => {
34
33
  const btnRef = useRef(null);
35
34
  const buttonRef = useMergeRefs(btnRef, ref);
36
35
  // Update internal toggle state when used as controlled component and outside toggle state changes
37
- const previousActive = usePrevious(active);
36
+ // Note, using the usePrevious hook resulted in an endless loop, hence the useState here
37
+ const [previousActive, setPreviousActive] = useState(active);
38
38
  if (active !== previousActive) {
39
39
  setIsToggled(active);
40
+ setPreviousActive(active);
40
41
  }
41
42
  const handleClick = (event) => {
42
43
  var _a;
@@ -66,7 +66,7 @@ export type DatePickerProps = Omit<DatetimepickerProps, 'onChange' | 'initialVal
66
66
  * @param isValid
67
67
  * @returns
68
68
  */
69
- onChange?: (value: Moment, isValid: boolean) => void;
69
+ onChange?: (value: Moment | string, isValid: boolean) => void;
70
70
  /**
71
71
  * Defines whether the input shows an error when the date is invalid or cleared.
72
72
  *
@@ -79,7 +79,7 @@ export type DatePickerProps = Omit<DatetimepickerProps, 'onChange' | 'initialVal
79
79
  * @param date
80
80
  * @returns
81
81
  */
82
- dateValidation?: (date: Moment) => boolean;
82
+ dateValidation?: (date: Moment | string) => boolean;
83
83
  /**
84
84
  * Additional classes to be set on the DatePicker element.
85
85
  */
@@ -150,7 +150,7 @@ declare const DatePicker: React.ForwardRefExoticComponent<Omit<Datetime.Datetime
150
150
  * @param isValid
151
151
  * @returns
152
152
  */
153
- onChange?: ((value: Moment, isValid: boolean) => void) | undefined;
153
+ onChange?: ((value: Moment | string, isValid: boolean) => void) | undefined;
154
154
  /**
155
155
  * Defines whether the input shows an error when the date is invalid or cleared.
156
156
  *
@@ -163,7 +163,7 @@ declare const DatePicker: React.ForwardRefExoticComponent<Omit<Datetime.Datetime
163
163
  * @param date
164
164
  * @returns
165
165
  */
166
- dateValidation?: ((date: Moment) => boolean) | undefined;
166
+ dateValidation?: ((date: Moment | string) => boolean) | undefined;
167
167
  /**
168
168
  * Additional classes to be set on the DatePicker element.
169
169
  */
@@ -2,28 +2,34 @@ import { __rest } from "tslib";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useState, forwardRef } from 'react';
4
4
  import classNames from 'classnames';
5
- import noop from 'lodash/fp/noop';
6
5
  import moment from 'moment';
7
6
  import Datetime from 'react-datetime';
7
+ import noop from 'lodash/fp/noop';
8
+ import isEmpty from 'lodash/fp/isEmpty';
8
9
  const DEFAULT_LOCALE = 'en-GB';
9
10
  const DEFAULT_MIN_WIDTH = 0;
10
- const isValidDate = (date) => typeof date === 'object';
11
+ const isValidDate = (date) => typeof date === 'object' && moment(date).isValid();
11
12
  const DatePicker = forwardRef((props, ref) => {
12
13
  const { id, dropup = false, alignRight = false, locale = DEFAULT_LOCALE, minWidth = DEFAULT_MIN_WIDTH, onChange = noop, mandatory = true, dateValidation, clearableInput = false, closeOnSelect = true, inputProps, className } = props, remainingProp = __rest(props, ["id", "dropup", "alignRight", "locale", "minWidth", "onChange", "mandatory", "dateValidation", "clearableInput", "closeOnSelect", "inputProps", "className"]);
13
14
  const [hasError, setHasError] = useState(false);
14
15
  const validateDate = (dateToValidate) => {
15
- return dateValidation ? dateValidation(dateToValidate) : isValidDate(dateToValidate);
16
+ if (dateValidation) {
17
+ return dateValidation(dateToValidate);
18
+ }
19
+ // if the date is mandatory, convert it to a moment object to validate
20
+ const value = isEmpty(dateToValidate) ? undefined : dateToValidate;
21
+ const dateValue = typeof value === 'string' ? moment(value) : value;
22
+ return isValidDate(dateValue);
16
23
  };
17
24
  const handleChange = (date) => {
18
- const dateValue = typeof date === 'string' ? moment(date) : date;
19
- const isValid = mandatory ? validateDate(dateValue) : true;
25
+ const isValid = mandatory ? validateDate(date) : true;
20
26
  setHasError(!isValid);
21
- onChange(dateValue, isValid);
27
+ onChange(date, isValid);
22
28
  };
23
29
  const classes = classNames('DatePicker', 'form-group', hasError && 'has-error', dropup && 'dropup', alignRight && 'align-right', className && className);
24
30
  // This way we can expose the "id" as top level prop and not as part of the inputProps which
25
31
  // makes the use of the id much more convenient
26
- const enhancedInputProps = Object.assign(Object.assign({}, inputProps), { id });
32
+ const enhancedInputProps = Object.assign({ id }, inputProps);
27
33
  return (_jsx(Datetime
28
34
  // TODO: add support for setting ref to the input. Maybe add a "inputRef" prop to react-datetime
29
35
  // ref={ref}
@@ -1,5 +1,5 @@
1
1
  import React, { PropsWithChildren } from 'react';
2
- export type bsSizeDialog = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full' | 'fullwidth' | 'fullheight' | 'fullscreen';
2
+ export type DialogSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full' | 'fullwidth' | 'fullheight' | 'fullscreen';
3
3
  export type BaseDialogProps = {
4
4
  /**
5
5
  * Opens the dialog when set to `true`.
@@ -22,7 +22,7 @@ export type BaseDialogProps = {
22
22
  /**
23
23
  * A callback function invoked when the dialog closes.
24
24
  */
25
- onClose?: Function;
25
+ onClose?: () => void;
26
26
  /**
27
27
  * Defined how large the dialog will be rendered.
28
28
  * By default, the dialog has a medium size and thus it can be omitted.
@@ -30,7 +30,7 @@ export type BaseDialogProps = {
30
30
  * Possible values are: `xs`, `sm`, `lg` `xl` `fullwidth` `fullheight` `fullscreen`
31
31
  * @default 'md'
32
32
  */
33
- bsSize?: bsSizeDialog;
33
+ bsSize?: DialogSize;
34
34
  /**
35
35
  * Enables or disabled closing the dialog via esc key.
36
36
  * @default false
@@ -55,7 +55,7 @@ export type DialogProps = BaseDialogProps & {
55
55
  /**
56
56
  * The dialog body content.
57
57
  */
58
- body: React.ReactNode;
58
+ body?: React.ReactNode;
59
59
  /**
60
60
  * The dialog body content.
61
61
  */
@@ -8,7 +8,7 @@ import noop from 'lodash/fp/noop';
8
8
  import { AnimatePresence, motion } from 'framer-motion';
9
9
  import { getOrCreatePortalRoot } from '../../utils/portalRoot';
10
10
  import useEsc from '../../hooks/useEsc';
11
- import useAfterMount from '../../hooks/useAfterMount';
11
+ import '../../hooks/useAfterMount';
12
12
  import DialogHeader from './DialogHeader';
13
13
  import DialogBody from './DialogBody';
14
14
  import DialogFooter from './DialogFooter';
@@ -46,10 +46,12 @@ const Dialog = (props) => {
46
46
  usedEscapeKey && onEsc();
47
47
  }
48
48
  };
49
- useAfterMount(() => {
49
+ const [previousShow, setPreviousShow] = useState(show);
50
+ if (show !== previousShow) {
50
51
  setOpen(show);
51
52
  toggleBodyClass(show);
52
- }, [show]);
53
+ setPreviousShow(show);
54
+ }
53
55
  useEsc(() => {
54
56
  if (!dialogWrapperRef || !dialogWrapperRef.current) {
55
57
  return;
@@ -83,7 +85,7 @@ const Dialog = (props) => {
83
85
  const modalClasses = classNames('modal', 'show', className);
84
86
  const isSmallestDialog = bsSize === 'xs';
85
87
  const hasChildren = !!children;
86
- const modalDialogClasses = classNames(MODAL_DIALOG_CLASS, useOverflow && 'modal-overflow', bsSize === 'xs' && 'modal-xs', bsSize === 'sm' && 'modal-sm', bsSize === 'lg' && 'modal-lg', bsSize === 'lg' && 'modal-xl', bsSize === 'full' && 'modal-full-width', bsSize === 'fullwidth' && 'modal-full-width', bsSize === 'fullheight' && 'modal-full-height', bsSize === 'fullscreen' && 'modal-fullscreen');
88
+ const modalDialogClasses = classNames(MODAL_DIALOG_CLASS, useOverflow && 'modal-overflow', bsSize === 'xs' && 'modal-xs', bsSize === 'sm' && 'modal-sm', bsSize === 'lg' && 'modal-lg', bsSize === 'xl' && 'modal-xl', bsSize === 'full' && 'modal-full-width', bsSize === 'fullwidth' && 'modal-full-width', bsSize === 'fullheight' && 'modal-full-height', bsSize === 'fullscreen' && 'modal-fullscreen');
87
89
  const spring = {
88
90
  type: 'spring',
89
91
  damping: 33,
@@ -26,7 +26,7 @@ const getPlacement = (pullRight, dropup) => {
26
26
  return 'bottom-start';
27
27
  };
28
28
  const ButtonDropdown = (props) => {
29
- const { id = Math.random().toString(36).substr(2, 16), items = [], bsSize = 'md', bsStyle = 'default', disabled = false, iconOnly = false, title, splitButton = false, customDropdown, open, dropup = false, pullRight = false, noCaret = false, onOpen = noop, onClose = noop, onLabelButtonClick = noop, usePortal = false, popperConfig, toggleClassName = '', dropdownClassName, className = '' } = props, remainingProps = __rest(props, ["id", "items", "bsSize", "bsStyle", "disabled", "iconOnly", "title", "splitButton", "customDropdown", "open", "dropup", "pullRight", "noCaret", "onOpen", "onClose", "onLabelButtonClick", "usePortal", "popperConfig", "toggleClassName", "dropdownClassName", "className"]);
29
+ const { id = Math.random().toString(36).substr(2, 16), items = [], bsSize = 'md', bsStyle = 'default', variant, disabled = false, iconOnly = false, title, splitButton = false, customDropdown, open, dropup = false, pullRight = false, noCaret = false, onOpen = noop, onClose = noop, onLabelButtonClick = noop, usePortal = false, popperConfig, toggleClassName = '', dropdownClassName, className = '' } = props, remainingProps = __rest(props, ["id", "items", "bsSize", "bsStyle", "variant", "disabled", "iconOnly", "title", "splitButton", "customDropdown", "open", "dropup", "pullRight", "noCaret", "onOpen", "onClose", "onLabelButtonClick", "usePortal", "popperConfig", "toggleClassName", "dropdownClassName", "className"]);
30
30
  const [internalOpen, setInternalOpen] = useState(open);
31
31
  const [refDropdownToggle, setRefDropdownToggle] = useState(null);
32
32
  const [refDropdownMenu, setRefDropdownMenu] = useState(null);
@@ -76,6 +76,6 @@ const ButtonDropdown = (props) => {
76
76
  const wrapperClasses = classNames('dropdown', 'btn-group', isOpen && 'open', className);
77
77
  const dropdownClasses = classNames(usePortal && 'dropdown-portal', splitButton && pullRight && 'pull-right', dropdownClassName);
78
78
  const dropdownMenu = (_jsx(MenuItemList, Object.assign({ className: dropdownClasses, ref: setRefDropdownMenu, style: styles.popper }, attributes.popper, { children: customDropdown ? customDropdown : _jsx(MenuItems, { items: items, closeMenu: toggleOpen }) })));
79
- return (_jsxs("div", Object.assign({}, remainingProps, { className: wrapperClasses, ref: wrapperRef }, { children: [_jsx(DropdownToggleButton, Object.assign({ id: id, splitButton: splitButton, bsStyle: bsStyle, bsSize: bsSize, iconOnly: iconOnly, disabled: disabled, ref: setRefDropdownToggle, onClick: handleDropdownButtonClick, className: toggleClassName }, { children: _jsxs(_Fragment, { children: [title, shouldShowCaret && _jsx(Caret, {})] }) })), splitButton && (_jsx(SplitCaretButton, { id: id, bsStyle: bsStyle, bsSize: bsSize, disabled: disabled, className: toggleClassName, onClick: toggleOpen, ref: setRefSplitButtonToggle })), isOpen && usePortal && ReactDOM.createPortal(dropdownMenu, dropdownRoot), isOpen && !usePortal && dropdownMenu] })));
79
+ return (_jsxs("div", Object.assign({}, remainingProps, { className: wrapperClasses, ref: wrapperRef }, { children: [_jsx(DropdownToggleButton, Object.assign({ id: id, splitButton: splitButton, bsStyle: bsStyle, bsSize: bsSize, variant: variant, iconOnly: iconOnly, disabled: disabled, ref: setRefDropdownToggle, onClick: handleDropdownButtonClick, className: toggleClassName }, { children: _jsxs(_Fragment, { children: [title, shouldShowCaret && _jsx(Caret, {})] }) })), splitButton && (_jsx(SplitCaretButton, { id: id, bsStyle: bsStyle, bsSize: bsSize, disabled: disabled, className: toggleClassName, onClick: toggleOpen, ref: setRefSplitButtonToggle })), isOpen && usePortal && ReactDOM.createPortal(dropdownMenu, dropdownRoot), isOpen && !usePortal && dropdownMenu] })));
80
80
  };
81
81
  export default ButtonDropdown;
@@ -1,5 +1,5 @@
1
1
  import React, { type HTMLProps } from 'react';
2
- import { type BUTTON_SIZE, type BUTTON_STYLE } from '../button/Button';
2
+ import { type BUTTON_VARIANT, type BUTTON_SIZE, type BUTTON_STYLE } from '../button/Button';
3
3
  export type DropdownToggleButtonProps = HTMLProps<HTMLButtonElement> & {
4
4
  id?: string;
5
5
  disabled?: boolean;
@@ -8,6 +8,7 @@ export type DropdownToggleButtonProps = HTMLProps<HTMLButtonElement> & {
8
8
  onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
9
9
  bsSize: BUTTON_SIZE;
10
10
  bsStyle: BUTTON_STYLE;
11
+ variant?: BUTTON_VARIANT;
11
12
  className?: string;
12
13
  };
13
14
  declare const DropdownToggleButton: React.ForwardRefExoticComponent<Omit<React.PropsWithChildren<DropdownToggleButtonProps>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
@@ -4,8 +4,8 @@ import { forwardRef } from 'react';
4
4
  import classNames from 'classnames';
5
5
  import Button from '../button/Button';
6
6
  const DropdownToggleButton = forwardRef((props, ref) => {
7
- const { id, disabled, bsSize, bsStyle, splitButton = false, onClick, className = '', children } = props, remainingProps = __rest(props, ["id", "disabled", "bsSize", "bsStyle", "splitButton", "onClick", "className", "children"]);
7
+ const { id, disabled, bsSize, bsStyle, variant, splitButton = false, onClick, className = '', children } = props, remainingProps = __rest(props, ["id", "disabled", "bsSize", "bsStyle", "variant", "splitButton", "onClick", "className", "children"]);
8
8
  const labelButtonClasses = classNames(!splitButton && 'dropdown-toggle', !splitButton && className);
9
- return (_jsx(Button, Object.assign({}, remainingProps, { id: splitButton ? `button-${id}` : id, type: 'button', ref: ref, disabled: disabled, bsStyle: bsStyle, bsSize: bsSize, onClick: onClick, className: labelButtonClasses }, { children: children })));
9
+ return (_jsx(Button, Object.assign({}, remainingProps, { id: splitButton ? `button-${id}` : id, type: 'button', ref: ref, disabled: disabled, bsStyle: bsStyle, bsSize: bsSize, variant: variant, onClick: onClick, className: labelButtonClasses }, { children: children })));
10
10
  });
11
11
  export default DropdownToggleButton;
@@ -66,6 +66,8 @@ export type EditableContentProps = {
66
66
  allowResize?: boolean;
67
67
  /**
68
68
  * Defines the number of rows to use by the internal textarea component.
69
+ * When a single line is used, the input is saved on "enter" key.
70
+ *
69
71
  * @default 1
70
72
  */
71
73
  inputRows?: number;
@@ -60,9 +60,9 @@ const EditableContent = (props) => {
60
60
  };
61
61
  const { styles, attributes } = usePopper(referenceElement, popperElement, popperConfig);
62
62
  const handleEditMode = () => {
63
- var _a;
63
+ var _a, _b;
64
64
  setIsEditMode(true);
65
- setInputValue((_a = referenceElement === null || referenceElement === void 0 ? void 0 : referenceElement.textContent) !== null && _a !== void 0 ? _a : '');
65
+ setInputValue((_b = (_a = referenceElement === null || referenceElement === void 0 ? void 0 : referenceElement.textContent) === null || _a === void 0 ? void 0 : _a.trimEnd()) !== null && _b !== void 0 ? _b : '');
66
66
  onEditMode();
67
67
  };
68
68
  const handleInputChange = (event) => {
@@ -72,6 +72,8 @@ const EditableContent = (props) => {
72
72
  // Prevent line breaks when textarea is a single line
73
73
  if (event.key === 'Enter' && inputRows === DEFAULT_TEXTAREA_ROWS) {
74
74
  event.preventDefault();
75
+ // Save on "enter" when textarea has a single line
76
+ handleSaveChanges();
75
77
  }
76
78
  };
77
79
  const handleCloseEditMode = () => {
@@ -83,7 +85,7 @@ const EditableContent = (props) => {
83
85
  setHasError(!isInputValid);
84
86
  if (isInputValid) {
85
87
  setIsEditMode(false);
86
- onSave(inputValue);
88
+ onSave(inputValue.trimEnd());
87
89
  }
88
90
  };
89
91
  // Control edit mode from outside for instance if text element got focus
@@ -103,8 +105,7 @@ const EditableContent = (props) => {
103
105
  minWidth: '100px',
104
106
  resize: allowResize ? 'vertical' : 'none',
105
107
  };
106
- // &nbsp handling if coming from outside -> check textarea for empty string and nbsp
107
108
  return (_jsxs(_Fragment, { children: [_jsx("span", Object.assign({ ref: setReferenceElement, onClick: handleEditMode, className: textWrapperClasses }, { children: children })), isEditMode &&
108
- createPortal(_jsxs("div", Object.assign({ className: overlayWrapperClasses, onClick: event => event.stopPropagation(), ref: setPopperElement, style: styles.popper }, attributes.popper, remainingProps, { children: [_jsxs("div", Object.assign({ className: inputWrapperClasses }, { children: [hasCustomControl && customEditor, !hasCustomControl && (_jsx("textarea", { ref: inputRef, className: inputClasses, value: inputValue, onChange: handleInputChange, onFocus: onFocus, onBlur: onBlur, onKeyDown: handleKeyDown, style: inputStyle, rows: inputRows })), hasError && _jsx("div", Object.assign({ className: 'help-block position-relative' }, { children: errorMessage }))] })), _jsxs("div", Object.assign({ className: 'display-flex gap-5' }, { children: [_jsx("button", Object.assign({ type: 'button', onClick: handleCloseEditMode, className: `EditableContentCancel btn btn-default btn-icon-only btn-${size}` }, { children: _jsx("span", { className: 'rioglyph rioglyph-remove' }) })), _jsx("button", Object.assign({ type: 'button', onClick: handleSaveChanges, className: `EditableContentSave btn btn-primary btn-icon-only btn-${size}` }, { children: _jsx("span", { className: 'rioglyph rioglyph-ok' }) }))] }))] })), getOrCreatePortalRoot())] }));
109
+ createPortal(_jsxs("div", Object.assign({ className: overlayWrapperClasses, onClick: event => event.stopPropagation(), ref: setPopperElement, style: styles.popper }, attributes.popper, remainingProps, { children: [_jsxs("div", Object.assign({ className: inputWrapperClasses }, { children: [hasCustomControl && customEditor, !hasCustomControl && (_jsx("textarea", { ref: inputRef, className: inputClasses, value: inputValue, onChange: handleInputChange, onFocus: onFocus, onBlur: onBlur, onKeyDown: handleKeyDown, style: inputStyle, rows: inputRows })), hasError && _jsx("div", Object.assign({ className: 'help-block position-relative' }, { children: errorMessage }))] })), _jsxs("div", Object.assign({ className: 'display-flex gap-5' }, { children: [_jsx("button", Object.assign({ type: 'button', onClick: handleCloseEditMode, className: `EditableContentCancel btn btn-default btn-icon-only btn-${size}`, "aria-label": 'EditableContent cancel button', "data-testid": 'EditableContentCancel' }, { children: _jsx("span", { className: 'rioglyph rioglyph-remove' }) })), _jsx("button", Object.assign({ type: 'button', onClick: handleSaveChanges, className: `EditableContentSave btn btn-primary btn-icon-only btn-${size}`, "aria-label": 'EditableContent save button', "data-testid": 'EditableContentSave' }, { children: _jsx("span", { className: 'rioglyph rioglyph-ok' }) }))] }))] })), getOrCreatePortalRoot())] }));
109
110
  };
110
111
  export default EditableContent;
@@ -12,8 +12,6 @@ const MenuItem = (props) => {
12
12
  }
13
13
  const role = divider ? 'separator' : 'presentation';
14
14
  const classes = classNames(divider && 'divider pointer-events-none', disabled && 'disabled', active && 'active');
15
- // biome-ignore lint/a11y/useValidAnchor: <explanation>
16
- const menuLink = _jsx("a", Object.assign({ role: 'menuitem' }, { children: value }));
17
15
  const handleSelectItem = (event) => {
18
16
  if (!disabled) {
19
17
  onSelect(index, event);
@@ -30,6 +28,6 @@ const MenuItem = (props) => {
30
28
  if (header) {
31
29
  return _jsx(DropdownHeader, { label: value, center: false });
32
30
  }
33
- return (_jsx("li", Object.assign({ role: role, className: classes, onClick: handleSelectItem, onMouseEnter: handleItemMouseEnter, "data-item-index": index }, { children: header ? value : menuLink })));
31
+ return (_jsx("li", Object.assign({ role: role, className: classes, onClick: handleSelectItem, onMouseEnter: handleItemMouseEnter, "data-item-index": index }, { children: _jsx("a", Object.assign({ role: 'menuitem' }, { children: value })) })));
34
32
  };
35
33
  export default MenuItem;
@@ -4,8 +4,8 @@ import noop from 'lodash/fp/noop';
4
4
  import MenuItemComponent from './MenuItem';
5
5
  const MenuItems = ({ items, closeMenu = noop, onMouseEnter = noop }) => {
6
6
  return (_jsx(_Fragment, { children: items.map((item, index) => {
7
- var _a;
8
- return (_jsx(MenuItemComponent, Object.assign({}, item, { index: index, closeMenu: closeMenu, onMouseEnter: onMouseEnter }), (_a = item.index) !== null && _a !== void 0 ? _a : index));
7
+ var _a, _b;
8
+ return (_jsx(MenuItemComponent, Object.assign({}, item, { index: (_a = item.index) !== null && _a !== void 0 ? _a : index, closeMenu: closeMenu, onMouseEnter: onMouseEnter }), (_b = item.index) !== null && _b !== void 0 ? _b : index));
9
9
  }) }));
10
10
  };
11
11
  export default MenuItems;
@@ -1,7 +1,23 @@
1
1
  import React from 'react';
2
2
  export type AutoSuggestSuggestion = {
3
+ /**
4
+ * The text label for a suggestion item. If present, this will be returned when selecting the suggestion.
5
+ */
3
6
  label?: string;
7
+ /**
8
+ * Set to disable the suggestion and disallow selecting it.
9
+ *
10
+ * @default false
11
+ */
4
12
  disabled?: boolean;
13
+ /**
14
+ * Optional custom suggestion node that will be rendered as given. Example, this is used by the TagManager
15
+ * to render a placeholder with an icon next to it.
16
+ */
17
+ customSuggestion?: React.ReactNode;
18
+ /**
19
+ * Additional key-value pairs that are not relevant for rendering but may be handled on your side.
20
+ */
5
21
  [name: string]: string | React.ReactNode;
6
22
  };
7
23
  export type SelectedSuggestion = {
@@ -18,7 +18,7 @@ const AutoSuggestAddons_1 = tslib_1.__importDefault(require("./AutoSuggestAddons
18
18
  const DropdownSpinner_1 = tslib_1.__importDefault(require("./DropdownSpinner"));
19
19
  const NoItemMessage_1 = tslib_1.__importDefault(require("./NoItemMessage"));
20
20
  const AutoSuggest = (props) => {
21
- const { id, onSuggestionSelected = noop_1.default, onSuggestionsFetchRequested = noop_1.default, onSuggestionHighlighted = noop_1.default, renderSuggestion = (suggestion) => suggestion.label, customSuggestionKey, getSuggestionValue = (suggestion) => { var _a; return (_a = suggestion.label) !== null && _a !== void 0 ? _a : suggestion === null || suggestion === void 0 ? void 0 : suggestion.customSuggestionKey; }, suggestions = [], autoDropDirection = true, pullRight = false, dropup = false, isLoading = false, openOnFocus = false, closeOnSelect = true, showSelectedItemsInInput = true, autoComplete = 'off', inputProps = {
21
+ const { id, onSuggestionSelected = noop_1.default, onSuggestionsFetchRequested = noop_1.default, onSuggestionHighlighted = noop_1.default, renderSuggestion, customSuggestionKey, getSuggestionValue, suggestions = [], autoDropDirection = true, pullRight = false, dropup = false, isLoading = false, openOnFocus = false, closeOnSelect = true, showSelectedItemsInInput = true, autoComplete = 'off', inputProps = {
22
22
  id,
23
23
  disabled: false,
24
24
  onChange: noop_1.default,
@@ -161,12 +161,18 @@ const AutoSuggest = (props) => {
161
161
  inputProps.onClear(event);
162
162
  }
163
163
  };
164
+ const getDefaultSuggestionValue = (suggestion) => {
165
+ var _a, _b;
166
+ return (_b = (_a = suggestion.label) !== null && _a !== void 0 ? _a : suggestion[customSuggestionKey !== null && customSuggestionKey !== void 0 ? customSuggestionKey : '']) !== null && _b !== void 0 ? _b : '';
167
+ };
164
168
  const onSuggestionClicked = (event, suggestion) => {
165
- updateInputValue(getSuggestionValue(suggestion), event, closeOnSelect);
169
+ const getSuggestionValueFunction = getSuggestionValue ? getSuggestionValue : getDefaultSuggestionValue;
170
+ const suggestionValue = getSuggestionValueFunction(suggestion);
171
+ updateInputValue(suggestionValue, event, closeOnSelect);
166
172
  // fire callback with the selected item
167
173
  onSuggestionSelected(event, {
168
174
  suggestion,
169
- suggestionValue: getSuggestionValue(suggestion),
175
+ suggestionValue,
170
176
  });
171
177
  };
172
178
  const onMouseEnter = (event) => {
@@ -185,6 +191,7 @@ const AutoSuggest = (props) => {
185
191
  }
186
192
  return input;
187
193
  };
194
+ const renderDefaultSuggestion = (suggestion) => suggestion.label;
188
195
  const renderDropdownMenu = () => {
189
196
  const dropdownMenuClasses = (0, classnames_1.default)('dropdown-menu', dropDirection.pullRight && 'pull-right', dropdownClassName);
190
197
  if (isLoading) {
@@ -196,11 +203,17 @@ const AutoSuggest = (props) => {
196
203
  }
197
204
  return ((0, jsx_runtime_1.jsxs)("ul", Object.assign({ role: 'menu', className: dropdownMenuClasses, ref: dropdownMenuRef }, { children: [hasNoSuggestions && noItemMessage && (0, jsx_runtime_1.jsx)(NoItemMessage_1.default, { message: noItemMessage }, 'NoItemMessage'), suggestions.map((suggestion, index) => {
198
205
  var _a;
206
+ // In case a custom renderer is used but the customSuggestionKey is not set, throw an error
207
+ if (renderSuggestion && !suggestion.label && !customSuggestionKey) {
208
+ throw new Error('The "customSuggestionKey" need to be set when using a custom renderer ' +
209
+ 'and not using the "label" prop for suggestions');
210
+ }
199
211
  const key = `index-${(_a = suggestion.label) !== null && _a !== void 0 ? _a : suggestion[customSuggestionKey !== null && customSuggestionKey !== void 0 ? customSuggestionKey : '']}`;
200
212
  if (suggestion.header && suggestion.label) {
201
213
  return (0, jsx_runtime_1.jsx)(DropdownHeader_1.default, { label: suggestion.label }, key);
202
214
  }
203
- return ((0, jsx_runtime_1.jsx)(MenuItem_1.default, { active: index === highlightedItemIndex, disabled: suggestion.disabled, value: suggestion.customSuggestion ? suggestion.customSuggestion : renderSuggestion(suggestion), onSelect: (_, event) => onSuggestionClicked(event, suggestion), index: index, onMouseEnter: onMouseEnter }, key));
215
+ const renderFunction = renderSuggestion ? renderSuggestion : renderDefaultSuggestion;
216
+ return ((0, jsx_runtime_1.jsx)(MenuItem_1.default, { active: index === highlightedItemIndex, disabled: suggestion.disabled, value: suggestion.customSuggestion ? suggestion.customSuggestion : renderFunction(suggestion), onSelect: (_, event) => onSuggestionClicked(event, suggestion), index: index, onMouseEnter: onMouseEnter }, key));
204
217
  })] })));
205
218
  };
206
219
  const classes = (0, classnames_1.default)('AutoSuggest', 'dropdown', isOpen && 'open', dropDirection.dropup && 'dropup', className);
@@ -8,7 +8,6 @@ const classnames_1 = tslib_1.__importDefault(require("classnames"));
8
8
  const noop_1 = tslib_1.__importDefault(require("lodash/fp/noop"));
9
9
  const buttonEffect_1 = require("../../utils/buttonEffect");
10
10
  const useMergeRefs_1 = tslib_1.__importDefault(require("../../hooks/useMergeRefs"));
11
- const usePrevious_1 = tslib_1.__importDefault(require("../../hooks/usePrevious"));
12
11
  exports.STYLES_MAP = {
13
12
  DEFAULT: 'default',
14
13
  PRIMARY: 'primary',
@@ -37,9 +36,11 @@ const Button = react_1.default.forwardRef((props, ref) => {
37
36
  const btnRef = (0, react_1.useRef)(null);
38
37
  const buttonRef = (0, useMergeRefs_1.default)(btnRef, ref);
39
38
  // Update internal toggle state when used as controlled component and outside toggle state changes
40
- const previousActive = (0, usePrevious_1.default)(active);
39
+ // Note, using the usePrevious hook resulted in an endless loop, hence the useState here
40
+ const [previousActive, setPreviousActive] = (0, react_1.useState)(active);
41
41
  if (active !== previousActive) {
42
42
  setIsToggled(active);
43
+ setPreviousActive(active);
43
44
  }
44
45
  const handleClick = (event) => {
45
46
  var _a;
@@ -66,7 +66,7 @@ export type DatePickerProps = Omit<DatetimepickerProps, 'onChange' | 'initialVal
66
66
  * @param isValid
67
67
  * @returns
68
68
  */
69
- onChange?: (value: Moment, isValid: boolean) => void;
69
+ onChange?: (value: Moment | string, isValid: boolean) => void;
70
70
  /**
71
71
  * Defines whether the input shows an error when the date is invalid or cleared.
72
72
  *
@@ -79,7 +79,7 @@ export type DatePickerProps = Omit<DatetimepickerProps, 'onChange' | 'initialVal
79
79
  * @param date
80
80
  * @returns
81
81
  */
82
- dateValidation?: (date: Moment) => boolean;
82
+ dateValidation?: (date: Moment | string) => boolean;
83
83
  /**
84
84
  * Additional classes to be set on the DatePicker element.
85
85
  */
@@ -150,7 +150,7 @@ declare const DatePicker: React.ForwardRefExoticComponent<Omit<Datetime.Datetime
150
150
  * @param isValid
151
151
  * @returns
152
152
  */
153
- onChange?: ((value: Moment, isValid: boolean) => void) | undefined;
153
+ onChange?: ((value: Moment | string, isValid: boolean) => void) | undefined;
154
154
  /**
155
155
  * Defines whether the input shows an error when the date is invalid or cleared.
156
156
  *
@@ -163,7 +163,7 @@ declare const DatePicker: React.ForwardRefExoticComponent<Omit<Datetime.Datetime
163
163
  * @param date
164
164
  * @returns
165
165
  */
166
- dateValidation?: ((date: Moment) => boolean) | undefined;
166
+ dateValidation?: ((date: Moment | string) => boolean) | undefined;
167
167
  /**
168
168
  * Additional classes to be set on the DatePicker element.
169
169
  */
@@ -4,28 +4,34 @@ const tslib_1 = require("tslib");
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const classnames_1 = tslib_1.__importDefault(require("classnames"));
7
- const noop_1 = tslib_1.__importDefault(require("lodash/fp/noop"));
8
7
  const moment_1 = tslib_1.__importDefault(require("moment"));
9
8
  const react_datetime_1 = tslib_1.__importDefault(require("react-datetime"));
9
+ const noop_1 = tslib_1.__importDefault(require("lodash/fp/noop"));
10
+ const isEmpty_1 = tslib_1.__importDefault(require("lodash/fp/isEmpty"));
10
11
  const DEFAULT_LOCALE = 'en-GB';
11
12
  const DEFAULT_MIN_WIDTH = 0;
12
- const isValidDate = (date) => typeof date === 'object';
13
+ const isValidDate = (date) => typeof date === 'object' && (0, moment_1.default)(date).isValid();
13
14
  const DatePicker = (0, react_1.forwardRef)((props, ref) => {
14
15
  const { id, dropup = false, alignRight = false, locale = DEFAULT_LOCALE, minWidth = DEFAULT_MIN_WIDTH, onChange = noop_1.default, mandatory = true, dateValidation, clearableInput = false, closeOnSelect = true, inputProps, className } = props, remainingProp = tslib_1.__rest(props, ["id", "dropup", "alignRight", "locale", "minWidth", "onChange", "mandatory", "dateValidation", "clearableInput", "closeOnSelect", "inputProps", "className"]);
15
16
  const [hasError, setHasError] = (0, react_1.useState)(false);
16
17
  const validateDate = (dateToValidate) => {
17
- return dateValidation ? dateValidation(dateToValidate) : isValidDate(dateToValidate);
18
+ if (dateValidation) {
19
+ return dateValidation(dateToValidate);
20
+ }
21
+ // if the date is mandatory, convert it to a moment object to validate
22
+ const value = (0, isEmpty_1.default)(dateToValidate) ? undefined : dateToValidate;
23
+ const dateValue = typeof value === 'string' ? (0, moment_1.default)(value) : value;
24
+ return isValidDate(dateValue);
18
25
  };
19
26
  const handleChange = (date) => {
20
- const dateValue = typeof date === 'string' ? (0, moment_1.default)(date) : date;
21
- const isValid = mandatory ? validateDate(dateValue) : true;
27
+ const isValid = mandatory ? validateDate(date) : true;
22
28
  setHasError(!isValid);
23
- onChange(dateValue, isValid);
29
+ onChange(date, isValid);
24
30
  };
25
31
  const classes = (0, classnames_1.default)('DatePicker', 'form-group', hasError && 'has-error', dropup && 'dropup', alignRight && 'align-right', className && className);
26
32
  // This way we can expose the "id" as top level prop and not as part of the inputProps which
27
33
  // makes the use of the id much more convenient
28
- const enhancedInputProps = Object.assign(Object.assign({}, inputProps), { id });
34
+ const enhancedInputProps = Object.assign({ id }, inputProps);
29
35
  return ((0, jsx_runtime_1.jsx)(react_datetime_1.default
30
36
  // TODO: add support for setting ref to the input. Maybe add a "inputRef" prop to react-datetime
31
37
  // ref={ref}
@@ -1,5 +1,5 @@
1
1
  import React, { PropsWithChildren } from 'react';
2
- export type bsSizeDialog = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full' | 'fullwidth' | 'fullheight' | 'fullscreen';
2
+ export type DialogSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full' | 'fullwidth' | 'fullheight' | 'fullscreen';
3
3
  export type BaseDialogProps = {
4
4
  /**
5
5
  * Opens the dialog when set to `true`.
@@ -22,7 +22,7 @@ export type BaseDialogProps = {
22
22
  /**
23
23
  * A callback function invoked when the dialog closes.
24
24
  */
25
- onClose?: Function;
25
+ onClose?: () => void;
26
26
  /**
27
27
  * Defined how large the dialog will be rendered.
28
28
  * By default, the dialog has a medium size and thus it can be omitted.
@@ -30,7 +30,7 @@ export type BaseDialogProps = {
30
30
  * Possible values are: `xs`, `sm`, `lg` `xl` `fullwidth` `fullheight` `fullscreen`
31
31
  * @default 'md'
32
32
  */
33
- bsSize?: bsSizeDialog;
33
+ bsSize?: DialogSize;
34
34
  /**
35
35
  * Enables or disabled closing the dialog via esc key.
36
36
  * @default false
@@ -55,7 +55,7 @@ export type DialogProps = BaseDialogProps & {
55
55
  /**
56
56
  * The dialog body content.
57
57
  */
58
- body: React.ReactNode;
58
+ body?: React.ReactNode;
59
59
  /**
60
60
  * The dialog body content.
61
61
  */
@@ -10,7 +10,7 @@ const noop_1 = tslib_1.__importDefault(require("lodash/fp/noop"));
10
10
  const framer_motion_1 = require("framer-motion");
11
11
  const portalRoot_1 = require("../../utils/portalRoot");
12
12
  const useEsc_1 = tslib_1.__importDefault(require("../../hooks/useEsc"));
13
- const useAfterMount_1 = tslib_1.__importDefault(require("../../hooks/useAfterMount"));
13
+ require("../../hooks/useAfterMount");
14
14
  const DialogHeader_1 = tslib_1.__importDefault(require("./DialogHeader"));
15
15
  const DialogBody_1 = tslib_1.__importDefault(require("./DialogBody"));
16
16
  const DialogFooter_1 = tslib_1.__importDefault(require("./DialogFooter"));
@@ -48,10 +48,12 @@ const Dialog = (props) => {
48
48
  usedEscapeKey && onEsc();
49
49
  }
50
50
  };
51
- (0, useAfterMount_1.default)(() => {
51
+ const [previousShow, setPreviousShow] = (0, react_1.useState)(show);
52
+ if (show !== previousShow) {
52
53
  setOpen(show);
53
54
  toggleBodyClass(show);
54
- }, [show]);
55
+ setPreviousShow(show);
56
+ }
55
57
  (0, useEsc_1.default)(() => {
56
58
  if (!dialogWrapperRef || !dialogWrapperRef.current) {
57
59
  return;
@@ -85,7 +87,7 @@ const Dialog = (props) => {
85
87
  const modalClasses = (0, classnames_1.default)('modal', 'show', className);
86
88
  const isSmallestDialog = bsSize === 'xs';
87
89
  const hasChildren = !!children;
88
- const modalDialogClasses = (0, classnames_1.default)(MODAL_DIALOG_CLASS, useOverflow && 'modal-overflow', bsSize === 'xs' && 'modal-xs', bsSize === 'sm' && 'modal-sm', bsSize === 'lg' && 'modal-lg', bsSize === 'lg' && 'modal-xl', bsSize === 'full' && 'modal-full-width', bsSize === 'fullwidth' && 'modal-full-width', bsSize === 'fullheight' && 'modal-full-height', bsSize === 'fullscreen' && 'modal-fullscreen');
90
+ const modalDialogClasses = (0, classnames_1.default)(MODAL_DIALOG_CLASS, useOverflow && 'modal-overflow', bsSize === 'xs' && 'modal-xs', bsSize === 'sm' && 'modal-sm', bsSize === 'lg' && 'modal-lg', bsSize === 'xl' && 'modal-xl', bsSize === 'full' && 'modal-full-width', bsSize === 'fullwidth' && 'modal-full-width', bsSize === 'fullheight' && 'modal-full-height', bsSize === 'fullscreen' && 'modal-fullscreen');
89
91
  const spring = {
90
92
  type: 'spring',
91
93
  damping: 33,
@@ -28,7 +28,7 @@ const getPlacement = (pullRight, dropup) => {
28
28
  return 'bottom-start';
29
29
  };
30
30
  const ButtonDropdown = (props) => {
31
- const { id = Math.random().toString(36).substr(2, 16), items = [], bsSize = 'md', bsStyle = 'default', disabled = false, iconOnly = false, title, splitButton = false, customDropdown, open, dropup = false, pullRight = false, noCaret = false, onOpen = noop_1.default, onClose = noop_1.default, onLabelButtonClick = noop_1.default, usePortal = false, popperConfig, toggleClassName = '', dropdownClassName, className = '' } = props, remainingProps = tslib_1.__rest(props, ["id", "items", "bsSize", "bsStyle", "disabled", "iconOnly", "title", "splitButton", "customDropdown", "open", "dropup", "pullRight", "noCaret", "onOpen", "onClose", "onLabelButtonClick", "usePortal", "popperConfig", "toggleClassName", "dropdownClassName", "className"]);
31
+ const { id = Math.random().toString(36).substr(2, 16), items = [], bsSize = 'md', bsStyle = 'default', variant, disabled = false, iconOnly = false, title, splitButton = false, customDropdown, open, dropup = false, pullRight = false, noCaret = false, onOpen = noop_1.default, onClose = noop_1.default, onLabelButtonClick = noop_1.default, usePortal = false, popperConfig, toggleClassName = '', dropdownClassName, className = '' } = props, remainingProps = tslib_1.__rest(props, ["id", "items", "bsSize", "bsStyle", "variant", "disabled", "iconOnly", "title", "splitButton", "customDropdown", "open", "dropup", "pullRight", "noCaret", "onOpen", "onClose", "onLabelButtonClick", "usePortal", "popperConfig", "toggleClassName", "dropdownClassName", "className"]);
32
32
  const [internalOpen, setInternalOpen] = (0, react_1.useState)(open);
33
33
  const [refDropdownToggle, setRefDropdownToggle] = (0, react_1.useState)(null);
34
34
  const [refDropdownMenu, setRefDropdownMenu] = (0, react_1.useState)(null);
@@ -78,6 +78,6 @@ const ButtonDropdown = (props) => {
78
78
  const wrapperClasses = (0, classnames_1.default)('dropdown', 'btn-group', isOpen && 'open', className);
79
79
  const dropdownClasses = (0, classnames_1.default)(usePortal && 'dropdown-portal', splitButton && pullRight && 'pull-right', dropdownClassName);
80
80
  const dropdownMenu = ((0, jsx_runtime_1.jsx)(MenuItemList_1.default, Object.assign({ className: dropdownClasses, ref: setRefDropdownMenu, style: styles.popper }, attributes.popper, { children: customDropdown ? customDropdown : (0, jsx_runtime_1.jsx)(MenuItems_1.default, { items: items, closeMenu: toggleOpen }) })));
81
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({}, remainingProps, { className: wrapperClasses, ref: wrapperRef }, { children: [(0, jsx_runtime_1.jsx)(DropdownToggleButton_1.default, Object.assign({ id: id, splitButton: splitButton, bsStyle: bsStyle, bsSize: bsSize, iconOnly: iconOnly, disabled: disabled, ref: setRefDropdownToggle, onClick: handleDropdownButtonClick, className: toggleClassName }, { children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [title, shouldShowCaret && (0, jsx_runtime_1.jsx)(Caret_1.default, {})] }) })), splitButton && ((0, jsx_runtime_1.jsx)(SplitCaretButton_1.default, { id: id, bsStyle: bsStyle, bsSize: bsSize, disabled: disabled, className: toggleClassName, onClick: toggleOpen, ref: setRefSplitButtonToggle })), isOpen && usePortal && react_dom_1.default.createPortal(dropdownMenu, dropdownRoot), isOpen && !usePortal && dropdownMenu] })));
81
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({}, remainingProps, { className: wrapperClasses, ref: wrapperRef }, { children: [(0, jsx_runtime_1.jsx)(DropdownToggleButton_1.default, Object.assign({ id: id, splitButton: splitButton, bsStyle: bsStyle, bsSize: bsSize, variant: variant, iconOnly: iconOnly, disabled: disabled, ref: setRefDropdownToggle, onClick: handleDropdownButtonClick, className: toggleClassName }, { children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [title, shouldShowCaret && (0, jsx_runtime_1.jsx)(Caret_1.default, {})] }) })), splitButton && ((0, jsx_runtime_1.jsx)(SplitCaretButton_1.default, { id: id, bsStyle: bsStyle, bsSize: bsSize, disabled: disabled, className: toggleClassName, onClick: toggleOpen, ref: setRefSplitButtonToggle })), isOpen && usePortal && react_dom_1.default.createPortal(dropdownMenu, dropdownRoot), isOpen && !usePortal && dropdownMenu] })));
82
82
  };
83
83
  exports.default = ButtonDropdown;
@@ -1,5 +1,5 @@
1
1
  import React, { type HTMLProps } from 'react';
2
- import { type BUTTON_SIZE, type BUTTON_STYLE } from '../button/Button';
2
+ import { type BUTTON_VARIANT, type BUTTON_SIZE, type BUTTON_STYLE } from '../button/Button';
3
3
  export type DropdownToggleButtonProps = HTMLProps<HTMLButtonElement> & {
4
4
  id?: string;
5
5
  disabled?: boolean;
@@ -8,6 +8,7 @@ export type DropdownToggleButtonProps = HTMLProps<HTMLButtonElement> & {
8
8
  onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
9
9
  bsSize: BUTTON_SIZE;
10
10
  bsStyle: BUTTON_STYLE;
11
+ variant?: BUTTON_VARIANT;
11
12
  className?: string;
12
13
  };
13
14
  declare const DropdownToggleButton: React.ForwardRefExoticComponent<Omit<React.PropsWithChildren<DropdownToggleButtonProps>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
@@ -6,8 +6,8 @@ const react_1 = require("react");
6
6
  const classnames_1 = tslib_1.__importDefault(require("classnames"));
7
7
  const Button_1 = tslib_1.__importDefault(require("../button/Button"));
8
8
  const DropdownToggleButton = (0, react_1.forwardRef)((props, ref) => {
9
- const { id, disabled, bsSize, bsStyle, splitButton = false, onClick, className = '', children } = props, remainingProps = tslib_1.__rest(props, ["id", "disabled", "bsSize", "bsStyle", "splitButton", "onClick", "className", "children"]);
9
+ const { id, disabled, bsSize, bsStyle, variant, splitButton = false, onClick, className = '', children } = props, remainingProps = tslib_1.__rest(props, ["id", "disabled", "bsSize", "bsStyle", "variant", "splitButton", "onClick", "className", "children"]);
10
10
  const labelButtonClasses = (0, classnames_1.default)(!splitButton && 'dropdown-toggle', !splitButton && className);
11
- return ((0, jsx_runtime_1.jsx)(Button_1.default, Object.assign({}, remainingProps, { id: splitButton ? `button-${id}` : id, type: 'button', ref: ref, disabled: disabled, bsStyle: bsStyle, bsSize: bsSize, onClick: onClick, className: labelButtonClasses }, { children: children })));
11
+ return ((0, jsx_runtime_1.jsx)(Button_1.default, Object.assign({}, remainingProps, { id: splitButton ? `button-${id}` : id, type: 'button', ref: ref, disabled: disabled, bsStyle: bsStyle, bsSize: bsSize, variant: variant, onClick: onClick, className: labelButtonClasses }, { children: children })));
12
12
  });
13
13
  exports.default = DropdownToggleButton;
@@ -66,6 +66,8 @@ export type EditableContentProps = {
66
66
  allowResize?: boolean;
67
67
  /**
68
68
  * Defines the number of rows to use by the internal textarea component.
69
+ * When a single line is used, the input is saved on "enter" key.
70
+ *
69
71
  * @default 1
70
72
  */
71
73
  inputRows?: number;
@@ -62,9 +62,9 @@ const EditableContent = (props) => {
62
62
  };
63
63
  const { styles, attributes } = (0, react_popper_1.usePopper)(referenceElement, popperElement, popperConfig);
64
64
  const handleEditMode = () => {
65
- var _a;
65
+ var _a, _b;
66
66
  setIsEditMode(true);
67
- setInputValue((_a = referenceElement === null || referenceElement === void 0 ? void 0 : referenceElement.textContent) !== null && _a !== void 0 ? _a : '');
67
+ setInputValue((_b = (_a = referenceElement === null || referenceElement === void 0 ? void 0 : referenceElement.textContent) === null || _a === void 0 ? void 0 : _a.trimEnd()) !== null && _b !== void 0 ? _b : '');
68
68
  onEditMode();
69
69
  };
70
70
  const handleInputChange = (event) => {
@@ -74,6 +74,8 @@ const EditableContent = (props) => {
74
74
  // Prevent line breaks when textarea is a single line
75
75
  if (event.key === 'Enter' && inputRows === DEFAULT_TEXTAREA_ROWS) {
76
76
  event.preventDefault();
77
+ // Save on "enter" when textarea has a single line
78
+ handleSaveChanges();
77
79
  }
78
80
  };
79
81
  const handleCloseEditMode = () => {
@@ -85,7 +87,7 @@ const EditableContent = (props) => {
85
87
  setHasError(!isInputValid);
86
88
  if (isInputValid) {
87
89
  setIsEditMode(false);
88
- onSave(inputValue);
90
+ onSave(inputValue.trimEnd());
89
91
  }
90
92
  };
91
93
  // Control edit mode from outside for instance if text element got focus
@@ -105,8 +107,7 @@ const EditableContent = (props) => {
105
107
  minWidth: '100px',
106
108
  resize: allowResize ? 'vertical' : 'none',
107
109
  };
108
- // &nbsp handling if coming from outside -> check textarea for empty string and nbsp
109
110
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", Object.assign({ ref: setReferenceElement, onClick: handleEditMode, className: textWrapperClasses }, { children: children })), isEditMode &&
110
- (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: overlayWrapperClasses, onClick: event => event.stopPropagation(), ref: setPopperElement, style: styles.popper }, attributes.popper, remainingProps, { children: [(0, jsx_runtime_1.jsxs)("div", Object.assign({ className: inputWrapperClasses }, { children: [hasCustomControl && customEditor, !hasCustomControl && ((0, jsx_runtime_1.jsx)("textarea", { ref: inputRef, className: inputClasses, value: inputValue, onChange: handleInputChange, onFocus: onFocus, onBlur: onBlur, onKeyDown: handleKeyDown, style: inputStyle, rows: inputRows })), hasError && (0, jsx_runtime_1.jsx)("div", Object.assign({ className: 'help-block position-relative' }, { children: errorMessage }))] })), (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: 'display-flex gap-5' }, { children: [(0, jsx_runtime_1.jsx)("button", Object.assign({ type: 'button', onClick: handleCloseEditMode, className: `EditableContentCancel btn btn-default btn-icon-only btn-${size}` }, { children: (0, jsx_runtime_1.jsx)("span", { className: 'rioglyph rioglyph-remove' }) })), (0, jsx_runtime_1.jsx)("button", Object.assign({ type: 'button', onClick: handleSaveChanges, className: `EditableContentSave btn btn-primary btn-icon-only btn-${size}` }, { children: (0, jsx_runtime_1.jsx)("span", { className: 'rioglyph rioglyph-ok' }) }))] }))] })), (0, portalRoot_1.getOrCreatePortalRoot)())] }));
111
+ (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: overlayWrapperClasses, onClick: event => event.stopPropagation(), ref: setPopperElement, style: styles.popper }, attributes.popper, remainingProps, { children: [(0, jsx_runtime_1.jsxs)("div", Object.assign({ className: inputWrapperClasses }, { children: [hasCustomControl && customEditor, !hasCustomControl && ((0, jsx_runtime_1.jsx)("textarea", { ref: inputRef, className: inputClasses, value: inputValue, onChange: handleInputChange, onFocus: onFocus, onBlur: onBlur, onKeyDown: handleKeyDown, style: inputStyle, rows: inputRows })), hasError && (0, jsx_runtime_1.jsx)("div", Object.assign({ className: 'help-block position-relative' }, { children: errorMessage }))] })), (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: 'display-flex gap-5' }, { children: [(0, jsx_runtime_1.jsx)("button", Object.assign({ type: 'button', onClick: handleCloseEditMode, className: `EditableContentCancel btn btn-default btn-icon-only btn-${size}`, "aria-label": 'EditableContent cancel button', "data-testid": 'EditableContentCancel' }, { children: (0, jsx_runtime_1.jsx)("span", { className: 'rioglyph rioglyph-remove' }) })), (0, jsx_runtime_1.jsx)("button", Object.assign({ type: 'button', onClick: handleSaveChanges, className: `EditableContentSave btn btn-primary btn-icon-only btn-${size}`, "aria-label": 'EditableContent save button', "data-testid": 'EditableContentSave' }, { children: (0, jsx_runtime_1.jsx)("span", { className: 'rioglyph rioglyph-ok' }) }))] }))] })), (0, portalRoot_1.getOrCreatePortalRoot)())] }));
111
112
  };
112
113
  exports.default = EditableContent;
@@ -15,8 +15,6 @@ const MenuItem = (props) => {
15
15
  }
16
16
  const role = divider ? 'separator' : 'presentation';
17
17
  const classes = (0, classnames_1.default)(divider && 'divider pointer-events-none', disabled && 'disabled', active && 'active');
18
- // biome-ignore lint/a11y/useValidAnchor: <explanation>
19
- const menuLink = (0, jsx_runtime_1.jsx)("a", Object.assign({ role: 'menuitem' }, { children: value }));
20
18
  const handleSelectItem = (event) => {
21
19
  if (!disabled) {
22
20
  onSelect(index, event);
@@ -33,6 +31,6 @@ const MenuItem = (props) => {
33
31
  if (header) {
34
32
  return (0, jsx_runtime_1.jsx)(DropdownHeader_1.default, { label: value, center: false });
35
33
  }
36
- return ((0, jsx_runtime_1.jsx)("li", Object.assign({ role: role, className: classes, onClick: handleSelectItem, onMouseEnter: handleItemMouseEnter, "data-item-index": index }, { children: header ? value : menuLink })));
34
+ return ((0, jsx_runtime_1.jsx)("li", Object.assign({ role: role, className: classes, onClick: handleSelectItem, onMouseEnter: handleItemMouseEnter, "data-item-index": index }, { children: (0, jsx_runtime_1.jsx)("a", Object.assign({ role: 'menuitem' }, { children: value })) })));
37
35
  };
38
36
  exports.default = MenuItem;
@@ -7,8 +7,8 @@ const noop_1 = tslib_1.__importDefault(require("lodash/fp/noop"));
7
7
  const MenuItem_1 = tslib_1.__importDefault(require("./MenuItem"));
8
8
  const MenuItems = ({ items, closeMenu = noop_1.default, onMouseEnter = noop_1.default }) => {
9
9
  return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: items.map((item, index) => {
10
- var _a;
11
- return ((0, jsx_runtime_1.jsx)(MenuItem_1.default, Object.assign({}, item, { index: index, closeMenu: closeMenu, onMouseEnter: onMouseEnter }), (_a = item.index) !== null && _a !== void 0 ? _a : index));
10
+ var _a, _b;
11
+ return ((0, jsx_runtime_1.jsx)(MenuItem_1.default, Object.assign({}, item, { index: (_a = item.index) !== null && _a !== void 0 ? _a : index, closeMenu: closeMenu, onMouseEnter: onMouseEnter }), (_b = item.index) !== null && _b !== void 0 ? _b : index));
12
12
  }) }));
13
13
  };
14
14
  exports.default = MenuItems;
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "0.16.4-beta.23"
2
+ "version": "0.16.4-beta.24"
3
3
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rio-cloud/rio-uikit",
3
- "version": "0.16.4-beta.23",
3
+ "version": "0.16.4-beta.24",
4
4
  "description": "The RIO UIKIT component library",
5
5
  "repository": "https://collaboration.msi.audi.com/stash/projects/RIOFRONT/repos/uikit-web/browse",
6
6
  "scripts": {
@@ -48,36 +48,36 @@
48
48
  "**/*.*"
49
49
  ],
50
50
  "devDependencies": {
51
- "@react-email/body": "0.0.4",
52
- "@react-email/button": "0.0.11",
53
- "@react-email/column": "0.0.8",
54
- "@react-email/container": "0.0.10",
55
- "@react-email/font": "0.0.4",
56
- "@react-email/head": "0.0.6",
57
- "@react-email/heading": "0.0.9",
58
- "@react-email/hr": "0.0.6",
59
- "@react-email/html": "0.0.6",
60
- "@react-email/img": "0.0.6",
61
- "@react-email/link": "0.0.6",
62
- "@react-email/preview": "0.0.7",
63
- "@react-email/render": "0.0.9",
64
- "@react-email/row": "0.0.6",
65
- "@react-email/section": "0.0.10",
66
- "@react-email/text": "0.0.6",
51
+ "@react-email/body": "0.0.7",
52
+ "@react-email/button": "0.0.13",
53
+ "@react-email/column": "0.0.9",
54
+ "@react-email/container": "0.0.11",
55
+ "@react-email/font": "0.0.5",
56
+ "@react-email/head": "0.0.7",
57
+ "@react-email/heading": "0.0.11",
58
+ "@react-email/hr": "0.0.7",
59
+ "@react-email/html": "0.0.7",
60
+ "@react-email/img": "0.0.7",
61
+ "@react-email/link": "0.0.7",
62
+ "@react-email/preview": "0.0.8",
63
+ "@react-email/render": "0.0.10",
64
+ "@react-email/row": "0.0.7",
65
+ "@react-email/section": "0.0.11",
66
+ "@react-email/text": "0.0.7",
67
67
  "@testing-library/dom": "9.3.3",
68
68
  "@testing-library/jest-dom": "5.17.0",
69
69
  "@testing-library/react": "12.1.5",
70
70
  "@testing-library/user-event": "14.5.1",
71
71
  "@types/heremaps": "^3.1.14",
72
72
  "@types/lodash": "4.14.202",
73
- "@types/react": "18.2.39",
73
+ "@types/react": "18.2.42",
74
74
  "@types/react-dom": "18.2.17",
75
75
  "@types/react-input-mask": "3.0.5",
76
- "@types/react-redux": "7.1.31",
77
- "@types/resize-observer-browser": "0.1.10",
78
- "@typescript-eslint/eslint-plugin": "6.13.1",
79
- "@typescript-eslint/parser": "6.13.1",
80
- "@vitejs/plugin-react": "4.2.0",
76
+ "@types/react-redux": "7.1.32",
77
+ "@types/resize-observer-browser": "0.1.11",
78
+ "@typescript-eslint/eslint-plugin": "6.13.2",
79
+ "@typescript-eslint/parser": "6.13.2",
80
+ "@vitejs/plugin-react": "4.2.1",
81
81
  "@vitest/coverage-c8": "0.33.0",
82
82
  "@wojtekmaj/enzyme-adapter-react-17": "0.8.0",
83
83
  "autoprefixer": "10.4.16",
@@ -86,8 +86,8 @@
86
86
  "dotenv": "16.3.1",
87
87
  "enzyme": "3.11.0",
88
88
  "enzyme-adapter-react-16": "1.15.7",
89
- "eslint": "8.54.0",
90
- "eslint-config-prettier": "9.0.0",
89
+ "eslint": "8.55.0",
90
+ "eslint-config-prettier": "9.1.0",
91
91
  "eslint-plugin-compat": "4.2.0",
92
92
  "eslint-plugin-getsentry": "2.0.0",
93
93
  "eslint-plugin-import": "2.29.0",
@@ -99,7 +99,7 @@
99
99
  "jsdom-global": "3.0.2",
100
100
  "less": "4.2.0",
101
101
  "license-checker": "25.0.1",
102
- "postcss": "8.4.31",
102
+ "postcss": "8.4.32",
103
103
  "postcss-preset-env": "8.5.1",
104
104
  "postcss-short": "5.0.0",
105
105
  "postcss-variable-compress": "2.1.0",
@@ -110,12 +110,12 @@
110
110
  "react-intl": "6.5.5",
111
111
  "rollup-plugin-copy": "3.5.0",
112
112
  "strip-ansi": "7.1.0",
113
- "svgo": "3.0.4",
113
+ "svgo": "3.0.5",
114
114
  "tiny-invariant": "^1.3.1",
115
115
  "typescript": "4.9.5",
116
116
  "vite": "4.5.0",
117
117
  "vite-plugin-zip-pack": "1.0.6",
118
- "vitest": "0.34.6",
118
+ "vitest": "1.0.1",
119
119
  "webfonts-generator": "github:rio-cloud/webfonts-generator#f666e60803da9155175a7f1775e09671d47a383b"
120
120
  },
121
121
  "peerDependencies": {
@@ -148,7 +148,7 @@
148
148
  "react-responsive": "9.0.2",
149
149
  "react-shadow-root": "6.2.0",
150
150
  "react-transition-group": "4.4.5",
151
- "recharts": "2.10.2",
151
+ "recharts": "2.10.3",
152
152
  "tslib": "2.6.2"
153
153
  },
154
154
  "pre-commit": [
package/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "0.16.4-beta.23"
2
+ "version": "0.16.4-beta.24"
3
3
  }