@festo-ui/react 5.0.1 → 5.1.0-dev.164

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 (144) hide show
  1. package/index.css +2 -2
  2. package/index.d.ts +4 -0
  3. package/index.js +4 -0
  4. package/lib/components/accordion/Accordion.d.ts +1 -1
  5. package/lib/components/accordion/Accordion.js +1 -1
  6. package/lib/components/accordion/accordion-header/AccordionHeader.d.ts +1 -1
  7. package/lib/components/accordion/accordion-item/AccordionItem.d.ts +1 -1
  8. package/lib/components/accordion/accordion-item/accordion-item-body/AccordionItemBody.d.ts +1 -1
  9. package/lib/components/accordion/accordion-item/accordion-item-header/AccordionItemHeader.d.ts +1 -1
  10. package/lib/components/loading-indicator/LoadingIndicator.d.ts +1 -1
  11. package/lib/components/mobile-flyout/MobileFlyout.d.ts +12 -0
  12. package/lib/components/mobile-flyout/MobileFlyout.js +83 -0
  13. package/lib/components/mobile-flyout/MobileFlyoutContext.d.ts +9 -0
  14. package/lib/components/mobile-flyout/MobileFlyoutContext.js +2 -0
  15. package/lib/components/mobile-flyout/mobile-flyout-item/MobileFlyoutItem.d.ts +19 -0
  16. package/lib/components/mobile-flyout/mobile-flyout-item/MobileFlyoutItem.js +54 -0
  17. package/lib/components/mobile-flyout/mobile-flyout-page/MobileFlyoutPage.d.ts +8 -0
  18. package/lib/components/mobile-flyout/mobile-flyout-page/MobileFlyoutPage.js +47 -0
  19. package/lib/components/modals/Modal.d.ts +5 -7
  20. package/lib/components/modals/Modal.js +28 -61
  21. package/lib/components/modals/ModalBase.d.ts +9 -0
  22. package/lib/components/modals/ModalBase.js +68 -0
  23. package/lib/components/modals/ModalFooter.d.ts +1 -1
  24. package/lib/components/modals/imageGallery/BaseGallery.d.ts +18 -0
  25. package/lib/components/modals/imageGallery/BaseGallery.js +77 -0
  26. package/lib/components/modals/imageGallery/ImageGallery.d.ts +15 -0
  27. package/lib/components/modals/imageGallery/ImageGallery.helper.d.ts +3 -0
  28. package/lib/components/modals/imageGallery/ImageGallery.helper.js +11 -0
  29. package/lib/components/modals/imageGallery/ImageGallery.js +77 -0
  30. package/lib/components/modals/imageGallery/ImageGallery.stories.helper.d.ts +3 -0
  31. package/lib/components/modals/imageGallery/ImageGallery.stories.helper.js +108 -0
  32. package/lib/components/modals/imageGallery/ImageGalleryContent.d.ts +10 -0
  33. package/lib/components/modals/imageGallery/ImageGalleryContent.js +16 -0
  34. package/lib/components/modals/imageGallery/ImageGalleryPagination.d.ts +8 -0
  35. package/lib/components/modals/imageGallery/ImageGalleryPagination.js +30 -0
  36. package/lib/components/modals/imageGallery/useClasses.d.ts +0 -0
  37. package/lib/components/modals/imageGallery/useClasses.js +0 -0
  38. package/lib/components/snackbar/SnackbarProvider.js +4 -4
  39. package/lib/components/stepper-horizontal/StepperHorizontal.d.ts +1 -1
  40. package/lib/components/stepper-horizontal/StepperHorizontal.js +1 -1
  41. package/lib/components/stepper-horizontal/step-horizontal/StepHorizontal.d.ts +1 -1
  42. package/lib/components/stepper-vertical/StepperVertical.d.ts +1 -1
  43. package/lib/components/stepper-vertical/StepperVertical.js +1 -1
  44. package/lib/components/stepper-vertical/step-vertical/StepVertical.d.ts +1 -1
  45. package/lib/components/tab/Tabs.d.ts +1 -1
  46. package/lib/components/tab/Tabs.js +3 -0
  47. package/lib/components/tab/useTabScroll.js +0 -1
  48. package/lib/components/table-header-cell/TableHeaderCell.d.ts +1 -1
  49. package/lib/components/table-header-cell/TableHeaderCell.js +10 -4
  50. package/lib/forms/checkbox/Checkbox.d.ts +5 -4
  51. package/lib/forms/checkbox/Checkbox.js +16 -18
  52. package/lib/forms/radio/RadioGroup.js +1 -1
  53. package/lib/forms/select/Select.d.ts +4 -10
  54. package/lib/forms/select/Select.js +96 -126
  55. package/lib/forms/select/list-item/ListItem.d.ts +6 -0
  56. package/lib/forms/select/list-item/ListItem.js +24 -0
  57. package/lib/forms/select/select-option/SelectOption.d.ts +2 -2
  58. package/lib/forms/select/utils.d.ts +2 -0
  59. package/lib/forms/select/utils.js +17 -0
  60. package/lib/forms/text-editor/TextEditor.d.ts +2 -1
  61. package/lib/forms/text-editor/TextEditor.js +29 -14
  62. package/lib/forms/text-input/TextInput.d.ts +1 -1
  63. package/lib/forms/time-picker/TimePicker.d.ts +1 -1
  64. package/lib/forms/time-picker/time-picker-dropdown/TimePickerDropdown.d.ts +1 -1
  65. package/lib/helper/types.d.ts +17 -0
  66. package/lib/helper/useId.js +2 -1
  67. package/node/index.js +30 -2
  68. package/node/lib/components/accordion/Accordion.js +2 -3
  69. package/node/lib/components/accordion/AccordionContext.js +1 -2
  70. package/node/lib/components/accordion/accordion-header/AccordionHeader.js +1 -2
  71. package/node/lib/components/accordion/accordion-item/AccordionItem.js +1 -2
  72. package/node/lib/components/accordion/accordion-item/AccordionItemContext.js +1 -2
  73. package/node/lib/components/accordion/accordion-item/accordion-item-body/AccordionItemBody.js +1 -2
  74. package/node/lib/components/accordion/accordion-item/accordion-item-header/AccordionItemHeader.js +1 -2
  75. package/node/lib/components/breadcrumb/Breadcrumb.js +1 -2
  76. package/node/lib/components/buttons/button/Button.js +1 -2
  77. package/node/lib/components/card/Card.js +1 -2
  78. package/node/lib/components/card/CardBody.js +1 -2
  79. package/node/lib/components/card/CardHeader.js +1 -2
  80. package/node/lib/components/card/CardNotification.js +1 -2
  81. package/node/lib/components/chips/chip/Chip.js +2 -4
  82. package/node/lib/components/chips/chip-container/ChipContainer.js +1 -2
  83. package/node/lib/components/link-button/LinkButton.js +1 -2
  84. package/node/lib/components/loading-indicator/LoadingIndicator.js +2 -4
  85. package/node/lib/components/mobile-flyout/MobileFlyout.js +89 -0
  86. package/node/lib/components/mobile-flyout/MobileFlyoutContext.js +8 -0
  87. package/node/lib/components/mobile-flyout/mobile-flyout-item/MobileFlyoutItem.js +77 -0
  88. package/node/lib/components/mobile-flyout/mobile-flyout-page/MobileFlyoutPage.js +53 -0
  89. package/node/lib/components/modals/AlertModal.js +1 -2
  90. package/node/lib/components/modals/ConfirmModal.js +1 -2
  91. package/node/lib/components/modals/Modal.js +30 -63
  92. package/node/lib/components/modals/ModalBase.js +73 -0
  93. package/node/lib/components/modals/ModalFooter.js +1 -2
  94. package/node/lib/components/modals/Prompt.js +2 -2
  95. package/node/lib/components/modals/imageGallery/BaseGallery.js +83 -0
  96. package/node/lib/components/modals/imageGallery/ImageGallery.helper.js +18 -0
  97. package/node/lib/components/modals/imageGallery/ImageGallery.js +82 -0
  98. package/node/lib/components/modals/imageGallery/ImageGallery.stories.helper.js +123 -0
  99. package/node/lib/components/modals/imageGallery/ImageGalleryContent.js +20 -0
  100. package/node/lib/components/modals/imageGallery/ImageGalleryPagination.js +34 -0
  101. package/node/lib/components/modals/imageGallery/useClasses.js +1 -0
  102. package/node/lib/components/pagination/Pagination.js +4 -6
  103. package/node/lib/components/popovers/legend/Legend.js +1 -2
  104. package/node/lib/components/popovers/popover/Popover.js +3 -4
  105. package/node/lib/components/popovers/popover-menu/PopoverMenu.js +1 -2
  106. package/node/lib/components/popovers/tooltip/Tooltip.js +1 -2
  107. package/node/lib/components/progress/Progress.js +1 -2
  108. package/node/lib/components/search-input/SearchInput.js +1 -2
  109. package/node/lib/components/snackbar/Snackbar.js +1 -2
  110. package/node/lib/components/snackbar/SnackbarContext.js +1 -2
  111. package/node/lib/components/snackbar/SnackbarProvider.js +4 -5
  112. package/node/lib/components/stepper-horizontal/StepperHorizontal.js +5 -6
  113. package/node/lib/components/stepper-horizontal/step-horizontal/StepHorizontal.js +1 -2
  114. package/node/lib/components/stepper-vertical/StepperVertical.js +5 -6
  115. package/node/lib/components/stepper-vertical/step-vertical/StepVertical.js +1 -2
  116. package/node/lib/components/tab/Tabs.js +5 -4
  117. package/node/lib/components/tab/tab-pane/TabPane.js +1 -2
  118. package/node/lib/components/tab/useTabScroll.js +3 -2
  119. package/node/lib/components/table-header-cell/TableHeaderCell.js +11 -6
  120. package/node/lib/forms/checkbox/Checkbox.js +17 -22
  121. package/node/lib/forms/color-indicator/ColorIndicator.js +3 -4
  122. package/node/lib/forms/color-picker/ColorPicker.js +4 -6
  123. package/node/lib/forms/date-picker/DatePicker.js +1 -2
  124. package/node/lib/forms/date-range-picker/DateRangePicker.js +1 -2
  125. package/node/lib/forms/radio/RadioButton.js +1 -2
  126. package/node/lib/forms/radio/RadioGroup.js +2 -3
  127. package/node/lib/forms/radio/RadioGroupContext.js +1 -2
  128. package/node/lib/forms/segment/Segment.js +1 -2
  129. package/node/lib/forms/segment/segment-control/SegmentControl.js +3 -4
  130. package/node/lib/forms/select/Select.js +99 -130
  131. package/node/lib/forms/select/list-item/ListItem.js +33 -0
  132. package/node/lib/forms/select/select-option/SelectOption.js +4 -6
  133. package/node/lib/forms/select/utils.js +23 -0
  134. package/node/lib/forms/slider/Slider.js +3 -4
  135. package/node/lib/forms/switch/Switch.js +1 -2
  136. package/node/lib/forms/text-area/TextArea.js +3 -4
  137. package/node/lib/forms/text-editor/TextEditor.js +29 -15
  138. package/node/lib/forms/text-editor/TextEditorButton.js +1 -2
  139. package/node/lib/forms/text-input/TextInput.js +3 -4
  140. package/node/lib/forms/time-picker/TimePicker.js +3 -4
  141. package/node/lib/forms/time-picker/time-picker-dropdown/TimePickerDropdown.js +3 -4
  142. package/node/lib/helper/index.js +1 -2
  143. package/node/lib/helper/useId.js +2 -1
  144. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { useMemo, useState } from 'react';
