@jetbrains/ring-ui 7.0.124 → 8.0.0-beta.10

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 (191) hide show
  1. package/babel.config.js +1 -9
  2. package/components/auth-dialog-service/auth-dialog-service.js +2 -2
  3. package/components/avatar/avatar-info.js +0 -2
  4. package/components/avatar/avatar-size.d.ts +0 -4
  5. package/components/avatar/avatar-size.js +0 -4
  6. package/components/avatar/avatar.js +0 -6
  7. package/components/avatar/fallback-avatar.js +0 -28
  8. package/components/avatar-stack/avatar-stack.js +1 -1
  9. package/components/button/button.css +4 -4
  10. package/components/button/button.d.ts +0 -4
  11. package/components/button/button.js +2 -7
  12. package/components/button-group/button-group.css +23 -23
  13. package/components/button-toolbar/button-toolbar.css +2 -2
  14. package/components/checkbox/checkbox.d.ts +1 -1
  15. package/components/collapse/collapse-content.js +7 -16
  16. package/components/collapse/collapse-context.d.ts +1 -0
  17. package/components/collapse/collapse-context.js +1 -0
  18. package/components/collapse/collapse-control.js +2 -2
  19. package/components/collapse/collapse.css +8 -2
  20. package/components/collapse/collapse.js +10 -2
  21. package/components/collapsible-group/collapsible-group.css +1 -1
  22. package/components/collapsible-group/collapsible-group.d.ts +5 -1
  23. package/components/collapsible-group/collapsible-group.js +13 -22
  24. package/components/confirm-service/confirm-service.js +2 -2
  25. package/components/contenteditable/contenteditable.js +1 -2
  26. package/components/data-list/data-list.d.ts +4 -4
  27. package/components/data-list/data-list.js +2 -2
  28. package/components/data-list/data-list.mock.d.ts +1 -1
  29. package/components/data-list/item.d.ts +1 -1
  30. package/components/data-list/selection.d.ts +1 -1
  31. package/components/data-list/selection.js +1 -1
  32. package/components/date-picker/month.d.ts +0 -2
  33. package/components/date-picker/month.js +5 -5
  34. package/components/date-picker/months.js +8 -7
  35. package/components/date-picker/use-scroll-behavior.js +5 -6
  36. package/components/date-picker/years.js +11 -10
  37. package/components/dialog/dialog.d.ts +2 -2
  38. package/components/dialog/dialog.js +2 -2
  39. package/components/dropdown-menu/dropdown-menu.d.ts +4 -4
  40. package/components/dropdown-menu/dropdown-menu.js +4 -4
  41. package/components/editable-heading/editable-heading.d.ts +1 -2
  42. package/components/editable-heading/editable-heading.js +5 -6
  43. package/components/global/compose-refs.d.ts +2 -1
  44. package/components/global/compose-refs.js +24 -8
  45. package/components/global/configuration.d.ts +0 -5
  46. package/components/global/configuration.js +0 -7
  47. package/components/global/create-stateful-context.js +5 -5
  48. package/components/global/focus-with-temporary-tabindex.d.ts +11 -0
  49. package/components/global/focus-with-temporary-tabindex.js +21 -0
  50. package/components/global/intersection-observer-context.d.ts +46 -0
  51. package/components/global/intersection-observer-context.js +91 -0
  52. package/components/global/is-within-interactive-element.d.ts +6 -0
  53. package/components/global/is-within-interactive-element.js +26 -0
  54. package/components/global/is-within-navigable-element.d.ts +6 -0
  55. package/components/global/is-within-navigable-element.js +27 -0
  56. package/components/global/parse-css-duration.d.ts +5 -0
  57. package/components/global/parse-css-duration.js +13 -0
  58. package/components/global/rerender-hoc.d.ts +4 -2
  59. package/components/global/rerender-hoc.js +4 -4
  60. package/components/global/schedule-with-cleanup.d.ts +12 -0
  61. package/components/global/schedule-with-cleanup.js +34 -0
  62. package/components/{table/selection.d.ts → global/table-selection.d.ts} +15 -15
  63. package/components/{table/selection.js → global/table-selection.js} +3 -3
  64. package/components/global/theme.d.ts +4 -3
  65. package/components/global/theme.js +8 -8
  66. package/components/global/variables.css +0 -10
  67. package/components/global/variables.interface.d.ts +0 -4
  68. package/components/global/variables_dark.css +0 -7
  69. package/components/i18n/i18n-context.js +1 -1
  70. package/components/icon/icon-svg.js +2 -3
  71. package/components/icon/icon.css +0 -27
  72. package/components/icon/icon.d.ts +0 -1
  73. package/components/icon/icon.js +2 -4
  74. package/components/input/input.d.ts +1 -1
  75. package/components/island/adaptive-island-hoc.js +4 -4
  76. package/components/island/content.d.ts +7 -2
  77. package/components/island/content.js +5 -5
  78. package/components/{table → legacy-table}/cell.js +1 -1
  79. package/components/{table → legacy-table}/header-cell.js +1 -1
  80. package/components/{table → legacy-table}/header.js +1 -1
  81. package/components/legacy-table/legacy-table.css +260 -0
  82. package/components/{table → legacy-table}/multitable.d.ts +1 -1
  83. package/components/{table → legacy-table}/row.d.ts +1 -1
  84. package/components/{table → legacy-table}/row.js +1 -1
  85. package/components/legacy-table/selection-adapter.d.ts +6 -0
  86. package/components/{table → legacy-table}/selection-shortcuts-hoc.d.ts +5 -5
  87. package/components/{table → legacy-table}/simple-table.d.ts +2 -2
  88. package/components/{table → legacy-table}/simple-table.js +3 -3
  89. package/components/{table → legacy-table}/smart-table.d.ts +5 -5
  90. package/components/{table → legacy-table}/smart-table.js +3 -3
  91. package/components/legacy-table/table.d.ts +109 -0
  92. package/components/legacy-table/table.js +191 -0
  93. package/components/list/consts.d.ts +0 -1
  94. package/components/list/consts.js +0 -1
  95. package/components/list/list.d.ts +0 -4
  96. package/components/login-dialog/service.js +2 -2
  97. package/components/popup/popup.target.d.ts +3 -2
  98. package/components/popup/popup.target.js +4 -6
  99. package/components/query-assist/query-assist.d.ts +3 -1
  100. package/components/query-assist/query-assist.js +2 -2
  101. package/components/radio/radio-item.d.ts +3 -3
  102. package/components/radio/radio-item.js +3 -4
  103. package/components/radio/radio.d.ts +2 -2
  104. package/components/radio/radio.js +1 -1
  105. package/components/select/select-popup.d.ts +3 -2
  106. package/components/select/select-popup.js +3 -3
  107. package/components/select/select.d.ts +6 -2
  108. package/components/select/select.js +2 -4
  109. package/components/selection-toolbar/selection-toolbar.css +86 -0
  110. package/components/selection-toolbar/selection-toolbar.d.ts +11 -0
  111. package/components/selection-toolbar/selection-toolbar.js +23 -0
  112. package/components/slider/slider.js +4 -5
  113. package/components/tab-trap/tab-trap.d.ts +3 -3
  114. package/components/tab-trap/tab-trap.js +3 -5
  115. package/components/table/default-item-renderer.d.ts +55 -0
  116. package/components/table/default-item-renderer.js +77 -0
  117. package/components/table/internal/reorder-animation-context.d.ts +21 -0
  118. package/components/table/internal/reorder-animation-context.js +60 -0
  119. package/components/table/internal/reorder-handle.d.ts +9 -0
  120. package/components/table/internal/reorder-handle.js +334 -0
  121. package/components/table/internal/reorder-layout-context.d.ts +16 -0
  122. package/components/table/internal/reorder-layout-context.js +69 -0
  123. package/components/table/internal/table-header.d.ts +1 -0
  124. package/components/table/internal/table-header.js +143 -0
  125. package/components/table/internal/virtualization.d.ts +41 -0
  126. package/components/table/internal/virtualization.js +186 -0
  127. package/components/table/item-virtualization.d.ts +37 -0
  128. package/components/table/item-virtualization.js +26 -0
  129. package/components/table/reorder-animation.d.ts +37 -0
  130. package/components/table/reorder-animation.js +11 -0
  131. package/components/table/reorder-item-layout.d.ts +32 -0
  132. package/components/table/reorder-item-layout.js +23 -0
  133. package/components/table/table-const.d.ts +10 -0
  134. package/components/table/table-const.js +10 -0
  135. package/components/table/table-primitives.d.ts +64 -0
  136. package/components/table/table-primitives.js +34 -0
  137. package/components/table/table-props.d.ts +304 -0
  138. package/components/table/table-props.js +1 -0
  139. package/components/table/table.css +156 -167
  140. package/components/table/table.d.ts +231 -107
  141. package/components/table/table.js +319 -183
  142. package/components/tags-input/tags-input.d.ts +3 -1
  143. package/components/tooltip/tooltip.d.ts +2 -1
  144. package/components/tooltip/tooltip.js +6 -5
  145. package/components/upload/upload.d.ts +4 -3
  146. package/components/upload/upload.js +3 -7
  147. package/components/user-agreement/service.js +2 -2
  148. package/components/util-stories.d.ts +26 -0
  149. package/components/util-stories.js +61 -0
  150. package/package.json +45 -48
  151. package/components/content-layout/content-layout.css +0 -109
  152. package/components/content-layout/content-layout.d.ts +0 -20
  153. package/components/content-layout/content-layout.js +0 -40
  154. package/components/content-layout/sidebar.d.ts +0 -26
  155. package/components/content-layout/sidebar.js +0 -71
  156. package/components/date-picker/use-intersection-observer.d.ts +0 -6
  157. package/components/date-picker/use-intersection-observer.js +0 -48
  158. package/components/expand/collapsible-group.css +0 -76
  159. package/components/expand/collapsible-group.d.ts +0 -8
  160. package/components/expand/collapsible-group.js +0 -14
  161. package/components/global/composeRefs.d.ts +0 -6
  162. package/components/global/composeRefs.js +0 -7
  163. package/components/global/use-event-callback.d.ts +0 -4
  164. package/components/global/use-event-callback.js +0 -20
  165. package/components/grid/col.d.ts +0 -16
  166. package/components/grid/col.js +0 -35
  167. package/components/grid/grid.css +0 -920
  168. package/components/grid/grid.d.ts +0 -13
  169. package/components/grid/grid.js +0 -19
  170. package/components/grid/row.d.ts +0 -21
  171. package/components/grid/row.js +0 -41
  172. package/components/old-browsers-message/__mocks__/old-browsers-message.js +0 -1
  173. package/components/old-browsers-message/old-browsers-message-stop.d.ts +0 -1
  174. package/components/old-browsers-message/old-browsers-message-stop.js +0 -2
  175. package/components/old-browsers-message/old-browsers-message.css +0 -26
  176. package/components/old-browsers-message/old-browsers-message.d.ts +0 -5
  177. package/components/old-browsers-message/old-browsers-message.js +0 -86
  178. package/components/old-browsers-message/white-list.d.ts +0 -2
  179. package/components/old-browsers-message/white-list.js +0 -24
  180. package/components/table/selection-adapter.d.ts +0 -6
  181. /package/components/{table → legacy-table}/cell.d.ts +0 -0
  182. /package/components/{table → legacy-table}/disable-hover-hoc.d.ts +0 -0
  183. /package/components/{table → legacy-table}/disable-hover-hoc.js +0 -0
  184. /package/components/{table → legacy-table}/header-cell.d.ts +0 -0
  185. /package/components/{table → legacy-table}/header.d.ts +0 -0
  186. /package/components/{table → legacy-table}/multitable.js +0 -0
  187. /package/components/{table → legacy-table}/row-with-focus-sensor.d.ts +0 -0
  188. /package/components/{table → legacy-table}/row-with-focus-sensor.js +0 -0
  189. /package/components/{table → legacy-table}/selection-adapter.js +0 -0
  190. /package/components/{table → legacy-table}/selection-shortcuts-hoc.js +0 -0
  191. /package/components/{table → legacy-table}/table.examples2.json +0 -0
