@liveblocks/react-ui 2.21.0-emails3 → 2.22.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.
Files changed (108) hide show
  1. package/dist/_private/index.cjs +2 -2
  2. package/dist/_private/index.d.cts +2 -2
  3. package/dist/_private/index.d.ts +2 -2
  4. package/dist/_private/index.js +1 -1
  5. package/dist/components/Comment.cjs +3 -3
  6. package/dist/components/Comment.cjs.map +1 -1
  7. package/dist/components/Comment.js +3 -3
  8. package/dist/components/Comment.js.map +1 -1
  9. package/dist/components/Composer.cjs.map +1 -1
  10. package/dist/components/Composer.js.map +1 -1
  11. package/dist/components/HistoryVersionSummary.cjs.map +1 -1
  12. package/dist/components/HistoryVersionSummary.js.map +1 -1
  13. package/dist/components/HistoryVersionSummaryList.cjs.map +1 -1
  14. package/dist/components/HistoryVersionSummaryList.js.map +1 -1
  15. package/dist/components/InboxNotification.cjs.map +1 -1
  16. package/dist/components/InboxNotification.js.map +1 -1
  17. package/dist/components/InboxNotificationList.cjs.map +1 -1
  18. package/dist/components/InboxNotificationList.js.map +1 -1
  19. package/dist/components/Thread.cjs.map +1 -1
  20. package/dist/components/Thread.js.map +1 -1
  21. package/dist/components/internal/Attachment.cjs.map +1 -1
  22. package/dist/components/internal/Attachment.js.map +1 -1
  23. package/dist/components/internal/Avatar.cjs.map +1 -1
  24. package/dist/components/internal/Avatar.js.map +1 -1
  25. package/dist/components/internal/Button.cjs.map +1 -1
  26. package/dist/components/internal/Button.js.map +1 -1
  27. package/dist/components/internal/Dropdown.cjs.map +1 -1
  28. package/dist/components/internal/Dropdown.js.map +1 -1
  29. package/dist/components/internal/EmojiPicker.cjs +68 -82
  30. package/dist/components/internal/EmojiPicker.cjs.map +1 -1
  31. package/dist/components/internal/EmojiPicker.js +70 -84
  32. package/dist/components/internal/EmojiPicker.js.map +1 -1
  33. package/dist/components/internal/Room.cjs.map +1 -1
  34. package/dist/components/internal/Room.js.map +1 -1
  35. package/dist/components/internal/Tooltip.cjs.map +1 -1
  36. package/dist/components/internal/Tooltip.js.map +1 -1
  37. package/dist/components/internal/User.cjs.map +1 -1
  38. package/dist/components/internal/User.js.map +1 -1
  39. package/dist/components.cjs.map +1 -1
  40. package/dist/components.js.map +1 -1
  41. package/dist/config.cjs.map +1 -1
  42. package/dist/config.js.map +1 -1
  43. package/dist/icon.cjs +16 -0
  44. package/dist/icon.cjs.map +1 -1
  45. package/dist/icon.js +8 -0
  46. package/dist/icon.js.map +1 -1
  47. package/dist/icons/{EmojiAdd.cjs → EmojiPlus.cjs} +3 -3
  48. package/dist/icons/EmojiPlus.cjs.map +1 -0
  49. package/dist/icons/{EmojiAdd.js → EmojiPlus.js} +3 -3
  50. package/dist/icons/EmojiPlus.js.map +1 -0
  51. package/dist/icons/index.cjs +2 -2
  52. package/dist/icons/index.js +1 -1
  53. package/dist/index.d.cts +25 -0
  54. package/dist/index.d.ts +25 -0
  55. package/dist/overrides.cjs +1 -0
  56. package/dist/overrides.cjs.map +1 -1
  57. package/dist/overrides.js +1 -0
  58. package/dist/overrides.js.map +1 -1
  59. package/dist/primitives/Composer/index.cjs.map +1 -1
  60. package/dist/primitives/Composer/index.js.map +1 -1
  61. package/dist/primitives/FileSize.cjs.map +1 -1
  62. package/dist/primitives/FileSize.js.map +1 -1
  63. package/dist/primitives/Timestamp.cjs.map +1 -1
  64. package/dist/primitives/Timestamp.js.map +1 -1
  65. package/dist/primitives/index.cjs +0 -2
  66. package/dist/primitives/index.cjs.map +1 -1
  67. package/dist/primitives/index.d.cts +4 -165
  68. package/dist/primitives/index.d.ts +4 -165
  69. package/dist/primitives/index.js +0 -2
  70. package/dist/primitives/index.js.map +1 -1
  71. package/dist/slate/plugins/paste.cjs +8 -1
  72. package/dist/slate/plugins/paste.cjs.map +1 -1
  73. package/dist/slate/plugins/paste.js +8 -1
  74. package/dist/slate/plugins/paste.js.map +1 -1
  75. package/dist/utils/Persist.cjs.map +1 -1
  76. package/dist/utils/Persist.js.map +1 -1
  77. package/dist/utils/Portal.cjs.map +1 -1
  78. package/dist/utils/Portal.js.map +1 -1
  79. package/dist/version.cjs +1 -1
  80. package/dist/version.cjs.map +1 -1
  81. package/dist/version.js +1 -1
  82. package/dist/version.js.map +1 -1
  83. package/package.json +5 -7
  84. package/src/styles/index.css +54 -10
  85. package/styles.css +1 -1
  86. package/styles.css.map +1 -1
  87. package/dist/icons/EmojiAdd.cjs.map +0 -1
  88. package/dist/icons/EmojiAdd.js.map +0 -1
  89. package/dist/primitives/EmojiPicker/contexts.cjs +0 -19
  90. package/dist/primitives/EmojiPicker/contexts.cjs.map +0 -1
  91. package/dist/primitives/EmojiPicker/contexts.js +0 -16
  92. package/dist/primitives/EmojiPicker/contexts.js.map +0 -1
  93. package/dist/primitives/EmojiPicker/index.cjs +0 -516
  94. package/dist/primitives/EmojiPicker/index.cjs.map +0 -1
  95. package/dist/primitives/EmojiPicker/index.js +0 -512
  96. package/dist/primitives/EmojiPicker/index.js.map +0 -1
  97. package/dist/primitives/EmojiPicker/utils.cjs +0 -330
  98. package/dist/primitives/EmojiPicker/utils.cjs.map +0 -1
  99. package/dist/primitives/EmojiPicker/utils.js +0 -326
  100. package/dist/primitives/EmojiPicker/utils.js.map +0 -1
  101. package/dist/utils/request-idle-callback.cjs +0 -15
  102. package/dist/utils/request-idle-callback.cjs.map +0 -1
  103. package/dist/utils/request-idle-callback.js +0 -12
  104. package/dist/utils/request-idle-callback.js.map +0 -1
  105. package/dist/utils/visually-hidden.cjs +0 -17
  106. package/dist/utils/visually-hidden.cjs.map +0 -1
  107. package/dist/utils/visually-hidden.js +0 -15
  108. package/dist/utils/visually-hidden.js.map +0 -1
