{React.cloneElement(element, this.getElementProps(), content)}
{vsb ? vsb.props.children : }
diff --git a/src/components/Scrollable/Scrollable.props.js b/src/components/Scrollable/Scrollable.props.js
index d45999d..143516d 100644
--- a/src/components/Scrollable/Scrollable.props.js
+++ b/src/components/Scrollable/Scrollable.props.js
@@ -15,11 +15,11 @@
*/
import React from 'react';
-import {func, shape, node, bool} from 'prop-types';
+import {func, node, bool, string} from 'prop-types';
import {noop} from 'utility/memory';
export const propTypes = {
- style: shape({}),
+ className: string,
onScroll: func,
onUpdate: func,
scrollOnDOMChange: bool,
@@ -29,7 +29,7 @@ export const propTypes = {
};
export const defaultProps = {
- style: null,
+ className: null,
onScroll: noop,
onUpdate: noop,
scrollOnDOMChange: true,
diff --git a/src/components/Scrollable/Scrollable.scss b/src/components/Scrollable/Scrollable.scss
index 2e617d7..b4589d7 100644
--- a/src/components/Scrollable/Scrollable.scss
+++ b/src/components/Scrollable/Scrollable.scss
@@ -2,6 +2,7 @@
--scrollable-track-thickness: 12px;
--scrollable-thumb-thickness: Calc(var(--scrollable-track-thickness)/2);
--scrollable-thumb-offset: 3px;
+ --scrollable-thumb-color: silver;
position: relative;
max-height: 100%;
@@ -37,10 +38,7 @@
cursor: pointer;
.scrollbar-thumb-inner {
- background-color: rgba(28, 34, 43, 0.6);
- border-radius: 4px;
- opacity: 0;
- transition: opacity 0.2s ease-out 0.5s; // The transition delay is used to keep the thumb visible for a short time when the cursor leaves. (see `Scrollable.constants.js`)
+ background-color: var(--scrollable-thumb-color);
}
}
}
diff --git a/src/components/Scrollable/components/HorizontalScrollbar/HorizontalScrollbar.jsx b/src/components/Scrollable/components/HorizontalScrollbar/HorizontalScrollbar.jsx
index 0cef8b4..caa4183 100644
--- a/src/components/Scrollable/components/HorizontalScrollbar/HorizontalScrollbar.jsx
+++ b/src/components/Scrollable/components/HorizontalScrollbar/HorizontalScrollbar.jsx
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import React, {useContext, useMemo, useRef} from 'react';
+import React, {useContext, useRef} from 'react';
import Movable from 'components/Movable';
import Context from '../../Scrollable.context';
import {CSS_VARS} from '../../Scrollable.constants';
@@ -25,7 +25,7 @@ const HorizontalScrollbar = () => {
const track = useRef();
const thumb = useRef();
const {container, scrollLeft, cssVarsOnTracks} = useContext(Context);
- const props = Movable.useMove(useMemo(() => [move(container, thumb, track)], [container]));
+ const props = Movable.useMove([move(container, thumb, track)]);
const handleOnClick = e => {
e.stopPropagation();
diff --git a/src/components/Scrollable/components/VerticalScrollbar/VerticalScrollbar.jsx b/src/components/Scrollable/components/VerticalScrollbar/VerticalScrollbar.jsx
index 5fb8e69..161df43 100644
--- a/src/components/Scrollable/components/VerticalScrollbar/VerticalScrollbar.jsx
+++ b/src/components/Scrollable/components/VerticalScrollbar/VerticalScrollbar.jsx
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import React, {useContext, useMemo, useRef} from 'react';
+import React, {useContext, useRef} from 'react';
import Movable from 'components/Movable';
import Context from '../../Scrollable.context';
import {CSS_VARS} from '../../Scrollable.constants';
@@ -25,7 +25,7 @@ const VerticalScrollbar = () => {
const track = useRef();
const thumb = useRef();
const {container, scrollTop, cssVarsOnTracks} = useContext(Context);
- const props = Movable.useMove(useMemo(() => [move(container, thumb, track)], [container]));
+ const props = Movable.useMove([move(container, thumb, track)]);
const handleOnClick = e => {
e.stopPropagation();
diff --git a/src/hooks/index.js b/src/hooks/index.js
index 58e6104..051211b 100644
--- a/src/hooks/index.js
+++ b/src/hooks/index.js
@@ -1,12 +1,12 @@
export {default as useAnimationFrame} from './useAnimationFrame';
export {default as useBooleanState, useVisibilityState, useFocusabilityState} from './useBooleanState';
export {default as useBoundingRectObserver} from './useBoundingRectObserver';
-export {default as useClickOutside, ClickOutside, ClickOutsideOverride} from './useClickOutside';
-export {default as useMounted, useUnmounted} from './useMounted';
+export {default as useClickOutside} from './useClickOutside';
+export {default as useMounted} from './useMounted';
export {default as useDebounce} from './useDebounce';
-export {default as useDimensions} from './useDimensions';
+export {default as useResizeObserver} from './useResizeObserver';
export {default as useEventListener} from './useEventListener';
export {default as useThrottle} from './useThrottle';
export {default as useObject} from './useObject';
export {default as usePrevious} from './usePrevious';
-export {default as useTimeout} from './useTimeout';
\ No newline at end of file
+export {default as useTimeout} from './useTimeout';
diff --git a/src/hooks/useClickOutside/index.js b/src/hooks/useClickOutside/index.js
index 516eaeb..f0aea3d 100644
--- a/src/hooks/useClickOutside/index.js
+++ b/src/hooks/useClickOutside/index.js
@@ -15,5 +15,4 @@
*/
import {useClickOutside} from './useClickOutside';
-export {ClickOutside, ClickOutsideOverride} from './useClickOutside';
export default useClickOutside;
\ No newline at end of file
diff --git a/src/hooks/useClickOutside/useClickOutside.js b/src/hooks/useClickOutside/useClickOutside.js
index 45b2d8f..a3ff612 100644
--- a/src/hooks/useClickOutside/useClickOutside.js
+++ b/src/hooks/useClickOutside/useClickOutside.js
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-import React, {useRef, useCallback, useContext} from 'react';
-import {func, node} from 'prop-types';
+import {useRef, useCallback, useContext} from 'react';
import {_document} from 'utility/mocks';
import useEventListener from '../useEventListener';
import OverrideContext from './useClickOutside.context';
@@ -39,6 +38,8 @@ import OverrideContext from './useClickOutside.context';
* element (for example, when dragging). In such cases the click is still considered as an inside click,
* since it originated inside the element.
*
+ * For class components use ClickOutside from 'webrix/tools/ClickOutside'
+ *
* @param {Function} callback
*/
export const useClickOutside = callback => {
@@ -57,26 +58,3 @@ export const useClickOutside = callback => {
isClickedInside.current = true;
}, [isClickedInside]);
};
-
-// Use this for class components
-export const ClickOutside = ({children, onClickOutside}) => {
- const handleOnMouseDownCapture = useClickOutside(onClickOutside);
- // We're updating the contained element instead of adding a wrapper since adding
- // a wrapper can may affect the styling/behavior
- return React.cloneElement(
- React.Children.only(children), {onMouseDownCapture: handleOnMouseDownCapture}
- );
-};
-
-// It is sometimes necessary to modify the condition of the click-outside handler
-// of one or more elements. This can be done using the ClickOutsideOverride
-export const ClickOutsideOverride = ({condition, children}) => (
-
- {children}
-
-);
-
-ClickOutsideOverride.propTypes = {
- condition: func,
- children: node,
-};
diff --git a/src/hooks/useClickOutside/useClickOutside.test.js b/src/hooks/useClickOutside/useClickOutside.test.js
index 395513c..2665dde 100644
--- a/src/hooks/useClickOutside/useClickOutside.test.js
+++ b/src/hooks/useClickOutside/useClickOutside.test.js
@@ -2,9 +2,8 @@ import React from 'react';
// https://reactjs.org/docs/hooks-faq.html#how-to-test-components-that-use-hooks
import {act} from 'react-dom/test-utils';
import sinon from 'sinon';
-import {mount, shallow} from 'enzyme';
-import OverrideContext from './useClickOutside.context';
-import {useClickOutside, ClickOutside, ClickOutsideOverride} from './useClickOutside';
+import {mount} from 'enzyme';
+import {useClickOutside} from './useClickOutside';
const Elem = callback => {
useClickOutside(callback);
@@ -33,15 +32,4 @@ describe('useClickOutside()', () => {
elem.simulate('click');
expect(callback.callCount).toEqual(0);
});
-
- it('', () => {
- const wrapper = shallow();
- expect(() => shallow()).toThrow();
- expect(typeof wrapper.find('div').prop('onMouseDownCapture')).toBe('function');
- });
-
- it('', () => {
- const wrapper = shallow();
- expect(wrapper.find(OverrideContext.Provider)).toHaveLength(1);
- });
});
diff --git a/src/hooks/useDimensions/readme.md b/src/hooks/useDimensions/readme.md
deleted file mode 100644
index e97cc4c..0000000
--- a/src/hooks/useDimensions/readme.md
+++ /dev/null
@@ -1,2 +0,0 @@
-See the full documentation of `useDimensions()` at the
-[Official Webrix Documentation Site](https://webrix.amdocs.com/docs/hooks/useDimensions)
\ No newline at end of file
diff --git a/src/hooks/useMounted/index.js b/src/hooks/useMounted/index.js
index 7f7b31e..dc4a5c8 100644
--- a/src/hooks/useMounted/index.js
+++ b/src/hooks/useMounted/index.js
@@ -15,5 +15,4 @@
*/
import {useMounted} from './useMounted';
-export {useUnmounted} from './useMounted';
export default useMounted;
\ No newline at end of file
diff --git a/src/hooks/useMounted/useMounted.js b/src/hooks/useMounted/useMounted.js
index e662fc4..7092099 100644
--- a/src/hooks/useMounted/useMounted.js
+++ b/src/hooks/useMounted/useMounted.js
@@ -20,13 +20,6 @@ export const useMounted = () => {
const mounted = useRef(false);
useEffect(() => {
mounted.current = true;
- return () => mounted.current = false;
}, []);
return mounted.current;
-};
-
-export const useUnmounted = () => {
- const unmounted = useRef(false);
- useEffect(() => () => {unmounted.current = true}, []);
- return unmounted.current;
};
\ No newline at end of file
diff --git a/src/hooks/useMounted/useMounted.test.js b/src/hooks/useMounted/useMounted.test.js
index 80819b1..c172f02 100644
--- a/src/hooks/useMounted/useMounted.test.js
+++ b/src/hooks/useMounted/useMounted.test.js
@@ -1,7 +1,7 @@
import React from 'react';
import {act} from 'react-dom/test-utils';
import {mount} from 'enzyme';
-import {useMounted, useUnmounted} from './useMounted';
+import {useMounted} from './useMounted';
describe('useMounted()', () => {
it('Should return the previous value', () => {
@@ -20,21 +20,3 @@ describe('useMounted()', () => {
expect(wrapper.find('.unmounted').length).toEqual(0);
});
});
-
-describe('useUnmounted()', () => {
- it('Should return the previous value', () => {
- const Elem = () => {
- const unmounted = useUnmounted();
- return (
-
- );
- };
- let wrapper = null;
- act(() => {wrapper = mount()});
- expect(wrapper.find('.unmounted').length).toEqual(0);
- expect(wrapper.find('.mounted').length).toEqual(1);
- wrapper.setProps({foo: 'bar'}); // Force an update...
- expect(wrapper.find('.mounted').length).toEqual(1);
- expect(wrapper.find('.unmounted').length).toEqual(0);
- });
-});
\ No newline at end of file
diff --git a/src/hooks/useDimensions/index.js b/src/hooks/useResizeObserver/index.js
similarity index 87%
rename from src/hooks/useDimensions/index.js
rename to src/hooks/useResizeObserver/index.js
index c64fd73..9596d5a 100644
--- a/src/hooks/useDimensions/index.js
+++ b/src/hooks/useResizeObserver/index.js
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-import useDimensions from './useDimensions';
+import useResizeObserver from './useResizeObserver';
-export default useDimensions;
\ No newline at end of file
+export default useResizeObserver;
\ No newline at end of file
diff --git a/src/hooks/useResizeObserver/readme.md b/src/hooks/useResizeObserver/readme.md
new file mode 100644
index 0000000..ed9847e
--- /dev/null
+++ b/src/hooks/useResizeObserver/readme.md
@@ -0,0 +1,2 @@
+See the full documentation of `useResizeObserver` at the
+[Official Webrix Documentation Site](https://webrix.amdocs.com/docs/hooks/useResizeObserver)
\ No newline at end of file
diff --git a/src/hooks/useDimensions/useDimensions.js b/src/hooks/useResizeObserver/useResizeObserver.js
similarity index 100%
rename from src/hooks/useDimensions/useDimensions.js
rename to src/hooks/useResizeObserver/useResizeObserver.js
diff --git a/src/hooks/useDimensions/useDimensions.test.js b/src/hooks/useResizeObserver/useResizeObserver.test.js
similarity index 81%
rename from src/hooks/useDimensions/useDimensions.test.js
rename to src/hooks/useResizeObserver/useResizeObserver.test.js
index b6c6321..8f05046 100644
--- a/src/hooks/useDimensions/useDimensions.test.js
+++ b/src/hooks/useResizeObserver/useResizeObserver.test.js
@@ -1,16 +1,16 @@
import React from 'react';
import {act} from 'react-dom/test-utils';
import {mount} from 'enzyme';
-import useDimensions, {__RewireAPI__ as rewireAPI} from './useDimensions';
+import useResizeObserver, {__RewireAPI__ as rewireAPI} from './useResizeObserver';
const Elem = () => {
- const {width, height} = useDimensions({current: {}});
+ const {width, height} = useResizeObserver({current: {}});
return (
{width},{height}
);
};
-describe('useDimensions()', () => {
+describe('useResizeObserver()', () => {
it('Should return the previous value', async () => {
let wrapper = null;
let observed = 0, disconnected = 0;
diff --git a/src/tools/ClickOutside/ClickOutside.jsx b/src/tools/ClickOutside/ClickOutside.jsx
new file mode 100644
index 0000000..2a34ae1
--- /dev/null
+++ b/src/tools/ClickOutside/ClickOutside.jsx
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2020, Amdocs Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import {func, node} from 'prop-types';
+import OverrideContext from 'hooks/useClickOutside/useClickOutside.context';
+import {useClickOutside} from 'hooks';
+
+export const ClickOutside = ({children, onClickOutside}) => {
+ const handleOnMouseDownCapture = useClickOutside(onClickOutside);
+ // We're updating the contained element instead of adding a wrapper since adding
+ // a wrapper can may affect the styling/behavior
+ return React.cloneElement(
+ React.Children.only(children), {onMouseDownCapture: handleOnMouseDownCapture}
+ );
+};
+
+// It is sometimes necessary to modify the condition of the click-outside handler
+// of one or more elements. This can be done using the ClickOutsideOverride
+export const ClickOutsideOverride = ({condition, children}) => (
+
+ {children}
+
+);
+
+ClickOutsideOverride.propTypes = {
+ condition: func,
+ children: node,
+};
\ No newline at end of file
diff --git a/src/tools/ClickOutside/ClickOutside.test.js b/src/tools/ClickOutside/ClickOutside.test.js
new file mode 100644
index 0000000..e30911e
--- /dev/null
+++ b/src/tools/ClickOutside/ClickOutside.test.js
@@ -0,0 +1,18 @@
+import React from 'react';
+// https://reactjs.org/docs/hooks-faq.html#how-to-test-components-that-use-hooks
+import { shallow} from 'enzyme';
+import OverrideContext from 'hooks/useClickOutside/useClickOutside.context';
+import {ClickOutside, ClickOutsideOverride} from './ClickOutside';
+
+describe('ClickOutside', () => {
+ it('', () => {
+ const wrapper = shallow();
+ expect(() => shallow()).toThrow();
+ expect(typeof wrapper.find('div').prop('onMouseDownCapture')).toBe('function');
+ });
+
+ it('', () => {
+ const wrapper = shallow();
+ expect(wrapper.find(OverrideContext.Provider)).toHaveLength(1);
+ });
+});
diff --git a/src/tools/ClickOutside/index.js b/src/tools/ClickOutside/index.js
new file mode 100644
index 0000000..5bb1ed7
--- /dev/null
+++ b/src/tools/ClickOutside/index.js
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2020, Amdocs Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {ClickOutside} from './ClickOutside';
+export {ClickOutsideOverride} from './ClickOutside';
+export default ClickOutside;
diff --git a/src/tools/index.js b/src/tools/index.js
index ec9a1db..ddb4561 100644
--- a/src/tools/index.js
+++ b/src/tools/index.js
@@ -1,2 +1,3 @@
export {default as ResizeObserver} from './ResizeObserver';
-export {default as Puppeteer, puppet} from './Puppeteer';
\ No newline at end of file
+export {default as Puppeteer, puppet} from './Puppeteer';
+export {default as ClickOutside, ClickOutsideOverride} from './ClickOutside';
\ No newline at end of file
diff --git a/src/utility/object/object.test.js b/src/utility/object/object.test.js
index 54fbe78..bc8d362 100644
--- a/src/utility/object/object.test.js
+++ b/src/utility/object/object.test.js
@@ -1,4 +1,4 @@
-import {get, set, isEqual, omit, clone} from './object';
+import {get, set, isEqual, omit, clone, EqualityIterators} from './object';
describe('Object', () => {
@@ -86,6 +86,32 @@ describe('Object', () => {
expect(isEqual(parent1, parent2)).toEqual(false);
});
+ it('isEqual() with shallow comparison', () => {
+ expect(isEqual(1, 1, EqualityIterators.SHALLOW)).toEqual(true);
+ expect(isEqual(true, false, EqualityIterators.SHALLOW)).toEqual(false);
+ expect(isEqual('hello', 'hello', EqualityIterators.SHALLOW)).toEqual(true);
+ expect(isEqual([1, 2, 3], [1, 2, 3], EqualityIterators.SHALLOW)).toEqual(true);
+ expect(isEqual([1, 2, 3], [3, 2, 1], EqualityIterators.SHALLOW)).toEqual(false);
+ expect(isEqual([{id: 1}], [{id: 2}], EqualityIterators.SHALLOW)).toEqual(false);
+ expect(isEqual({foo: 'bar'}, {foo: 'bar'}, EqualityIterators.SHALLOW)).toEqual(true);
+ expect(isEqual({foo: 'bar'}, {bar: 'foo'}, EqualityIterators.SHALLOW)).toEqual(false);
+ expect(isEqual({foo: [1, 2, {a: 1}]}, {foo: [1, 2, {a: 1}]}, EqualityIterators.SHALLOW)).toEqual(false);
+ expect(isEqual({foo: [1, 2, {a: 1}]}, {foo: [1, 2, {a: 2}]}, EqualityIterators.SHALLOW)).toEqual(false);
+
+ /* Check Circular Traversal */
+ const sub1 = {foo: [1, 2, {a: 1}]};
+ const sub2 = {foo: [1, 2, {a: 1}]};
+ const parent1 = {foo: [1, 2, {a: 1}], sub1, sub2};
+ const parent2 = {foo: [1, 2, {a: 1}], sub1, sub2};
+ parent1.aaa = parent2;
+ parent1.bbb = parent1;
+ parent2.aaa = parent1;
+ parent2.bbb = parent2;
+ expect(isEqual(parent1, parent2, EqualityIterators.SHALLOW)).toEqual(false);
+ parent2.ccc = 6;
+ expect(isEqual(parent1, parent2, EqualityIterators.SHALLOW)).toEqual(false);
+ });
+
it('clone()', () => {
const source = {foo: 1, bar: 'hello', baz: {baq: 23, test: [1, 2, 3]}};
const target = clone(source);