emoji-picker-react 4.20.2 → 4.20.5
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/README.md +1 -1
- package/dist/Stylesheet/stylesheet.d.ts +1 -1
- package/dist/components/body/EmojiCategory.d.ts +2 -1
- package/dist/components/emoji/Emoji.d.ts +2 -1
- package/dist/components/header/SkinTonePicker/BtnSkinToneVariation.d.ts +2 -1
- package/dist/emoji-picker-react.cjs.development.js +157 -42
- package/dist/emoji-picker-react.cjs.development.js.map +1 -1
- package/dist/emoji-picker-react.cjs.production.min.js +1 -1
- package/dist/emoji-picker-react.cjs.production.min.js.map +1 -1
- package/dist/emoji-picker-react.esm.js +121 -6
- package/dist/emoji-picker-react.esm.js.map +1 -1
- package/llms.txt +1 -1
- package/package.json +8 -2
- package/src/DomUtils/elementPositionInRow.ts +11 -0
- package/src/Stylesheet/stylesheet.tsx +1 -1
- package/src/components/Layout/Flex.tsx +1 -1
- package/src/components/Layout/Space.tsx +1 -1
- package/src/components/Reactions/BtnPlus.tsx +1 -1
- package/src/components/Reactions/Reactions.tsx +21 -1
- package/src/components/atoms/Button.tsx +1 -1
- package/src/components/body/Body.tsx +1 -1
- package/src/components/body/EmojiCategory.tsx +10 -2
- package/src/components/body/EmojiList.tsx +12 -2
- package/src/components/body/EmojiVariationPicker.tsx +1 -1
- package/src/components/emoji/ClickableEmojiButton.tsx +1 -1
- package/src/components/emoji/Emoji.tsx +3 -0
- package/src/components/emoji/EmojiImg.tsx +1 -1
- package/src/components/emoji/NativeEmoji.tsx +1 -1
- package/src/components/footer/Preview.tsx +1 -1
- package/src/components/header/Header.tsx +1 -1
- package/src/components/header/Search/BtnClearSearch.tsx +1 -1
- package/src/components/header/Search/IcnSearch.tsx +1 -1
- package/src/components/header/Search/Search.tsx +1 -1
- package/src/components/header/SkinTonePicker/BtnSkinToneVariation.tsx +4 -1
- package/src/components/header/SkinTonePicker/SkinTonePicker.tsx +7 -1
- package/src/components/main/PickerMain.tsx +1 -1
- package/src/components/navigation/CategoryButton.tsx +1 -1
- package/src/components/navigation/CategoryNavigation.tsx +1 -1
- package/src/hooks/useKeyboardNavigation.ts +81 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React__default, { memo, createElement, useState, useEffect, useContext, createContext, useRef, useMemo, createRef, useCallback, Fragment, useLayoutEffect, Component } from 'react';
|
|
2
|
-
import { createSheet, cx } from '
|
|
2
|
+
import { createSheet, cx } from 'shipstyles';
|
|
3
3
|
|
|
4
4
|
function _arrayLikeToArray(r, a) {
|
|
5
5
|
(null == a || a > r.length) && (a = r.length);
|
|
@@ -27899,6 +27899,7 @@ function useKeyboardNavigation() {
|
|
|
27899
27899
|
useSearchInputKeyboardEvents();
|
|
27900
27900
|
useSkinTonePickerKeyboardEvents();
|
|
27901
27901
|
useCategoryNavigationKeyboardEvents();
|
|
27902
|
+
useReactionsKeyboardEvents();
|
|
27902
27903
|
useBodyKeyboardEvents();
|
|
27903
27904
|
}
|
|
27904
27905
|
function usePickerMainKeyboardEvents() {
|
|
@@ -28104,6 +28105,65 @@ function useCategoryNavigationKeyboardEvents() {
|
|
|
28104
28105
|
};
|
|
28105
28106
|
}, [CategoryNavigationRef, BodyRef, onKeyDown]);
|
|
28106
28107
|
}
|
|
28108
|
+
// Arrow keys move between reaction buttons (and the expand button)
|
|
28109
|
+
// while the reactions bar has focus. The bar lives outside the scroll
|
|
28110
|
+
// body, so the body handler never sees these events.
|
|
28111
|
+
// https://github.com/ealush/emoji-picker-react/issues/411
|
|
28112
|
+
function useReactionsKeyboardEvents() {
|
|
28113
|
+
var ReactionsRef = useReactionsRef();
|
|
28114
|
+
// The reactions bar mounts late when the user collapses the full
|
|
28115
|
+
// picker, so the listener effect must rerun when it opens.
|
|
28116
|
+
var _useReactionsModeStat = useReactionsModeState(),
|
|
28117
|
+
reactionsOpen = _useReactionsModeStat[0];
|
|
28118
|
+
var onKeyDown = useMemo(function () {
|
|
28119
|
+
return function onKeyDown(event) {
|
|
28120
|
+
var key = event.key;
|
|
28121
|
+
var current = ReactionsRef.current;
|
|
28122
|
+
if (!current) {
|
|
28123
|
+
return;
|
|
28124
|
+
}
|
|
28125
|
+
var delta = reactionFocusDelta(key);
|
|
28126
|
+
if (delta !== 0 && focusReactionSibling(current, delta)) {
|
|
28127
|
+
event.preventDefault();
|
|
28128
|
+
}
|
|
28129
|
+
};
|
|
28130
|
+
},
|
|
28131
|
+
// reactionsOpen: the bar mounts late on collapse, and the new
|
|
28132
|
+
// callback identity reinstalls the listener effect below.
|
|
28133
|
+
[ReactionsRef, reactionsOpen]);
|
|
28134
|
+
useEffect(function () {
|
|
28135
|
+
var current = ReactionsRef.current;
|
|
28136
|
+
if (!current) {
|
|
28137
|
+
return;
|
|
28138
|
+
}
|
|
28139
|
+
current.addEventListener('keydown', onKeyDown);
|
|
28140
|
+
return function () {
|
|
28141
|
+
current.removeEventListener('keydown', onKeyDown);
|
|
28142
|
+
};
|
|
28143
|
+
}, [ReactionsRef, onKeyDown]);
|
|
28144
|
+
}
|
|
28145
|
+
function reactionFocusDelta(key) {
|
|
28146
|
+
switch (key) {
|
|
28147
|
+
case KeyboardEvents.ArrowRight:
|
|
28148
|
+
case KeyboardEvents.ArrowDown:
|
|
28149
|
+
return 1;
|
|
28150
|
+
case KeyboardEvents.ArrowLeft:
|
|
28151
|
+
case KeyboardEvents.ArrowUp:
|
|
28152
|
+
return -1;
|
|
28153
|
+
default:
|
|
28154
|
+
return 0;
|
|
28155
|
+
}
|
|
28156
|
+
}
|
|
28157
|
+
function focusReactionSibling(root, delta) {
|
|
28158
|
+
var buttons = Array.from(root.querySelectorAll('button'));
|
|
28159
|
+
var activeIndex = buttons.indexOf(getActiveElement());
|
|
28160
|
+
var sibling = activeIndex === -1 ? null : buttons[activeIndex + delta];
|
|
28161
|
+
if (!sibling) {
|
|
28162
|
+
return false;
|
|
28163
|
+
}
|
|
28164
|
+
focusElement(sibling);
|
|
28165
|
+
return true;
|
|
28166
|
+
}
|
|
28107
28167
|
function useBodyKeyboardEvents() {
|
|
28108
28168
|
var BodyRef = useBodyRef();
|
|
28109
28169
|
var goUpFromBody = useGoUpFromBody();
|
|
@@ -28479,9 +28539,20 @@ var styles = /*#__PURE__*/stylesheet.create({
|
|
|
28479
28539
|
});
|
|
28480
28540
|
|
|
28481
28541
|
function elementCountInRow(parent, element) {
|
|
28542
|
+
var _parent$dataset;
|
|
28482
28543
|
if (!parent || !element) {
|
|
28483
28544
|
return 0;
|
|
28484
28545
|
}
|
|
28546
|
+
// The virtualized layout positions emojis with a fixed per-row count that
|
|
28547
|
+
// is rendered onto the category content element. That count is the single
|
|
28548
|
+
// source of truth: deriving it again from fractional rect widths can be
|
|
28549
|
+
// off by one (e.g. category padding shrinking the content box), which
|
|
28550
|
+
// makes arrow-up/arrow-down drift sideways by a column.
|
|
28551
|
+
// https://github.com/ealush/emoji-picker-react/issues/502
|
|
28552
|
+
var declared = Number((_parent$dataset = parent.dataset) == null ? void 0 : _parent$dataset.emojisPerRow);
|
|
28553
|
+
if (Number.isInteger(declared) && declared > 0) {
|
|
28554
|
+
return declared;
|
|
28555
|
+
}
|
|
28485
28556
|
var parentWidth = parent.getBoundingClientRect().width;
|
|
28486
28557
|
var elementWidth = element.getBoundingClientRect().width;
|
|
28487
28558
|
return Math.floor(parentWidth / elementWidth);
|
|
@@ -29119,6 +29190,7 @@ function ClickableEmoji(_ref) {
|
|
|
29119
29190
|
lazyLoad = _ref.lazyLoad,
|
|
29120
29191
|
getEmojiUrl = _ref.getEmojiUrl,
|
|
29121
29192
|
className = _ref.className,
|
|
29193
|
+
buttonClassName = _ref.buttonClassName,
|
|
29122
29194
|
_ref$noBackground = _ref.noBackground,
|
|
29123
29195
|
noBackground = _ref$noBackground === void 0 ? false : _ref$noBackground,
|
|
29124
29196
|
style = _ref.style;
|
|
@@ -29131,7 +29203,8 @@ function ClickableEmoji(_ref) {
|
|
|
29131
29203
|
emojiNames: emojiNames(emoji),
|
|
29132
29204
|
unified: unified,
|
|
29133
29205
|
noBackground: noBackground,
|
|
29134
|
-
style: style
|
|
29206
|
+
style: style,
|
|
29207
|
+
className: buttonClassName
|
|
29135
29208
|
}, createElement(ViewOnlyEmoji, {
|
|
29136
29209
|
unified: unified,
|
|
29137
29210
|
emoji: emoji,
|
|
@@ -29235,6 +29308,7 @@ function Reactions() {
|
|
|
29235
29308
|
unified: reaction,
|
|
29236
29309
|
showVariations: false,
|
|
29237
29310
|
className: cx(styles$6.emojiButton),
|
|
29311
|
+
buttonClassName: cx(styles$6.reactionButton),
|
|
29238
29312
|
noBackground: true,
|
|
29239
29313
|
getEmojiUrl: getEmojiUrl
|
|
29240
29314
|
}));
|
|
@@ -29250,6 +29324,24 @@ var styles$6 = /*#__PURE__*/stylesheet.create({
|
|
|
29250
29324
|
alignItems: 'center',
|
|
29251
29325
|
height: '100%'
|
|
29252
29326
|
},
|
|
29327
|
+
reactionButton: {
|
|
29328
|
+
// Every picker button sets outline: none, and reaction buttons also
|
|
29329
|
+
// suppress the focus background, so keyboard focus was invisible.
|
|
29330
|
+
// Focus mirrors the hover treatment (scale plus a soft circular
|
|
29331
|
+
// wash, no outline ring): the scale transform on the inner image
|
|
29332
|
+
// alone is clipped by the button's overflow: hidden, and does
|
|
29333
|
+
// nothing on inline native emoji, so the button itself carries the
|
|
29334
|
+
// effect. Scoped to the reactions bar so grid focus treatment is
|
|
29335
|
+
// untouched.
|
|
29336
|
+
// https://github.com/ealush/emoji-picker-react/issues/473
|
|
29337
|
+
':focus-visible': {
|
|
29338
|
+
transform: 'scale(1.2)',
|
|
29339
|
+
transition: 'background-color 0.2s, transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.5)',
|
|
29340
|
+
backgroundColor: 'var(--epr-hover-bg-color-reduced-opacity)',
|
|
29341
|
+
borderRadius: '50%',
|
|
29342
|
+
outline: 'none'
|
|
29343
|
+
}
|
|
29344
|
+
},
|
|
29253
29345
|
emojiButton: {
|
|
29254
29346
|
':hover': {
|
|
29255
29347
|
transform: 'scale(1.2)'
|
|
@@ -29473,12 +29565,14 @@ function EmojiCategory(_ref) {
|
|
|
29473
29565
|
children = _ref.children,
|
|
29474
29566
|
hidden = _ref.hidden,
|
|
29475
29567
|
hiddenOnSearch = _ref.hiddenOnSearch,
|
|
29476
|
-
height = _ref.height
|
|
29568
|
+
height = _ref.height,
|
|
29569
|
+
emojisPerRow = _ref.emojisPerRow;
|
|
29477
29570
|
var category = categoryFromCategoryConfig(categoryConfig);
|
|
29478
29571
|
var categoryName = categoryNameFromCategoryConfig(categoryConfig);
|
|
29479
29572
|
return createElement("li", {
|
|
29480
29573
|
className: cx(styles$7.category, hidden && commonStyles.hidden, hiddenOnSearch && commonInteractionStyles.hiddenOnSearch),
|
|
29481
29574
|
"data-name": category,
|
|
29575
|
+
role: "rowgroup",
|
|
29482
29576
|
"aria-label": categoryName
|
|
29483
29577
|
}, createElement("h2", {
|
|
29484
29578
|
className: cx(styles$7.label)
|
|
@@ -29486,7 +29580,9 @@ function EmojiCategory(_ref) {
|
|
|
29486
29580
|
className: cx(styles$7.categoryContent),
|
|
29487
29581
|
style: {
|
|
29488
29582
|
height: height
|
|
29489
|
-
}
|
|
29583
|
+
},
|
|
29584
|
+
role: "row",
|
|
29585
|
+
"data-emojis-per-row": emojisPerRow
|
|
29490
29586
|
}, children));
|
|
29491
29587
|
}
|
|
29492
29588
|
var styles$7 = /*#__PURE__*/stylesheet.create({
|
|
@@ -29588,9 +29684,19 @@ function EmojiList(_ref) {
|
|
|
29588
29684
|
var getEmojisByCategory = useGetEmojisByCategory();
|
|
29589
29685
|
var labelHeight = getLabelHeight(EmojiListRef.current);
|
|
29590
29686
|
var topOffset = 0;
|
|
29687
|
+
// role="grid" makes screen readers switch out of virtual-cursor mode so
|
|
29688
|
+
// arrow keys reach the picker's keyboard handler. Each category is one
|
|
29689
|
+
// rowgroup: visual rows shift under virtualization, so the category is
|
|
29690
|
+
// the only stable row unit. Emoji buttons intentionally keep their
|
|
29691
|
+
// native button role for activation semantics.
|
|
29692
|
+
// https://github.com/ealush/emoji-picker-react/issues/508
|
|
29693
|
+
// The list markup is kept for a backwards-compatible DOM structure;
|
|
29694
|
+
// the grid role override is intentional (see below).
|
|
29695
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-to-interactive-role
|
|
29591
29696
|
return createElement("ul", {
|
|
29592
29697
|
className: cx(styles$8.emojiList),
|
|
29593
|
-
ref: EmojiListRef
|
|
29698
|
+
ref: EmojiListRef,
|
|
29699
|
+
role: "grid"
|
|
29594
29700
|
}, createElement(MeasureEmoji, null), categories.map(function (categoryConfig) {
|
|
29595
29701
|
var category = categoryFromCategoryConfig(categoryConfig);
|
|
29596
29702
|
var currentOffset = topOffset;
|
|
@@ -29636,6 +29742,7 @@ function RenderCategory(_ref2) {
|
|
|
29636
29742
|
return createElement(EmojiCategory, {
|
|
29637
29743
|
categoryConfig: categoryConfig,
|
|
29638
29744
|
height: dimensions == null ? void 0 : dimensions.categoryHeight,
|
|
29745
|
+
emojisPerRow: dimensions == null ? void 0 : dimensions.emojisPerRow,
|
|
29639
29746
|
// Indicates that there are no visible emojis
|
|
29640
29747
|
// Hence, the category should be hidden
|
|
29641
29748
|
hidden: !emojis.length && virtualizedCounter === 0
|
|
@@ -30002,10 +30109,12 @@ function BtnSkinToneVariation(_ref) {
|
|
|
30002
30109
|
onClick = _ref.onClick,
|
|
30003
30110
|
isActive = _ref.isActive,
|
|
30004
30111
|
skinToneVariation = _ref.skinToneVariation,
|
|
30005
|
-
style = _ref.style
|
|
30112
|
+
style = _ref.style,
|
|
30113
|
+
tabIndex = _ref.tabIndex;
|
|
30006
30114
|
return createElement(Button, {
|
|
30007
30115
|
style: style,
|
|
30008
30116
|
onClick: onClick,
|
|
30117
|
+
tabIndex: tabIndex,
|
|
30009
30118
|
className: cx("epr-tone-" + skinToneVariation, styles$c.tone, !isOpen && styles$c.closedTone, isActive && styles$c.active),
|
|
30010
30119
|
"aria-pressed": isActive,
|
|
30011
30120
|
"aria-label": "Skin tone " + skinTonesNamed[skinToneVariation]
|
|
@@ -30114,6 +30223,12 @@ function SkinTonePicker(_ref) {
|
|
|
30114
30223
|
key: skinToneVariation,
|
|
30115
30224
|
skinToneVariation: skinToneVariation,
|
|
30116
30225
|
isOpen: isOpen,
|
|
30226
|
+
// Roving tabindex: when the fan is closed the inactive tones
|
|
30227
|
+
// are invisible (opacity: 0, stacked), so they must not be
|
|
30228
|
+
// reachable via Tab. The active tone stays tabbable to open
|
|
30229
|
+
// the fan from the keyboard.
|
|
30230
|
+
// https://github.com/ealush/emoji-picker-react/issues/492
|
|
30231
|
+
tabIndex: isOpen || active ? 0 : -1,
|
|
30117
30232
|
style: {
|
|
30118
30233
|
transform: cx(vertical ? "translateY(-" + i * (isOpen ? ITEM_SIZE : 0) + "px)" : "translateX(-" + i * (isOpen ? ITEM_SIZE : 0) + "px)", isOpen && active && 'scale(1.3)')
|
|
30119
30234
|
},
|