@@ -1,19 +0,0 @@
1
- 'use strict';
2
-
3
- var core = require('@liveblocks/core');
4
- var react = require('react');
5
-
6
- const EmojiPickerContext = react.createContext(
7
- null
8
- );
9
- function useEmojiPicker() {
10
- const emojiPickerContext = react.useContext(EmojiPickerContext);
11
- return core.nn(
12
- emojiPickerContext,
13
- "EmojiPicker.Root is missing from the React tree."
14
- );
15
- }
16
-
17
- exports.EmojiPickerContext = EmojiPickerContext;
18
- exports.useEmojiPicker = useEmojiPicker;
19
- //# sourceMappingURL=contexts.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"contexts.cjs","sources":["../../../src/primitives/EmojiPicker/contexts.ts"],"sourcesContent":["import type { Relax, Resolve } from \"@liveblocks/core\";\nimport { nn } from \"@liveblocks/core\";\nimport type { Dispatch, KeyboardEvent, SetStateAction } from \"react\";\nimport { createContext, useContext } from \"react\";\n\nimport type {\n EmojiPickerData,\n EmojiPickerInteraction,\n EmojiPickerSelectionDirection,\n} from \"./types\";\n\ntype EmojiPickerContextData = Relax<\n | { isLoading: true }\n | {\n data: EmojiPickerData;\n isLoading: false;\n }\n | {\n error: Error;\n isLoading: false;\n }\n>;\n\nexport type EmojiPickerContext = Resolve<\n EmojiPickerContextData & {\n columns: number;\n onSearch: (search: string) => void;\n selectCurrentEmoji: () => void;\n onEmojiSelect?: (emoji: string) => void;\n selectedColumnIndex: number;\n selectedRowIndex: number;\n moveSelection: (\n direction: EmojiPickerSelectionDirection,\n event: KeyboardEvent<HTMLInputElement>\n ) => void;\n setPointerSelection: (columnIndex: number, rowIndex: number) => void;\n interaction: EmojiPickerInteraction;\n setInteraction: Dispatch<SetStateAction<EmojiPickerInteraction>>;\n }\n>;\n\nexport const EmojiPickerContext = createContext<EmojiPickerContext | null>(\n null\n);\n\nexport function useEmojiPicker(): EmojiPickerContext {\n const emojiPickerContext = useContext(EmojiPickerContext);\n\n return nn(\n emojiPickerContext,\n \"EmojiPicker.Root is missing from the React tree.\"\n );\n}\n"],"names":["createContext","useContext","nn"],"mappings":";;;;;AAyCO,MAAM,kBAAqB,GAAAA,mBAAA;AAAA,EAChC,IAAA;AACF,EAAA;AAEO,SAAS,cAAqC,GAAA;AACnD,EAAM,MAAA,kBAAA,GAAqBC,iBAAW,kBAAkB,CAAA,CAAA;AAExD,EAAO,OAAAC,OAAA;AAAA,IACL,kBAAA;AAAA,IACA,kDAAA;AAAA,GACF,CAAA;AACF;;;;;"}
@@ -1,16 +0,0 @@
1
- import { nn } from '@liveblocks/core';
2
- import { createContext, useContext } from 'react';
3
-
4
- const EmojiPickerContext = createContext(
5
- null
6
- );
7
- function useEmojiPicker() {
8
- const emojiPickerContext = useContext(EmojiPickerContext);
9
- return nn(
10
- emojiPickerContext,
11
- "EmojiPicker.Root is missing from the React tree."
12
- );
13
- }
14
-
15
- export { EmojiPickerContext, useEmojiPicker };
16
- //# sourceMappingURL=contexts.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"contexts.js","sources":["../../../src/primitives/EmojiPicker/contexts.ts"],"sourcesContent":["import type { Relax, Resolve } from \"@liveblocks/core\";\nimport { nn } from \"@liveblocks/core\";\nimport type { Dispatch, KeyboardEvent, SetStateAction } from \"react\";\nimport { createContext, useContext } from \"react\";\n\nimport type {\n EmojiPickerData,\n EmojiPickerInteraction,\n EmojiPickerSelectionDirection,\n} from \"./types\";\n\ntype EmojiPickerContextData = Relax<\n | { isLoading: true }\n | {\n data: EmojiPickerData;\n isLoading: false;\n }\n | {\n error: Error;\n isLoading: false;\n }\n>;\n\nexport type EmojiPickerContext = Resolve<\n EmojiPickerContextData & {\n columns: number;\n onSearch: (search: string) => void;\n selectCurrentEmoji: () => void;\n onEmojiSelect?: (emoji: string) => void;\n selectedColumnIndex: number;\n selectedRowIndex: number;\n moveSelection: (\n direction: EmojiPickerSelectionDirection,\n event: KeyboardEvent<HTMLInputElement>\n ) => void;\n setPointerSelection: (columnIndex: number, rowIndex: number) => void;\n interaction: EmojiPickerInteraction;\n setInteraction: Dispatch<SetStateAction<EmojiPickerInteraction>>;\n }\n>;\n\nexport const EmojiPickerContext = createContext<EmojiPickerContext | null>(\n null\n);\n\nexport function useEmojiPicker(): EmojiPickerContext {\n const emojiPickerContext = useContext(EmojiPickerContext);\n\n return nn(\n emojiPickerContext,\n \"EmojiPicker.Root is missing from the React tree.\"\n );\n}\n"],"names":[],"mappings":";;;AAyCO,MAAM,kBAAqB,GAAA,aAAA;AAAA,EAChC,IAAA;AACF,EAAA;AAEO,SAAS,cAAqC,GAAA;AACnD,EAAM,MAAA,kBAAA,GAAqB,WAAW,kBAAkB,CAAA,CAAA;AAExD,EAAO,OAAA,EAAA;AAAA,IACL,kBAAA;AAAA,IACA,kDAAA;AAAA,GACF,CAAA;AACF;;;;"}
@@ -1,516 +0,0 @@
1
- "use client";
2
- 'use strict';
3
-
4
- var jsxRuntime = require('react/jsx-runtime');
5
- var _private = require('@liveblocks/react/_private');
6
- var reactSlot = require('@radix-ui/react-slot');
7
- var react = require('react');
8
- var reactVirtuoso = require('react-virtuoso');
9
- var isKey = require('../../utils/is-key.cjs');
10
- var requestIdleCallback = require('../../utils/request-idle-callback.cjs');
11
- var visuallyHidden = require('../../utils/visually-hidden.cjs');
12
- var Emoji = require('../internal/Emoji.cjs');
13
- var contexts = require('./contexts.cjs');
14
- var utils = require('./utils.cjs');
15
-
16
-
17
- const DEFAULT_COLUMNS = 10;
18
- const DEFAULT_LOCALE = "en";
19
- const LOADING_MINIMUM_TIMEOUT = 100;
20
- const EMOJIPICKER_ROOT_NAME = "EmojiPickerRoot";
21
- const EMOJIPICKER_CONTENT_NAME = "EmojiPickerContent";
22
- const EMOJIPICKER_SEARCH_NAME = "EmojiPickerSearch";
23
- function EmojiPickerRoot({
24
- columns = DEFAULT_COLUMNS,
25
- locale = DEFAULT_LOCALE,
26
- onEmojiSelect,
27
- children
28
- }) {
29
- const emojiData = react.useRef();
30
- const search = react.useRef("");
31
- const [, startEmojisTransition] = react.useTransition();
32
- const [data, setData] = react.useState();
33
- const [error, setError] = react.useState();
34
- const [selectedColumnIndex, setSelectedColumnIndex] = react.useState(0);
35
- const [selectedRowIndex, setSelectedRowIndex] = react.useState(0);
36
- const [interaction, setInteraction] = react.useState("none");
37
- const selectCurrentEmoji = react.useCallback(() => {
38
- if (onEmojiSelect) {
39
- const emoji = data?.rows[selectedRowIndex]?.[selectedColumnIndex];
40
- if (emoji) {
41
- onEmojiSelect(emoji.emoji);
42
- }
43
- }
44
- }, [data?.rows, onEmojiSelect, selectedColumnIndex, selectedRowIndex]);
45
- const resetSelection = react.useCallback(() => {
46
- setSelectedColumnIndex(0);
47
- setSelectedRowIndex(0);
48
- }, []);
49
- const setPointerSelection = react.useCallback(
50
- (columnIndex, rowIndex) => {
51
- setInteraction("pointer");
52
- setSelectedColumnIndex(columnIndex);
53
- setSelectedRowIndex(rowIndex);
54
- },
55
- []
56
- );
57
- const moveSelection = react.useCallback(
58
- (direction, event) => {
59
- if (!data) {
60
- return;
61
- }
62
- event.preventDefault();
63
- if (interaction === "none") {
64
- setInteraction("keyboard");
65
- return;
66
- }
67
- setInteraction("keyboard");
68
- switch (direction) {
69
- case "left": {
70
- if (selectedColumnIndex === 0) {
71
- const previousRowIndex = selectedRowIndex - 1;
72
- const previousRow = data.rows[previousRowIndex];
73
- if (previousRow) {
74
- setSelectedRowIndex(previousRowIndex);
75
- setSelectedColumnIndex(previousRow.length - 1);
76
- }
77
- } else {
78
- setSelectedColumnIndex(selectedColumnIndex - 1);
79
- }
80
- break;
81
- }
82
- case "right": {
83
- const currentRow = data.rows[selectedRowIndex];
84
- if (!currentRow) {
85
- return;
86
- }
87
- if (selectedColumnIndex === currentRow.length - 1) {
88
- const nextRowIndex = selectedRowIndex + 1;
89
- const nextRow = data.rows[nextRowIndex];
90
- if (nextRow) {
91
- setSelectedRowIndex(nextRowIndex);
92
- setSelectedColumnIndex(0);
93
- }
94
- } else {
95
- setSelectedColumnIndex(selectedColumnIndex + 1);
96
- }
97
- break;
98
- }
99
- case "up": {
100
- const previousRow = data.rows[selectedRowIndex - 1];
101
- if (previousRow) {
102
- setSelectedRowIndex(selectedRowIndex - 1);
103
- if (!previousRow[selectedColumnIndex]) {
104
- setSelectedColumnIndex(previousRow.length - 1);
105
- }
106
- }
107
- break;
108
- }
109
- case "down": {
110
- const nextRow = data.rows[selectedRowIndex + 1];
111
- if (nextRow) {
112
- setSelectedRowIndex(selectedRowIndex + 1);
113
- if (!nextRow[selectedColumnIndex]) {
114
- setSelectedColumnIndex(nextRow.length - 1);
115
- }
116
- }
117
- break;
118
- }
119
- }
120
- },
121
- [data, interaction, selectedColumnIndex, selectedRowIndex]
122
- );
123
- const updateEmojis = react.useCallback(() => {
124
- if (!emojiData.current) {
125
- return;
126
- }
127
- startEmojisTransition(() => {
128
- setData(() => {
129
- if (!emojiData.current) {
130
- return;
131
- }
132
- const filteredEmojis = utils.filterEmojis(
133
- emojiData.current.emojis,
134
- search.current
135
- );
136
- return utils.generateEmojiPickerData(
137
- filteredEmojis,
138
- emojiData.current.categories,
139
- columns
140
- );
141
- });
142
- resetSelection();
143
- });
144
- }, [columns, resetSelection]);
145
- const handleSearch = react.useCallback(
146
- (value) => {
147
- search.current = value;
148
- updateEmojis();
149
- },
150
- [updateEmojis]
151
- );
152
- const initializeEmojiData = react.useCallback(
153
- async (locale2) => {
154
- try {
155
- emojiData.current = await utils.getEmojiData(locale2);
156
- updateEmojis();
157
- } catch (error2) {
158
- setError(error2);
159
- }
160
- },
161
- [updateEmojis]
162
- );
163
- react.useEffect(() => {
164
- let idleCallbackId;
165
- const timeoutId = setTimeout(() => {
166
- idleCallbackId = requestIdleCallback.requestIdleCallback(() => {
167
- initializeEmojiData(locale);
168
- });
169
- }, LOADING_MINIMUM_TIMEOUT);
170
- return () => {
171
- clearTimeout(timeoutId);
172
- requestIdleCallback.cancelIdleCallback(idleCallbackId);
173
- };
174
- }, [locale]);
175
- react.useEffect(() => {
176
- if (interaction === "none") {
177
- resetSelection();
178
- }
179
- }, [interaction]);
180
- return /* @__PURE__ */ jsxRuntime.jsx(contexts.EmojiPickerContext.Provider, {
181
- value: {
182
- data,
183
- error,
184
- isLoading: !data && !error,
185
- columns,
186
- onSearch: handleSearch,
187
- onEmojiSelect,
188
- selectCurrentEmoji,
189
- selectedRowIndex,
190
- selectedColumnIndex,
191
- moveSelection,
192
- setPointerSelection,
193
- interaction,
194
- setInteraction
195
- },
196
- children
197
- });
198
- }
199
- const EmojiPickerSearch = react.forwardRef(
200
- ({ asChild, value, defaultValue, onChange, ...props }, forwardedRef) => {
201
- const Component = asChild ? reactSlot.Slot : "input";
202
- const {
203
- onSearch,
204
- selectCurrentEmoji,
205
- moveSelection,
206
- interaction,
207
- setInteraction
208
- } = contexts.useEmojiPicker();
209
- const handleChange = react.useCallback(
210
- (event) => {
211
- onChange?.(event);
212
- if (event.isDefaultPrevented()) {
213
- return;
214
- }
215
- const value2 = event.target.value;
216
- setInteraction(value2 ? "keyboard" : "none");
217
- onSearch(value2);
218
- },
219
- [onChange, onSearch, setInteraction]
220
- );
221
- const handleKeyDown = react.useCallback(
222
- (event) => {
223
- if (event.isDefaultPrevented()) {
224
- return;
225
- }
226
- if (isKey.isKey(event, "ArrowLeft")) {
227
- moveSelection("left", event);
228
- } else if (isKey.isKey(event, "ArrowRight")) {
229
- moveSelection("right", event);
230
- } else if (isKey.isKey(event, "ArrowUp")) {
231
- moveSelection("up", event);
232
- } else if (isKey.isKey(event, "ArrowDown")) {
233
- moveSelection("down", event);
234
- } else if (isKey.isKey(event, "Enter")) {
235
- if (interaction !== "none") {
236
- event.preventDefault();
237
- selectCurrentEmoji();
238
- }
239
- }
240
- },
241
- [interaction, moveSelection, selectCurrentEmoji]
242
- );
243
- react.useEffect(() => {
244
- onSearch(
245
- value ? String(value) : defaultValue ? String(defaultValue) : ""
246
- );
247
- }, []);
248
- return /* @__PURE__ */ jsxRuntime.jsx(Component, {
249
- type: "search",
250
- value,
251
- defaultValue,
252
- onChange: handleChange,
253
- onKeyDown: handleKeyDown,
254
- ...props,
255
- ref: forwardedRef
256
- });
257
- }
258
- );
259
- const defaultContentComponents = {
260
- CategoryHeader: ({ category, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", {
261
- ...props,
262
- children: category
263
- }),
264
- Row: ({ children, attributes, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", {
265
- ...props,
266
- children
267
- }),
268
- Emoji: ({ emoji, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("button", {
269
- ...props,
270
- children: /* @__PURE__ */ jsxRuntime.jsx(Emoji.Emoji, {
271
- emoji
272
- })
273
- }),
274
- Loading: (props) => /* @__PURE__ */ jsxRuntime.jsx("div", {
275
- ...props
276
- }),
277
- Empty: (props) => /* @__PURE__ */ jsxRuntime.jsx("div", {
278
- ...props
279
- }),
280
- Grid: (props) => /* @__PURE__ */ jsxRuntime.jsx("div", {
281
- ...props
282
- }),
283
- Error: ({ error, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", {
284
- ...props
285
- })
286
- };
287
- const placeholderRowAttributes = {
288
- rowIndex: -1,
289
- categoryRowIndex: -1,
290
- categoryRowsCount: 0
291
- };
292
- const VirtuosoScroller = react.forwardRef(
293
- ({ children, ...props }, forwardedRef) => {
294
- return /* @__PURE__ */ jsxRuntime.jsx("div", {
295
- ...props,
296
- tabIndex: -1,
297
- "data-testid": void 0,
298
- ref: forwardedRef,
299
- children
300
- });
301
- }
302
- );
303
- const VirtuosoTopList = react.forwardRef(
304
- ({ children, ...props }, forwardedRef) => {
305
- return /* @__PURE__ */ jsxRuntime.jsx("div", {
306
- ...props,
307
- "data-testid": void 0,
308
- ref: forwardedRef,
309
- children
310
- });
311
- }
312
- );
313
- const EmojiPickerContent = react.forwardRef(
314
- ({ components, asChild, ...props }, forwardedRef) => {
315
- const Component = asChild ? reactSlot.Slot : "div";
316
- const virtuosoRef = react.useRef(null);
317
- const placeholderContainerRef = react.useRef(null);
318
- const rowScrollMarginTopRef = react.useRef(0);
319
- const rowScrollMarginBottomRef = react.useRef(0);
320
- const categoryHeaderHeightRef = react.useRef(0);
321
- const {
322
- data,
323
- error,
324
- isLoading,
325
- columns,
326
- onEmojiSelect,
327
- selectedColumnIndex,
328
- selectedRowIndex,
329
- setPointerSelection,
330
- interaction,
331
- setInteraction
332
- } = contexts.useEmojiPicker();
333
- const selectedEmoji = react.useMemo(
334
- () => data?.rows[selectedRowIndex]?.[selectedColumnIndex],
335
- [data?.rows, selectedColumnIndex, selectedRowIndex]
336
- );
337
- const { Loading, Empty, Error, CategoryHeader, Grid, Row, Emoji } = react.useMemo(
338
- () => ({ ...defaultContentComponents, ...components }),
339
- [components]
340
- );
341
- const VirtuosoList = react.useMemo(
342
- () => react.forwardRef(
343
- ({ children, ...props2 }, forwardedRef2) => {
344
- return /* @__PURE__ */ jsxRuntime.jsx("div", {
345
- role: "grid",
346
- "aria-colcount": columns,
347
- ...props2,
348
- "data-testid": void 0,
349
- ref: forwardedRef2,
350
- children
351
- });
352
- }
353
- ),
354
- [columns]
355
- );
356
- const placeholderColumns = react.useMemo(
357
- () => Array(columns).fill("\u{1F32B}\uFE0F"),
358
- [columns]
359
- );
360
- const preventDefault = react.useCallback((event) => {
361
- event.preventDefault();
362
- }, []);
363
- const handleEmojiPointerLeave = react.useCallback(() => {
364
- if (interaction === "pointer") {
365
- setInteraction("none");
366
- }
367
- }, [interaction, setInteraction]);
368
- _private.useLayoutEffect(() => {
369
- if (!placeholderContainerRef.current) {
370
- return;
371
- }
372
- const row = placeholderContainerRef.current.childNodes[0];
373
- const categoryHeader = placeholderContainerRef.current.childNodes[1];
374
- if (row instanceof HTMLElement) {
375
- const style = window.getComputedStyle(row);
376
- rowScrollMarginTopRef.current = parseFloat(style.scrollMarginTop);
377
- rowScrollMarginBottomRef.current = parseFloat(style.scrollMarginBottom);
378
- }
379
- if (categoryHeader instanceof HTMLElement) {
380
- categoryHeaderHeightRef.current = categoryHeader.offsetHeight;
381
- }
382
- }, []);
383
- const calculateViewLocation = react.useCallback(
384
- ({
385
- itemTop,
386
- itemBottom,
387
- viewportTop,
388
- viewportBottom,
389
- locationParams: { behavior, align, ...params }
390
- }) => {
391
- if (itemTop - (categoryHeaderHeightRef.current + rowScrollMarginTopRef.current) < viewportTop) {
392
- return {
393
- ...params,
394
- behavior,
395
- align: align ?? "start"
396
- };
397
- }
398
- if (itemBottom > viewportBottom) {
399
- return {
400
- ...params,
401
- behavior,
402
- align: align ?? "end",
403
- offset: rowScrollMarginBottomRef.current
404
- };
405
- }
406
- return null;
407
- },
408
- []
409
- );
410
- react.useEffect(() => {
411
- if (interaction === "keyboard") {
412
- virtuosoRef.current?.scrollIntoView({
413
- index: selectedRowIndex,
414
- behavior: "auto",
415
- calculateViewLocation
416
- });
417
- }
418
- }, [interaction, selectedRowIndex, calculateViewLocation]);
419
- return /* @__PURE__ */ jsxRuntime.jsxs(Component, {
420
- ...props,
421
- ref: forwardedRef,
422
- children: [
423
- /* @__PURE__ */ jsxRuntime.jsxs("div", {
424
- style: {
425
- visibility: "hidden",
426
- height: 0
427
- },
428
- ref: placeholderContainerRef,
429
- children: [
430
- /* @__PURE__ */ jsxRuntime.jsx(Row, {
431
- attributes: placeholderRowAttributes,
432
- children: placeholderColumns.map((placeholder, index) => /* @__PURE__ */ jsxRuntime.jsx(Emoji, {
433
- emoji: placeholder
434
- }, index))
435
- }),
436
- /* @__PURE__ */ jsxRuntime.jsx(CategoryHeader, {
437
- category: "Category"
438
- })
439
- ]
440
- }),
441
- isLoading ? /* @__PURE__ */ jsxRuntime.jsx(Loading, {}) : error ? /* @__PURE__ */ jsxRuntime.jsx(Error, {
442
- error
443
- }) : data.count === 0 ? /* @__PURE__ */ jsxRuntime.jsx(Empty, {}) : /* @__PURE__ */ jsxRuntime.jsx(Grid, {
444
- children: /* @__PURE__ */ jsxRuntime.jsx(reactVirtuoso.GroupedVirtuoso, {
445
- ref: virtuosoRef,
446
- components: {
447
- Scroller: VirtuosoScroller,
448
- List: VirtuosoList,
449
- TopItemList: VirtuosoTopList
450
- },
451
- groupCounts: data.categoriesRowCounts,
452
- groupContent: (groupIndex) => {
453
- const category = data.categories[groupIndex];
454
- if (!category) {
455
- return null;
456
- }
457
- return /* @__PURE__ */ jsxRuntime.jsx(CategoryHeader, {
458
- category
459
- });
460
- },
461
- itemContent: (rowIndex, groupIndex) => {
462
- const categoryRow = data.rows[rowIndex];
463
- const categoryRowIndex = data.categoriesRowIndices[groupIndex]?.indexOf(rowIndex);
464
- const categoryRowsCount = data.categoriesRowCounts[groupIndex];
465
- if (categoryRow === void 0 || categoryRowIndex === void 0 || categoryRowsCount === void 0) {
466
- return null;
467
- }
468
- return /* @__PURE__ */ jsxRuntime.jsx(Row, {
469
- attributes: {
470
- rowIndex,
471
- categoryRowIndex,
472
- categoryRowsCount
473
- },
474
- children: categoryRow.map((emoji, columnIndex) => {
475
- const isSelected = interaction !== "none" && selectedColumnIndex === columnIndex && selectedRowIndex === rowIndex;
476
- return /* @__PURE__ */ jsxRuntime.jsx(Emoji, {
477
- role: "gridcell",
478
- "aria-colindex": columnIndex,
479
- "aria-selected": isSelected || void 0,
480
- "data-selected": isSelected || void 0,
481
- onMouseDown: preventDefault,
482
- tabIndex: -1,
483
- onPointerEnter: () => {
484
- setPointerSelection(columnIndex, rowIndex);
485
- },
486
- onPointerLeave: handleEmojiPointerLeave,
487
- onClick: (event) => {
488
- onEmojiSelect?.(emoji.emoji);
489
- event.stopPropagation();
490
- },
491
- emoji: emoji.emoji
492
- }, emoji.emoji);
493
- })
494
- });
495
- }
496
- })
497
- }),
498
- selectedEmoji && interaction !== "none" && /* @__PURE__ */ jsxRuntime.jsx("div", {
499
- "aria-live": "polite",
500
- style: visuallyHidden.visuallyHidden,
501
- children: selectedEmoji.name
502
- })
503
- ]
504
- });
505
- }
506
- );
507
- if (process.env.NODE_ENV !== "production") {
508
- EmojiPickerRoot.displayName = EMOJIPICKER_ROOT_NAME;
509
- EmojiPickerContent.displayName = EMOJIPICKER_CONTENT_NAME;
510
- EmojiPickerSearch.displayName = EMOJIPICKER_SEARCH_NAME;
511
- }
512
-
513
- exports.Content = EmojiPickerContent;
514
- exports.Root = EmojiPickerRoot;
515
- exports.Search = EmojiPickerSearch;
516
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","sources":["../../../src/primitives/EmojiPicker/index.tsx"],"sourcesContent":["\"use client\";\n\nimport { useLayoutEffect } from \"@liveblocks/react/_private\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport type { ChangeEvent, KeyboardEvent, SyntheticEvent } from \"react\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useTransition,\n} from \"react\";\nimport type {\n CalculateViewLocationParams,\n GroupedVirtuosoHandle,\n ListProps as VirtuosoListProps,\n ScrollerProps,\n TopItemListProps,\n} from \"react-virtuoso\";\nimport { GroupedVirtuoso } from \"react-virtuoso\";\n\nimport { isKey } from \"../../utils/is-key\";\nimport {\n cancelIdleCallback,\n requestIdleCallback,\n} from \"../../utils/request-idle-callback\";\nimport { visuallyHidden } from \"../../utils/visually-hidden\";\nimport { Emoji as EmojiPrimitive } from \"../internal/Emoji\";\nimport { EmojiPickerContext, useEmojiPicker } from \"./contexts\";\nimport type {\n EmojiData,\n EmojiPickerContentComponents,\n EmojiPickerContentEmojiRowAttributes,\n EmojiPickerContentProps,\n EmojiPickerData,\n EmojiPickerRootProps,\n EmojiPickerSearchProps,\n EmojiPickerSelectionDirection,\n} from \"./types\";\nimport { filterEmojis, generateEmojiPickerData, getEmojiData } from \"./utils\";\n\nconst DEFAULT_COLUMNS = 10;\nconst DEFAULT_LOCALE = \"en\";\nconst LOADING_MINIMUM_TIMEOUT = 100;\n\nconst EMOJIPICKER_ROOT_NAME = \"EmojiPickerRoot\";\nconst EMOJIPICKER_CONTENT_NAME = \"EmojiPickerContent\";\nconst EMOJIPICKER_SEARCH_NAME = \"EmojiPickerSearch\";\n\n/**\n * @private\n * The EmojiPicker primitive is undocumented for now and subject to change,\n * use at your own risk. If you have any feedback on it, please let us know!\n * See how we use it in the default components to learn how to use it:\n * https://github.com/liveblocks/liveblocks/blob/main/packages/liveblocks-react-ui/src/components/internal/EmojiPicker.tsx.\n *\n * Surrounds the emoji picker, it handles emoji data and coordinates\n * `EmojiPicker.Search` and `EmojiPicker.Content`.\n *\n * @example\n * <EmojiPicker.Root>\n * <EmojiPicker.Search />\n * <EmojiPicker.Content />\n * </EmojiPicker.Root>\n */\nfunction EmojiPickerRoot({\n columns = DEFAULT_COLUMNS,\n locale = DEFAULT_LOCALE,\n onEmojiSelect,\n children,\n}: EmojiPickerRootProps) {\n const emojiData = useRef<EmojiData>();\n const search = useRef(\"\");\n const [, startEmojisTransition] = useTransition();\n const [data, setData] = useState<EmojiPickerData>();\n const [error, setError] = useState<Error>();\n const [selectedColumnIndex, setSelectedColumnIndex] = useState(0);\n const [selectedRowIndex, setSelectedRowIndex] = useState(0);\n const [interaction, setInteraction] = useState<\n \"keyboard\" | \"pointer\" | \"none\"\n >(\"none\");\n\n const selectCurrentEmoji = useCallback(() => {\n if (onEmojiSelect) {\n const emoji = data?.rows[selectedRowIndex]?.[selectedColumnIndex];\n\n if (emoji) {\n onEmojiSelect(emoji.emoji);\n }\n }\n }, [data?.rows, onEmojiSelect, selectedColumnIndex, selectedRowIndex]);\n\n const resetSelection = useCallback(() => {\n setSelectedColumnIndex(0);\n setSelectedRowIndex(0);\n }, []);\n\n const setPointerSelection = useCallback(\n (columnIndex: number, rowIndex: number) => {\n setInteraction(\"pointer\");\n setSelectedColumnIndex(columnIndex);\n setSelectedRowIndex(rowIndex);\n },\n []\n );\n\n const moveSelection = useCallback(\n (\n direction: EmojiPickerSelectionDirection,\n event: KeyboardEvent<HTMLInputElement>\n ) => {\n if (!data) {\n return;\n }\n\n event.preventDefault();\n\n if (interaction === \"none\") {\n setInteraction(\"keyboard\");\n return;\n }\n\n setInteraction(\"keyboard\");\n\n switch (direction) {\n // If first column, move to last column of previous row (if available)\n // Otherwise, move to previous column\n case \"left\": {\n if (selectedColumnIndex === 0) {\n const previousRowIndex = selectedRowIndex - 1;\n const previousRow = data.rows[previousRowIndex];\n\n if (previousRow) {\n setSelectedRowIndex(previousRowIndex);\n setSelectedColumnIndex(previousRow.length - 1);\n }\n } else {\n setSelectedColumnIndex(selectedColumnIndex - 1);\n }\n\n break;\n }\n\n // If last column, move to first column of next row (if available)\n // Otherwise, move to next column\n case \"right\": {\n const currentRow = data.rows[selectedRowIndex];\n\n if (!currentRow) {\n return;\n }\n\n if (selectedColumnIndex === currentRow.length - 1) {\n const nextRowIndex = selectedRowIndex + 1;\n const nextRow = data.rows[nextRowIndex];\n\n if (nextRow) {\n setSelectedRowIndex(nextRowIndex);\n setSelectedColumnIndex(0);\n }\n } else {\n setSelectedColumnIndex(selectedColumnIndex + 1);\n }\n\n break;\n }\n\n // Move to same column of previous row\n // If same column is not available, move to last column of previous row\n case \"up\": {\n const previousRow = data.rows[selectedRowIndex - 1];\n\n if (previousRow) {\n setSelectedRowIndex(selectedRowIndex - 1);\n\n if (!previousRow[selectedColumnIndex]) {\n setSelectedColumnIndex(previousRow.length - 1);\n }\n }\n\n break;\n }\n\n // Move to same column of next row\n // If same column is not available, move to last column of next row\n case \"down\": {\n const nextRow = data.rows[selectedRowIndex + 1];\n\n if (nextRow) {\n setSelectedRowIndex(selectedRowIndex + 1);\n\n if (!nextRow[selectedColumnIndex]) {\n setSelectedColumnIndex(nextRow.length - 1);\n }\n }\n\n break;\n }\n }\n },\n [data, interaction, selectedColumnIndex, selectedRowIndex]\n );\n\n const updateEmojis = useCallback(() => {\n if (!emojiData.current) {\n return;\n }\n\n startEmojisTransition(() => {\n setData(() => {\n if (!emojiData.current) {\n return;\n }\n\n const filteredEmojis = filterEmojis(\n emojiData.current.emojis,\n search.current\n );\n\n return generateEmojiPickerData(\n filteredEmojis,\n emojiData.current.categories,\n columns\n );\n });\n resetSelection();\n });\n }, [columns, resetSelection]);\n\n const handleSearch = useCallback(\n (value: string) => {\n search.current = value;\n updateEmojis();\n },\n [updateEmojis]\n );\n\n const initializeEmojiData = useCallback(\n async (locale: string) => {\n try {\n emojiData.current = await getEmojiData(locale);\n updateEmojis();\n } catch (error) {\n setError(error as Error);\n }\n },\n [updateEmojis]\n );\n\n useEffect(() => {\n let idleCallbackId: number;\n const timeoutId = setTimeout(() => {\n idleCallbackId = requestIdleCallback(() => {\n initializeEmojiData(locale);\n });\n }, LOADING_MINIMUM_TIMEOUT);\n\n return () => {\n clearTimeout(timeoutId);\n cancelIdleCallback(idleCallbackId);\n };\n }, [locale]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n if (interaction === \"none\") {\n resetSelection();\n }\n }, [interaction]); // eslint-disable-line react-hooks/exhaustive-deps\n\n return (\n <EmojiPickerContext.Provider\n value={{\n data: data as EmojiPickerData,\n error: error as undefined,\n isLoading: (!data && !error) as false,\n columns,\n onSearch: handleSearch,\n onEmojiSelect,\n selectCurrentEmoji,\n selectedRowIndex,\n selectedColumnIndex,\n moveSelection,\n setPointerSelection,\n interaction,\n setInteraction,\n }}\n >\n {children}\n </EmojiPickerContext.Provider>\n );\n}\n\n/**\n * @private\n * The EmojiPicker primitive is undocumented for now and subject to change,\n * use at your own risk. If you have any feedback on it, please let us know!\n * See how we use it in the default components to learn how to use it:\n * https://github.com/liveblocks/liveblocks/blob/main/packages/liveblocks-react-ui/src/components/internal/EmojiPicker.tsx.\n *\n * The search input of the emoji picker. It also affects the focus and selection\n * within `EmojiPicker.Content`.\n *\n * @example\n * <EmojiPicker.Search />\n */\nconst EmojiPickerSearch = forwardRef<HTMLInputElement, EmojiPickerSearchProps>(\n ({ asChild, value, defaultValue, onChange, ...props }, forwardedRef) => {\n const Component = asChild ? Slot : \"input\";\n const {\n onSearch,\n selectCurrentEmoji,\n moveSelection,\n interaction,\n setInteraction,\n } = useEmojiPicker();\n\n const handleChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n onChange?.(event);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n const value = event.target.value;\n setInteraction(value ? \"keyboard\" : \"none\");\n onSearch(value);\n },\n [onChange, onSearch, setInteraction]\n );\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.isDefaultPrevented()) {\n return;\n }\n\n if (isKey(event, \"ArrowLeft\")) {\n moveSelection(\"left\", event);\n } else if (isKey(event, \"ArrowRight\")) {\n moveSelection(\"right\", event);\n } else if (isKey(event, \"ArrowUp\")) {\n moveSelection(\"up\", event);\n } else if (isKey(event, \"ArrowDown\")) {\n moveSelection(\"down\", event);\n } else if (isKey(event, \"Enter\")) {\n if (interaction !== \"none\") {\n event.preventDefault();\n selectCurrentEmoji();\n }\n }\n },\n [interaction, moveSelection, selectCurrentEmoji]\n );\n\n useEffect(() => {\n onSearch(\n value ? String(value) : defaultValue ? String(defaultValue) : \"\"\n );\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n return (\n <Component\n type=\"search\"\n value={value}\n defaultValue={defaultValue}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n {...props}\n ref={forwardedRef}\n />\n );\n }\n);\n\nconst defaultContentComponents: EmojiPickerContentComponents = {\n CategoryHeader: ({ category, ...props }) => <div {...props}>{category}</div>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n Row: ({ children, attributes, ...props }) => <div {...props}>{children}</div>,\n Emoji: ({ emoji, ...props }) => (\n <button {...props}>\n <EmojiPrimitive emoji={emoji} />\n </button>\n ),\n Loading: (props) => <div {...props} />,\n Empty: (props) => <div {...props} />,\n Grid: (props) => <div {...props} />,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n Error: ({ error, ...props }) => <div {...props} />,\n};\n\nconst placeholderRowAttributes: EmojiPickerContentEmojiRowAttributes = {\n rowIndex: -1,\n categoryRowIndex: -1,\n categoryRowsCount: 0,\n};\n\n// About `data-testid={undefined}`: Virtuoso bakes test IDs into the components we pass\n// to it, so we manually remove them.\n\nconst VirtuosoScroller = forwardRef<HTMLDivElement, ScrollerProps>(\n ({ children, ...props }, forwardedRef) => {\n return (\n <div {...props} tabIndex={-1} data-testid={undefined} ref={forwardedRef}>\n {children}\n </div>\n );\n }\n);\n\nconst VirtuosoTopList = forwardRef<HTMLDivElement, TopItemListProps>(\n ({ children, ...props }, forwardedRef) => {\n return (\n <div {...props} data-testid={undefined} ref={forwardedRef}>\n {children}\n </div>\n );\n }\n);\n\n/**\n * @private\n * The EmojiPicker primitive is undocumented for now and subject to change,\n * use at your own risk. If you have any feedback on it, please let us know!\n * See how we use it in the default components to learn how to use it:\n * https://github.com/liveblocks/liveblocks/blob/main/packages/liveblocks-react-ui/src/components/internal/EmojiPicker.tsx.\n *\n * The main content of the emoji picker, either displaying the emoji grid or various\n * alternative states (loading, empty, and error).\n *\n * @example\n * <EmojiPicker.Content\n * components={{\n * Loading: EmojiPickerLoading,\n * Empty: EmojiPickerEmpty,\n * Error: EmojiPickerError,\n * CategoryHeader: EmojiPickerCategoryHeader,\n * Grid: EmojiPickerGrid,\n * Row: EmojiPickerRow,\n * Emoji: EmojiPickerEmoji,\n * }}\n * />\n */\nconst EmojiPickerContent = forwardRef<HTMLDivElement, EmojiPickerContentProps>(\n ({ components, asChild, ...props }, forwardedRef) => {\n const Component = asChild ? Slot : \"div\";\n const virtuosoRef = useRef<GroupedVirtuosoHandle>(null);\n const placeholderContainerRef = useRef<HTMLDivElement>(null);\n const rowScrollMarginTopRef = useRef<number>(0);\n const rowScrollMarginBottomRef = useRef<number>(0);\n const categoryHeaderHeightRef = useRef<number>(0);\n const {\n data,\n error,\n isLoading,\n columns,\n onEmojiSelect,\n selectedColumnIndex,\n selectedRowIndex,\n setPointerSelection,\n interaction,\n setInteraction,\n } = useEmojiPicker();\n const selectedEmoji = useMemo(\n () => data?.rows[selectedRowIndex]?.[selectedColumnIndex],\n [data?.rows, selectedColumnIndex, selectedRowIndex]\n );\n const { Loading, Empty, Error, CategoryHeader, Grid, Row, Emoji } = useMemo(\n () => ({ ...defaultContentComponents, ...components }),\n [components]\n );\n const VirtuosoList = useMemo(\n () =>\n forwardRef<HTMLDivElement, VirtuosoListProps>(\n ({ children, ...props }, forwardedRef) => {\n return (\n <div\n role=\"grid\"\n aria-colcount={columns}\n {...props}\n data-testid={undefined}\n ref={forwardedRef}\n >\n {children}\n </div>\n );\n }\n ),\n [columns]\n );\n const placeholderColumns = useMemo(\n () => Array<string>(columns).fill(\"🌫️\"),\n [columns]\n );\n\n const preventDefault = useCallback((event: SyntheticEvent) => {\n event.preventDefault();\n }, []);\n\n const handleEmojiPointerLeave = useCallback(() => {\n if (interaction === \"pointer\") {\n setInteraction(\"none\");\n }\n }, [interaction, setInteraction]);\n\n useLayoutEffect(() => {\n if (!placeholderContainerRef.current) {\n return;\n }\n\n const row = placeholderContainerRef.current.childNodes[0];\n const categoryHeader = placeholderContainerRef.current.childNodes[1];\n\n if (row instanceof HTMLElement) {\n const style = window.getComputedStyle(row);\n\n rowScrollMarginTopRef.current = parseFloat(style.scrollMarginTop);\n rowScrollMarginBottomRef.current = parseFloat(style.scrollMarginBottom);\n }\n\n if (categoryHeader instanceof HTMLElement) {\n categoryHeaderHeightRef.current = categoryHeader.offsetHeight;\n }\n }, []);\n\n // Customize `scrollIntoView` behavior to take into account category headers and margins\n const calculateViewLocation = useCallback(\n ({\n itemTop,\n itemBottom,\n viewportTop,\n viewportBottom,\n locationParams: { behavior, align, ...params },\n }: CalculateViewLocationParams) => {\n if (\n itemTop -\n (categoryHeaderHeightRef.current + rowScrollMarginTopRef.current) <\n viewportTop\n ) {\n return {\n ...params,\n behavior,\n align: align ?? \"start\",\n };\n }\n\n if (itemBottom > viewportBottom) {\n return {\n ...params,\n behavior,\n align: align ?? \"end\",\n offset: rowScrollMarginBottomRef.current,\n };\n }\n\n return null;\n },\n []\n );\n\n useEffect(() => {\n if (interaction === \"keyboard\") {\n virtuosoRef.current?.scrollIntoView({\n index: selectedRowIndex,\n behavior: \"auto\",\n calculateViewLocation,\n });\n }\n }, [interaction, selectedRowIndex, calculateViewLocation]);\n\n return (\n <Component {...props} ref={forwardedRef}>\n <div\n style={{\n visibility: \"hidden\",\n height: 0,\n }}\n ref={placeholderContainerRef}\n >\n {/* Virtualized rows are absolutely positioned so they won't make\n the container automatically pick up their width. To achieve\n an automatic width, we add a relative (but hidden) full row. */}\n <Row attributes={placeholderRowAttributes}>\n {placeholderColumns.map((placeholder, index) => (\n <Emoji emoji={placeholder} key={index} />\n ))}\n </Row>\n {/* We also add a hidden category header to get its computed height. */}\n <CategoryHeader category=\"Category\" />\n </div>\n {isLoading ? (\n <Loading />\n ) : error ? (\n <Error error={error} />\n ) : data.count === 0 ? (\n <Empty />\n ) : (\n <Grid>\n <GroupedVirtuoso\n ref={virtuosoRef}\n components={{\n Scroller: VirtuosoScroller,\n List: VirtuosoList,\n TopItemList: VirtuosoTopList,\n }}\n groupCounts={data.categoriesRowCounts}\n groupContent={(groupIndex) => {\n const category = data.categories[groupIndex];\n\n if (!category) {\n return null;\n }\n\n return <CategoryHeader category={category} />;\n }}\n itemContent={(rowIndex, groupIndex) => {\n const categoryRow = data.rows[rowIndex];\n const categoryRowIndex =\n data.categoriesRowIndices[groupIndex]?.indexOf(rowIndex);\n const categoryRowsCount = data.categoriesRowCounts[groupIndex];\n\n if (\n categoryRow === undefined ||\n categoryRowIndex === undefined ||\n categoryRowsCount === undefined\n ) {\n return null;\n }\n\n return (\n <Row\n attributes={{\n rowIndex,\n categoryRowIndex,\n categoryRowsCount,\n }}\n >\n {categoryRow.map((emoji, columnIndex) => {\n const isSelected =\n interaction !== \"none\" &&\n selectedColumnIndex === columnIndex &&\n selectedRowIndex === rowIndex;\n\n return (\n <Emoji\n key={emoji.emoji}\n role=\"gridcell\"\n aria-colindex={columnIndex}\n aria-selected={isSelected || undefined}\n data-selected={isSelected || undefined}\n onMouseDown={preventDefault}\n tabIndex={-1}\n onPointerEnter={() => {\n setPointerSelection(columnIndex, rowIndex);\n }}\n onPointerLeave={handleEmojiPointerLeave}\n onClick={(event) => {\n onEmojiSelect?.(emoji.emoji);\n event.stopPropagation();\n }}\n emoji={emoji.emoji}\n />\n );\n })}\n </Row>\n );\n }}\n />\n </Grid>\n )}\n {selectedEmoji && interaction !== \"none\" && (\n <div aria-live=\"polite\" style={visuallyHidden}>\n {selectedEmoji.name}\n </div>\n )}\n </Component>\n );\n }\n);\n\nif (process.env.NODE_ENV !== \"production\") {\n EmojiPickerRoot.displayName = EMOJIPICKER_ROOT_NAME;\n EmojiPickerContent.displayName = EMOJIPICKER_CONTENT_NAME;\n EmojiPickerSearch.displayName = EMOJIPICKER_SEARCH_NAME;\n}\n\n// NOTE: Every export from this file will be available publicly as EmojiPicker.*\nexport {\n EmojiPickerContent as Content,\n EmojiPickerRoot as Root,\n EmojiPickerSearch as Search,\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA;AA2CA;AACA;AACA;AAEA;AACA;AACA;AAkBA;AAAyB;AACb;AACD;AACT;AAEF;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACE;AACE;AAEA;AACE;AAAyB;AAC3B;AACF;AAGF;AACE;AACA;AAAqB;AAGvB;AAA4B;AAExB;AACA;AACA;AAA4B;AAC9B;AACC;AAGH;AAAsB;AAKlB;AACE;AAAA;AAGF;AAEA;AACE;AACA;AAAA;AAGF;AAEA;AAAmB;AAIf;AACE;AACA;AAEA;AACE;AACA;AAA6C;AAC/C;AAEA;AAA8C;AAGhD;AAAA;AACF;AAKE;AAEA;AACE;AAAA;AAGF;AACE;AACA;AAEA;AACE;AACA;AAAwB;AAC1B;AAEA;AAA8C;AAGhD;AAAA;AACF;AAKE;AAEA;AACE;AAEA;AACE;AAA6C;AAC/C;AAGF;AAAA;AACF;AAKE;AAEA;AACE;AAEA;AACE;AAAyC;AAC3C;AAGF;AAAA;AACF;AACF;AACF;AACyD;AAG3D;AACE;AACE;AAAA;AAGF;AACE;AACE;AACE;AAAA;AAGF;AAAuB;AACH;AACX;AAGT;AAAO;AACL;AACkB;AAClB;AACF;AAEF;AAAe;AAChB;AAGH;AAAqB;AAEjB;AACA;AAAa;AACf;AACa;AAGf;AAA4B;AAExB;AACE;AACA;AAAa;AAEb;AAAuB;AACzB;AACF;AACa;AAGf;AACE;AACA;AACE;AACE;AAA0B;AAC3B;AAGH;AACE;AACA;AAAiC;AACnC;AAGF;AACE;AACE;AAAe;AACjB;AAGF;AACG;AACQ;AACL;AACA;AACsB;AACtB;AACU;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF;AAEC;AAGP;AAeA;AAA0B;AAEtB;AACA;AAAM;AACJ;AACA;AACA;AACA;AACA;AAGF;AAAqB;AAEjB;AAEA;AACE;AAAA;AAGF;AACA;AACA;AAAc;AAChB;AACmC;AAGrC;AAAsB;AAElB;AACE;AAAA;AAGF;AACE;AAA2B;AAE3B;AAA4B;AAE5B;AAAyB;AAEzB;AAA2B;AAE3B;AACE;AACA;AAAmB;AACrB;AACF;AACF;AAC+C;AAGjD;AACE;AAAA;AACgE;AAChE;AAGF;AACG;AACM;AACL;AACA;AACU;AACC;AACP;AACC;AACP;AAGN;AAEA;AAA+D;AAChB;AAAQ;AAAQ;AAAS;AAExB;AAAQ;AAAQ;AAAS;AAEpE;AAAW;AACT;AAAe;AAAc;AAChC;AAEmB;AAAQ;AAAO;AACjB;AAAQ;AAAO;AAChB;AAAQ;AAAO;AAEA;AAAQ;AAC3C;AAEA;AAAuE;AAC3D;AACQ;AAEpB;AAKA;AAAyB;AAErB;AACG;AAAQ;AAAiB;AAAiB;AAAgB;AACxD;AACH;AAGN;AAEA;AAAwB;AAEpB;AACG;AAAQ;AAAoB;AAAgB;AAC1C;AACH;AAGN;AAyBA;AAA2B;AAEvB;AACA;AACA;AACA;AACA;AACA;AACA;AAAM;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEF;AAAsB;AACiB;AACa;AAEpD;AAAoE;AACd;AACzC;AAEb;AAAqB;AAEjB;AAEI;AACG;AACM;AACU;AACX;AACS;AACR;AAEJ;AACH;AAEJ;AACF;AACM;AAEV;AAA2B;AACc;AAC/B;AAGV;AACE;AAAqB;AAGvB;AACE;AACE;AAAqB;AACvB;AAGF;AACE;AACE;AAAA;AAGF;AACA;AAEA;AACE;AAEA;AACA;AAAsE;AAGxE;AACE;AAAiD;AACnD;AAIF;AAA8B;AAC3B;AACC;AACA;AACA;AACA;AAC6C;AAE7C;AAKE;AAAO;AACF;AACH;AACgB;AAClB;AAGF;AACE;AAAO;AACF;AACH;AACgB;AACiB;AACnC;AAGF;AAAO;AACT;AACC;AAGH;AACE;AACE;AAAoC;AAC3B;AACG;AACV;AACD;AACH;AAGF;AACG;AAAc;AAAY;AACzB;AAAC;AACQ;AACO;AACJ;AACV;AACK;AAKL;AAAC;AAAgB;AAEZ;AAAa;AACf;AACH;AAEC;AAAwB;AAAW;AAAA;AACtC;AAIG;AAAM;AAIN;AACE;AACM;AACO;AACA;AACJ;AACO;AACf;AACkB;AAEhB;AAEA;AACE;AAAO;AAGT;AAAQ;AAAe;AAAoB;AAC7C;AAEE;AACA;AAEA;AAEA;AAKE;AAAO;AAGT;AACG;AACa;AACV;AACA;AACA;AACF;AAGE;AAKA;AACG;AAEM;AACU;AACc;AACA;AAChB;AACH;AAER;AAAyC;AAC3C;AACgB;AAEd;AACA;AAAsB;AACxB;AACa;AACf;AAEH;AACH;AAEJ;AACF;AACF;AAGC;AAAc;AAAgB;AACd;AACjB;AAAA;AAEJ;AAGN;AAEA;AACE;AACA;AACA;AACF;;;;"}