@jetbrains/ring-ui 5.0.46 → 5.0.48

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.
@@ -6,7 +6,6 @@ import pencilIcon from '@jetbrains/icons/pencil';
6
6
  import angularDecorator, {APP_NAME} from '../../.storybook/angular-decorator';
7
7
 
8
8
  import IconNG from '../icon-ng/icon-ng';
9
- import ThemeNG from '../theme-ng/theme-ng';
10
9
  import CheckboxNG from '../checkbox-ng/checkbox-ng';
11
10
  import Theme from '../global/theme';
12
11
  import styles from '../global/variables_dark.css';
@@ -21,7 +20,7 @@ export default {
21
20
 
22
21
  export const basic = () => {
23
22
  angular.
24
- module(APP_NAME, [IconNG, ThemeNG, CheckboxNG, ButtonNG]).
23
+ module(APP_NAME, [IconNG, CheckboxNG, ButtonNG]).
25
24
  controller('testCtrl', function controller($scope) {
26
25
  $scope.pencil = pencilIcon;
27
26
  $scope.Theme = Theme;
@@ -2,11 +2,15 @@
2
2
 
3
3
  .editableHeading {
4
4
  display: flex;
5
- gap: unit;
5
+ align-items: center;
6
6
 
7
7
  &.fullSize {
8
8
  width: 100%;
9
9
  }
10
+
11
+ &.isEditing {
12
+ gap: unit;
13
+ }
10
14
  }
11
15
 
12
16
  .heading.heading {
@@ -61,6 +65,10 @@
61
65
  border-bottom-color: var(--ring-main-color);
62
66
  }
63
67
 
68
+ &[disabled] {
69
+ background-color: initial;
70
+ }
71
+
64
72
  @nest .error & {
65
73
  margin-bottom: 1px;
66
74
 
@@ -73,6 +81,15 @@
73
81
  margin: 6px 0;
74
82
  }
75
83
 
84
+ .errorText {
85
+ margin: calc(unit / 2) 0;
86
+
87
+ color: var(--ring-error-color);
88
+
89
+ font-size: var(--ring-font-size-smaller);
90
+ line-height: var(--ring-line-height-lowest);
91
+ }
92
+
76
93
  .level1 {
77
94
  font-size: 24px;
78
95
  }
@@ -4,23 +4,22 @@ import { Size } from '../input/input';
4
4
  export { Levels };
5
5
  export declare type EditableHeadingProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'size'> & {
6
6
  level?: Levels;
7
- className?: string | null;
8
7
  headingClassName?: string | null;
9
8
  inputClassName?: string | null;
10
- editing?: boolean;
11
- edited?: boolean;
9
+ isEditing?: boolean;
10
+ isSavingPossible?: boolean;
11
+ isSaving?: boolean;
12
12
  children?: string;
13
- placeholder?: string;
14
13
  embedded?: boolean;
15
14
  size?: Size;
16
15
  onEdit?: () => void;
17
16
  onSave?: () => void;
18
17
  onCancel?: () => void;
19
- autoFocus?: boolean;
20
18
  'data-test'?: string | null;
21
- error?: boolean;
22
- disabled?: boolean;
19
+ error?: string;
20
+ renderMenu?: () => React.ReactNode;
23
21
  };
22
+ export { Size } from '../input/input';
24
23
  export declare const EditableHeading: (props: EditableHeadingProps) => JSX.Element;
25
24
  declare const _default: React.MemoExoticComponent<(props: EditableHeadingProps) => JSX.Element>;
26
25
  export default _default;
@@ -4,42 +4,55 @@ import Heading, { Levels } from '../heading/heading';
4
4
  import Button from '../button/button';
5
5
  import { Size } from '../input/input';
6
6
  import inputStyles from '../input/input.css';
7
- import { ControlsHeight } from '../global/controls-height';
8
7
  import getUID from '../global/get-uid';
9
8
  import Shortcuts from '../shortcuts/shortcuts';
10
9
  import styles from './editable-heading.css';
11
10
  export { Levels };
12
11
  function noop() { }
13
12
  const shortcutsScope = getUID('ring-editable-heading-');
13
+ export { Size } from '../input/input';
14
14
  export const EditableHeading = (props) => {
15
- const { level = Levels.H1, className, headingClassName, inputClassName, editing, edited, children, placeholder, embedded = false, size = Size.L, onEdit, onSave = noop, onCancel = noop, autoFocus, 'data-test': dataTest, error, disabled, ...restProps } = props;
15
+ const { level = Levels.H1, className, headingClassName, inputClassName, isEditing, isSavingPossible, isSaving, children, embedded = false, size = Size.L, onEdit, onSave = noop, onCancel = noop, autoFocus = true, 'data-test': dataTest, error, disabled, renderMenu = () => null, ...restProps } = props;
16
+ const hasError = error !== undefined;
16
17
  const classes = classNames(styles.editableHeading, className, {
17
18
  [styles.fullSize]: size === Size.FULL,
18
- [styles.error]: error,
19
+ [styles.isEditing]: isEditing,
20
+ [styles.error]: hasError,
19
21
  [styles.disabled]: disabled
20
22
  });
21
23
  const headingClasses = classNames(styles.heading, headingClassName);
22
24
  const inputClasses = classNames('ring-js-shortcuts', styles.input, inputStyles[`size${size}`], styles[`level${level}`], inputClassName);
23
- const onClick = () => {
25
+ const onClick = React.useCallback(() => {
24
26
  if (disabled || !onEdit) {
25
27
  return undefined;
26
28
  }
27
29
  return onEdit();
28
- };
29
- return (<div className={classes}>
30
- {!disabled && editing
30
+ }, [disabled, onEdit]);
31
+ const isSaveDisabled = !isSavingPossible || !children || children.trim() === '' || hasError || isSaving;
32
+ const isCancelDisabled = isSaving;
33
+ return (<>
34
+ <div className={classes}>
35
+ {!disabled && isEditing
31
36
  ? (<>
32
- <Shortcuts map={{ enter: onSave, esc: onCancel }} scope={shortcutsScope}/>
37
+ <Shortcuts map={{
38
+ enter: () => !isSaveDisabled && onSave(),
39
+ esc: () => !isCancelDisabled && onCancel()
40
+ }} scope={shortcutsScope} disabled={isSaving}/>
33
41
 
34
- <input className={inputClasses} value={children} placeholder={placeholder} autoFocus={autoFocus} data-test={dataTest} {...restProps}/>
35
- </>)
42
+ <input className={inputClasses} value={children} autoFocus={autoFocus} data-test={dataTest} disabled={isSaving} {...restProps}/>
43
+ </>)
36
44
  : (<Heading className={headingClasses} level={level} onClick={onClick} data-test={dataTest}>{children}</Heading>)}
37
45
 
38
- {editing && !embedded && (<>
39
- <Button height={ControlsHeight.M} className={styles.button} primary disabled={!edited || !children || children?.trim() === '' || error} onClick={onSave}>{'Save'}</Button>
46
+ {!isEditing && (renderMenu())}
40
47
 
41
- <Button height={ControlsHeight.M} className={styles.button} onClick={onCancel}>{'Cancel'}</Button>
42
- </>)}
43
- </div>);
48
+ {isEditing && !embedded && (<>
49
+ <Button className={styles.button} primary disabled={isSaveDisabled} loader={isSaving} onClick={onSave}>{'Save'}</Button>
50
+
51
+ <Button className={styles.button} disabled={isCancelDisabled} onClick={onCancel}>{'Cancel'}</Button>
52
+ </>)}
53
+ </div>
54
+
55
+ {isEditing && error && (<div className={classNames(styles.errorText, inputStyles[`size${size}`])}>{error}</div>)}
56
+ </>);
44
57
  };
45
58
  export default React.memo(EditableHeading);
@@ -45,7 +45,7 @@ export const ThemeProvider = forwardRef(function ThemeProvider({ theme = Theme.A
45
45
  ? (<PopupTarget id={id}>
46
46
  {target => (<>
47
47
  {children}
48
- {createPortal(target, parentTarget && getPopupContainer(parentTarget) || document.body)}
48
+ {createPortal(<div className={themeClasses}>{target}</div>, parentTarget && getPopupContainer(parentTarget) || document.body)}
49
49
  </>)}
50
50
  </PopupTarget>)
51
51
  : children}
@@ -1,5 +1,6 @@
1
1
  /* stylelint-disable color-no-hex */
2
2
 
3
+ :global(.ring-ui-theme-dark),
3
4
  .dark,
4
5
  :root.dark {
5
6
  --ring-line-components: 71, 81, 89;
@@ -56,7 +56,9 @@ const ThemeProvider = /*#__PURE__*/forwardRef(function ThemeProvider(_ref, ref)
56
56
  className: classNames(className, themeClasses)
57
57
  }, restProps), passToPopups ? /*#__PURE__*/React.createElement(PopupTarget, {
58
58
  id: id
59
- }, target => /*#__PURE__*/React.createElement(React.Fragment, null, children, /*#__PURE__*/createPortal(target, parentTarget && getPopupContainer(parentTarget) || document.body))) : children);
59
+ }, target => /*#__PURE__*/React.createElement(React.Fragment, null, children, /*#__PURE__*/createPortal( /*#__PURE__*/React.createElement("div", {
60
+ className: themeClasses
61
+ }, target), parentTarget && getPopupContainer(parentTarget) || document.body))) : children);
60
62
  });
