@connectif/ui-components 9.0.4 → 9.0.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.
package/CHANGELOG.md CHANGED
@@ -1,11 +1,37 @@
1
1
  # Changelog
2
2
 
3
+ ## [9.0.6] - 2026-06-23
4
+
5
+ ### Added
6
+
7
+ - `Autocomplete`: added optional `exclusiveOption` property.
8
+
9
+ ## [9.0.5] - 2026-06-19
10
+
11
+ ### Added
12
+
13
+ - `InputLabel`: added focused visual state — the label color switches to `primary.main` when the associated input (linked via `htmlFor`) is focused.
14
+ - `InputLabel`: added `focused` prop to allow external control of the focused visual state, overriding the internal focus tracking.
15
+ - `InputLabel`: added `onClick` prop forwarded to the underlying `<label>` element.
16
+ - `ColorPicker`: added `disabled` prop.
17
+
18
+ ### Changed
19
+
20
+ - `Toolbar` story `ToolbarInDrawer`: drawer now starts closed, with an open button and a close button in the toolbar actions.
21
+ - `Dialog` story: dialog now starts closed, with a centered "Open Dialog" button to open it.
22
+ - `ConfirmationDialog` story: dialogs now start closed, with a centered "Open Dialog" button to open them.
23
+ - `Snackbar` story: removed the `Dialog` wrapper — buttons now render directly.
24
+
3
25
  ## [9.0.4] - 2026-06-08
4
26
 
5
27
  ### Changed
6
28
 
7
29
  - `LineChart`: now the secondary metric is positioned in left side of the chart.
8
30
 
31
+ ### Fixed
32
+
33
+ - `Stepper`: Stepper connector fixed when only label is specified in steps
34
+
9
35
  ## [9.0.3] - 2026-06-02
10
36
 
11
37
  ### Added
@@ -53,6 +53,11 @@ export type ColorPickerProps = {
53
53
  * @default 'auto'
54
54
  */
55
55
  mode?: ColorPickerMode;
56
+ /**
57
+ * (optional) Whether the color picker is disabled.
58
+ * @default false
59
+ */
60
+ disabled?: boolean;
56
61
  /**
57
62
  * A function to update color value
58
63
  */
@@ -21,6 +21,15 @@ export type InputLabelProps = React.PropsWithChildren<{
21
21
  * Show an info icon with the text as tooltip
22
22
  */
23
23
  infoText?: TooltipProps['title'];
24
+ /**
25
+ * Override the focused visual state. When provided, takes
26
+ * precedence over the internal focus tracking via `htmlFor`.
27
+ */
28
+ focused?: boolean;
29
+ /**
30
+ * Click handler for the label element.
31
+ */
32
+ onClick?: React.MouseEventHandler<HTMLLabelElement>;
24
33
  }>;
25
34
  /**
26
35
  * A label text to be shown along with form fields, like Select or TextFields, usually
@@ -44,6 +53,15 @@ declare const InputLabel: React.ForwardRefExoticComponent<{
44
53
  * Show an info icon with the text as tooltip
45
54
  */
46
55
  infoText?: TooltipProps["title"];
56
+ /**
57
+ * Override the focused visual state. When provided, takes
58
+ * precedence over the internal focus tracking via `htmlFor`.
59
+ */
60
+ focused?: boolean;
61
+ /**
62
+ * Click handler for the label element.
63
+ */
64
+ onClick?: React.MouseEventHandler<HTMLLabelElement>;
47
65
  } & {
48
66
  children?: React.ReactNode | undefined;
49
67
  } & React.RefAttributes<HTMLLabelElement>>;
@@ -124,9 +124,19 @@ export type AutocompleteProps<T extends string, Multiple extends boolean | undef
124
124
  * Ref to the inner HTMLInputElement
125
125
  */
126
126
  ref?: React.Ref<HTMLInputElement>;
127
+ /**
128
+ * When provided, this option is always displayed as the first item in the
129
+ * dropdown, separated from the rest by a divider. Selecting it clears all
130
+ * other selections; selecting any other option deselects this one.
131
+ * In multiple mode, while this option is active the input renders as plain
132
+ * text (no chips).
133
+ */
134
+ exclusiveOption?: AutocompleteOption<T> & {
135
+ label?: string;
136
+ };
127
137
  };
128
138
  /**
129
139
  * Powered TextField with the ability to select from a predefined list of options, allowing to select one or multiple values.
130
140
  */
