@jetbrains/ring-ui 8.0.0-beta.2 → 8.0.0-beta.4

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 (121) hide show
  1. package/babel.config.js +1 -1
  2. package/components/auth-dialog-service/auth-dialog-service.js +2 -2
  3. package/components/checkbox/checkbox.d.ts +1 -1
  4. package/components/collapse/collapse-content.js +2 -2
  5. package/components/collapse/collapse-control.js +2 -2
  6. package/components/collapse/collapse.js +2 -2
  7. package/components/collapsible-group/collapsible-group.css +138 -0
  8. package/components/collapsible-group/collapsible-group.d.ts +20 -0
  9. package/components/collapsible-group/collapsible-group.js +73 -0
  10. package/components/confirm-service/confirm-service.js +2 -2
  11. package/components/data-list/data-list.d.ts +1 -1
  12. package/components/data-list/data-list.mock.d.ts +1 -1
  13. package/components/data-list/item.d.ts +1 -1
  14. package/components/data-list/selection.d.ts +1 -1
  15. package/components/data-list/selection.js +1 -1
  16. package/components/date-picker/months.js +2 -2
  17. package/components/date-picker/use-scroll-behavior.js +5 -6
  18. package/components/date-picker/years.js +2 -2
  19. package/components/dialog/dialog.d.ts +2 -2
  20. package/components/dialog/dialog.js +2 -2
  21. package/components/dropdown-menu/dropdown-menu.d.ts +4 -4
  22. package/components/dropdown-menu/dropdown-menu.js +4 -4
  23. package/components/editable-heading/editable-heading.d.ts +1 -2
  24. package/components/editable-heading/editable-heading.js +18 -19
  25. package/components/expand/collapsible-group.css +23 -89
  26. package/components/expand/collapsible-group.d.ts +8 -16
  27. package/components/expand/collapsible-group.js +13 -72
  28. package/components/global/compose-refs.d.ts +2 -1
  29. package/components/global/compose-refs.js +24 -8
  30. package/components/global/create-stateful-context.js +5 -5
  31. package/components/global/focus-with-temporary-tabindex.d.ts +11 -0
  32. package/components/global/focus-with-temporary-tabindex.js +21 -0
  33. package/components/global/intersection-observer-context.d.ts +31 -11
  34. package/components/global/intersection-observer-context.js +47 -28
  35. package/components/global/is-within-interactive-element.d.ts +6 -0
  36. package/components/global/is-within-interactive-element.js +26 -0
  37. package/components/global/is-within-navigable-element.d.ts +6 -0
  38. package/components/global/is-within-navigable-element.js +27 -0
  39. package/components/global/parse-css-duration.d.ts +5 -0
  40. package/components/global/parse-css-duration.js +13 -0
  41. package/components/global/rerender-hoc.d.ts +4 -2
  42. package/components/global/rerender-hoc.js +4 -4
  43. package/components/global/schedule-with-cleanup.d.ts +12 -0
  44. package/components/global/schedule-with-cleanup.js +34 -0
  45. package/components/{legacy-table/selection.d.ts → global/table-selection.d.ts} +14 -14
  46. package/components/{legacy-table/selection.js → global/table-selection.js} +2 -2
  47. package/components/global/theme.d.ts +4 -3
  48. package/components/global/theme.js +8 -8
  49. package/components/i18n/i18n-context.js +1 -1
  50. package/components/input/input.d.ts +1 -1
  51. package/components/island/adaptive-island-hoc.js +4 -4
  52. package/components/island/content.d.ts +7 -2
  53. package/components/island/content.js +5 -5
  54. package/components/legacy-table/cell.js +1 -1
  55. package/components/legacy-table/header-cell.js +1 -1
  56. package/components/legacy-table/header.js +1 -1
  57. package/components/legacy-table/multitable.d.ts +1 -1
  58. package/components/legacy-table/row.d.ts +1 -1
  59. package/components/legacy-table/row.js +1 -1
  60. package/components/legacy-table/selection-adapter.d.ts +3 -3
  61. package/components/legacy-table/selection-shortcuts-hoc.d.ts +5 -5
  62. package/components/legacy-table/simple-table.d.ts +2 -2
  63. package/components/legacy-table/simple-table.js +3 -3
  64. package/components/legacy-table/smart-table.d.ts +5 -5
  65. package/components/legacy-table/smart-table.js +3 -3
  66. package/components/legacy-table/table.js +1 -1
  67. package/components/login-dialog/service.js +2 -2
  68. package/components/popup/popup.d.ts +2 -0
  69. package/components/popup/popup.js +2 -2
  70. package/components/popup/popup.target.d.ts +3 -2
  71. package/components/popup/popup.target.js +4 -6
  72. package/components/query-assist/query-assist.d.ts +3 -1
  73. package/components/query-assist/query-assist.js +2 -2
  74. package/components/radio/radio-item.d.ts +3 -3
  75. package/components/radio/radio-item.js +3 -4
  76. package/components/radio/radio.d.ts +2 -2
  77. package/components/radio/radio.js +1 -1
  78. package/components/select/select-popup.d.ts +1 -1
  79. package/components/select/select.d.ts +4 -2
  80. package/components/slider/slider.js +4 -5
  81. package/components/tab-trap/tab-trap.d.ts +3 -3
  82. package/components/tab-trap/tab-trap.js +3 -5
  83. package/components/table/default-item-renderer.d.ts +35 -11
  84. package/components/table/default-item-renderer.js +47 -47
  85. package/components/table/internal/column-animation.d.ts +16 -0
  86. package/components/table/internal/column-animation.js +45 -0
  87. package/components/table/internal/table-header.d.ts +4 -0
  88. package/components/table/internal/table-header.js +357 -0
  89. package/components/table/internal/virtual-items.d.ts +34 -0
  90. package/components/table/{table-virtualize.js → internal/virtual-items.js} +78 -44
  91. package/components/table/item-virtualization.d.ts +35 -0
  92. package/components/table/item-virtualization.js +28 -0
  93. package/components/table/table-const.d.ts +40 -6
  94. package/components/table/table-const.js +14 -5
  95. package/components/table/table-primitives.d.ts +21 -0
  96. package/components/table/table-primitives.js +25 -0
  97. package/components/table/table-props.d.ts +280 -0
  98. package/components/table/table-props.js +1 -0
  99. package/components/table/table.css +171 -66
  100. package/components/table/table.d.ts +205 -224
  101. package/components/table/table.js +298 -2
  102. package/components/tags-input/tags-input.d.ts +3 -1
  103. package/components/tooltip/tooltip.js +2 -2
  104. package/components/upload/upload.d.ts +4 -3
  105. package/components/upload/upload.js +3 -7
  106. package/components/user-agreement/service.js +2 -2
  107. package/components/util-stories.d.ts +26 -0
  108. package/components/util-stories.js +61 -0
  109. package/package.json +41 -41
  110. package/components/date-picker/use-intersection-observer.d.ts +0 -6
  111. package/components/date-picker/use-intersection-observer.js +0 -48
  112. package/components/global/composeRefs.d.ts +0 -6
  113. package/components/global/composeRefs.js +0 -7
  114. package/components/global/use-event-callback.d.ts +0 -1
  115. package/components/global/use-event-callback.js +0 -15
  116. package/components/table/table-base.d.ts +0 -24
  117. package/components/table/table-base.js +0 -79
  118. package/components/table/table-component.d.ts +0 -53
  119. package/components/table/table-component.js +0 -101
  120. package/components/table/table-virtualize.d.ts +0 -32
  121. /package/components/legacy-table/{table.css → legacy-table.css} +0 -0