61
63
  var Theme$1 = Theme;
62
64
 
@@ -4,23 +4,22 @@ import { Size } from '../input/input';
4
4
  export { Levels };
5
5
  export declare type EditableHeadingProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'size'> & {
6
6
  level?: Levels;
7
- className?: string | null;
8
7
  headingClassName?: string | null;
9
8
  inputClassName?: string | null;
10
- editing?: boolean;
11
- edited?: boolean;
9
+ isEditing?: boolean;
10
+ isSavingPossible?: boolean;
11
+ isSaving?: boolean;
12
12
  children?: string;
13
- placeholder?: string;
14
13
  embedded?: boolean;
15
14
  size?: Size;
16
15
  onEdit?: () => void;
17
16
  onSave?: () => void;
18
17
  onCancel?: () => void;
19
- autoFocus?: boolean;
20
18
  'data-test'?: string | null;
21
- error?: boolean;
22
- disabled?: boolean;
19
+ error?: string;
20
+ renderMenu?: () => React.ReactNode;
23
21
  };
22
+ export { Size } from '../input/input';
24
23
  export declare const EditableHeading: (props: EditableHeadingProps) => JSX.Element;
25
24
  declare const _default: React.MemoExoticComponent<(props: EditableHeadingProps) => JSX.Element>;