131
- declare const Autocomplete: <T extends string, Multiple extends boolean | undefined = undefined, Value = AutocompleteValue<T, Multiple>>({ variant, value, multiple, textFieldProps, options, disabled, mode, isCaseSensitive, isDiacriticSensitive, onChange, renderLabel, isLoading, onSearch, loadingText, noOptionsText, allowFreeText, addNewValueText, closeOnSelect, maxValueLength, maxValues, maxValuesText, startIconId, onClose, onOpen, disableClear, disableCloseOnClickAway, size }: AutocompleteProps<T, Multiple, Value>) => import("react/jsx-runtime").JSX.Element;
141
+ declare const Autocomplete: <T extends string, Multiple extends boolean | undefined = undefined, Value = AutocompleteValue<T, Multiple>>({ variant, value, multiple, textFieldProps, options, disabled, mode, isCaseSensitive, isDiacriticSensitive, onChange, renderLabel, isLoading, onSearch, loadingText, noOptionsText, allowFreeText, addNewValueText, closeOnSelect, maxValueLength, maxValues, maxValuesText, startIconId, onClose, onOpen, disableClear, disableCloseOnClickAway, size, exclusiveOption }: AutocompleteProps<T, Multiple, Value>) => import("react/jsx-runtime").JSX.Element;
132
142
  export default Autocomplete;
@@ -67,9 +67,19 @@ export type AutocompleteInputProps<T extends string, Multiple extends boolean |
67
67
  onSearchValueChange: (event: React.SyntheticEvent, searchValue: string) => void;
68
68
  onPressEnter: (event: React.SyntheticEvent, inputValue: string) => void;
69
69
  onRemoveValue: (event: React.SyntheticEvent, value: Value) => void;
70
+ /**
71
+ * When true (exclusive option selected in multiple mode), chips are hidden
72
+ * and the input displays as a plain text field.
73
+ */
74
+ exclusiveOptionSelected?: boolean;
75
+ /**
76
+ * Label to display in the text field when the exclusive option is selected
77
+ * and the component is in multiple mode.
78
+ */
79
+ exclusiveOptionLabel?: string;
70
80
  };
71
81
  /**
72
82
  * Powered TextField Input.
73
83
  */
74
- declare const AutocompleteInput: <T extends string, Multiple extends boolean | undefined = undefined, Value = AutocompleteValue<T, Multiple>>({ variant, value, multiple, textFieldProps, hasFilteredOptions, disabled, renderLabel, maxValueLength, canAddValues, maxValuesText, disableClear, containerRef, inputRef, onClosePopover, onOpenPopover, isOpenPopover, inputValue, setInputValue, placeholder, startIconId, size, onSearchValueChange, onPressEnter, onRemoveValue }: AutocompleteInputProps<T, Multiple, Value>) => import("react/jsx-runtime").JSX.Element;
84
+ declare const AutocompleteInput: <T extends string, Multiple extends boolean | undefined = undefined, Value = AutocompleteValue<T, Multiple>>({ variant, value, multiple, textFieldProps, hasFilteredOptions, disabled, renderLabel, maxValueLength, canAddValues, maxValuesText, disableClear, containerRef, inputRef, onClosePopover, onOpenPopover, isOpenPopover, inputValue, setInputValue, placeholder, startIconId, size, onSearchValueChange, onPressEnter, onRemoveValue, exclusiveOptionSelected, exclusiveOptionLabel }: AutocompleteInputProps<T, Multiple, Value>) => import("react/jsx-runtime").JSX.Element;
75
85
  export default AutocompleteInput;
@@ -30,10 +30,19 @@ type AutocompleteListProps<T extends string, Multiple extends boolean | undefine
30
30
  highlightedIndex: number;
31
31
  onAddSelectedValue: (event: React.MouseEvent<HTMLElement, MouseEvent>, option: AutocompleteLabeledOption<T>) => void;
32
32
  onClickAwayPopover: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
33
+ /**
34
+ * Option that is always shown first, separated by a divider, and when selected
35
+ * clears all other selections (and vice versa).
36
+ */
37
+ exclusiveOption?: AutocompleteLabeledOption<T>;
38
+ /**
39
+ * Whether the exclusive option is currently selected.
40
+ */
41
+ isExclusiveSelected?: boolean;
33
42
  };
34
43
  export declare const AUTOCOMPLETE_ITEM_HEIGHT = 44;