@@ -1,4 +1,4 @@
1
- import React, { forwardRef, useContext, useState } from 'react';
1
+ import React, { use, useState } from 'react';
2
2
  import classNames from 'classnames';
3
3
  import chevronRightIcon from '@jetbrains/icons/chevron-12px-right';
4
4
  import chevronDownIcon from '@jetbrains/icons/chevron-12px-down';
@@ -8,7 +8,7 @@ import CollapseContent from '../collapse/collapse-content';
8
8
  import { CollapseContext } from '../collapse/collapse-context';
9
9
  import styles from './collapsible-group.css';
10
10
  function CollapsibleGroupHeaderContent({ avatar, titleContent, subtitle }) {
11
- const { collapsed } = useContext(CollapseContext);
11
+ const { collapsed } = use(CollapseContext);
12
12
  return (<span className={styles.header}>
13
13
  <span className={styles.headerContent}>
14
14
  <span className={styles.avatarGroup}>
@@ -26,7 +26,7 @@ function CollapsibleGroupHeaderContent({ avatar, titleContent, subtitle }) {
26
26
  </span>);
27
27
  }
28
28
  function CollapsibleGroupHeader({ avatar, titleContent, subtitle, ...buttonProps }) {
29
- const { setCollapsed, collapsed, id } = useContext(CollapseContext);
29
+ const { setCollapsed, collapsed, id } = use(CollapseContext);
30
30
  return (<button type='button' {...buttonProps} className={styles.headerButton} onClick={setCollapsed} aria-controls={`collapse-content-${id}`} aria-expanded={!collapsed}>
31
31
  <CollapsibleGroupHeaderContent avatar={avatar} titleContent={titleContent} subtitle={subtitle}/>
32
32
  </button>);
@@ -36,10 +36,9 @@ function CollapsibleGroupHeaderStatic({ avatar, titleContent, subtitle }) {
36
36
  <CollapsibleGroupHeaderContent avatar={avatar} titleContent={titleContent} subtitle={subtitle}/>
37
37
  </span>);
38
38
  }
39
- const CollapsibleGroup = forwardRef(({ avatar, title, subtitle, children, className, defaultExpanded = false, expanded = null, onChange = () => { }, disableAnimation = false, interactive = true, keepMounted = false, headingLevel, 'data-test': dataTest, }, ref) => {
39
+ const CollapsibleGroup = ({ ref, avatar, title, subtitle, children, className, defaultExpanded = false, expanded = null, onChange = () => { }, disableAnimation = false, interactive = true, keepMounted = false, headingLevel, 'data-test': dataTest, }) => {
40
40
  const [innerExpanded, setInnerExpanded] = useState(defaultExpanded);
41
41
  const [hovered, setHovered] = useState(false);
42
- const [focused, setFocused] = useState(false);
43
42
  const isExpanded = expanded ?? innerExpanded;
44
43
  const handleChange = (collapsed) => {
45
44
  const nextExpanded = !collapsed;
@@ -48,27 +47,19 @@ const CollapsibleGroup = forwardRef(({ avatar, title, subtitle, children, classN
48
47
  }
49
48
  onChange(nextExpanded);
50
49
  };
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
50
  const classes = classNames(styles.expand, className, {
59
51
  [styles.hovered]: hovered,
60
52
  [styles.expanded]: isExpanded,
61
- [styles.focused]: focused,
62
53
  });
63
- const header = 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}/>);
54
+ const header = interactive ? (<CollapsibleGroupHeader avatar={avatar} titleContent={title} subtitle={subtitle} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}/>) : (<CollapsibleGroupHeaderStatic avatar={avatar} titleContent={title} subtitle={subtitle}/>);
64
55
  return (<div ref={ref} className={classes} data-test={dataTest}>
65
- <Collapse defaultCollapsed={!defaultExpanded} collapsed={expanded == null ? null : !expanded} onChange={handleChange} disableAnimation={disableAnimation} keepMounted={keepMounted} className={styles.collapseRoot}>
66
- {headingLevel != null ? React.createElement(`h${headingLevel}`, { className: styles.heading }, header) : header}
67
- <CollapseContent>
68
- <div className={styles.body}>{children}</div>
69
- </CollapseContent>
70
- </Collapse>
71
- </div>);
72
- });
56
+ <Collapse defaultCollapsed={!defaultExpanded} collapsed={expanded == null ? null : !expanded} onChange={handleChange} disableAnimation={disableAnimation} keepMounted={keepMounted} className={styles.collapseRoot}>
57
+ {headingLevel != null ? React.createElement(`h${headingLevel}`, { className: styles.heading }, header) : header}
58
+ <CollapseContent>
59
+ <div className={styles.body}>{children}</div>
60
+ </CollapseContent>
61
+ </Collapse>
62
+ </div>);
63
+ };
73
64
  CollapsibleGroup.displayName = 'CollapsibleGroup';
