@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
@@ -1,40 +1,62 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import "./TextArea.css";
3
3
  import classnames from "classnames";
4
- import react, { useEffect, useState } from "react";
4
+ import react, { forwardRef, useEffect, useLayoutEffect, useState } from "react";
5
5
  import { useId } from "../../utils/useId.js";
6
- function TextArea({ disabled, onBlur, onChange, onFocus, onInput, readonly, required, label, error, hint, value, defaultValue, name, rows, maxLength, className, id: idProps }) {
6
+ const TextArea = /*#__PURE__*/ forwardRef(({ onChange, label, error, hint, value, defaultValue, rows, maxLength, className, id: idProps, ...props }, ref)=>{
7
7
  const controlled = void 0 !== value;
8
- const [innerValue, setInnerValue] = useState(controlled ? value : defaultValue);
8
+ const [innerValue, setInnerValue] = useState(controlled ? value : defaultValue ?? '');
9
9
  const id = useId(idProps);
10
10
  const hintClasses = classnames('fwe-input-text-info');
11
11
  const shadowRef = react.useRef(null);
12
- const ref = react.useRef(null);
12
+ const textareaRef = react.useRef(null);
13
13
  const [height, setHeight] = useState(void 0);
14
+ const resizeToContent = react.useCallback(()=>{
15
+ const input = textareaRef.current;
16
+ const shadow = shadowRef.current;
17
+ const minRows = 2;
18
+ if (shadow && input) {
19
+ shadow.value = input.value || innerValue || 'x';
20
+ shadow.style.width = input.clientWidth.toString();
21
+ const newHeight = Math.max(24 * minRows, shadow.scrollHeight);
22
+ setHeight(newHeight + 4 + 4 + 1);
23
+ }
24
+ }, [
25
+ innerValue
26
+ ]);
14
27
  useEffect(()=>{
15
28
  if (controlled) setInnerValue(value);
16
29
  }, [
17
30
  value,
18
31
  controlled
19
32
  ]);
33
+ useLayoutEffect(()=>{
34
+ if (rows) return;
35
+ resizeToContent();
36
+ }, [
37
+ rows,
38
+ resizeToContent
39
+ ]);
20
40
  useEffect(()=>{
21
- const input = ref.current;
22
- const shadow = shadowRef.current;
23
- const minRows = 2;
24
- if (shadow && input) {
25
- shadow.value = input.value || 'x';
26
- shadow.style.width = `${input.clientWidth}`;
27
- const newHeight = Math.max(24 * minRows, shadow.scrollHeight);
28
- setHeight(newHeight + 4 + 4 + 1);
29
- }
30
- }, []);
41
+ if (rows) return;
42
+ const handleResize = ()=>resizeToContent();
43
+ window.addEventListener('resize', handleResize);
44
+ return ()=>{
45
+ window.removeEventListener('resize', handleResize);
46
+ };
47
+ }, [
48
+ rows,
49
+ resizeToContent
50
+ ]);
31
51
  function handleChange(event) {
32
52
  if (!controlled) setInnerValue(event.target.value);
33
- if (onChange) onChange(event);
53
+ if (!rows) resizeToContent();
54
+ if (onChange) onChange(event.target.value, event);
34
55
  }
35
56
  return /*#__PURE__*/ jsxs("label", {
36
57
  className: classnames('fwe-input-text', className),
37
58
  htmlFor: id,
59
+ ref: ref,
38
60
  children: [
39
61
  /*#__PURE__*/ jsx("textarea", {
40
62
  style: {
@@ -43,21 +65,15 @@ function TextArea({ disabled, onBlur, onChange, onFocus, onInput, readonly, requ
43
65
  overflow: 'hidden'
44
66
  }
45
67
  },
46
- ref: ref,
47
- name: name,
68
+ ref: textareaRef,
48
69
  className: classnames('fr-textarea', `fwe-row-${rows}`),
49
- disabled: disabled,
50
- readOnly: readonly,
51
- required: required,
52
70
  autoComplete: "off",
53
71
  onChange: handleChange,
54
- onFocus: onFocus,
55
- onInput: onInput,
56
- onBlur: onBlur,
57
72
  maxLength: maxLength,
58
73
  defaultValue: defaultValue,
59
74
  value: value,
60
- id: id
75
+ id: id,
76
+ ...props
61
77
  }),
62
78
  /*#__PURE__*/ jsx("textarea", {
63
79
  style: {
@@ -95,5 +111,6 @@ function TextArea({ disabled, onBlur, onChange, onFocus, onInput, readonly, requ
95
111
  })
96
112
  ]
97
113
  });
98
- }
114
+ });
115
+ TextArea.displayName = 'TextArea';
99
116
  export { TextArea };
@@ -0,0 +1,31 @@
1
+ label.fwe-input-text input[type="text"][aria-invalid="true"], label.fwe-input-text input[type="password"][aria-invalid="true"], label.fwe-input-text input[type="date"][aria-invalid="true"], label.fwe-input-text input[type="datetime-local"][aria-invalid="true"], label.fwe-input-text input[type="number"][aria-invalid="true"] {
2
+ box-shadow: none;
3
+ outline: none;
4
+ border-bottom: 1px solid var(--fwe-red) !important;
5
+ }
6
+
7
+ label.fwe-input-text input[type="text"][aria-invalid="true"]:focus, label.fwe-input-text input[type="password"][aria-invalid="true"]:focus, label.fwe-input-text input[type="date"][aria-invalid="true"]:focus, label.fwe-input-text input[type="datetime-local"][aria-invalid="true"]:focus, label.fwe-input-text input[type="number"][aria-invalid="true"]:focus {
8
+ border-bottom: 1px solid var(--fwe-red) !important;
9
+ }
10
+
11
+ label.fwe-input-text input[type="text"][aria-invalid="true"]:disabled, label.fwe-input-text input[type="password"][aria-invalid="true"]:disabled, label.fwe-input-text input[type="date"][aria-invalid="true"]:disabled, label.fwe-input-text input[type="datetime-local"][aria-invalid="true"]:disabled, label.fwe-input-text input[type="number"][aria-invalid="true"]:disabled {
12
+ border-bottom: 1px solid var(--fwe-control-disabled) !important;
13
+ }
14
+
15
+ label.fwe-input-text input[type="text"][aria-invalid="true"]:disabled ~ .fwe-input-text-label, label.fwe-input-text input[type="text"][aria-invalid="true"]:disabled ~ .fwe-input-text-invalid, label.fwe-input-text input[type="text"][aria-invalid="true"]:disabled ~ .fwe-input-text-info, label.fwe-input-text input[type="password"][aria-invalid="true"]:disabled ~ .fwe-input-text-label, label.fwe-input-text input[type="password"][aria-invalid="true"]:disabled ~ .fwe-input-text-invalid, label.fwe-input-text input[type="password"][aria-invalid="true"]:disabled ~ .fwe-input-text-info, label.fwe-input-text input[type="date"][aria-invalid="true"]:disabled ~ .fwe-input-text-label, label.fwe-input-text input[type="date"][aria-invalid="true"]:disabled ~ .fwe-input-text-invalid, label.fwe-input-text input[type="date"][aria-invalid="true"]:disabled ~ .fwe-input-text-info, label.fwe-input-text input[type="datetime-local"][aria-invalid="true"]:disabled ~ .fwe-input-text-label, label.fwe-input-text input[type="datetime-local"][aria-invalid="true"]:disabled ~ .fwe-input-text-invalid, label.fwe-input-text input[type="datetime-local"][aria-invalid="true"]:disabled ~ .fwe-input-text-info, label.fwe-input-text input[type="number"][aria-invalid="true"]:disabled ~ .fwe-input-text-label, label.fwe-input-text input[type="number"][aria-invalid="true"]:disabled ~ .fwe-input-text-invalid, label.fwe-input-text input[type="number"][aria-invalid="true"]:disabled ~ .fwe-input-text-info {
16
+ color: var(--fwe-text-disabled);
17
+ }
18
+
19
+ label.fwe-input-text input[type="text"][aria-invalid="true"] ~ .fwe-input-text-info, label.fwe-input-text input[type="password"][aria-invalid="true"] ~ .fwe-input-text-info, label.fwe-input-text input[type="date"][aria-invalid="true"] ~ .fwe-input-text-info, label.fwe-input-text input[type="datetime-local"][aria-invalid="true"] ~ .fwe-input-text-info, label.fwe-input-text input[type="number"][aria-invalid="true"] ~ .fwe-input-text-info {
20
+ display: none;
21
+ }
22
+
23
+ label.fwe-input-text input[type="text"][aria-invalid="true"] ~ .fwe-input-text-invalid, label.fwe-input-text input[type="password"][aria-invalid="true"] ~ .fwe-input-text-invalid, label.fwe-input-text input[type="date"][aria-invalid="true"] ~ .fwe-input-text-invalid, label.fwe-input-text input[type="datetime-local"][aria-invalid="true"] ~ .fwe-input-text-invalid, label.fwe-input-text input[type="number"][aria-invalid="true"] ~ .fwe-input-text-invalid {
24
+ display: block;
25
+ }
26
+
27
+ label.fwe-input-text:has(input:disabled) {
28
+ cursor: not-allowed;
29
+ pointer-events: none;
30
+ }
31
+
@@ -1,24 +1,13 @@
1
- import type React from 'react';
2
- export interface TextInputProps {
3
- disabled?: boolean;
4
- required?: boolean;
1
+ import './TextInput.scss';
2
+ import React, { type ComponentPropsWithoutRef, type ReactNode } from 'react';
3
+ export interface TextInputProps extends Omit<ComponentPropsWithoutRef<'input'>, 'onChange'> {
5
4
  readonly?: boolean;
6
- placeholder?: string;
7
- type?: string;
8
- step?: string;
9
- min?: number;
10
- max?: number;
11
5
  value?: string;
12
6
  defaultValue?: string;
13
- name?: string;
14
- onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
15
- onInput?: (event: React.FormEvent<HTMLInputElement>) => void;
16
- onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
17
7
  label?: string;
18
8
  hint?: string;
19
9
  error?: string;
20
- labelClassName?: string;
21
- icon?: React.ReactNode;
22
- autoFocus?: boolean;
10
+ icon?: ReactNode;
11
+ onChange?: (value: string, event: React.ChangeEvent<HTMLInputElement>) => void;
23
12
  }
24
- export declare const TextInput: (props: TextInputProps & React.HTMLProps<HTMLInputElement> & React.RefAttributes<HTMLLabelElement>) => React.ReactElement | null;
13
+ export declare const TextInput: (props: TextInputProps & React.RefAttributes<HTMLLabelElement>) => React.ReactElement | null;
@@ -1,10 +1,20 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
+ import "./TextInput.css";
2
3
  import classnames from "classnames";
3
4
  import { forwardRef, useEffect, useRef } from "react";
4
5
  import { useId } from "../../utils/useId.js";
5
- const TextInput = /*#__PURE__*/ forwardRef(({ disabled, required, readonly, placeholder, max, min, onBlur, onFocus, onInput, step, type, value, defaultValue, name, error, hint, label, labelClassName, icon, id: idProps, autoFocus, ...props }, ref)=>{
6
+ const SUPPORTED_INPUT_TYPES = [
7
+ 'text',
8
+ 'number',
9
+ 'password',
10
+ 'datetime-local'
11
+ ];
12
+ const TextInput = /*#__PURE__*/ forwardRef(({ readonly, type, value, defaultValue, error, hint, label, icon, onChange, className, id: idProps, autoFocus, ...props }, ref)=>{
6
13
  const id = useId(idProps);
7
14
  const inputRef = useRef(null);
15
+ const handleChange = (e)=>{
16
+ onChange?.(e.target.value, e);
17
+ };
8
18
  useEffect(()=>{
9
19
  if (autoFocus && inputRef.current) {
10
20
  const timer = setTimeout(()=>{
@@ -15,42 +25,22 @@ const TextInput = /*#__PURE__*/ forwardRef(({ disabled, required, readonly, plac
15
25
  }, [
16
26
  autoFocus
17
27
  ]);
18
- const supported = [
19
- 'text',
20
- 'number',
21
- 'password',
22
- 'datetime-local'
23
- ];
24
- const innerType = type && supported.includes(type) ? type : 'text';
28
+ const innerType = type && SUPPORTED_INPUT_TYPES.includes(type) ? type : 'text';
25
29
  const labelClasses = classnames('fwe-input-text', {
26
30
  'fwe-input-text-icon': icon
27
- }, labelClassName);
28
- const hintClasses = classnames('fwe-input-text-info');
29
- function handleChange(e) {
30
- if (props.onChange) props.onChange(e);
31
- }
31
+ }, className);
32
32
  return /*#__PURE__*/ jsxs("label", {
33
33
  className: labelClasses,
34
34
  htmlFor: id,
35
35
  ref: ref,
36
36
  children: [
37
37
  /*#__PURE__*/ jsx("input", {
38
- name: name,
39
- disabled: disabled,
40
- required: required,
41
38
  readOnly: readonly,
42
- placeholder: placeholder,
43
39
  autoComplete: "off",
44
- min: min,
45
- max: max,
46
- step: step,
47
- onChange: handleChange,
48
- onBlur: onBlur,
49
- onFocus: onFocus,
50
- onInput: onInput,
51
40
  type: innerType,
52
41
  value: value,
53
42
  defaultValue: defaultValue,
43
+ onChange: handleChange,
54
44
  id: id,
55
45
  ref: inputRef,
56
46
  ...props
@@ -61,7 +51,7 @@ const TextInput = /*#__PURE__*/ forwardRef(({ disabled, required, readonly, plac
61
51
  children: label
62
52
  }),
63
53
  hint && /*#__PURE__*/ jsx("span", {
64
- className: hintClasses,
54
+ className: "fwe-input-text-info",
65
55
  children: hint
66
56
  }),
67
57
  error && /*#__PURE__*/ jsx("span", {
@@ -71,4 +61,5 @@ const TextInput = /*#__PURE__*/ forwardRef(({ disabled, required, readonly, plac
71
61
  ]
72
62
  });
73
63
  });
64
+ TextInput.displayName = 'TextInput';
74
65
  export { TextInput };
@@ -1,6 +1,5 @@
1
1
  import './TimePicker.scss';
2
2
  import type React from 'react';
3
- import { type ComponentPropsWithoutRef } from 'react';
4
3
  export interface TimePickerOptions {
5
4
  readonly timeFormat?: '12' | '24';
6
5
  readonly showSeconds?: boolean;
@@ -10,13 +9,15 @@ export interface TimePickerOptions {
10
9
  maxValue: Date;
11
10
  };
12
11
  }
13
- export interface TimePickerProps extends Omit<ComponentPropsWithoutRef<'button'>, 'value' | 'defaultValue' | 'onChange'> {
14
- readonly error?: string;
15
- readonly hint?: string;
16
- readonly required?: boolean;
17
- readonly disabled?: boolean;
12
+ export interface TimePickerProps extends Omit<React.ComponentPropsWithoutRef<'button'>, 'onChange' | 'value' | 'defaultValue' | 'children'> {
18
13
  readonly value?: Date;
19
14
  readonly defaultValue?: Date;
15
+ readonly name?: string;
16
+ readonly required?: boolean;
17
+ readonly disabled?: boolean;
18
+ readonly children?: React.ReactNode;
19
+ readonly error?: string;
20
+ readonly hint?: string;
20
21
  readonly options?: TimePickerOptions;
21
22
  readonly formatDate?: (date: Date) => string;
22
23
  readonly onChange?: (date: Date) => void;
@@ -1,14 +1,14 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import "./TimePicker.css";
3
3
  import { IconTime } from "@festo-ui/react-icons";
4
+ import { offset, useFloating } from "@floating-ui/react";
4
5
  import classnames from "classnames";
5
- import { forwardRef, useEffect, useMemo, useRef, useState } from "react";
6
- import react_dom from "react-dom";
7
- import { usePopper } from "react-popper";
6
+ import { forwardRef, useEffect, useRef, useState } from "react";
7
+ import { createPortal } from "react-dom";
8
8
  import { useForkRef } from "../../utils/useForkRef.js";
9
9
  import { useId } from "../../utils/useId.js";
10
10
  import { TimePickerDropdown } from "./time-picker-dropdown/TimePickerDropdown.js";
11
- const TimePicker = /*#__PURE__*/ forwardRef(({ error, hint, required, disabled, children, value, options, defaultValue, formatDate, onChange, id: idProps, ...props }, ref)=>{
11
+ const TimePicker = /*#__PURE__*/ forwardRef(({ error, hint, required, disabled, children, value, options, defaultValue, formatDate, name, onChange, id: idProps, className, ...props }, ref)=>{
12
12
  const id = useId(idProps);
13
13
  const innerFormatDate = formatDate ?? Intl.DateTimeFormat('default', {
14
14
  hour: 'numeric',
@@ -18,34 +18,18 @@ const TimePicker = /*#__PURE__*/ forwardRef(({ error, hint, required, disabled,
18
18
  }
19
19
  }).format;
20
20
  const timeFormat = options?.timeFormat ?? '24';
21
- const [referenceElement, setReferenceElement] = useState(null);
22
- const [popperElement, setPopperElement] = useState(null);
23
- const customModifier = useMemo(()=>({
24
- name: 'offset',
25
- options: {
26
- offset: ({ placement })=>{
27
- if ('bottom' === placement) return [
28
- 0,
29
- -12
30
- ];
31
- return [
32
- 0,
33
- 0
34
- ];
35
- }
36
- }
37
- }), []);
38
- const { styles, attributes } = usePopper(referenceElement, popperElement, {
39
- modifiers: [
40
- customModifier
21
+ const { refs, floatingStyles } = useFloating({
22
+ placement: 'bottom',
23
+ middleware: [
24
+ offset(({ rects })=>-rects.reference.height - 12)
41
25
  ]
42
26
  });
43
27
  const buttonRef = useRef(null);
44
28
  const allRefs = useForkRef(ref, buttonRef);
45
29
  const labelRef = useRef(null);
46
- const combinedLabelRef = useForkRef(labelRef, (r)=>setReferenceElement(r));
30
+ const combinedLabelRef = useForkRef(labelRef, refs.setReference);
47
31
  const timePickerRef = useRef(null);
48
- const combinedTimePickerRef = useForkRef(timePickerRef, (r)=>setPopperElement(r));
32
+ const combinedTimePickerRef = useForkRef(timePickerRef, refs.setFloating);
49
33
  const [open, setOpen] = useState(false);
50
34
  const controlled = void 0 !== value;
51
35
  const initialValue = controlled ? value : defaultValue;
@@ -78,7 +62,7 @@ const TimePicker = /*#__PURE__*/ forwardRef(({ error, hint, required, disabled,
78
62
  ref: allRefs,
79
63
  onClick: toggle,
80
64
  disabled: disabled,
81
- className: "fr-time-picker",
65
+ className: classnames('fr-time-picker', className),
82
66
  ...props,
83
67
  children: /*#__PURE__*/ jsxs("label", {
84
68
  htmlFor: id,
@@ -95,6 +79,7 @@ const TimePicker = /*#__PURE__*/ forwardRef(({ error, hint, required, disabled,
95
79
  id: id,
96
80
  "aria-label": "picked time",
97
81
  type: "text",
82
+ name: name,
98
83
  readOnly: true,
99
84
  required: required,
100
85
  className: classnames({
@@ -118,7 +103,7 @@ const TimePicker = /*#__PURE__*/ forwardRef(({ error, hint, required, disabled,
118
103
  ]
119
104
  })
120
105
  }),
121
- open && /*#__PURE__*/ react_dom.createPortal(/*#__PURE__*/ jsx(TimePickerDropdown, {
106
+ open && /*#__PURE__*/ createPortal(/*#__PURE__*/ jsx(TimePickerDropdown, {
122
107
  labelRef: labelRef,
123
108
  ref: combinedTimePickerRef,
124
109
  onClose: handleClose,
@@ -129,12 +114,12 @@ const TimePicker = /*#__PURE__*/ forwardRef(({ error, hint, required, disabled,
129
114
  range: options?.range,
130
115
  date: innerValue,
131
116
  style: {
132
- ...styles.popper,
117
+ ...floatingStyles,
133
118
  minWidth: labelRef?.current?.scrollWidth
134
- },
135
- ...attributes.popper
119
+ }
136
120
  }), container.body)
137
121
  ]
138
122
  });
139
123
  });
124
+ TimePicker.displayName = 'TimePicker';
140
125
  export { TimePicker };
@@ -205,4 +205,5 @@ const TimePickerDropdown = /*#__PURE__*/ forwardRef(({ timeFormat, date, onDateC
205
205
  ]
206
206
  });
207
207
  });
208
+ TimePickerDropdown.displayName = 'TimePickerDropdown';
208
209
  export { TimePickerDropdown };
@@ -11,4 +11,5 @@ const TimePickerInput = /*#__PURE__*/ forwardRef(({ min, max, value, onInput, 'a
11
11
  onInput: onInput,
12
12
  ref: ref
13
13
  }));
14
+ TimePickerInput.displayName = 'TimePickerInput';
14
15
  export { TimePickerInput };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export type { Placement } from '@floating-ui/react';
1
2
  export { Accordion, type AccordionProps, } from './components/accordion/Accordion';
2
3
  export { AccordionHeader } from './components/accordion/accordion-header/AccordionHeader';
3
4
  export { AccordionItem, type AccordionItemProps, } from './components/accordion/accordion-item/AccordionItem';
@@ -25,11 +26,11 @@ export { ImageGallerySwiper, type ImageGallerySwiperProps, } from './components/
25
26
  export { ImageGalleryThumbsSwiper, type ImageGalleryThumbsSwiperProps, } from './components/modals/image-gallery/ImageGalleryThumbsSwiper';
26
27
  export { Prompt, type PromptProps } from './components/modals/Prompt';
27
28
  export { Pagination, type PaginationProps, type PaginationType, } from './components/pagination/Pagination';
28
- export { Legend, type LegendProps, type PopoverLegendItem, } from './components/popovers/legend/Legend';
29
+ export { Legend, type LegendItem, type LegendProps, } from './components/popovers/legend/Legend';
29
30
  export { Popover, type PopoverProps, } from './components/popovers/popover/Popover';
30
31
  export { PopoverMenu, type PopoverMenuProps, } from './components/popovers/popover-menu/PopoverMenu';
31
32
  export { PopoverMenuContext } from './components/popovers/popover-menu/PopoverMenuContext';
32
- export { PopoverMenuItem, type PopoverMenuItemProps, } from './components/popovers/popover-menu-item/PopoverMenuItem';
33
+ export { PopoverMenuItem, type PopoverMenuItemProps, } from './components/popovers/popover-menu/popover-menu-item/PopoverMenuItem';
33
34
  export { Tooltip, type TooltipProps, } from './components/popovers/tooltip/Tooltip';
34
35
  export { Progress, type ProgressProps } from './components/progress/Progress';
35
36
  export { SearchInput, type SearchInputProps, } from './components/search-input/SearchInput';
@@ -45,12 +46,13 @@ export { type TabItemAppearance, Tabs, type TabsConfiguration, type TabsProps, t
45
46
  export { TabPane, type TabPaneProps } from './components/tab/tab-pane/TabPane';
46
47
  export { TableHeaderCell, type TableHeaderCellProps, } from './components/table-header-cell/TableHeaderCell';
47
48
  export { Checkbox, type CheckboxProps } from './forms/checkbox/Checkbox';
48
- export { RadioButton, type RadioButtonProps as RadioProps, } from './forms/radio/RadioButton';
49
+ export { ComboBox, type ComboBoxOption, type ComboBoxProps, } from './forms/combobox/ComboBox';
50
+ export { MultiSelect, type MultiSelectProps, } from './forms/multi-select/MultiSelect';
51
+ export { RadioButton, type RadioButtonProps, } from './forms/radio/RadioButton';
49
52
  export { RadioGroup, type RadioGroupProps } from './forms/radio/RadioGroup';
50
53
  export { Segment, type SegmentConfiguration, type SegmentProps, } from './forms/segment/Segment';
51
54
  export { SegmentControl, type SegmentControlProps, } from './forms/segment/segment-control/SegmentControl';
52
- export { Select, type SelectProps } from './forms/select/Select';
53
- export { SelectOption, type SelectOptionProps, type SelectOptionType, } from './forms/select/select-option/SelectOption';
55
+ export { Select, type SelectOption, type SelectProps, } from './forms/select/Select';
54
56
  export { Slider, type SliderProps } from './forms/slider/Slider';
55
57
  export { Switch, type SwitchProps } from './forms/switch/Switch';
56
58
  export { TextArea, type TextAreaProps } from './forms/text-area/TextArea';
package/dist/index.js CHANGED
@@ -29,7 +29,7 @@ import { Legend } from "./components/popovers/legend/Legend.js";
29
29
  import { Popover } from "./components/popovers/popover/Popover.js";
30
30
  import { PopoverMenu } from "./components/popovers/popover-menu/PopoverMenu.js";
31
31
  import { PopoverMenuContext } from "./components/popovers/popover-menu/PopoverMenuContext.js";
32
- import { PopoverMenuItem } from "./components/popovers/popover-menu-item/PopoverMenuItem.js";
32
+ import { PopoverMenuItem } from "./components/popovers/popover-menu/popover-menu-item/PopoverMenuItem.js";
33
33
  import { Tooltip } from "./components/popovers/tooltip/Tooltip.js";
34
34
  import { Progress } from "./components/progress/Progress.js";
35
35
  import { SearchInput } from "./components/search-input/SearchInput.js";
@@ -45,15 +45,16 @@ import { Tabs } from "./components/tab/Tabs.js";
45
45
  import { TabPane } from "./components/tab/tab-pane/TabPane.js";
46
46
  import { TableHeaderCell } from "./components/table-header-cell/TableHeaderCell.js";
47
47
  import { Checkbox } from "./forms/checkbox/Checkbox.js";
48
+ import { ComboBox } from "./forms/combobox/ComboBox.js";
49
+ import { MultiSelect } from "./forms/multi-select/MultiSelect.js";
48
50
  import { RadioButton } from "./forms/radio/RadioButton.js";
49
51
  import { RadioGroup } from "./forms/radio/RadioGroup.js";
50
52
  import { Segment } from "./forms/segment/Segment.js";
51
53
  import { SegmentControl } from "./forms/segment/segment-control/SegmentControl.js";
52
54
  import { Select } from "./forms/select/Select.js";
53
- import { SelectOption } from "./forms/select/select-option/SelectOption.js";
54
55
  import { Slider } from "./forms/slider/Slider.js";
55
56
  import { Switch } from "./forms/switch/Switch.js";
56
57
  import { TextArea } from "./forms/text-area/TextArea.js";
57
58
  import { TextInput } from "./forms/text-input/TextInput.js";
58
59
  import { TimePicker } from "./forms/time-picker/TimePicker.js";
59
- export { Accordion, AccordionHeader, AccordionItem, AccordionItemBody, AccordionItemHeader, AlertModal, BottomSheet, Breadcrumb, Button, Card, CardBody, CardHeader, CardNotification, Checkbox, Chip, ChipContainer, ChipType, ConfirmModal, CustomModal, ImageGallery, ImageGalleryContent, ImageGallerySwiper, ImageGalleryThumbsSwiper, Legend, LoadingIndicator, MobileFlyout, MobileFlyoutItem, MobileFlyoutPage, Pagination, Popover, PopoverMenu, PopoverMenuContext, PopoverMenuItem, Progress, Prompt, RadioButton, RadioGroup, SearchInput, SearchSuggestion, Segment, SegmentControl, Select, SelectOption, Slider, Snackbar, SnackbarProvider, StepHorizontal, StepVertical, StepperHorizontal, StepperVertical, Switch, TabPane, TableHeaderCell, Tabs, TextArea, TextInput, TimePicker, Tooltip, addSnackbar, useSnackbar };
60
+ export { Accordion, AccordionHeader, AccordionItem, AccordionItemBody, AccordionItemHeader, AlertModal, BottomSheet, Breadcrumb, Button, Card, CardBody, CardHeader, CardNotification, Checkbox, Chip, ChipContainer, ChipType, ComboBox, ConfirmModal, CustomModal, ImageGallery, ImageGalleryContent, ImageGallerySwiper, ImageGalleryThumbsSwiper, Legend, LoadingIndicator, MobileFlyout, MobileFlyoutItem, MobileFlyoutPage, MultiSelect, Pagination, Popover, PopoverMenu, PopoverMenuContext, PopoverMenuItem, Progress, Prompt, RadioButton, RadioGroup, SearchInput, SearchSuggestion, Segment, SegmentControl, Select, Slider, Snackbar, SnackbarProvider, StepHorizontal, StepVertical, StepperHorizontal, StepperVertical, Switch, TabPane, TableHeaderCell, Tabs, TextArea, TextInput, TimePicker, Tooltip, addSnackbar, useSnackbar };
@@ -1,9 +1,3 @@
1
- export interface ClassNameProps {
2
- className?: string;
3
- }
4
- export interface ClassNamePropsWithChildren extends ClassNameProps {
5
- children?: React.ReactNode;
6
- }
7
1
  export interface Image {
8
2
  src: string;
9
3
  alt: string;
@@ -1,16 +1,16 @@
1
1
  import { useCallback, useRef, useState } from "react";
2
2
  function useControlled({ controlled, default: defaultValue, onChange }) {
3
3
  const { current: isControlled } = useRef(void 0 !== controlled);
4
- const [valueState, setValue] = useState(defaultValue);
4
+ const [valueState, setValueState] = useState(defaultValue);
5
5
  const value = isControlled ? controlled : valueState;
6
6
  const setValueIfUncontrolled = useCallback((newValue)=>{
7
- if (!isControlled) setValue(newValue);
7
+ if (!isControlled) setValueState(newValue);
8
8
  const setter = newValue;
9
9
  const onChangeValue = 'function' == typeof newValue ? setter(controlled) : newValue;
10
10
  onChange?.(onChangeValue);
11
11
  }, [
12
- controlled,
13
- onChange
12
+ onChange,
13
+ controlled
14
14
  ]);
15
15
  return [
16
16
  value,
@@ -1,2 +1,2 @@
1
- import React from 'react';
2
- export declare function useForkRef<T>(refA: React.Ref<T> | null | undefined, refB: React.Ref<T> | null | undefined): React.RefCallback<T> | null;
1
+ import { type Ref, type RefCallback } from 'react';
2
+ export declare function useForkRef<T>(refA: Ref<T> | null | undefined, refB: Ref<T> | null | undefined): RefCallback<T> | null;
@@ -1,7 +1,7 @@
1
- import react from "react";
1
+ import { useMemo } from "react";
2
2
  import { setRef } from "./setRef.js";
3
3
  function useForkRef(refA, refB) {
4
- return react.useMemo(()=>{
4
+ return useMemo(()=>{
5
5
  if (null == refA && (null == refB || void 0 === refB)) return null;
6
6
  return (instance)=>{
7
7
  setRef(refA, instance);
@@ -1,2 +1,2 @@
1
1
  import { type RefObject } from 'react';
2
- export declare function useOnClickOutside(ref: RefObject<HTMLElement>, callback: (event: MouseEvent | TouchEvent) => void, ref2?: RefObject<HTMLElement>): void;
2
+ export declare function useOnClickOutside(ref: RefObject<HTMLElement | null>, callback: (event: MouseEvent | TouchEvent) => void, ref2?: RefObject<HTMLElement | null>): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@festo-ui/react",
3
- "version": "9.0.1",
3
+ "version": "10.0.0-dev.826",
4
4
  "author": "Festo UI (styleguide@festo.com)",
5
5
  "copyright": "Copyright (c) 2025 Festo SE & Co. KG. All rights reserved.",
6
6
  "license": "apache-2.0",
@@ -34,17 +34,16 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@festo-ui/react-icons": "*",
37
- "@popperjs/core": "^2.11.0",
37
+ "@floating-ui/react": "^0.26.0",
38
+ "@headlessui/react": "^2.2.9",
38
39
  "classnames": "^2.2.6",
39
- "react-popper": "^2.3.0",
40
- "react-remove-scroll": "^2.5.7",
41
- "react-transition-group": "^4.4.2",
40
+ "react-remove-scroll": "^2.7.2",
41
+ "react-transition-group": "^4.4.5",
42
42
  "swiper": "^12.0.3"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@biomejs/biome": "2.3.2",
46
- "@chromatic-com/storybook": "^4.1.1",
47
- "@cyclonedx/cyclonedx-npm": "^1.19.3",
46
+ "@chromatic-com/storybook": "^5.0.0",
48
47
  "@rsbuild/core": "~1.6.2",
49
48
  "@rsbuild/plugin-react": "^1.4.1",
50
49
  "@rsbuild/plugin-sass": "^1.4.0",
@@ -52,38 +51,28 @@
52
51
  "@rslib/core": "^0.17.1",
53
52
  "@rstest/core": "^0.6.5",
54
53
  "@rstest/coverage-istanbul": "^0.0.5",
55
- "@storybook/addon-docs": "^9.1.16",
56
- "@storybook/addon-links": "^9.1.10",
57
- "@storybook/addon-webpack5-compiler-babel": "^3.0.6",
58
- "@storybook/preset-scss": "^1.0.3",
59
- "@storybook/react": "^9.1.16",
54
+ "@storybook/addon-docs": "^10.2.3",
60
55
  "@testing-library/dom": "^10.4.0",
61
56
  "@testing-library/jest-dom": "^6.9.1",
62
57
  "@testing-library/react": "^16.3.0",
63
58
  "@testing-library/user-event": "^14.6.1",
64
- "@types/react": "^18.2.0",
65
- "@types/react-dom": "^18.2.0",
59
+ "@types/react": "^19.2.0",
60
+ "@types/react-dom": "^19.2.0",
66
61
  "@types/react-transition-group": "^4.4.5",
67
- "autoprefixer": "^10.4.13",
68
- "cross-env": "^7.0.3",
69
- "css-minimizer-webpack-plugin": "^4.2.2",
62
+ "cross-env": "^10.1.0",
70
63
  "jsdom": "^26.1.0",
71
- "mini-css-extract-plugin": "^2.9.2",
72
64
  "postcss": "^8.4.49",
73
- "postcss-loader": "^8.1.1",
74
- "react": "^18.2.0",
75
- "react-dom": "^18.2.0",
65
+ "react": "^19.2.0",
66
+ "react-dom": "^19.2.0",
76
67
  "sass": "^1.82.0",
77
- "sass-loader": "^16.0.4",
78
- "storybook": "^9.1.16",
79
- "storybook-addon-rslib": "^2.1.3",
80
- "storybook-react-rsbuild": "^2.1.3",
81
- "ts-loader": "^9.4.2",
68
+ "storybook": "^10.2.3",
69
+ "storybook-addon-rslib": "^3.2.2",
70
+ "storybook-react-rsbuild": "^3.2.2",
82
71
  "typescript": "^5.9.3"
83
72
  },
84
73
  "peerDependencies": {
85
74
  "@festo-ui/web-essentials": "*",
86
- "react": ">=17.0.0",
87
- "react-dom": ">=17.0.0"
75
+ "react": ">=18.0.0",
76
+ "react-dom": ">=18.0.0"
88
77
  }
89
78
  }
@@ -1,9 +0,0 @@
1
- export interface PopoverMenuItemProps {
2
- text: string;
3
- icon: React.ReactNode;
4
- action?: (data: unknown) => void;
5
- data?: unknown;
6
- }
7
- export declare function PopoverMenuItem({ item, }: Readonly<{
8
- item: PopoverMenuItemProps;
9
- }>): import("react/jsx-runtime").JSX.Element | null;