26
25
  export default _default;
@@ -5,8 +5,8 @@ import Heading, { Levels } from '../heading/heading.js';
5
5
  export { Levels } from '../heading/heading.js';
6
6
  import { Button } from '../button/button.js';
7
7
  import { Size } from '../input/input.js';
8
+ export { Size } from '../input/input.js';
8
9
  import { m as modules_88cfaf40 } from '../_helpers/input.js';
9
- import { ControlsHeight } from '../global/controls-height.js';
10
10
  import getUID from '../global/get-uid.js';
11
11
  import Shortcuts from '../shortcuts/shortcuts.js';
12
12
  import 'prop-types';
@@ -19,6 +19,7 @@ import '../_helpers/icon.js';
19
19
  import '../icon/icon__svg.js';
20
20
  import '../global/memoize.js';
21
21
  import '../link/clickableLink.js';
22
+ import '../global/controls-height.js';
22
23
  import '../_helpers/button__classes.js';
23
24
  import '@jetbrains/icons/close-12px';
24
25
  import '../global/prop-types.js';
@@ -28,7 +29,7 @@ import 'combokeys';
28
29
  import '../global/sniffer.js';
29
30
  import 'sniffr';
30
31
 
31
- var modules_6e69b0fe = {"unit":"8px","editableHeading":"editableHeading_rui_0870","fullSize":"fullSize_rui_0870","heading":"heading_rui_0870","disabled":"disabled_rui_0870","input":"input_rui_0870","error":"error_rui_0870","button":"button_rui_0870","level1":"level1_rui_0870","level2":"level2_rui_0870","level3":"level3_rui_0870"};
32
+ var modules_6e69b0fe = {"unit":"8px","editableHeading":"editableHeading_rui_0870","fullSize":"fullSize_rui_0870","isEditing":"isEditing_rui_0870","heading":"heading_rui_0870","disabled":"disabled_rui_0870","input":"input_rui_0870","error":"error_rui_0870","button":"button_rui_0870","errorText":"errorText_rui_0870","level1":"level1_rui_0870","level2":"level2_rui_0870","level3":"level3_rui_0870"};
32
33
 
