@synerise/ds-emoji-picker 1.3.22 → 1.3.24
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/README.md +1 -1
- package/dist/EmojiList/EmojiList.d.ts +2 -2
- package/dist/EmojiList/EmojiList.js +36 -52
- package/dist/EmojiList/EmojiList.styles.d.ts +9 -9
- package/dist/EmojiList/EmojiList.styles.js +23 -30
- package/dist/EmojiList/EmojiList.types.d.ts +2 -2
- package/dist/EmojiList/EmojiList.types.js +1 -1
- package/dist/EmojiList/EmojiList.utils.d.ts +2 -2
- package/dist/EmojiList/EmojiList.utils.js +13 -11
- package/dist/EmojiList/EmojiListItem.d.ts +2 -2
- package/dist/EmojiList/EmojiListItem.js +26 -35
- package/dist/EmojiOverlay/EmojiOverlay.d.ts +2 -2
- package/dist/EmojiOverlay/EmojiOverlay.js +25 -33
- package/dist/EmojiOverlay/EmojiOverlay.types.d.ts +1 -1
- package/dist/EmojiOverlay/EmojiOverlay.types.js +1 -1
- package/dist/EmojiPicker.const.js +6 -2
- package/dist/EmojiPicker.d.ts +2 -2
- package/dist/EmojiPicker.js +30 -48
- package/dist/EmojiPicker.styles.d.ts +1 -1
- package/dist/EmojiPicker.styles.js +6 -3
- package/dist/EmojiPicker.types.d.ts +4 -4
- package/dist/EmojiPicker.types.js +1 -1
- package/dist/hooks/useEmojiTranslations.d.ts +1 -1
- package/dist/hooks/useEmojiTranslations.js +28 -55
- package/dist/hooks/useMultipleItemsPerRow.d.ts +1 -1
- package/dist/hooks/useMultipleItemsPerRow.js +19 -14
- package/dist/index.js +5 -1
- package/package.json +13 -12
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.3.24](https://github.com/Synerise/synerise-design/compare/@synerise/ds-emoji-picker@1.3.23...@synerise/ds-emoji-picker@1.3.24) (2026-03-24)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @synerise/ds-emoji-picker
|
|
9
|
+
|
|
10
|
+
## [1.3.23](https://github.com/Synerise/synerise-design/compare/@synerise/ds-emoji-picker@1.3.22...@synerise/ds-emoji-picker@1.3.23) (2026-03-20)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @synerise/ds-emoji-picker
|
|
13
|
+
|
|
6
14
|
## [1.3.22](https://github.com/Synerise/synerise-design/compare/@synerise/ds-emoji-picker@1.3.21...@synerise/ds-emoji-picker@1.3.22) (2026-03-09)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @synerise/ds-emoji-picker
|
package/README.md
CHANGED
|
@@ -33,5 +33,5 @@ import EmojiPicker from '@synerise/ds-emoji-picker'
|
|
|
33
33
|
| children | the element that triggers showing the picker | ReactElement | - |
|
|
34
34
|
| onSelect | triggered when an emoji has been selected | (emoji: Emoji) => void | - |
|
|
35
35
|
| closeOnSelect | determines whether dropdown should hide when an emoji has been selected. true by default | boolean | true |
|
|
36
|
-
| dropdownProps | Dropdown customisation props see ds-dropdown
|
|
36
|
+
| dropdownProps | Dropdown customisation props (see ds-dropdown). `size`, `overlay`, and `open` are controlled internally and cannot be overridden. | Partial<DropdownSharedProps> | - |
|
|
37
37
|
| texts | customise texts / labels | Partial<EmojiPickerTexts> | - |
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { EmojiListProps } from './EmojiList.types';
|
|
3
3
|
export declare const EmojiList: ({ texts: customTexts, onSelect, searchQuery, }: EmojiListProps) => React.JSX.Element;
|
|
@@ -1,31 +1,26 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
grouped.forEach(
|
|
23
|
-
|
|
24
|
-
var _emoji$keywords;
|
|
25
|
-
return (_emoji$keywords = emoji.keywords) == null ? void 0 : _emoji$keywords.find(function (keyword) {
|
|
26
|
-
return keyword.match(searchQuery);
|
|
27
|
-
});
|
|
28
|
-
}) : emojis;
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useMemo } from "react";
|
|
3
|
+
import EmptyState, { EmptyStatesSize } from "@synerise/ds-empty-states";
|
|
4
|
+
import { SearchNoResultsL } from "@synerise/ds-icon";
|
|
5
|
+
import Scrollbar from "@synerise/ds-scrollbar";
|
|
6
|
+
import { ITEMS_PER_ROW, ITEM_SIZE } from "../EmojiPicker.const.js";
|
|
7
|
+
import { useEmojiTranslations } from "../hooks/useEmojiTranslations.js";
|
|
8
|
+
import { useMultipleItemsPerRow } from "../hooks/useMultipleItemsPerRow.js";
|
|
9
|
+
import { VirtualList, EmptyList } from "./EmojiList.styles.js";
|
|
10
|
+
import { getEmojisByGroup, createItemData } from "./EmojiList.utils.js";
|
|
11
|
+
import { EmojiListItem } from "./EmojiListItem.js";
|
|
12
|
+
const EmojiList = ({
|
|
13
|
+
texts: customTexts,
|
|
14
|
+
onSelect,
|
|
15
|
+
searchQuery
|
|
16
|
+
}) => {
|
|
17
|
+
const texts = useEmojiTranslations(customTexts);
|
|
18
|
+
const listRef = useRef(null);
|
|
19
|
+
const grouped = useMemo(() => getEmojisByGroup("group"), []);
|
|
20
|
+
const filteredList = useMemo(() => {
|
|
21
|
+
const items = [];
|
|
22
|
+
grouped.forEach((emojis, category) => {
|
|
23
|
+
const matching = searchQuery ? emojis.filter((emoji) => emoji.keywords?.find((keyword) => keyword.match(searchQuery))) : emojis;
|
|
29
24
|
if (matching.length) {
|
|
30
25
|
items.push({
|
|
31
26
|
title: texts[category] || category,
|
|
@@ -35,31 +30,20 @@ export var EmojiList = function EmojiList(_ref) {
|
|
|
35
30
|
});
|
|
36
31
|
return items;
|
|
37
32
|
}, [searchQuery, grouped, texts]);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
const virtualListData = useMultipleItemsPerRow(filteredList, ITEMS_PER_ROW);
|
|
34
|
+
const itemData = createItemData(virtualListData, ITEM_SIZE, onSelect, ITEMS_PER_ROW);
|
|
35
|
+
const handleScroll = ({
|
|
36
|
+
currentTarget
|
|
37
|
+
}) => {
|
|
38
|
+
const {
|
|
39
|
+
scrollTop
|
|
40
|
+
} = currentTarget;
|
|
43
41
|
if (listRef.current) {
|
|
44
42
|
listRef.current.scrollTo(scrollTop);
|
|
45
43
|
}
|
|
46
44
|
};
|
|
47
|
-
return filteredList.length ?
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
ref: listRef,
|
|
53
|
-
height: 330,
|
|
54
|
-
itemCount: virtualListData.length,
|
|
55
|
-
itemData: itemData,
|
|
56
|
-
itemSize: ITEM_SIZE,
|
|
57
|
-
width: "100%"
|
|
58
|
-
}, function (props) {
|
|
59
|
-
return /*#__PURE__*/React.createElement(EmojiListItem, props);
|
|
60
|
-
})) : /*#__PURE__*/React.createElement(S.EmptyList, null, /*#__PURE__*/React.createElement(EmptyState, {
|
|
61
|
-
customIcon: /*#__PURE__*/React.createElement(SearchNoResultsL, null),
|
|
62
|
-
size: EmptyStatesSize.SMALL,
|
|
63
|
-
text: texts.empty
|
|
64
|
-
}));
|
|
65
|
-
};
|
|
45
|
+
return filteredList.length ? /* @__PURE__ */ jsx(Scrollbar, { maxHeight: 330, onScroll: handleScroll, children: /* @__PURE__ */ jsx(VirtualList, { listHeight: 330, ref: listRef, height: 330, itemCount: virtualListData.length, itemData, itemSize: ITEM_SIZE, width: "100%", children: (props) => /* @__PURE__ */ jsx(EmojiListItem, { ...props }) }) }) : /* @__PURE__ */ jsx(EmptyList, { children: /* @__PURE__ */ jsx(EmptyState, { customIcon: /* @__PURE__ */ jsx(SearchNoResultsL, {}), size: EmptyStatesSize.SMALL, text: texts.empty }) });
|
|
46
|
+
};
|
|
47
|
+
export {
|
|
48
|
+
EmojiList
|
|
49
|
+
};
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { FixedSizeList } from '
|
|
3
|
-
export declare const EmojiItem: import(
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { FixedSizeList } from '../../../../../config/vitest/__mocks__/reactWindowMock.js';
|
|
3
|
+
export declare const EmojiItem: import('styled-components').StyledComponent<"div", any, {
|
|
4
4
|
itemsPerRow: number;
|
|
5
5
|
}, never>;
|
|
6
|
-
export declare const EmojiButton: import(
|
|
7
|
-
export declare const EmptyList: import(
|
|
8
|
-
export declare const EmojiCategoryWrapper: import(
|
|
9
|
-
export declare const VirtualList: import(
|
|
6
|
+
export declare const EmojiButton: import('styled-components').StyledComponent<(props: any) => React.JSX.Element, any, {}, never>;
|
|
7
|
+
export declare const EmptyList: import('styled-components').StyledComponent<"div", any, {}, never>;
|
|
8
|
+
export declare const EmojiCategoryWrapper: import('styled-components').StyledComponent<"div", any, {}, never>;
|
|
9
|
+
export declare const VirtualList: import('styled-components').StyledComponent<typeof FixedSizeList, any, {
|
|
10
10
|
listHeight: number;
|
|
11
11
|
}, never>;
|
|
12
|
-
export declare const ListRow: import(
|
|
13
|
-
export declare const Title: import(
|
|
12
|
+
export declare const ListRow: import('styled-components').StyledComponent<"div", any, {}, never>;
|
|
13
|
+
export declare const Title: import('styled-components').StyledComponent<"div", any, {
|
|
14
14
|
elementSize: string;
|
|
15
15
|
}, never>;
|
|
@@ -1,48 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
export var EmojiItem = styled.div.withConfig({
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { FixedSizeList } from "react-window";
|
|
3
|
+
import styled from "styled-components";
|
|
4
|
+
import Button from "@synerise/ds-button";
|
|
5
|
+
const EmojiItem = /* @__PURE__ */ styled.div.withConfig({
|
|
7
6
|
displayName: "EmojiListstyles__EmojiItem",
|
|
8
7
|
componentId: "sc-1yme2ir-0"
|
|
9
|
-
})(["display:flex;width:", "%;align-items:center;justify-content:center;"],
|
|
10
|
-
|
|
11
|
-
});
|
|
12
|
-
export var EmojiButton = styled(function (props) {
|
|
13
|
-
return /*#__PURE__*/React.createElement(Button, _extends({}, props, {
|
|
14
|
-
type: "ghost",
|
|
15
|
-
mode: "single-icon"
|
|
16
|
-
}));
|
|
17
|
-
}).withConfig({
|
|
8
|
+
})(["display:flex;width:", "%;align-items:center;justify-content:center;"], (props) => 100 / props.itemsPerRow);
|
|
9
|
+
const EmojiButton = /* @__PURE__ */ styled((props) => /* @__PURE__ */ jsx(Button, { ...props, type: "ghost", mode: "single-icon" })).withConfig({
|
|
18
10
|
displayName: "EmojiListstyles__EmojiButton",
|
|
19
11
|
componentId: "sc-1yme2ir-1"
|
|
20
12
|
})(["&&{font-size:24px;display:flex;align-items:center;cursor:pointer;}"]);
|
|
21
|
-
|
|
13
|
+
const EmptyList = /* @__PURE__ */ styled.div.withConfig({
|
|
22
14
|
displayName: "EmojiListstyles__EmptyList",
|
|
23
15
|
componentId: "sc-1yme2ir-2"
|
|
24
16
|
})(["padding:12px;"]);
|
|
25
|
-
|
|
17
|
+
const EmojiCategoryWrapper = /* @__PURE__ */ styled.div.withConfig({
|
|
26
18
|
displayName: "EmojiListstyles__EmojiCategoryWrapper",
|
|
27
19
|
componentId: "sc-1yme2ir-3"
|
|
28
20
|
})(["display:flex;gap:4px;flex-wrap:wrap;"]);
|
|
29
|
-
|
|
21
|
+
const VirtualList = /* @__PURE__ */ styled(FixedSizeList).withConfig({
|
|
30
22
|
displayName: "EmojiListstyles__VirtualList",
|
|
31
23
|
componentId: "sc-1yme2ir-4"
|
|
32
|
-
})(["max-height:", "px;height:auto !important;overflow-x:unset !important;overflow-y:unset !important;"],
|
|
33
|
-
|
|
34
|
-
});
|
|
35
|
-
export var ListRow = styled.div.withConfig({
|
|
24
|
+
})(["max-height:", "px;height:auto !important;overflow-x:unset !important;overflow-y:unset !important;"], (props) => props.listHeight);
|
|
25
|
+
const ListRow = /* @__PURE__ */ styled.div.withConfig({
|
|
36
26
|
displayName: "EmojiListstyles__ListRow",
|
|
37
27
|
componentId: "sc-1yme2ir-5"
|
|
38
28
|
})(["display:flex;flex-wrap:wrap;justify-content:flex-start;align-items:center;box-sizing:border-box;width:100%;height:100%;max-width:100%;"]);
|
|
39
|
-
|
|
29
|
+
const Title = /* @__PURE__ */ styled.div.withConfig({
|
|
40
30
|
displayName: "EmojiListstyles__Title",
|
|
41
31
|
componentId: "sc-1yme2ir-6"
|
|
42
|
-
})(["font-size:10px;line-height:1.6;font-weight:500;text-transform:uppercase;color:", ";padding:0 12px;flex-basis:100%;height:", ";line-height:", ";"],
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
32
|
+
})(["font-size:10px;line-height:1.6;font-weight:500;text-transform:uppercase;color:", ";padding:0 12px;flex-basis:100%;height:", ";line-height:", ";"], (props) => props.theme.palette["grey-500"], (props) => props.elementSize, (props) => props.elementSize);
|
|
33
|
+
export {
|
|
34
|
+
EmojiButton,
|
|
35
|
+
EmojiCategoryWrapper,
|
|
36
|
+
EmojiItem,
|
|
37
|
+
EmptyList,
|
|
38
|
+
ListRow,
|
|
39
|
+
Title,
|
|
40
|
+
VirtualList
|
|
41
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
import { Emoji } from 'unicode-emoji-utils';
|
|
3
3
|
export type EmojiListTexts = {
|
|
4
4
|
'smileys-emotion': ReactNode;
|
|
5
5
|
'people-body': ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { Emoji, getEmojisByGroup as getEmojisByGroupBase } from 'unicode-emoji-utils';
|
|
2
|
+
import { EmojiCategories, ListItemData } from './EmojiList.types';
|
|
3
3
|
export declare const createItemData: (items: ListItemData["items"], elementSize: ListItemData["elementSize"], onSelect: ListItemData["onSelect"], itemsPerRow: ListItemData["itemsPerRow"]) => ListItemData;
|
|
4
4
|
export declare const getEmojisByGroup: (...props: Parameters<typeof getEmojisByGroupBase>) => Map<EmojiCategories, Emoji[]>;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import memoize from
|
|
2
|
-
import { getEmojisByGroup as
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import memoize from "memoize-one";
|
|
2
|
+
import { getEmojisByGroup as getEmojisByGroup$1 } from "unicode-emoji-utils";
|
|
3
|
+
const createItemData = memoize((items, elementSize, onSelect, itemsPerRow) => ({
|
|
4
|
+
items,
|
|
5
|
+
elementSize,
|
|
6
|
+
onSelect,
|
|
7
|
+
itemsPerRow
|
|
8
|
+
}));
|
|
9
|
+
const getEmojisByGroup = getEmojisByGroup$1;
|
|
10
|
+
export {
|
|
11
|
+
createItemData,
|
|
12
|
+
getEmojisByGroup
|
|
13
|
+
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import React,
|
|
2
|
-
import {
|
|
1
|
+
import { default as React, ReactElement } from 'react';
|
|
2
|
+
import { RowItemProps } from './EmojiList.types';
|
|
3
3
|
export declare const EmojiListItem: React.MemoExoticComponent<({ data, index, style }: RowItemProps) => ReactElement>;
|
|
@@ -1,36 +1,27 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from "react";
|
|
3
|
+
import { areEqual } from "react-window";
|
|
4
|
+
import Tooltip from "@synerise/ds-tooltip";
|
|
5
|
+
import { ListRow, Title, EmojiItem, EmojiButton } from "./EmojiList.styles.js";
|
|
6
|
+
const isTitle = (item) => {
|
|
7
|
+
return item[0] && "title" in item[0];
|
|
8
|
+
};
|
|
9
|
+
const EmojiListItem = memo(({
|
|
10
|
+
data,
|
|
11
|
+
index,
|
|
12
|
+
style
|
|
13
|
+
}) => {
|
|
14
|
+
const {
|
|
15
|
+
elementSize,
|
|
16
|
+
itemsPerRow,
|
|
17
|
+
onSelect,
|
|
18
|
+
items
|
|
19
|
+
} = data;
|
|
20
|
+
const rowItems = items[index];
|
|
21
|
+
return /* @__PURE__ */ jsx("div", { style, children: /* @__PURE__ */ jsx(ListRow, { children: isTitle(rowItems) ? /* @__PURE__ */ jsx(Title, { elementSize: `${elementSize}px`, children: rowItems[0].title }) : rowItems.map((item) => {
|
|
22
|
+
return /* @__PURE__ */ jsx(Tooltip, { title: item.keywords?.join(", "), children: /* @__PURE__ */ jsx(EmojiItem, { onClick: () => onSelect && onSelect(item), itemsPerRow, children: /* @__PURE__ */ jsx(EmojiButton, { "data-testid": "ds-emoji-item", "data-keywords": item.keywords?.join(","), children: item.emoji }) }, item.emoji) });
|
|
23
|
+
}) }) });
|
|
24
|
+
}, areEqual);
|
|
25
|
+
export {
|
|
26
|
+
EmojiListItem
|
|
7
27
|
};
|
|
8
|
-
export var EmojiListItem = /*#__PURE__*/memo(function (_ref) {
|
|
9
|
-
var data = _ref.data,
|
|
10
|
-
index = _ref.index,
|
|
11
|
-
style = _ref.style;
|
|
12
|
-
var elementSize = data.elementSize,
|
|
13
|
-
itemsPerRow = data.itemsPerRow,
|
|
14
|
-
onSelect = data.onSelect,
|
|
15
|
-
items = data.items;
|
|
16
|
-
var rowItems = items[index];
|
|
17
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
18
|
-
style: style
|
|
19
|
-
}, /*#__PURE__*/React.createElement(S.ListRow, null, isTitle(rowItems) ? /*#__PURE__*/React.createElement(S.Title, {
|
|
20
|
-
elementSize: elementSize + "px"
|
|
21
|
-
}, rowItems[0].title) : rowItems.map(function (item) {
|
|
22
|
-
var _item$keywords, _item$keywords2;
|
|
23
|
-
return /*#__PURE__*/React.createElement(Tooltip, {
|
|
24
|
-
title: (_item$keywords = item.keywords) == null ? void 0 : _item$keywords.join(', ')
|
|
25
|
-
}, /*#__PURE__*/React.createElement(S.EmojiItem, {
|
|
26
|
-
onClick: function onClick() {
|
|
27
|
-
return onSelect && onSelect(item);
|
|
28
|
-
},
|
|
29
|
-
itemsPerRow: itemsPerRow,
|
|
30
|
-
key: item.emoji
|
|
31
|
-
}, /*#__PURE__*/React.createElement(S.EmojiButton, {
|
|
32
|
-
"data-testid": "ds-emoji-item",
|
|
33
|
-
"data-keywords": (_item$keywords2 = item.keywords) == null ? void 0 : _item$keywords2.join(',')
|
|
34
|
-
}, item.emoji)));
|
|
35
|
-
})));
|
|
36
|
-
}, areEqual);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { EmojiOverlayType } from './EmojiOverlay.types';
|
|
3
3
|
export declare const EmojiOverlay: ({ texts: customTexts, onSelect, focus, }: EmojiOverlayType) => React.JSX.Element;
|
|
@@ -1,36 +1,28 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
setSearchQuery(
|
|
1
|
+
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { theme } from "@synerise/ds-core";
|
|
4
|
+
import Dropdown from "@synerise/ds-dropdown";
|
|
5
|
+
import Icon, { SearchM } from "@synerise/ds-icon";
|
|
6
|
+
import { EmojiList } from "../EmojiList/EmojiList.js";
|
|
7
|
+
import { useEmojiTranslations } from "../hooks/useEmojiTranslations.js";
|
|
8
|
+
const EmojiOverlay = ({
|
|
9
|
+
texts: customTexts,
|
|
10
|
+
onSelect,
|
|
11
|
+
focus
|
|
12
|
+
}) => {
|
|
13
|
+
const texts = useEmojiTranslations(customTexts);
|
|
14
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
15
|
+
const handleClearInput = () => {
|
|
16
|
+
setSearchQuery("");
|
|
17
17
|
};
|
|
18
|
-
|
|
18
|
+
const handleSearchChange = (query) => {
|
|
19
19
|
setSearchQuery(query);
|
|
20
20
|
};
|
|
21
|
-
return
|
|
22
|
-
onSearchChange: handleSearchChange,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
color: theme.palette['grey-600']
|
|
30
|
-
})
|
|
31
|
-
}), /*#__PURE__*/React.createElement(EmojiList, {
|
|
32
|
-
onSelect: onSelect,
|
|
33
|
-
searchQuery: searchQuery,
|
|
34
|
-
texts: texts
|
|
35
|
-
}));
|
|
36
|
-
};
|
|
21
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
22
|
+
/* @__PURE__ */ jsx(Dropdown.SearchInput, { onSearchChange: handleSearchChange, onClearInput: handleClearInput, placeholder: texts.placeholder, value: searchQuery, autofocus: focus, iconLeft: /* @__PURE__ */ jsx(Icon, { component: /* @__PURE__ */ jsx(SearchM, {}), color: theme.palette["grey-600"] }) }),
|
|
23
|
+
/* @__PURE__ */ jsx(EmojiList, { onSelect, searchQuery, texts })
|
|
24
|
+
] });
|
|
25
|
+
};
|
|
26
|
+
export {
|
|
27
|
+
EmojiOverlay
|
|
28
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
|
package/dist/EmojiPicker.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { EmojiPickerProps } from './EmojiPicker.types';
|
|
3
3
|
export declare const EmojiPicker: ({ children, closeOnSelect, onSelect, texts, dropdownProps, }: EmojiPickerProps) => React.JSX.Element;
|
package/dist/EmojiPicker.js
CHANGED
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import Dropdown from
|
|
4
|
-
import { useOnClickOutside } from
|
|
5
|
-
import { EmojiOverlay } from
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
setFocus = _useState2[1];
|
|
20
|
-
var ref = useRef(null);
|
|
21
|
-
var triggerRef = useRef(null);
|
|
22
|
-
useOnClickOutside(ref, function (event) {
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useRef } from "react";
|
|
3
|
+
import Dropdown from "@synerise/ds-dropdown";
|
|
4
|
+
import { useOnClickOutside } from "@synerise/ds-utils";
|
|
5
|
+
import { EmojiOverlay } from "./EmojiOverlay/EmojiOverlay.js";
|
|
6
|
+
import { Overlay } from "./EmojiPicker.styles.js";
|
|
7
|
+
const EmojiPicker = ({
|
|
8
|
+
children,
|
|
9
|
+
closeOnSelect = true,
|
|
10
|
+
onSelect,
|
|
11
|
+
texts,
|
|
12
|
+
dropdownProps
|
|
13
|
+
}) => {
|
|
14
|
+
const [isOpen, setOpen] = useState(false);
|
|
15
|
+
const [focus, setFocus] = useState(false);
|
|
16
|
+
const ref = useRef(null);
|
|
17
|
+
const triggerRef = useRef(null);
|
|
18
|
+
useOnClickOutside(ref, (event) => {
|
|
23
19
|
if (triggerRef.current && event.target) {
|
|
24
20
|
if (triggerRef.current.contains(event.target)) {
|
|
25
21
|
return;
|
|
@@ -27,32 +23,18 @@ export var EmojiPicker = function EmojiPicker(_ref) {
|
|
|
27
23
|
}
|
|
28
24
|
setOpen(false);
|
|
29
25
|
});
|
|
30
|
-
|
|
26
|
+
const toggleOpen = (newState) => {
|
|
31
27
|
setOpen(newState);
|
|
32
28
|
setFocus(newState);
|
|
33
29
|
};
|
|
34
|
-
return
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
ref: ref,
|
|
46
|
-
onClick: function onClick(event) {
|
|
47
|
-
return event.stopPropagation();
|
|
48
|
-
}
|
|
49
|
-
}, /*#__PURE__*/React.createElement(EmojiOverlay, {
|
|
50
|
-
onSelect: function onSelect(val) {
|
|
51
|
-
closeOnSelect && toggleOpen(false);
|
|
52
|
-
_onSelect == null || _onSelect(val);
|
|
53
|
-
},
|
|
54
|
-
texts: texts,
|
|
55
|
-
focus: focus
|
|
56
|
-
}))
|
|
57
|
-
}), children);
|
|
58
|
-
};
|
|
30
|
+
return /* @__PURE__ */ jsx(Dropdown, { open: isOpen, onOpenChange: toggleOpen, placement: "bottomRight", asChild: true, ...dropdownProps, popoverProps: {
|
|
31
|
+
testId: "emojipicker",
|
|
32
|
+
...dropdownProps?.popoverProps
|
|
33
|
+
}, size: "medium", overlay: /* @__PURE__ */ jsx(Overlay, { ref, onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsx(EmojiOverlay, { onSelect: (val) => {
|
|
34
|
+
closeOnSelect && toggleOpen(false);
|
|
35
|
+
onSelect?.(val);
|
|
36
|
+
}, texts, focus }) }), children });
|
|
37
|
+
};
|
|
38
|
+
export {
|
|
39
|
+
EmojiPicker
|
|
40
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const Overlay: import(
|
|
1
|
+
export declare const Overlay: import('styled-components').StyledComponent<"div", any, {}, never>;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import styled from
|
|
2
|
-
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
const Overlay = /* @__PURE__ */ styled.div.withConfig({
|
|
3
3
|
displayName: "EmojiPickerstyles__Overlay",
|
|
4
4
|
componentId: "sc-562kws-0"
|
|
5
|
-
})([""]);
|
|
5
|
+
})([""]);
|
|
6
|
+
export {
|
|
7
|
+
Overlay
|
|
8
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import { Emoji } from 'unicode-emoji-utils';
|
|
3
|
+
import { DropdownSharedProps } from '@synerise/ds-dropdown';
|
|
4
|
+
import { EmojiListTexts } from './EmojiList/EmojiList.types';
|
|
5
5
|
export type EmojiPickerTexts = EmojiListTexts & {
|
|
6
6
|
placeholder: string;
|
|
7
7
|
empty: ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EmojiPickerTexts } from '../EmojiPicker.types';
|
|
2
2
|
export declare const useEmojiTranslations: (texts?: Partial<EmojiPickerTexts>) => EmojiPickerTexts;
|
|
@@ -1,56 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
formatMessage
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
'travel-places': /*#__PURE__*/React.createElement(FormattedMessage, {
|
|
26
|
-
id: "DS.ICON-PICKER.SMILEYS",
|
|
27
|
-
defaultMessage: "Travel & places"
|
|
28
|
-
}),
|
|
29
|
-
activities: /*#__PURE__*/React.createElement(FormattedMessage, {
|
|
30
|
-
id: "DS.ICON-PICKER.SMILEYS",
|
|
31
|
-
defaultMessage: "Activities"
|
|
32
|
-
}),
|
|
33
|
-
objects: /*#__PURE__*/React.createElement(FormattedMessage, {
|
|
34
|
-
id: "DS.ICON-PICKER.SMILEYS",
|
|
35
|
-
defaultMessage: "Objects"
|
|
36
|
-
}),
|
|
37
|
-
symbols: /*#__PURE__*/React.createElement(FormattedMessage, {
|
|
38
|
-
id: "DS.ICON-PICKER.SMILEYS",
|
|
39
|
-
defaultMessage: "Symbols"
|
|
40
|
-
}),
|
|
41
|
-
flags: /*#__PURE__*/React.createElement(FormattedMessage, {
|
|
42
|
-
id: "DS.ICON-PICKER.SMILEYS",
|
|
43
|
-
defaultMessage: "Flags"
|
|
44
|
-
}),
|
|
45
|
-
placeholder: formatMessage({
|
|
46
|
-
id: 'DS.ICON-PICKER.PLACEHOLDER',
|
|
47
|
-
defaultMessage: 'Search'
|
|
48
|
-
}),
|
|
49
|
-
empty: /*#__PURE__*/React.createElement(FormattedMessage, {
|
|
50
|
-
id: "DS.ICON-PICKER.NO-MATCHES",
|
|
51
|
-
defaultMessage: "No emojis found"
|
|
52
|
-
})
|
|
53
|
-
}, texts || {});
|
|
54
|
-
}, [texts, formatMessage]);
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { useIntl, FormattedMessage } from "react-intl";
|
|
4
|
+
const useEmojiTranslations = (texts) => {
|
|
5
|
+
const {
|
|
6
|
+
formatMessage
|
|
7
|
+
} = useIntl();
|
|
8
|
+
const allTexts = useMemo(() => ({
|
|
9
|
+
"smileys-emotion": /* @__PURE__ */ jsx(FormattedMessage, { id: "DS.ICON-PICKER.SMILEYS", defaultMessage: "Smileys" }),
|
|
10
|
+
"people-body": /* @__PURE__ */ jsx(FormattedMessage, { id: "DS.ICON-PICKER.SMILEYS", defaultMessage: "People & body" }),
|
|
11
|
+
"animals-nature": /* @__PURE__ */ jsx(FormattedMessage, { id: "DS.ICON-PICKER.SMILEYS", defaultMessage: "Animals & nature" }),
|
|
12
|
+
"food-drink": /* @__PURE__ */ jsx(FormattedMessage, { id: "DS.ICON-PICKER.SMILEYS", defaultMessage: "Food & drink" }),
|
|
13
|
+
"travel-places": /* @__PURE__ */ jsx(FormattedMessage, { id: "DS.ICON-PICKER.SMILEYS", defaultMessage: "Travel & places" }),
|
|
14
|
+
activities: /* @__PURE__ */ jsx(FormattedMessage, { id: "DS.ICON-PICKER.SMILEYS", defaultMessage: "Activities" }),
|
|
15
|
+
objects: /* @__PURE__ */ jsx(FormattedMessage, { id: "DS.ICON-PICKER.SMILEYS", defaultMessage: "Objects" }),
|
|
16
|
+
symbols: /* @__PURE__ */ jsx(FormattedMessage, { id: "DS.ICON-PICKER.SMILEYS", defaultMessage: "Symbols" }),
|
|
17
|
+
flags: /* @__PURE__ */ jsx(FormattedMessage, { id: "DS.ICON-PICKER.SMILEYS", defaultMessage: "Flags" }),
|
|
18
|
+
placeholder: formatMessage({
|
|
19
|
+
id: "DS.ICON-PICKER.PLACEHOLDER",
|
|
20
|
+
defaultMessage: "Search"
|
|
21
|
+
}),
|
|
22
|
+
empty: /* @__PURE__ */ jsx(FormattedMessage, { id: "DS.ICON-PICKER.NO-MATCHES", defaultMessage: "No emojis found" }),
|
|
23
|
+
...texts || {}
|
|
24
|
+
}), [texts, formatMessage]);
|
|
55
25
|
return allTexts;
|
|
56
|
-
};
|
|
26
|
+
};
|
|
27
|
+
export {
|
|
28
|
+
useEmojiTranslations
|
|
29
|
+
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { EmojiCategory, EmojiVirtualListItem } from '../EmojiList/EmojiList.types';
|
|
2
2
|
export declare const useMultipleItemsPerRow: (data: EmojiCategory[], itemsPerRow: number) => EmojiVirtualListItem[];
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import { useMemo } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
return data.reduce(
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
const useMultipleItemsPerRow = (data, itemsPerRow) => {
|
|
3
|
+
const groupedData = useMemo(() => {
|
|
4
|
+
return data.reduce((flatItemsAndCategories, group) => {
|
|
5
|
+
const {
|
|
6
|
+
title,
|
|
7
|
+
emojis
|
|
8
|
+
} = group;
|
|
7
9
|
flatItemsAndCategories.push([{
|
|
8
|
-
title
|
|
10
|
+
title
|
|
9
11
|
}]);
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
for (
|
|
13
|
-
|
|
14
|
-
for (
|
|
15
|
-
|
|
12
|
+
const groupItemsLength = emojis.length;
|
|
13
|
+
const rowCount = Math.ceil(groupItemsLength / itemsPerRow);
|
|
14
|
+
for (let i = 0; i < rowCount; i += 1) {
|
|
15
|
+
const rowItems = [];
|
|
16
|
+
for (let j = 0; j < itemsPerRow; j += 1) {
|
|
17
|
+
const idx = itemsPerRow * i + j;
|
|
16
18
|
if (idx < groupItemsLength) {
|
|
17
19
|
rowItems.push(emojis[idx]);
|
|
18
20
|
}
|
|
@@ -23,4 +25,7 @@ export var useMultipleItemsPerRow = function useMultipleItemsPerRow(data, itemsP
|
|
|
23
25
|
}, []);
|
|
24
26
|
}, [data, itemsPerRow]);
|
|
25
27
|
return groupedData;
|
|
26
|
-
};
|
|
28
|
+
};
|
|
29
|
+
export {
|
|
30
|
+
useMultipleItemsPerRow
|
|
31
|
+
};
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synerise/ds-emoji-picker",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.24",
|
|
4
4
|
"description": "EmojiPicker UI Component for the Synerise Design System",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"repository": "Synerise/synerise-design",
|
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
"access": "public"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "
|
|
19
|
+
"build": "vite build",
|
|
20
20
|
"build:css": "node ../../../scripts/style/less.js",
|
|
21
21
|
"build:js": "babel --delete-dir-on-start --root-mode upward src --out-dir dist --extensions '.js,.ts,.tsx'",
|
|
22
|
-
"build:watch": "
|
|
22
|
+
"build:watch": "vite build --watch",
|
|
23
23
|
"defs": "tsc --declaration --outDir dist/ --emitDeclarationOnly",
|
|
24
24
|
"pack:ci": "pnpm pack --pack-destination ../../storybook/storybook-static/static",
|
|
25
25
|
"prepublish": "pnpm run build",
|
|
@@ -35,15 +35,16 @@
|
|
|
35
35
|
],
|
|
36
36
|
"types": "dist/index.d.ts",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@synerise/ds-button": "^1.5.
|
|
39
|
-
"@synerise/ds-divider": "^1.3.
|
|
40
|
-
"@synerise/ds-dropdown": "^1.3.
|
|
41
|
-
"@synerise/ds-empty-states": "^1.0.
|
|
42
|
-
"@synerise/ds-icon": "^1.
|
|
43
|
-
"@synerise/ds-scrollbar": "^1.2.
|
|
44
|
-
"@synerise/ds-tooltip": "^1.4.
|
|
45
|
-
"@synerise/ds-utils": "^1.
|
|
38
|
+
"@synerise/ds-button": "^1.5.18",
|
|
39
|
+
"@synerise/ds-divider": "^1.3.2",
|
|
40
|
+
"@synerise/ds-dropdown": "^1.3.2",
|
|
41
|
+
"@synerise/ds-empty-states": "^1.0.36",
|
|
42
|
+
"@synerise/ds-icon": "^1.15.1",
|
|
43
|
+
"@synerise/ds-scrollbar": "^1.2.17",
|
|
44
|
+
"@synerise/ds-tooltip": "^1.4.10",
|
|
45
|
+
"@synerise/ds-utils": "^1.7.1",
|
|
46
46
|
"memoize-one": "^5.1.1",
|
|
47
|
+
"react-window": "^1.8.11",
|
|
47
48
|
"unicode-emoji-utils": "^1.2.0"
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
@@ -52,5 +53,5 @@
|
|
|
52
53
|
"react-intl": ">=3.12.0 <= 6.8",
|
|
53
54
|
"styled-components": "^5.3.3"
|
|
54
55
|
},
|
|
55
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "e4ecca8944fc9b41c1b9d59c8bcad5e5e2013225"
|
|
56
57
|
}
|