@festo-ui/react 9.0.1 → 10.0.0-dev.826

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 (150) hide show
  1. package/dist/components/accordion/Accordion.d.ts +3 -3
  2. package/dist/components/accordion/Accordion.js +2 -1
  3. package/dist/components/accordion/accordion-header/AccordionHeader.js +1 -0
  4. package/dist/components/accordion/accordion-item/AccordionItem.d.ts +1 -1
  5. package/dist/components/accordion/accordion-item/AccordionItem.js +2 -1
  6. package/dist/components/accordion/accordion-item/accordion-item-body/AccordionItemBody.js +1 -0
  7. package/dist/components/accordion/accordion-item/accordion-item-header/AccordionItemHeader.js +1 -0
  8. package/dist/components/bottom-sheet/BottomSheet.d.ts +2 -3
  9. package/dist/components/bottom-sheet/BottomSheet.js +7 -4
  10. package/dist/components/breadcrumb/Breadcrumb.d.ts +9 -9
  11. package/dist/components/breadcrumb/Breadcrumb.js +86 -26
  12. package/dist/components/button/Button.js +1 -0
  13. package/dist/components/card/Card.d.ts +3 -4
  14. package/dist/components/card/Card.js +6 -4
  15. package/dist/components/card/CardBody.d.ts +3 -3
  16. package/dist/components/card/CardBody.js +6 -4
  17. package/dist/components/card/CardHeader.d.ts +3 -3
  18. package/dist/components/card/CardHeader.js +6 -4
  19. package/dist/components/card/CardNotification.d.ts +2 -3
  20. package/dist/components/card/CardNotification.js +6 -2
  21. package/dist/components/chips/chip/Chip.d.ts +4 -5
  22. package/dist/components/chips/chip/Chip.js +11 -4
  23. package/dist/components/chips/chip-container/ChipContainer.d.ts +3 -3
  24. package/dist/components/chips/chip-container/ChipContainer.js +6 -2
  25. package/dist/components/icon-wrapper/IconWrapper.d.ts +2 -1
  26. package/dist/components/loading-indicator/LoadingIndicator.d.ts +2 -2
  27. package/dist/components/loading-indicator/LoadingIndicator.js +1 -0
  28. package/dist/components/mobile-flyout/MobileFlyout.js +1 -0
  29. package/dist/components/mobile-flyout/mobile-flyout-item/MobileFlyoutItem.d.ts +1 -0
  30. package/dist/components/mobile-flyout/mobile-flyout-item/MobileFlyoutItem.js +3 -2
  31. package/dist/components/mobile-flyout/mobile-flyout-page/MobileFlyoutPage.js +4 -3
  32. package/dist/components/modals/AlertModal.d.ts +1 -1
  33. package/dist/components/modals/AlertModal.js +5 -4
  34. package/dist/components/modals/ConfirmModal.d.ts +1 -1
  35. package/dist/components/modals/ConfirmModal.js +5 -4
  36. package/dist/components/modals/CustomModal.js +1 -0
  37. package/dist/components/modals/Modal.js +1 -0
  38. package/dist/components/modals/ModalBase.js +1 -0
  39. package/dist/components/modals/ModalFooter.d.ts +2 -2
  40. package/dist/components/modals/ModalFooter.js +3 -1
  41. package/dist/components/modals/Prompt.d.ts +3 -3
  42. package/dist/components/modals/Prompt.js +9 -6
  43. package/dist/components/modals/image-gallery/ImageGallery.css +24 -6
  44. package/dist/components/modals/image-gallery/ImageGallery.d.ts +1 -1
  45. package/dist/components/modals/image-gallery/ImageGallery.js +1 -0
  46. package/dist/components/modals/image-gallery/ImageGallerySwiper.js +1 -1
  47. package/dist/components/modals/image-gallery/internal/ImageGalleryContainer.d.ts +1 -1
  48. package/dist/components/pagination/Pagination.d.ts +3 -4
  49. package/dist/components/pagination/Pagination.js +17 -13
  50. package/dist/components/popovers/legend/Legend.d.ts +6 -4
  51. package/dist/components/popovers/legend/Legend.js +8 -4
  52. package/dist/components/popovers/popover/Popover.css +5 -52
  53. package/dist/components/popovers/popover/Popover.d.ts +12 -14
  54. package/dist/components/popovers/popover/Popover.js +82 -91
  55. package/dist/components/popovers/popover-menu/PopoverMenu.d.ts +6 -4
  56. package/dist/components/popovers/popover-menu/PopoverMenu.js +23 -27
  57. package/dist/components/popovers/popover-menu/PopoverMenuContext.d.ts +2 -1
  58. package/dist/components/popovers/popover-menu/PopoverMenuContext.js +1 -1
  59. package/dist/components/popovers/popover-menu/popover-menu-item/PopoverMenuItem.d.ts +8 -0
  60. package/dist/components/popovers/popover-menu/popover-menu-item/PopoverMenuItem.js +31 -0
  61. package/dist/components/popovers/tooltip/Tooltip.d.ts +4 -3
  62. package/dist/components/popovers/tooltip/Tooltip.js +7 -6
  63. package/dist/components/progress/Progress.d.ts +2 -3
  64. package/dist/components/progress/Progress.js +6 -2
  65. package/dist/components/search-input/ClearButton.d.ts +1 -2
  66. package/dist/components/search-input/ClearButton.js +5 -4
  67. package/dist/components/search-input/SearchInput.d.ts +3 -4
  68. package/dist/components/search-input/SearchInput.js +9 -5
  69. package/dist/components/snackbar/Snackbar.d.ts +4 -4
  70. package/dist/components/snackbar/Snackbar.js +11 -7
  71. package/dist/components/snackbar/SnackbarProvider.d.ts +3 -3
  72. package/dist/components/snackbar/SnackbarProvider.js +7 -4
  73. package/dist/components/stepper-horizontal/StepperHorizontal.d.ts +2 -2
  74. package/dist/components/stepper-horizontal/StepperHorizontal.js +4 -3
  75. package/dist/components/stepper-horizontal/step-horizontal/StepHorizontal.js +2 -1
  76. package/dist/components/stepper-vertical/StepperVertical.js +1 -1
  77. package/dist/components/stepper-vertical/step-vertical/StepVertical.js +1 -0
  78. package/dist/components/tab/Tabs.js +3 -3
  79. package/dist/components/tab/tab-pane/TabPane.d.ts +3 -4
  80. package/dist/components/tab/tab-pane/TabPane.js +6 -2
  81. package/dist/components/table-header-cell/TableHeaderCell.d.ts +2 -1
  82. package/dist/components/table-header-cell/TableHeaderCell.js +1 -0
  83. package/dist/forms/checkbox/Checkbox.d.ts +3 -6
  84. package/dist/forms/checkbox/Checkbox.js +5 -2
  85. package/dist/forms/combobox/ComboBox.css +124 -0
  86. package/dist/forms/combobox/ComboBox.d.ts +27 -0
  87. package/dist/forms/combobox/ComboBox.js +174 -0
  88. package/dist/forms/multi-select/MultiSelect.css +13 -0
  89. package/dist/forms/multi-select/MultiSelect.d.ts +20 -0
  90. package/dist/forms/multi-select/MultiSelect.js +192 -0
  91. package/dist/forms/radio/RadioButton.d.ts +4 -4
  92. package/dist/forms/radio/RadioButton.js +11 -10
  93. package/dist/forms/radio/RadioGroup.d.ts +4 -4
  94. package/dist/forms/radio/RadioGroup.js +1 -0
  95. package/dist/forms/segment/Segment.d.ts +4 -5
  96. package/dist/forms/segment/Segment.js +10 -9
  97. package/dist/forms/segment/segment-control/SegmentControl.d.ts +4 -8
  98. package/dist/forms/segment/segment-control/SegmentControl.js +8 -6
  99. package/dist/forms/select/Select.d.ts +16 -17
  100. package/dist/forms/select/Select.js +80 -82
  101. package/dist/forms/select/internal/SelectButton.d.ts +0 -12
  102. package/dist/forms/select/internal/SelectButton.js +0 -49
  103. package/dist/forms/select/internal/SelectButtonContent.d.ts +0 -7
  104. package/dist/forms/select/internal/SelectButtonContent.js +0 -31
  105. package/dist/forms/select/internal/SelectOptionsContainer.d.ts +0 -17
  106. package/dist/forms/select/internal/SelectOptionsContainer.js +0 -103
  107. package/dist/forms/slider/Slider.d.ts +4 -7
  108. package/dist/forms/slider/Slider.js +11 -6
  109. package/dist/forms/switch/Switch.d.ts +4 -6
  110. package/dist/forms/switch/Switch.js +12 -6
  111. package/dist/forms/text-area/TextArea.d.ts +6 -15
  112. package/dist/forms/text-area/TextArea.js +42 -25
  113. package/dist/forms/text-input/TextInput.css +31 -0
  114. package/dist/forms/text-input/TextInput.d.ts +6 -17
  115. package/dist/forms/text-input/TextInput.js +16 -25
  116. package/dist/forms/time-picker/TimePicker.d.ts +7 -6
  117. package/dist/forms/time-picker/TimePicker.js +16 -31
  118. package/dist/forms/time-picker/time-picker-dropdown/TimePickerDropdown.js +1 -0
  119. package/dist/forms/time-picker/time-picker-dropdown/TimePickerInput.js +1 -0
  120. package/dist/index.d.ts +7 -5
  121. package/dist/index.js +4 -3
  122. package/dist/utils/types.d.ts +0 -6
  123. package/dist/utils/useControlled.js +4 -4
  124. package/dist/utils/useForkRef.d.ts +2 -2
  125. package/dist/utils/useForkRef.js +2 -2
  126. package/dist/utils/useOnClickOutside.d.ts +1 -1
  127. package/package.json +17 -28
  128. package/dist/components/popovers/popover-menu-item/PopoverMenuItem.d.ts +0 -9
  129. package/dist/components/popovers/popover-menu-item/PopoverMenuItem.js +0 -29
  130. package/dist/forms/select/Select.css +0 -160
  131. package/dist/forms/select/internal/HiddenInput.d.ts +0 -8
  132. package/dist/forms/select/internal/HiddenInput.js +0 -15
  133. package/dist/forms/select/internal/ListItem.d.ts +0 -18
  134. package/dist/forms/select/internal/ListItem.js +0 -69
  135. package/dist/forms/select/internal/SelectCheckbox.d.ts +0 -4
  136. package/dist/forms/select/internal/SelectCheckbox.js +0 -13
  137. package/dist/forms/select/internal/SelectLabel.d.ts +0 -7
  138. package/dist/forms/select/internal/SelectLabel.js +0 -12
  139. package/dist/forms/select/internal/SelectScrollContainer.d.ts +0 -8
  140. package/dist/forms/select/internal/SelectScrollContainer.js +0 -15
  141. package/dist/forms/select/internal/SelectWrapper.d.ts +0 -6
  142. package/dist/forms/select/internal/SelectWrapper.js +0 -12
  143. package/dist/forms/select/internal/index.d.ts +0 -6
  144. package/dist/forms/select/internal/index.js +0 -7
  145. package/dist/forms/select/internal/utils.d.ts +0 -7
  146. package/dist/forms/select/internal/utils.js +0 -30
  147. package/dist/forms/select/select-option/SelectOption.d.ts +0 -14
  148. package/dist/forms/select/select-option/SelectOption.js +0 -12
  149. package/dist/forms/select/utils.d.ts +0 -2
  150. package/dist/forms/select/utils.js +0 -12
