@liveblocks/react-ui 2.5.2 → 2.7.0-beta2
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/dist/components/Comment.js +61 -3
- package/dist/components/Comment.js.map +1 -1
- package/dist/components/Comment.mjs +62 -5
- package/dist/components/Comment.mjs.map +1 -1
- package/dist/components/Composer.js +217 -101
- package/dist/components/Composer.js.map +1 -1
- package/dist/components/Composer.mjs +220 -104
- package/dist/components/Composer.mjs.map +1 -1
- package/dist/components/InboxNotification.js +20 -4
- package/dist/components/InboxNotification.js.map +1 -1
- package/dist/components/InboxNotification.mjs +20 -4
- package/dist/components/InboxNotification.mjs.map +1 -1
- package/dist/components/Thread.js +2 -0
- package/dist/components/Thread.js.map +1 -1
- package/dist/components/Thread.mjs +2 -0
- package/dist/components/Thread.mjs.map +1 -1
- package/dist/components/internal/Attachment.js +207 -0
- package/dist/components/internal/Attachment.js.map +1 -0
- package/dist/components/internal/Attachment.mjs +205 -0
- package/dist/components/internal/Attachment.mjs.map +1 -0
- package/dist/components/internal/InboxNotificationThread.js +10 -2
- package/dist/components/internal/InboxNotificationThread.js.map +1 -1
- package/dist/components/internal/InboxNotificationThread.mjs +11 -3
- package/dist/components/internal/InboxNotificationThread.mjs.map +1 -1
- package/dist/icons/Attachment.js +15 -0
- package/dist/icons/Attachment.js.map +1 -0
- package/dist/icons/Attachment.mjs +13 -0
- package/dist/icons/Attachment.mjs.map +1 -0
- package/dist/icons/Spinner.js +3 -9
- package/dist/icons/Spinner.js.map +1 -1
- package/dist/icons/Spinner.mjs +4 -10
- package/dist/icons/Spinner.mjs.map +1 -1
- package/dist/icons/{Missing.js → Warning.js} +3 -3
- package/dist/icons/{Missing.js.map → Warning.js.map} +1 -1
- package/dist/icons/{Missing.mjs → Warning.mjs} +3 -3
- package/dist/icons/{Missing.mjs.map → Warning.mjs.map} +1 -1
- package/dist/index.d.mts +70 -4
- package/dist/index.d.ts +70 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/overrides.js +5 -0
- package/dist/overrides.js.map +1 -1
- package/dist/overrides.mjs +5 -0
- package/dist/overrides.mjs.map +1 -1
- package/dist/primitives/Composer/contexts.js +17 -3
- package/dist/primitives/Composer/contexts.js.map +1 -1
- package/dist/primitives/Composer/contexts.mjs +15 -4
- package/dist/primitives/Composer/contexts.mjs.map +1 -1
- package/dist/primitives/Composer/index.js +185 -26
- package/dist/primitives/Composer/index.js.map +1 -1
- package/dist/primitives/Composer/index.mjs +188 -31
- package/dist/primitives/Composer/index.mjs.map +1 -1
- package/dist/primitives/Composer/utils.js +224 -0
- package/dist/primitives/Composer/utils.js.map +1 -1
- package/dist/primitives/Composer/utils.mjs +222 -1
- package/dist/primitives/Composer/utils.mjs.map +1 -1
- package/dist/primitives/EmojiPicker/utils.js +2 -2
- package/dist/primitives/EmojiPicker/utils.js.map +1 -1
- package/dist/primitives/EmojiPicker/utils.mjs +1 -1
- package/dist/primitives/EmojiPicker/utils.mjs.map +1 -1
- package/dist/primitives/FileSize.js +33 -0
- package/dist/primitives/FileSize.js.map +1 -0
- package/dist/primitives/FileSize.mjs +31 -0
- package/dist/primitives/FileSize.mjs.map +1 -0
- package/dist/primitives/index.d.mts +83 -3
- package/dist/primitives/index.d.ts +83 -3
- package/dist/primitives/index.js +4 -0
- package/dist/primitives/index.js.map +1 -1
- package/dist/primitives/index.mjs +2 -0
- package/dist/primitives/index.mjs.map +1 -1
- package/dist/utils/download.js +14 -0
- package/dist/utils/download.js.map +1 -0
- package/dist/utils/download.mjs +12 -0
- package/dist/utils/download.mjs.map +1 -0
- package/dist/utils/format-file-size.js +45 -0
- package/dist/utils/format-file-size.js.map +1 -0
- package/dist/utils/format-file-size.mjs +43 -0
- package/dist/utils/format-file-size.mjs.map +1 -0
- package/dist/utils/intl.js +6 -0
- package/dist/utils/intl.js.map +1 -1
- package/dist/utils/intl.mjs +6 -1
- package/dist/utils/intl.mjs.map +1 -1
- package/dist/utils/use-initial.js +2 -1
- package/dist/utils/use-initial.js.map +1 -1
- package/dist/utils/use-initial.mjs +3 -2
- package/dist/utils/use-initial.mjs.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/version.mjs +1 -1
- package/dist/version.mjs.map +1 -1
- package/package.json +4 -4
- package/src/styles/dark/index.css +1 -0
- package/src/styles/index.css +296 -62
- package/src/styles/utils.css +44 -0
- package/styles/dark/attributes.css +1 -1
- package/styles/dark/attributes.css.map +1 -1
- package/styles/dark/media-query.css +1 -1
- package/styles/dark/media-query.css.map +1 -1
- package/styles.css +1 -1
- package/styles.css.map +1 -1
- package/dist/utils/chunk.js +0 -12
- package/dist/utils/chunk.js.map +0 -1
- package/dist/utils/chunk.mjs +0 -10
- package/dist/utils/chunk.mjs.map +0 -1
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
import { makeEventSource } from '@liveblocks/core';
|
|
2
|
+
import { useRoom } from '@liveblocks/react';
|
|
3
|
+
import { useState, useCallback, useEffect, useMemo } from 'react';
|
|
4
|
+
import { useSyncExternalStore } from 'use-sync-external-store/shim/index.js';
|
|
1
5
|
import { isComposerBodyAutoLink } from '../../slate/plugins/auto-links.mjs';
|
|
2
6
|
import { isComposerBodyCustomLink } from '../../slate/plugins/custom-links.mjs';
|
|
3
7
|
import { isComposerBodyMention } from '../../slate/plugins/mentions.mjs';
|
|
4
8
|
import { isText } from '../../slate/utils/is-text.mjs';
|
|
5
9
|
import { exists } from '../../utils/exists.mjs';
|
|
10
|
+
import { useInitial } from '../../utils/use-initial.mjs';
|
|
6
11
|
import { isCommentBodyMention, isCommentBodyLink, isCommentBodyText } from '../Comment/utils.mjs';
|
|
12
|
+
import { useComposer, useComposerAttachmentsContext } from './contexts.mjs';
|
|
7
13
|
|
|
8
14
|
function composerBodyMentionToCommentBodyMention(mention) {
|
|
9
15
|
return {
|
|
@@ -109,6 +115,221 @@ function getSideAndAlignFromPlacement(placement) {
|
|
|
109
115
|
const [side, align = "center"] = placement.split("-");
|
|
110
116
|
return [side, align];
|
|
111
117
|
}
|
|
118
|
+
function useComposerAttachmentsDropArea({
|
|
119
|
+
onDragEnter,
|
|
120
|
+
onDragLeave,
|
|
121
|
+
onDragOver,
|
|
122
|
+
onDrop,
|
|
123
|
+
ignoreLeaveEvent,
|
|
124
|
+
disabled
|
|
125
|
+
}) {
|
|
126
|
+
const { isDisabled: isComposerDisabled } = useComposer();
|
|
127
|
+
const isDisabled = isComposerDisabled || disabled;
|
|
128
|
+
const { createAttachments } = useComposerAttachmentsContext();
|
|
129
|
+
const [isDraggingOver, setDraggingOver] = useState(false);
|
|
130
|
+
const handleDragEnter = useCallback(
|
|
131
|
+
(event) => {
|
|
132
|
+
onDragEnter?.(event);
|
|
133
|
+
if (isDisabled || event.isDefaultPrevented()) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const dataTransfer = event.dataTransfer;
|
|
137
|
+
if (dataTransfer.types.includes("Files")) {
|
|
138
|
+
event.preventDefault();
|
|
139
|
+
event.stopPropagation();
|
|
140
|
+
setDraggingOver(true);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
[onDragEnter, isDisabled]
|
|
144
|
+
);
|
|
145
|
+
const handleDragLeave = useCallback(
|
|
146
|
+
(event) => {
|
|
147
|
+
onDragLeave?.(event);
|
|
148
|
+
if (isDisabled || event.isDefaultPrevented()) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (ignoreLeaveEvent?.(event)) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
event.preventDefault();
|
|
155
|
+
event.stopPropagation();
|
|
156
|
+
setDraggingOver(false);
|
|
157
|
+
},
|
|
158
|
+
[onDragLeave, ignoreLeaveEvent, isDisabled]
|
|
159
|
+
);
|
|
160
|
+
const handleDragOver = useCallback(
|
|
161
|
+
(event) => {
|
|
162
|
+
onDragOver?.(event);
|
|
163
|
+
if (isDisabled || !isDraggingOver || event.isDefaultPrevented()) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
event.preventDefault();
|
|
167
|
+
event.stopPropagation();
|
|
168
|
+
},
|
|
169
|
+
[onDragOver, isDraggingOver, isDisabled]
|
|
170
|
+
);
|
|
171
|
+
const handleDrop = useCallback(
|
|
172
|
+
(event) => {
|
|
173
|
+
onDrop?.(event);
|
|
174
|
+
if (isDisabled || event.isDefaultPrevented()) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
event.preventDefault();
|
|
178
|
+
event.stopPropagation();
|
|
179
|
+
setDraggingOver(false);
|
|
180
|
+
const files = Array.from(event.dataTransfer.items).map((item) => {
|
|
181
|
+
const entry = item.webkitGetAsEntry();
|
|
182
|
+
return entry && entry.isFile ? item.getAsFile() : null;
|
|
183
|
+
}).filter(exists);
|
|
184
|
+
createAttachments(files);
|
|
185
|
+
},
|
|
186
|
+
[onDrop, createAttachments, isDisabled]
|
|
187
|
+
);
|
|
188
|
+
return [
|
|
189
|
+
isDraggingOver,
|
|
190
|
+
{
|
|
191
|
+
onDragEnter: handleDragEnter,
|
|
192
|
+
onDragLeave: handleDragLeave,
|
|
193
|
+
onDragOver: handleDragOver,
|
|
194
|
+
onDrop: handleDrop,
|
|
195
|
+
"data-drop": isDraggingOver ? "" : void 0,
|
|
196
|
+
"data-disabled": isDisabled ? "" : void 0
|
|
197
|
+
}
|
|
198
|
+
];
|
|
199
|
+
}
|
|
200
|
+
class AttachmentTooLargeError extends Error {
|
|
201
|
+
constructor() {
|
|
202
|
+
super(...arguments);
|
|
203
|
+
this.name = "AttachmentTooLargeError";
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function createComposerAttachmentsManager(room, options) {
|
|
207
|
+
const attachments = /* @__PURE__ */ new Map();
|
|
208
|
+
const abortControllers = /* @__PURE__ */ new Map();
|
|
209
|
+
const eventSource = makeEventSource();
|
|
210
|
+
let cachedSnapshot = null;
|
|
211
|
+
function notifySubscribers() {
|
|
212
|
+
cachedSnapshot = null;
|
|
213
|
+
eventSource.notify();
|
|
214
|
+
}
|
|
215
|
+
function setAttachment(attachment) {
|
|
216
|
+
attachments.set(attachment.id, attachment);
|
|
217
|
+
notifySubscribers();
|
|
218
|
+
}
|
|
219
|
+
function addAttachment(attachment) {
|
|
220
|
+
if (attachments.has(attachment.id)) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (attachment.type === "localAttachment") {
|
|
224
|
+
if (attachment.status !== "idle") {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (attachment.file.size > options.maxFileSize) {
|
|
228
|
+
setAttachment({
|
|
229
|
+
...attachment,
|
|
230
|
+
status: "error",
|
|
231
|
+
error: new AttachmentTooLargeError("File is too large.")
|
|
232
|
+
});
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const abortController = new AbortController();
|
|
236
|
+
abortControllers.set(attachment.id, abortController);
|
|
237
|
+
setAttachment({
|
|
238
|
+
...attachment,
|
|
239
|
+
status: "uploading"
|
|
240
|
+
});
|
|
241
|
+
room.uploadAttachment(attachment, {
|
|
242
|
+
signal: abortController.signal
|
|
243
|
+
}).then(() => {
|
|
244
|
+
setAttachment({
|
|
245
|
+
...attachment,
|
|
246
|
+
status: "uploaded"
|
|
247
|
+
});
|
|
248
|
+
}).catch((error) => {
|
|
249
|
+
if (error instanceof Error && error.name !== "AbortError" && error.name !== "TimeoutError") {
|
|
250
|
+
setAttachment({
|
|
251
|
+
...attachment,
|
|
252
|
+
status: "error",
|
|
253
|
+
error
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
} else {
|
|
258
|
+
setAttachment(attachment);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function removeAttachment(attachmentId) {
|
|
262
|
+
const abortController = abortControllers.get(attachmentId);
|
|
263
|
+
abortController?.abort();
|
|
264
|
+
attachments.delete(attachmentId);
|
|
265
|
+
abortControllers.delete(attachmentId);
|
|
266
|
+
notifySubscribers();
|
|
267
|
+
}
|
|
268
|
+
function getSnapshot() {
|
|
269
|
+
if (!cachedSnapshot) {
|
|
270
|
+
cachedSnapshot = Array.from(attachments.values());
|
|
271
|
+
}
|
|
272
|
+
return cachedSnapshot;
|
|
273
|
+
}
|
|
274
|
+
function clear() {
|
|
275
|
+
abortControllers.forEach((controller) => controller.abort());
|
|
276
|
+
abortControllers.clear();
|
|
277
|
+
eventSource.clear();
|
|
278
|
+
attachments.clear();
|
|
279
|
+
notifySubscribers();
|
|
280
|
+
}
|
|
281
|
+
return {
|
|
282
|
+
addAttachment,
|
|
283
|
+
removeAttachment,
|
|
284
|
+
getSnapshot,
|
|
285
|
+
subscribe: eventSource.subscribe,
|
|
286
|
+
clear
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function preventBeforeUnloadDefault(event) {
|
|
290
|
+
event.preventDefault();
|
|
291
|
+
}
|
|
292
|
+
function useComposerAttachmentsManager(defaultAttachments, options) {
|
|
293
|
+
const room = useRoom();
|
|
294
|
+
const frozenDefaultAttachments = useInitial(defaultAttachments);
|
|
295
|
+
const attachmentsManager = useInitial(
|
|
296
|
+
() => createComposerAttachmentsManager(room, options)
|
|
297
|
+
);
|
|
298
|
+
useEffect(() => {
|
|
299
|
+
frozenDefaultAttachments.forEach((attachment) => {
|
|
300
|
+
attachmentsManager.addAttachment(attachment);
|
|
301
|
+
});
|
|
302
|
+
return () => {
|
|
303
|
+
attachmentsManager.clear();
|
|
304
|
+
};
|
|
305
|
+
}, [frozenDefaultAttachments, attachmentsManager]);
|
|
306
|
+
const attachments = useSyncExternalStore(
|
|
307
|
+
attachmentsManager.subscribe,
|
|
308
|
+
attachmentsManager.getSnapshot,
|
|
309
|
+
attachmentsManager.getSnapshot
|
|
310
|
+
);
|
|
311
|
+
const isUploadingAttachments = useMemo(() => {
|
|
312
|
+
return attachments.some(
|
|
313
|
+
(attachment) => attachment.type === "localAttachment" && attachment.status === "uploading"
|
|
314
|
+
);
|
|
315
|
+
}, [attachments]);
|
|
316
|
+
useEffect(() => {
|
|
317
|
+
if (!isUploadingAttachments) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
window.addEventListener("beforeunload", preventBeforeUnloadDefault);
|
|
321
|
+
return () => {
|
|
322
|
+
window.removeEventListener("beforeunload", preventBeforeUnloadDefault);
|
|
323
|
+
};
|
|
324
|
+
}, [isUploadingAttachments]);
|
|
325
|
+
return {
|
|
326
|
+
attachments,
|
|
327
|
+
isUploadingAttachments,
|
|
328
|
+
addAttachment: attachmentsManager.addAttachment,
|
|
329
|
+
removeAttachment: attachmentsManager.removeAttachment,
|
|
330
|
+
clearAttachments: attachmentsManager.clear
|
|
331
|
+
};
|
|
332
|
+
}
|
|
112
333
|
|
|
113
|
-
export { commentBodyLinkToComposerBodyLink, commentBodyMentionToComposerBodyMention, commentBodyToComposerBody, composerBodyAutoLinkToCommentBodyLink, composerBodyCustomLinkToCommentBodyLink, composerBodyMentionToCommentBodyMention, composerBodyToCommentBody, getPlacementFromPosition, getSideAndAlignFromPlacement };
|
|
334
|
+
export { AttachmentTooLargeError, commentBodyLinkToComposerBodyLink, commentBodyMentionToComposerBodyMention, commentBodyToComposerBody, composerBodyAutoLinkToCommentBodyLink, composerBodyCustomLinkToCommentBodyLink, composerBodyMentionToCommentBodyMention, composerBodyToCommentBody, getPlacementFromPosition, getSideAndAlignFromPlacement, useComposerAttachmentsDropArea, useComposerAttachmentsManager };
|
|
114
335
|
//# sourceMappingURL=utils.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","sources":["../../../src/primitives/Composer/utils.ts"],"sourcesContent":["import type { Placement } from \"@floating-ui/react-dom\";\nimport type {\n CommentBody,\n CommentBodyLink,\n CommentBodyMention,\n} from \"@liveblocks/core\";\n\nimport { isComposerBodyAutoLink } from \"../../slate/plugins/auto-links\";\nimport { isComposerBodyCustomLink } from \"../../slate/plugins/custom-links\";\nimport { isComposerBodyMention } from \"../../slate/plugins/mentions\";\nimport { isText } from \"../../slate/utils/is-text\";\nimport type {\n ComposerBody,\n ComposerBodyAutoLink,\n ComposerBodyCustomLink,\n ComposerBodyMention,\n ComposerBodyText,\n Direction,\n} from \"../../types\";\nimport { exists } from \"../../utils/exists\";\nimport {\n isCommentBodyLink,\n isCommentBodyMention,\n isCommentBodyText,\n} from \"../Comment/utils\";\nimport type { SuggestionsPosition } from \"./types\";\n\nexport function composerBodyMentionToCommentBodyMention(\n mention: ComposerBodyMention\n): CommentBodyMention {\n return {\n type: \"mention\",\n id: mention.id,\n };\n}\n\nexport function composerBodyAutoLinkToCommentBodyLink(\n link: ComposerBodyAutoLink\n): CommentBodyLink {\n return {\n type: \"link\",\n url: link.url,\n };\n}\n\nexport function composerBodyCustomLinkToCommentBodyLink(\n link: ComposerBodyCustomLink\n): CommentBodyLink {\n return {\n type: \"link\",\n url: link.url,\n text: link.children.map((child) => child.text).join(\"\"),\n };\n}\n\nexport function commentBodyMentionToComposerBodyMention(\n mention: CommentBodyMention\n): ComposerBodyMention {\n return {\n type: \"mention\",\n id: mention.id,\n children: [{ text: \"\" }],\n };\n}\n\nexport function commentBodyLinkToComposerBodyLink(\n link: CommentBodyLink\n): ComposerBodyAutoLink | ComposerBodyCustomLink {\n if (link.text) {\n return {\n type: \"custom-link\",\n url: link.url,\n children: [{ text: link.text }],\n };\n } else {\n return {\n type: \"auto-link\",\n url: link.url,\n children: [{ text: link.url }],\n };\n }\n}\n\nexport function composerBodyToCommentBody(body: ComposerBody): CommentBody {\n return {\n version: 1,\n content: body\n .map((block) => {\n // All root blocks are paragraphs at the moment\n if (block.type !== \"paragraph\") {\n return null;\n }\n\n const children = block.children\n .map((inline) => {\n if (isComposerBodyMention(inline)) {\n return composerBodyMentionToCommentBodyMention(inline);\n }\n\n if (isComposerBodyAutoLink(inline)) {\n return composerBodyAutoLinkToCommentBodyLink(inline);\n }\n\n if (isComposerBodyCustomLink(inline)) {\n return composerBodyCustomLinkToCommentBodyLink(inline);\n }\n\n if (isText(inline)) {\n return inline;\n }\n\n return null;\n })\n .filter(exists);\n\n return {\n ...block,\n children,\n };\n })\n .filter(exists),\n };\n}\n\nconst emptyComposerBody: ComposerBody = [];\n\nexport function commentBodyToComposerBody(body: CommentBody): ComposerBody {\n if (!body || !body?.content) {\n return emptyComposerBody;\n }\n\n return body.content\n .map((block) => {\n // All root blocks are paragraphs at the moment\n if (block.type !== \"paragraph\") {\n return null;\n }\n\n const children = block.children\n .map((inline) => {\n if (isCommentBodyMention(inline)) {\n return commentBodyMentionToComposerBodyMention(inline);\n }\n\n if (isCommentBodyLink(inline)) {\n return commentBodyLinkToComposerBodyLink(inline);\n }\n\n if (isCommentBodyText(inline)) {\n return inline as ComposerBodyText;\n }\n\n return null;\n })\n .filter(exists);\n\n return {\n ...block,\n children,\n };\n })\n .filter(exists);\n}\n\nexport function getPlacementFromPosition(\n position: SuggestionsPosition,\n direction: Direction = \"ltr\"\n): Placement {\n return `${position}-${direction === \"rtl\" ? \"end\" : \"start\"}`;\n}\n\nexport function getSideAndAlignFromPlacement(placement: Placement) {\n const [side, align = \"center\"] = placement.split(\"-\");\n\n return [side, align] as const;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.mjs","sources":["../../../src/primitives/Composer/utils.ts"],"sourcesContent":["import type { Placement } from \"@floating-ui/react-dom\";\nimport {\n type CommentAttachment,\n type CommentBody,\n type CommentBodyLink,\n type CommentBodyMention,\n type CommentMixedAttachment,\n makeEventSource,\n type OpaqueRoom,\n} from \"@liveblocks/core\";\nimport { useRoom } from \"@liveblocks/react\";\nimport type { DragEvent } from \"react\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\nimport { isComposerBodyAutoLink } from \"../../slate/plugins/auto-links\";\nimport { isComposerBodyCustomLink } from \"../../slate/plugins/custom-links\";\nimport { isComposerBodyMention } from \"../../slate/plugins/mentions\";\nimport { isText } from \"../../slate/utils/is-text\";\nimport type {\n ComposerBody,\n ComposerBodyAutoLink,\n ComposerBodyCustomLink,\n ComposerBodyMention,\n ComposerBodyText,\n Direction,\n} from \"../../types\";\nimport { exists } from \"../../utils/exists\";\nimport { useInitial } from \"../../utils/use-initial\";\nimport {\n isCommentBodyLink,\n isCommentBodyMention,\n isCommentBodyText,\n} from \"../Comment/utils\";\nimport { useComposer, useComposerAttachmentsContext } from \"./contexts\";\nimport type { SuggestionsPosition } from \"./types\";\n\nexport function composerBodyMentionToCommentBodyMention(\n mention: ComposerBodyMention\n): CommentBodyMention {\n return {\n type: \"mention\",\n id: mention.id,\n };\n}\n\nexport function composerBodyAutoLinkToCommentBodyLink(\n link: ComposerBodyAutoLink\n): CommentBodyLink {\n return {\n type: \"link\",\n url: link.url,\n };\n}\n\nexport function composerBodyCustomLinkToCommentBodyLink(\n link: ComposerBodyCustomLink\n): CommentBodyLink {\n return {\n type: \"link\",\n url: link.url,\n text: link.children.map((child) => child.text).join(\"\"),\n };\n}\n\nexport function commentBodyMentionToComposerBodyMention(\n mention: CommentBodyMention\n): ComposerBodyMention {\n return {\n type: \"mention\",\n id: mention.id,\n children: [{ text: \"\" }],\n };\n}\n\nexport function commentBodyLinkToComposerBodyLink(\n link: CommentBodyLink\n): ComposerBodyAutoLink | ComposerBodyCustomLink {\n if (link.text) {\n return {\n type: \"custom-link\",\n url: link.url,\n children: [{ text: link.text }],\n };\n } else {\n return {\n type: \"auto-link\",\n url: link.url,\n children: [{ text: link.url }],\n };\n }\n}\n\nexport function composerBodyToCommentBody(body: ComposerBody): CommentBody {\n return {\n version: 1,\n content: body\n .map((block) => {\n // All root blocks are paragraphs at the moment\n if (block.type !== \"paragraph\") {\n return null;\n }\n\n const children = block.children\n .map((inline) => {\n if (isComposerBodyMention(inline)) {\n return composerBodyMentionToCommentBodyMention(inline);\n }\n\n if (isComposerBodyAutoLink(inline)) {\n return composerBodyAutoLinkToCommentBodyLink(inline);\n }\n\n if (isComposerBodyCustomLink(inline)) {\n return composerBodyCustomLinkToCommentBodyLink(inline);\n }\n\n if (isText(inline)) {\n return inline;\n }\n\n return null;\n })\n .filter(exists);\n\n return {\n ...block,\n children,\n };\n })\n .filter(exists),\n };\n}\n\nconst emptyComposerBody: ComposerBody = [];\n\nexport function commentBodyToComposerBody(body: CommentBody): ComposerBody {\n if (!body || !body?.content) {\n return emptyComposerBody;\n }\n\n return body.content\n .map((block) => {\n // All root blocks are paragraphs at the moment\n if (block.type !== \"paragraph\") {\n return null;\n }\n\n const children = block.children\n .map((inline) => {\n if (isCommentBodyMention(inline)) {\n return commentBodyMentionToComposerBodyMention(inline);\n }\n\n if (isCommentBodyLink(inline)) {\n return commentBodyLinkToComposerBodyLink(inline);\n }\n\n if (isCommentBodyText(inline)) {\n return inline as ComposerBodyText;\n }\n\n return null;\n })\n .filter(exists);\n\n return {\n ...block,\n children,\n };\n })\n .filter(exists);\n}\n\nexport function getPlacementFromPosition(\n position: SuggestionsPosition,\n direction: Direction = \"ltr\"\n): Placement {\n return `${position}-${direction === \"rtl\" ? \"end\" : \"start\"}`;\n}\n\nexport function getSideAndAlignFromPlacement(placement: Placement) {\n const [side, align = \"center\"] = placement.split(\"-\");\n\n return [side, align] as const;\n}\n\nexport function useComposerAttachmentsDropArea<\n T extends HTMLElement = HTMLElement,\n>({\n onDragEnter,\n onDragLeave,\n onDragOver,\n onDrop,\n ignoreLeaveEvent,\n disabled,\n}: {\n onDragEnter?: (event: DragEvent<T>) => void;\n onDragLeave?: (event: DragEvent<T>) => void;\n onDragOver?: (event: DragEvent<T>) => void;\n onDrop?: (event: DragEvent<T>) => void;\n ignoreLeaveEvent?: (event: DragEvent<T>) => boolean;\n disabled?: boolean;\n}) {\n const { isDisabled: isComposerDisabled } = useComposer();\n const isDisabled = isComposerDisabled || disabled;\n const { createAttachments } = useComposerAttachmentsContext();\n const [isDraggingOver, setDraggingOver] = useState(false);\n\n const handleDragEnter = useCallback(\n (event: DragEvent<T>) => {\n onDragEnter?.(event);\n\n if (isDisabled || event.isDefaultPrevented()) {\n return;\n }\n\n const dataTransfer = event.dataTransfer;\n\n if (dataTransfer.types.includes(\"Files\")) {\n event.preventDefault();\n event.stopPropagation();\n\n setDraggingOver(true);\n }\n },\n [onDragEnter, isDisabled]\n );\n\n const handleDragLeave = useCallback(\n (event: DragEvent<T>) => {\n onDragLeave?.(event);\n\n if (isDisabled || event.isDefaultPrevented()) {\n return;\n }\n\n if (ignoreLeaveEvent?.(event)) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n setDraggingOver(false);\n },\n [onDragLeave, ignoreLeaveEvent, isDisabled]\n );\n\n const handleDragOver = useCallback(\n (event: DragEvent<T>) => {\n onDragOver?.(event);\n\n if (isDisabled || !isDraggingOver || event.isDefaultPrevented()) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n },\n [onDragOver, isDraggingOver, isDisabled]\n );\n\n const handleDrop = useCallback(\n (event: DragEvent<T>) => {\n onDrop?.(event);\n\n if (isDisabled || event.isDefaultPrevented()) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n setDraggingOver(false);\n\n const files = Array.from(event.dataTransfer.items)\n .map((item) => {\n const entry = item.webkitGetAsEntry();\n\n return entry && entry.isFile ? item.getAsFile() : null;\n })\n .filter(exists);\n\n createAttachments(files);\n },\n [onDrop, createAttachments, isDisabled]\n );\n\n return [\n isDraggingOver,\n {\n onDragEnter: handleDragEnter,\n onDragLeave: handleDragLeave,\n onDragOver: handleDragOver,\n onDrop: handleDrop,\n \"data-drop\": isDraggingOver ? \"\" : undefined,\n \"data-disabled\": isDisabled ? \"\" : undefined,\n } as const,\n ] as const;\n}\n\ninterface ComposerAttachmentsManagerOptions {\n maxFileSize: number;\n}\n\nexport class AttachmentTooLargeError extends Error {\n name = \"AttachmentTooLargeError\";\n}\n\nfunction createComposerAttachmentsManager(\n room: OpaqueRoom,\n options: ComposerAttachmentsManagerOptions\n) {\n const attachments: Map<string, CommentMixedAttachment> = new Map();\n const abortControllers: Map<string, AbortController> = new Map();\n const eventSource = makeEventSource<void>();\n let cachedSnapshot: CommentMixedAttachment[] | null = null;\n\n function notifySubscribers() {\n // Invalidate the cached snapshot\n cachedSnapshot = null;\n eventSource.notify();\n }\n\n function setAttachment(attachment: CommentMixedAttachment) {\n attachments.set(attachment.id, attachment);\n\n notifySubscribers();\n }\n\n function addAttachment(attachment: CommentMixedAttachment) {\n // The attachment already exists\n if (attachments.has(attachment.id)) {\n return;\n }\n\n if (attachment.type === \"localAttachment\") {\n if (attachment.status !== \"idle\") {\n return;\n }\n\n // The file is too large to be uploaded\n if (attachment.file.size > options.maxFileSize) {\n setAttachment({\n ...attachment,\n status: \"error\",\n error: new AttachmentTooLargeError(\"File is too large.\"),\n });\n\n return;\n }\n\n const abortController = new AbortController();\n abortControllers.set(attachment.id, abortController);\n\n setAttachment({\n ...attachment,\n status: \"uploading\",\n });\n\n // Start uploading the attachment immediately\n // TODO: Queue uploads and keep them in \"idle\" state until they actually start uploading?\n room\n .uploadAttachment(attachment, {\n signal: abortController.signal,\n })\n .then(() => {\n setAttachment({\n ...attachment,\n status: \"uploaded\",\n });\n })\n .catch((error) => {\n if (\n error instanceof Error &&\n error.name !== \"AbortError\" &&\n error.name !== \"TimeoutError\"\n ) {\n setAttachment({\n ...attachment,\n status: \"error\",\n error,\n });\n }\n });\n } else {\n // The attachment is already uploaded\n setAttachment(attachment);\n }\n }\n\n function removeAttachment(attachmentId: string) {\n const abortController = abortControllers.get(attachmentId);\n\n abortController?.abort();\n\n attachments.delete(attachmentId);\n abortControllers.delete(attachmentId);\n\n notifySubscribers();\n }\n\n function getSnapshot() {\n if (!cachedSnapshot) {\n cachedSnapshot = Array.from(attachments.values());\n }\n\n return cachedSnapshot;\n }\n\n function clear() {\n abortControllers.forEach((controller) => controller.abort());\n abortControllers.clear();\n eventSource.clear();\n attachments.clear();\n\n notifySubscribers();\n }\n\n return {\n addAttachment,\n removeAttachment,\n getSnapshot,\n subscribe: eventSource.subscribe,\n clear,\n };\n}\n\nfunction preventBeforeUnloadDefault(event: BeforeUnloadEvent) {\n event.preventDefault();\n}\n\nexport function useComposerAttachmentsManager(\n defaultAttachments: CommentAttachment[],\n options: ComposerAttachmentsManagerOptions\n) {\n const room = useRoom();\n const frozenDefaultAttachments = useInitial(defaultAttachments);\n const attachmentsManager = useInitial(() =>\n createComposerAttachmentsManager(room, options)\n );\n\n useEffect(() => {\n // Initialize default attachments\n frozenDefaultAttachments.forEach((attachment) => {\n attachmentsManager.addAttachment(attachment);\n });\n\n return () => {\n attachmentsManager.clear();\n };\n }, [frozenDefaultAttachments, attachmentsManager]);\n\n const attachments = useSyncExternalStore(\n attachmentsManager.subscribe,\n attachmentsManager.getSnapshot,\n attachmentsManager.getSnapshot\n );\n\n const isUploadingAttachments = useMemo(() => {\n return attachments.some(\n (attachment) =>\n attachment.type === \"localAttachment\" &&\n attachment.status === \"uploading\"\n );\n }, [attachments]);\n\n useEffect(() => {\n if (!isUploadingAttachments) {\n return;\n }\n\n window.addEventListener(\"beforeunload\", preventBeforeUnloadDefault);\n\n return () => {\n window.removeEventListener(\"beforeunload\", preventBeforeUnloadDefault);\n };\n }, [isUploadingAttachments]);\n\n return {\n attachments,\n isUploadingAttachments,\n addAttachment: attachmentsManager.addAttachment,\n removeAttachment: attachmentsManager.removeAttachment,\n clearAttachments: attachmentsManager.clear,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var core = require('@liveblocks/core');
|
|
3
4
|
var constants = require('../../constants.js');
|
|
4
5
|
var capitalize = require('../../utils/capitalize.js');
|
|
5
|
-
var chunk = require('../../utils/chunk.js');
|
|
6
6
|
|
|
7
7
|
const EMOJIBASE_VERSION = "15.3.0";
|
|
8
8
|
const EMOJIBASE_CDN_URL = `https://cdn.jsdelivr.net/npm/emojibase-data@${EMOJIBASE_VERSION}`;
|
|
@@ -304,7 +304,7 @@ function generateEmojiPickerData(emojis, categories, columns) {
|
|
|
304
304
|
emojis: indexedEmojis.filter((emoji) => emoji.category === category.key)
|
|
305
305
|
})).filter((category) => category.emojis.length > 0);
|
|
306
306
|
for (const category of categorizedEmojis) {
|
|
307
|
-
const categoryRows =
|
|
307
|
+
const categoryRows = core.chunk(category.emojis, columns);
|
|
308
308
|
const nextIndex = currentIndex + categoryRows.length;
|
|
309
309
|
rows.push(...categoryRows);
|
|
310
310
|
categoriesNames.push(category.name);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../src/primitives/EmojiPicker/utils.ts"],"sourcesContent":["import type {\n Emoji as EmojibaseEmoji,\n Locale as EmojibaseLocale,\n MessagesDataset as EmojibaseMessagesDataset,\n} from \"emojibase\";\n\nimport { EMOJI_FONT_FAMILY } from \"../../constants\";\nimport { capitalize } from \"../../utils/capitalize\";\nimport { chunk } from \"../../utils/chunk\";\nimport type {\n Emoji,\n EmojiCategory,\n EmojiData,\n EmojiPickerData,\n EmojiPickerRow,\n} from \"./types\";\n\nconst EMOJIBASE_VERSION = \"15.3.0\";\nconst EMOJIBASE_CDN_URL = `https://cdn.jsdelivr.net/npm/emojibase-data@${EMOJIBASE_VERSION}`;\nconst EMOJIBASE_EMOJIS_URL = (locale: EmojibaseLocale) =>\n `${EMOJIBASE_CDN_URL}/${locale}/data.json`;\nconst EMOJIBASE_MESSAGES_URL = (locale: EmojibaseLocale) =>\n `${EMOJIBASE_CDN_URL}/${locale}/messages.json`;\nconst EMOJIBASE_LOCALES: EmojibaseLocale[] = [\n \"bn\",\n \"da\",\n \"de\",\n \"en\",\n \"en-gb\",\n \"es\",\n \"es-mx\",\n \"et\",\n \"fi\",\n \"fr\",\n \"hi\",\n \"hu\",\n \"it\",\n \"ja\",\n \"ko\",\n \"lt\",\n \"ms\",\n \"nb\",\n \"nl\",\n \"pl\",\n \"pt\",\n \"ru\",\n \"sv\",\n \"th\",\n \"uk\",\n \"zh\",\n \"zh-hant\",\n];\nconst EMOJIBASE_DEFAULT_LOCALE: EmojibaseLocale = \"en\";\n\nconst CACHE_EMOJI_DATA_KEY = (locale: string) => `lb-emoji-data-${locale}`;\nconst CACHE_EMOJI_METADATA_KEY = (locale: string) =>\n `lb-emoji-metadata-${locale}`;\nconst CACHE_EMOJI_SESSION_METADATA_KEY = \"lb-emoji-metadata\";\n\nconst EMOJI_DETECTION_CANVAS_WIDTH = 20;\nconst EMOJI_DETECTION_CANVAS_HEIGHT = 25;\nconst EMOJI_DETECTION_COUNTRY_FLAG = \"🇫🇷\";\n\ntype EmojiMetadata = {\n emojisEtag: string | null;\n messagesEtag: string | null;\n};\n\ntype EmojiSessionMetadata = {\n emojiVersion: number;\n countryFlags: boolean;\n};\n\nfunction generateRangeIndices(start: number, end: number) {\n const range: number[] = [];\n\n for (let i = start; i <= end; i++) {\n range.push(i);\n }\n\n return range;\n}\n\nfunction getStorageItem<T>(storage: Storage, key: string) {\n const item = storage.getItem(key);\n\n return item ? (JSON.parse(item) as T) : null;\n}\n\nfunction setStorageItem<T>(storage: Storage, key: string, value: T) {\n storage.setItem(key, JSON.stringify(value));\n}\n\nasync function fetchEtag(url: string) {\n try {\n const response = await fetch(url, { method: \"HEAD\" });\n\n return response.headers.get(\"etag\");\n } catch (error) {\n return null;\n }\n}\n\nfunction getEmojibaseSupportedLocale(locale: string): EmojibaseLocale {\n return EMOJIBASE_LOCALES.includes(locale as EmojibaseLocale)\n ? (locale as EmojibaseLocale)\n : EMOJIBASE_DEFAULT_LOCALE;\n}\n\nasync function fetchEmojibaseData(locale: EmojibaseLocale) {\n const [{ emojis, emojisEtag }, { messages, messagesEtag }] =\n await Promise.all([\n fetch(EMOJIBASE_EMOJIS_URL(locale)).then(async (response) => {\n return {\n emojis: (await response.json()) as EmojibaseEmoji[],\n emojisEtag: response.headers.get(\"etag\"),\n };\n }),\n fetch(EMOJIBASE_MESSAGES_URL(locale)).then(async (response) => {\n return {\n messages: (await response.json()) as EmojibaseMessagesDataset,\n messagesEtag: response.headers.get(\"etag\"),\n };\n }),\n ]);\n\n return {\n emojis,\n messages,\n emojisEtag,\n messagesEtag,\n };\n}\n\nasync function fetchEmojibaseEtags(locale: EmojibaseLocale) {\n const [emojisEtag, messagesEtag] = await Promise.all([\n fetchEtag(EMOJIBASE_EMOJIS_URL(locale)),\n fetchEtag(EMOJIBASE_MESSAGES_URL(locale)),\n ]);\n\n return {\n emojisEtag,\n messagesEtag,\n };\n}\n\nasync function fetchEmojiData(locale: EmojibaseLocale): Promise<EmojiData> {\n const { emojis, emojisEtag, messages, messagesEtag } =\n await fetchEmojibaseData(locale);\n const countryFlagsSubgroup = messages.subgroups.find(\n (subgroup) => subgroup.key === \"subdivision-flag\"\n );\n\n // Filter out component/modifier category and emojis\n const filteredGroups = messages.groups.filter(\n (group) => group.key !== \"component\"\n );\n const filteredEmojis = emojis.filter((emoji) => {\n return \"group\" in emoji;\n });\n\n // Pick and compact the data\n const categories = filteredGroups.map((group) => ({\n key: group.order,\n name: capitalize(group.message),\n }));\n const skinTones = messages.skinTones.map((skinTone) => ({\n key: skinTone.key,\n name: capitalize(skinTone.message),\n }));\n const compactEmojis = filteredEmojis.map((emoji) => {\n const compactEmoji: Emoji = {\n emoji: emoji.emoji,\n category: emoji.group!,\n version: emoji.version,\n name: capitalize(emoji.label),\n tags: emoji.tags,\n };\n\n if (countryFlagsSubgroup && emoji.subgroup === countryFlagsSubgroup.order) {\n compactEmoji.countryFlag = true;\n }\n\n return compactEmoji;\n });\n\n const emojiData = {\n emojis: compactEmojis,\n categories,\n skinTones,\n };\n\n // Cache the data and metadata\n setStorageItem<EmojiData>(\n localStorage,\n CACHE_EMOJI_DATA_KEY(locale),\n emojiData\n );\n setStorageItem<EmojiMetadata>(\n localStorage,\n CACHE_EMOJI_METADATA_KEY(locale),\n {\n emojisEtag,\n messagesEtag,\n }\n );\n\n return emojiData;\n}\n\n// Adapted from https://github.com/koala-interactive/is-emoji-supported/tree/master\nfunction detectEmojiSupport(\n canvasContext: CanvasRenderingContext2D,\n emoji: string\n): boolean {\n canvasContext.clearRect(\n 0,\n 0,\n EMOJI_DETECTION_CANVAS_WIDTH * 2,\n EMOJI_DETECTION_CANVAS_HEIGHT\n );\n\n // Draw in red on the left\n canvasContext.fillStyle = \"#f00\";\n canvasContext.fillText(emoji, 0, 22);\n\n // Draw in blue on right\n canvasContext.fillStyle = \"#00f\";\n canvasContext.fillText(emoji, EMOJI_DETECTION_CANVAS_WIDTH, 22);\n\n const pixels = canvasContext.getImageData(\n 0,\n 0,\n EMOJI_DETECTION_CANVAS_WIDTH,\n EMOJI_DETECTION_CANVAS_HEIGHT\n ).data;\n const pixelCount = pixels.length;\n let i = 0;\n\n // Search for the first visible pixel\n for (; i < pixelCount && !pixels[i + 3]; i += 4);\n\n // No visible pixel\n if (i >= pixelCount) {\n return false;\n }\n\n // Emojis have an immutable color, so we check the color of the emoji in two\n // different colors, the result should be the same\n const x =\n EMOJI_DETECTION_CANVAS_WIDTH + ((i / 4) % EMOJI_DETECTION_CANVAS_WIDTH);\n const y = Math.floor(i / 4 / EMOJI_DETECTION_CANVAS_WIDTH);\n const pixel = canvasContext.getImageData(x, y, 1, 1).data;\n\n if (pixels[i] !== pixel[0] || pixels[i + 2] !== pixel[2]) {\n return false;\n }\n\n // Unsupported ZWJ sequence emojis show up as separate emojis\n if (canvasContext.measureText(emoji).width >= EMOJI_DETECTION_CANVAS_WIDTH) {\n return false;\n }\n\n return true;\n}\n\nfunction getEmojiFontFamily() {\n try {\n const element = document.createElement(\"span\");\n element.style.display = \"none\";\n element.dataset.emoji = \"\";\n\n document.body.appendChild(element);\n\n const computedFontFamily = window.getComputedStyle(element).fontFamily;\n\n document.body.removeChild(element);\n\n return computedFontFamily;\n } catch {\n return EMOJI_FONT_FAMILY;\n }\n}\n\nfunction getEmojiSessionMetadata(emojis: Emoji[]): EmojiSessionMetadata {\n const versions = new Map<number, string>();\n\n for (const emoji of emojis) {\n if (!versions.has(emoji.version)) {\n versions.set(emoji.version, emoji.emoji);\n }\n }\n\n const descendingVersions = [...versions.keys()].sort((a, b) => b - a);\n\n const canvasContext = document\n .createElement(\"canvas\")\n .getContext(\"2d\", { willReadFrequently: true });\n\n if (!canvasContext) {\n return { emojiVersion: descendingVersions[0], countryFlags: true };\n }\n\n canvasContext.font = `${Math.floor(\n EMOJI_DETECTION_CANVAS_HEIGHT / 2\n )}px ${getEmojiFontFamily()}`;\n canvasContext.textBaseline = \"top\";\n canvasContext.canvas.width = EMOJI_DETECTION_CANVAS_WIDTH * 2;\n canvasContext.canvas.height = EMOJI_DETECTION_CANVAS_HEIGHT;\n\n const supportsCountryFlags = detectEmojiSupport(\n canvasContext,\n EMOJI_DETECTION_COUNTRY_FLAG\n );\n\n for (const version of descendingVersions) {\n const emoji = versions.get(version)!;\n const isSupported = detectEmojiSupport(canvasContext, emoji);\n\n if (isSupported) {\n return {\n emojiVersion: version,\n countryFlags: supportsCountryFlags,\n };\n }\n }\n\n return {\n emojiVersion: descendingVersions[0],\n countryFlags: supportsCountryFlags,\n };\n}\n\nexport async function getEmojiData(locale: string): Promise<EmojiData> {\n const emojibaseLocale = getEmojibaseSupportedLocale(locale);\n\n const sessionMetadata = getStorageItem<EmojiSessionMetadata>(\n sessionStorage,\n CACHE_EMOJI_SESSION_METADATA_KEY\n );\n const cachedData = getStorageItem<EmojiData>(\n localStorage,\n CACHE_EMOJI_DATA_KEY(emojibaseLocale)\n );\n let data: EmojiData;\n\n // If there is data already cached, check if the ETags are the same.\n // If they are, return the cached data, otherwise fetch it again.\n if (cachedData) {\n // ETags only need to be checked once per session\n if (sessionMetadata) {\n data = cachedData;\n } else {\n const { emojisEtag, messagesEtag } =\n await fetchEmojibaseEtags(emojibaseLocale);\n const cachedMetadata = getStorageItem<EmojiMetadata>(\n localStorage,\n CACHE_EMOJI_METADATA_KEY(emojibaseLocale)\n );\n\n if (\n cachedMetadata &&\n emojisEtag === cachedMetadata.emojisEtag &&\n messagesEtag === cachedMetadata.messagesEtag\n ) {\n data = cachedData;\n } else {\n data = await fetchEmojiData(emojibaseLocale);\n }\n }\n } else {\n data = await fetchEmojiData(emojibaseLocale);\n }\n\n const newSessionMetadata =\n sessionMetadata ?? getEmojiSessionMetadata(data.emojis);\n setStorageItem(\n sessionStorage,\n CACHE_EMOJI_SESSION_METADATA_KEY,\n newSessionMetadata\n );\n\n // Filter out unsupported emojis\n const filteredEmojis = data.emojis.filter((emoji) => {\n const isSupportedVersion = emoji.version <= newSessionMetadata.emojiVersion;\n\n return emoji.countryFlag\n ? isSupportedVersion && newSessionMetadata.countryFlags\n : isSupportedVersion;\n });\n\n return {\n emojis: filteredEmojis,\n categories: data.categories,\n skinTones: data.skinTones,\n };\n}\n\nexport function filterEmojis(emojis: Emoji[], search?: string) {\n if (!search) {\n return emojis;\n }\n\n const searchText = search.toLowerCase().trim();\n\n return emojis.filter(\n (emoji) =>\n emoji.name.toLowerCase().includes(searchText) ||\n emoji.tags?.some((tag) => tag.toLowerCase().includes(searchText))\n );\n}\n\nexport function generateEmojiPickerData(\n emojis: Emoji[],\n categories: EmojiCategory[],\n columns: number\n): EmojiPickerData {\n let currentIndex = 0;\n const rows: EmojiPickerRow[] = [];\n const indexedEmojis = emojis.map((emoji, index) => ({ ...emoji, index }));\n const categoriesRowCounts: number[] = [];\n const categoriesRowIndices: number[][] = [];\n const categoriesNames: string[] = [];\n const categorizedEmojis = categories\n .map((category) => ({\n ...category,\n emojis: indexedEmojis.filter((emoji) => emoji.category === category.key),\n }))\n .filter((category) => category.emojis.length > 0);\n\n for (const category of categorizedEmojis) {\n const categoryRows = chunk(category.emojis, columns);\n const nextIndex = currentIndex + categoryRows.length;\n\n rows.push(...categoryRows);\n categoriesNames.push(category.name);\n categoriesRowCounts.push(categoryRows.length);\n categoriesRowIndices.push(\n generateRangeIndices(currentIndex, nextIndex - 1)\n );\n currentIndex = nextIndex;\n }\n\n return {\n count: emojis.length,\n rows,\n categories: categoriesNames,\n categoriesRowCounts,\n categoriesRowIndices,\n };\n}\n"],"names":["capitalize","EMOJI_FONT_FAMILY","chunk"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../src/primitives/EmojiPicker/utils.ts"],"sourcesContent":["import { chunk } from \"@liveblocks/core\";\nimport type {\n Emoji as EmojibaseEmoji,\n Locale as EmojibaseLocale,\n MessagesDataset as EmojibaseMessagesDataset,\n} from \"emojibase\";\n\nimport { EMOJI_FONT_FAMILY } from \"../../constants\";\nimport { capitalize } from \"../../utils/capitalize\";\nimport type {\n Emoji,\n EmojiCategory,\n EmojiData,\n EmojiPickerData,\n EmojiPickerRow,\n} from \"./types\";\n\nconst EMOJIBASE_VERSION = \"15.3.0\";\nconst EMOJIBASE_CDN_URL = `https://cdn.jsdelivr.net/npm/emojibase-data@${EMOJIBASE_VERSION}`;\nconst EMOJIBASE_EMOJIS_URL = (locale: EmojibaseLocale) =>\n `${EMOJIBASE_CDN_URL}/${locale}/data.json`;\nconst EMOJIBASE_MESSAGES_URL = (locale: EmojibaseLocale) =>\n `${EMOJIBASE_CDN_URL}/${locale}/messages.json`;\nconst EMOJIBASE_LOCALES: EmojibaseLocale[] = [\n \"bn\",\n \"da\",\n \"de\",\n \"en\",\n \"en-gb\",\n \"es\",\n \"es-mx\",\n \"et\",\n \"fi\",\n \"fr\",\n \"hi\",\n \"hu\",\n \"it\",\n \"ja\",\n \"ko\",\n \"lt\",\n \"ms\",\n \"nb\",\n \"nl\",\n \"pl\",\n \"pt\",\n \"ru\",\n \"sv\",\n \"th\",\n \"uk\",\n \"zh\",\n \"zh-hant\",\n];\nconst EMOJIBASE_DEFAULT_LOCALE: EmojibaseLocale = \"en\";\n\nconst CACHE_EMOJI_DATA_KEY = (locale: string) => `lb-emoji-data-${locale}`;\nconst CACHE_EMOJI_METADATA_KEY = (locale: string) =>\n `lb-emoji-metadata-${locale}`;\nconst CACHE_EMOJI_SESSION_METADATA_KEY = \"lb-emoji-metadata\";\n\nconst EMOJI_DETECTION_CANVAS_WIDTH = 20;\nconst EMOJI_DETECTION_CANVAS_HEIGHT = 25;\nconst EMOJI_DETECTION_COUNTRY_FLAG = \"🇫🇷\";\n\ntype EmojiMetadata = {\n emojisEtag: string | null;\n messagesEtag: string | null;\n};\n\ntype EmojiSessionMetadata = {\n emojiVersion: number;\n countryFlags: boolean;\n};\n\nfunction generateRangeIndices(start: number, end: number) {\n const range: number[] = [];\n\n for (let i = start; i <= end; i++) {\n range.push(i);\n }\n\n return range;\n}\n\nfunction getStorageItem<T>(storage: Storage, key: string) {\n const item = storage.getItem(key);\n\n return item ? (JSON.parse(item) as T) : null;\n}\n\nfunction setStorageItem<T>(storage: Storage, key: string, value: T) {\n storage.setItem(key, JSON.stringify(value));\n}\n\nasync function fetchEtag(url: string) {\n try {\n const response = await fetch(url, { method: \"HEAD\" });\n\n return response.headers.get(\"etag\");\n } catch (error) {\n return null;\n }\n}\n\nfunction getEmojibaseSupportedLocale(locale: string): EmojibaseLocale {\n return EMOJIBASE_LOCALES.includes(locale as EmojibaseLocale)\n ? (locale as EmojibaseLocale)\n : EMOJIBASE_DEFAULT_LOCALE;\n}\n\nasync function fetchEmojibaseData(locale: EmojibaseLocale) {\n const [{ emojis, emojisEtag }, { messages, messagesEtag }] =\n await Promise.all([\n fetch(EMOJIBASE_EMOJIS_URL(locale)).then(async (response) => {\n return {\n emojis: (await response.json()) as EmojibaseEmoji[],\n emojisEtag: response.headers.get(\"etag\"),\n };\n }),\n fetch(EMOJIBASE_MESSAGES_URL(locale)).then(async (response) => {\n return {\n messages: (await response.json()) as EmojibaseMessagesDataset,\n messagesEtag: response.headers.get(\"etag\"),\n };\n }),\n ]);\n\n return {\n emojis,\n messages,\n emojisEtag,\n messagesEtag,\n };\n}\n\nasync function fetchEmojibaseEtags(locale: EmojibaseLocale) {\n const [emojisEtag, messagesEtag] = await Promise.all([\n fetchEtag(EMOJIBASE_EMOJIS_URL(locale)),\n fetchEtag(EMOJIBASE_MESSAGES_URL(locale)),\n ]);\n\n return {\n emojisEtag,\n messagesEtag,\n };\n}\n\nasync function fetchEmojiData(locale: EmojibaseLocale): Promise<EmojiData> {\n const { emojis, emojisEtag, messages, messagesEtag } =\n await fetchEmojibaseData(locale);\n const countryFlagsSubgroup = messages.subgroups.find(\n (subgroup) => subgroup.key === \"subdivision-flag\"\n );\n\n // Filter out component/modifier category and emojis\n const filteredGroups = messages.groups.filter(\n (group) => group.key !== \"component\"\n );\n const filteredEmojis = emojis.filter((emoji) => {\n return \"group\" in emoji;\n });\n\n // Pick and compact the data\n const categories = filteredGroups.map((group) => ({\n key: group.order,\n name: capitalize(group.message),\n }));\n const skinTones = messages.skinTones.map((skinTone) => ({\n key: skinTone.key,\n name: capitalize(skinTone.message),\n }));\n const compactEmojis = filteredEmojis.map((emoji) => {\n const compactEmoji: Emoji = {\n emoji: emoji.emoji,\n category: emoji.group!,\n version: emoji.version,\n name: capitalize(emoji.label),\n tags: emoji.tags,\n };\n\n if (countryFlagsSubgroup && emoji.subgroup === countryFlagsSubgroup.order) {\n compactEmoji.countryFlag = true;\n }\n\n return compactEmoji;\n });\n\n const emojiData = {\n emojis: compactEmojis,\n categories,\n skinTones,\n };\n\n // Cache the data and metadata\n setStorageItem<EmojiData>(\n localStorage,\n CACHE_EMOJI_DATA_KEY(locale),\n emojiData\n );\n setStorageItem<EmojiMetadata>(\n localStorage,\n CACHE_EMOJI_METADATA_KEY(locale),\n {\n emojisEtag,\n messagesEtag,\n }\n );\n\n return emojiData;\n}\n\n// Adapted from https://github.com/koala-interactive/is-emoji-supported/tree/master\nfunction detectEmojiSupport(\n canvasContext: CanvasRenderingContext2D,\n emoji: string\n): boolean {\n canvasContext.clearRect(\n 0,\n 0,\n EMOJI_DETECTION_CANVAS_WIDTH * 2,\n EMOJI_DETECTION_CANVAS_HEIGHT\n );\n\n // Draw in red on the left\n canvasContext.fillStyle = \"#f00\";\n canvasContext.fillText(emoji, 0, 22);\n\n // Draw in blue on right\n canvasContext.fillStyle = \"#00f\";\n canvasContext.fillText(emoji, EMOJI_DETECTION_CANVAS_WIDTH, 22);\n\n const pixels = canvasContext.getImageData(\n 0,\n 0,\n EMOJI_DETECTION_CANVAS_WIDTH,\n EMOJI_DETECTION_CANVAS_HEIGHT\n ).data;\n const pixelCount = pixels.length;\n let i = 0;\n\n // Search for the first visible pixel\n for (; i < pixelCount && !pixels[i + 3]; i += 4);\n\n // No visible pixel\n if (i >= pixelCount) {\n return false;\n }\n\n // Emojis have an immutable color, so we check the color of the emoji in two\n // different colors, the result should be the same\n const x =\n EMOJI_DETECTION_CANVAS_WIDTH + ((i / 4) % EMOJI_DETECTION_CANVAS_WIDTH);\n const y = Math.floor(i / 4 / EMOJI_DETECTION_CANVAS_WIDTH);\n const pixel = canvasContext.getImageData(x, y, 1, 1).data;\n\n if (pixels[i] !== pixel[0] || pixels[i + 2] !== pixel[2]) {\n return false;\n }\n\n // Unsupported ZWJ sequence emojis show up as separate emojis\n if (canvasContext.measureText(emoji).width >= EMOJI_DETECTION_CANVAS_WIDTH) {\n return false;\n }\n\n return true;\n}\n\nfunction getEmojiFontFamily() {\n try {\n const element = document.createElement(\"span\");\n element.style.display = \"none\";\n element.dataset.emoji = \"\";\n\n document.body.appendChild(element);\n\n const computedFontFamily = window.getComputedStyle(element).fontFamily;\n\n document.body.removeChild(element);\n\n return computedFontFamily;\n } catch {\n return EMOJI_FONT_FAMILY;\n }\n}\n\nfunction getEmojiSessionMetadata(emojis: Emoji[]): EmojiSessionMetadata {\n const versions = new Map<number, string>();\n\n for (const emoji of emojis) {\n if (!versions.has(emoji.version)) {\n versions.set(emoji.version, emoji.emoji);\n }\n }\n\n const descendingVersions = [...versions.keys()].sort((a, b) => b - a);\n\n const canvasContext = document\n .createElement(\"canvas\")\n .getContext(\"2d\", { willReadFrequently: true });\n\n if (!canvasContext) {\n return { emojiVersion: descendingVersions[0], countryFlags: true };\n }\n\n canvasContext.font = `${Math.floor(\n EMOJI_DETECTION_CANVAS_HEIGHT / 2\n )}px ${getEmojiFontFamily()}`;\n canvasContext.textBaseline = \"top\";\n canvasContext.canvas.width = EMOJI_DETECTION_CANVAS_WIDTH * 2;\n canvasContext.canvas.height = EMOJI_DETECTION_CANVAS_HEIGHT;\n\n const supportsCountryFlags = detectEmojiSupport(\n canvasContext,\n EMOJI_DETECTION_COUNTRY_FLAG\n );\n\n for (const version of descendingVersions) {\n const emoji = versions.get(version)!;\n const isSupported = detectEmojiSupport(canvasContext, emoji);\n\n if (isSupported) {\n return {\n emojiVersion: version,\n countryFlags: supportsCountryFlags,\n };\n }\n }\n\n return {\n emojiVersion: descendingVersions[0],\n countryFlags: supportsCountryFlags,\n };\n}\n\nexport async function getEmojiData(locale: string): Promise<EmojiData> {\n const emojibaseLocale = getEmojibaseSupportedLocale(locale);\n\n const sessionMetadata = getStorageItem<EmojiSessionMetadata>(\n sessionStorage,\n CACHE_EMOJI_SESSION_METADATA_KEY\n );\n const cachedData = getStorageItem<EmojiData>(\n localStorage,\n CACHE_EMOJI_DATA_KEY(emojibaseLocale)\n );\n let data: EmojiData;\n\n // If there is data already cached, check if the ETags are the same.\n // If they are, return the cached data, otherwise fetch it again.\n if (cachedData) {\n // ETags only need to be checked once per session\n if (sessionMetadata) {\n data = cachedData;\n } else {\n const { emojisEtag, messagesEtag } =\n await fetchEmojibaseEtags(emojibaseLocale);\n const cachedMetadata = getStorageItem<EmojiMetadata>(\n localStorage,\n CACHE_EMOJI_METADATA_KEY(emojibaseLocale)\n );\n\n if (\n cachedMetadata &&\n emojisEtag === cachedMetadata.emojisEtag &&\n messagesEtag === cachedMetadata.messagesEtag\n ) {\n data = cachedData;\n } else {\n data = await fetchEmojiData(emojibaseLocale);\n }\n }\n } else {\n data = await fetchEmojiData(emojibaseLocale);\n }\n\n const newSessionMetadata =\n sessionMetadata ?? getEmojiSessionMetadata(data.emojis);\n setStorageItem(\n sessionStorage,\n CACHE_EMOJI_SESSION_METADATA_KEY,\n newSessionMetadata\n );\n\n // Filter out unsupported emojis\n const filteredEmojis = data.emojis.filter((emoji) => {\n const isSupportedVersion = emoji.version <= newSessionMetadata.emojiVersion;\n\n return emoji.countryFlag\n ? isSupportedVersion && newSessionMetadata.countryFlags\n : isSupportedVersion;\n });\n\n return {\n emojis: filteredEmojis,\n categories: data.categories,\n skinTones: data.skinTones,\n };\n}\n\nexport function filterEmojis(emojis: Emoji[], search?: string) {\n if (!search) {\n return emojis;\n }\n\n const searchText = search.toLowerCase().trim();\n\n return emojis.filter(\n (emoji) =>\n emoji.name.toLowerCase().includes(searchText) ||\n emoji.tags?.some((tag) => tag.toLowerCase().includes(searchText))\n );\n}\n\nexport function generateEmojiPickerData(\n emojis: Emoji[],\n categories: EmojiCategory[],\n columns: number\n): EmojiPickerData {\n let currentIndex = 0;\n const rows: EmojiPickerRow[] = [];\n const indexedEmojis = emojis.map((emoji, index) => ({ ...emoji, index }));\n const categoriesRowCounts: number[] = [];\n const categoriesRowIndices: number[][] = [];\n const categoriesNames: string[] = [];\n const categorizedEmojis = categories\n .map((category) => ({\n ...category,\n emojis: indexedEmojis.filter((emoji) => emoji.category === category.key),\n }))\n .filter((category) => category.emojis.length > 0);\n\n for (const category of categorizedEmojis) {\n const categoryRows = chunk(category.emojis, columns);\n const nextIndex = currentIndex + categoryRows.length;\n\n rows.push(...categoryRows);\n categoriesNames.push(category.name);\n categoriesRowCounts.push(categoryRows.length);\n categoriesRowIndices.push(\n generateRangeIndices(currentIndex, nextIndex - 1)\n );\n currentIndex = nextIndex;\n }\n\n return {\n count: emojis.length,\n rows,\n categories: categoriesNames,\n categoriesRowCounts,\n categoriesRowIndices,\n };\n}\n"],"names":["capitalize","EMOJI_FONT_FAMILY","chunk"],"mappings":";;;;;;AAiBA,MAAM,iBAAoB,GAAA,QAAA,CAAA;AAC1B,MAAM,oBAAoB,CAA+C,4CAAA,EAAA,iBAAA,CAAA,CAAA,CAAA;AACzE,MAAM,oBAAuB,GAAA,CAAC,MAC5B,KAAA,CAAA,EAAG,iBAAqB,CAAA,CAAA,EAAA,MAAA,CAAA,UAAA,CAAA,CAAA;AAC1B,MAAM,sBAAyB,GAAA,CAAC,MAC9B,KAAA,CAAA,EAAG,iBAAqB,CAAA,CAAA,EAAA,MAAA,CAAA,cAAA,CAAA,CAAA;AAC1B,MAAM,iBAAuC,GAAA;AAAA,EAC3C,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,OAAA;AAAA,EACA,IAAA;AAAA,EACA,OAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,SAAA;AACF,CAAA,CAAA;AACA,MAAM,wBAA4C,GAAA,IAAA,CAAA;AAElD,MAAM,oBAAA,GAAuB,CAAC,MAAA,KAAmB,CAAiB,cAAA,EAAA,MAAA,CAAA,CAAA,CAAA;AAClE,MAAM,wBAAA,GAA2B,CAAC,MAAA,KAChC,CAAqB,kBAAA,EAAA,MAAA,CAAA,CAAA,CAAA;AACvB,MAAM,gCAAmC,GAAA,mBAAA,CAAA;AAEzC,MAAM,4BAA+B,GAAA,EAAA,CAAA;AACrC,MAAM,6BAAgC,GAAA,EAAA,CAAA;AACtC,MAAM,4BAA+B,GAAA,oBAAA,CAAA;AAYrC,SAAS,oBAAA,CAAqB,OAAe,GAAa,EAAA;AACxD,EAAA,MAAM,QAAkB,EAAC,CAAA;AAEzB,EAAA,KAAA,IAAS,CAAI,GAAA,KAAA,EAAO,CAAK,IAAA,GAAA,EAAK,CAAK,EAAA,EAAA;AACjC,IAAA,KAAA,CAAM,KAAK,CAAC,CAAA,CAAA;AAAA,GACd;AAEA,EAAO,OAAA,KAAA,CAAA;AACT,CAAA;AAEA,SAAS,cAAA,CAAkB,SAAkB,GAAa,EAAA;AACxD,EAAM,MAAA,IAAA,GAAO,OAAQ,CAAA,OAAA,CAAQ,GAAG,CAAA,CAAA;AAEhC,EAAA,OAAO,IAAQ,GAAA,IAAA,CAAK,KAAM,CAAA,IAAI,CAAU,GAAA,IAAA,CAAA;AAC1C,CAAA;AAEA,SAAS,cAAA,CAAkB,OAAkB,EAAA,GAAA,EAAa,KAAU,EAAA;AAClE,EAAA,OAAA,CAAQ,OAAQ,CAAA,GAAA,EAAK,IAAK,CAAA,SAAA,CAAU,KAAK,CAAC,CAAA,CAAA;AAC5C,CAAA;AAEA,eAAe,UAAU,GAAa,EAAA;AACpC,EAAI,IAAA;AACF,IAAA,MAAM,WAAW,MAAM,KAAA,CAAM,KAAK,EAAE,MAAA,EAAQ,QAAQ,CAAA,CAAA;AAEpD,IAAO,OAAA,QAAA,CAAS,OAAQ,CAAA,GAAA,CAAI,MAAM,CAAA,CAAA;AAAA,WAC3B,KAAP,EAAA;AACA,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AACF,CAAA;AAEA,SAAS,4BAA4B,MAAiC,EAAA;AACpE,EAAA,OAAO,iBAAkB,CAAA,QAAA,CAAS,MAAyB,CAAA,GACtD,MACD,GAAA,wBAAA,CAAA;AACN,CAAA;AAEA,eAAe,mBAAmB,MAAyB,EAAA;AACzD,EAAA,MAAM,CAAC,EAAE,MAAQ,EAAA,UAAA,EAAc,EAAA,EAAE,QAAU,EAAA,YAAA,EAAc,CAAA,GACvD,MAAM,OAAA,CAAQ,GAAI,CAAA;AAAA,IAChB,MAAM,oBAAqB,CAAA,MAAM,CAAC,CAAE,CAAA,IAAA,CAAK,OAAO,QAAa,KAAA;AAC3D,MAAO,OAAA;AAAA,QACL,MAAA,EAAS,MAAM,QAAA,CAAS,IAAK,EAAA;AAAA,QAC7B,UAAY,EAAA,QAAA,CAAS,OAAQ,CAAA,GAAA,CAAI,MAAM,CAAA;AAAA,OACzC,CAAA;AAAA,KACD,CAAA;AAAA,IACD,MAAM,sBAAuB,CAAA,MAAM,CAAC,CAAE,CAAA,IAAA,CAAK,OAAO,QAAa,KAAA;AAC7D,MAAO,OAAA;AAAA,QACL,QAAA,EAAW,MAAM,QAAA,CAAS,IAAK,EAAA;AAAA,QAC/B,YAAc,EAAA,QAAA,CAAS,OAAQ,CAAA,GAAA,CAAI,MAAM,CAAA;AAAA,OAC3C,CAAA;AAAA,KACD,CAAA;AAAA,GACF,CAAA,CAAA;AAEH,EAAO,OAAA;AAAA,IACL,MAAA;AAAA,IACA,QAAA;AAAA,IACA,UAAA;AAAA,IACA,YAAA;AAAA,GACF,CAAA;AACF,CAAA;AAEA,eAAe,oBAAoB,MAAyB,EAAA;AAC1D,EAAA,MAAM,CAAC,UAAY,EAAA,YAAY,CAAI,GAAA,MAAM,QAAQ,GAAI,CAAA;AAAA,IACnD,SAAA,CAAU,oBAAqB,CAAA,MAAM,CAAC,CAAA;AAAA,IACtC,SAAA,CAAU,sBAAuB,CAAA,MAAM,CAAC,CAAA;AAAA,GACzC,CAAA,CAAA;AAED,EAAO,OAAA;AAAA,IACL,UAAA;AAAA,IACA,YAAA;AAAA,GACF,CAAA;AACF,CAAA;AAEA,eAAe,eAAe,MAA6C,EAAA;AACzE,EAAM,MAAA,EAAE,QAAQ,UAAY,EAAA,QAAA,EAAU,cACpC,GAAA,MAAM,mBAAmB,MAAM,CAAA,CAAA;AACjC,EAAM,MAAA,oBAAA,GAAuB,SAAS,SAAU,CAAA,IAAA;AAAA,IAC9C,CAAC,QAAa,KAAA,QAAA,CAAS,GAAQ,KAAA,kBAAA;AAAA,GACjC,CAAA;AAGA,EAAM,MAAA,cAAA,GAAiB,SAAS,MAAO,CAAA,MAAA;AAAA,IACrC,CAAC,KAAU,KAAA,KAAA,CAAM,GAAQ,KAAA,WAAA;AAAA,GAC3B,CAAA;AACA,EAAA,MAAM,cAAiB,GAAA,MAAA,CAAO,MAAO,CAAA,CAAC,KAAU,KAAA;AAC9C,IAAA,OAAO,OAAW,IAAA,KAAA,CAAA;AAAA,GACnB,CAAA,CAAA;AAGD,EAAA,MAAM,UAAa,GAAA,cAAA,CAAe,GAAI,CAAA,CAAC,KAAW,MAAA;AAAA,IAChD,KAAK,KAAM,CAAA,KAAA;AAAA,IACX,IAAA,EAAMA,qBAAW,CAAA,KAAA,CAAM,OAAO,CAAA;AAAA,GAC9B,CAAA,CAAA,CAAA;AACF,EAAA,MAAM,SAAY,GAAA,QAAA,CAAS,SAAU,CAAA,GAAA,CAAI,CAAC,QAAc,MAAA;AAAA,IACtD,KAAK,QAAS,CAAA,GAAA;AAAA,IACd,IAAA,EAAMA,qBAAW,CAAA,QAAA,CAAS,OAAO,CAAA;AAAA,GACjC,CAAA,CAAA,CAAA;AACF,EAAA,MAAM,aAAgB,GAAA,cAAA,CAAe,GAAI,CAAA,CAAC,KAAU,KAAA;AAClD,IAAA,MAAM,YAAsB,GAAA;AAAA,MAC1B,OAAO,KAAM,CAAA,KAAA;AAAA,MACb,UAAU,KAAM,CAAA,KAAA;AAAA,MAChB,SAAS,KAAM,CAAA,OAAA;AAAA,MACf,IAAA,EAAMA,qBAAW,CAAA,KAAA,CAAM,KAAK,CAAA;AAAA,MAC5B,MAAM,KAAM,CAAA,IAAA;AAAA,KACd,CAAA;AAEA,IAAA,IAAI,oBAAwB,IAAA,KAAA,CAAM,QAAa,KAAA,oBAAA,CAAqB,KAAO,EAAA;AACzE,MAAA,YAAA,CAAa,WAAc,GAAA,IAAA,CAAA;AAAA,KAC7B;AAEA,IAAO,OAAA,YAAA,CAAA;AAAA,GACR,CAAA,CAAA;AAED,EAAA,MAAM,SAAY,GAAA;AAAA,IAChB,MAAQ,EAAA,aAAA;AAAA,IACR,UAAA;AAAA,IACA,SAAA;AAAA,GACF,CAAA;AAGA,EAAA,cAAA;AAAA,IACE,YAAA;AAAA,IACA,qBAAqB,MAAM,CAAA;AAAA,IAC3B,SAAA;AAAA,GACF,CAAA;AACA,EAAA,cAAA;AAAA,IACE,YAAA;AAAA,IACA,yBAAyB,MAAM,CAAA;AAAA,IAC/B;AAAA,MACE,UAAA;AAAA,MACA,YAAA;AAAA,KACF;AAAA,GACF,CAAA;AAEA,EAAO,OAAA,SAAA,CAAA;AACT,CAAA;AAGA,SAAS,kBAAA,CACP,eACA,KACS,EAAA;AACT,EAAc,aAAA,CAAA,SAAA;AAAA,IACZ,CAAA;AAAA,IACA,CAAA;AAAA,IACA,4BAA+B,GAAA,CAAA;AAAA,IAC/B,6BAAA;AAAA,GACF,CAAA;AAGA,EAAA,aAAA,CAAc,SAAY,GAAA,MAAA,CAAA;AAC1B,EAAc,aAAA,CAAA,QAAA,CAAS,KAAO,EAAA,CAAA,EAAG,EAAE,CAAA,CAAA;AAGnC,EAAA,aAAA,CAAc,SAAY,GAAA,MAAA,CAAA;AAC1B,EAAc,aAAA,CAAA,QAAA,CAAS,KAAO,EAAA,4BAAA,EAA8B,EAAE,CAAA,CAAA;AAE9D,EAAA,MAAM,SAAS,aAAc,CAAA,YAAA;AAAA,IAC3B,CAAA;AAAA,IACA,CAAA;AAAA,IACA,4BAAA;AAAA,IACA,6BAAA;AAAA,GACA,CAAA,IAAA,CAAA;AACF,EAAA,MAAM,aAAa,MAAO,CAAA,MAAA,CAAA;AAC1B,EAAA,IAAI,CAAI,GAAA,CAAA,CAAA;AAGR,EAAA,OAAO,IAAI,UAAc,IAAA,CAAC,MAAO,CAAA,CAAA,GAAI,IAAI,CAAK,IAAA,CAAA;AAAE,IAAA,CAAA;AAGhD,EAAA,IAAI,KAAK,UAAY,EAAA;AACnB,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAIA,EAAM,MAAA,CAAA,GACJ,4BAAiC,GAAA,CAAA,GAAI,CAAK,GAAA,4BAAA,CAAA;AAC5C,EAAA,MAAM,CAAI,GAAA,IAAA,CAAK,KAAM,CAAA,CAAA,GAAI,IAAI,4BAA4B,CAAA,CAAA;AACzD,EAAA,MAAM,QAAQ,aAAc,CAAA,YAAA,CAAa,GAAG,CAAG,EAAA,CAAA,EAAG,CAAC,CAAE,CAAA,IAAA,CAAA;AAErD,EAAI,IAAA,MAAA,CAAO,OAAO,KAAM,CAAA,CAAA,CAAA,IAAM,OAAO,CAAI,GAAA,CAAA,CAAA,KAAO,MAAM,CAAI,CAAA,EAAA;AACxD,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAGA,EAAA,IAAI,aAAc,CAAA,WAAA,CAAY,KAAK,CAAA,CAAE,SAAS,4BAA8B,EAAA;AAC1E,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAO,OAAA,IAAA,CAAA;AACT,CAAA;AAEA,SAAS,kBAAqB,GAAA;AAC5B,EAAI,IAAA;AACF,IAAM,MAAA,OAAA,GAAU,QAAS,CAAA,aAAA,CAAc,MAAM,CAAA,CAAA;AAC7C,IAAA,OAAA,CAAQ,MAAM,OAAU,GAAA,MAAA,CAAA;AACxB,IAAA,OAAA,CAAQ,QAAQ,KAAQ,GAAA,EAAA,CAAA;AAExB,IAAS,QAAA,CAAA,IAAA,CAAK,YAAY,OAAO,CAAA,CAAA;AAEjC,IAAA,MAAM,kBAAqB,GAAA,MAAA,CAAO,gBAAiB,CAAA,OAAO,CAAE,CAAA,UAAA,CAAA;AAE5D,IAAS,QAAA,CAAA,IAAA,CAAK,YAAY,OAAO,CAAA,CAAA;AAEjC,IAAO,OAAA,kBAAA,CAAA;AAAA,GACP,CAAA,MAAA;AACA,IAAO,OAAAC,2BAAA,CAAA;AAAA,GACT;AACF,CAAA;AAEA,SAAS,wBAAwB,MAAuC,EAAA;AACtE,EAAM,MAAA,QAAA,uBAAe,GAAoB,EAAA,CAAA;AAEzC,EAAA,KAAA,MAAW,SAAS,MAAQ,EAAA;AAC1B,IAAA,IAAI,CAAC,QAAA,CAAS,GAAI,CAAA,KAAA,CAAM,OAAO,CAAG,EAAA;AAChC,MAAA,QAAA,CAAS,GAAI,CAAA,KAAA,CAAM,OAAS,EAAA,KAAA,CAAM,KAAK,CAAA,CAAA;AAAA,KACzC;AAAA,GACF;AAEA,EAAA,MAAM,kBAAqB,GAAA,CAAC,GAAG,QAAA,CAAS,IAAK,EAAC,CAAE,CAAA,IAAA,CAAK,CAAC,CAAA,EAAG,CAAM,KAAA,CAAA,GAAI,CAAC,CAAA,CAAA;AAEpE,EAAM,MAAA,aAAA,GAAgB,QACnB,CAAA,aAAA,CAAc,QAAQ,CAAA,CACtB,WAAW,IAAM,EAAA,EAAE,kBAAoB,EAAA,IAAA,EAAM,CAAA,CAAA;AAEhD,EAAA,IAAI,CAAC,aAAe,EAAA;AAClB,IAAA,OAAO,EAAE,YAAA,EAAc,kBAAmB,CAAA,CAAA,CAAA,EAAI,cAAc,IAAK,EAAA,CAAA;AAAA,GACnE;AAEA,EAAc,aAAA,CAAA,IAAA,GAAO,GAAG,IAAK,CAAA,KAAA;AAAA,IAC3B,6BAAgC,GAAA,CAAA;AAAA,SAC3B,kBAAmB,EAAA,CAAA,CAAA,CAAA;AAC1B,EAAA,aAAA,CAAc,YAAe,GAAA,KAAA,CAAA;AAC7B,EAAc,aAAA,CAAA,MAAA,CAAO,QAAQ,4BAA+B,GAAA,CAAA,CAAA;AAC5D,EAAA,aAAA,CAAc,OAAO,MAAS,GAAA,6BAAA,CAAA;AAE9B,EAAA,MAAM,oBAAuB,GAAA,kBAAA;AAAA,IAC3B,aAAA;AAAA,IACA,4BAAA;AAAA,GACF,CAAA;AAEA,EAAA,KAAA,MAAW,WAAW,kBAAoB,EAAA;AACxC,IAAM,MAAA,KAAA,GAAQ,QAAS,CAAA,GAAA,CAAI,OAAO,CAAA,CAAA;AAClC,IAAM,MAAA,WAAA,GAAc,kBAAmB,CAAA,aAAA,EAAe,KAAK,CAAA,CAAA;AAE3D,IAAA,IAAI,WAAa,EAAA;AACf,MAAO,OAAA;AAAA,QACL,YAAc,EAAA,OAAA;AAAA,QACd,YAAc,EAAA,oBAAA;AAAA,OAChB,CAAA;AAAA,KACF;AAAA,GACF;AAEA,EAAO,OAAA;AAAA,IACL,cAAc,kBAAmB,CAAA,CAAA,CAAA;AAAA,IACjC,YAAc,EAAA,oBAAA;AAAA,GAChB,CAAA;AACF,CAAA;AAEA,eAAsB,aAAa,MAAoC,EAAA;AACrE,EAAM,MAAA,eAAA,GAAkB,4BAA4B,MAAM,CAAA,CAAA;AAE1D,EAAA,MAAM,eAAkB,GAAA,cAAA;AAAA,IACtB,cAAA;AAAA,IACA,gCAAA;AAAA,GACF,CAAA;AACA,EAAA,MAAM,UAAa,GAAA,cAAA;AAAA,IACjB,YAAA;AAAA,IACA,qBAAqB,eAAe,CAAA;AAAA,GACtC,CAAA;AACA,EAAI,IAAA,IAAA,CAAA;AAIJ,EAAA,IAAI,UAAY,EAAA;AAEd,IAAA,IAAI,eAAiB,EAAA;AACnB,MAAO,IAAA,GAAA,UAAA,CAAA;AAAA,KACF,MAAA;AACL,MAAA,MAAM,EAAE,UAAY,EAAA,YAAA,EAClB,GAAA,MAAM,oBAAoB,eAAe,CAAA,CAAA;AAC3C,MAAA,MAAM,cAAiB,GAAA,cAAA;AAAA,QACrB,YAAA;AAAA,QACA,yBAAyB,eAAe,CAAA;AAAA,OAC1C,CAAA;AAEA,MAAA,IACE,kBACA,UAAe,KAAA,cAAA,CAAe,UAC9B,IAAA,YAAA,KAAiB,eAAe,YAChC,EAAA;AACA,QAAO,IAAA,GAAA,UAAA,CAAA;AAAA,OACF,MAAA;AACL,QAAO,IAAA,GAAA,MAAM,eAAe,eAAe,CAAA,CAAA;AAAA,OAC7C;AAAA,KACF;AAAA,GACK,MAAA;AACL,IAAO,IAAA,GAAA,MAAM,eAAe,eAAe,CAAA,CAAA;AAAA,GAC7C;AAEA,EAAA,MAAM,kBACJ,GAAA,eAAA,IAAmB,uBAAwB,CAAA,IAAA,CAAK,MAAM,CAAA,CAAA;AACxD,EAAA,cAAA;AAAA,IACE,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,kBAAA;AAAA,GACF,CAAA;AAGA,EAAA,MAAM,cAAiB,GAAA,IAAA,CAAK,MAAO,CAAA,MAAA,CAAO,CAAC,KAAU,KAAA;AACnD,IAAM,MAAA,kBAAA,GAAqB,KAAM,CAAA,OAAA,IAAW,kBAAmB,CAAA,YAAA,CAAA;AAE/D,IAAA,OAAO,KAAM,CAAA,WAAA,GACT,kBAAsB,IAAA,kBAAA,CAAmB,YACzC,GAAA,kBAAA,CAAA;AAAA,GACL,CAAA,CAAA;AAED,EAAO,OAAA;AAAA,IACL,MAAQ,EAAA,cAAA;AAAA,IACR,YAAY,IAAK,CAAA,UAAA;AAAA,IACjB,WAAW,IAAK,CAAA,SAAA;AAAA,GAClB,CAAA;AACF,CAAA;AAEgB,SAAA,YAAA,CAAa,QAAiB,MAAiB,EAAA;AAC7D,EAAA,IAAI,CAAC,MAAQ,EAAA;AACX,IAAO,OAAA,MAAA,CAAA;AAAA,GACT;AAEA,EAAA,MAAM,UAAa,GAAA,MAAA,CAAO,WAAY,EAAA,CAAE,IAAK,EAAA,CAAA;AAE7C,EAAA,OAAO,MAAO,CAAA,MAAA;AAAA,IACZ,CAAC,KACC,KAAA,KAAA,CAAM,KAAK,WAAY,EAAA,CAAE,SAAS,UAAU,CAAA,IAC5C,MAAM,IAAM,EAAA,IAAA,CAAK,CAAC,GAAQ,KAAA,GAAA,CAAI,aAAc,CAAA,QAAA,CAAS,UAAU,CAAC,CAAA;AAAA,GACpE,CAAA;AACF,CAAA;AAEgB,SAAA,uBAAA,CACd,MACA,EAAA,UAAA,EACA,OACiB,EAAA;AACjB,EAAA,IAAI,YAAe,GAAA,CAAA,CAAA;AACnB,EAAA,MAAM,OAAyB,EAAC,CAAA;AAChC,EAAM,MAAA,aAAA,GAAgB,MAAO,CAAA,GAAA,CAAI,CAAC,KAAA,EAAO,WAAW,EAAE,GAAG,KAAO,EAAA,KAAA,EAAQ,CAAA,CAAA,CAAA;AACxE,EAAA,MAAM,sBAAgC,EAAC,CAAA;AACvC,EAAA,MAAM,uBAAmC,EAAC,CAAA;AAC1C,EAAA,MAAM,kBAA4B,EAAC,CAAA;AACnC,EAAA,MAAM,iBAAoB,GAAA,UAAA,CACvB,GAAI,CAAA,CAAC,QAAc,MAAA;AAAA,IAClB,GAAG,QAAA;AAAA,IACH,MAAA,EAAQ,cAAc,MAAO,CAAA,CAAC,UAAU,KAAM,CAAA,QAAA,KAAa,SAAS,GAAG,CAAA;AAAA,GACzE,CAAE,EACD,MAAO,CAAA,CAAC,aAAa,QAAS,CAAA,MAAA,CAAO,SAAS,CAAC,CAAA,CAAA;AAElD,EAAA,KAAA,MAAW,YAAY,iBAAmB,EAAA;AACxC,IAAA,MAAM,YAAe,GAAAC,UAAA,CAAM,QAAS,CAAA,MAAA,EAAQ,OAAO,CAAA,CAAA;AACnD,IAAM,MAAA,SAAA,GAAY,eAAe,YAAa,CAAA,MAAA,CAAA;AAE9C,IAAK,IAAA,CAAA,IAAA,CAAK,GAAG,YAAY,CAAA,CAAA;AACzB,IAAgB,eAAA,CAAA,IAAA,CAAK,SAAS,IAAI,CAAA,CAAA;AAClC,IAAoB,mBAAA,CAAA,IAAA,CAAK,aAAa,MAAM,CAAA,CAAA;AAC5C,IAAqB,oBAAA,CAAA,IAAA;AAAA,MACnB,oBAAA,CAAqB,YAAc,EAAA,SAAA,GAAY,CAAC,CAAA;AAAA,KAClD,CAAA;AACA,IAAe,YAAA,GAAA,SAAA,CAAA;AAAA,GACjB;AAEA,EAAO,OAAA;AAAA,IACL,OAAO,MAAO,CAAA,MAAA;AAAA,IACd,IAAA;AAAA,IACA,UAAY,EAAA,eAAA;AAAA,IACZ,mBAAA;AAAA,IACA,oBAAA;AAAA,GACF,CAAA;AACF;;;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { chunk } from '@liveblocks/core';
|
|
1
2
|
import { EMOJI_FONT_FAMILY } from '../../constants.mjs';
|
|
2
3
|
import { capitalize } from '../../utils/capitalize.mjs';
|
|
3
|
-
import { chunk } from '../../utils/chunk.mjs';
|
|
4
4
|
|
|
5
5
|
const EMOJIBASE_VERSION = "15.3.0";
|
|
6
6
|
const EMOJIBASE_CDN_URL = `https://cdn.jsdelivr.net/npm/emojibase-data@${EMOJIBASE_VERSION}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","sources":["../../../src/primitives/EmojiPicker/utils.ts"],"sourcesContent":["import type {\n Emoji as EmojibaseEmoji,\n Locale as EmojibaseLocale,\n MessagesDataset as EmojibaseMessagesDataset,\n} from \"emojibase\";\n\nimport { EMOJI_FONT_FAMILY } from \"../../constants\";\nimport { capitalize } from \"../../utils/capitalize\";\nimport { chunk } from \"../../utils/chunk\";\nimport type {\n Emoji,\n EmojiCategory,\n EmojiData,\n EmojiPickerData,\n EmojiPickerRow,\n} from \"./types\";\n\nconst EMOJIBASE_VERSION = \"15.3.0\";\nconst EMOJIBASE_CDN_URL = `https://cdn.jsdelivr.net/npm/emojibase-data@${EMOJIBASE_VERSION}`;\nconst EMOJIBASE_EMOJIS_URL = (locale: EmojibaseLocale) =>\n `${EMOJIBASE_CDN_URL}/${locale}/data.json`;\nconst EMOJIBASE_MESSAGES_URL = (locale: EmojibaseLocale) =>\n `${EMOJIBASE_CDN_URL}/${locale}/messages.json`;\nconst EMOJIBASE_LOCALES: EmojibaseLocale[] = [\n \"bn\",\n \"da\",\n \"de\",\n \"en\",\n \"en-gb\",\n \"es\",\n \"es-mx\",\n \"et\",\n \"fi\",\n \"fr\",\n \"hi\",\n \"hu\",\n \"it\",\n \"ja\",\n \"ko\",\n \"lt\",\n \"ms\",\n \"nb\",\n \"nl\",\n \"pl\",\n \"pt\",\n \"ru\",\n \"sv\",\n \"th\",\n \"uk\",\n \"zh\",\n \"zh-hant\",\n];\nconst EMOJIBASE_DEFAULT_LOCALE: EmojibaseLocale = \"en\";\n\nconst CACHE_EMOJI_DATA_KEY = (locale: string) => `lb-emoji-data-${locale}`;\nconst CACHE_EMOJI_METADATA_KEY = (locale: string) =>\n `lb-emoji-metadata-${locale}`;\nconst CACHE_EMOJI_SESSION_METADATA_KEY = \"lb-emoji-metadata\";\n\nconst EMOJI_DETECTION_CANVAS_WIDTH = 20;\nconst EMOJI_DETECTION_CANVAS_HEIGHT = 25;\nconst EMOJI_DETECTION_COUNTRY_FLAG = \"🇫🇷\";\n\ntype EmojiMetadata = {\n emojisEtag: string | null;\n messagesEtag: string | null;\n};\n\ntype EmojiSessionMetadata = {\n emojiVersion: number;\n countryFlags: boolean;\n};\n\nfunction generateRangeIndices(start: number, end: number) {\n const range: number[] = [];\n\n for (let i = start; i <= end; i++) {\n range.push(i);\n }\n\n return range;\n}\n\nfunction getStorageItem<T>(storage: Storage, key: string) {\n const item = storage.getItem(key);\n\n return item ? (JSON.parse(item) as T) : null;\n}\n\nfunction setStorageItem<T>(storage: Storage, key: string, value: T) {\n storage.setItem(key, JSON.stringify(value));\n}\n\nasync function fetchEtag(url: string) {\n try {\n const response = await fetch(url, { method: \"HEAD\" });\n\n return response.headers.get(\"etag\");\n } catch (error) {\n return null;\n }\n}\n\nfunction getEmojibaseSupportedLocale(locale: string): EmojibaseLocale {\n return EMOJIBASE_LOCALES.includes(locale as EmojibaseLocale)\n ? (locale as EmojibaseLocale)\n : EMOJIBASE_DEFAULT_LOCALE;\n}\n\nasync function fetchEmojibaseData(locale: EmojibaseLocale) {\n const [{ emojis, emojisEtag }, { messages, messagesEtag }] =\n await Promise.all([\n fetch(EMOJIBASE_EMOJIS_URL(locale)).then(async (response) => {\n return {\n emojis: (await response.json()) as EmojibaseEmoji[],\n emojisEtag: response.headers.get(\"etag\"),\n };\n }),\n fetch(EMOJIBASE_MESSAGES_URL(locale)).then(async (response) => {\n return {\n messages: (await response.json()) as EmojibaseMessagesDataset,\n messagesEtag: response.headers.get(\"etag\"),\n };\n }),\n ]);\n\n return {\n emojis,\n messages,\n emojisEtag,\n messagesEtag,\n };\n}\n\nasync function fetchEmojibaseEtags(locale: EmojibaseLocale) {\n const [emojisEtag, messagesEtag] = await Promise.all([\n fetchEtag(EMOJIBASE_EMOJIS_URL(locale)),\n fetchEtag(EMOJIBASE_MESSAGES_URL(locale)),\n ]);\n\n return {\n emojisEtag,\n messagesEtag,\n };\n}\n\nasync function fetchEmojiData(locale: EmojibaseLocale): Promise<EmojiData> {\n const { emojis, emojisEtag, messages, messagesEtag } =\n await fetchEmojibaseData(locale);\n const countryFlagsSubgroup = messages.subgroups.find(\n (subgroup) => subgroup.key === \"subdivision-flag\"\n );\n\n // Filter out component/modifier category and emojis\n const filteredGroups = messages.groups.filter(\n (group) => group.key !== \"component\"\n );\n const filteredEmojis = emojis.filter((emoji) => {\n return \"group\" in emoji;\n });\n\n // Pick and compact the data\n const categories = filteredGroups.map((group) => ({\n key: group.order,\n name: capitalize(group.message),\n }));\n const skinTones = messages.skinTones.map((skinTone) => ({\n key: skinTone.key,\n name: capitalize(skinTone.message),\n }));\n const compactEmojis = filteredEmojis.map((emoji) => {\n const compactEmoji: Emoji = {\n emoji: emoji.emoji,\n category: emoji.group!,\n version: emoji.version,\n name: capitalize(emoji.label),\n tags: emoji.tags,\n };\n\n if (countryFlagsSubgroup && emoji.subgroup === countryFlagsSubgroup.order) {\n compactEmoji.countryFlag = true;\n }\n\n return compactEmoji;\n });\n\n const emojiData = {\n emojis: compactEmojis,\n categories,\n skinTones,\n };\n\n // Cache the data and metadata\n setStorageItem<EmojiData>(\n localStorage,\n CACHE_EMOJI_DATA_KEY(locale),\n emojiData\n );\n setStorageItem<EmojiMetadata>(\n localStorage,\n CACHE_EMOJI_METADATA_KEY(locale),\n {\n emojisEtag,\n messagesEtag,\n }\n );\n\n return emojiData;\n}\n\n// Adapted from https://github.com/koala-interactive/is-emoji-supported/tree/master\nfunction detectEmojiSupport(\n canvasContext: CanvasRenderingContext2D,\n emoji: string\n): boolean {\n canvasContext.clearRect(\n 0,\n 0,\n EMOJI_DETECTION_CANVAS_WIDTH * 2,\n EMOJI_DETECTION_CANVAS_HEIGHT\n );\n\n // Draw in red on the left\n canvasContext.fillStyle = \"#f00\";\n canvasContext.fillText(emoji, 0, 22);\n\n // Draw in blue on right\n canvasContext.fillStyle = \"#00f\";\n canvasContext.fillText(emoji, EMOJI_DETECTION_CANVAS_WIDTH, 22);\n\n const pixels = canvasContext.getImageData(\n 0,\n 0,\n EMOJI_DETECTION_CANVAS_WIDTH,\n EMOJI_DETECTION_CANVAS_HEIGHT\n ).data;\n const pixelCount = pixels.length;\n let i = 0;\n\n // Search for the first visible pixel\n for (; i < pixelCount && !pixels[i + 3]; i += 4);\n\n // No visible pixel\n if (i >= pixelCount) {\n return false;\n }\n\n // Emojis have an immutable color, so we check the color of the emoji in two\n // different colors, the result should be the same\n const x =\n EMOJI_DETECTION_CANVAS_WIDTH + ((i / 4) % EMOJI_DETECTION_CANVAS_WIDTH);\n const y = Math.floor(i / 4 / EMOJI_DETECTION_CANVAS_WIDTH);\n const pixel = canvasContext.getImageData(x, y, 1, 1).data;\n\n if (pixels[i] !== pixel[0] || pixels[i + 2] !== pixel[2]) {\n return false;\n }\n\n // Unsupported ZWJ sequence emojis show up as separate emojis\n if (canvasContext.measureText(emoji).width >= EMOJI_DETECTION_CANVAS_WIDTH) {\n return false;\n }\n\n return true;\n}\n\nfunction getEmojiFontFamily() {\n try {\n const element = document.createElement(\"span\");\n element.style.display = \"none\";\n element.dataset.emoji = \"\";\n\n document.body.appendChild(element);\n\n const computedFontFamily = window.getComputedStyle(element).fontFamily;\n\n document.body.removeChild(element);\n\n return computedFontFamily;\n } catch {\n return EMOJI_FONT_FAMILY;\n }\n}\n\nfunction getEmojiSessionMetadata(emojis: Emoji[]): EmojiSessionMetadata {\n const versions = new Map<number, string>();\n\n for (const emoji of emojis) {\n if (!versions.has(emoji.version)) {\n versions.set(emoji.version, emoji.emoji);\n }\n }\n\n const descendingVersions = [...versions.keys()].sort((a, b) => b - a);\n\n const canvasContext = document\n .createElement(\"canvas\")\n .getContext(\"2d\", { willReadFrequently: true });\n\n if (!canvasContext) {\n return { emojiVersion: descendingVersions[0], countryFlags: true };\n }\n\n canvasContext.font = `${Math.floor(\n EMOJI_DETECTION_CANVAS_HEIGHT / 2\n )}px ${getEmojiFontFamily()}`;\n canvasContext.textBaseline = \"top\";\n canvasContext.canvas.width = EMOJI_DETECTION_CANVAS_WIDTH * 2;\n canvasContext.canvas.height = EMOJI_DETECTION_CANVAS_HEIGHT;\n\n const supportsCountryFlags = detectEmojiSupport(\n canvasContext,\n EMOJI_DETECTION_COUNTRY_FLAG\n );\n\n for (const version of descendingVersions) {\n const emoji = versions.get(version)!;\n const isSupported = detectEmojiSupport(canvasContext, emoji);\n\n if (isSupported) {\n return {\n emojiVersion: version,\n countryFlags: supportsCountryFlags,\n };\n }\n }\n\n return {\n emojiVersion: descendingVersions[0],\n countryFlags: supportsCountryFlags,\n };\n}\n\nexport async function getEmojiData(locale: string): Promise<EmojiData> {\n const emojibaseLocale = getEmojibaseSupportedLocale(locale);\n\n const sessionMetadata = getStorageItem<EmojiSessionMetadata>(\n sessionStorage,\n CACHE_EMOJI_SESSION_METADATA_KEY\n );\n const cachedData = getStorageItem<EmojiData>(\n localStorage,\n CACHE_EMOJI_DATA_KEY(emojibaseLocale)\n );\n let data: EmojiData;\n\n // If there is data already cached, check if the ETags are the same.\n // If they are, return the cached data, otherwise fetch it again.\n if (cachedData) {\n // ETags only need to be checked once per session\n if (sessionMetadata) {\n data = cachedData;\n } else {\n const { emojisEtag, messagesEtag } =\n await fetchEmojibaseEtags(emojibaseLocale);\n const cachedMetadata = getStorageItem<EmojiMetadata>(\n localStorage,\n CACHE_EMOJI_METADATA_KEY(emojibaseLocale)\n );\n\n if (\n cachedMetadata &&\n emojisEtag === cachedMetadata.emojisEtag &&\n messagesEtag === cachedMetadata.messagesEtag\n ) {\n data = cachedData;\n } else {\n data = await fetchEmojiData(emojibaseLocale);\n }\n }\n } else {\n data = await fetchEmojiData(emojibaseLocale);\n }\n\n const newSessionMetadata =\n sessionMetadata ?? getEmojiSessionMetadata(data.emojis);\n setStorageItem(\n sessionStorage,\n CACHE_EMOJI_SESSION_METADATA_KEY,\n newSessionMetadata\n );\n\n // Filter out unsupported emojis\n const filteredEmojis = data.emojis.filter((emoji) => {\n const isSupportedVersion = emoji.version <= newSessionMetadata.emojiVersion;\n\n return emoji.countryFlag\n ? isSupportedVersion && newSessionMetadata.countryFlags\n : isSupportedVersion;\n });\n\n return {\n emojis: filteredEmojis,\n categories: data.categories,\n skinTones: data.skinTones,\n };\n}\n\nexport function filterEmojis(emojis: Emoji[], search?: string) {\n if (!search) {\n return emojis;\n }\n\n const searchText = search.toLowerCase().trim();\n\n return emojis.filter(\n (emoji) =>\n emoji.name.toLowerCase().includes(searchText) ||\n emoji.tags?.some((tag) => tag.toLowerCase().includes(searchText))\n );\n}\n\nexport function generateEmojiPickerData(\n emojis: Emoji[],\n categories: EmojiCategory[],\n columns: number\n): EmojiPickerData {\n let currentIndex = 0;\n const rows: EmojiPickerRow[] = [];\n const indexedEmojis = emojis.map((emoji, index) => ({ ...emoji, index }));\n const categoriesRowCounts: number[] = [];\n const categoriesRowIndices: number[][] = [];\n const categoriesNames: string[] = [];\n const categorizedEmojis = categories\n .map((category) => ({\n ...category,\n emojis: indexedEmojis.filter((emoji) => emoji.category === category.key),\n }))\n .filter((category) => category.emojis.length > 0);\n\n for (const category of categorizedEmojis) {\n const categoryRows = chunk(category.emojis, columns);\n const nextIndex = currentIndex + categoryRows.length;\n\n rows.push(...categoryRows);\n categoriesNames.push(category.name);\n categoriesRowCounts.push(categoryRows.length);\n categoriesRowIndices.push(\n generateRangeIndices(currentIndex, nextIndex - 1)\n );\n currentIndex = nextIndex;\n }\n\n return {\n count: emojis.length,\n rows,\n categories: categoriesNames,\n categoriesRowCounts,\n categoriesRowIndices,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.mjs","sources":["../../../src/primitives/EmojiPicker/utils.ts"],"sourcesContent":["import { chunk } from \"@liveblocks/core\";\nimport type {\n Emoji as EmojibaseEmoji,\n Locale as EmojibaseLocale,\n MessagesDataset as EmojibaseMessagesDataset,\n} from \"emojibase\";\n\nimport { EMOJI_FONT_FAMILY } from \"../../constants\";\nimport { capitalize } from \"../../utils/capitalize\";\nimport type {\n Emoji,\n EmojiCategory,\n EmojiData,\n EmojiPickerData,\n EmojiPickerRow,\n} from \"./types\";\n\nconst EMOJIBASE_VERSION = \"15.3.0\";\nconst EMOJIBASE_CDN_URL = `https://cdn.jsdelivr.net/npm/emojibase-data@${EMOJIBASE_VERSION}`;\nconst EMOJIBASE_EMOJIS_URL = (locale: EmojibaseLocale) =>\n `${EMOJIBASE_CDN_URL}/${locale}/data.json`;\nconst EMOJIBASE_MESSAGES_URL = (locale: EmojibaseLocale) =>\n `${EMOJIBASE_CDN_URL}/${locale}/messages.json`;\nconst EMOJIBASE_LOCALES: EmojibaseLocale[] = [\n \"bn\",\n \"da\",\n \"de\",\n \"en\",\n \"en-gb\",\n \"es\",\n \"es-mx\",\n \"et\",\n \"fi\",\n \"fr\",\n \"hi\",\n \"hu\",\n \"it\",\n \"ja\",\n \"ko\",\n \"lt\",\n \"ms\",\n \"nb\",\n \"nl\",\n \"pl\",\n \"pt\",\n \"ru\",\n \"sv\",\n \"th\",\n \"uk\",\n \"zh\",\n \"zh-hant\",\n];\nconst EMOJIBASE_DEFAULT_LOCALE: EmojibaseLocale = \"en\";\n\nconst CACHE_EMOJI_DATA_KEY = (locale: string) => `lb-emoji-data-${locale}`;\nconst CACHE_EMOJI_METADATA_KEY = (locale: string) =>\n `lb-emoji-metadata-${locale}`;\nconst CACHE_EMOJI_SESSION_METADATA_KEY = \"lb-emoji-metadata\";\n\nconst EMOJI_DETECTION_CANVAS_WIDTH = 20;\nconst EMOJI_DETECTION_CANVAS_HEIGHT = 25;\nconst EMOJI_DETECTION_COUNTRY_FLAG = \"🇫🇷\";\n\ntype EmojiMetadata = {\n emojisEtag: string | null;\n messagesEtag: string | null;\n};\n\ntype EmojiSessionMetadata = {\n emojiVersion: number;\n countryFlags: boolean;\n};\n\nfunction generateRangeIndices(start: number, end: number) {\n const range: number[] = [];\n\n for (let i = start; i <= end; i++) {\n range.push(i);\n }\n\n return range;\n}\n\nfunction getStorageItem<T>(storage: Storage, key: string) {\n const item = storage.getItem(key);\n\n return item ? (JSON.parse(item) as T) : null;\n}\n\nfunction setStorageItem<T>(storage: Storage, key: string, value: T) {\n storage.setItem(key, JSON.stringify(value));\n}\n\nasync function fetchEtag(url: string) {\n try {\n const response = await fetch(url, { method: \"HEAD\" });\n\n return response.headers.get(\"etag\");\n } catch (error) {\n return null;\n }\n}\n\nfunction getEmojibaseSupportedLocale(locale: string): EmojibaseLocale {\n return EMOJIBASE_LOCALES.includes(locale as EmojibaseLocale)\n ? (locale as EmojibaseLocale)\n : EMOJIBASE_DEFAULT_LOCALE;\n}\n\nasync function fetchEmojibaseData(locale: EmojibaseLocale) {\n const [{ emojis, emojisEtag }, { messages, messagesEtag }] =\n await Promise.all([\n fetch(EMOJIBASE_EMOJIS_URL(locale)).then(async (response) => {\n return {\n emojis: (await response.json()) as EmojibaseEmoji[],\n emojisEtag: response.headers.get(\"etag\"),\n };\n }),\n fetch(EMOJIBASE_MESSAGES_URL(locale)).then(async (response) => {\n return {\n messages: (await response.json()) as EmojibaseMessagesDataset,\n messagesEtag: response.headers.get(\"etag\"),\n };\n }),\n ]);\n\n return {\n emojis,\n messages,\n emojisEtag,\n messagesEtag,\n };\n}\n\nasync function fetchEmojibaseEtags(locale: EmojibaseLocale) {\n const [emojisEtag, messagesEtag] = await Promise.all([\n fetchEtag(EMOJIBASE_EMOJIS_URL(locale)),\n fetchEtag(EMOJIBASE_MESSAGES_URL(locale)),\n ]);\n\n return {\n emojisEtag,\n messagesEtag,\n };\n}\n\nasync function fetchEmojiData(locale: EmojibaseLocale): Promise<EmojiData> {\n const { emojis, emojisEtag, messages, messagesEtag } =\n await fetchEmojibaseData(locale);\n const countryFlagsSubgroup = messages.subgroups.find(\n (subgroup) => subgroup.key === \"subdivision-flag\"\n );\n\n // Filter out component/modifier category and emojis\n const filteredGroups = messages.groups.filter(\n (group) => group.key !== \"component\"\n );\n const filteredEmojis = emojis.filter((emoji) => {\n return \"group\" in emoji;\n });\n\n // Pick and compact the data\n const categories = filteredGroups.map((group) => ({\n key: group.order,\n name: capitalize(group.message),\n }));\n const skinTones = messages.skinTones.map((skinTone) => ({\n key: skinTone.key,\n name: capitalize(skinTone.message),\n }));\n const compactEmojis = filteredEmojis.map((emoji) => {\n const compactEmoji: Emoji = {\n emoji: emoji.emoji,\n category: emoji.group!,\n version: emoji.version,\n name: capitalize(emoji.label),\n tags: emoji.tags,\n };\n\n if (countryFlagsSubgroup && emoji.subgroup === countryFlagsSubgroup.order) {\n compactEmoji.countryFlag = true;\n }\n\n return compactEmoji;\n });\n\n const emojiData = {\n emojis: compactEmojis,\n categories,\n skinTones,\n };\n\n // Cache the data and metadata\n setStorageItem<EmojiData>(\n localStorage,\n CACHE_EMOJI_DATA_KEY(locale),\n emojiData\n );\n setStorageItem<EmojiMetadata>(\n localStorage,\n CACHE_EMOJI_METADATA_KEY(locale),\n {\n emojisEtag,\n messagesEtag,\n }\n );\n\n return emojiData;\n}\n\n// Adapted from https://github.com/koala-interactive/is-emoji-supported/tree/master\nfunction detectEmojiSupport(\n canvasContext: CanvasRenderingContext2D,\n emoji: string\n): boolean {\n canvasContext.clearRect(\n 0,\n 0,\n EMOJI_DETECTION_CANVAS_WIDTH * 2,\n EMOJI_DETECTION_CANVAS_HEIGHT\n );\n\n // Draw in red on the left\n canvasContext.fillStyle = \"#f00\";\n canvasContext.fillText(emoji, 0, 22);\n\n // Draw in blue on right\n canvasContext.fillStyle = \"#00f\";\n canvasContext.fillText(emoji, EMOJI_DETECTION_CANVAS_WIDTH, 22);\n\n const pixels = canvasContext.getImageData(\n 0,\n 0,\n EMOJI_DETECTION_CANVAS_WIDTH,\n EMOJI_DETECTION_CANVAS_HEIGHT\n ).data;\n const pixelCount = pixels.length;\n let i = 0;\n\n // Search for the first visible pixel\n for (; i < pixelCount && !pixels[i + 3]; i += 4);\n\n // No visible pixel\n if (i >= pixelCount) {\n return false;\n }\n\n // Emojis have an immutable color, so we check the color of the emoji in two\n // different colors, the result should be the same\n const x =\n EMOJI_DETECTION_CANVAS_WIDTH + ((i / 4) % EMOJI_DETECTION_CANVAS_WIDTH);\n const y = Math.floor(i / 4 / EMOJI_DETECTION_CANVAS_WIDTH);\n const pixel = canvasContext.getImageData(x, y, 1, 1).data;\n\n if (pixels[i] !== pixel[0] || pixels[i + 2] !== pixel[2]) {\n return false;\n }\n\n // Unsupported ZWJ sequence emojis show up as separate emojis\n if (canvasContext.measureText(emoji).width >= EMOJI_DETECTION_CANVAS_WIDTH) {\n return false;\n }\n\n return true;\n}\n\nfunction getEmojiFontFamily() {\n try {\n const element = document.createElement(\"span\");\n element.style.display = \"none\";\n element.dataset.emoji = \"\";\n\n document.body.appendChild(element);\n\n const computedFontFamily = window.getComputedStyle(element).fontFamily;\n\n document.body.removeChild(element);\n\n return computedFontFamily;\n } catch {\n return EMOJI_FONT_FAMILY;\n }\n}\n\nfunction getEmojiSessionMetadata(emojis: Emoji[]): EmojiSessionMetadata {\n const versions = new Map<number, string>();\n\n for (const emoji of emojis) {\n if (!versions.has(emoji.version)) {\n versions.set(emoji.version, emoji.emoji);\n }\n }\n\n const descendingVersions = [...versions.keys()].sort((a, b) => b - a);\n\n const canvasContext = document\n .createElement(\"canvas\")\n .getContext(\"2d\", { willReadFrequently: true });\n\n if (!canvasContext) {\n return { emojiVersion: descendingVersions[0], countryFlags: true };\n }\n\n canvasContext.font = `${Math.floor(\n EMOJI_DETECTION_CANVAS_HEIGHT / 2\n )}px ${getEmojiFontFamily()}`;\n canvasContext.textBaseline = \"top\";\n canvasContext.canvas.width = EMOJI_DETECTION_CANVAS_WIDTH * 2;\n canvasContext.canvas.height = EMOJI_DETECTION_CANVAS_HEIGHT;\n\n const supportsCountryFlags = detectEmojiSupport(\n canvasContext,\n EMOJI_DETECTION_COUNTRY_FLAG\n );\n\n for (const version of descendingVersions) {\n const emoji = versions.get(version)!;\n const isSupported = detectEmojiSupport(canvasContext, emoji);\n\n if (isSupported) {\n return {\n emojiVersion: version,\n countryFlags: supportsCountryFlags,\n };\n }\n }\n\n return {\n emojiVersion: descendingVersions[0],\n countryFlags: supportsCountryFlags,\n };\n}\n\nexport async function getEmojiData(locale: string): Promise<EmojiData> {\n const emojibaseLocale = getEmojibaseSupportedLocale(locale);\n\n const sessionMetadata = getStorageItem<EmojiSessionMetadata>(\n sessionStorage,\n CACHE_EMOJI_SESSION_METADATA_KEY\n );\n const cachedData = getStorageItem<EmojiData>(\n localStorage,\n CACHE_EMOJI_DATA_KEY(emojibaseLocale)\n );\n let data: EmojiData;\n\n // If there is data already cached, check if the ETags are the same.\n // If they are, return the cached data, otherwise fetch it again.\n if (cachedData) {\n // ETags only need to be checked once per session\n if (sessionMetadata) {\n data = cachedData;\n } else {\n const { emojisEtag, messagesEtag } =\n await fetchEmojibaseEtags(emojibaseLocale);\n const cachedMetadata = getStorageItem<EmojiMetadata>(\n localStorage,\n CACHE_EMOJI_METADATA_KEY(emojibaseLocale)\n );\n\n if (\n cachedMetadata &&\n emojisEtag === cachedMetadata.emojisEtag &&\n messagesEtag === cachedMetadata.messagesEtag\n ) {\n data = cachedData;\n } else {\n data = await fetchEmojiData(emojibaseLocale);\n }\n }\n } else {\n data = await fetchEmojiData(emojibaseLocale);\n }\n\n const newSessionMetadata =\n sessionMetadata ?? getEmojiSessionMetadata(data.emojis);\n setStorageItem(\n sessionStorage,\n CACHE_EMOJI_SESSION_METADATA_KEY,\n newSessionMetadata\n );\n\n // Filter out unsupported emojis\n const filteredEmojis = data.emojis.filter((emoji) => {\n const isSupportedVersion = emoji.version <= newSessionMetadata.emojiVersion;\n\n return emoji.countryFlag\n ? isSupportedVersion && newSessionMetadata.countryFlags\n : isSupportedVersion;\n });\n\n return {\n emojis: filteredEmojis,\n categories: data.categories,\n skinTones: data.skinTones,\n };\n}\n\nexport function filterEmojis(emojis: Emoji[], search?: string) {\n if (!search) {\n return emojis;\n }\n\n const searchText = search.toLowerCase().trim();\n\n return emojis.filter(\n (emoji) =>\n emoji.name.toLowerCase().includes(searchText) ||\n emoji.tags?.some((tag) => tag.toLowerCase().includes(searchText))\n );\n}\n\nexport function generateEmojiPickerData(\n emojis: Emoji[],\n categories: EmojiCategory[],\n columns: number\n): EmojiPickerData {\n let currentIndex = 0;\n const rows: EmojiPickerRow[] = [];\n const indexedEmojis = emojis.map((emoji, index) => ({ ...emoji, index }));\n const categoriesRowCounts: number[] = [];\n const categoriesRowIndices: number[][] = [];\n const categoriesNames: string[] = [];\n const categorizedEmojis = categories\n .map((category) => ({\n ...category,\n emojis: indexedEmojis.filter((emoji) => emoji.category === category.key),\n }))\n .filter((category) => category.emojis.length > 0);\n\n for (const category of categorizedEmojis) {\n const categoryRows = chunk(category.emojis, columns);\n const nextIndex = currentIndex + categoryRows.length;\n\n rows.push(...categoryRows);\n categoriesNames.push(category.name);\n categoriesRowCounts.push(categoryRows.length);\n categoriesRowIndices.push(\n generateRangeIndices(currentIndex, nextIndex - 1)\n );\n currentIndex = nextIndex;\n }\n\n return {\n count: emojis.length,\n rows,\n categories: categoriesNames,\n categoriesRowCounts,\n categoriesRowIndices,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var reactSlot = require('@radix-ui/react-slot');
|
|
5
|
+
var React = require('react');
|
|
6
|
+
var formatFileSize = require('../utils/format-file-size.js');
|
|
7
|
+
|
|
8
|
+
const FILE_SIZE_NAME = "FileSize";
|
|
9
|
+
const FileSize = React.forwardRef(
|
|
10
|
+
({
|
|
11
|
+
size,
|
|
12
|
+
locale,
|
|
13
|
+
children: renderChildren = formatFileSize.formatFileSize,
|
|
14
|
+
asChild,
|
|
15
|
+
...props
|
|
16
|
+
}, forwardedRef) => {
|
|
17
|
+
const Component = asChild ? reactSlot.Slot : "span";
|
|
18
|
+
const children = React.useMemo(
|
|
19
|
+
() => typeof renderChildren === "function" ? renderChildren(size, locale) : renderChildren,
|
|
20
|
+
[renderChildren, size]
|
|
21
|
+
);
|
|
22
|
+
return /* @__PURE__ */ React.createElement(Component, {
|
|
23
|
+
...props,
|
|
24
|
+
ref: forwardedRef
|
|
25
|
+
}, children);
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
if (process.env.NODE_ENV !== "production") {
|
|
29
|
+
FileSize.displayName = FILE_SIZE_NAME;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
exports.FileSize = FileSize;
|
|
33
|
+
//# sourceMappingURL=FileSize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileSize.js","sources":["../../src/primitives/FileSize.tsx"],"sourcesContent":["\"use client\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport type { ReactNode } from \"react\";\nimport React, { forwardRef, useMemo } from \"react\";\n\nimport type { ComponentPropsWithSlot } from \"../types\";\nimport { formatFileSize } from \"../utils/format-file-size\";\n\nconst FILE_SIZE_NAME = \"FileSize\";\n\nexport interface FileSizeProps\n extends Omit<ComponentPropsWithSlot<\"span\">, \"children\"> {\n /**\n * The file size to display.\n */\n size: number;\n\n /**\n * A function to format the displayed file size.\n */\n children?: (size: number, locale?: string) => ReactNode;\n\n /**\n * The locale used when formatting the file size.\n */\n locale?: string;\n}\n\n/**\n * Displays a formatted file size.\n *\n * @example\n * <FileSize size={100000} />\n */\nexport const FileSize = forwardRef<HTMLSpanElement, FileSizeProps>(\n (\n {\n size,\n locale,\n children: renderChildren = formatFileSize,\n asChild,\n ...props\n },\n forwardedRef\n ) => {\n const Component = asChild ? Slot : \"span\";\n const children = useMemo(\n () =>\n typeof renderChildren === \"function\"\n ? renderChildren(size, locale)\n : renderChildren,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [renderChildren, size]\n );\n\n return (\n <Component {...props} ref={forwardedRef}>\n {children}\n </Component>\n );\n }\n);\n\nif (process.env.NODE_ENV !== \"production\") {\n FileSize.displayName = FILE_SIZE_NAME;\n}\n"],"names":[],"mappings":";;;;;;;AASA;AA0BO;AAAiB;AAEpB;AACE;AACA;AAC2B;AAC3B;AACG;AAIL;AACA;AAAiB;AAIT;AAEe;AAGvB;AACG;AAAc;AAAY;AAE3B;AAGN;AAEA;AACE;AACF;;"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
3
|
+
import React__default, { forwardRef, useMemo } from 'react';
|
|
4
|
+
import { formatFileSize } from '../utils/format-file-size.mjs';
|
|
5
|
+
|
|
6
|
+
const FILE_SIZE_NAME = "FileSize";
|
|
7
|
+
const FileSize = forwardRef(
|
|
8
|
+
({
|
|
9
|
+
size,
|
|
10
|
+
locale,
|
|
11
|
+
children: renderChildren = formatFileSize,
|
|
12
|
+
asChild,
|
|
13
|
+
...props
|
|
14
|
+
}, forwardedRef) => {
|
|
15
|
+
const Component = asChild ? Slot : "span";
|
|
16
|
+
const children = useMemo(
|
|
17
|
+
() => typeof renderChildren === "function" ? renderChildren(size, locale) : renderChildren,
|
|
18
|
+
[renderChildren, size]
|
|
19
|
+
);
|
|
20
|
+
return /* @__PURE__ */ React__default.createElement(Component, {
|
|
21
|
+
...props,
|
|
22
|
+
ref: forwardedRef
|
|
23
|
+
}, children);
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
if (process.env.NODE_ENV !== "production") {
|
|
27
|
+
FileSize.displayName = FILE_SIZE_NAME;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { FileSize };
|
|
31
|
+
//# sourceMappingURL=FileSize.mjs.map
|