74
65
  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) => {
@@ -1,6 +1,5 @@
1
1
  import { Component } from 'react';
2
2
  import { renderToStaticMarkup } from 'react-dom/server';
3
- import { getTrustedHTML } from '../global/configuration';
4
3
  /**
5
4
  * @name ContentEditable
6
5
  */
@@ -24,7 +23,7 @@ class ContentEditableBase extends Component {
24
23
  return (<div {...props} ref={inputRef}
25
24
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
26
25
  // @ts-ignore
27
- disabled={disabled} role='textbox' tabIndex={disabled ? undefined : tabIndex} contentEditable={!this.props.disabled} dangerouslySetInnerHTML={{ __html: getTrustedHTML(__html) }}/>);
26
+ disabled={disabled} role='textbox' tabIndex={disabled ? undefined : tabIndex} contentEditable={!this.props.disabled} dangerouslySetInnerHTML={{ __html }}/>);
28
27
  }
29
28
  }
30
29
  const ContentEditable = ({ children, ...props }) => (<ContentEditableBase {...props} __html={renderToStaticMarkup(children)}/>);
@@ -3,9 +3,9 @@
3
3
  */
4
4
  import { Component } from 'react';
5
5
  import { type FocusSensorOuterProps } from '../global/focus-sensor-hoc';
