@festo-ui/react 5.0.0-dev.154 → 5.0.0-dev.158

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.
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { forwardRef, useRef } from 'react';
2
+ import { forwardRef, useEffect, useRef } from 'react';
3
3
  import ReactDOM from 'react-dom';
4
4
  import { CSSTransition } from 'react-transition-group';
5
5
  import useForkRef from '../../helper/useForkRef';
@@ -21,6 +21,15 @@ const ModalBase = /*#__PURE__*/forwardRef((_ref, ref) => {
21
21
  const allRefs = useForkRef(combinedRef, divRef);
22
22
  const container = divRef?.current?.ownerDocument || document;
23
23
  useOnClickOutside(divRef, () => onClose?.());
24
+ useEffect(() => {
25
+ const handleKeyDown = event => {
26
+ if (event.key === 'Escape') {
27
+ onClose?.();
28
+ }
29
+ };
30
+ container.addEventListener('keydown', handleKeyDown);
31
+ return () => container.removeEventListener('keydown', handleKeyDown);
32
+ }, [onClose, container]);
24
33
  return /*#__PURE__*/_jsx(_Fragment, {
25
34
  children: /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/_jsxs(_Fragment, {
26
35
  children: [/*#__PURE__*/_jsx(CSSTransition, {
@@ -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", {
@@ -18,6 +18,7 @@ export interface TextEditorProps {
18
18
  label: string;
19
19
  maxLength?: number;
20
20
  value?: string;
21
+ defaultValue?: string;
21
22
  hint?: string;
22
23
  error?: string;
23
24
  readOnly?: boolean;
@@ -25,5 +26,5 @@ export interface TextEditorProps {
25
26
  className?: string;
26
27
  config?: TextEditorConfiguration;
27
28
  }
28
- declare function TextEditor({ disabled, label, maxLength, value, hint, error, readOnly, onChange, className, config: configProps, }: TextEditorProps): JSX.Element;
29
+ declare function TextEditor({ disabled, defaultValue, label, maxLength, value, hint, error, readOnly, onChange, className, config: configProps, }: TextEditorProps): JSX.Element;
29
30
  export default TextEditor;
@@ -1,4 +1,4 @@
1
- import { useEffect, useRef, useState } from 'react';
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import classNames from 'classnames';
3
3
  import TextEditorButton from './TextEditorButton';
4
4
  import useId from '../../helper/useId';
@@ -19,9 +19,13 @@ const defaultConfig = {
19
19
  link: true
20
20
  }
21
21
  };
22
+ function postpone(fn) {
23
+ Promise.resolve().then(fn);
24
+ }
22
25
  function TextEditor(_ref) {
23
26
  let {
24
27
  disabled = false,
28
+ defaultValue,
25
29
  label,
26
30
  maxLength,
27
31
  value,
@@ -35,13 +39,29 @@ function TextEditor(_ref) {
35
39
  const editorRef = useRef(null);
36
40
  const [editor, setEditor] = useState(null);
37
41
  const id = useId();
38
- const [innerValue, setInnerValue] = useState(value);
42
+ const [innerValue, setInnerValue] = useState(null);
39
43
  const config = {
40
44
  toolbar: {
41
45
  ...defaultConfig.toolbar,
42
46
  ...configProps?.toolbar
43
47
  }
44
48
  };
49
+ const setEditorContents = useCallback((e, v) => {
50
+ if (e) {
51
+ const whiteList = {
52
+ ...xss.whiteList,
53
+ a: [...xss.whiteList.a, 'rel']
54
+ };
55
+ const sanitizedValue = xss(v, {
56
+ whiteList
57
+ });
58
+ const content = e.clipboard.convert(sanitizedValue);
59
+ const selection = e.getSelection();
60
+ e.setContents(content, 'silent');
61
+ setInnerValue(sanitizedValue);
62
+ postpone(() => e.setSelection(selection));
63
+ }
64
+ }, []);
45
65
  useEffect(() => {
46
66
  if (editorRef && editor === null && typeof window === 'object') {
47
67
  // eslint-disable-next-line global-require
@@ -75,8 +95,11 @@ function TextEditor(_ref) {
75
95
  return new Delta().insert('');
76
96
  });
77
97
  setEditor(newEditor);
98
+ if (defaultValue) {
99
+ setEditorContents(newEditor, defaultValue);
100
+ }
78
101
  }
79
- }, [editorRef, editor, disabled, readOnly, className, id, config.toolbar?.image]);
102
+ }, [editorRef, editor, disabled, readOnly, className, id, config.toolbar?.image, setEditorContents, defaultValue]);
80
103
  useEffect(() => {
81
104
  if (editor) {
82
105
  editor.on('text-change', () => {
@@ -92,18 +115,10 @@ function TextEditor(_ref) {
92
115
  }
93
116
  }, [editor, onChange]);
94
117
  useEffect(() => {
95
- if (editor) {
96
- const whiteList = {
97
- ...xss.whiteList,
98
- a: [...xss.whiteList.a, 'rel']
99
- };
100
- const sanitizedValue = xss(value, {
101
- whiteList
102
- });
103
- const content = editor.clipboard.convert(sanitizedValue);
104
- editor.setContents(content, 'silent');
118
+ if (value !== innerValue && value !== undefined && value !== null) {
119
+ setEditorContents(editor, value);
105
120
  }
106
- }, [editor, value]);
121
+ }, [editor, innerValue, setEditorContents, value]);
107
122
  function currentLength() {
108
123
  return innerValue?.length || 0;
109
124
  }
@@ -26,6 +26,15 @@ const ModalBase = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
26
26
  const allRefs = (0, _useForkRef.default)(combinedRef, divRef);
27
27
  const container = divRef?.current?.ownerDocument || document;
28
28
  (0, _useOnClickOutside.default)(divRef, () => onClose?.());
29
+ (0, _react.useEffect)(() => {
30
+ const handleKeyDown = event => {
31
+ if (event.key === 'Escape') {
32
+ onClose?.();
33
+ }
34
+ };
35
+ container.addEventListener('keydown', handleKeyDown);
36
+ return () => container.removeEventListener('keydown', handleKeyDown);
37
+ }, [onClose, container]);
29
38
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
30
39
  children: /*#__PURE__*/_reactDom.default.createPortal( /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
31
40
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactTransitionGroup.CSSTransition, {
@@ -4,16 +4,16 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _react = _interopRequireWildcard(require("react"));
8
7
  var _classnames = _interopRequireDefault(require("classnames"));
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _useControlled = _interopRequireDefault(require("../../helper/useControlled"));
9
10
  var _jsxRuntime = require("react/jsx-runtime");
10
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
12
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
13
12
  function Checkbox(_ref) {
14
13
  let {
15
14
  id,
16
- checked,
15
+ checked: checkedProp,
16
+ defaultChecked,
17
17
  onChange,
18
18
  name,
19
19
  large = false,
@@ -26,19 +26,14 @@ function Checkbox(_ref) {
26
26
  className,
27
27
  ...props
28
28
  } = _ref;
29
- const [isChecked, setChecked] = (0, _react.useState)(checked);
30
- const [isIndeterminate, setIndeterminate] = (0, _react.useState)(indeterminate);
31
- (0, _react.useEffect)(() => {
32
- setChecked(checked);
33
- setIndeterminate(indeterminate);
34
- }, [checked, indeterminate]);
35
- const handleChange = () => {
29
+ const [isChecked, setChecked] = (0, _useControlled.default)({
30
+ controlled: checkedProp,
31
+ default: defaultChecked
32
+ });
33
+ const handleChange = e => {
36
34
  const newChecked = !isChecked;
37
- if (indeterminate) {
38
- setIndeterminate(false);
39
- }
40
35
  setChecked(newChecked);
41
- onChange(newChecked);
36
+ onChange?.(newChecked, e);
42
37
  };
43
38
  const containerClasses = (0, _classnames.default)('fwe-checkbox-container', {
44
39
  'fr-checkbox-large': large
@@ -53,7 +48,7 @@ function Checkbox(_ref) {
53
48
  }, {
54
49
  'fwe-label-before': labelPosition === 'before'
55
50
  }, {
56
- 'fr-checkbox-indeterminate': isIndeterminate
51
+ 'fr-checkbox-indeterminate': indeterminate
57
52
  }, className);
58
53
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("label", {
59
54
  className: containerClasses,
@@ -63,13 +58,14 @@ function Checkbox(_ref) {
63
58
  type: "checkbox",
64
59
  id: id,
65
60
  disabled: disabled,
66
- onChange: () => handleChange(),
67
- ...props
61
+ onChange: e => handleChange(e),
62
+ ...props,
63
+ checked: isChecked
68
64
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
69
65
  className: "fwe-checkbox-indicator-container",
70
66
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
71
67
  className: "fwe-checkbox-indicator-background"
72
- }), !isIndeterminate && isChecked && (large ? /*#__PURE__*/(0, _jsxRuntime.jsx)("svg", {
68
+ }), !indeterminate && isChecked && (large ? /*#__PURE__*/(0, _jsxRuntime.jsx)("svg", {
73
69
  width: "24px",
74
70
  height: "24px",
75
71
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
@@ -84,7 +80,7 @@ function Checkbox(_ref) {
84
80
  d: "M6 12L3 9l1.25-1.25L6 9.5l5.75-5.75L13 5l-7 7z",
85
81
  fill: "#fff"
86
82
  })
87
- })), isIndeterminate && !isChecked && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
83
+ })), indeterminate && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
88
84
  className: "fwe-indeterminate-indicator"
89
85
  })]
90
86
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
@@ -24,9 +24,13 @@ const defaultConfig = {
24
24
  link: true
25
25
  }
26
26
  };
27
+ function postpone(fn) {
28
+ Promise.resolve().then(fn);
29
+ }
27
30
  function TextEditor(_ref) {
28
31
  let {
29
32
  disabled = false,
33
+ defaultValue,
30
34
  label,
31
35
  maxLength,
32
36
  value,
@@ -40,13 +44,29 @@ function TextEditor(_ref) {
40
44
  const editorRef = (0, _react.useRef)(null);
41
45
  const [editor, setEditor] = (0, _react.useState)(null);
42
46
  const id = (0, _useId.default)();
43
- const [innerValue, setInnerValue] = (0, _react.useState)(value);
47
+ const [innerValue, setInnerValue] = (0, _react.useState)(null);
44
48
  const config = {
45
49
  toolbar: {
46
50
  ...defaultConfig.toolbar,
47
51
  ...configProps?.toolbar
48
52
  }
49
53
  };
54
+ const setEditorContents = (0, _react.useCallback)((e, v) => {
55
+ if (e) {
56
+ const whiteList = {
57
+ ...xss.whiteList,
58
+ a: [...xss.whiteList.a, 'rel']
59
+ };
60
+ const sanitizedValue = xss(v, {
61
+ whiteList
62
+ });
63
+ const content = e.clipboard.convert(sanitizedValue);
64
+ const selection = e.getSelection();
65
+ e.setContents(content, 'silent');
66
+ setInnerValue(sanitizedValue);
67
+ postpone(() => e.setSelection(selection));
68
+ }
69
+ }, []);
50
70
  (0, _react.useEffect)(() => {
51
71
  if (editorRef && editor === null && typeof window === 'object') {
52
72
  // eslint-disable-next-line global-require
@@ -80,8 +100,11 @@ function TextEditor(_ref) {
80
100
  return new Delta().insert('');
81
101
  });
82
102
  setEditor(newEditor);
103
+ if (defaultValue) {
104
+ setEditorContents(newEditor, defaultValue);
105
+ }
83
106
  }
84
- }, [editorRef, editor, disabled, readOnly, className, id, config.toolbar?.image]);
107
+ }, [editorRef, editor, disabled, readOnly, className, id, config.toolbar?.image, setEditorContents, defaultValue]);
85
108
  (0, _react.useEffect)(() => {
86
109
  if (editor) {
87
110
  editor.on('text-change', () => {
@@ -97,18 +120,10 @@ function TextEditor(_ref) {
97
120
  }
98
121
  }, [editor, onChange]);
99
122
  (0, _react.useEffect)(() => {
100
- if (editor) {
101
- const whiteList = {
102
- ...xss.whiteList,
103
- a: [...xss.whiteList.a, 'rel']
104
- };
105
- const sanitizedValue = xss(value, {
106
- whiteList
107
- });
108
- const content = editor.clipboard.convert(sanitizedValue);
109
- editor.setContents(content, 'silent');
123
+ if (value !== innerValue && value !== undefined && value !== null) {
124
+ setEditorContents(editor, value);
110
125
  }
111
- }, [editor, value]);
126
+ }, [editor, innerValue, setEditorContents, value]);
112
127
  function currentLength() {
113
128
  return innerValue?.length || 0;
114
129
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@festo-ui/react",
3
- "version": "5.0.0-dev.154",
3
+ "version": "5.0.0-dev.158",
4
4
  "author": "Festo UI (styleguide@festo.com)",
5
5
  "license": "apache-2.0",
6
6
  "peerDependencies": {