33
34
  function noop() {}
34
35
  const shortcutsScope = getUID('ring-editable-heading-');
@@ -38,64 +39,72 @@ const EditableHeading = props => {
38
39
  className,
39
40
  headingClassName,
40
41
  inputClassName,
41
- editing,
42
- edited,
42
+ isEditing,
43
+ isSavingPossible,
44
+ isSaving,
43
45
  children,
44
- placeholder,
45
46
  embedded = false,
46
47
  size = Size.L,
47
48
  onEdit,
48
49
  onSave = noop,
49
50
  onCancel = noop,
50
- autoFocus,
51
+ autoFocus = true,
51
52
  'data-test': dataTest,
52
53
  error,
53
54
  disabled,
55
+ renderMenu = () => null,
54
56
  ...restProps
55
57
  } = props;
58
+ const hasError = error !== undefined;
56
59
  const classes = classNames(modules_6e69b0fe.editableHeading, className, {
57
60
  [modules_6e69b0fe.fullSize]: size === Size.FULL,
58
- [modules_6e69b0fe.error]: error,
61
+ [modules_6e69b0fe.isEditing]: isEditing,
62
+ [modules_6e69b0fe.error]: hasError,
59
63
  [modules_6e69b0fe.disabled]: disabled
60
64
  });
61
65
  const headingClasses = classNames(modules_6e69b0fe.heading, headingClassName);
62
66
  const inputClasses = classNames('ring-js-shortcuts', modules_6e69b0fe.input, modules_88cfaf40[`size${size}`], modules_6e69b0fe[`level${level}`], inputClassName);
63
- const onClick = () => {
67
+ const onClick = React.useCallback(() => {
64
68
  if (disabled || !onEdit) {
65
69
  return undefined;
66
70
  }
67
71
  return onEdit();
68
- };
69
- return /*#__PURE__*/React.createElement("div", {
72
+ }, [disabled, onEdit]);
73
+ const isSaveDisabled = !isSavingPossible || !children || children.trim() === '' || hasError || isSaving;
74
+ const isCancelDisabled = isSaving;
75
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
70
76
  className: classes
71
- }, !disabled && editing ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Shortcuts, {
77
+ }, !disabled && isEditing ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Shortcuts, {
72
78
  map: {
73
- enter: onSave,
74
- esc: onCancel
79
+ enter: () => !isSaveDisabled && onSave(),
80
+ esc: () => !isCancelDisabled && onCancel()
75
81
  },
76
- scope: shortcutsScope
82
+ scope: shortcutsScope,
83
+ disabled: isSaving
77
84
  }), /*#__PURE__*/React.createElement("input", _extends({
78
85
  className: inputClasses,
79
86
  value: children,
80
- placeholder: placeholder,
81
87
  autoFocus: autoFocus,
82
- "data-test": dataTest
88
+ "data-test": dataTest,
89
+ disabled: isSaving
83
90
  }, restProps))) : /*#__PURE__*/React.createElement(Heading, {
84
91
  className: headingClasses,
85
92
  level: level,
86
93
  onClick: onClick,
87
94
  "data-test": dataTest
88
- }, children), editing && !embedded && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
89
- height: ControlsHeight.M,
95
+ }, children), !isEditing && renderMenu(), isEditing && !embedded && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
90
96
  className: modules_6e69b0fe.button,
91
97
  primary: true,
92
- disabled: !edited || !children || (children === null || children === void 0 ? void 0 : children.trim()) === '' || error,
98
+ disabled: isSaveDisabled,
99
+ loader: isSaving,
93
100
  onClick: onSave
94
101
  }, 'Save'), /*#__PURE__*/React.createElement(Button, {
95
- height: ControlsHeight.M,
96
102
  className: modules_6e69b0fe.button,
103
+ disabled: isCancelDisabled,
97
104
  onClick: onCancel
98
- }, 'Cancel')));
105
+ }, 'Cancel'))), isEditing && error && /*#__PURE__*/React.createElement("div", {
106
+ className: classNames(modules_6e69b0fe.errorText, modules_88cfaf40[`size${size}`])
107
+ }, error));
99
108
  };
100
109
  var editableHeading = /*#__PURE__*/React.memo(EditableHeading);
101
110