1
+ import { useCallback, useMemo, useState } from 'react';
2
2
  import classNames from 'classnames';
3
3
  import Snackbar from './Snackbar';
4
4
  import SnackbarContext from './SnackbarContext';
@@ -13,7 +13,7 @@ function SnackbarProvider(props) {
13
13
  className
14
14
  } = props;
15
15
  const [snacks, setSnacks] = useState([]);
16
- function addSnackbar(snackData, onAction, onClose) {
16
+ const addSnackbar = useCallback((snackData, onAction, onClose) => {
17
17
  const key = snackData.key ?? new Date().getTime() + Math.random();
18
18
  setSnacks(prevSnacks => [{
19
19
  data: {
@@ -26,7 +26,7 @@ function SnackbarProvider(props) {
26
26
  first: prevSnacks.length === 0
27
27
  }, ...prevSnacks]);
28
28
  return key;
29
- }
29
+ }, [config]);
30
30
  function closeSnackbar(key) {
31
31
  if (key !== undefined) {
32
32
  setSnacks(prevSnacks => prevSnacks.filter(snack => snack.key !== key));
@@ -41,7 +41,7 @@ function SnackbarProvider(props) {
41
41
  const contextValue = useMemo(() => ({
42
42
  addSnackbar,
43
43
  closeSnackbar
44
- }), []);
44
+ }), [addSnackbar]);
45
45
  return /*#__PURE__*/_jsxs(SnackbarContext.Provider, {
46
46
  value: contextValue,
47
47
  children: [children, /*#__PURE__*/_jsx("div", {
@@ -3,5 +3,5 @@ interface StepperHorizontalProps extends Omit<ComponentPropsWithoutRef<'div'>, '
3
3
  stepIndex?: number;
4
4
  onChange?: (stepIndex: number) => void;
5
5
  }
6
- declare const StepperHorizontal: React.ForwardRefExoticComponent<StepperHorizontalProps & React.RefAttributes<HTMLDivElement>>;
6
+ export declare const StepperHorizontal: (props: StepperHorizontalProps & React.RefAttributes<HTMLDivElement>) => React.ReactElement<any, string | React.JSXElementConstructor<any>> | null;
7
7
  export default StepperHorizontal;
@@ -3,7 +3,7 @@ import React, { forwardRef } from 'react';
3
3
  import { jsx as _jsx } from "react/jsx-runtime";
4
4
  import { jsxs as _jsxs } from "react/jsx-runtime";
5
5
  import { Fragment as _Fragment } from "react/jsx-runtime";
6
- const StepperHorizontal = /*#__PURE__*/forwardRef((_ref, ref) => {
6
+ export const StepperHorizontal = /*#__PURE__*/forwardRef((_ref, ref) => {
7
7
  let {
8
8
  children,
9
9
  className,
@@ -3,5 +3,5 @@ import { ComponentPropsWithoutRef } from 'react';
3
3
  export interface StepHorizontalProps extends ComponentPropsWithoutRef<'div'> {
4
4
  isActive?: boolean;
5
5
  }
6
- declare const StepHorizontal: import("react").ForwardRefExoticComponent<StepHorizontalProps & import("react").RefAttributes<HTMLDivElement>>;
6
+ declare const StepHorizontal: (props: StepHorizontalProps & import("react").RefAttributes<HTMLDivElement>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | null;
7
7
  export default StepHorizontal;
@@ -3,5 +3,5 @@ interface StepperVerticalProps extends Omit<ComponentPropsWithoutRef<'div'>, 'on
3
3
  stepIndex?: number;
4
4
  onChange?: (stepIndex: number) => void;
5
5
  }
6
- declare const StepperVertical: React.ForwardRefExoticComponent<StepperVerticalProps & React.RefAttributes<HTMLDivElement>>;
6
+ export declare const StepperVertical: (props: StepperVerticalProps & React.RefAttributes<HTMLDivElement>) => React.ReactElement<any, string | React.JSXElementConstructor<any>> | null;
7
7
  export default StepperVertical;
@@ -1,7 +1,7 @@
1
1
  import cn from 'classnames';
2
2
  import React, { forwardRef } from 'react';
3
3
  import { jsx as _jsx } from "react/jsx-runtime";
4
- const StepperVertical = /*#__PURE__*/forwardRef((_ref, ref) => {
4
+ export const StepperVertical = /*#__PURE__*/forwardRef((_ref, ref) => {
5
5
  let {
6
6
  children,
7
7
  className,
@@ -8,5 +8,5 @@ interface StepVerticalProps extends ComponentPropsWithoutRef<'div'> {
8
8
  title?: string;
9
9
  onStepClick?: () => void;
10
10
  }
11
- declare const StepVertical: import("react").ForwardRefExoticComponent<StepVerticalProps & import("react").RefAttributes<HTMLDivElement>>;
11
+ declare const StepVertical: (props: StepVerticalProps & import("react").RefAttributes<HTMLDivElement>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | null;
12
12
  export default StepVertical;
@@ -19,5 +19,5 @@ interface TabsProps extends Omit<ComponentPropsWithoutRef<'div'>, 'onChange'> {
19
19
  current: string;
20
20
  }) => void;
21
21
  }
22
- declare const Tabs: React.ForwardRefExoticComponent<TabsProps & React.RefAttributes<HTMLDivElement>>;
22
+ declare const Tabs: (props: TabsProps & React.RefAttributes<HTMLDivElement>) => React.ReactElement<any, string | React.JSXElementConstructor<any>> | null;
23
23
  export default Tabs;
@@ -2,6 +2,9 @@ import classNames from 'classnames';
2
2
  import React, { forwardRef, isValidElement, useEffect, useRef, useState } from 'react';
3
3
  import useForkRef from '../../helper/useForkRef';
4
4
  import useTabScroll from './useTabScroll';
5
+
6
+ // legacy: recommended for desktop only applications
7
+ // responsive: desktop, tablet, mobile with scrollable tabs
5
8
  import { jsx as _jsx } from "react/jsx-runtime";
6
9
  import { jsxs as _jsxs } from "react/jsx-runtime";
7
10
  import { Fragment as _Fragment } from "react/jsx-runtime";
@@ -2,7 +2,6 @@ import { useState } from 'react';
2
2
 
3
3
  // provides details about the left and right edges of the tab element and the tab content element
4
4
  // these values are used to determine the visual position of the tab with respect of its parent container
5
-
6
5
  const useTabScroll = (tabLength, componentId, refs) => {
7
6
  const {
8
7
  elRef,
@@ -3,5 +3,5 @@ export interface TableHeaderCellProps extends React.ThHTMLAttributes<HTMLTableCe
3
3
  active?: boolean;
4
4
  ascending: boolean;
5
5
  }
6
- declare const TableHeaderCell: import("react").ForwardRefExoticComponent<TableHeaderCellProps & import("react").RefAttributes<HTMLTableHeaderCellElement>>;
6
+ declare const TableHeaderCell: (props: TableHeaderCellProps & import("react").RefAttributes<HTMLTableCellElement>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | null;
7
7
  export default TableHeaderCell;
@@ -1,7 +1,13 @@
1
1
  import classNames from 'classnames';
2
2
  import { forwardRef } from 'react';
3
3
  import { jsx as _jsx } from "react/jsx-runtime";
4
- const TableHeaderCell = /*#__PURE__*/forwardRef((props, ref) => {
4
+ const TableHeaderCell = /*#__PURE__*/forwardRef((_ref, ref) => {
5
+ let {
6
+ active,
7
+ ascending,
8
+ className,
9
+ ...props
10
+ } = _ref;
5
11
  function handleClick(event) {
6
12
  if (props.onClick) {
7
13
  props.onClick(event);
@@ -10,10 +16,10 @@ const TableHeaderCell = /*#__PURE__*/forwardRef((props, ref) => {
10
16
  return /*#__PURE__*/_jsx("th", {
11
17
  ...props,
12
18
  className: classNames('fwe-table-order', {
13
- 'fwe-active': props.active
19
+ 'fwe-active': active
14
20
  }, {
15
- 'fwe-table-order-descending': !props.ascending
16
- }, props.className),
21
+ 'fwe-table-order-descending': !ascending
22
+ }, className),
17
23
  onClick: handleClick,
18
24
  ref: ref
19
25
  });
@@ -1,9 +1,10 @@
1
- import React from 'react';
2
1
  import './Checkbox.scss';
2
+ import React from 'react';
3
3
  export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> {
4
4
  id: string;
5
- checked: boolean;
6
- onChange: (value: boolean) => void;
5
+ checked?: boolean;
6
+ defaultChecked?: boolean;
7
+ onChange?: (value: boolean, e: React.ChangeEvent<HTMLInputElement>) => void;
7
8
  name?: string;
8
9
  large?: boolean;
9
10
  valid?: boolean;
@@ -12,5 +13,5 @@ export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputE
12
13
  disabled?: boolean;
13
14
  indeterminate?: boolean;
14
15
  }
15
- declare function Checkbox({ id, checked, onChange, name, large, valid, labelPosition, required, disabled, indeterminate, children, className, ...props }: CheckboxProps): JSX.Element;
16
+ declare function Checkbox({ id, checked: checkedProp, defaultChecked, onChange, name, large, valid, labelPosition, required, disabled, indeterminate, children, className, ...props }: CheckboxProps): JSX.Element;
16
17
  export default Checkbox;
@@ -1,11 +1,13 @@
1
- import React, { useState, useEffect } from 'react';
2
1
  import classNames from 'classnames';
2
+ import React from 'react';
3
+ import useControlled from '../../helper/useControlled';
3
4
  import { jsx as _jsx } from "react/jsx-runtime";
4
5
  import { jsxs as _jsxs } from "react/jsx-runtime";
5
6
  function Checkbox(_ref) {
6
7
  let {
7
8
  id,
8
- checked,
9
+ checked: checkedProp,
10
+ defaultChecked,
9
11
  onChange,
10
12
  name,
11
13
  large = false,
@@ -18,19 +20,14 @@ function Checkbox(_ref) {
18
20
  className,
19
21
  ...props
20
22
  } = _ref;
21
- const [isChecked, setChecked] = useState(checked);
22
- const [isIndeterminate, setIndeterminate] = useState(indeterminate);
23
- useEffect(() => {
24
- setChecked(checked);
25
- setIndeterminate(indeterminate);
26
- }, [checked, indeterminate]);
27
- const handleChange = () => {
23
+ const [isChecked, setChecked] = useControlled({
24
+ controlled: checkedProp,
25
+ default: defaultChecked
26
+ });
27
+ const handleChange = e => {
28
28
  const newChecked = !isChecked;
29
- if (indeterminate) {
30
- setIndeterminate(false);
31
- }
32
29
  setChecked(newChecked);
33
- onChange(newChecked);
30
+ onChange?.(newChecked, e);
34
31
  };
35
32
  const containerClasses = classNames('fwe-checkbox-container', {
36
33
  'fr-checkbox-large': large
@@ -45,7 +42,7 @@ function Checkbox(_ref) {
45
42
  }, {
46
43
  'fwe-label-before': labelPosition === 'before'
47
44
  }, {
48
- 'fr-checkbox-indeterminate': isIndeterminate
45
+ 'fr-checkbox-indeterminate': indeterminate
49
46
  }, className);
50
47
  return /*#__PURE__*/_jsxs("label", {
51
48
  className: containerClasses,
@@ -55,13 +52,14 @@ function Checkbox(_ref) {
55
52
  type: "checkbox",
56
53
  id: id,
57
54
  disabled: disabled,
58
- onChange: () => handleChange(),
59
- ...props
55
+ onChange: e => handleChange(e),
56
+ ...props,
57
+ checked: isChecked
60
58
  }), /*#__PURE__*/_jsxs("div", {
61
59
  className: "fwe-checkbox-indicator-container",
62
60
  children: [/*#__PURE__*/_jsx("div", {
63
61
  className: "fwe-checkbox-indicator-background"
64
- }), !isIndeterminate && isChecked && (large ? /*#__PURE__*/_jsx("svg", {
62
+ }), !indeterminate && isChecked && (large ? /*#__PURE__*/_jsx("svg", {
65
63
  width: "24px",
66
64
  height: "24px",
67
65
  children: /*#__PURE__*/_jsx("path", {
@@ -76,7 +74,7 @@ function Checkbox(_ref) {
76
74
  d: "M6 12L3 9l1.25-1.25L6 9.5l5.75-5.75L13 5l-7 7z",
77
75
  fill: "#fff"
78
76
  })
79
- })), isIndeterminate && !isChecked && /*#__PURE__*/_jsx("div", {
77
+ })), indeterminate && /*#__PURE__*/_jsx("div", {
80
78
  className: "fwe-indeterminate-indicator"
81
79
  })]
82
80
  }), /*#__PURE__*/_jsx("div", {
@@ -22,7 +22,7 @@ function RadioGroup(_ref) {
22
22
  large,
23
23
  disabled,
24
24
  required
25
- }), []);
25
+ }), [checked, disabled, labelPosition, large, name, required, value]);
26
26
  return /*#__PURE__*/_jsx(RadioGroupContext.Provider, {
27
27
  value: contextValue,
28
28
  children: /*#__PURE__*/_jsx("div", {
@@ -1,13 +1,7 @@
1
- import React, { ComponentPropsWithoutRef } from 'react';
2
1
  import './Select.scss';
2
+ import React, { ComponentPropsWithoutRef } from 'react';
3
+ import { SelectConfiguration } from '../../helper/types';
3
4
  import { SelectOptionType } from './select-option/SelectOption';
4
- interface Configuration {
5
- hideLabel?: boolean;
6
- scroll?: {
7
- enabled?: boolean;
8
- viewportSize?: number;
9
- };
10
- }
11
5
  export interface SelectProps extends Omit<ComponentPropsWithoutRef<'div'>, 'onChange'> {
12
6
  defaultValue?: any;
13
7
  value?: any;
@@ -15,12 +9,12 @@ export interface SelectProps extends Omit<ComponentPropsWithoutRef<'div'>, 'onCh
15
9
  options?: SelectOptionType[];
16
10
  required?: boolean;
17
11
  onChange?: (value: any) => void;
18
- config?: Configuration;
12
+ config?: SelectConfiguration;
19
13
  disabled?: boolean;
20
14
  name?: string;
21
15
  id?: string;
22
16
  hint?: string;
23
17
  error?: string;
24
18
  }
25
- declare const Select: React.ForwardRefExoticComponent<SelectProps & React.RefAttributes<HTMLDivElement>>;
19
+ declare const Select: (props: SelectProps & React.RefAttributes<HTMLDivElement>) => React.ReactElement<any, string | React.JSXElementConstructor<any>> | null;
26
20
  export default Select;
@@ -1,30 +1,16 @@
1
- import React, { useState, useEffect, useRef, useCallback, forwardRef } from 'react';
2
- import OutsideClickHandler from 'react-outside-click-handler';
3
1
  import classNames from 'classnames';
4
- import { SelectOption } from './select-option/SelectOption';
2
+ import React, { forwardRef, useCallback, useEffect, useRef, useState } from 'react';
3
+ import useControlled from '../../helper/useControlled';
4
+ import useForkRef from '../../helper/useForkRef';
5
+ import useOnClickOutside from '../../helper/useOnClickOutside';
6
+ import ListItem from './list-item/ListItem';
7
+ import calcVirtualScrollHeight from './utils';
5
8
  import { jsx as _jsx } from "react/jsx-runtime";
6
9
  import { Fragment as _Fragment } from "react/jsx-runtime";
7
10
  import { jsxs as _jsxs } from "react/jsx-runtime";
8
- function calcVirtualScrollHeight(config, itemLength) {
9
- const defaultHeight = 48;
10
- let height = defaultHeight;
11
- if (itemLength === 2) {
12
- height = defaultHeight * 2;
13
- } else if (itemLength >= 3) {
14
- height = defaultHeight * 3;
15
- }
16
- if (config?.scroll?.viewportSize != null && config.scroll.viewportSize !== undefined) {
17
- if (itemLength >= config.scroll.viewportSize) {
18
- height = config.scroll.viewportSize * defaultHeight;
19
- } else if (itemLength < config.scroll.viewportSize) {
20
- height = itemLength * defaultHeight;
21
- }
22
- }
23
- return height;
24
- }
25
11
  const Select = /*#__PURE__*/forwardRef((_ref, ref) => {
26
12
  let {
27
- defaultValue,
13
+ defaultValue = '',
28
14
  value,
29
15
  label,
30
16
  options,
@@ -44,8 +30,12 @@ const Select = /*#__PURE__*/forwardRef((_ref, ref) => {
44
30
  isFocused: false,
45
31
  action: ''
46
32
  });
47
- const controlled = value !== undefined;
48
- const [innerValue, setInnerValue] = useState(controlled ? value : defaultValue);
33
+ const [innerValue, setInnerValue] = useControlled({
34
+ controlled: value,
35
+ default: defaultValue
36
+ });
37
+ const innerRef = useRef(null);
38
+ const combinedRef = useForkRef(ref, innerRef);
49
39
  const buttonEl = useRef(null);
50
40
  const childrenList = [];
51
41
  React.Children.forEach(children, element => {
@@ -63,17 +53,7 @@ const Select = /*#__PURE__*/forwardRef((_ref, ref) => {
63
53
  const listItemRef = useRef(Array.from({
64
54
  length: usedOptions.length
65
55
  }, () => /*#__PURE__*/React.createRef()));
66
- useEffect(() => {
67
- if (controlled) {
68
- setInnerValue(value);
69
- }
70
- }, [value, controlled]);
71
- const getSelectedOptionLabel = useCallback(() => {
72
- if (innerValue !== undefined) {
73
- return usedOptions.find(option => option.data === innerValue)?.label;
74
- }
75
- return undefined;
76
- }, [usedOptions, innerValue]);
56
+ const getSelectedOptionLabel = useCallback(() => usedOptions.find(option => option.data === innerValue)?.label, [usedOptions, innerValue]);
77
57
  const scroll = config?.scroll;
78
58
  function handleButtonFocus(blur) {
79
59
  if (buttonEl && buttonEl.current) {
@@ -84,30 +64,31 @@ const Select = /*#__PURE__*/forwardRef((_ref, ref) => {
84
64
  }
85
65
  }
86
66
  }
87
- const focusNextElement = nextIndex => {
67
+ const focusNextElement = useCallback(nextIndex => {
88
68
  if (listItemRef && listItemRef.current) {
89
69
  const nextItem = listItemRef.current[nextIndex].current;
90
70
  if (nextItem !== null) {
91
71
  nextItem.focus();
92
72
  }
93
73
  }
94
- };
74
+ }, []);
75
+ const handleKeyAction = useCallback(index => {
76
+ if (index >= 0) {
77
+ focusNextElement(index);
78
+ }
79
+ }, [focusNextElement]);
95
80
  useEffect(() => {
96
81
  if (optionsWrapper.isFocused) {
97
82
  if (optionsWrapper.action === 'key') {
98
83
  const index = usedOptions.findIndex(option => option.label === getSelectedOptionLabel());
99
- if (index >= 0) {
100
- focusNextElement(index);
101
- }
84
+ handleKeyAction(index);
102
85
  } else if (optionsWrapper.action === 'click') {
103
86
  handleButtonFocus(true);
104
87
  }
105
88
  }
106
- }, [optionsWrapper, usedOptions, innerValue, getSelectedOptionLabel]);
89
+ }, [optionsWrapper, usedOptions, innerValue, getSelectedOptionLabel, handleKeyAction]);
107
90
  const handleOptionChange = newOption => {
108
- if (!controlled) {
109
- setInnerValue(newOption.data);
110
- }
91
+ setInnerValue(newOption.data);
111
92
  if (onChange) {
112
93
  onChange(newOption.data);
113
94
  }
@@ -119,28 +100,23 @@ const Select = /*#__PURE__*/forwardRef((_ref, ref) => {
119
100
  buttonEl.current.focus();
120
101
  }
121
102
  };
122
- const handleListKeyDown = (event, option, index) => {
103
+ const handleListKeyDown = (e, option, index) => {
123
104
  const arrowKeys = ['ArrowDown', 'ArrowUp'];
124
105
  const validKeys = ['Enter', ' '];
125
- if (arrowKeys.concat(validKeys).includes(event.key)) {
126
- event.preventDefault();
106
+ if (arrowKeys.concat(validKeys).includes(e.key)) {
107
+ e.preventDefault();
127
108
  }
128
- if (event.key === 'ArrowDown') {
109
+ if (e.key === 'ArrowDown') {
129
110
  focusNextElement((index + 1) % usedOptions.length);
130
111
  }
131
- if (event.key === 'ArrowUp') {
132
- event.preventDefault();
133
- let nextIndex = (index - 1) % usedOptions.length;
134
- if (nextIndex < 0) {
135
- nextIndex += usedOptions.length;
136
- }
112
+ if (e.key === 'ArrowUp') {
113
+ const nextIndex = (index - 1 + usedOptions.length) % usedOptions.length;
137
114
  focusNextElement(nextIndex);
138
115
  }
139
- if (validKeys.includes(event.key)) {
116
+ if (validKeys.includes(e.key)) {
140
117
  handleOptionChange(option);
141
- event.preventDefault();
142
118
  }
143
- if (event.key === 'Escape') {
119
+ if (e.key === 'Escape') {
144
120
  setOptionsWrapper(prevOptionsWrapper => ({
145
121
  ...prevOptionsWrapper,
146
122
  isFocused: false
@@ -169,6 +145,16 @@ const Select = /*#__PURE__*/forwardRef((_ref, ref) => {
169
145
  }));
170
146
  }
171
147
  };
148
+ const handleChange = event => {
149
+ const child = usedOptions.find(childItem => childItem.data === event.target.value);
150
+ if (child === undefined) {
151
+ return;
152
+ }
153
+ setInnerValue(child.data);
154
+ if (onChange) {
155
+ onChange(child.data);
156
+ }
157
+ };
172
158
  const selectedOptionLabel = getSelectedOptionLabel();
173
159
  const selectClassName = classNames('fwe-select', {
174
160
  'fwe-focus': optionsWrapper.isFocused
@@ -183,16 +169,12 @@ const Select = /*#__PURE__*/forwardRef((_ref, ref) => {
183
169
  });
184
170
  function renderOptions() {
185
171
  return /*#__PURE__*/_jsxs(_Fragment, {
186
- children: [options && options.map((option, i) => /*#__PURE__*/_jsx("li", {
172
+ children: [options && options.map((option, i) => /*#__PURE__*/_jsx(ListItem, {
187
173
  ref: listItemRef.current[i],
188
- role: "option",
189
174
  "aria-selected": option.label === selectedOptionLabel,
190
175
  onClick: () => handleOptionChange(option),
191
- className: classNames('fwe-select-option', {
192
- 'fwe-empty': !option.label
193
- }),
176
+ empty: !option.label,
194
177
  onKeyDown: e => handleListKeyDown(e, option, i),
195
- tabIndex: 0,
196
178
  children: /*#__PURE__*/_jsx("span", {
197
179
  className: "fwe-select-option-content",
198
180
  children: option.label
@@ -202,80 +184,68 @@ const Select = /*#__PURE__*/forwardRef((_ref, ref) => {
202
184
  option,
203
185
  ...propsWithoutOption
204
186
  } = child.props;
205
- return /*#__PURE__*/_jsx("li", {
187
+ return /*#__PURE__*/_jsx(ListItem, {
206
188
  ref: listItemRef.current[i],
207
- role: "option",
208
189
  "aria-selected": option.label === selectedOptionLabel,
209
190
  onClick: () => handleOptionChange(option),
210
- className: classNames('fwe-select-option', {
211
- 'fwe-empty': !option.label
212
- }),
191
+ empty: !option.label,
213
192
  onKeyDown: e => handleListKeyDown(e, option, i),
214
- tabIndex: 0,
215
- children: /*#__PURE__*/_jsx(SelectOption, {
193
+ children: /*#__PURE__*/_jsx("span", {
216
194
  ...propsWithoutOption
217
195
  })
218
196
  }, option.data);
219
197
  })]
220
198
  });
221
199
  }
222
- return /*#__PURE__*/_jsx(OutsideClickHandler, {
223
- onOutsideClick: () => setOptionsWrapper({
224
- action: '',
225
- isFocused: false
226
- }),
227
- children: /*#__PURE__*/_jsxs("div", {
228
- ref: ref,
229
- className: classNames('fwe-select-wrapper', className),
230
- ...props,
231
- children: [/*#__PURE__*/_jsx("select", {
232
- defaultValue: defaultValue,
233
- value: innerValue,
234
- name: name,
235
- id: id,
236
- "aria-label": label,
237
- disabled: disabled,
238
- required: required,
239
- children: usedOptions.map(option => /*#__PURE__*/_jsx("option", {
240
- value: option.data,
241
- children: option.label
242
- }, option.data))
243
- }), /*#__PURE__*/_jsx("div", {
244
- role: "button",
245
- tabIndex: 0,
246
- className: selectClassName,
247
- onClick: e => handleClick(e),
248
- ref: buttonEl,
249
- onKeyDown: handleKeyPress,
250
- children: /*#__PURE__*/_jsx("div", {
251
- className: "fwe-select-content",
252
- children: selectedOptionLabel
253
- })
254
- }), /*#__PURE__*/_jsx("label", {
255
- className: classNames('fwe-select-label', {
256
- 'fwe-sr-only': config?.hideLabel
257
- }),
258
- htmlFor: id,
259
- children: label || ''
260
- }), /*#__PURE__*/_jsx("div", {
261
- className: "fwe-select-underline"
262
- }), hint && !error && /*#__PURE__*/_jsx("div", {
263
- className: "fwe-select-description",
264
- children: hint
265
- }), error && /*#__PURE__*/_jsxs("div", {
266
- className: "fwe-select-invalid",
267
- children: [" ", error, " "]
268
- }), /*#__PURE__*/_jsx("ul", {
269
- className: `fwe-select-options-container${optionsWrapper.isFocused ? '' : ' fwe-d-none'}`,
270
- children: scroll?.enabled ? /*#__PURE__*/_jsx("div", {
271
- className: "fr-select-scroll",
272
- style: {
273
- height: calcVirtualScrollHeight(config, usedOptions.length)
274
- },
275
- children: renderOptions()
276
- }) : renderOptions()
277
- })]
278
- })
200
+ useOnClickOutside(innerRef, () => setOptionsWrapper({
201
+ action: '',
202
+ isFocused: false
203
+ }));
204
+ return /*#__PURE__*/_jsxs("div", {
205
+ ref: combinedRef,
206
+ className: classNames('fwe-select-wrapper', className),
207
+ ...props,
208
+ children: [/*#__PURE__*/_jsx("input", {
209
+ className: "fr-select-input",
210
+ "aria-hidden": true,
211
+ tabIndex: -1,
212
+ value: innerValue,
213
+ onChange: e => handleChange(e)
214
+ }), /*#__PURE__*/_jsx("div", {
215
+ role: "button",
216
+ tabIndex: 0,
217
+ className: selectClassName,
218
+ onClick: e => handleClick(e),
219
+ ref: buttonEl,
220
+ onKeyDown: handleKeyPress,
221
+ children: /*#__PURE__*/_jsx("div", {
222
+ className: "fwe-select-content",
223
+ children: selectedOptionLabel
224
+ })
225
+ }), /*#__PURE__*/_jsx("label", {
226
+ className: classNames('fwe-select-label', {
227
+ 'fwe-sr-only': config?.hideLabel
228
+ }),
229
+ htmlFor: id,
230
+ children: label || ''
231
+ }), /*#__PURE__*/_jsx("div", {
232
+ className: "fwe-select-underline"
233
+ }), hint && !error && /*#__PURE__*/_jsx("div", {
234
+ className: "fwe-select-description",
235
+ children: hint
236
+ }), error && /*#__PURE__*/_jsxs("div", {
237
+ className: "fwe-select-invalid",
238
+ children: [" ", error, " "]
239
+ }), /*#__PURE__*/_jsx("ul", {
240
+ className: `fwe-select-options-container${optionsWrapper.isFocused ? '' : ' fwe-d-none'}`,
241
+ children: scroll?.enabled ? /*#__PURE__*/_jsx("div", {
242
+ className: "fr-select-scroll",
243
+ style: {
244
+ height: calcVirtualScrollHeight(config, usedOptions.length)
245
+ },
246
+ children: renderOptions()
247
+ }) : renderOptions()
248
+ })]
279
249
  });
280
250
  });
281
251
  export default Select;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export interface ListItemProps extends React.ComponentPropsWithoutRef<'li'> {
3
+ empty?: boolean;
4
+ }
5
+ declare const ListItem: (props: ListItemProps & React.RefAttributes<HTMLLIElement>) => React.ReactElement<any, string | React.JSXElementConstructor<any>> | null;
6
+ export default ListItem;
@@ -0,0 +1,24 @@
1
+ import cn from 'classnames';
2
+ import React, { forwardRef } from 'react';
3
+ import { jsx as _jsx } from "react/jsx-runtime";
4
+ const ListItem = /*#__PURE__*/forwardRef((_ref, ref) => {
5
+ let {
6
+ children,
7
+ className,
8
+ "aria-selected": ariaSelected,
9
+ empty,
10
+ ...props
11
+ } = _ref;
12
+ return /*#__PURE__*/_jsx("li", {
13
+ ref: ref,
14
+ role: "option",
15
+ "aria-selected": ariaSelected,
16
+ className: cn('fwe-select-option', {
17
+ 'fwe-empty': empty
18
+ }, className),
19
+ tabIndex: 0,
20
+ ...props,
21
+ children: children
22
+ });
23
+ });
24
+ export default ListItem;