@@ -6,11 +6,12 @@ const StepHorizontal = /*#__PURE__*/ forwardRef(({ children, className, isActive
6
6
  ref: ref,
7
7
  className: classnames('overflow-hidden', {
8
8
  hidden: !isActive
9
- }),
9
+ }, className),
10
10
  ...props,
11
11
  children: /*#__PURE__*/ jsx("div", {
12
12
  className: "fr-moving-container",
13
13
  children: children
14
14
  })
15
15
  }));
16
+ StepHorizontal.displayName = 'StepHorizontal';
16
17
  export { StepHorizontal };
@@ -7,7 +7,6 @@ const StepperVertical = /*#__PURE__*/ forwardRef(({ children, className, stepInd
7
7
  }
8
8
  const stepComponents = react.Children.map(children, (child, i)=>{
9
9
  if (/*#__PURE__*/ react.isValidElement(child)) return /*#__PURE__*/ react.cloneElement(child, {
10
- ...child.props,
11
10
  isActive: i === stepIndex,
12
11
  index: i,
13
12
  isDone: i < stepIndex,
@@ -23,4 +22,5 @@ const StepperVertical = /*#__PURE__*/ forwardRef(({ children, className, stepInd
23
22
  children: stepComponents
24
23
  });
25
24
  });
25
+ StepperVertical.displayName = 'StepperVertical';
26
26
  export { StepperVertical };
@@ -55,4 +55,5 @@ const StepVertical = /*#__PURE__*/ forwardRef(({ children, className, isActive,
55
55
  ]
56
56
  });
57
57
  });
58
+ StepVertical.displayName = 'StepVertical';
58
59
  export { StepVertical };
@@ -17,8 +17,7 @@ const Tabs = /*#__PURE__*/ forwardRef(({ config, children, className, onChange,
17
17
  let activeId = '';
18
18
  react.Children.forEach(children, (element, i)=>{
19
19
  if (/*#__PURE__*/ react.isValidElement(element)) {
20
- if ('' === activeId) activeId = `${componentId.current}-tab-panel-${i}`;
21
- else if (element.props.active) activeId = `${componentId.current}-tab-panel-${i}`;
20
+ if ('' === activeId || element.props.active) activeId = `${componentId.current}-tab-panel-${i}`;
22
21
  }
23
22
  });
24
23
  const [currentId, setId] = useState(activeId);
@@ -125,7 +124,7 @@ const Tabs = /*#__PURE__*/ forwardRef(({ config, children, className, onChange,
125
124
  })
126
125
  ]
127
126
  }) : /*#__PURE__*/ jsxs("div", {
128
- className: "fr-tab-bar",
127
+ className: classnames('fr-tab-bar', className),
129
128
  role: "tablist",
130
129
  ref: combinedRef,
131
130
  ...props,
@@ -191,4 +190,5 @@ const Tabs = /*#__PURE__*/ forwardRef(({ config, children, className, onChange,
191
190
  })
192
191
  });
193
192
  });
193
+ Tabs.displayName = 'Tabs';
194
194
  export { Tabs };
@@ -1,9 +1,8 @@
1
1
  import './TabPane.scss';
2
- import type { ClassNamePropsWithChildren } from '../../../utils/types';
2
+ import type React from 'react';
3
3
  import type { Tab } from '../interfaces';
4
- export interface TabPaneProps extends ClassNamePropsWithChildren, Tab {
5
- readonly id?: string;
4
+ export interface TabPaneProps extends React.ComponentPropsWithoutRef<'div'>, Tab {
6
5
  readonly isVisible?: boolean;
7
6
  readonly tabId?: string;
8
7
  }
9
- export declare function TabPane({ isVisible, children, className, tabId, id, }: TabPaneProps): import("react/jsx-runtime").JSX.Element;
8
+ export declare const TabPane: (props: TabPaneProps & React.RefAttributes<HTMLDivElement>) => React.ReactElement | null;
@@ -1,7 +1,8 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import "./TabPane.css";
3
3
  import classnames from "classnames";
4
- function TabPane({ isVisible = false, children, className, tabId, id }) {
4
+ import { forwardRef } from "react";
5
+ const TabPane = /*#__PURE__*/ forwardRef(({ isVisible = false, children, className, tabId, id, ...props }, ref)=>{
5
6
  const tabPaneClasses = classnames({
6
7
  'fr-show': isVisible
7
8
  }, {
@@ -12,7 +13,10 @@ function TabPane({ isVisible = false, children, className, tabId, id }) {
12
13
  role: "tabpanel",
13
14
  "aria-labelledby": tabId,
14
15
  className: tabPaneClasses,
16
+ ref: ref,
17
+ ...props,
15
18
  children: children
16
19
  });
17
- }
20
+ });
21
+ TabPane.displayName = 'TabPane';
18
22
  export { TabPane };
@@ -1,4 +1,5 @@
1
- export interface TableHeaderCellProps extends React.ThHTMLAttributes<HTMLTableCellElement> {
1
+ import { type ComponentPropsWithoutRef } from 'react';
2
+ export interface TableHeaderCellProps extends ComponentPropsWithoutRef<'th'> {
2
3
  readonly active?: boolean;
3
4
  readonly ascending: boolean;
4
5
  }
@@ -18,4 +18,5 @@ const TableHeaderCell = /*#__PURE__*/ forwardRef(({ active, ascending, className
18
18
  ref: ref
19
19
  });
20
20
  });
21
+ TableHeaderCell.displayName = 'TableHeaderCell';
21
22
  export { TableHeaderCell };
@@ -1,15 +1,12 @@
1
1
  import './Checkbox.scss';
2
- export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> {
3
- readonly id?: string;
2
+ import { type ComponentPropsWithoutRef } from 'react';
3
+ export interface CheckboxProps extends Omit<ComponentPropsWithoutRef<'input'>, 'type' | 'onChange' | 'checked' | 'defaultChecked'> {
4
4
  readonly checked?: boolean;
5
5
  readonly defaultChecked?: boolean;
6
6
  readonly onChange?: (value: boolean, e: React.ChangeEvent<HTMLInputElement>) => void;
7
- readonly name?: string;
8
7
  readonly large?: boolean;
9
8
  readonly valid?: boolean;
10
9
  readonly labelPosition?: 'before' | 'after' | 'below';
11
- readonly required?: boolean;
12
- readonly disabled?: boolean;
13
10
  readonly indeterminate?: boolean;
14
11
  }
15
- export declare function Checkbox({ id, checked: checkedProp, defaultChecked, onChange, name, large, valid, labelPosition, required, disabled, indeterminate, children, className, ...props }: CheckboxProps): import("react/jsx-runtime").JSX.Element;
12
+ export declare const Checkbox: (props: CheckboxProps & import("react").RefAttributes<HTMLLabelElement>) => React.ReactElement | null;
@@ -1,8 +1,9 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import "./Checkbox.css";
3
3
  import classnames from "classnames";
4
+ import { forwardRef } from "react";
4
5
  import { useControlled } from "../../utils/useControlled.js";
5
- function Checkbox({ id, checked: checkedProp, defaultChecked, onChange, name, large = false, valid = true, labelPosition = 'after', required, disabled = false, indeterminate = false, children, className, ...props }) {
6
+ const Checkbox = /*#__PURE__*/ forwardRef(({ id, checked: checkedProp, defaultChecked, onChange, name, large = false, valid = true, labelPosition = 'after', required, disabled = false, indeterminate = false, children, className, ...props }, ref)=>{
6
7
  const [isChecked, setChecked] = useControlled({
7
8
  controlled: checkedProp,
8
9
  default: defaultChecked ?? false
@@ -30,6 +31,7 @@ function Checkbox({ id, checked: checkedProp, defaultChecked, onChange, name, la
30
31
  return /*#__PURE__*/ jsxs("label", {
31
32
  className: containerClasses,
32
33
  htmlFor: id,
34
+ ref: ref,
33
35
  children: [
34
36
  /*#__PURE__*/ jsx("input", {
35
37
  name: name,
@@ -76,5 +78,6 @@ function Checkbox({ id, checked: checkedProp, defaultChecked, onChange, name, la
76
78
  })
77
79
  ]
78
80
  });
79
- }
81
+ });
82
+ Checkbox.displayName = 'Checkbox';
80
83
  export { Checkbox };
@@ -0,0 +1,124 @@
1
+ .fr-combobox-wrapper {
2
+ width: inherit;
3
+ min-width: 64px;
4
+ font-size: var(--fwe-font-size-base);
5
+ flex-direction: column;
6
+ padding-bottom: 18px;
7
+ display: flex;
8
+ position: relative;
9
+ }
10
+
11
+ .fr-combobox-label {
12
+ height: 18px;
13
+ color: var(--fwe-text);
14
+ font-size: var(--fwe-font-size-small);
15
+ line-height: var(--fwe-line-height-base);
16
+ font-weight: var(--fwe-font-weight-bold);
17
+ order: 1;
18
+ }
19
+
20
+ .fr-combobox-control {
21
+ order: 2;
22
+ position: relative;
23
+ }
24
+
25
+ .fr-combobox-input {
26
+ width: 100%;
27
+ height: 33px;
28
+ font-size: var(--fwe-font-size-base);
29
+ appearance: none;
30
+ border: none;
31
+ border-bottom: 1px solid var(--fwe-control-border);
32
+ white-space: nowrap;
33
+ text-overflow: ellipsis;
34
+ cursor: pointer;
35
+ background: none;
36
+ outline: 0;
37
+ padding: 4px 24px 4px 0;
38
+ display: block;
39
+ overflow: hidden;
40
+ }
41
+
42
+ .fr-combobox-input:hover:not(:disabled), .fr-combobox-input:focus:not(:disabled) {
43
+ color: var(--fwe-hero);
44
+ border-color: var(--fwe-hero);
45
+ }
46
+
47
+ .fr-combobox-button {
48
+ cursor: pointer;
49
+ background-color: var(--fwe-text);
50
+ border: none;
51
+ width: 24px;
52
+ height: 24px;
53
+ padding: 0;
54
+ position: absolute;
55
+ top: 50%;
56
+ right: 0;
57
+ transform: translateY(-50%);
58
+ mask: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgyNHYyNEgweiIgZGF0YS1uYW1lPSJ3aGl0ZSBiYWNrZ3JvdW5kIi8+PHBhdGggZmlsbD0iIzMzMyIgZD0iTTUuNjM2IDkuMTcyIDEyIDE1LjUzNmw2LjM2NC02LjM2NC0uNzA3LS43MDhMMTIgMTQuMTIxIDYuMzQzIDguNDY0bC0uNzA3LjcwOHoiIGRhdGEtbmFtZT0iY29udGVudCIvPjwvc3ZnPg==) center / 24px 24px no-repeat;
59
+ }
60
+
61
+ .fr-combobox-button[aria-expanded="true"] {
62
+ transform: translateY(-50%)rotate(180deg);
63
+ }
64
+
65
+ .fr-combobox-description, .fr-combobox-invalid {
66
+ width: 100%;
67
+ font-size: var(--fwe-font-size-small);
68
+ line-height: var(--fwe-line-height-base);
69
+ position: absolute;
70
+ bottom: 0;
71
+ }
72
+
73
+ .fr-combobox-description {
74
+ color: var(--fwe-text-disabled);
75
+ }
76
+
77
+ .fr-combobox-invalid {
78
+ color: var(--fwe-red);
79
+ display: none;
80
+ }
81
+
82
+ .fr-combobox-wrapper.fr-disabled .fr-combobox-input {
83
+ cursor: default;
84
+ color: var(--fwe-text-disabled);
85
+ border-color: var(--fwe-control-disabled);
86
+ }
87
+
88
+ .fr-combobox-wrapper.fr-disabled .fr-combobox-label {
89
+ color: var(--fwe-text-disabled);
90
+ }
91
+
92
+ .fr-combobox-wrapper.fr-disabled .fr-combobox-button {
93
+ background-color: var(--fwe-text-disabled);
94
+ cursor: default;
95
+ }
96
+
97
+ .fr-combobox-wrapper.fr-invalid .fr-combobox-input {
98
+ border-color: var(--fwe-red);
99
+ }
100
+
101
+ .fr-combobox-wrapper.fr-invalid .fr-combobox-invalid {
102
+ display: block;
103
+ }
104
+
105
+ .fr-combobox-wrapper.fr-invalid .fr-combobox-description {
106
+ display: none;
107
+ }
108
+
109
+ .fwe-combobox-option-content {
110
+ white-space: nowrap;
111
+ text-overflow: ellipsis;
112
+ display: block;
113
+ overflow: hidden;
114
+ }
115
+
116
+ .fwe-combobox-highlight {
117
+ color: var(--fwe-hero);
118
+ }
119
+
120
+ .fwe-combobox-empty {
121
+ cursor: default;
122
+ color: var(--fwe-text-disabled);
123
+ }
124
+
@@ -0,0 +1,27 @@
1
+ import './ComboBox.scss';
2
+ import { type Ref } from 'react';
3
+ export interface ComboBoxOption<T> {
4
+ readonly label: string;
5
+ readonly data: T;
6
+ readonly disabled?: boolean;
7
+ }
8
+ export interface ComboBoxProps<T> extends Omit<React.ComponentPropsWithoutRef<'div'>, 'onChange' | 'value' | 'defaultValue'> {
9
+ readonly value?: T;
10
+ readonly defaultValue?: T;
11
+ readonly name?: string;
12
+ readonly disabled?: boolean;
13
+ readonly required?: boolean;
14
+ readonly label?: string;
15
+ readonly options?: ComboBoxOption<T>[];
16
+ readonly hint?: string;
17
+ readonly error?: string;
18
+ readonly placeholder?: string;
19
+ readonly onChange?: (value: T) => void;
20
+ readonly onInputChange?: (value: string) => void;
21
+ readonly emptyMessage?: string;
22
+ }
23
+ declare function ComboBoxComponent<T>({ defaultValue, value: controlled, label, options, onChange, required, disabled, name, id: idProp, hint, error, placeholder, onInputChange, emptyMessage, className, ...props }: ComboBoxProps<T>, ref: Ref<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
24
+ export declare const ComboBox: <T>(props: ComboBoxProps<T> & {
25
+ ref?: Ref<HTMLDivElement>;
26
+ }) => ReturnType<typeof ComboBoxComponent>;
27
+ export {};
@@ -0,0 +1,174 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import "./ComboBox.css";
3
+ import { Combobox, ComboboxButton, ComboboxInput, ComboboxOption, ComboboxOptions } from "@headlessui/react";
4
+ import classnames from "classnames";
5
+ import { forwardRef, useMemo, useState } from "react";
6
+ import { useControlled } from "../../utils/useControlled.js";
7
+ import { useId } from "../../utils/useId.js";
8
+ function getHighlightedLabel(label, query) {
9
+ if (!query) return [
10
+ {
11
+ text: label,
12
+ highlighted: false
13
+ }
14
+ ];
15
+ const parts = [];
16
+ const lowerLabel = label.toLowerCase();
17
+ const lowerQuery = query.toLowerCase();
18
+ let currentIndex = 0;
19
+ while(currentIndex < label.length){
20
+ const matchIndex = lowerLabel.indexOf(lowerQuery, currentIndex);
21
+ if (-1 === matchIndex) {
22
+ parts.push({
23
+ text: label.slice(currentIndex),
24
+ highlighted: false
25
+ });
26
+ break;
27
+ }
28
+ if (matchIndex > currentIndex) parts.push({
29
+ text: label.slice(currentIndex, matchIndex),
30
+ highlighted: false
31
+ });
32
+ parts.push({
33
+ text: label.slice(matchIndex, matchIndex + query.length),
34
+ highlighted: true
35
+ });
36
+ currentIndex = matchIndex + query.length;
37
+ }
38
+ return parts;
39
+ }
40
+ function ComboBoxComponent({ defaultValue = '', value: controlled, label, options = [], onChange, required = false, disabled, name, id: idProp, hint, error, placeholder, onInputChange, emptyMessage = 'No results found', className, ...props }, ref) {
41
+ const id = useId(idProp);
42
+ const [value, setValue] = useControlled({
43
+ controlled,
44
+ default: defaultValue,
45
+ onChange
46
+ });
47
+ const [query, setQuery] = useState('');
48
+ const selectedOption = useMemo(()=>options.find((option)=>option.data === value && !option.disabled), [
49
+ options,
50
+ value
51
+ ]);
52
+ const filteredOptions = useMemo(()=>{
53
+ if (!query) return options;
54
+ const normalizedQuery = query.toLowerCase();
55
+ return options.filter((option)=>option.label.toLowerCase().includes(normalizedQuery));
56
+ }, [
57
+ options,
58
+ query
59
+ ]);
60
+ function handleChange(option) {
61
+ if (!option || option.disabled) return;
62
+ setValue(option.data);
63
+ setQuery('');
64
+ }
65
+ function handleInputChange(inputValue) {
66
+ setQuery(inputValue);
67
+ onInputChange?.(inputValue);
68
+ }
69
+ const inputClasses = classnames('fr-combobox-input', {
70
+ 'fr-required': required,
71
+ 'fr-disabled': disabled,
72
+ 'fr-invalid': error,
73
+ 'fr-empty': !query && !selectedOption
74
+ });
75
+ return /*#__PURE__*/ jsx(Combobox, {
76
+ value: selectedOption ?? null,
77
+ onChange: handleChange,
78
+ disabled: disabled,
79
+ immediate: true,
80
+ children: /*#__PURE__*/ jsxs("div", {
81
+ className: classnames(className, 'fr-combobox-wrapper', {
82
+ 'fr-disabled': disabled,
83
+ 'fr-invalid': error,
84
+ 'fr-required': required
85
+ }),
86
+ ref: ref,
87
+ ...props,
88
+ children: [
89
+ /*#__PURE__*/ jsx("label", {
90
+ className: "fr-combobox-label",
91
+ htmlFor: id,
92
+ children: label || ''
93
+ }),
94
+ /*#__PURE__*/ jsxs("div", {
95
+ className: "fr-combobox-control",
96
+ children: [
97
+ /*#__PURE__*/ jsx(ComboboxInput, {
98
+ className: inputClasses,
99
+ id: id,
100
+ required: required,
101
+ disabled: disabled,
102
+ placeholder: placeholder,
103
+ autoComplete: "off",
104
+ displayValue: (option)=>option?.label ?? '',
105
+ onChange: (event)=>handleInputChange(event.target.value)
106
+ }),
107
+ /*#__PURE__*/ jsx(ComboboxButton, {
108
+ className: "fr-combobox-button",
109
+ disabled: disabled
110
+ })
111
+ ]
112
+ }),
113
+ name && /*#__PURE__*/ jsx("input", {
114
+ type: "hidden",
115
+ name: name,
116
+ value: String(value ?? ''),
117
+ disabled: disabled
118
+ }),
119
+ /*#__PURE__*/ jsxs(ComboboxOptions, {
120
+ className: "fwe-options-container",
121
+ as: "ul",
122
+ portal: false,
123
+ style: {
124
+ minWidth: 'var(--input-width)'
125
+ },
126
+ anchor: {
127
+ to: 'bottom start',
128
+ gap: 12,
129
+ padding: 8
130
+ },
131
+ children: [
132
+ 0 === filteredOptions.length && /*#__PURE__*/ jsx("li", {
133
+ className: "fwe-combobox-option fwe-combobox-empty",
134
+ children: /*#__PURE__*/ jsx("span", {
135
+ className: "fwe-combobox-option-content",
136
+ children: emptyMessage
137
+ })
138
+ }),
139
+ filteredOptions.map((option)=>/*#__PURE__*/ jsx(ComboboxOption, {
140
+ value: option,
141
+ disabled: option.disabled,
142
+ as: "li",
143
+ className: ({ focus, selected, disabled: isDisabled })=>classnames('fwe-combobox-option', {
144
+ 'fwe-selected': selected,
145
+ 'fwe-focus': focus,
146
+ 'fwe-disabled': isDisabled
147
+ }),
148
+ children: /*#__PURE__*/ jsx("span", {
149
+ className: "fwe-combobox-option-content",
150
+ children: getHighlightedLabel(option.label, query).map((part, index)=>/*#__PURE__*/ jsx("span", {
151
+ className: classnames({
152
+ 'fwe-combobox-highlight': part.highlighted
153
+ }),
154
+ children: part.text
155
+ }, `${part.text}-${index}`))
156
+ })
157
+ }, String(option.data)))
158
+ ]
159
+ }),
160
+ hint && !error && /*#__PURE__*/ jsx("div", {
161
+ className: "fr-combobox-description",
162
+ children: hint
163
+ }),
164
+ error && /*#__PURE__*/ jsx("div", {
165
+ className: "fr-combobox-invalid",
166
+ children: error
167
+ })
168
+ ]
169
+ })
170
+ });
171
+ }
172
+ const ComboBox = /*#__PURE__*/ forwardRef(ComboBoxComponent);
173
+ ComboBox.displayName = 'ComboBox';
174
+ export { ComboBox };
@@ -0,0 +1,13 @@
1
+ .fr-multiselect-chip-container {
2
+ flex-wrap: nowrap;
3
+ gap: 8px;
4
+ display: flex;
5
+ overflow: hidden;
6
+ }
7
+
8
+ .fr-multiselect-chip-ellipsis {
9
+ text-overflow: ellipsis;
10
+ white-space: nowrap;
11
+ overflow: hidden;
12
+ }
13
+
@@ -0,0 +1,20 @@
1
+ import type { Ref } from 'react';
2
+ import type { SelectOption } from '../select/Select';
3
+ import './MultiSelect.scss';
4
+ export interface MultiSelectProps<T> extends Omit<React.ComponentPropsWithoutRef<'div'>, 'onChange' | 'value' | 'defaultValue'> {
5
+ readonly defaultValue?: T[];
6
+ readonly value?: T[];
7
+ readonly label?: string;
8
+ readonly options?: SelectOption<T>[];
9
+ readonly onChange?: (value: T[]) => void;
10
+ readonly disabled?: boolean;
11
+ readonly name?: string;
12
+ readonly hint?: string;
13
+ readonly error?: string;
14
+ readonly placeholder?: string;
15
+ }
16
+ declare function MultiSelectComponent<T>({ defaultValue, value: controlled, label, options, onChange, disabled, name, id: idProp, hint, error, placeholder, className, ...props }: MultiSelectProps<T>, ref: Ref<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
17
+ export declare const MultiSelect: <T>(props: MultiSelectProps<T> & {
18
+ ref?: Ref<HTMLDivElement>;
19
+ }) => ReturnType<typeof MultiSelectComponent>;
20
+ export {};