@atlaskit/react-select 2.2.0 → 2.2.1
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.
- package/CHANGELOG.md +8 -0
- package/dist/cjs/emotion/components/containers.js +111 -0
- package/dist/cjs/emotion/components/control.js +110 -0
- package/dist/cjs/emotion/components/group.js +71 -0
- package/dist/cjs/emotion/components/index.js +52 -0
- package/dist/cjs/emotion/components/indicators.js +137 -0
- package/dist/cjs/emotion/components/input.js +94 -0
- package/dist/cjs/emotion/components/internal/a11y-text.js +36 -0
- package/dist/cjs/emotion/components/internal/dummy-input.js +44 -0
- package/dist/cjs/emotion/components/internal/index.js +34 -0
- package/dist/cjs/emotion/components/internal/notify-open-layer-observer.js +21 -0
- package/dist/cjs/emotion/components/internal/required-input.js +43 -0
- package/dist/cjs/emotion/components/internal/scroll-manager.js +57 -0
- package/dist/cjs/emotion/components/internal/use-scroll-capture.js +132 -0
- package/dist/cjs/emotion/components/internal/use-scroll-lock.js +149 -0
- package/dist/cjs/emotion/components/live-region.js +182 -0
- package/dist/cjs/emotion/components/menu.js +456 -0
- package/dist/cjs/emotion/components/multi-value.js +224 -0
- package/dist/cjs/emotion/components/option.js +82 -0
- package/dist/cjs/emotion/components/placeholder.js +34 -0
- package/dist/cjs/emotion/components/single-value.js +40 -0
- package/dist/es2019/emotion/components/containers.js +109 -0
- package/dist/es2019/emotion/components/control.js +107 -0
- package/dist/es2019/emotion/components/group.js +59 -0
- package/dist/es2019/emotion/components/index.js +41 -0
- package/dist/es2019/emotion/components/indicators.js +128 -0
- package/dist/es2019/emotion/components/input.js +86 -0
- package/dist/es2019/emotion/components/internal/a11y-text.js +27 -0
- package/dist/es2019/emotion/components/internal/dummy-input.js +37 -0
- package/dist/es2019/emotion/components/internal/index.js +4 -0
- package/dist/es2019/emotion/components/internal/notify-open-layer-observer.js +16 -0
- package/dist/es2019/emotion/components/internal/required-input.js +35 -0
- package/dist/es2019/emotion/components/internal/scroll-manager.js +49 -0
- package/dist/es2019/emotion/components/internal/use-scroll-capture.js +128 -0
- package/dist/es2019/emotion/components/internal/use-scroll-lock.js +143 -0
- package/dist/es2019/emotion/components/live-region.js +178 -0
- package/dist/es2019/emotion/components/menu.js +450 -0
- package/dist/es2019/emotion/components/multi-value.js +227 -0
- package/dist/es2019/emotion/components/option.js +78 -0
- package/dist/es2019/emotion/components/placeholder.js +28 -0
- package/dist/es2019/emotion/components/single-value.js +34 -0
- package/dist/esm/emotion/components/containers.js +105 -0
- package/dist/esm/emotion/components/control.js +103 -0
- package/dist/esm/emotion/components/group.js +65 -0
- package/dist/esm/emotion/components/index.js +43 -0
- package/dist/esm/emotion/components/indicators.js +132 -0
- package/dist/esm/emotion/components/input.js +89 -0
- package/dist/esm/emotion/components/internal/a11y-text.js +29 -0
- package/dist/esm/emotion/components/internal/dummy-input.js +38 -0
- package/dist/esm/emotion/components/internal/index.js +4 -0
- package/dist/esm/emotion/components/internal/notify-open-layer-observer.js +15 -0
- package/dist/esm/emotion/components/internal/required-input.js +36 -0
- package/dist/esm/emotion/components/internal/scroll-manager.js +49 -0
- package/dist/esm/emotion/components/internal/use-scroll-capture.js +126 -0
- package/dist/esm/emotion/components/internal/use-scroll-lock.js +143 -0
- package/dist/esm/emotion/components/live-region.js +175 -0
- package/dist/esm/emotion/components/menu.js +454 -0
- package/dist/esm/emotion/components/multi-value.js +217 -0
- package/dist/esm/emotion/components/option.js +75 -0
- package/dist/esm/emotion/components/placeholder.js +27 -0
- package/dist/esm/emotion/components/single-value.js +33 -0
- package/dist/types/emotion/components/containers.d.ts +54 -0
- package/dist/types/emotion/components/control.d.ts +42 -0
- package/dist/types/emotion/components/group.d.ts +52 -0
- package/dist/types/emotion/components/index.d.ts +67 -0
- package/dist/types/emotion/components/indicators.d.ts +73 -0
- package/dist/types/emotion/components/input.d.ts +37 -0
- package/dist/types/emotion/components/internal/a11y-text.d.ts +8 -0
- package/dist/types/emotion/components/internal/dummy-input.d.ts +9 -0
- package/dist/types/emotion/components/internal/index.d.ts +4 -0
- package/dist/types/emotion/components/internal/notify-open-layer-observer.d.ts +11 -0
- package/dist/types/emotion/components/internal/required-input.d.ts +10 -0
- package/dist/types/emotion/components/internal/scroll-manager.d.ts +17 -0
- package/dist/types/emotion/components/internal/use-scroll-capture.d.ts +12 -0
- package/dist/types/emotion/components/internal/use-scroll-lock.d.ts +9 -0
- package/dist/types/emotion/components/live-region.d.ts +25 -0
- package/dist/types/emotion/components/menu.d.ts +116 -0
- package/dist/types/emotion/components/multi-value.d.ts +47 -0
- package/dist/types/emotion/components/option.d.ts +49 -0
- package/dist/types/emotion/components/placeholder.d.ts +22 -0
- package/dist/types/emotion/components/single-value.d.ts +28 -0
- package/dist/types-ts4.5/emotion/components/containers.d.ts +54 -0
- package/dist/types-ts4.5/emotion/components/control.d.ts +42 -0
- package/dist/types-ts4.5/emotion/components/group.d.ts +52 -0
- package/dist/types-ts4.5/emotion/components/index.d.ts +67 -0
- package/dist/types-ts4.5/emotion/components/indicators.d.ts +73 -0
- package/dist/types-ts4.5/emotion/components/input.d.ts +37 -0
- package/dist/types-ts4.5/emotion/components/internal/a11y-text.d.ts +8 -0
- package/dist/types-ts4.5/emotion/components/internal/dummy-input.d.ts +9 -0
- package/dist/types-ts4.5/emotion/components/internal/index.d.ts +4 -0
- package/dist/types-ts4.5/emotion/components/internal/notify-open-layer-observer.d.ts +11 -0
- package/dist/types-ts4.5/emotion/components/internal/required-input.d.ts +10 -0
- package/dist/types-ts4.5/emotion/components/internal/scroll-manager.d.ts +17 -0
- package/dist/types-ts4.5/emotion/components/internal/use-scroll-capture.d.ts +12 -0
- package/dist/types-ts4.5/emotion/components/internal/use-scroll-lock.d.ts +9 -0
- package/dist/types-ts4.5/emotion/components/live-region.d.ts +25 -0
- package/dist/types-ts4.5/emotion/components/menu.d.ts +116 -0
- package/dist/types-ts4.5/emotion/components/multi-value.d.ts +47 -0
- package/dist/types-ts4.5/emotion/components/option.d.ts +49 -0
- package/dist/types-ts4.5/emotion/components/placeholder.d.ts +22 -0
- package/dist/types-ts4.5/emotion/components/single-value.d.ts +28 -0
- package/package.json +1 -1
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
/**
|
|
3
|
+
* @jsxRuntime classic
|
|
4
|
+
* @jsx jsx
|
|
5
|
+
*/
|
|
6
|
+
import { css, jsx } from '@emotion/react';
|
|
7
|
+
|
|
8
|
+
// Assistive text to describe visual elements. Hidden for sighted users.
|
|
9
|
+
var styles = css({
|
|
10
|
+
width: 1,
|
|
11
|
+
height: 1,
|
|
12
|
+
padding: 0,
|
|
13
|
+
position: 'absolute',
|
|
14
|
+
zIndex: 9999,
|
|
15
|
+
border: 0,
|
|
16
|
+
clip: 'rect(1px, 1px, 1px, 1px)',
|
|
17
|
+
label: 'a11yText',
|
|
18
|
+
overflow: 'hidden',
|
|
19
|
+
userSelect: 'none',
|
|
20
|
+
// while hidden text is sitting in the DOM, it should not be selectable
|
|
21
|
+
whiteSpace: 'nowrap'
|
|
22
|
+
});
|
|
23
|
+
var A11yText = function A11yText(props) {
|
|
24
|
+
return jsx("span", _extends({
|
|
25
|
+
css: styles
|
|
26
|
+
// eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props
|
|
27
|
+
}, props));
|
|
28
|
+
};
|
|
29
|
+
export default A11yText;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
3
|
+
var _excluded = ["innerRef"];
|
|
4
|
+
/**
|
|
5
|
+
* @jsxRuntime classic
|
|
6
|
+
* @jsx jsx
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { css, jsx } from '@emotion/react';
|
|
10
|
+
import { removeProps } from '../../../utils';
|
|
11
|
+
var dummyInputStyles = css({
|
|
12
|
+
width: 1,
|
|
13
|
+
padding: 0,
|
|
14
|
+
position: 'relative',
|
|
15
|
+
background: 0,
|
|
16
|
+
border: 0,
|
|
17
|
+
caretColor: 'transparent',
|
|
18
|
+
color: 'transparent',
|
|
19
|
+
// eslint-disable-next-line @atlaskit/design-system/use-tokens-typography
|
|
20
|
+
fontSize: 'inherit',
|
|
21
|
+
gridArea: '1 / 1 / 2 / 3',
|
|
22
|
+
insetInlineStart: -100,
|
|
23
|
+
label: 'dummyInput',
|
|
24
|
+
opacity: 0,
|
|
25
|
+
outline: 0,
|
|
26
|
+
transform: 'scale(.01)'
|
|
27
|
+
});
|
|
28
|
+
export default function DummyInput(_ref) {
|
|
29
|
+
var innerRef = _ref.innerRef,
|
|
30
|
+
props = _objectWithoutProperties(_ref, _excluded);
|
|
31
|
+
// Remove animation props not meant for HTML elements
|
|
32
|
+
var filteredProps = removeProps(props, 'onExited', 'in', 'enter', 'exit', 'appear');
|
|
33
|
+
return jsx("input", _extends({
|
|
34
|
+
ref: innerRef
|
|
35
|
+
}, filteredProps, {
|
|
36
|
+
css: dummyInputStyles
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useNotifyOpenLayerObserver } from '@atlaskit/layering/experimental/open-layer-observer';
|
|
2
|
+
/**
|
|
3
|
+
* Functional component wrapper around `useNotifyOpenLayerObserver`.
|
|
4
|
+
*
|
|
5
|
+
* This is needed as Select is a class component, which cannot use hooks directly.
|
|
6
|
+
*/
|
|
7
|
+
export function NotifyOpenLayerObserver(_ref) {
|
|
8
|
+
var isOpen = _ref.isOpen,
|
|
9
|
+
onClose = _ref.onClose;
|
|
10
|
+
useNotifyOpenLayerObserver({
|
|
11
|
+
isOpen: isOpen,
|
|
12
|
+
onClose: onClose
|
|
13
|
+
});
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jsxRuntime classic
|
|
3
|
+
* @jsx jsx
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { css, jsx } from '@emotion/react';
|
|
7
|
+
import __noop from '@atlaskit/ds-lib/noop';
|
|
8
|
+
var styles = css({
|
|
9
|
+
width: '100%',
|
|
10
|
+
position: 'absolute',
|
|
11
|
+
insetBlockEnd: 0,
|
|
12
|
+
insetInlineEnd: 0,
|
|
13
|
+
insetInlineStart: 0,
|
|
14
|
+
label: 'requiredInput',
|
|
15
|
+
opacity: 0,
|
|
16
|
+
pointerEvents: 'none'
|
|
17
|
+
});
|
|
18
|
+
var RequiredInput = function RequiredInput(_ref) {
|
|
19
|
+
var name = _ref.name,
|
|
20
|
+
onFocus = _ref.onFocus;
|
|
21
|
+
return jsx("input", {
|
|
22
|
+
required: true,
|
|
23
|
+
name: name,
|
|
24
|
+
tabIndex: -1,
|
|
25
|
+
"aria-hidden": "true",
|
|
26
|
+
onFocus: onFocus,
|
|
27
|
+
css: styles
|
|
28
|
+
// Prevent `Switching from uncontrolled to controlled` error
|
|
29
|
+
,
|
|
30
|
+
value: "",
|
|
31
|
+
onChange: __noop
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// eslint-disable-next-line @repo/internal/react/require-jsdoc
|
|
36
|
+
export default RequiredInput;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jsxRuntime classic
|
|
3
|
+
* @jsx jsx
|
|
4
|
+
*/
|
|
5
|
+
import { Fragment } from 'react';
|
|
6
|
+
import { css, jsx } from '@emotion/react';
|
|
7
|
+
import useScrollCapture from './use-scroll-capture';
|
|
8
|
+
import useScrollLock from './use-scroll-lock';
|
|
9
|
+
var styles = css({
|
|
10
|
+
position: 'fixed',
|
|
11
|
+
insetBlockEnd: 0,
|
|
12
|
+
insetBlockStart: 0,
|
|
13
|
+
insetInlineEnd: 0,
|
|
14
|
+
insetInlineStart: 0
|
|
15
|
+
});
|
|
16
|
+
var blurSelectInput = function blurSelectInput(event) {
|
|
17
|
+
var element = event.target;
|
|
18
|
+
return element.ownerDocument.activeElement && element.ownerDocument.activeElement.blur();
|
|
19
|
+
};
|
|
20
|
+
export default function ScrollManager(_ref) {
|
|
21
|
+
var children = _ref.children,
|
|
22
|
+
lockEnabled = _ref.lockEnabled,
|
|
23
|
+
_ref$captureEnabled = _ref.captureEnabled,
|
|
24
|
+
captureEnabled = _ref$captureEnabled === void 0 ? true : _ref$captureEnabled,
|
|
25
|
+
onBottomArrive = _ref.onBottomArrive,
|
|
26
|
+
onBottomLeave = _ref.onBottomLeave,
|
|
27
|
+
onTopArrive = _ref.onTopArrive,
|
|
28
|
+
onTopLeave = _ref.onTopLeave;
|
|
29
|
+
var setScrollCaptureTarget = useScrollCapture({
|
|
30
|
+
isEnabled: captureEnabled,
|
|
31
|
+
onBottomArrive: onBottomArrive,
|
|
32
|
+
onBottomLeave: onBottomLeave,
|
|
33
|
+
onTopArrive: onTopArrive,
|
|
34
|
+
onTopLeave: onTopLeave
|
|
35
|
+
});
|
|
36
|
+
var setScrollLockTarget = useScrollLock({
|
|
37
|
+
isEnabled: lockEnabled
|
|
38
|
+
});
|
|
39
|
+
var targetRef = function targetRef(element) {
|
|
40
|
+
setScrollCaptureTarget(element);
|
|
41
|
+
setScrollLockTarget(element);
|
|
42
|
+
};
|
|
43
|
+
return jsx(Fragment, null, lockEnabled &&
|
|
44
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
|
45
|
+
jsx("div", {
|
|
46
|
+
onClick: blurSelectInput,
|
|
47
|
+
css: styles
|
|
48
|
+
}), children(targetRef));
|
|
49
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
import { supportsPassiveEvents } from '../../../utils';
|
|
3
|
+
var cancelScroll = function cancelScroll(event) {
|
|
4
|
+
if (event.cancelable) {
|
|
5
|
+
event.preventDefault();
|
|
6
|
+
}
|
|
7
|
+
event.stopPropagation();
|
|
8
|
+
};
|
|
9
|
+
// TODO: Fill in the hook {description}.
|
|
10
|
+
/**
|
|
11
|
+
* {description}.
|
|
12
|
+
*/
|
|
13
|
+
export default function useScrollCapture(_ref) {
|
|
14
|
+
var isEnabled = _ref.isEnabled,
|
|
15
|
+
onBottomArrive = _ref.onBottomArrive,
|
|
16
|
+
onBottomLeave = _ref.onBottomLeave,
|
|
17
|
+
onTopArrive = _ref.onTopArrive,
|
|
18
|
+
onTopLeave = _ref.onTopLeave;
|
|
19
|
+
var isBottom = useRef(false);
|
|
20
|
+
var isTop = useRef(false);
|
|
21
|
+
var touchStart = useRef(0);
|
|
22
|
+
var scrollTarget = useRef(null);
|
|
23
|
+
var handleEventDelta = useCallback(function (event, delta) {
|
|
24
|
+
if (scrollTarget.current === null) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
var _scrollTarget$current = scrollTarget.current,
|
|
28
|
+
scrollTop = _scrollTarget$current.scrollTop,
|
|
29
|
+
scrollHeight = _scrollTarget$current.scrollHeight,
|
|
30
|
+
clientHeight = _scrollTarget$current.clientHeight;
|
|
31
|
+
var target = scrollTarget.current;
|
|
32
|
+
var isDeltaPositive = delta > 0;
|
|
33
|
+
var availableScroll = scrollHeight - clientHeight - scrollTop;
|
|
34
|
+
var shouldCancelScroll = false;
|
|
35
|
+
|
|
36
|
+
// reset bottom/top flags
|
|
37
|
+
if (availableScroll > delta && isBottom.current) {
|
|
38
|
+
if (onBottomLeave) {
|
|
39
|
+
onBottomLeave(event);
|
|
40
|
+
}
|
|
41
|
+
isBottom.current = false;
|
|
42
|
+
}
|
|
43
|
+
if (isDeltaPositive && isTop.current) {
|
|
44
|
+
if (onTopLeave) {
|
|
45
|
+
onTopLeave(event);
|
|
46
|
+
}
|
|
47
|
+
isTop.current = false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// bottom limit
|
|
51
|
+
if (isDeltaPositive && delta > availableScroll) {
|
|
52
|
+
if (onBottomArrive && !isBottom.current) {
|
|
53
|
+
onBottomArrive(event);
|
|
54
|
+
}
|
|
55
|
+
target.scrollTop = scrollHeight;
|
|
56
|
+
shouldCancelScroll = true;
|
|
57
|
+
isBottom.current = true;
|
|
58
|
+
|
|
59
|
+
// top limit
|
|
60
|
+
} else if (!isDeltaPositive && -delta > scrollTop) {
|
|
61
|
+
if (onTopArrive && !isTop.current) {
|
|
62
|
+
onTopArrive(event);
|
|
63
|
+
}
|
|
64
|
+
target.scrollTop = 0;
|
|
65
|
+
shouldCancelScroll = true;
|
|
66
|
+
isTop.current = true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// cancel scroll
|
|
70
|
+
if (shouldCancelScroll) {
|
|
71
|
+
cancelScroll(event);
|
|
72
|
+
}
|
|
73
|
+
}, [onBottomArrive, onBottomLeave, onTopArrive, onTopLeave]);
|
|
74
|
+
var onWheel = useCallback(function (event) {
|
|
75
|
+
handleEventDelta(event, event.deltaY);
|
|
76
|
+
}, [handleEventDelta]);
|
|
77
|
+
var onTouchStart = useCallback(function (event) {
|
|
78
|
+
// set touch start so we can calculate touchmove delta
|
|
79
|
+
touchStart.current = event.changedTouches[0].clientY;
|
|
80
|
+
}, []);
|
|
81
|
+
var onTouchMove = useCallback(function (event) {
|
|
82
|
+
var deltaY = touchStart.current - event.changedTouches[0].clientY;
|
|
83
|
+
handleEventDelta(event, deltaY);
|
|
84
|
+
}, [handleEventDelta]);
|
|
85
|
+
var startListening = useCallback(function (el) {
|
|
86
|
+
// bail early if no element is available to attach to
|
|
87
|
+
if (!el) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
var notPassive = supportsPassiveEvents ? {
|
|
91
|
+
passive: false
|
|
92
|
+
} : false;
|
|
93
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
94
|
+
el.addEventListener('wheel', onWheel, notPassive);
|
|
95
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
96
|
+
el.addEventListener('touchstart', onTouchStart, notPassive);
|
|
97
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
98
|
+
el.addEventListener('touchmove', onTouchMove, notPassive);
|
|
99
|
+
}, [onTouchMove, onTouchStart, onWheel]);
|
|
100
|
+
var stopListening = useCallback(function (el) {
|
|
101
|
+
// bail early if no element is available to detach from
|
|
102
|
+
if (!el) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
107
|
+
el.removeEventListener('wheel', onWheel, false);
|
|
108
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
109
|
+
el.removeEventListener('touchstart', onTouchStart, false);
|
|
110
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
111
|
+
el.removeEventListener('touchmove', onTouchMove, false);
|
|
112
|
+
}, [onTouchMove, onTouchStart, onWheel]);
|
|
113
|
+
useEffect(function () {
|
|
114
|
+
if (!isEnabled) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
var element = scrollTarget.current;
|
|
118
|
+
startListening(element);
|
|
119
|
+
return function () {
|
|
120
|
+
stopListening(element);
|
|
121
|
+
};
|
|
122
|
+
}, [isEnabled, startListening, stopListening]);
|
|
123
|
+
return function (element) {
|
|
124
|
+
scrollTarget.current = element;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
var STYLE_KEYS = ['boxSizing', 'height', 'overflow', 'paddingRight', 'position'];
|
|
3
|
+
var LOCK_STYLES = {
|
|
4
|
+
boxSizing: 'border-box',
|
|
5
|
+
// account for possible declaration `width: 100%;` on body
|
|
6
|
+
overflow: 'hidden',
|
|
7
|
+
position: 'relative',
|
|
8
|
+
height: '100%'
|
|
9
|
+
};
|
|
10
|
+
function preventTouchMove(e) {
|
|
11
|
+
e.preventDefault();
|
|
12
|
+
}
|
|
13
|
+
function allowTouchMove(e) {
|
|
14
|
+
e.stopPropagation();
|
|
15
|
+
}
|
|
16
|
+
function preventInertiaScroll() {
|
|
17
|
+
var top = this.scrollTop;
|
|
18
|
+
var totalScroll = this.scrollHeight;
|
|
19
|
+
var currentScroll = top + this.offsetHeight;
|
|
20
|
+
if (top === 0) {
|
|
21
|
+
this.scrollTop = 1;
|
|
22
|
+
} else if (currentScroll === totalScroll) {
|
|
23
|
+
this.scrollTop = top - 1;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// `ontouchstart` check works on most browsers
|
|
28
|
+
// `maxTouchPoints` works on IE10/11 and Surface
|
|
29
|
+
function isTouchDevice() {
|
|
30
|
+
// eslint-disable-next-line compat/compat
|
|
31
|
+
return 'ontouchstart' in window || navigator.maxTouchPoints;
|
|
32
|
+
}
|
|
33
|
+
var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
|
|
34
|
+
var activeScrollLocks = 0;
|
|
35
|
+
var listenerOptions = {
|
|
36
|
+
capture: false,
|
|
37
|
+
passive: false
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// TODO: Fill in the hook {description}.
|
|
41
|
+
/**
|
|
42
|
+
* {description}.
|
|
43
|
+
*/
|
|
44
|
+
export default function useScrollLock(_ref) {
|
|
45
|
+
var isEnabled = _ref.isEnabled,
|
|
46
|
+
_ref$accountForScroll = _ref.accountForScrollbars,
|
|
47
|
+
accountForScrollbars = _ref$accountForScroll === void 0 ? true : _ref$accountForScroll;
|
|
48
|
+
var originalStyles = useRef({});
|
|
49
|
+
var scrollTarget = useRef(null);
|
|
50
|
+
var addScrollLock = useCallback(function (touchScrollTarget) {
|
|
51
|
+
if (!canUseDOM) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
var target = document.body;
|
|
55
|
+
var targetStyle = target && target.style;
|
|
56
|
+
if (accountForScrollbars) {
|
|
57
|
+
// store any styles already applied to the body
|
|
58
|
+
STYLE_KEYS.forEach(function (key) {
|
|
59
|
+
var val = targetStyle && targetStyle[key];
|
|
60
|
+
originalStyles.current[key] = val;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// apply the lock styles and padding if this is the first scroll lock
|
|
65
|
+
if (accountForScrollbars && activeScrollLocks < 1) {
|
|
66
|
+
var currentPadding = parseInt(originalStyles.current.paddingRight, 10) || 0;
|
|
67
|
+
var clientWidth = document.body ? document.body.clientWidth : 0;
|
|
68
|
+
var adjustedPadding = window.innerWidth - clientWidth + currentPadding || 0;
|
|
69
|
+
Object.keys(LOCK_STYLES).forEach(function (key) {
|
|
70
|
+
var val = LOCK_STYLES[key];
|
|
71
|
+
if (targetStyle) {
|
|
72
|
+
targetStyle[key] = val;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
if (targetStyle) {
|
|
76
|
+
targetStyle.paddingRight = "".concat(adjustedPadding, "px");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// account for touch devices
|
|
81
|
+
if (target && isTouchDevice()) {
|
|
82
|
+
// Mobile Safari ignores { overflow: hidden } declaration on the body.
|
|
83
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
84
|
+
target.addEventListener('touchmove', preventTouchMove, listenerOptions);
|
|
85
|
+
|
|
86
|
+
// Allow scroll on provided target
|
|
87
|
+
if (touchScrollTarget) {
|
|
88
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
89
|
+
touchScrollTarget.addEventListener('touchstart', preventInertiaScroll, listenerOptions);
|
|
90
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
91
|
+
touchScrollTarget.addEventListener('touchmove', allowTouchMove, listenerOptions);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// increment active scroll locks
|
|
96
|
+
activeScrollLocks += 1;
|
|
97
|
+
}, [accountForScrollbars]);
|
|
98
|
+
var removeScrollLock = useCallback(function (touchScrollTarget) {
|
|
99
|
+
if (!canUseDOM) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
var target = document.body;
|
|
103
|
+
var targetStyle = target && target.style;
|
|
104
|
+
|
|
105
|
+
// safely decrement active scroll locks
|
|
106
|
+
activeScrollLocks = Math.max(activeScrollLocks - 1, 0);
|
|
107
|
+
|
|
108
|
+
// reapply original body styles, if any
|
|
109
|
+
if (accountForScrollbars && activeScrollLocks < 1) {
|
|
110
|
+
STYLE_KEYS.forEach(function (key) {
|
|
111
|
+
var val = originalStyles.current[key];
|
|
112
|
+
if (targetStyle) {
|
|
113
|
+
targetStyle[key] = val;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// remove touch listeners
|
|
119
|
+
if (target && isTouchDevice()) {
|
|
120
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
121
|
+
target.removeEventListener('touchmove', preventTouchMove, listenerOptions);
|
|
122
|
+
if (touchScrollTarget) {
|
|
123
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
124
|
+
touchScrollTarget.removeEventListener('touchstart', preventInertiaScroll, listenerOptions);
|
|
125
|
+
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
126
|
+
touchScrollTarget.removeEventListener('touchmove', allowTouchMove, listenerOptions);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}, [accountForScrollbars]);
|
|
130
|
+
useEffect(function () {
|
|
131
|
+
if (!isEnabled) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
var element = scrollTarget.current;
|
|
135
|
+
addScrollLock(element);
|
|
136
|
+
return function () {
|
|
137
|
+
removeScrollLock(element);
|
|
138
|
+
};
|
|
139
|
+
}, [isEnabled, addScrollLock, removeScrollLock]);
|
|
140
|
+
return function (element) {
|
|
141
|
+
scrollTarget.current = element;
|
|
142
|
+
};
|
|
143
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
/* eslint-disable @atlaskit/platform/ensure-feature-flag-prefix */
|
|
5
|
+
/**
|
|
6
|
+
* @jsxRuntime classic
|
|
7
|
+
* @jsx jsx
|
|
8
|
+
* @jsxFrag React.Fragment
|
|
9
|
+
*/
|
|
10
|
+
import React, { Fragment, useMemo, useRef } from 'react';
|
|
11
|
+
import { jsx } from '@emotion/react';
|
|
12
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
13
|
+
import { defaultAriaLiveMessages } from '../../accessibility';
|
|
14
|
+
import A11yText from './internal/a11y-text';
|
|
15
|
+
|
|
16
|
+
// ==============================
|
|
17
|
+
// Root Container
|
|
18
|
+
// ==============================
|
|
19
|
+
|
|
20
|
+
// eslint-disable-next-line @repo/internal/react/require-jsdoc
|
|
21
|
+
var LiveRegion = function LiveRegion(props) {
|
|
22
|
+
var ariaSelection = props.ariaSelection,
|
|
23
|
+
focusedOption = props.focusedOption,
|
|
24
|
+
focusedValue = props.focusedValue,
|
|
25
|
+
focusableOptions = props.focusableOptions,
|
|
26
|
+
isFocused = props.isFocused,
|
|
27
|
+
selectValue = props.selectValue,
|
|
28
|
+
selectProps = props.selectProps,
|
|
29
|
+
id = props.id,
|
|
30
|
+
isAppleDevice = props.isAppleDevice;
|
|
31
|
+
var ariaLiveMessages = selectProps.ariaLiveMessages,
|
|
32
|
+
getOptionLabel = selectProps.getOptionLabel,
|
|
33
|
+
inputValue = selectProps.inputValue,
|
|
34
|
+
isMulti = selectProps.isMulti,
|
|
35
|
+
isOptionDisabled = selectProps.isOptionDisabled,
|
|
36
|
+
isSearchable = selectProps.isSearchable,
|
|
37
|
+
label = selectProps.label,
|
|
38
|
+
menuIsOpen = selectProps.menuIsOpen,
|
|
39
|
+
options = selectProps.options,
|
|
40
|
+
screenReaderStatus = selectProps.screenReaderStatus,
|
|
41
|
+
tabSelectsValue = selectProps.tabSelectsValue,
|
|
42
|
+
isLoading = selectProps.isLoading;
|
|
43
|
+
var ariaLabel = selectProps['aria-label'] || label;
|
|
44
|
+
var ariaLive = selectProps['aria-live'];
|
|
45
|
+
|
|
46
|
+
// for safari, we will use minimum support from aria-live region
|
|
47
|
+
var isA11yImprovementEnabled = fg('design_system_select-a11y-improvement') && !isAppleDevice;
|
|
48
|
+
|
|
49
|
+
// Update aria live message configuration when prop changes
|
|
50
|
+
var messages = useMemo(function () {
|
|
51
|
+
return _objectSpread(_objectSpread({}, defaultAriaLiveMessages), ariaLiveMessages || {});
|
|
52
|
+
}, [ariaLiveMessages]);
|
|
53
|
+
|
|
54
|
+
// Update aria live selected option when prop changes
|
|
55
|
+
var ariaSelected = useMemo(function () {
|
|
56
|
+
var message = '';
|
|
57
|
+
if (isA11yImprovementEnabled && menuIsOpen) {
|
|
58
|
+
// we don't need to have selected message when the menu is open
|
|
59
|
+
return '';
|
|
60
|
+
}
|
|
61
|
+
if (ariaSelection && messages.onChange) {
|
|
62
|
+
var option = ariaSelection.option,
|
|
63
|
+
selectedOptions = ariaSelection.options,
|
|
64
|
+
removedValue = ariaSelection.removedValue,
|
|
65
|
+
removedValues = ariaSelection.removedValues,
|
|
66
|
+
value = ariaSelection.value;
|
|
67
|
+
// select-option when !isMulti does not return option so we assume selected option is value
|
|
68
|
+
var asOption = function asOption(val) {
|
|
69
|
+
return !Array.isArray(val) ? val : null;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// If there is just one item from the action then get its label
|
|
73
|
+
var selected = removedValue || option || asOption(value);
|
|
74
|
+
var _label = selected ? getOptionLabel(selected) : '';
|
|
75
|
+
|
|
76
|
+
// If there are multiple items from the action then return an array of labels
|
|
77
|
+
var multiSelected = selectedOptions || removedValues || undefined;
|
|
78
|
+
var labels = multiSelected ? multiSelected.map(getOptionLabel) : [];
|
|
79
|
+
if (isA11yImprovementEnabled && !_label && !labels.length) {
|
|
80
|
+
// return empty string if no labels provided
|
|
81
|
+
return '';
|
|
82
|
+
}
|
|
83
|
+
var onChangeProps = _objectSpread({
|
|
84
|
+
// multiSelected items are usually items that have already been selected
|
|
85
|
+
// or set by the user as a default value so we assume they are not disabled
|
|
86
|
+
isDisabled: selected && isOptionDisabled(selected, selectValue),
|
|
87
|
+
label: _label,
|
|
88
|
+
labels: labels
|
|
89
|
+
}, ariaSelection);
|
|
90
|
+
message = messages.onChange(onChangeProps);
|
|
91
|
+
}
|
|
92
|
+
return message;
|
|
93
|
+
}, [ariaSelection, messages, isOptionDisabled, selectValue, getOptionLabel, isA11yImprovementEnabled, menuIsOpen]);
|
|
94
|
+
var prevInputValue = useRef('');
|
|
95
|
+
var ariaFocused = useMemo(function () {
|
|
96
|
+
var focusMsg = '';
|
|
97
|
+
var focused = focusedOption || focusedValue;
|
|
98
|
+
var isSelected = !!(focusedOption && selectValue && selectValue.includes(focusedOption));
|
|
99
|
+
if (inputValue === prevInputValue.current && isA11yImprovementEnabled) {
|
|
100
|
+
// only announce focus option when searching when ff is on and the input value changed
|
|
101
|
+
// for safari, we will announce for all
|
|
102
|
+
return '';
|
|
103
|
+
}
|
|
104
|
+
if (focused && messages.onFocus) {
|
|
105
|
+
var onFocusProps = {
|
|
106
|
+
focused: focused,
|
|
107
|
+
label: getOptionLabel(focused),
|
|
108
|
+
isDisabled: isOptionDisabled(focused, selectValue),
|
|
109
|
+
isSelected: isSelected,
|
|
110
|
+
options: focusableOptions,
|
|
111
|
+
context: focused === focusedOption ? 'menu' : 'value',
|
|
112
|
+
selectValue: selectValue,
|
|
113
|
+
isMulti: isMulti
|
|
114
|
+
};
|
|
115
|
+
focusMsg = messages.onFocus(onFocusProps);
|
|
116
|
+
}
|
|
117
|
+
prevInputValue.current = inputValue;
|
|
118
|
+
return focusMsg;
|
|
119
|
+
}, [inputValue, focusedOption, focusedValue, getOptionLabel, isOptionDisabled, messages, focusableOptions, selectValue, isA11yImprovementEnabled, isMulti]);
|
|
120
|
+
var ariaResults = useMemo(function () {
|
|
121
|
+
var resultsMsg = '';
|
|
122
|
+
if (menuIsOpen && options.length && !isLoading && messages.onFilter) {
|
|
123
|
+
var resultsMessage = screenReaderStatus({
|
|
124
|
+
count: focusableOptions.length
|
|
125
|
+
});
|
|
126
|
+
resultsMsg = messages.onFilter({
|
|
127
|
+
inputValue: inputValue,
|
|
128
|
+
resultsMessage: resultsMessage
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return resultsMsg;
|
|
132
|
+
}, [focusableOptions, inputValue, menuIsOpen, messages, options, screenReaderStatus, isLoading]);
|
|
133
|
+
var isInitialFocus = (ariaSelection === null || ariaSelection === void 0 ? void 0 : ariaSelection.action) === 'initial-input-focus';
|
|
134
|
+
var ariaGuidance = useMemo(function () {
|
|
135
|
+
if (fg('design_system_select-a11y-improvement')) {
|
|
136
|
+
// don't announce guidance at all when ff is on
|
|
137
|
+
return '';
|
|
138
|
+
}
|
|
139
|
+
var guidanceMsg = '';
|
|
140
|
+
if (messages.guidance) {
|
|
141
|
+
var context = focusedValue ? 'value' : menuIsOpen ? 'menu' : 'input';
|
|
142
|
+
guidanceMsg = messages.guidance({
|
|
143
|
+
'aria-label': ariaLabel,
|
|
144
|
+
context: context,
|
|
145
|
+
isDisabled: focusedOption && isOptionDisabled(focusedOption, selectValue),
|
|
146
|
+
isMulti: isMulti,
|
|
147
|
+
isSearchable: isSearchable,
|
|
148
|
+
tabSelectsValue: tabSelectsValue,
|
|
149
|
+
isInitialFocus: isInitialFocus
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return guidanceMsg;
|
|
153
|
+
}, [ariaLabel, focusedOption, focusedValue, isMulti, isOptionDisabled, isSearchable, menuIsOpen, messages, selectValue, tabSelectsValue, isInitialFocus]);
|
|
154
|
+
var ScreenReaderText = jsx(Fragment, null, jsx("span", {
|
|
155
|
+
id: "aria-selection"
|
|
156
|
+
}, ariaSelected), jsx("span", {
|
|
157
|
+
id: "aria-results"
|
|
158
|
+
}, ariaResults), !fg('design_system_select-a11y-improvement') && jsx(React.Fragment, null, jsx("span", {
|
|
159
|
+
id: "aria-focused"
|
|
160
|
+
}, ariaFocused), jsx("span", {
|
|
161
|
+
id: "aria-guidance"
|
|
162
|
+
}, ariaGuidance)));
|
|
163
|
+
return jsx(Fragment, null, jsx(A11yText, {
|
|
164
|
+
id: id
|
|
165
|
+
}, isInitialFocus && ScreenReaderText), jsx(A11yText, {
|
|
166
|
+
"aria-live": ariaLive // Should be undefined by default unless a specific use case requires it
|
|
167
|
+
,
|
|
168
|
+
"aria-atomic": fg('design_system_select-a11y-improvement') ? undefined : 'false',
|
|
169
|
+
"aria-relevant": fg('design_system_select-a11y-improvement') ? undefined : 'additions text',
|
|
170
|
+
role: fg('design_system_select-a11y-improvement') ? 'status' : 'log'
|
|
171
|
+
}, isFocused && !isInitialFocus && ScreenReaderText));
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// eslint-disable-next-line @repo/internal/react/require-jsdoc
|
|
175
|
+
export default LiveRegion;
|