package/babel.config.js CHANGED
@@ -8,7 +8,7 @@ module.exports = function config(api) {
8
8
  [
9
9
  'babel-plugin-react-compiler',
10
10
  {
11
- target: '18', // should be the minimal supported version from peerDependencies
11
+ target: '19', // should be the minimal supported version from peerDependencies
12
12
  panicThreshold: 'all_errors',
13
13
  },
14
14
  ],
@@ -10,9 +10,9 @@ export const reactRoot = createRoot(containerElement);
10
10
  * Renders AuthDialog into virtual node to skip maintaining container
11
11
  */
12
12
  function renderAuthDialog(props) {
13
- reactRoot.render(<ControlsHeightContext.Provider value={getGlobalControlsHeight()}>
13
+ reactRoot.render(<ControlsHeightContext value={getGlobalControlsHeight()}>
14
14
  <AuthDialog {...props}/>
15
- </ControlsHeightContext.Provider>);
15
+ </ControlsHeightContext>);
16
16
  }
17
17
  export default function showAuthDialog(props = {}) {
18
18
  renderAuthDialog({
@@ -24,6 +24,6 @@ export default class Checkbox extends PureComponent<CheckboxProps> {
24
24
  componentDidUpdate(prevProps: CheckboxProps): void;
25
25
  input?: HTMLInputElement | null;
26
26
  inputRef: (el: HTMLInputElement | null) => void;
27
- composedInputRef: import("memoize-one").MemoizedFn<(...refs: (Ref<HTMLInputElement> | undefined)[]) => (value: T | null) => void>;
27
+ composedInputRef: import("memoize-one").MemoizedFn<(...refs: (Ref<HTMLInputElement> | undefined)[]) => (value: T | null) => () => void>;
28
28
  render(): import("react").JSX.Element;
29
29
  }
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect, useRef, useContext } from 'react';
1
+ import React, { useState, useEffect, useRef, use } from 'react';
2
2
  import classNames from 'classnames';
3
3
  import dataTests from '../global/data-tests';
4
4
  import { getRect } from '../global/dom';
@@ -14,7 +14,7 @@ const HIDDEN = 0;
14
14
  * @name CollapseContent
15
15
  */
16
16
  export const CollapseContent = ({ children, minHeight = DEFAULT_HEIGHT, 'data-test': dataTest, }) => {
17
- const { collapsed, duration, id, disableAnimation } = useContext(CollapseContext);
17
+ const { collapsed, duration, id, disableAnimation } = use(CollapseContext);
18
18
  const containerRef = useRef(null);
19
19
  const contentRef = useRef(null);
20
20
  const [initialContentHeight] = useState(minHeight);
@@ -1,4 +1,4 @@
1
- import { useContext, cloneElement } from 'react';
1
+ import { use, cloneElement } from 'react';
2
2
  import * as React from 'react';
3
3
  import dataTests from '../global/data-tests';
4
4
  import { CollapseContext } from './collapse-context';
@@ -7,7 +7,7 @@ import { COLLAPSE_CONTROL_TEST_ID } from './consts';
7
7
  * @name CollapseControl
8
8
  */
9
9
  export const CollapseControl = ({ children, 'data-test': dataTest }) => {
10
- const { setCollapsed, collapsed, id } = useContext(CollapseContext);
10
+ const { setCollapsed, collapsed, id } = use(CollapseContext);
11
11
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
12
  const child = typeof children === 'function' ? children(collapsed) : children;
13
13
  return (<p data-test={dataTests(COLLAPSE_CONTROL_TEST_ID, dataTest)}>
@@ -14,7 +14,7 @@ export const Collapse = ({ children, duration = BASE_ANIMATION_DURATION, disable
14
14
  onChange(!finalCollapsedValue);
15
15
  };
16
16
  return (<div className={className}>
17
- <CollapseContext.Provider value={{
17
+ <CollapseContext value={{
18
18
  collapsed: finalCollapsedValue,
19
19
  setCollapsed,
20
20
  duration,
@@ -22,7 +22,7 @@ export const Collapse = ({ children, duration = BASE_ANIMATION_DURATION, disable
22
22
  id,
23
23
  }}>
24
24
  {children}
25
- </CollapseContext.Provider>
25
+ </CollapseContext>
26
26
  </div>);
27
27
  };
28
28
  export default Collapse;
@@ -0,0 +1,138 @@
1
+ @import '../global/variables.css';
2
+
3
+ .expand .collapseRoot {
4
+ display: flex;
5
+ flex-direction: column;
6
+ }
7
+
8
+ .expand {
9
+ display: flex;
10
+ flex-direction: column;
11
+
12
+ box-sizing: border-box;
13
+
14
+ border: 1px solid var(--ring-line-color);
15
+ border-radius: var(--ring-border-radius-large);
16
+ outline: none;
17
+ background: var(--ring-content-background-color);
18
+ }
19
+
20
+ .hovered {
21
+ box-shadow: var(--ring-popup-shadow);
22
+ }
23
+
24
+ .expanded {
25
+ box-shadow: var(--ring-popup-shadow);
26
+ }
27
+
28
+ .focused {
29
+ box-shadow: 0 0 0 2px var(--ring-border-hover-color), var(--ring-popup-shadow);
30
+ }
31
+
32
+ .header {
33
+ display: flex;
34
+ align-items: center;
35
+ gap: calc(var(--ring-unit) * 1.5);
36
+
37
+ height: 28px;
38
+ }
39
+
40
+ .headerButton {
41
+ display: block;
42
+
43
+ box-sizing: border-box;
44
+ width: 100%;
45
+ padding: calc(var(--ring-unit) * 1.5);
46
+
47
+ cursor: pointer;
48
+ text-align: left;
49
+
50
+ color: inherit;
51
+
52
+ border: 0;
53
+ background: transparent;
54
+
55
+ font: inherit;
56
+ }
57
+
58
+ .headerButton:focus-visible {
59
+ outline: none;
60
+ }
61
+
62
+ .headerStatic {
63
+ display: block;
64
+
65
+ padding: calc(var(--ring-unit) * 1.5);
66
+ }
67
+
68
+ .headerContent {
69
+ display: flex;
70
+ align-items: center;
71
+ gap: var(--ring-unit);
72
+
73
+ flex: 1;
74
+
75
+ min-width: 0;
76
+ }
77
+
78
+ .avatarGroup {
79
+ display: flex;
80
+ align-items: center;
81
+ gap: var(--ring-unit);
82
+
83
+ flex-shrink: 0;
84
+ }
85
+
86
+ .title {
87
+ color: var(--ring-text-color);
88
+
89
+ font-size: var(--ring-font-size);
90
+ font-weight: var(--ring-font-weight-bold);
91
+ line-height: var(--ring-line-height);
92
+ }
93
+
94
+ .subtitleGroup {
95
+ display: flex;
96
+ align-items: center;
97
+ gap: var(--ring-unit);
98
+
99
+ min-width: 0;
100
+ }
101
+
102
+ .subtitle {
103
+ color: var(--ring-secondary-color);
104
+
105
+ font-size: var(--ring-font-size);
106
+ line-height: var(--ring-line-height);
107
+ }
108
+
109
+ .subtitleChevron {
110
+ color: var(--ring-secondary-color);
111
+ }
112
+
113
+ .toggle {
114
+ display: flex;
115
+ align-items: center;
116
+
117
+ flex-shrink: 0;
118
+ justify-content: center;
119
+
120
+ width: calc(var(--ring-unit) * 3);
121
+ height: calc(var(--ring-unit) * 3);
122
+
123
+ border-radius: calc(var(--ring-unit) / 2);
124
+ background: var(--ring-secondary-background-color);
125
+ }
126
+
127
+ .toggleIcon {
128
+ color: var(--ring-secondary-color);
129
+ }
130
+
131
+ .body {
132
+ padding: 0 calc(var(--ring-unit) * 2) calc(var(--ring-unit) * 1.5);
133
+
134
+ color: var(--ring-text-color);
135
+
136
+ font-size: var(--ring-font-size);
137
+ line-height: var(--ring-line-height);
138
+ }
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ export interface CollapsibleGroupProps {
3
+ ref?: React.Ref<HTMLDivElement>;
4
+ avatar?: React.ReactNode;
5
+ title: React.ReactNode;
6
+ subtitle?: React.ReactNode;
7
+ children?: React.ReactNode;
8
+ className?: string | null | undefined;
9
+ defaultExpanded?: boolean;
10
+ expanded?: boolean | null | undefined;
11
+ onChange?: (expanded: boolean) => void;
12
+ disableAnimation?: boolean;
13
+ interactive?: boolean;
14
+ 'data-test'?: string | null | undefined;
15
+ }
16
+ declare const CollapsibleGroup: {
17
+ ({ ref, avatar, title, subtitle, children, className, defaultExpanded, expanded, onChange, disableAnimation, interactive, "data-test": dataTest, }: CollapsibleGroupProps): React.JSX.Element;
18
+ displayName: string;
19
+ };
20
+ export default CollapsibleGroup;
@@ -0,0 +1,73 @@
1
+ import React, { use, useState } from 'react';
2
+ import classNames from 'classnames';
3
+ import chevronRightIcon from '@jetbrains/icons/chevron-12px-right';
4
+ import chevronDownIcon from '@jetbrains/icons/chevron-12px-down';
5
+ import Icon from '../icon/icon';
6
+ import Collapse from '../collapse/collapse';
7
+ import CollapseContent from '../collapse/collapse-content';
8
+ import { CollapseContext } from '../collapse/collapse-context';
9
+ import styles from './collapsible-group.css';
10
+ function CollapsibleGroupHeaderContent({ avatar, titleContent, subtitle }) {
11
+ const { collapsed } = use(CollapseContext);
12
+ return (<span className={styles.header}>
13
+ <span className={styles.headerContent}>
14
+ <span className={styles.avatarGroup}>
15
+ {avatar}
16
+ <span className={styles.title}>{titleContent}</span>
17
+ </span>
18
+ {subtitle ? (<span className={styles.subtitleGroup}>
19
+ <Icon className={styles.subtitleChevron} glyph={chevronRightIcon} aria-hidden/>
20
+ <span className={styles.subtitle}>{subtitle}</span>
21
+ </span>) : null}
22
+ </span>
23
+ <span className={styles.toggle} aria-hidden>
24
+ <Icon className={styles.toggleIcon} glyph={collapsed ? chevronRightIcon : chevronDownIcon}/>
25
+ </span>
26
+ </span>);
27
+ }
28
+ function CollapsibleGroupHeader({ avatar, titleContent, subtitle, ...buttonProps }) {
29
+ const { setCollapsed, collapsed, id } = use(CollapseContext);
30
+ return (<button type='button' {...buttonProps} className={styles.headerButton} onClick={setCollapsed} aria-controls={`collapse-content-${id}`} aria-expanded={!collapsed}>
31
+ <CollapsibleGroupHeaderContent avatar={avatar} titleContent={titleContent} subtitle={subtitle}/>
32
+ </button>);
33
+ }
34
+ function CollapsibleGroupHeaderStatic({ avatar, titleContent, subtitle }) {
35
+ return (<span className={styles.headerStatic}>
36
+ <CollapsibleGroupHeaderContent avatar={avatar} titleContent={titleContent} subtitle={subtitle}/>
37
+ </span>);
38
+ }
39
+ const CollapsibleGroup = ({ ref, avatar, title, subtitle, children, className, defaultExpanded = false, expanded = null, onChange = () => { }, disableAnimation = false, interactive = true, 'data-test': dataTest, }) => {
40
+ const [innerExpanded, setInnerExpanded] = useState(defaultExpanded);
41
+ const [hovered, setHovered] = useState(false);
42
+ const [focused, setFocused] = useState(false);
43
+ const isExpanded = expanded ?? innerExpanded;
44
+ const handleChange = (collapsed) => {
45
+ const nextExpanded = !collapsed;
46
+ if (expanded == null) {
47
+ setInnerExpanded(nextExpanded);
48
+ }
49
+ onChange(nextExpanded);
50
+ };
51
+ const onBlur = (event) => {
52
+ const nextTarget = event.relatedTarget;
53
+ if (nextTarget instanceof Node && event.currentTarget.contains(nextTarget)) {
54
+ return;
55
+ }
56
+ setFocused(false);
57
+ };
58
+ const classes = classNames(styles.expand, className, {
59
+ [styles.hovered]: hovered,
60
+ [styles.expanded]: isExpanded,
61
+ [styles.focused]: focused,
62
+ });
63
+ return (<div ref={ref} className={classes} data-test={dataTest}>
64
+ <Collapse defaultCollapsed={!defaultExpanded} collapsed={expanded == null ? null : !expanded} onChange={handleChange} disableAnimation={disableAnimation} className={styles.collapseRoot}>
65
+ {interactive ? (<CollapsibleGroupHeader avatar={avatar} titleContent={title} subtitle={subtitle} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)} onFocus={() => setFocused(true)} onBlur={onBlur}/>) : (<CollapsibleGroupHeaderStatic avatar={avatar} titleContent={title} subtitle={subtitle}/>)}
66
+ <CollapseContent>
67
+ <div className={styles.body}>{children}</div>
68
+ </CollapseContent>
69
+ </Collapse>
70
+ </div>);
71
+ };
72
+ CollapsibleGroup.displayName = 'CollapsibleGroup';
73
+ export default CollapsibleGroup;
@@ -8,9 +8,9 @@ export const reactRoot = createRoot(containerElement);
8
8
  */
9
9
  function renderConfirm(props) {
10
10
  const { buttonsHeight = getGlobalControlsHeight(), ...restProps } = props;
11
- reactRoot.render(<ControlsHeightContext.Provider value={buttonsHeight}>
11
+ reactRoot.render(<ControlsHeightContext value={buttonsHeight}>
12
12
  <Confirm {...restProps}/>
13
- </ControlsHeightContext.Provider>);
13
+ </ControlsHeightContext>);
14
14
  }
15
15
  export default function confirm({ text, description, confirmLabel = 'OK', rejectLabel = 'Cancel', cancelIsDefault, onBeforeConfirm, buttonsHeight, }) {
16
16
  return new Promise((resolve, reject) => {
@@ -5,7 +5,7 @@ import { Component } from 'react';
5
5
  import { type FocusSensorOuterProps } from '../global/focus-sensor-hoc';
6
6
  import { type SelectionShortcutsAddProps, type SelectionShortcutsOuterProps } from '../legacy-table/selection-shortcuts-hoc';
7
7
  import { type DisableHoverAddProps } from '../legacy-table/disable-hover-hoc';
8
- import { type SelectionItem } from '../legacy-table/selection';
8
+ import { type SelectionItem } from '../global/table-selection';
9
9
  import { type FormattedItem, moreLessButtonStates } from './item';
10
10
  export interface DataListBaseProps<T extends SelectionItem> {
11
11
  data: readonly T[];
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from 'react';
2
- import { type SelectionItem } from '../legacy-table/selection';
2
+ import { type SelectionItem } from '../global/table-selection';
3
3
  export interface Item extends SelectionItem {
4
4
  title: ReactNode;
5
5
  collapsible?: boolean;
@@ -1,5 +1,5 @@
1
1
  import { PureComponent, type ReactNode } from 'react';
2
- import { type SelectionItem } from '../legacy-table/selection';
2
+ import { type SelectionItem } from '../global/table-selection';
3
3
  import type Selection from './selection';
4
4
  export declare enum moreLessButtonStates {
5
5
  UNUSED = 0,
@@ -1,4 +1,4 @@
1
- import TableSelection, { type CloneWithConfig, type SelectionItem, type TableSelectionConfig } from '../legacy-table/selection';
1
+ import TableSelection, { type CloneWithConfig, type SelectionItem, type TableSelectionConfig } from '../global/table-selection';
2
2
  interface DataListSelectionConfig<T extends SelectionItem> extends TableSelectionConfig<T> {
3
3
  partialSelected?: Set<T> | undefined;
4
4
  }
@@ -1,4 +1,4 @@
1
- import TableSelection from '../legacy-table/selection';
1
+ import TableSelection from '../global/table-selection';
2
2
  export default class Selection extends TableSelection {
3
3
  _partialSelected;
4
4
  constructor({ partialSelected = new Set(), ...props }) {
@@ -29,9 +29,9 @@ const intersectionObserverRootMargin = units.cellSize * 2;
29
29
  export default function Months(props) {
30
30
  const { scrollDate, setScrollDate, locale } = props;
31
31
  const { containerRef, items } = useScrollBehavior(scrollDate, setScrollDate, locale, 'monthsScroll', scrollArith, scheduleScroll);
32
- return (<IntersectionObserverContext.Provider value={useIntersectionObserverHandle(containerRef, intersectionObserverRootMargin)}>
32
+ return (<IntersectionObserverContext value={useIntersectionObserverHandle(containerRef, intersectionObserverRootMargin)}>
33
33
  <div className={styles.months} ref={containerRef} data-test='ring-date-popup--months'>
34
34
  {items.map(month => (<Month {...props} month={month} key={+month}/>))}
35
35
  </div>
36
- </IntersectionObserverContext.Provider>);
36
+ </IntersectionObserverContext>);
37
37
  }
@@ -1,11 +1,10 @@
1
- import { useEffect, useLayoutEffect, useRef, useState } from 'react';
1
+ import { useEffect, useEffectEvent, useLayoutEffect, useRef, useState } from 'react';
2
2
  import units, { isSafariOnIPhone, scrollerReRenderDelayIPhone } from './consts';
3
- import useEventCallback from '../global/use-event-callback';
4
3
  export function useScrollBehavior(scrollDate, onContainerScroll, locale, selfScrollDateSource, arith, scheduleScroll) {
5
4
  const [items, setItems] = useState(() => arith.getItems(scrollDate.date));
6
5
  const [scrollTop, setScrollTop] = useState(() => arith.getScrollTop(items, scrollDate.date, locale));
7
6
  const containerRef = useRef(null);
8
- const syncSelfState = useEventCallback((newScrollDate) => {
7
+ const syncSelfState = useEffectEvent((newScrollDate) => {
9
8
  const newScrollTopOnExistingItems = arith.getScrollTop(items, newScrollDate, locale);
10
9
  if (isNearEdge(newScrollTopOnExistingItems, containerRef.current)) {
11
10
  const { newItems, newScrollTop } = arith.getItemsAndScrollTop(newScrollDate, locale);
@@ -28,7 +27,7 @@ export function useScrollBehavior(scrollDate, onContainerScroll, locale, selfScr
28
27
  if (scrollDate.source === selfScrollDateSource)
29
28
  return;
30
29
  syncSelfState(scrollDate.date);
31
- }, [scrollDate, selfScrollDateSource, syncSelfState]);
30
+ }, [scrollDate, selfScrollDateSource]);
32
31
  const ignoreNextScrollEventRef = useRef(true);
33
32
  useLayoutEffect(function setContainerScrollFromState() {
34
33
  const container = containerRef.current;
@@ -38,7 +37,7 @@ export function useScrollBehavior(scrollDate, onContainerScroll, locale, selfScr
38
37
  container.scrollTop = scrollTop;
39
38
  }, [items, scrollTop]);
40
39
  const updateStateTimerRef = useRef(null);
41
- const handleScroll = useEventCallback(() => {
40
+ const handleScroll = useEffectEvent(() => {
42
41
  scheduleScroll(() => {
43
42
  if (updateStateTimerRef.current != null) {
44
43
  window.clearTimeout(updateStateTimerRef.current);
@@ -83,7 +82,7 @@ export function useScrollBehavior(scrollDate, onContainerScroll, locale, selfScr
83
82
  updateStateTimerRef.current = null;
84
83
  }
85
84
  };
86
- }, [handleScroll]);
85
+ }, []);
87
86
  return { containerRef, items };
88
87
  }
89
88
  function isNearEdge(scrollTop, container) {
@@ -87,11 +87,11 @@ export default function Years({ scrollDate, setScrollDate }) {
87
87
  }, yearsAnimationDuration);
88
88
  }, [localScrollDate.date, setScrollDate]);
89
89
  const { containerRef, items } = useScrollBehavior(localScrollDate, syncCalendarScrollDate, undefined, 'yearsScroll', scrollArith, scheduleScroll);
90
- return (<IntersectionObserverContext.Provider value={useIntersectionObserverHandle(containerRef, intersectionObserverRootMargin)}>
90
+ return (<IntersectionObserverContext value={useIntersectionObserverHandle(containerRef, intersectionObserverRootMargin)}>
91
91
  <div className={styles.years} ref={containerRef} data-test='ring-date-popup--years'>
92
92
  {items.map(year => (<Year year={year} scrollDate={localScrollDate.date} handleYearClick={handleYearClick} key={+year}/>))}
93
93
  </div>
94
- </IntersectionObserverContext.Provider>);
94
+ </IntersectionObserverContext>);
95
95
  }
96
96
  function Year({ year, scrollDate, handleYearClick, }) {
97
97
  const buttonRef = useRef(null);
@@ -1,6 +1,6 @@
1
1
  import { PureComponent } from 'react';
2
2
  import * as React from 'react';
3
- import TabTrap, { type TabTrapProps } from '../tab-trap/tab-trap';
3
+ import { type TabTrapObject, type TabTrapProps } from '../tab-trap/tab-trap';
4
4
  import type { ShortcutsScopeOptions } from '../shortcuts/core';
5
5
  export interface DialogProps extends Partial<TabTrapProps> {
6
6
  show: boolean;
@@ -43,7 +43,7 @@ export default class Dialog extends PureComponent<DialogProps> {
43
43
  esc: (event: KeyboardEvent) => void;
44
44
  };
45
45
  dialog?: HTMLElement | null;
46
- dialogRef: (tabTrap: TabTrap | null) => void;
46
+ dialogRef: (tabTrapObj: TabTrapObject | null) => void;
47
47
  nativeDialog: React.RefObject<HTMLDialogElement | null>;
48
48
  render(): false | React.JSX.Element;
49
49
  }
@@ -104,8 +104,8 @@ export default class Dialog extends PureComponent {
104
104
  };
105
105
  };
106
106
  dialog;
107
- dialogRef = (tabTrap) => {
108
- this.dialog = tabTrap && tabTrap.node;
107
+ dialogRef = (tabTrapObj) => {
108
+ this.dialog = tabTrapObj && tabTrapObj.node;
109
109
  };
110
110
  nativeDialog = createRef();
111
111
  render() {
@@ -1,4 +1,4 @@
1
- import { type ReactElement, type HTMLAttributes, type SyntheticEvent, type Ref, type ReactNode } from 'react';
1
+ import { type ReactElement, type HTMLAttributes, type SyntheticEvent, type ReactNode } from 'react';
2
2
  import { type SelectHandlerParams } from '../list/list';
3
3
  import { type AnchorProps, type DropdownAttrs, type DropdownChildrenFunction } from '../dropdown/dropdown';
4
4
  import PopupMenu, { type PopupMenuAttrs } from '../popup-menu/popup-menu';
@@ -10,6 +10,7 @@ export interface DropdownAnchorWrapperProps extends AnchorProps {
10
10
  }
11
11
  type OnSelectHandler<T> = ((item: ListDataItem<T>, event: Event | SyntheticEvent, params?: SelectHandlerParams) => void) | undefined;
12
12
  export interface DropdownMenuProps<T = unknown> extends Omit<DropdownAttrs, 'anchor' | 'onSelect' | 'children'> {
13
+ ref?: React.Ref<PopupMenu<T> | null>;
13
14
  anchor: ReactElement | ReactNode[] | string | ((props: AnchorProps, ariaProps: HTMLAttributes<HTMLElement>) => ReactElement | null);
14
15
  data?: readonly ListDataItem<T>[] | undefined;
15
16
  ariaLabel?: string | null | undefined;
@@ -17,9 +18,8 @@ export interface DropdownMenuProps<T = unknown> extends Omit<DropdownAttrs, 'anc
17
18
  menuProps?: PopupMenuAttrs<T> | null | undefined;
18
19
  children?: DropdownChildrenFunction;
19
20
  }
20
- declare const _default: (<T = unknown>(props: DropdownMenuProps<T> & {
21
- ref?: Ref<PopupMenu>;
22
- }) => ReactElement | null) & {
21
+ declare function DropdownMenu<T = unknown>({ ref, id, anchor, ariaLabel, data, onSelect, menuProps, children, ...restDropdownProps }: DropdownMenuProps<T>): import("react").JSX.Element;
22
+ declare const _default: typeof DropdownMenu & {
23
23
  ListProps: {
24
24
  Type: typeof import("../list/consts").Type;
25
25
  Dimension: {
@@ -1,4 +1,4 @@
1
- import { forwardRef, cloneElement, useState, } from 'react';
1
+ import { cloneElement, useState, } from 'react';
2
2
  import List, { ActiveItemContext } from '../list/list';
3
3
  import Dropdown from '../dropdown/dropdown';
4
4
  import PopupMenu from '../popup-menu/popup-menu';
@@ -31,11 +31,11 @@ function renderDropdownMenuChildren({ children, popupMenuProps }) {
31
31
  }
32
32
  return (popupProps) => children({ ...popupProps, ...popupMenuProps });
33
33
  }
34
- const DropdownMenu = forwardRef(function DropdownMenu({ id, anchor, ariaLabel, data, onSelect, menuProps, children, ...restDropdownProps }, forwardedRef) {
34
+ function DropdownMenu({ ref, id, anchor, ariaLabel, data, onSelect, menuProps, children, ...restDropdownProps }) {
35
35
  const [uid] = useState(() => getUID('dropdown-menu-list'));
36
36
  const listId = id || uid;
37
37
  const popupMenuProps = {
38
- ref: forwardedRef,
38
+ ref,
39
39
  id: listId,
40
40
  ariaLabel: ariaLabel || defaultAriaLabel,
41
41
  closeOnSelect: true,
@@ -51,5 +51,5 @@ const DropdownMenu = forwardRef(function DropdownMenu({ id, anchor, ariaLabel, d
51
51
  {renderDropdownMenuChildren({ children, popupMenuProps })}
52
52
  </Dropdown>
53
53
  </ActiveItemContext.Provider>);
54
- });
54
+ }
55
55
  export default Object.assign(DropdownMenu, { ListProps: List.ListProps });
@@ -29,5 +29,4 @@ export type EditableHeadingProps = Omit<InputHTMLAttributes<HTMLInputElement | H
29
29
  translations?: EditableHeadingTranslations;
30
30
  };
31
31
  export declare const EditableHeading: (props: EditableHeadingProps) => React.JSX.Element;
32
- declare const _default: React.MemoExoticComponent<(props: EditableHeadingProps) => React.JSX.Element>;
33
- export default _default;
32
+ export default EditableHeading;
@@ -1,4 +1,4 @@
1
- import { useEffect } from 'react';
1
+ import { useEffect, useEffectEvent, useLayoutEffect } from 'react';
2
2
  import * as React from 'react';
3
3
  import classNames from 'classnames';
4
4
  import Heading, { Levels } from '../heading/heading';
@@ -6,7 +6,6 @@ import Button from '../button/button';
6
6
  import { Size } from '../input/input';
7
7
  import getUID from '../global/get-uid';
8
8
  import Shortcuts from '../shortcuts/shortcuts';
9
- import useEventCallback from '../global/use-event-callback';
10
9
  import inputStyles from '../input/input.css';
11
10
  import styles from './editable-heading.css';
12
11
  export { Levels };
@@ -46,36 +45,30 @@ export const EditableHeading = (props) => {
46
45
  });
47
46
  const headingClasses = classNames(styles.heading, headingClassName, size !== Size.AUTO && styles[`size${size}`]);
48
47
  const inputClasses = classNames('ring-js-shortcuts', styles.input, styles.textarea, { [styles.textareaNotOverflow]: !isOverflow }, size !== Size.AUTO && inputStyles[`size${size}`], level !== Levels.H4 && styles[`level${level}`], inputClassName);
49
- const stretch = (el) => {
50
- if (!el || !el.style) {
51
- return;
52
- }
53
- el.style.height = '0';
54
- const { paddingTop, paddingBottom } = window.getComputedStyle(el);
55
- el.style.height = `${el.scrollHeight - parseFloat(paddingTop) - parseFloat(paddingBottom)}px`;
56
- };
57
- const checkValue = (el) => {
48
+ const checkValue = React.useCallback((el) => {
58
49
  if (multiline && el && el.scrollHeight >= el.clientHeight) {
59
- stretch(el);
50
+ el.style.height = '0';
51
+ const { paddingTop, paddingBottom } = window.getComputedStyle(el);
52
+ el.style.height = `${el.scrollHeight - parseFloat(paddingTop) - parseFloat(paddingBottom)}px`;
60
53
  }
61
- };
62
- const checkOverflow = (el) => {
54
+ }, [multiline]);
55
+ const checkOverflow = React.useCallback((el) => {
63
56
  const scrollHeight = el.scrollHeight || 0;
64
57
  const clientHeight = el.clientHeight || 0;
65
58
  const scrollTop = el.scrollTop || 0;
66
59
  setIsScrolledToBottom(scrollHeight - clientHeight <= scrollTop);
67
60
  setIsOverflow(scrollHeight > clientHeight);
68
- };
61
+ }, []);
69
62
  const onHeadingMouseDown = () => {
70
63
  setIsMouseDown(true);
71
64
  };
72
- const onMouseMove = useEventCallback(() => {
65
+ const onMouseMove = useEffectEvent(() => {
73
66
  if (!isMouseDown) {
74
67
  return;
75
68
  }
76
69
  setIsInSelectionMode(true);
77
70
  });
78
- const onMouseUp = useEventCallback(() => {
71
+ const onMouseUp = useEffectEvent(() => {
79
72
  if (isMouseDown && !isInSelectionMode && !disabled) {
80
73
  onEdit();
81
74
  }
@@ -101,6 +94,12 @@ export const EditableHeading = (props) => {
101
94
  setIsInFocus(false);
102
95
  onBlur?.(e);
103
96
  };
97
+ useLayoutEffect(() => {
98
+ if (multiline && isEditing && textAreaRef.current) {
99
+ checkValue(textAreaRef.current);
100
+ checkOverflow(textAreaRef.current);
101
+ }
102
+ }, [checkOverflow, checkValue, isEditing, multiline]);
104
103
  useEffect(() => {
105
104
  window.addEventListener('mousemove', onMouseMove);
106
105
  window.addEventListener('mouseup', onMouseUp);
@@ -108,7 +107,7 @@ export const EditableHeading = (props) => {
108
107
  window.removeEventListener('mousemove', onMouseMove);
109
108
  window.removeEventListener('mouseup', onMouseUp);
110
109
  };
111
- }, [onMouseMove, onMouseUp]);
110
+ }, []);
112
111
  return (<>
113
112
  <div className={classes}>
114
113
  {!disabled && isEditing ? (<>
@@ -140,4 +139,4 @@ export const EditableHeading = (props) => {
140
139
  {isEditing && error && (<div className={classNames(styles.errorText, size !== Size.AUTO && inputStyles[`size${size}`])}>{error}</div>)}
141
140
  </>);
142
141
  };
143
- export default React.memo(EditableHeading);
142
+ export default EditableHeading;