Skip to content

Commit

Permalink
STCOM-1336 remove react-overlays dependency (#2429)
Browse files Browse the repository at this point in the history
## [STCOM-1336](https://folio-org.atlassian.net/browse/STCOM-1336)

This implements
[STCOM-1339](https://folio-org.atlassian.net/browse/STCOM-1339), as it
was a sub-task of this story.

`react-overlays` hasn't been published in 2 years.

After the modal refactor, the remaining bits were the 
`useRootClose` hook and an instance of `<Portal>`

- <Portal> was a simple refactor - `React-DOM`'s base functionality for
portals is all that's necessary there.

- ~~I opted to pull in a new dependency - `usehooks-ts` instead of
re-implementing `useRootClose` locally.
[usehooks-ts](https://usehooks-ts.com/introduction) is a minimal,
no-dependency lib with active development and a nice dev experience
curtesy of TS! It is pre-transpiled to commonjs, of course...
`useClickOutside` nicely replaced `onRootClose`.~~
- our own `useClickOutside` is implemented a bit differently, but served
purpose just fine rather than taking on any dependency - and the logic
is quite similar to that of the compound hook within `usehooks-ts`.


Additionally - updated shared workflows to 1.9 so that tests can run!
  • Loading branch information
JohnC-80 authored Feb 21, 2025
1 parent f6c9ac7 commit 7454877
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 120 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:

jobs:
ui:
uses: folio-org/.github/.github/workflows/ui.yml@v1.5
uses: folio-org/.github/.github/workflows/ui.yml@v1
if: github.ref_name == github.event.repository.default_branch || github.event_name != 'push' || github.ref_type == 'tag'
secrets: inherit
with:
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
* *BREAKING* remove deprecated props. Refs STCOM-1398.
* Add marginTop0 prop to the MessageBanner component. Refs STCOM-1408.
* Popper - hide overlay if popper anchor is scrolled out of the view. Refs STCOM-1386.
* Switch `useRootClose` hook to `useOClickOutside`. Refs STCOM-1339.
* Removed `react-overlays` dependency. Refs STCOM-1336.

## [12.2.0](https://github.com/folio-org/stripes-components/tree/v12.2.0) (2024-10-11)
[Full Changelog](https://github.com/folio-org/stripes-components/compare/v12.1.0...v12.2.0)
Expand Down
3 changes: 2 additions & 1 deletion lib/Datepicker/tests/Datepicker-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
converge,
} from '@folio/stripes-testing';
import { mountWithContext, focusPrevious, focusNext } from '../../../tests/helpers';
import { RoledHTML } from '../../../tests/helpers/localInteractors';

import Datepicker from '../Datepicker';
import {
Expand Down Expand Up @@ -485,7 +486,7 @@ describe('Datepicker', () => {
});

describe('clicking outside of calendar', () => {
beforeEach(() => document.body.click());
beforeEach(() => RoledHTML({ tagName: 'BODY' }).click());
it('closes the calendar picker', () => calendar.absent());
});
});
Expand Down
13 changes: 6 additions & 7 deletions lib/DropdownMenu/DropdownMenu.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { cloneElement, useRef } from 'react';
import React, { cloneElement, useRef, useCallback } from 'react';
import isBoolean from 'lodash/isBoolean';
import useRootClose from 'react-overlays/useRootClose';
import noop from 'lodash/noop';
import PropTypes from 'prop-types';
import useClickOutside from '../../hooks/useClickOutside';
import separateComponentProps from '../../util/separateComponentProps';
import css from './DropdownMenu.css';

Expand Down Expand Up @@ -32,17 +33,15 @@ const DropdownMenu = ({ overrideStyle = {}, ...rest }) => {
minWidth,
onSelect,
onSelectItem,
onToggle,
onToggle = noop,
open,
pullRight,
width
} = props;

const ref = useRef(null);

useRootClose(ref, onToggle, {
disabled: !open
});
const handleClickOutside = useCallback((e, outside) => outside && onToggle(), [onToggle]);
useClickOutside(ref, open ? handleClickOutside : noop);

const renderChildren = () => {
// don't pass along props that we didn't receive. if the
Expand Down
44 changes: 25 additions & 19 deletions lib/Selection/SelectionOverlay.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React, { useEffect, useRef } from 'react';
import { createPortal } from 'react-dom';
import PropTypes from 'prop-types';
import Portal from 'react-overlays/Portal';
import SelectionList from './SelectionList';
import Popper, { OVERLAY_MODIFIERS } from '../Popper';
import { OVERLAY_CONTAINER_ID } from '../../util/consts';

import css from './Selection.css';

Expand All @@ -23,7 +24,7 @@ const SelectionOverlay = ({
...props
}) => {
const filterRef = useRef(null);
const getPortalElement = useRef(() => document.getElementById('OverlayContainer')).current;
const getPortalElement = useRef(() => document.getElementById(OVERLAY_CONTAINER_ID)).current;

useEffect(() => {
// if the overlay is open and focus is outside of it, move focus to the filter.
Expand Down Expand Up @@ -57,26 +58,31 @@ const SelectionOverlay = ({
);

if (atSmallMedia) {
const portalContent = (
<div
role="presentation"
className={css.selectionMobileBackdrop}
onClick={() => { controlRef.current?.focus() }}
>
<div
className={css.selectionListRoot}
style={{ width: '85vw' }}
id={`sl-container-${id}`}
ref={listContainerRef}
>
{renderFilterInput(filterRef)}
{isOpen && selectList}
</div>
</div>
);

return (
<div>
{isOpen &&
<Portal container={getPortalElement()}>
<div
role="presentation"
className={css.selectionMobileBackdrop}
onClick={() => { controlRef.current?.focus() }}
>
<div
className={css.selectionListRoot}
style={{ width: '85vw' }}
id={`sl-container-${id}`}
ref={listContainerRef}
>
{renderFilterInput(filterRef)}
{isOpen && selectList}
</div>
</div>
</Portal>
createPortal(
portalContent,
getPortalElement()
)
}
</div>
);
Expand Down
25 changes: 25 additions & 0 deletions lib/Selection/tests/Selection-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { RoledHTML } from '../../../tests/helpers/localInteractors';
import Selection from '../Selection';
import SingleSelectionHarness from './SingleSelectionHarness';
import AsyncFilter from '../stories/AsyncFilter';
import { OVERLAY_CONTAINER_ID } from '../../../util/consts';

const asyncSelectionList = SelectListInteractor.extend('selection list with loading')
.filters({
Expand Down Expand Up @@ -774,4 +775,28 @@ describe('Selection', () => {
it('displays resulting options', () => asyncSelectionList().is({ optionCount: 30 }));
})
})

describe('small screens rendering', () => {
beforeEach(async () => {
viewport.set(300);
await mountWithContext(
<>
<div id={OVERLAY_CONTAINER_ID}/>
<Selection
label="test selection"
id={testId}
dataOptions={listOptions}
/>
</>
);
await selection.open();
});

it('opens dropdown in overlayContainer', expectOpenedMenu);

afterEach(() => {
viewport.reset();
});
})

});
2 changes: 0 additions & 2 deletions lib/Timepicker/TimeDropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,6 @@ const TimeDropdown = ({
}
}, [hourMax, hourMin, hoursFormat]);

useEffect(() => () => onHide(), []); // eslint-disable-line

const enterTime = (e, unit) => {
if (unit === 'hour') {
let parsedHour = parseInt(e.target.value, 10);
Expand Down
8 changes: 4 additions & 4 deletions lib/Timepicker/tests/Timepicker-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dayjs.extend(utc);
dayjs.extend(timeZone);

// check for DST with respect to the timezone of the tests since different zones can observe DST differently.
const isDST = function (tz='UTC') {
const isDST = function (tz = 'UTC') {
const julDate = '2022-07-20';
const janDate = '2022-01-01';

Expand Down Expand Up @@ -210,7 +210,7 @@ describe('Timepicker', () => {

describe('selecting a time with timeZone prop (Los Angeles) (RFF)', () => {
const tz = 'America/Los_Angeles';
const testTime = isDST('America/Los_Angeles') ? '00:00:00.000Z' : '01:00:00.000Z';;
const testTime = isDST('America/Los_Angeles') ? '00:00:00.000Z' : '01:00:00.000Z';
let timeOutput = '';
beforeEach(async () => {
timeOutput = '';
Expand Down Expand Up @@ -303,7 +303,7 @@ describe('Timepicker', () => {
id="timepicker-dropdown-test"
autoFocus
/>
<div id="anywhere-else" />
<div id="anywhere-else">anywhere else</div>
</div>
);

Expand Down Expand Up @@ -450,7 +450,7 @@ describe('Timepicker', () => {
});

describe('clicking outside the dropdown', () => {
beforeEach(() => document.getElementById('anywhere-else').click());
beforeEach(() => HTML({ id: 'anywhere-else' }).click());

it('should close the timepicker dropdown', () => timeDropdown.absent());
});
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@
"prop-types-extra": "^1.1.0",
"query-string": "^8.1.0",
"react-highlight-words": "^0.20.0",
"react-overlays": "^5.2.1",
"react-quill": "^2.0.0",
"react-transition-group": "^4.4.5",
"react-virtualized-auto-sizer": "^1.0.2",
Expand Down
15 changes: 9 additions & 6 deletions util/RootCloseWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@
* It's only used for class components that does not support using the useRootClose hook.
*/

import { forwardRef } from 'react';
import { forwardRef, useCallback } from 'react';
import PropTypes from 'prop-types';
import useRootClose from 'react-overlays/useRootClose';
import noop from 'lodash/noop';
import useClickOutside from '../hooks/useClickOutside';

const RootCloseWrapper = forwardRef(({ children, onRootClose, disabled }, ref) => {
useRootClose(ref, onRootClose, {
disabled
});
const RootCloseWrapper = forwardRef(({ children, onRootClose = noop, disabled }, ref) => {
const handleOutsideClick = useCallback((e, outside) => outside && onRootClose(e), [onRootClose]);
useClickOutside(
ref,
disabled ? noop : handleOutsideClick,
);

return children;
});
Expand Down
Loading

0 comments on commit 7454877

Please sign in to comment.