@fibery/ui-kit 1.38.0 → 1.38.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/config/jest/testFrameworkSetup.js +1 -1
- package/package.json +16 -15
- package/src/abbreviate-name.ts +42 -0
- package/src/actions-menu/actions-menu-item.tsx +14 -5
- package/src/actions-menu/actions-menu-props.tsx +1 -0
- package/src/actions-menu/actions-menu.tsx +4 -1
- package/src/actions-menu/context-actions-menu.tsx +22 -0
- package/src/animated-height-container.tsx +24 -5
- package/src/antd/ant-upload.tsx +1 -1
- package/src/antd/input.tsx +4 -0
- package/src/avatar.tsx +1 -27
- package/src/button/base-button.tsx +2 -0
- package/src/button/button.tsx +3 -2
- package/src/button/icon-button.tsx +3 -3
- package/src/card-container.tsx +3 -2
- package/src/checkbox.tsx +17 -0
- package/src/collapsible-section.tsx +3 -1
- package/src/date-picker/autocomplete.tsx +11 -5
- package/src/date-picker/date-range-input.tsx +5 -1
- package/src/date-picker/date-range-picker-popup-content.tsx +31 -13
- package/src/date-picker/single-date-input.tsx +5 -1
- package/src/date-picker/styles.ts +20 -0
- package/src/design-system.ts +24 -0
- package/src/dropdown-menu/index.tsx +11 -1
- package/src/emoji-picker/emoji-picker-preview-footer.tsx +4 -0
- package/src/emoji-picker/emoji.tsx +4 -3
- package/src/emoji-picker/primitives/emoji.tsx +49 -51
- package/src/emoji-picker/primitives/footer.tsx +6 -0
- package/src/emoji-picker/primitives/search.tsx +8 -0
- package/src/emoji-picker/primitives/skin-tone.tsx +12 -2
- package/src/fibermoji-placeholder.tsx +1 -27
- package/src/file-item-2.tsx +408 -0
- package/src/file-item.tsx +63 -12
- package/src/header-layout.tsx +11 -0
- package/src/html-styles.ts +13 -4
- package/src/icons/ast/Back.ts +1 -1
- package/src/icons/ast/ExtensionFiles.ts +1 -1
- package/src/icons/ast/FileUpload.ts +1 -1
- package/src/icons/ast/SwitchToMention.ts +8 -0
- package/src/icons/ast/SwitchToText.ts +8 -0
- package/src/icons/ast/SwitchToWidget.ts +8 -0
- package/src/icons/ast/ViewGallery.ts +8 -0
- package/src/icons/ast/index.tsx +4 -0
- package/src/icons/react/SwitchToMention.tsx +13 -0
- package/src/icons/react/SwitchToText.tsx +13 -0
- package/src/icons/react/SwitchToWidget.tsx +13 -0
- package/src/icons/react/ViewGallery.tsx +13 -0
- package/src/icons/react/index.tsx +4 -0
- package/src/icons/svg/back.svg +3 -1
- package/src/icons/svg/extension/files.svg +3 -1
- package/src/icons/svg/file-upload.svg +3 -6
- package/src/icons/svg/switch-to-mention.svg +3 -0
- package/src/icons/svg/switch-to-text.svg +4 -0
- package/src/icons/svg/switch-to-widget.svg +4 -0
- package/src/icons/svg/view-gallery.svg +4 -0
- package/src/images-gallery/images-gallery-fall-through-provider.tsx +11 -0
- package/src/images-gallery/images-gallery.tsx +13 -10
- package/src/images-gallery/zoom.tsx +13 -2
- package/src/images-gallery-2/images-gallery-2.tsx +442 -0
- package/src/images-gallery-2/slide-buttons.tsx +230 -0
- package/src/images-gallery-2/zoom.tsx +35 -0
- package/src/kbd.tsx +46 -0
- package/src/modal-menu/modal-menu-item.tsx +10 -2
- package/src/modal-menu/modal-menu-trigger.tsx +19 -2
- package/src/notification-dot.tsx +16 -7
- package/src/platform-symbols.ts +9 -0
- package/src/platform.ts +2 -0
- package/src/popover/index.tsx +31 -8
- package/src/popover/modifiers.tsx +26 -19
- package/src/reactions/reaction-button.tsx +323 -101
- package/src/reactions/reaction-picker.tsx +14 -1
- package/src/reactions/reactions.tsx +11 -1
- package/src/reactions/tootltip.tsx +55 -0
- package/src/rich-text-embed-error.tsx +2 -1
- package/src/select/components/group-heading.tsx +8 -0
- package/src/select/components/menu-list-virtualized.tsx +6 -2
- package/src/select/components/option.tsx +4 -0
- package/src/select/select-control-settings-context.tsx +11 -2
- package/src/select/select-in-popover.tsx +10 -7
- package/src/select/styles.ts +21 -1
- package/src/tab-nav/tab-nav.tsx +1 -1
- package/src/toggle.tsx +8 -0
- package/src/tooltip.tsx +27 -18
- package/src/type-badge.tsx +5 -2
- package/src/unit/unit-with-tooltip.tsx +1 -1
- package/src/use-is-phone.tsx +27 -6
- package/src/shortcut-badge.tsx +0 -29
|
@@ -6,6 +6,7 @@ import {AntTransparentInput} from "../antd/input";
|
|
|
6
6
|
import {inputOverrides} from "../antd/styles";
|
|
7
7
|
import {space} from "../design-system";
|
|
8
8
|
import {IconButton} from "../button/icon-button";
|
|
9
|
+
import {mobileRootSelector} from "../mobile-styles";
|
|
9
10
|
import RemoveIcon from "../icons/react/Remove";
|
|
10
11
|
import {AutoComplete, OnChangeArgs} from "./autocomplete";
|
|
11
12
|
import {InputRef} from "./rc-input-types";
|
|
@@ -192,6 +193,9 @@ export const SingleDateInput = forwardRef<
|
|
|
192
193
|
display: flex;
|
|
193
194
|
margin-bottom: ${space.s12 + space.s6}px;
|
|
194
195
|
padding-right: ${space.s12 - 2}px;
|
|
196
|
+
${mobileRootSelector} & {
|
|
197
|
+
min-height: ${space.s44}px;
|
|
198
|
+
}
|
|
195
199
|
`,
|
|
196
200
|
{[selectedStyle]: selected, [disabledStyle]: disabled}
|
|
197
201
|
)}
|
|
@@ -228,7 +232,7 @@ export const SingleDateInput = forwardRef<
|
|
|
228
232
|
/>
|
|
229
233
|
</div>
|
|
230
234
|
{allowClear && inputValue !== "" && (
|
|
231
|
-
<IconButton onClick={onClear} size={"tiny"}>
|
|
235
|
+
<IconButton onClick={onClear} size={"tiny"} supportMobile>
|
|
232
236
|
<RemoveIcon />
|
|
233
237
|
</IconButton>
|
|
234
238
|
)}
|
|
@@ -156,6 +156,10 @@ export const datePickerStylesOverrideClassName = css`
|
|
|
156
156
|
position: relative;
|
|
157
157
|
|
|
158
158
|
margin: 0;
|
|
159
|
+
|
|
160
|
+
${mobileRootSelector} & {
|
|
161
|
+
--rdp-cell-size: 44px;
|
|
162
|
+
}
|
|
159
163
|
}
|
|
160
164
|
|
|
161
165
|
padding: ${space.s12}px;
|
|
@@ -171,6 +175,9 @@ export const datePickerStylesOverrideClassName = css`
|
|
|
171
175
|
border: none;
|
|
172
176
|
color: ${themeVars.textColor};
|
|
173
177
|
border-radius: 0;
|
|
178
|
+
${mobileRootSelector} & {
|
|
179
|
+
${textStyles.big}
|
|
180
|
+
}
|
|
174
181
|
}
|
|
175
182
|
|
|
176
183
|
.rdp-day:focus {
|
|
@@ -237,6 +244,14 @@ export const datePickerStylesOverrideClassName = css`
|
|
|
237
244
|
.rdp-head th {
|
|
238
245
|
${textStyles.small};
|
|
239
246
|
color: ${themeVars.disabledTextColor};
|
|
247
|
+
${mobileRootSelector} & {
|
|
248
|
+
${textStyles.regular}
|
|
249
|
+
color: ${themeVars.accentTextColor};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
${mobileRootSelector} & .rdp-caption {
|
|
254
|
+
margin: ${space.s8}px 0;
|
|
240
255
|
}
|
|
241
256
|
|
|
242
257
|
.rdp-caption_label {
|
|
@@ -252,6 +267,11 @@ export const datePickerStylesOverrideClassName = css`
|
|
|
252
267
|
padding: ${space.s6}px !important;
|
|
253
268
|
}
|
|
254
269
|
|
|
270
|
+
${mobileRootSelector} & .rdp-nav_button {
|
|
271
|
+
width: ${space.s44}px;
|
|
272
|
+
height: ${space.s44}px;
|
|
273
|
+
}
|
|
274
|
+
|
|
255
275
|
.rdp-nav_icon {
|
|
256
276
|
color: ${themeVars.textColor};
|
|
257
277
|
}
|
package/src/design-system.ts
CHANGED
|
@@ -33,6 +33,22 @@ export const fontWeight = {
|
|
|
33
33
|
bold: 700,
|
|
34
34
|
} as const;
|
|
35
35
|
|
|
36
|
+
// 300 basic, 310 experiment with a variable Inter
|
|
37
|
+
export const fontSize = {
|
|
38
|
+
xxl: 30,
|
|
39
|
+
xl: 24,
|
|
40
|
+
lg: 18,
|
|
41
|
+
md: 16,
|
|
42
|
+
sm: 15,
|
|
43
|
+
xs: 14,
|
|
44
|
+
xxs: 13,
|
|
45
|
+
xxxs: 12,
|
|
46
|
+
tiny: 11,
|
|
47
|
+
mini: 10,
|
|
48
|
+
micro: 9,
|
|
49
|
+
nano: 8,
|
|
50
|
+
} as const;
|
|
51
|
+
|
|
36
52
|
const transparent = "rgba(255, 255, 255, 0)";
|
|
37
53
|
|
|
38
54
|
export const minPanelWidth = 490;
|
|
@@ -246,6 +262,8 @@ export const themeColors = {
|
|
|
246
262
|
menuFooterHoverColor: [getOpacities(whiteA.whiteA0).opacity60, slateDark.slate4],
|
|
247
263
|
menuIconColor: [getOpacities(slate.slate12).opacity70, getOpacities(slateDark.slate12).opacity70],
|
|
248
264
|
menuSelectedIconColor: [getOpacities(slate.slate1).opacity90, getOpacities(slate.slate1).opacity90],
|
|
265
|
+
|
|
266
|
+
// Text, links colors
|
|
249
267
|
textColor: [slateDark.slate5, slate.slate6],
|
|
250
268
|
textSelectionColor: [getOpacities(blue.blue10).opacity20, getOpacities(blueDark.blue10).opacity40],
|
|
251
269
|
accentTextColor: [slate.slate10, slateDark.slate10],
|
|
@@ -575,6 +593,11 @@ export const themeColors = {
|
|
|
575
593
|
// Drag and drop
|
|
576
594
|
colorBgDropLine: [indigo.indigo8, indigoDark.indigo8],
|
|
577
595
|
|
|
596
|
+
// Views
|
|
597
|
+
viewBg: [slate.slate1, slateDark.slate1],
|
|
598
|
+
viewSecondaryBg: [slate.slate2, slateDark.slate2],
|
|
599
|
+
viewHighlightBg: [indigo.indigo3, indigoDark.indigo3],
|
|
600
|
+
|
|
578
601
|
// Board
|
|
579
602
|
boardBg: [slate.slate1, slateDark.slate1],
|
|
580
603
|
boardBgWithOpacity80: [getOpacities(slate.slate1).opacity80, getOpacities(slateDark.slate1).opacity80],
|
|
@@ -972,6 +995,7 @@ export const space = {
|
|
|
972
995
|
s44: 44,
|
|
973
996
|
s48: 48,
|
|
974
997
|
s56: 56,
|
|
998
|
+
s60: 60,
|
|
975
999
|
s64: 64,
|
|
976
1000
|
s80: 80,
|
|
977
1001
|
s96: 96,
|
|
@@ -10,7 +10,17 @@ export const Root = (dropdownMenuProps: DropdownMenuPrimitive.DropdownMenuProps)
|
|
|
10
10
|
<DropdownMenuPrimitive.Root dir="ltr" modal={false} {...dropdownMenuProps} />
|
|
11
11
|
);
|
|
12
12
|
|
|
13
|
-
export const Trigger =
|
|
13
|
+
export const Trigger = forwardRef<
|
|
14
|
+
HTMLButtonElement,
|
|
15
|
+
DropdownMenuPrimitive.DropdownMenuTriggerProps & {triggerEvent?: string}
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
17
|
+
>(({triggerEvent, className, children, ...otherProps}, ref) => {
|
|
18
|
+
return (
|
|
19
|
+
<DropdownMenuPrimitive.Trigger ref={ref} className={className} {...otherProps}>
|
|
20
|
+
{children}
|
|
21
|
+
</DropdownMenuPrimitive.Trigger>
|
|
22
|
+
);
|
|
23
|
+
});
|
|
14
24
|
|
|
15
25
|
const rowItemStyles = {
|
|
16
26
|
...textStyles.regular,
|
|
@@ -9,6 +9,7 @@ import {useEmojiPreview} from "./primitives/preview-provider";
|
|
|
9
9
|
import {useEmojiPickerCtx} from "./primitives/root";
|
|
10
10
|
import {useEmojiSkin} from "./primitives/skin-provider";
|
|
11
11
|
import {EmojiPickerSkinTone} from "./primitives/skin-tone";
|
|
12
|
+
import {mobileRootSelector} from "../mobile-styles";
|
|
12
13
|
|
|
13
14
|
const previewCss = css`
|
|
14
15
|
display: flex;
|
|
@@ -81,6 +82,9 @@ export const EmojiPickerPreviewFooter: React.FC<{
|
|
|
81
82
|
position: absolute;
|
|
82
83
|
top: 4px;
|
|
83
84
|
right: ${space.s12}px;
|
|
85
|
+
${mobileRootSelector} & {
|
|
86
|
+
top: 12px;
|
|
87
|
+
}
|
|
84
88
|
`}
|
|
85
89
|
style={{
|
|
86
90
|
right: space.s12 + measureScrollbar(),
|
|
@@ -2,8 +2,9 @@ import {isAndroid} from "../is-android";
|
|
|
2
2
|
import {Emoji as EmojiPrimitive, EmojiProps as EmojiPrimitiveProps} from "./primitives/emoji";
|
|
3
3
|
import {isApple} from "./utils/emoji-set";
|
|
4
4
|
import {detectEmojiSupportLevel} from "./utils/emoji-support";
|
|
5
|
+
import {forwardRef} from "react";
|
|
5
6
|
|
|
6
7
|
export type EmojiProps = EmojiPrimitiveProps;
|
|
7
|
-
export const Emoji
|
|
8
|
-
return <EmojiPrimitive version={detectEmojiSupportLevel()} native={isApple() || isAndroid()} {...props} />;
|
|
9
|
-
};
|
|
8
|
+
export const Emoji = forwardRef<HTMLSpanElement, EmojiPrimitiveProps>((props, ref) => {
|
|
9
|
+
return <EmojiPrimitive ref={ref} version={detectEmojiSupportLevel()} native={isApple() || isAndroid()} {...props} />;
|
|
10
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {forwardRef} from "react";
|
|
2
2
|
import {EmojiItem, EmojiSkin, NativeEmoji} from "@fibery/emoji-data";
|
|
3
3
|
import {css, cx} from "@linaria/core";
|
|
4
4
|
import {themeVars} from "../../design-system";
|
|
@@ -43,77 +43,75 @@ export type EmojiProps = {
|
|
|
43
43
|
emoji: string;
|
|
44
44
|
/** max supported version of emojis */
|
|
45
45
|
version?: number;
|
|
46
|
-
onClick?: (emoji: EmojiItem, event: React.MouseEvent) => void;
|
|
47
46
|
skin?: EmojiSkin;
|
|
48
47
|
/** render emoji as native unicode if possible */
|
|
49
48
|
native?: boolean;
|
|
50
49
|
fallback?: "shortcode" | "hidden";
|
|
51
50
|
showTitle?: boolean;
|
|
52
|
-
}
|
|
51
|
+
} & React.HTMLAttributes<HTMLSpanElement>;
|
|
53
52
|
|
|
54
|
-
function getTitle(emoji: EmojiItem) {
|
|
53
|
+
export function getTitle(emoji: EmojiItem) {
|
|
55
54
|
if ((emoji as NativeEmoji).native) {
|
|
56
55
|
return emoji.colons;
|
|
57
56
|
}
|
|
58
57
|
return `:${emoji.name}:`;
|
|
59
58
|
}
|
|
60
59
|
|
|
61
|
-
export const Emoji
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const config = useEmojiRenderConfig();
|
|
72
|
-
if (!emoji) {
|
|
73
|
-
return fallback === "shortcode" ? <>{idOrColons}</> : null;
|
|
74
|
-
}
|
|
60
|
+
export const Emoji = forwardRef<HTMLSpanElement, EmojiProps>(
|
|
61
|
+
(
|
|
62
|
+
{className, emoji: idOrColons, size, version = 14, fallback = "hidden", skin, native, showTitle = false, ...rest},
|
|
63
|
+
ref
|
|
64
|
+
) => {
|
|
65
|
+
const emoji = useEmojiDataStoreSelector((store) => store.get(idOrColons, {skin}));
|
|
66
|
+
const config = useEmojiRenderConfig();
|
|
67
|
+
if (!emoji) {
|
|
68
|
+
return fallback === "shortcode" ? <>{idOrColons}</> : null;
|
|
69
|
+
}
|
|
75
70
|
|
|
76
|
-
|
|
71
|
+
let emojiNode: React.ReactNode;
|
|
77
72
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
73
|
+
if ("native" in emoji) {
|
|
74
|
+
if (native && version >= emoji.version) {
|
|
75
|
+
emojiNode = emoji.native;
|
|
76
|
+
} else {
|
|
77
|
+
emojiNode = (
|
|
78
|
+
<img
|
|
79
|
+
alt={emoji.name}
|
|
80
|
+
className={cx(size ? emojiSizedImgCss : emojiInlineImgCss)}
|
|
81
|
+
src={emptyPixel}
|
|
82
|
+
style={{
|
|
83
|
+
backgroundImage: `url(${emoji.sprite.src})`,
|
|
84
|
+
backgroundSize: emoji.sprite.size,
|
|
85
|
+
backgroundPosition: emoji.sprite.position,
|
|
86
|
+
}}
|
|
87
|
+
/>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
81
90
|
} else {
|
|
82
91
|
emojiNode = (
|
|
83
92
|
<img
|
|
84
93
|
alt={emoji.name}
|
|
94
|
+
loading={config.loading}
|
|
95
|
+
draggable={config.draggable}
|
|
85
96
|
className={cx(size ? emojiSizedImgCss : emojiInlineImgCss)}
|
|
86
|
-
src={
|
|
87
|
-
style={{
|
|
88
|
-
backgroundImage: `url(${emoji.sprite.src})`,
|
|
89
|
-
backgroundSize: emoji.sprite.size,
|
|
90
|
-
backgroundPosition: emoji.sprite.position,
|
|
91
|
-
}}
|
|
97
|
+
src={emoji.imageUrl}
|
|
92
98
|
/>
|
|
93
99
|
);
|
|
94
100
|
}
|
|
95
|
-
} else {
|
|
96
|
-
emojiNode = (
|
|
97
|
-
<img
|
|
98
|
-
alt={emoji.name}
|
|
99
|
-
loading={config.loading}
|
|
100
|
-
draggable={config.draggable}
|
|
101
|
-
className={cx(size ? emojiSizedImgCss : emojiInlineImgCss)}
|
|
102
|
-
src={emoji.imageUrl}
|
|
103
|
-
/>
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
101
|
|
|
107
|
-
|
|
102
|
+
const style = size ? {fontSize: size, width: size, height: size} : {};
|
|
108
103
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
104
|
+
return (
|
|
105
|
+
<span
|
|
106
|
+
ref={ref}
|
|
107
|
+
style={style}
|
|
108
|
+
title={showTitle ? getTitle(emoji) : undefined}
|
|
109
|
+
className={cx(className, emojiWrapperCss, size && emojiWrapperSizedCss)}
|
|
110
|
+
aria-label={emoji.name}
|
|
111
|
+
{...rest}
|
|
112
|
+
>
|
|
113
|
+
{emojiNode}
|
|
114
|
+
</span>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
);
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import {css} from "@linaria/core";
|
|
2
2
|
import {space} from "../../design-system";
|
|
3
|
+
import {mobileRootSelector} from "../../mobile-styles";
|
|
3
4
|
|
|
4
5
|
const footerCss = css`
|
|
5
6
|
position: relative;
|
|
6
7
|
border-top: 1px solid var(--fibery-color-separatorColor);
|
|
7
8
|
padding: ${space.s6}px ${space.s12}px;
|
|
9
|
+
height: 40px;
|
|
8
10
|
|
|
9
11
|
display: flex;
|
|
10
12
|
align-items: center;
|
|
13
|
+
|
|
14
|
+
${mobileRootSelector} & {
|
|
15
|
+
height: 68px;
|
|
16
|
+
}
|
|
11
17
|
`;
|
|
12
18
|
|
|
13
19
|
export const EmojiPickerFooter: React.FC<React.PropsWithChildren> = ({children}) => {
|
|
@@ -12,6 +12,7 @@ import {useEmojiPickerCtx, useEmojiPickerI18N} from "./root";
|
|
|
12
12
|
import {useFoundEmojis, useSetFoundEmojis} from "./search-provider";
|
|
13
13
|
import {useEmojiSkin} from "./skin-provider";
|
|
14
14
|
import ClearInputFilled from "../../icons/react/ClearInputFilled";
|
|
15
|
+
import {mobileRootSelector} from "../../mobile-styles";
|
|
15
16
|
|
|
16
17
|
const searchCss = css`
|
|
17
18
|
${textStyles.regular}
|
|
@@ -27,6 +28,10 @@ const searchCss = css`
|
|
|
27
28
|
padding: 0 ${space.s4}px;
|
|
28
29
|
gap: ${space.s4}px;
|
|
29
30
|
|
|
31
|
+
${mobileRootSelector} & {
|
|
32
|
+
height: 40px;
|
|
33
|
+
}
|
|
34
|
+
|
|
30
35
|
/* For screenreaders only, via https://stackoverflow.com/a/19758620 */
|
|
31
36
|
& .sr-only {
|
|
32
37
|
position: absolute;
|
|
@@ -59,6 +64,9 @@ const searchInputCss = css`
|
|
|
59
64
|
|
|
60
65
|
const searchIconCss = css`
|
|
61
66
|
padding: ${space.s4}px;
|
|
67
|
+
${mobileRootSelector} & {
|
|
68
|
+
padding: ${space.s6}px;
|
|
69
|
+
}
|
|
62
70
|
`;
|
|
63
71
|
|
|
64
72
|
const extraActionSlotCss = css`
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import {EmojiSkin} from "@fibery/emoji-data";
|
|
2
2
|
import {css, cx} from "@linaria/core";
|
|
3
3
|
import {useState} from "react";
|
|
4
|
+
import {useIsPhone} from "../../use-is-phone";
|
|
4
5
|
import {IconButton} from "../../button/icon-button";
|
|
5
6
|
import {textStyles, themeVars} from "../../design-system";
|
|
7
|
+
import {mobileRootSelector} from "../../mobile-styles";
|
|
6
8
|
import {Emoji} from "./emoji";
|
|
7
9
|
import {useEmojiPickerCtx, useEmojiPickerI18N} from "./root";
|
|
8
10
|
import {useEmojiSkin, useSetEmojiSkin} from "./skin-provider";
|
|
@@ -44,6 +46,10 @@ const skinToneSwatchCss = css`
|
|
|
44
46
|
|
|
45
47
|
const expandedCss = css`
|
|
46
48
|
width: 32px;
|
|
49
|
+
|
|
50
|
+
${mobileRootSelector} & {
|
|
51
|
+
width: 44px;
|
|
52
|
+
}
|
|
47
53
|
`;
|
|
48
54
|
|
|
49
55
|
const openedSkinTextCss = css`
|
|
@@ -55,12 +61,17 @@ const openedSkinTextCss = css`
|
|
|
55
61
|
width: 98px;
|
|
56
62
|
color: ${themeVars.accentTextColor};
|
|
57
63
|
padding-left: 8px;
|
|
64
|
+
|
|
65
|
+
${mobileRootSelector} & {
|
|
66
|
+
display: none;
|
|
67
|
+
}
|
|
58
68
|
`;
|
|
59
69
|
|
|
60
70
|
export type EmojiPickerSkinToneProps = {
|
|
61
71
|
className?: string;
|
|
62
72
|
};
|
|
63
73
|
export const EmojiPickerSkinTone: React.FC<EmojiPickerSkinToneProps> = ({className}) => {
|
|
74
|
+
const isPhone = useIsPhone();
|
|
64
75
|
const [opened, setOpened] = useState(false);
|
|
65
76
|
const emojiPickerCtx = useEmojiPickerCtx();
|
|
66
77
|
const i18n = useEmojiPickerI18N();
|
|
@@ -75,14 +86,13 @@ export const EmojiPickerSkinTone: React.FC<EmojiPickerSkinToneProps> = ({classNa
|
|
|
75
86
|
skinToneNodes.push(
|
|
76
87
|
<span key={`skin-tone-${skinTone}`} className={cx(skinToneSwatchCss, (selected || opened) && expandedCss)}>
|
|
77
88
|
<IconButton
|
|
78
|
-
size="large"
|
|
89
|
+
size={isPhone ? "xLarge" : "large"}
|
|
79
90
|
onClick={() => {
|
|
80
91
|
if (opened) {
|
|
81
92
|
setSkin(skinTone as EmojiSkin);
|
|
82
93
|
}
|
|
83
94
|
setOpened(!opened);
|
|
84
95
|
}}
|
|
85
|
-
supportMobile
|
|
86
96
|
className={css`
|
|
87
97
|
&:hover:not(:disabled),
|
|
88
98
|
&:focus-visible {
|
|
@@ -3,33 +3,7 @@ import {css} from "@linaria/core";
|
|
|
3
3
|
import {FC, useEffect, useRef} from "react";
|
|
4
4
|
import {textStyles} from "./design-system";
|
|
5
5
|
import {useFeatures} from "./features";
|
|
6
|
-
|
|
7
|
-
const preservedNameEmojis = ["🤖", "👻", "🧮", "🪄", "🔌", "🔗", "🔒"];
|
|
8
|
-
|
|
9
|
-
const abbreviateName = (name?: string) => {
|
|
10
|
-
if (name === undefined) {
|
|
11
|
-
return "…";
|
|
12
|
-
}
|
|
13
|
-
if (preservedNameEmojis.includes(name)) {
|
|
14
|
-
return name;
|
|
15
|
-
}
|
|
16
|
-
const filteredName = (name || "").replace(/[!~.\-@[\]]/g, "").trim();
|
|
17
|
-
const match = filteredName.match(/\p{Letter}[\p{Letter} ]+/gu);
|
|
18
|
-
const processedName = match ? match[0] : "";
|
|
19
|
-
const parts = processedName.split(" ").filter((part) => part !== "");
|
|
20
|
-
let result;
|
|
21
|
-
if (parts.length === 1) {
|
|
22
|
-
result = processedName.slice(0, 2);
|
|
23
|
-
} else {
|
|
24
|
-
result = parts
|
|
25
|
-
.filter((part, index) => index < 2)
|
|
26
|
-
.map((part) => {
|
|
27
|
-
return part[0].toUpperCase();
|
|
28
|
-
})
|
|
29
|
-
.join("");
|
|
30
|
-
}
|
|
31
|
-
return result || "?";
|
|
32
|
-
};
|
|
6
|
+
import {abbreviateName} from "./abbreviate-name";
|
|
33
7
|
|
|
34
8
|
const cyrb53 = (str: string, seed = 0) => {
|
|
35
9
|
let h1 = 0xdeadbeef ^ seed;
|