@atlaskit/emoji 67.0.7 → 67.2.0
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 +37 -0
- package/dist/cjs/api/EmojiResource.js +41 -25
- package/dist/cjs/api/media/TokenManager.js +4 -4
- package/dist/cjs/components/common/CachingEmoji.js +14 -6
- package/dist/cjs/components/common/Emoji.js +48 -12
- package/dist/cjs/components/common/EmojiActions.js +62 -26
- package/dist/cjs/components/common/EmojiErrorMessage.js +12 -7
- package/dist/cjs/components/common/EmojiPlaceholder.js +1 -0
- package/dist/cjs/components/common/{EmojiButton.js → EmojiRadioButton.js} +28 -19
- package/dist/cjs/components/common/EmojiUploadPicker.js +80 -37
- package/dist/cjs/components/common/EmojiUploadPreview.js +11 -2
- package/dist/cjs/components/common/FileChooser.js +2 -2
- package/dist/cjs/components/common/ResourcedEmojiComponent.js +4 -0
- package/dist/cjs/components/common/RetryableButton.js +7 -3
- package/dist/cjs/components/common/TonePreviewButton.js +44 -0
- package/dist/cjs/components/common/ToneSelector.js +53 -25
- package/dist/cjs/components/common/styles.js +45 -16
- package/dist/cjs/components/i18n.js +44 -4
- package/dist/cjs/components/picker/CategorySelector.js +112 -90
- package/dist/cjs/components/picker/CategoryTracker.js +0 -28
- package/dist/cjs/components/picker/EmojiPickerCategoryHeading.js +2 -1
- package/dist/cjs/components/picker/EmojiPickerComponent.js +33 -44
- package/dist/cjs/components/picker/EmojiPickerEmojiRow.js +32 -4
- package/dist/cjs/components/picker/EmojiPickerList.js +154 -88
- package/dist/cjs/components/picker/EmojiPickerListSearch.js +66 -117
- package/dist/cjs/components/picker/EmojiPickerVirtualItems.js +5 -2
- package/dist/cjs/components/picker/VirtualList.js +273 -171
- package/dist/cjs/components/picker/styles.js +43 -51
- package/dist/cjs/components/typeahead/EmojiTypeAheadComponent.js +0 -10
- package/dist/cjs/context/EmojiPickerListContext.js +33 -0
- package/dist/cjs/hooks/useEmojiPickerListContext.js +12 -0
- package/dist/cjs/hooks/useIsMounted.js +17 -0
- package/dist/cjs/i18n/cs.js +35 -34
- package/dist/cjs/i18n/da.js +35 -34
- package/dist/cjs/i18n/de.js +35 -34
- package/dist/cjs/i18n/en.js +35 -34
- package/dist/cjs/i18n/en_GB.js +35 -34
- package/dist/cjs/i18n/es.js +35 -34
- package/dist/cjs/i18n/fi.js +35 -34
- package/dist/cjs/i18n/fr.js +35 -34
- package/dist/cjs/i18n/hu.js +35 -34
- package/dist/cjs/i18n/it.js +35 -34
- package/dist/cjs/i18n/ja.js +35 -34
- package/dist/cjs/i18n/ko.js +35 -34
- package/dist/cjs/i18n/nb.js +35 -34
- package/dist/cjs/i18n/nl.js +35 -34
- package/dist/cjs/i18n/pl.js +35 -34
- package/dist/cjs/i18n/pt_BR.js +35 -34
- package/dist/cjs/i18n/ru.js +35 -34
- package/dist/cjs/i18n/sv.js +35 -34
- package/dist/cjs/i18n/th.js +35 -34
- package/dist/cjs/i18n/tr.js +35 -34
- package/dist/cjs/i18n/uk.js +35 -34
- package/dist/cjs/i18n/vi.js +35 -34
- package/dist/cjs/i18n/zh.js +35 -34
- package/dist/cjs/i18n/zh_TW.js +35 -34
- package/dist/cjs/types.js +7 -1
- package/dist/cjs/util/constants.js +43 -2
- package/dist/cjs/util/shared-styles.js +3 -4
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/api/EmojiResource.js +42 -26
- package/dist/es2019/api/media/TokenManager.js +4 -4
- package/dist/es2019/components/common/CachingEmoji.js +10 -3
- package/dist/es2019/components/common/Emoji.js +44 -11
- package/dist/es2019/components/common/EmojiActions.js +55 -24
- package/dist/es2019/components/common/EmojiErrorMessage.js +7 -3
- package/dist/es2019/components/common/EmojiPlaceholder.js +1 -0
- package/dist/es2019/components/common/EmojiRadioButton.js +54 -0
- package/dist/es2019/components/common/EmojiUploadPicker.js +75 -36
- package/dist/es2019/components/common/EmojiUploadPreview.js +11 -2
- package/dist/es2019/components/common/FileChooser.js +1 -1
- package/dist/es2019/components/common/ResourcedEmojiComponent.js +4 -0
- package/dist/es2019/components/common/RetryableButton.js +7 -3
- package/dist/es2019/components/common/TonePreviewButton.js +34 -0
- package/dist/es2019/components/common/ToneSelector.js +55 -21
- package/dist/es2019/components/common/styles.js +41 -10
- package/dist/es2019/components/i18n.js +44 -4
- package/dist/es2019/components/picker/CategorySelector.js +114 -89
- package/dist/es2019/components/picker/CategoryTracker.js +0 -24
- package/dist/es2019/components/picker/EmojiPickerCategoryHeading.js +2 -2
- package/dist/es2019/components/picker/EmojiPickerComponent.js +36 -46
- package/dist/es2019/components/picker/EmojiPickerEmojiRow.js +51 -21
- package/dist/es2019/components/picker/EmojiPickerList.js +113 -55
- package/dist/es2019/components/picker/EmojiPickerListSearch.js +61 -98
- package/dist/es2019/components/picker/EmojiPickerVirtualItems.js +4 -1
- package/dist/es2019/components/picker/VirtualList.js +247 -108
- package/dist/es2019/components/picker/styles.js +20 -28
- package/dist/es2019/components/typeahead/EmojiTypeAheadComponent.js +0 -10
- package/dist/es2019/context/EmojiPickerListContext.js +17 -0
- package/dist/es2019/hooks/useEmojiPickerListContext.js +3 -0
- package/dist/es2019/hooks/useIsMounted.js +11 -0
- package/dist/es2019/i18n/cs.js +35 -34
- package/dist/es2019/i18n/da.js +35 -34
- package/dist/es2019/i18n/de.js +35 -34
- package/dist/es2019/i18n/en.js +35 -34
- package/dist/es2019/i18n/en_GB.js +35 -34
- package/dist/es2019/i18n/es.js +35 -34
- package/dist/es2019/i18n/fi.js +35 -34
- package/dist/es2019/i18n/fr.js +35 -34
- package/dist/es2019/i18n/hu.js +35 -34
- package/dist/es2019/i18n/it.js +35 -34
- package/dist/es2019/i18n/ja.js +35 -34
- package/dist/es2019/i18n/ko.js +35 -34
- package/dist/es2019/i18n/nb.js +35 -34
- package/dist/es2019/i18n/nl.js +35 -34
- package/dist/es2019/i18n/pl.js +35 -34
- package/dist/es2019/i18n/pt_BR.js +35 -34
- package/dist/es2019/i18n/ru.js +35 -34
- package/dist/es2019/i18n/sv.js +35 -34
- package/dist/es2019/i18n/th.js +35 -34
- package/dist/es2019/i18n/tr.js +35 -34
- package/dist/es2019/i18n/uk.js +35 -34
- package/dist/es2019/i18n/vi.js +35 -34
- package/dist/es2019/i18n/zh.js +35 -34
- package/dist/es2019/i18n/zh_TW.js +35 -34
- package/dist/es2019/types.js +5 -0
- package/dist/es2019/util/constants.js +32 -0
- package/dist/es2019/util/shared-styles.js +1 -2
- package/dist/es2019/version.json +1 -1
- package/dist/esm/api/EmojiResource.js +42 -26
- package/dist/esm/api/media/TokenManager.js +4 -4
- package/dist/esm/components/common/CachingEmoji.js +14 -6
- package/dist/esm/components/common/Emoji.js +48 -12
- package/dist/esm/components/common/EmojiActions.js +62 -26
- package/dist/esm/components/common/EmojiErrorMessage.js +7 -3
- package/dist/esm/components/common/EmojiPlaceholder.js +1 -0
- package/dist/esm/components/common/EmojiRadioButton.js +52 -0
- package/dist/esm/components/common/EmojiUploadPicker.js +77 -36
- package/dist/esm/components/common/EmojiUploadPreview.js +11 -2
- package/dist/esm/components/common/FileChooser.js +1 -1
- package/dist/esm/components/common/ResourcedEmojiComponent.js +4 -0
- package/dist/esm/components/common/RetryableButton.js +7 -3
- package/dist/esm/components/common/TonePreviewButton.js +33 -0
- package/dist/esm/components/common/ToneSelector.js +49 -18
- package/dist/esm/components/common/styles.js +40 -12
- package/dist/esm/components/i18n.js +44 -4
- package/dist/esm/components/picker/CategorySelector.js +114 -95
- package/dist/esm/components/picker/CategoryTracker.js +0 -28
- package/dist/esm/components/picker/EmojiPickerCategoryHeading.js +2 -2
- package/dist/esm/components/picker/EmojiPickerComponent.js +35 -46
- package/dist/esm/components/picker/EmojiPickerEmojiRow.js +32 -4
- package/dist/esm/components/picker/EmojiPickerList.js +156 -86
- package/dist/esm/components/picker/EmojiPickerListSearch.js +64 -117
- package/dist/esm/components/picker/EmojiPickerVirtualItems.js +5 -2
- package/dist/esm/components/picker/VirtualList.js +274 -172
- package/dist/esm/components/picker/styles.js +37 -45
- package/dist/esm/components/typeahead/EmojiTypeAheadComponent.js +0 -10
- package/dist/esm/context/EmojiPickerListContext.js +21 -0
- package/dist/esm/hooks/useEmojiPickerListContext.js +5 -0
- package/dist/esm/hooks/useIsMounted.js +11 -0
- package/dist/esm/i18n/cs.js +35 -34
- package/dist/esm/i18n/da.js +35 -34
- package/dist/esm/i18n/de.js +35 -34
- package/dist/esm/i18n/en.js +35 -34
- package/dist/esm/i18n/en_GB.js +35 -34
- package/dist/esm/i18n/es.js +35 -34
- package/dist/esm/i18n/fi.js +35 -34
- package/dist/esm/i18n/fr.js +35 -34
- package/dist/esm/i18n/hu.js +35 -34
- package/dist/esm/i18n/it.js +35 -34
- package/dist/esm/i18n/ja.js +35 -34
- package/dist/esm/i18n/ko.js +35 -34
- package/dist/esm/i18n/nb.js +35 -34
- package/dist/esm/i18n/nl.js +35 -34
- package/dist/esm/i18n/pl.js +35 -34
- package/dist/esm/i18n/pt_BR.js +35 -34
- package/dist/esm/i18n/ru.js +35 -34
- package/dist/esm/i18n/sv.js +35 -34
- package/dist/esm/i18n/th.js +35 -34
- package/dist/esm/i18n/tr.js +35 -34
- package/dist/esm/i18n/uk.js +35 -34
- package/dist/esm/i18n/vi.js +35 -34
- package/dist/esm/i18n/zh.js +35 -34
- package/dist/esm/i18n/zh_TW.js +35 -34
- package/dist/esm/types.js +5 -0
- package/dist/esm/util/constants.js +32 -0
- package/dist/esm/util/shared-styles.js +1 -2
- package/dist/esm/version.json +1 -1
- package/dist/types/api/EmojiResource.d.ts +2 -0
- package/dist/types/components/common/Emoji.d.ts +7 -1
- package/dist/types/components/common/EmojiActions.d.ts +4 -3
- package/dist/types/components/common/{EmojiButton.d.ts → EmojiRadioButton.d.ts} +3 -4
- package/dist/types/components/common/EmojiUploadPicker.d.ts +6 -4
- package/dist/types/components/common/RetryableButton.d.ts +1 -0
- package/dist/types/components/common/TonePreviewButton.d.ts +14 -0
- package/dist/types/components/common/ToneSelector.d.ts +8 -5
- package/dist/types/components/common/internal-types.d.ts +9 -0
- package/dist/types/components/common/styles.d.ts +2 -1
- package/dist/types/components/i18n.d.ts +40 -0
- package/dist/types/components/picker/CategorySelector.d.ts +3 -10
- package/dist/types/components/picker/CategoryTracker.d.ts +0 -2
- package/dist/types/components/picker/EmojiPickerCategoryHeading.d.ts +2 -1
- package/dist/types/components/picker/EmojiPickerEmojiRow.d.ts +5 -0
- package/dist/types/components/picker/EmojiPickerList.d.ts +14 -7
- package/dist/types/components/picker/EmojiPickerListSearch.d.ts +4 -8
- package/dist/types/components/picker/EmojiPickerVirtualItems.d.ts +1 -1
- package/dist/types/components/picker/VirtualList.d.ts +7 -24
- package/dist/types/components/picker/styles.d.ts +1 -1
- package/dist/types/context/EmojiPickerListContext.d.ts +10 -0
- package/dist/types/hooks/useEmojiPickerListContext.d.ts +1 -0
- package/dist/types/hooks/useIsMounted.d.ts +1 -0
- package/dist/types/i18n/cs.d.ts +34 -34
- package/dist/types/i18n/da.d.ts +34 -34
- package/dist/types/i18n/de.d.ts +34 -34
- package/dist/types/i18n/en.d.ts +34 -34
- package/dist/types/i18n/en_GB.d.ts +34 -34
- package/dist/types/i18n/es.d.ts +34 -34
- package/dist/types/i18n/fi.d.ts +34 -34
- package/dist/types/i18n/fr.d.ts +34 -34
- package/dist/types/i18n/hu.d.ts +34 -34
- package/dist/types/i18n/it.d.ts +34 -34
- package/dist/types/i18n/ja.d.ts +34 -34
- package/dist/types/i18n/ko.d.ts +34 -34
- package/dist/types/i18n/nb.d.ts +34 -34
- package/dist/types/i18n/nl.d.ts +34 -34
- package/dist/types/i18n/pl.d.ts +34 -34
- package/dist/types/i18n/pt_BR.d.ts +34 -34
- package/dist/types/i18n/ru.d.ts +34 -34
- package/dist/types/i18n/sv.d.ts +34 -34
- package/dist/types/i18n/th.d.ts +34 -34
- package/dist/types/i18n/tr.d.ts +34 -34
- package/dist/types/i18n/uk.d.ts +34 -34
- package/dist/types/i18n/vi.d.ts +34 -34
- package/dist/types/i18n/zh.d.ts +34 -34
- package/dist/types/i18n/zh_TW.d.ts +34 -34
- package/dist/types/types.d.ts +5 -0
- package/dist/types/util/constants.d.ts +28 -0
- package/dist/types/util/shared-styles.d.ts +1 -1
- package/dist/types/util/type-helpers.d.ts +1 -1
- package/package.json +12 -8
- package/report.api.md +62 -1
- package/README.md +0 -3
- package/dist/cjs/components/hooks.js +0 -14
- package/dist/es2019/components/common/EmojiButton.js +0 -49
- package/dist/es2019/components/hooks.js +0 -8
- package/dist/esm/components/common/EmojiButton.js +0 -43
- package/dist/esm/components/hooks.js +0 -8
- package/dist/types/components/hooks.d.ts +0 -1
|
@@ -101,6 +101,10 @@ export const ResourcedEmojiComponent = props => {
|
|
|
101
101
|
}
|
|
102
102
|
fetchOrGetEmoji(resolvedEmojiProvider, emojiId, optimistic);
|
|
103
103
|
}, [resolvedEmojiProvider, emojiId, optimistic, fetchOrGetEmoji]);
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Setting resolved emoji provider for optimistic rendering
|
|
107
|
+
*/
|
|
104
108
|
useEffect(() => {
|
|
105
109
|
Promise.resolve(emojiProvider).then(emojiProvider => {
|
|
106
110
|
setResolvedEmojiProvider(emojiProvider);
|
|
@@ -21,20 +21,24 @@ const RetryButton = props => {
|
|
|
21
21
|
css: uploadRetryButton,
|
|
22
22
|
appearance: "warning",
|
|
23
23
|
onClick: onSubmit,
|
|
24
|
-
testId: retryUploadButtonTestId
|
|
24
|
+
testId: retryUploadButtonTestId,
|
|
25
|
+
autoFocus: true
|
|
25
26
|
}, retryLabel));
|
|
26
27
|
};
|
|
27
28
|
const UploadButton = props => {
|
|
28
29
|
const {
|
|
29
30
|
appearance,
|
|
30
31
|
onSubmit,
|
|
31
|
-
label
|
|
32
|
+
label,
|
|
33
|
+
ariaDescribedby
|
|
32
34
|
} = props;
|
|
33
35
|
return jsx(AkButton, {
|
|
34
36
|
css: uploadEmojiButton,
|
|
35
37
|
appearance: appearance,
|
|
36
38
|
onClick: onSubmit,
|
|
37
|
-
testId: uploadEmojiButtonTestId
|
|
39
|
+
testId: uploadEmojiButtonTestId,
|
|
40
|
+
"aria-describedby": ariaDescribedby,
|
|
41
|
+
autoFocus: true
|
|
38
42
|
}, label);
|
|
39
43
|
};
|
|
40
44
|
const RetryableButton = props => {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { forwardRef, memo } from 'react';
|
|
3
|
+
import { jsx } from '@emotion/react';
|
|
4
|
+
import { emojiButton, hidden } from './styles';
|
|
5
|
+
import Emoji from './Emoji';
|
|
6
|
+
export const tonePreviewTestId = 'tone-preview';
|
|
7
|
+
export const TonePreviewButton = /*#__PURE__*/forwardRef((props, ref) => {
|
|
8
|
+
const {
|
|
9
|
+
emoji,
|
|
10
|
+
selectOnHover,
|
|
11
|
+
ariaLabelText,
|
|
12
|
+
ariaExpanded,
|
|
13
|
+
onSelected,
|
|
14
|
+
isVisible = true
|
|
15
|
+
} = props;
|
|
16
|
+
return jsx("button", {
|
|
17
|
+
ref: ref,
|
|
18
|
+
css: [emojiButton, !isVisible && hidden],
|
|
19
|
+
onClick: onSelected,
|
|
20
|
+
"aria-label": ariaLabelText,
|
|
21
|
+
"aria-expanded": ariaExpanded,
|
|
22
|
+
"aria-controls": "emoji-picker-tone-selector",
|
|
23
|
+
style: {
|
|
24
|
+
overflow: 'hidden'
|
|
25
|
+
},
|
|
26
|
+
"data-testid": tonePreviewTestId
|
|
27
|
+
}, jsx(Emoji, {
|
|
28
|
+
emoji: emoji,
|
|
29
|
+
selectOnHover: selectOnHover,
|
|
30
|
+
shouldBeInteractive: false,
|
|
31
|
+
"aria-hidden": true
|
|
32
|
+
}));
|
|
33
|
+
});
|
|
34
|
+
export default /*#__PURE__*/memo(TonePreviewButton);
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { jsx } from '@emotion/react';
|
|
3
|
+
import { memo, useEffect, useMemo, useRef } from 'react';
|
|
3
4
|
import { withAnalyticsEvents } from '@atlaskit/analytics-next';
|
|
4
5
|
import { createAndFireEventInElementsChannel, toneSelectedEvent, toneSelectorOpenedEvent } from '../../util/analytics';
|
|
5
6
|
import { setSkinToneAriaLabelText } from './setSkinToneAriaLabelText';
|
|
7
|
+
import EmojiRadioButton from './EmojiRadioButton';
|
|
8
|
+
import { useIntl } from 'react-intl-next';
|
|
9
|
+
import { messages } from '../i18n';
|
|
10
|
+
import { hidden } from './styles';
|
|
11
|
+
export const toneSelectorTestId = 'tone-selector';
|
|
6
12
|
const extractAllTones = emoji => {
|
|
7
13
|
if (emoji.skinVariations) {
|
|
8
14
|
return [emoji, ...emoji.skinVariations];
|
|
@@ -13,30 +19,52 @@ export const ToneSelectorInternal = props => {
|
|
|
13
19
|
const {
|
|
14
20
|
createAnalyticsEvent,
|
|
15
21
|
emoji,
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
onToneSelected,
|
|
23
|
+
onToneClose,
|
|
24
|
+
selectedTone,
|
|
25
|
+
isVisible
|
|
18
26
|
} = props;
|
|
19
27
|
const isMounted = useRef(false);
|
|
20
|
-
const
|
|
28
|
+
const selectedToneRadioRef = useRef(null);
|
|
29
|
+
const {
|
|
30
|
+
formatMessage
|
|
31
|
+
} = useIntl();
|
|
21
32
|
const emojiToneCollection = useMemo(() => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
var selectedToneIndex = -1;
|
|
34
|
+
const toneColletion = extractAllTones(emoji).map((tone, index) => {
|
|
35
|
+
const isSelected = index === selectedTone;
|
|
36
|
+
if (isSelected) {
|
|
37
|
+
selectedToneIndex = index;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
...tone,
|
|
41
|
+
isSelected: isSelected,
|
|
42
|
+
label: setSkinToneAriaLabelText(tone.name),
|
|
43
|
+
toneIndex: index
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// push description of selected tone to the end of the array
|
|
48
|
+
// so that it gets rendered last/rightmost
|
|
49
|
+
toneColletion.push(toneColletion.splice(selectedToneIndex, 1)[0]);
|
|
50
|
+
return toneColletion;
|
|
51
|
+
}, [emoji, selectedTone]);
|
|
29
52
|
useEffect(() => {
|
|
30
|
-
if (
|
|
31
|
-
|
|
53
|
+
if (isVisible) {
|
|
54
|
+
var _selectedToneRadioRef;
|
|
55
|
+
(_selectedToneRadioRef = selectedToneRadioRef.current) === null || _selectedToneRadioRef === void 0 ? void 0 : _selectedToneRadioRef.focus();
|
|
32
56
|
}
|
|
33
|
-
}, [
|
|
57
|
+
}, [isVisible, selectedToneRadioRef]);
|
|
34
58
|
const fireAnalyticsEvent = event => {
|
|
35
59
|
if (createAnalyticsEvent) {
|
|
36
60
|
createAndFireEventInElementsChannel(event)(createAnalyticsEvent);
|
|
37
61
|
}
|
|
38
62
|
};
|
|
39
63
|
const onToneSelectedHandler = toneValue => () => {
|
|
64
|
+
if (selectedTone === toneValue && onToneClose) {
|
|
65
|
+
onToneClose();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
40
68
|
onToneSelected(toneValue);
|
|
41
69
|
const toneList = ['default', 'light', 'mediumLight', 'medium', 'mediumDark', 'dark'];
|
|
42
70
|
fireAnalyticsEvent(toneSelectedEvent({
|
|
@@ -47,17 +75,23 @@ export const ToneSelectorInternal = props => {
|
|
|
47
75
|
fireAnalyticsEvent(toneSelectorOpenedEvent({}));
|
|
48
76
|
}
|
|
49
77
|
isMounted.current = true;
|
|
50
|
-
return
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
78
|
+
return jsx("div", {
|
|
79
|
+
role: "radiogroup",
|
|
80
|
+
"data-testid": toneSelectorTestId,
|
|
81
|
+
id: "emoji-picker-tone-selector",
|
|
82
|
+
"aria-label": formatMessage(messages.emojiSelectSkinToneListAriaLabelText),
|
|
83
|
+
css: !isVisible && hidden
|
|
84
|
+
}, emojiToneCollection.map(tone => {
|
|
85
|
+
return jsx(EmojiRadioButton, {
|
|
86
|
+
ref: tone.isSelected ? selectedToneRadioRef : null,
|
|
87
|
+
defaultChecked: tone.isSelected,
|
|
54
88
|
ariaLabelText: tone.label,
|
|
55
89
|
key: `${tone.id}`,
|
|
56
|
-
onSelected: onToneSelectedHandler(tone.toneId),
|
|
57
90
|
emoji: tone,
|
|
91
|
+
onSelected: onToneSelectedHandler(tone.toneIndex),
|
|
58
92
|
selectOnHover: true
|
|
59
93
|
});
|
|
60
94
|
}));
|
|
61
95
|
};
|
|
62
96
|
const ToneSelector = withAnalyticsEvents()(ToneSelectorInternal);
|
|
63
|
-
export default ToneSelector;
|
|
97
|
+
export default /*#__PURE__*/memo(ToneSelector);
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { css, keyframes } from '@emotion/react';
|
|
2
|
-
import { borderRadius } from '@atlaskit/theme/constants';
|
|
3
2
|
import { defaultEmojiHeight } from '../../util/constants';
|
|
4
3
|
import { akEmojiSelectedBackgroundColor } from '../../util/shared-styles';
|
|
5
|
-
import { N20, N200, N20A, N300, N900, R300, R400 } from '@atlaskit/theme/colors';
|
|
4
|
+
import { B100, N20, N200, N20A, N300, N900, R300, R400 } from '@atlaskit/theme/colors';
|
|
6
5
|
export const commonSelectedStyles = 'emoji-common-selected';
|
|
7
6
|
export const selectOnHoverStyles = 'emoji-common-select-on-hover';
|
|
8
7
|
export const emojiSprite = 'emoji-common-emoji-sprite';
|
|
@@ -30,7 +29,7 @@ export const emojiToneSelectorContainer = css({
|
|
|
30
29
|
padding: '10px 10px 11px 0'
|
|
31
30
|
});
|
|
32
31
|
export const emojiStyles = css({
|
|
33
|
-
borderRadius:
|
|
32
|
+
borderRadius: "var(--ds-radius-100, 3px)",
|
|
34
33
|
backgroundColor: 'transparent',
|
|
35
34
|
display: 'inline-block',
|
|
36
35
|
verticalAlign: 'middle',
|
|
@@ -47,6 +46,11 @@ export const emojiStyles = css({
|
|
|
47
46
|
},
|
|
48
47
|
img: {
|
|
49
48
|
display: 'block'
|
|
49
|
+
},
|
|
50
|
+
'&:focus': {
|
|
51
|
+
boxShadow: `0 0 0 2px ${`var(--ds-border-focused, ${B100})`}`,
|
|
52
|
+
transitionDuration: '0s, 0.2s',
|
|
53
|
+
outline: 'none'
|
|
50
54
|
}
|
|
51
55
|
});
|
|
52
56
|
export const emojiContainer = css({
|
|
@@ -62,6 +66,11 @@ export const emojiContainer = css({
|
|
|
62
66
|
minHeight: `${defaultEmojiHeight}px`,
|
|
63
67
|
minWidth: `${defaultEmojiHeight}px`,
|
|
64
68
|
verticalAlign: 'middle'
|
|
69
|
+
},
|
|
70
|
+
'&:focus': {
|
|
71
|
+
boxShadow: `0 0 0 2px ${`var(--ds-border-focused, ${B100})`}`,
|
|
72
|
+
transitionDuration: '0s, 0.2s',
|
|
73
|
+
outline: 'none'
|
|
65
74
|
}
|
|
66
75
|
});
|
|
67
76
|
export const placeholder = 'emoji-common-placeholder';
|
|
@@ -70,7 +79,7 @@ export const placeholderContainer = css({
|
|
|
70
79
|
margin: '-1px 0',
|
|
71
80
|
display: 'inline-block',
|
|
72
81
|
background: "var(--ds-border, #f7f7f7)",
|
|
73
|
-
borderRadius:
|
|
82
|
+
borderRadius: "var(--ds-radius-100, 3px)",
|
|
74
83
|
overflow: 'hidden',
|
|
75
84
|
verticalAlign: 'middle',
|
|
76
85
|
whiteSpace: 'nowrap',
|
|
@@ -95,18 +104,25 @@ export const placeholderContainerAnimated = css({
|
|
|
95
104
|
animation: `${easeSweep} 1s cubic-bezier(0.4, 0.0, 0.2, 1) infinite`
|
|
96
105
|
}
|
|
97
106
|
});
|
|
107
|
+
export const hidden = css({
|
|
108
|
+
opacity: 0,
|
|
109
|
+
visibility: 'hidden',
|
|
110
|
+
display: 'none'
|
|
111
|
+
});
|
|
98
112
|
export const emojiButton = css({
|
|
99
113
|
backgroundColor: 'transparent',
|
|
100
114
|
border: '0',
|
|
115
|
+
borderRadius: "var(--ds-radius-100, 3px)",
|
|
101
116
|
cursor: 'pointer',
|
|
102
117
|
padding: 0,
|
|
118
|
+
position: 'relative',
|
|
119
|
+
display: 'inline-block',
|
|
103
120
|
/* Firefox */
|
|
104
121
|
['&::-moz-focus-inner']: {
|
|
105
122
|
border: '0 none',
|
|
106
123
|
padding: 0
|
|
107
124
|
},
|
|
108
125
|
'&>span': {
|
|
109
|
-
borderRadius: `${borderRadius()}px`,
|
|
110
126
|
padding: '6px',
|
|
111
127
|
// Scale sprite to fit regardless of default emoji size
|
|
112
128
|
[`&>.${emojiSprite}`]: {
|
|
@@ -118,11 +134,26 @@ export const emojiButton = css({
|
|
|
118
134
|
height: '24px',
|
|
119
135
|
width: '24px'
|
|
120
136
|
}
|
|
137
|
+
},
|
|
138
|
+
'&:focus': {
|
|
139
|
+
boxShadow: `0 0 0 2px ${`var(--ds-border-focused, ${B100})`}`,
|
|
140
|
+
transitionDuration: '0s, 0.2s',
|
|
141
|
+
outline: 'none'
|
|
121
142
|
}
|
|
122
143
|
});
|
|
123
|
-
export const
|
|
124
|
-
|
|
125
|
-
|
|
144
|
+
export const emojiRadio = css({
|
|
145
|
+
opacity: 0,
|
|
146
|
+
position: 'absolute',
|
|
147
|
+
top: '-10px',
|
|
148
|
+
left: '-10px',
|
|
149
|
+
'+span': {
|
|
150
|
+
borderRadius: "var(--ds-radius-100, 3px)"
|
|
151
|
+
},
|
|
152
|
+
'&:focus + span': {
|
|
153
|
+
boxShadow: `0 0 0 2px ${`var(--ds-border-focused, ${B100})`}`,
|
|
154
|
+
transitionDuration: '0s, 0.2s',
|
|
155
|
+
outline: 'none'
|
|
156
|
+
}
|
|
126
157
|
});
|
|
127
158
|
|
|
128
159
|
// Emoji Preview
|
|
@@ -197,7 +228,7 @@ export const previewImg = css({
|
|
|
197
228
|
|
|
198
229
|
export const emojiScrollable = css({
|
|
199
230
|
border: `1px solid ${"var(--ds-border, #fff)"}`,
|
|
200
|
-
borderRadius:
|
|
231
|
+
borderRadius: "var(--ds-radius-100, 3px)",
|
|
201
232
|
display: 'block',
|
|
202
233
|
margin: '0',
|
|
203
234
|
overflowX: 'hidden',
|
|
@@ -264,7 +295,7 @@ export const uploadPreview = css({
|
|
|
264
295
|
justifyContent: 'space-between',
|
|
265
296
|
alignItems: 'center',
|
|
266
297
|
background: `var(--ds-background-neutral, ${N20})`,
|
|
267
|
-
borderRadius:
|
|
298
|
+
borderRadius: "var(--ds-radius-100, 3px)",
|
|
268
299
|
padding: '10px'
|
|
269
300
|
});
|
|
270
301
|
export const uploadPreviewText = css({
|
|
@@ -22,8 +22,8 @@ export const messages = defineMessages({
|
|
|
22
22
|
},
|
|
23
23
|
emojiPlaceholder: {
|
|
24
24
|
id: 'fabric.emoji.placeholder',
|
|
25
|
-
defaultMessage: '
|
|
26
|
-
description: 'Placeholder for emoji'
|
|
25
|
+
defaultMessage: 'e.g. hello',
|
|
26
|
+
description: 'Placeholder for emoji that provides an example for emoji name'
|
|
27
27
|
},
|
|
28
28
|
emojiNameAriaLabel: {
|
|
29
29
|
id: 'fabric.emoji.name.ariaLabel',
|
|
@@ -42,9 +42,14 @@ export const messages = defineMessages({
|
|
|
42
42
|
},
|
|
43
43
|
emojiSelectSkinToneButtonAriaLabelText: {
|
|
44
44
|
id: 'fabric.emoji.select.skin.tone.ariaLabel',
|
|
45
|
-
defaultMessage: '
|
|
45
|
+
defaultMessage: 'Choose your skin tone, {selectedTone} selected',
|
|
46
46
|
description: 'Message indicating the purpose of the skin tone selection button and the selected tone'
|
|
47
47
|
},
|
|
48
|
+
emojiSelectSkinToneListAriaLabelText: {
|
|
49
|
+
id: 'fabric.emoji.select.skin.list.ariaLabel',
|
|
50
|
+
defaultMessage: 'Skin tone selector',
|
|
51
|
+
description: 'Message indicating the purpose of the skin tone list and make user to choose one tone'
|
|
52
|
+
},
|
|
48
53
|
emojiImageRequirements: {
|
|
49
54
|
id: 'fabric.emoji.image.requirements',
|
|
50
55
|
defaultMessage: 'JPG, PNG or GIF. Max size 1 MB.',
|
|
@@ -82,9 +87,24 @@ export const messages = defineMessages({
|
|
|
82
87
|
},
|
|
83
88
|
searchLabel: {
|
|
84
89
|
id: 'fabric.emoji.search.label',
|
|
85
|
-
defaultMessage: '
|
|
90
|
+
defaultMessage: 'Emoji name',
|
|
86
91
|
description: 'verb - button label to search'
|
|
87
92
|
},
|
|
93
|
+
searchResultsStatus: {
|
|
94
|
+
id: 'fabric.emoji.search.status',
|
|
95
|
+
defaultMessage: 'Found {count} emojis',
|
|
96
|
+
description: 'search results status for screenreader to read out'
|
|
97
|
+
},
|
|
98
|
+
searchResultsStatusSeeAll: {
|
|
99
|
+
id: 'fabric.emoji.search.status',
|
|
100
|
+
defaultMessage: 'Seeing all emojis',
|
|
101
|
+
description: 'search results status when no search query for screenreader to read out'
|
|
102
|
+
},
|
|
103
|
+
categoriesSelectorLabel: {
|
|
104
|
+
id: 'fabric.emoji.categories.label',
|
|
105
|
+
defaultMessage: 'Choose a emoji category',
|
|
106
|
+
description: 'Aria label for Emoji categories selector at the top of emoji picker'
|
|
107
|
+
},
|
|
88
108
|
categoriesSearchResults: {
|
|
89
109
|
id: 'fabric.emoji.categories.search.results',
|
|
90
110
|
defaultMessage: 'Search results',
|
|
@@ -169,5 +189,25 @@ export const messages = defineMessages({
|
|
|
169
189
|
id: 'fabric.emoji.error.image.too.big',
|
|
170
190
|
defaultMessage: 'Selected image is more than 1 MB',
|
|
171
191
|
description: 'Error message for image too big, beyond the size limit'
|
|
192
|
+
},
|
|
193
|
+
emojiPickerTitle: {
|
|
194
|
+
id: 'fabric.emoji.picker',
|
|
195
|
+
defaultMessage: 'Emoji picker',
|
|
196
|
+
description: 'Aria label for emoji picker'
|
|
197
|
+
},
|
|
198
|
+
emojiPickerListPanel: {
|
|
199
|
+
id: 'fabric.emoji.pickerlist.tabpanel',
|
|
200
|
+
defaultMessage: 'Emojis actions and list panel',
|
|
201
|
+
description: 'Aria lable for tabpanel of emoji picker, which shows emojis actions and list'
|
|
202
|
+
},
|
|
203
|
+
emojiPickerGrid: {
|
|
204
|
+
id: 'fabric.emoji.pickerlist.grid',
|
|
205
|
+
defaultMessage: '{showSearchResults, select, true{Search results} other{Emojis}}',
|
|
206
|
+
description: `Aria label for emoji picker grid, showSearchResults is a boolean variable, message will be "Entering Emojis table", or "Leaving Emojis"`
|
|
207
|
+
},
|
|
208
|
+
emojiButtonRoleDescription: {
|
|
209
|
+
id: 'fabric.emoji.emojipicker.emoi.roledescription',
|
|
210
|
+
defaultMessage: 'emoji button',
|
|
211
|
+
description: `Aria roledescription for emoji button, used in emoji picker.`
|
|
172
212
|
}
|
|
173
213
|
});
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
1
|
/** @jsx jsx */
|
|
3
|
-
import React from 'react';
|
|
2
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
3
|
import { jsx } from '@emotion/react';
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import { defaultCategories } from '../../util/constants';
|
|
4
|
+
import { useIntl } from 'react-intl-next';
|
|
5
|
+
import Tooltip from '@atlaskit/tooltip';
|
|
6
|
+
import { CATEGORYSELECTOR_KEYBOARD_KEYS_SUPPORTED, defaultCategories, KeyboardKeys } from '../../util/constants';
|
|
8
7
|
import { messages } from '../i18n';
|
|
9
8
|
import { CategoryDescriptionMap } from './categories';
|
|
10
|
-
import { active, categorySelector, disable, categoryStyles } from './styles';
|
|
9
|
+
import { active, categorySelector, disable, categoryStyles, categorySelectorTablist } from './styles';
|
|
10
|
+
import { usePrevious } from '../../hooks/usePrevious';
|
|
11
|
+
import { RENDER_EMOJI_PICKER_LIST_TESTID } from './EmojiPickerList';
|
|
11
12
|
export const sortCategories = (c1, c2) => CategoryDescriptionMap[c1].order - CategoryDescriptionMap[c2].order;
|
|
12
13
|
const addNewCategories = (oldCategories, newCategories) => {
|
|
13
14
|
if (!newCategories) {
|
|
@@ -17,90 +18,114 @@ const addNewCategories = (oldCategories, newCategories) => {
|
|
|
17
18
|
};
|
|
18
19
|
export const categorySelectorComponentTestId = 'category-selector-component';
|
|
19
20
|
export const categorySelectorCategoryTestId = categoryId => `category-selector-${categoryId}`;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (dynamicCategories) {
|
|
42
|
-
categories = addNewCategories(categories, dynamicCategories);
|
|
21
|
+
const CategorySelector = props => {
|
|
22
|
+
const {
|
|
23
|
+
disableCategories,
|
|
24
|
+
dynamicCategories,
|
|
25
|
+
activeCategoryId,
|
|
26
|
+
onCategorySelected
|
|
27
|
+
} = props;
|
|
28
|
+
const [categories, setCategories] = useState(addNewCategories(defaultCategories, dynamicCategories));
|
|
29
|
+
const [currentFocus, setCurrentFocus] = useState(0);
|
|
30
|
+
const categoryRef = useRef(null);
|
|
31
|
+
const prevDynamicCategories = usePrevious(dynamicCategories);
|
|
32
|
+
const {
|
|
33
|
+
formatMessage
|
|
34
|
+
} = useIntl();
|
|
35
|
+
const updateCategories = useCallback(() => {
|
|
36
|
+
const newCategories = addNewCategories(defaultCategories, dynamicCategories);
|
|
37
|
+
setCategories(newCategories);
|
|
38
|
+
}, [dynamicCategories]);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (prevDynamicCategories !== dynamicCategories) {
|
|
41
|
+
updateCategories();
|
|
43
42
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
43
|
+
}, [prevDynamicCategories, dynamicCategories, updateCategories]);
|
|
44
|
+
const focusCategory = useCallback(index => {
|
|
45
|
+
var _categoryRef$current;
|
|
46
|
+
const categoryToFocus = (_categoryRef$current = categoryRef.current) === null || _categoryRef$current === void 0 ? void 0 : _categoryRef$current.querySelector(`[data-focus-index="${index}"]`);
|
|
47
|
+
categoryToFocus && categoryToFocus.focus();
|
|
48
|
+
setCurrentFocus(index);
|
|
49
|
+
}, [categoryRef, setCurrentFocus]);
|
|
50
|
+
const handleKeyDown = e => {
|
|
51
|
+
if (!CATEGORYSELECTOR_KEYBOARD_KEYS_SUPPORTED.includes(e.key)) {
|
|
52
|
+
return;
|
|
53
53
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const Icon = category.icon;
|
|
80
|
-
const categoryName = formatMessage(messages[category.name]);
|
|
81
|
-
return jsx("li", {
|
|
82
|
-
key: category.id
|
|
83
|
-
}, jsx("button", {
|
|
84
|
-
"aria-label": categoryName,
|
|
85
|
-
"data-category-id": category.id,
|
|
86
|
-
disabled: disableCategories,
|
|
87
|
-
css: categoryClasses,
|
|
88
|
-
onClick: this.onClick,
|
|
89
|
-
title: categoryName,
|
|
90
|
-
type: "button",
|
|
91
|
-
"data-testid": categorySelectorCategoryTestId(categoryId)
|
|
92
|
-
}, jsx(Icon, {
|
|
93
|
-
label: categoryName
|
|
94
|
-
})));
|
|
95
|
-
}));
|
|
54
|
+
e.preventDefault();
|
|
55
|
+
const lastCategoryIndex = categories.length - 1;
|
|
56
|
+
switch (e.key) {
|
|
57
|
+
// navigate to the right category
|
|
58
|
+
case KeyboardKeys.ArrowRight:
|
|
59
|
+
focusCategory(currentFocus === lastCategoryIndex ? 0 : currentFocus + 1);
|
|
60
|
+
break;
|
|
61
|
+
// navigate to the left category
|
|
62
|
+
case KeyboardKeys.ArrowLeft:
|
|
63
|
+
focusCategory(currentFocus === 0 ? lastCategoryIndex : currentFocus - 1);
|
|
64
|
+
break;
|
|
65
|
+
// navigate to the first category
|
|
66
|
+
case KeyboardKeys.Home:
|
|
67
|
+
focusCategory(0);
|
|
68
|
+
break;
|
|
69
|
+
// navigate to the last category
|
|
70
|
+
case KeyboardKeys.End:
|
|
71
|
+
focusCategory(lastCategoryIndex);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const handleClick = (categoryId, index) => event => {
|
|
76
|
+
if (disableCategories) {
|
|
77
|
+
event.preventDefault();
|
|
78
|
+
return;
|
|
96
79
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
80
|
+
if (onCategorySelected) {
|
|
81
|
+
onCategorySelected(categoryId);
|
|
82
|
+
}
|
|
83
|
+
setCurrentFocus(index);
|
|
84
|
+
};
|
|
85
|
+
let categoriesSection;
|
|
86
|
+
if (categories) {
|
|
87
|
+
categoriesSection = jsx("div", {
|
|
88
|
+
role: "tablist",
|
|
89
|
+
"aria-label": formatMessage(messages.categoriesSelectorLabel),
|
|
90
|
+
"data-testid": categorySelectorComponentTestId,
|
|
91
|
+
ref: categoryRef,
|
|
92
|
+
css: categorySelectorTablist
|
|
93
|
+
}, categories.map((categoryId, index) => {
|
|
94
|
+
const category = CategoryDescriptionMap[categoryId];
|
|
95
|
+
const categoryClasses = [categoryStyles];
|
|
96
|
+
if (categoryId === activeCategoryId) {
|
|
97
|
+
categoryClasses.push(active);
|
|
98
|
+
}
|
|
99
|
+
if (disableCategories) {
|
|
100
|
+
categoryClasses.push(disable);
|
|
101
|
+
}
|
|
102
|
+
const Icon = category.icon;
|
|
103
|
+
const categoryName = formatMessage(messages[category.name]);
|
|
104
|
+
return jsx(Tooltip, {
|
|
105
|
+
content: categoryName,
|
|
106
|
+
position: "bottom",
|
|
107
|
+
key: category.id
|
|
108
|
+
}, jsx("button", {
|
|
109
|
+
type: "button",
|
|
110
|
+
id: `category-selector-${category.id}`,
|
|
111
|
+
"data-focus-index": index,
|
|
112
|
+
"aria-label": categoryName,
|
|
113
|
+
"aria-controls": currentFocus === index ? RENDER_EMOJI_PICKER_LIST_TESTID : undefined,
|
|
114
|
+
"aria-selected": currentFocus === index ? true : false,
|
|
115
|
+
css: categoryClasses,
|
|
116
|
+
disabled: disableCategories,
|
|
117
|
+
onClick: handleClick(categoryId, index),
|
|
118
|
+
"data-testid": categorySelectorCategoryTestId(categoryId),
|
|
119
|
+
tabIndex: currentFocus === index ? 0 : -1,
|
|
120
|
+
onKeyDown: handleKeyDown,
|
|
121
|
+
role: "tab"
|
|
122
|
+
}, jsx(Icon, {
|
|
123
|
+
label: categoryName
|
|
124
|
+
})));
|
|
125
|
+
}));
|
|
100
126
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
export default injectIntl(CategorySelector);
|
|
127
|
+
return jsx("div", {
|
|
128
|
+
css: categorySelector
|
|
129
|
+
}, categoriesSection);
|
|
130
|
+
};
|
|
131
|
+
export default CategorySelector;
|
|
@@ -21,28 +21,4 @@ export default class CategoryTracker {
|
|
|
21
21
|
getRow(category) {
|
|
22
22
|
return this.categoryToRow.get(category);
|
|
23
23
|
}
|
|
24
|
-
findNearestCategoryAbove(startIndex, list) {
|
|
25
|
-
const rows = Array.from(this.rowToCategory.keys()).sort((a, b) => a - b);
|
|
26
|
-
if (rows.length === 0) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Return first category if list not yet rendered
|
|
31
|
-
// or the top row is above the first category
|
|
32
|
-
if (!list || rows[0] > startIndex) {
|
|
33
|
-
return this.rowToCategory.get(rows[0]);
|
|
34
|
-
}
|
|
35
|
-
let bounds = [0, rows.length - 1];
|
|
36
|
-
let index = Math.floor(rows.length / 2);
|
|
37
|
-
while (rows[index] !== startIndex && bounds[0] < bounds[1]) {
|
|
38
|
-
if (rows[index] > startIndex) {
|
|
39
|
-
bounds[1] = Math.max(index - 1, 0);
|
|
40
|
-
} else {
|
|
41
|
-
bounds[0] = index + 1;
|
|
42
|
-
}
|
|
43
|
-
index = Math.floor((bounds[0] + bounds[1]) / 2);
|
|
44
|
-
}
|
|
45
|
-
const headerRow = rows[rows[index] > startIndex ? Math.max(index - 1, 0) : index];
|
|
46
|
-
return this.rowToCategory.get(headerRow);
|
|
47
|
-
}
|
|
48
24
|
}
|
|
@@ -5,7 +5,6 @@ import { FormattedMessage } from 'react-intl-next';
|
|
|
5
5
|
import { isMessagesKey } from '../../util/type-helpers';
|
|
6
6
|
import { messages } from '../i18n';
|
|
7
7
|
import { emojiCategoryTitle } from './styles';
|
|
8
|
-
|
|
9
8
|
/**
|
|
10
9
|
* Test id for wrapper Emoji Picker List div
|
|
11
10
|
*/
|
|
@@ -18,7 +17,8 @@ const EmojiPickerCategoryHeading = ({
|
|
|
18
17
|
id: id,
|
|
19
18
|
"data-category-id": id,
|
|
20
19
|
className: className,
|
|
21
|
-
"data-testid": RENDER_EMOJI_PICKER_CATEGORY_HEADING_TESTID
|
|
20
|
+
"data-testid": RENDER_EMOJI_PICKER_CATEGORY_HEADING_TESTID,
|
|
21
|
+
role: "rowheader"
|
|
22
22
|
}, jsx("div", {
|
|
23
23
|
css: emojiCategoryTitle
|
|
24
24
|
}, isMessagesKey(title) ? jsx(FormattedMessage, messages[title]) : title));
|