35
44
  /**
36
45
  * Powered autocomplete list.
37
46
  */
38
- declare const AutocompleteList: <T extends string, Multiple extends boolean | undefined = undefined>({ options, isLoading, loadingText, noOptionsText, addNewValueText, inputContainerRef, isOpen, selectedIndex, highlightedIndex, virtualListRef, filteredOptions, onAddSelectedValue, onClickAwayPopover }: AutocompleteListProps<T, Multiple>) => import("react/jsx-runtime").JSX.Element;
47
+ declare const AutocompleteList: <T extends string, Multiple extends boolean | undefined = undefined>({ options, isLoading, loadingText, noOptionsText, addNewValueText, inputContainerRef, isOpen, selectedIndex, highlightedIndex, virtualListRef, filteredOptions, onAddSelectedValue, onClickAwayPopover, exclusiveOption, isExclusiveSelected }: AutocompleteListProps<T, Multiple>) => import("react/jsx-runtime").JSX.Element;
39
48
  export default AutocompleteList;
package/dist/index.js CHANGED
@@ -19343,7 +19343,7 @@ function useDebouncedCallback(callback, wait) {
19343
19343
  }
19344
19344
 
19345
19345
  // src/components/input/DebouncedTextField.tsx
19346
- import { useEffect as useEffect12, useState as useState17 } from "react";
19346
+ import { useEffect as useEffect13, useState as useState18 } from "react";
19347
19347
 
19348
19348
  // src/components/input/TextField.tsx
19349
19349
  import * as React52 from "react";
@@ -19355,23 +19355,49 @@ import { styled as styled4 } from "@mui/material";
19355
19355
  import { jsx as jsx99, jsxs as jsxs44 } from "react/jsx-runtime";
19356
19356
  var getSeverityColor = ({ palette: palette2 }, severity) => severity === "error" ? palette2.error.main : palette2.grey[900];