6
- import { type SelectionShortcutsAddProps, type SelectionShortcutsOuterProps } from '../table/selection-shortcuts-hoc';
7
- import { type DisableHoverAddProps } from '../table/disable-hover-hoc';
8
- import { type SelectionItem } from '../table/selection';
6
+ import { type SelectionShortcutsAddProps, type SelectionShortcutsOuterProps } from '../legacy-table/selection-shortcuts-hoc';
7
+ import { type DisableHoverAddProps } from '../legacy-table/disable-hover-hoc';
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[];
@@ -20,7 +20,7 @@ export interface DataListBaseProps<T extends SelectionItem> {
20
20
  type FocusableProps<T extends SelectionItem> = DataListBaseProps<T> & DisableHoverAddProps & FocusSensorOuterProps<HTMLDivElement> & SelectionShortcutsAddProps<T>;
21
21
  export type DataListContainerProps<T extends SelectionItem> = DataListBaseProps<T> & FocusSensorOuterProps<HTMLDivElement> & SelectionShortcutsOuterProps<T>;
22
22
  export default class DataListContainer<T extends SelectionItem> extends Component<DataListContainerProps<T>> {
23
- DataList: import("react").ComponentClass<import("../table/disable-hover-hoc").DisableHoverProps<import("../table/selection-shortcuts-hoc").SelectionShortcutsProps<T, FocusableProps<T>>>, any>;
23
+ DataList: import("react").ComponentClass<import("../legacy-table/disable-hover-hoc").DisableHoverProps<import("../legacy-table/selection-shortcuts-hoc").SelectionShortcutsProps<T, FocusableProps<T>>>, any>;
24
24
  render(): import("react").JSX.Element;
25
25
  }
26
26
  export {};
@@ -4,8 +4,8 @@
4
4
  import { PureComponent, Component } from 'react';
5
5
  import classNames from 'classnames';
6
6
  import focusSensorHOC from '../global/focus-sensor-hoc';
7
- import selectionShortcutsHOC from '../table/selection-shortcuts-hoc';
8
- import disableHoverHOC from '../table/disable-hover-hoc';
7
+ import selectionShortcutsHOC from '../legacy-table/selection-shortcuts-hoc';
8
+ import disableHoverHOC from '../legacy-table/disable-hover-hoc';
9
9
  import getUID from '../global/get-uid';
10
10
  import Shortcuts from '../shortcuts/shortcuts';
11
11
  import Loader from '../loader/loader';
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from 'react';
2
- import { type SelectionItem } from '../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 '../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 '../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 '../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 }) {
@@ -1,9 +1,7 @@
1
1
  import { type Locale } from 'date-fns';
2
2
  import { type MonthsProps } from './consts';
3
- import { type IntersectionObserverHandle } from './use-intersection-observer';
4
3
  export interface MonthProps extends MonthsProps {
5
4
  month: Date;
6
- intersectionObserverHandle: IntersectionObserverHandle | null;
7
5
  }
8
6
  export default function Month(props: MonthProps): import("react").JSX.Element;
9
7
  export declare function getMonthHeight(monthStart: Date | number, locale: Locale | undefined): number;
@@ -4,14 +4,14 @@ import { getDaysInMonth, setDate } from 'date-fns';
4
4
  import { useRef } from 'react';
5
5
  import Day from './day';
6
6
  import units, { WEEK, getWeekStartsOn } from './consts';
7
- import { useVisibility } from './use-intersection-observer';
7
+ import { useIsIntersecting } from '../global/intersection-observer-context';
8
8
  import styles from './date-picker.css';
9
9
  export default function Month(props) {
10
- const { month, locale, intersectionObserverHandle } = props;
10
+ const { month, locale } = props;
11
11
  const containerRef = useRef(null);
12
- const visible = useVisibility(intersectionObserverHandle, containerRef);
13
- return (<div className={styles.month} ref={containerRef} style={visible ? {} : { height: getMonthHeight(month, locale) }}>
14
- {visible && (<>
12
+ const isIntersecting = useIsIntersecting(containerRef);
13
+ return (<div className={styles.month} ref={containerRef} style={isIntersecting ? {} : { height: getMonthHeight(month, locale) }}>
14
+ {isIntersecting && (<>
15
15
  <span className={styles.monthTitle}>{format(month, 'LLLL', { locale })}</span>
16
16
 
17
17
  {Array.from({ length: getPaddingCellsNum(month, locale) }, (_, i) => (<Day {...props} day={new Date(0)} empty key={`e_${i}`}/>))}
@@ -5,7 +5,7 @@ import units from './consts';
5
5
  import { ScrollArith } from './scroll-arith';
6
6
  import { useScrollBehavior } from './use-scroll-behavior';
7
7
  import scheduleRAF from '../global/schedule-raf';
8
- import { useIntersectionObserver } from './use-intersection-observer';
8
+ import { useIntersectionObserverHandle, IntersectionObserverContext } from '../global/intersection-observer-context';
9
9
  import styles from './date-picker.css';
10
10
  function getMonthHeightWithMargin(date, locale) {
11
11
  return units.unit * 2 + getMonthHeight(date, locale);
@@ -23,14 +23,15 @@ const scheduleScroll = scheduleRAF();
23
23
  *
24
24
  * To avoid an unpainted gap at the viewport boundary, the next month must be reported
25
25
  * as visible slightly before it actually enters the viewport. We achieve this by
26
- * extending the IntersectionObserver scrollMargin.
26
+ * extending the IntersectionObserver rootMargin.
27
27
  */
28
- const intersectionObserverScrollMargin = units.cellSize * 2;
28
+ 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
- const intersectionObserverHandle = useIntersectionObserver(containerRef, intersectionObserverScrollMargin);
33
- return (<div className={styles.months} ref={containerRef} data-test='ring-date-popup--months'>
34
- {items.map(month => (<Month {...props} month={month} key={+month} intersectionObserverHandle={intersectionObserverHandle}/>))}
35
- </div>);
32
+ return (<IntersectionObserverContext value={useIntersectionObserverHandle(containerRef, intersectionObserverRootMargin)}>
33
+ <div className={styles.months} ref={containerRef} data-test='ring-date-popup--months'>
34
+ {items.map(month => (<Month {...props} month={month} key={+month}/>))}
35
+ </div>
36
+ </IntersectionObserverContext>);
36
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) {
@@ -12,7 +12,7 @@ import { ScrollArith } from './scroll-arith';
12
12
  import { useScrollBehavior } from './use-scroll-behavior';
13
13
  import { animateDate } from './animate-date';
14
14
  import scheduleRAF from '../global/schedule-raf';
15
- import { useIntersectionObserver, useVisibility } from './use-intersection-observer';
15
+ import { IntersectionObserverContext, useIntersectionObserverHandle, useIsIntersecting, } from '../global/intersection-observer-context';
16
16
  import styles from './date-picker.css';
17
17
  const { yearHeight } = units;
18
18
  const scrollArith = new ScrollArith({
@@ -25,7 +25,7 @@ const scheduleScroll = scheduleRAF();
25
25
  /**
26
26
  * Reduces "empty" years during fast scrolling.
27
27
  */
28
- const intersectionObserverScrollMargin = units.calHeight / 2;
28
+ const intersectionObserverRootMargin = units.calHeight / 2;
29
29
  export default function Years({ scrollDate, setScrollDate }) {
30
30
  const [localScrollDate, setLocalScrollDate] = useState(scrollDate);
31
31
  const syncCleanupRef = useRef(null);
@@ -87,15 +87,16 @@ 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
- const intersectionObserverHandle = useIntersectionObserver(containerRef, intersectionObserverScrollMargin);
91
- return (<div className={styles.years} ref={containerRef} data-test='ring-date-popup--years'>
92
- {items.map(year => (<Year year={year} scrollDate={localScrollDate.date} handleYearClick={handleYearClick} key={+year} intersectionObserverHandle={intersectionObserverHandle}/>))}
93
- </div>);
90
+ return (<IntersectionObserverContext value={useIntersectionObserverHandle(containerRef, intersectionObserverRootMargin)}>
91
+ <div className={styles.years} ref={containerRef} data-test='ring-date-popup--years'>
92
+ {items.map(year => (<Year year={year} scrollDate={localScrollDate.date} handleYearClick={handleYearClick} key={+year}/>))}
93
+ </div>
94
+ </IntersectionObserverContext>);
94
95
  }
95
- function Year({ year, scrollDate, handleYearClick, intersectionObserverHandle, }) {
96
+ function Year({ year, scrollDate, handleYearClick, }) {
96
97
  const buttonRef = useRef(null);
97
- const visible = useVisibility(intersectionObserverHandle, buttonRef);
98
- return (<button type='button' ref={buttonRef} key={+year} disabled={!visible} className={classNames(styles.year, visible && isSameYear(year, scrollDate) && styles.currentYear, visible && isThisYear(year) && styles.today)} onClick={visible ? () => handleYearClick(year) : undefined}>
99
- {visible ? format(year, 'yyyy') : '\u00A0'}
98
+ const isIntersecting = useIsIntersecting(buttonRef);
99
+ return (<button type='button' ref={buttonRef} key={+year} disabled={!isIntersecting} className={classNames(styles.year, isIntersecting && isSameYear(year, scrollDate) && styles.currentYear, isIntersecting && isThisYear(year) && styles.today)} onClick={isIntersecting ? () => handleYearClick(year) : undefined}>
100
+ {isIntersecting ? format(year, 'yyyy') : '\u00A0'}
100
101
  </button>);
101
102
  }
@@ -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, useLayoutEffect } 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 };
@@ -63,13 +62,13 @@ export const EditableHeading = (props) => {
63
62
  const onHeadingMouseDown = () => {
64
63
  setIsMouseDown(true);
65
64
  };
66
- const onMouseMove = useEventCallback(() => {
65
+ const onMouseMove = useEffectEvent(() => {
67
66
  if (!isMouseDown) {
68
67
  return;
69
68
  }
70
69
  setIsInSelectionMode(true);
71
70
  });
72
- const onMouseUp = useEventCallback(() => {
71
+ const onMouseUp = useEffectEvent(() => {
73
72
  if (isMouseDown && !isInSelectionMode && !disabled) {
74
73
  onEdit();
75
74
  }
@@ -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;
@@ -1,2 +1,3 @@
1
1
  import { type Ref } from 'react';
2
- export declare function createComposedRef<T>(): import("memoize-one").MemoizedFn<(...refs: (Ref<T> | undefined)[]) => (value: T | null) => void>;
2
+ export declare function createComposedRef<T>(): import("memoize-one").MemoizedFn<(...refs: (Ref<T> | undefined)[]) => (value: T | null) => () => void>;
3
+ export declare function useComposedRef<T>(...refs: (Ref<T> | undefined)[]): Ref<T>;
@@ -1,14 +1,30 @@
1
+ import { useMemo } from 'react';
1
2
  import memoizeOne from 'memoize-one';
2
3
  function composeRefs(...refs) {
3
- return (value) => refs.forEach(ref => {
4
- if (typeof ref === 'function') {
5
- ref(value);
6
- }
7
- else if (ref) {
8
- ref.current = value;
9
- }
10
- });
4
+ return (value) => {
5
+ const cleanups = [];
6
+ refs.forEach(ref => {
7
+ if (typeof ref === 'function') {
8
+ const cleanup = ref(value);
9
+ if (typeof cleanup === 'function') {
10
+ cleanups.push(cleanup);
11
+ }
12
+ }
13
+ else if (ref) {
14
+ ref.current = value;
15
+ }
16
+ });
17
+ return () => cleanups.forEach(cleanup => cleanup());
18
+ };
11
19
  }
12
20
  export function createComposedRef() {
13
21
  return memoizeOne((composeRefs));
14
22
  }
23
+ export function useComposedRef(...refs) {
24
+ /**
25
+ * The React Compiler doesn't allow non-literal arrays in useMemo
26
+ * dependency lists, so we still use memoizeOne under the hood.
27
+ */
28
+ const composer = useMemo(() => createComposedRef(), []);
29
+ return composer(...refs);
30
+ }
@@ -3,14 +3,9 @@ export declare enum ControlsHeight {
3
3
  M = "M",
4
4
  L = "L"
5
5
  }
6
- export interface RingUITrustedTypePolicy {
7
- createHTML(html: string): TrustedHTML;
8
- }
9
6
  export interface RingUIConfiguration {
10
7
  controlsHeight?: ControlsHeight;
11
8
  popupsCssPositioning?: boolean;
12
- trustedTypePolicy?: RingUITrustedTypePolicy | null;
13
9
  }
14
10
  export declare function configure(config: RingUIConfiguration): void;
15
11
  export declare function getConfiguration(): Required<RingUIConfiguration>;
16
- export declare function getTrustedHTML(html: string): string | TrustedHTML;
@@ -7,7 +7,6 @@ export var ControlsHeight;
7
7
  const globalConfiguration = {
8
8
  controlsHeight: ControlsHeight.M,
9
9
  popupsCssPositioning: true,
10
- trustedTypePolicy: null,
11
10
  };
12
11
  export function configure(config) {
13
12
  if (config.controlsHeight !== undefined) {
@@ -16,13 +15,7 @@ export function configure(config) {
16
15
  if (config.popupsCssPositioning !== undefined) {
17
16
  globalConfiguration.popupsCssPositioning = config.popupsCssPositioning;
18
17
  }
19
- if (config.trustedTypePolicy !== undefined) {
20
- globalConfiguration.trustedTypePolicy = config.trustedTypePolicy;
21
- }
22
18
  }
23
19
  export function getConfiguration() {
24
20
  return { ...globalConfiguration };
25
21
  }
26
- export function getTrustedHTML(html) {
27
- return globalConfiguration.trustedTypePolicy?.createHTML(html) ?? html;
28
- }
@@ -1,16 +1,16 @@
1
- import { createContext, memo, useContext, useEffect, useState } from 'react';
1
+ import { createContext, memo, use, useEffect, useState } from 'react';
2
2
  export default function createStatefulContext(initialValue, name = '') {
3
3
  const ValueContext = createContext(initialValue);
4
4
  const UpdateContext = createContext(() => { });
5
5
  function Provider({ children }) {
6
6
  const [value, update] = useState(initialValue);
7
- return (<ValueContext.Provider value={value}>
8
- <UpdateContext.Provider value={update}>{children}</UpdateContext.Provider>
9
- </ValueContext.Provider>);
7
+ return (<ValueContext value={value}>
8
+ <UpdateContext value={update}>{children}</UpdateContext>
9
+ </ValueContext>);
10
10
  }
11
11
  Provider.displayName = `${name}Provider`;
12
12
  function useUpdate(value, skipUpdate) {
13
- const update = useContext(UpdateContext);
13
+ const update = use(UpdateContext);
14
14
  useEffect(() => {
15
15
  if (!skipUpdate) {
16
16
  update(value);
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Focuses an element, temporarily adding `tabindex="0"` if necessary.
3
+ *
4
+ * If the element does not already have a `tabindex` attribute, one is
5
+ * added before focusing and automatically removed when the element loses
6
+ * focus.
7
+ *
8
+ * This is useful when implementing roving tabindex patterns on elements
9
+ * that are not normally focusable.
10
+ */
11
+ export declare function focusWithTemporaryTabIndex(element: HTMLElement): void;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Focuses an element, temporarily adding `tabindex="0"` if necessary.
3
+ *
4
+ * If the element does not already have a `tabindex` attribute, one is
5
+ * added before focusing and automatically removed when the element loses
6
+ * focus.
7
+ *
8
+ * This is useful when implementing roving tabindex patterns on elements
9
+ * that are not normally focusable.
10
+ */
11
+ export function focusWithTemporaryTabIndex(element) {
12
+ if (!element.hasAttribute('tabindex')) {
13
+ element.tabIndex = 0;
14
+ function onBlur() {
15
+ element.removeAttribute('tabindex');
16
+ element.removeEventListener('blur', onBlur);
17
+ }
18
+ element.addEventListener('blur', onBlur);
19
+ }
20
+ element.focus();
21
+ }