19357
19357
  var StyledLabel = styled4("label", {
19358
- shouldForwardProp: (prop) => prop !== "severity"
19358
+ shouldForwardProp: (prop) => prop !== "severity" && prop !== "focused"
19359
19359
  })(
19360
- ({ severity, theme: theme2 }) => theme2.unstable_sx({
19360
+ ({ severity, focused, theme: theme2 }) => theme2.unstable_sx({
19361
19361
  display: "block",
19362
19362
  padding: "4px 0",
19363
19363
  ...variants["caption"],
19364
- color: getSeverityColor(theme2, severity)
19364
+ color: focused && severity !== "error" ? theme2.palette.primary.main : getSeverityColor(theme2, severity)
19365
19365
  })
19366
19366
  );
19367
19367
  var InputLabel = React50.forwardRef(
19368
- function InputLabel2({ htmlFor, sx, children, severity = "info", infoText }, ref) {
19368
+ function InputLabel2({
19369
+ htmlFor,
19370
+ sx,
19371
+ children,
19372
+ severity = "info",
19373
+ infoText,
19374
+ focused: focusedProp,
19375
+ onClick
19376
+ }, ref) {
19377
+ const [internalFocused, setInternalFocused] = React50.useState(false);
19378
+ const focused = focusedProp ?? internalFocused;
19379
+ React50.useEffect(() => {
19380
+ const input = htmlFor ? document.getElementById(htmlFor) : null;
19381
+ if (!input) {
19382
+ return;
19383
+ }
19384
+ const handleFocus = () => setInternalFocused(true);
19385
+ const handleBlur = () => setInternalFocused(false);
19386
+ input.addEventListener("focus", handleFocus);
19387
+ input.addEventListener("blur", handleBlur);
19388
+ return () => {
19389
+ input.removeEventListener("focus", handleFocus);
19390
+ input.removeEventListener("blur", handleBlur);
19391
+ };
19392
+ }, [htmlFor]);
19369
19393
  return /* @__PURE__ */ jsxs44(
19370
19394
  StyledLabel,
19371
19395
  {
19372
19396
  htmlFor,
19373
19397
  sx,
19374
19398
  severity,
19399
+ focused,
19400
+ onClick,
19375
19401
  ref,
19376
19402
  children: [
19377
19403
  children,
@@ -19749,7 +19775,7 @@ var TextField_default = TextField;
19749
19775
  // src/components/input/DebouncedTextField.tsx
19750
19776
  import { jsx as jsx102 } from "react/jsx-runtime";
19751
19777
  var DebouncedTextField = React53.forwardRef(function DebouncedTextField2({ value, onChange, debounce = 100, ...rest }, ref) {
19752
- const [text, setText] = useState17(value ?? "");
19778
+ const [text, setText] = useState18(value ?? "");
19753
19779
  const expectedChangeRef = React53.useRef(void 0);
19754
19780
  const onChangeDebounced = useDebouncedCallback(
19755
19781
  (e) => {
@@ -19760,7 +19786,7 @@ var DebouncedTextField = React53.forwardRef(function DebouncedTextField2({ value
19760
19786
  },
19761
19787
  debounce
19762
19788
  );
19763
- useEffect12(() => {
19789
+ useEffect13(() => {
19764
19790
  if (expectedChangeRef.current === value) {
19765
19791
  expectedChangeRef.current = void 0;
19766
19792
  } else {
@@ -22552,6 +22578,7 @@ var ColorPicker = React67.forwardRef(function ColorPickerWrapper({
22552
22578
  popoverZIndex,
22553
22579
  inputWidthStyle = "150px",
22554
22580
  mode = "auto",
22581
+ disabled = false,
22555
22582
  onChange
22556
22583
  }, ref) {
22557
22584
  const { t } = useTranslation();
@@ -22584,6 +22611,7 @@ var ColorPicker = React67.forwardRef(function ColorPickerWrapper({
22584
22611
  {
22585
22612
  iconId: value ? "color-square" : "transparent",
22586
22613
  size: "M",
22614
+ disabled,
22587
22615
  onClick: (event) => {
22588
22616
  setAnchorEl(event.currentTarget);
22589
22617
  },
@@ -22626,6 +22654,11 @@ var ColorPicker = React67.forwardRef(function ColorPickerWrapper({
22626
22654
  );
22627
22655
  }
22628
22656
  }, [value, internalPickerValue, colorChangeOccurred, allowEmpty, mode]);
22657
+ React67.useEffect(() => {
22658
+ if (disabled) {
22659
+ setAnchorEl(void 0);
22660
+ }
22661
+ }, [disabled]);
22629
22662
  React67.useEffect(() => {
22630
22663
  if (anchorEl) {
22631
22664
  const handleFocus = () => {
@@ -22663,14 +22696,14 @@ var ColorPicker = React67.forwardRef(function ColorPickerWrapper({
22663
22696
  {
22664
22697
  value: textFieldValue,
22665
22698
  label,
22699
+ disabled,
22666
22700
  sx: {
22667
22701
  width: inputWidthStyle,
22668
22702
  height: "36px !important"
22669
22703
  },
22670
22704
  inputSx: {
22671
22705
  fontFamily: "Source Sans Pro, sans-serif",
22672
- fontWeight: "400",
22673
- color: grey900
22706
+ fontWeight: "400"
22674
22707
  },
22675
22708
  placeholder: t("COLOR_PICKER.VALUE_NOT_DEFINED"),
22676
22709
  onChange: handleTextFieldChange,
@@ -23538,7 +23571,7 @@ import * as React73 from "react";
23538
23571
  // src/components/input/SelectPopover.tsx
23539
23572
  import * as React72 from "react";
23540
23573
  import { Grid as Grid4, Stack as Stack12 } from "@mui/material";
23541
- import { useState as useState30 } from "react";
23574
+ import { useState as useState31 } from "react";
23542
23575
  import InfiniteScroll from "react-infinite-scroll-component";
23543
23576
  import { jsx as jsx132, jsxs as jsxs62 } from "react/jsx-runtime";
23544
23577
  var defaultItemsColorStyles = {
@@ -23576,9 +23609,9 @@ var SelectPopover = function SelectPopover2({
23576
23609
  itemsTitle
23577
23610
  }) {
23578
23611
  const { t } = useTranslation();
23579
- const [searchText, setSearchText] = useState30("");
23580
- const [isScrollBottom, setIsScrollBottom] = useState30(false);
23581
- const [currentItems, setCurrentItems] = useState30([]);
23612
+ const [searchText, setSearchText] = useState31("");
23613
+ const [isScrollBottom, setIsScrollBottom] = useState31(false);
23614
+ const [currentItems, setCurrentItems] = useState31([]);
23582
23615
  const [currentSelectedItems, setCurrentSelectedItems] = React72.useState([]);
23583
23616
  const prevSelectedItemsIdsRef = React72.useRef([]);
23584
23617
  const onSearchTextChanged = (text) => {
@@ -24288,7 +24321,9 @@ var AutocompleteInput = function AutocompleteInput2({
24288
24321
  size,
24289
24322
  onSearchValueChange,
24290
24323
  onPressEnter,
24291
- onRemoveValue
24324
+ onRemoveValue,
24325
+ exclusiveOptionSelected = false,
24326
+ exclusiveOptionLabel
24292
24327
  }) {
24293
24328
  const { palette: palette2 } = useCustomTheme();
24294
24329
  const { t } = useTranslation();
@@ -24334,7 +24369,7 @@ var AutocompleteInput = function AutocompleteInput2({
24334
24369
  },
24335
24370
  maxLength: maxValueLength,
24336
24371
  placeholder: !canAddValues ? maxValuesText || t("AUTOCOMPLETE.MAX_VALUES") : Array.isArray(value) && value.length > 0 || !Array.isArray(value) && !!value ? "" : placeholder,
24337
- value: inputValue || (!Array.isArray(value) ? renderLabel(value) : ""),
24372
+ value: inputValue || exclusiveOptionLabel || (!Array.isArray(value) ? renderLabel(value) : ""),
24338
24373
  multiline: false,
24339
24374
  disabled: disabled || !canAddValues,
24340
24375
  onChange: (event) => {
@@ -24372,7 +24407,7 @@ var AutocompleteInput = function AutocompleteInput2({
24372
24407
  }
24373
24408
  },
24374
24409
  containerRef,
24375
- startAdornment: multiple ? /* @__PURE__ */ jsx135(
24410
+ startAdornment: multiple && !exclusiveOptionSelected ? /* @__PURE__ */ jsx135(
24376
24411
  AutocompleteInputSelection_default,
24377
24412
  {
24378
24413
  value,
@@ -24504,11 +24539,14 @@ var AutocompleteList = function AutocompleteList2({
24504
24539
  virtualListRef,
24505
24540
  filteredOptions,
24506
24541
  onAddSelectedValue,
24507
- onClickAwayPopover
24542
+ onClickAwayPopover,
24543
+ exclusiveOption,
24544
+ isExclusiveSelected
24508
24545
  }) {
24509
24546
  const { palette: palette2 } = useCustomTheme();
24510
24547
  const { t } = useTranslation();
24511
24548
  const listRef = React76.useRef(null);
24549
+ const popoverWidth = inputContainerRef.current?.clientWidth;
24512
24550
  const getText = (option) => {
24513
24551
  const isInOptions = options.some((elem) => elem.id === option.id);
24514
24552
  if (!isInOptions) {
@@ -24565,58 +24603,90 @@ var AutocompleteList = function AutocompleteList2({
24565
24603
  anchorEl: inputContainerRef.current,
24566
24604
  open: isOpen,
24567
24605
  sx: { zIndex: 3e3 },
24568
- children: /* @__PURE__ */ jsx136(Paper_default, { sx: { boxShadow: shadows[1], borderRadius: "8px" }, children: /* @__PURE__ */ jsxs66(
24569
- Box_default2,
24606
+ children: /* @__PURE__ */ jsxs66(
24607
+ Paper_default,
24570
24608
  {
24571
24609
  sx: {
24572
- maxHeight: "40vh",
24573
- height: !isLoading && filteredOptions.length ? filteredOptions.length * 44 : "auto",
24574
- width: inputContainerRef.current ? inputContainerRef.current.clientWidth : null,
24575
- borderRadius: "8px"
24610
+ boxShadow: shadows[1],
24611
+ borderRadius: "8px",
24612
+ width: popoverWidth ?? "auto"
24576
24613
  },
24577
- className: "Slim-Vertical-Scroll",
24578
- ref: listRef,
24579
24614
  children: [
24580
- isLoading && /* @__PURE__ */ jsx136(
24581
- ListItem_default,
24582
- {
24583
- text: loadingText ?? t("AUTOCOMPLETE.LOADING")
24584
- }
24585
- ),
24586
- !isLoading && filteredOptions.length === 0 && /* @__PURE__ */ jsx136(
24587
- ListItem_default,
24588
- {
24589
- text: noOptionsText ?? t("AUTOCOMPLETE.NO_OPTIONS")
24590
- }
24591
- ),
24592
- !isLoading && filteredOptions.length > 0 && /* @__PURE__ */ jsx136(AutoSizer5, { children: ({
24593
- height: height2,
24594
- width: width2
24595
- }) => /* @__PURE__ */ jsx136(
24596
- FixedSizeList3,
24615
+ exclusiveOption && /* @__PURE__ */ jsxs66(Fragment34, { children: [
24616
+ /* @__PURE__ */ jsx136(
24617
+ ListItemButton_default,
24618
+ {
24619
+ selected: isExclusiveSelected,
24620
+ tabIndex: -1,
24621
+ role: "option",
24622
+ baseSx: {
24623
+ color: palette2.grey[900]
24624
+ },
24625
+ text: exclusiveOption.label,
24626
+ onClick: (event) => onAddSelectedValue(
24627
+ event,
24628
+ exclusiveOption
24629
+ ),
24630
+ "data-testid": `autocomplete-option-${exclusiveOption.id}`
24631
+ }
24632
+ ),
24633
+ /* @__PURE__ */ jsx136(Divider_default, {})
24634
+ ] }),
24635
+ (!exclusiveOption || filteredOptions.length > 0 || isLoading) && /* @__PURE__ */ jsxs66(
24636
+ Box_default2,
24597
24637
  {
24598
- overscanCount: 3,
24599
- height: height2,
24600
- itemCount: filteredOptions.length,
24601
- itemSize: AUTOCOMPLETE_ITEM_HEIGHT,
24602
- width: width2,
24638
+ sx: {
24639
+ maxHeight: "40vh",
24640
+ height: !isLoading && filteredOptions.length ? filteredOptions.length * 44 : "auto",
24641
+ width: "100%",
24642
+ borderRadius: "8px"
24643
+ },
24603
24644
  className: "Slim-Vertical-Scroll",
24604
- ref: virtualListRef,
24605
- initialScrollOffset: getInitialListScroll(
24606
- {
24607
- itemHeight: AUTOCOMPLETE_ITEM_HEIGHT,
24608
- containerHeight: listRef.current?.clientHeight ?? 0,
24609
- highlightedIndex,
24610
- selectedIndex,
24611
- totalItems: filteredOptions.length
24612
- }
24613
- ),
24614
- children: ListItemButtonWrapper
24645
+ ref: listRef,
24646
+ children: [
24647
+ isLoading && /* @__PURE__ */ jsx136(
24648
+ ListItem_default,
24649
+ {
24650
+ text: loadingText ?? t("AUTOCOMPLETE.LOADING")
24651
+ }
24652
+ ),
24653
+ !isLoading && filteredOptions.length === 0 && /* @__PURE__ */ jsx136(
24654
+ ListItem_default,
24655
+ {
24656
+ text: noOptionsText ?? t("AUTOCOMPLETE.NO_OPTIONS")
24657
+ }
24658
+ ),
24659
+ !isLoading && filteredOptions.length > 0 && /* @__PURE__ */ jsx136(AutoSizer5, { children: ({
24660
+ height: height2,
24661
+ width: width2
24662
+ }) => /* @__PURE__ */ jsx136(
24663
+ FixedSizeList3,
24664
+ {
24665
+ overscanCount: 3,
24666
+ height: height2,
24667
+ itemCount: filteredOptions.length,
24668
+ itemSize: AUTOCOMPLETE_ITEM_HEIGHT,
24669
+ width: width2,
24670
+ className: "Slim-Vertical-Scroll",
24671
+ ref: virtualListRef,
24672
+ initialScrollOffset: getInitialListScroll(
24673
+ {
24674
+ itemHeight: AUTOCOMPLETE_ITEM_HEIGHT,
24675
+ containerHeight: listRef.current?.clientHeight ?? 0,
24676
+ highlightedIndex,
24677
+ selectedIndex,
24678
+ totalItems: filteredOptions.length
24679
+ }
24680
+ ),
24681
+ children: ListItemButtonWrapper
24682
+ }
24683
+ ) })
24684
+ ]
24615
24685
  }
24616
- ) })
24686
+ )
24617
24687
  ]
24618
24688
  }
24619
- ) })
24689
+ )
24620
24690
  }
24621
24691
  )
24622
24692
  }
@@ -24654,7 +24724,8 @@ var Autocomplete = function Autocomplete2({
24654
24724
  onOpen = () => ({}),
24655
24725
  disableClear,
24656
24726
  disableCloseOnClickAway = false,
24657
- size = "S"
24727
+ size = "S",
24728
+ exclusiveOption
24658
24729
  }) {
24659
24730
  const anchorRef = React77.useRef(null);
24660
24731
  const inputRef = React77.useRef(null);
@@ -24664,6 +24735,24 @@ var Autocomplete = function Autocomplete2({
24664
24735
  const _renderLabel = React77.useCallback((id) => id, []);
24665
24736
  const [inputValue, setInputValue] = React77.useState("");
24666
24737
  const [isDirty, setDirty] = React77.useState(false);
24738
+ const labeledExclusiveOption = React77.useMemo(() => {
24739
+ if (!exclusiveOption) {
24740
+ return void 0;
24741
+ }
24742
+ return {
24743
+ ...exclusiveOption,
24744
+ label: exclusiveOption.label ?? (renderLabel ?? _renderLabel)(exclusiveOption.id)
24745
+ };
24746
+ }, [exclusiveOption, renderLabel, _renderLabel]);
24747
+ const isExclusiveSelected = React77.useMemo(() => {
24748
+ if (!exclusiveOption) {
24749
+ return false;
24750
+ }
24751
+ if (Array.isArray(value)) {
24752
+ return value.includes(exclusiveOption.id);
24753
+ }
24754
+ return value === exclusiveOption.id;
24755
+ }, [exclusiveOption, value]);
24667
24756
  const getOptionsLabeled = React77.useCallback(
24668
24757
  (options2, inputValue2 = "") => {
24669
24758
  const searchValue = escapeRegExp2(inputValue2.trim());
@@ -24865,28 +24954,43 @@ var Autocomplete = function Autocomplete2({
24865
24954
  onChange && onChange(event, newValue);
24866
24955
  onClosePopoverAfterSelect(newValue, newFilteredOptions);
24867
24956
  };
24868
- const onSelectValueMultiple = (newValue, value2, event) => {
24957
+ const onSelectValueMultiple = (newValue, value2, event, options2) => {
24869
24958
  if (!onChange) {
24870
24959
  return;
24871
24960
  }
24872
24961
  let newValues = [];
24873
- if (value2.includes(newValue)) {
24962
+ const exclusiveCurrentlySelected = exclusiveOption && value2.includes(exclusiveOption.id);
24963
+ const selectingExclusive = exclusiveOption && newValue === exclusiveOption.id;
24964
+ if (selectingExclusive && !value2.includes(newValue)) {
24965
+ newValues = [newValue];
24966
+ } else if (value2.includes(newValue)) {
24874
24967
  newValues = value2.filter((v) => v !== newValue);
24875
24968
  } else if (newValue) {
24876
24969
  newValues = [...value2, newValue];
24970
+ if (exclusiveCurrentlySelected) {
24971
+ newValues = newValues.filter((v) => v !== exclusiveOption.id);
24972
+ }
24877
24973
  }
24878
24974
  onChange(event, newValues);
24879
- onClosePopoverAfterSelect(newValues);
24975
+ onClosePopoverAfterSelect(
24976
+ newValues,
24977
+ void 0,
24978
+ options2
24979
+ );
24880
24980
  };
24881
- const onSelectValueSingle = (newValue, event) => {
24981
+ const onSelectValueSingle = (newValue, event, options2) => {
24882
24982
  if (!onChange) {
24883
24983
  return;
24884
24984
  }
24885
24985
  onChange(event, newValue);
24886
- onClosePopoverAfterSelect(newValue);
24986
+ onClosePopoverAfterSelect(
24987
+ newValue,
24988
+ void 0,
24989
+ options2
24990
+ );
24887
24991
  };
24888
- const onClosePopoverAfterSelect = (selectedValue, newFilteredOptions) => {
24889
- if (closeOnSelect) {
24992
+ const onClosePopoverAfterSelect = (selectedValue, newFilteredOptions, options2) => {
24993
+ if (closeOnSelect || options2?.forceClose) {
24890
24994
  closePopover();
24891
24995
  } else {
24892
24996
  setNextIndexByValue(selectedValue, newFilteredOptions);
@@ -24897,10 +25001,22 @@ var Autocomplete = function Autocomplete2({
24897
25001
  if (!onChange) {
24898
25002
  return;
24899
25003
  }
25004
+ const isSelectingExclusiveOption = !!exclusiveOption && option.id === exclusiveOption.id && (!Array.isArray(value) || !value.includes(option.id));
25005
+ if (isSelectingExclusiveOption) {
25006
+ setInputValue("");
25007
+ setDirty(false);
25008
+ setPlaceholder(textFieldProps?.placeholder ?? "");
25009
+ setFilteredOptions(getOptionsLabeled([...options]));
25010
+ onSearch && onSearch("");
25011
+ }
24900
25012
  if (Array.isArray(value)) {
24901
- onSelectValueMultiple(option.id, value, event);
25013
+ onSelectValueMultiple(option.id, value, event, {
25014
+ forceClose: isSelectingExclusiveOption
25015
+ });
24902
25016
  } else {
24903
- onSelectValueSingle(option.id, event);
25017
+ onSelectValueSingle(option.id, event, {
25018
+ forceClose: isSelectingExclusiveOption
25019
+ });
24904
25020
  }
24905
25021
  setPlaceholder(textFieldProps?.placeholder ?? "");
24906
25022
  };
@@ -24980,7 +25096,9 @@ var Autocomplete = function Autocomplete2({
24980
25096
  setInputValue,
24981
25097
  placeholder,
24982
25098
  size,
24983
- onRemoveValue: onRemoveInputValue
25099
+ onRemoveValue: onRemoveInputValue,
25100
+ exclusiveOptionSelected: !!multiple && isExclusiveSelected,
25101
+ exclusiveOptionLabel: isExclusiveSelected ? labeledExclusiveOption?.label : void 0
24984
25102
  }
24985
25103
  ),
24986
25104
  /* @__PURE__ */ jsx137(
@@ -24998,7 +25116,9 @@ var Autocomplete = function Autocomplete2({
24998
25116
  highlightedIndex,
24999
25117
  inputContainerRef: anchorRef,
25000
25118
  onAddSelectedValue: handleSelectValue,
25001
- onClickAwayPopover
25119
+ onClickAwayPopover,
25120
+ exclusiveOption: labeledExclusiveOption,
25121
+ isExclusiveSelected
25002
25122
  }
25003
25123
  )
25004
25124
  ] });
@@ -28142,7 +28262,7 @@ import MuiTabs from "@mui/material/Tabs";
28142
28262
 
28143
28263
  // src/components/layout/SwipeableViews.tsx
28144
28264
  import * as React95 from "react";
28145
- import { useEffect as useEffect28, useRef as useRef33, useState as useState41 } from "react";
28265
+ import { useEffect as useEffect29, useRef as useRef33, useState as useState42 } from "react";
28146
28266
  import { jsx as jsx167 } from "react/jsx-runtime";
28147
28267
  var styles = {
28148
28268
  container: {
@@ -28179,9 +28299,9 @@ function SwipeableViews({
28179
28299
  const containerRef = useRef33(null);
28180
28300
  const scrollTimeout = useRef33(null);
28181
28301
  const scrollingMethod = useRef33("none");
28182
- const [previousIndex, setPreviousIndex] = useState41(index);
28302
+ const [previousIndex, setPreviousIndex] = useState42(index);
28183
28303
  const hideScrollAnimation = useRef33(true);
28184
- useEffect28(() => {
28304
+ useEffect29(() => {
28185
28305
  if (containerRef.current) {
28186
28306
  if (scrollingMethod.current === "manual") {
28187
28307
  scrollingMethod.current = "none";
@@ -28806,7 +28926,7 @@ var Toolbar_default = Toolbar;
28806
28926
 
28807
28927
  // src/components/toolbar/ToolbarTitle.tsx
28808
28928
  import * as React99 from "react";
28809
- import { useState as useState44 } from "react";
28929
+ import { useState as useState45 } from "react";
28810
28930
  import { jsx as jsx182, jsxs as jsxs89 } from "react/jsx-runtime";
28811
28931
  var ToolbarTitle = React99.forwardRef(function ToolbarTitle2({
28812
28932
  title,
@@ -28818,7 +28938,7 @@ var ToolbarTitle = React99.forwardRef(function ToolbarTitle2({
28818
28938
  const textElementRef = React99.useRef(
28819
28939
  null
28820
28940
  );
28821
- const [showHoverActions, setShowHoverActions] = useState44(false);
28941
+ const [showHoverActions, setShowHoverActions] = useState45(false);
28822
28942
  return /* @__PURE__ */ jsx182(Box_default2, { sx: { maxWidth: "100%" }, children: /* @__PURE__ */ jsx182(
28823
28943
  TextEllipsisTooltip_default,
28824
28944
  {