@fibery/ui-kit 1.38.0 → 1.38.2
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 +19 -0
- package/config/jest/testFrameworkSetup.js +1 -1
- package/package.json +23 -22
- 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 +4 -4
- package/src/button/icon-button.tsx +3 -3
- package/src/card-container.tsx +3 -2
- package/src/checkbox.tsx +17 -0
- package/src/collapsible/index.tsx +4 -2
- 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 +26 -1
- 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 +2 -29
- package/src/file-item-2.tsx +566 -0
- package/src/file-item.tsx +196 -162
- 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/FileArchive.ts +8 -0
- package/src/icons/ast/FileBroken.ts +8 -0
- package/src/icons/ast/FileDocument.ts +8 -0
- package/src/icons/ast/FileImage.ts +8 -0
- package/src/icons/ast/FilePresentation.ts +8 -0
- package/src/icons/ast/FileTable.ts +8 -0
- package/src/icons/ast/FileUpload.ts +1 -1
- package/src/icons/ast/FileVideo.ts +8 -0
- 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 +11 -0
- package/src/icons/react/FileArchive.tsx +13 -0
- package/src/icons/react/FileBroken.tsx +13 -0
- package/src/icons/react/FileDocument.tsx +13 -0
- package/src/icons/react/FileImage.tsx +13 -0
- package/src/icons/react/FilePresentation.tsx +13 -0
- package/src/icons/react/FileTable.tsx +13 -0
- package/src/icons/react/FileVideo.tsx +13 -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 +11 -0
- package/src/icons/svg/back.svg +3 -1
- package/src/icons/svg/extension/files.svg +3 -1
- package/src/icons/svg/file-archive.svg +3 -0
- package/src/icons/svg/file-broken.svg +3 -0
- package/src/icons/svg/file-document.svg +3 -0
- package/src/icons/svg/file-image.svg +3 -0
- package/src/icons/svg/file-presentation.svg +3 -0
- package/src/icons/svg/file-table.svg +3 -0
- package/src/icons/svg/file-upload.svg +3 -6
- package/src/icons/svg/file-video.svg +3 -0
- 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 +522 -0
- package/src/images-gallery-2/slide-buttons.tsx +271 -0
- package/src/images-gallery-2/zoom.tsx +35 -0
- package/src/kbd.tsx +46 -0
- package/src/loading-sausage.tsx +2 -2
- 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 +28 -19
- package/src/type-badge.tsx +5 -2
- package/src/unit/unit-with-tooltip.tsx +1 -1
- package/src/use-is-phone.tsx +34 -6
- package/src/shortcut-badge.tsx +0 -29
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
weekendClassName,
|
|
20
20
|
} from "./styles";
|
|
21
21
|
import {getWeekendsForMonth} from "./get-weekends-for-month";
|
|
22
|
+
import {mobileRootSelector} from "../mobile-styles";
|
|
22
23
|
|
|
23
24
|
export const sortDates = ({from, to}: {from: Date; to: Date}) => {
|
|
24
25
|
const [sortedFrom, sortedTo] = [from, to].sort((a, b) => a.getTime() - b.getTime());
|
|
@@ -108,19 +109,36 @@ export const DateRangePickerPopupContent = forwardRef<
|
|
|
108
109
|
: null;
|
|
109
110
|
|
|
110
111
|
const footer = duration ? (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
112
|
+
<>
|
|
113
|
+
<hr
|
|
114
|
+
className={css`
|
|
115
|
+
display: none;
|
|
116
|
+
margin: 0 ${-space.s12}px;
|
|
117
|
+
border: none;
|
|
118
|
+
border-bottom: ${themeVars.separators.opacity5};
|
|
119
|
+
${mobileRootSelector} & {
|
|
120
|
+
display: block;
|
|
121
|
+
}
|
|
122
|
+
`}
|
|
123
|
+
/>
|
|
124
|
+
<div
|
|
125
|
+
className={css`
|
|
126
|
+
background-color: ${themeVars.inputDisabledBgColor};
|
|
127
|
+
border-radius: ${border.radius6}px;
|
|
128
|
+
padding: ${space.s4}px ${space.s8}px;
|
|
129
|
+
${textStyles.small}
|
|
130
|
+
text-align: center;
|
|
131
|
+
color: ${themeVars.disabledTextColor};
|
|
132
|
+
margin-top: ${space.s12}px;
|
|
133
|
+
${mobileRootSelector} & {
|
|
134
|
+
${textStyles.big}
|
|
135
|
+
color: ${themeVars.disabledTextColor};
|
|
136
|
+
}
|
|
137
|
+
`}
|
|
138
|
+
>
|
|
139
|
+
{duration}
|
|
140
|
+
</div>
|
|
141
|
+
</>
|
|
124
142
|
) : null;
|
|
125
143
|
|
|
126
144
|
const placeholder = useRef<string>(`e.g. ${getRandomPlaceholder(showTime, true)}`);
|
|
@@ -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],
|
|
@@ -281,10 +299,11 @@ export const themeColors = {
|
|
|
281
299
|
],
|
|
282
300
|
entityNodeBgColor: [slate.slate2, slateDark.slate3],
|
|
283
301
|
shortcutTextColor: [slate.slate9, slateDark.slate11],
|
|
284
|
-
|
|
302
|
+
shortcutBorder: [
|
|
285
303
|
`1px solid ${getOpacities(slate.slate8).opacity50}`,
|
|
286
304
|
`1px solid ${getOpacities(slateDark.slate10).opacity20}`,
|
|
287
305
|
],
|
|
306
|
+
shortcutBorderColor: [getOpacities(slate.slate8).opacity50, getOpacities(slateDark.slate10).opacity20],
|
|
288
307
|
|
|
289
308
|
// Input
|
|
290
309
|
inputBgColor: [whiteA.whiteA0, slateDark.slate2],
|
|
@@ -575,6 +594,11 @@ export const themeColors = {
|
|
|
575
594
|
// Drag and drop
|
|
576
595
|
colorBgDropLine: [indigo.indigo8, indigoDark.indigo8],
|
|
577
596
|
|
|
597
|
+
// Views
|
|
598
|
+
viewBg: [slate.slate1, slateDark.slate1],
|
|
599
|
+
viewSecondaryBg: [slate.slate2, slateDark.slate2],
|
|
600
|
+
viewHighlightBg: [indigo.indigo3, indigoDark.indigo3],
|
|
601
|
+
|
|
578
602
|
// Board
|
|
579
603
|
boardBg: [slate.slate1, slateDark.slate1],
|
|
580
604
|
boardBgWithOpacity80: [getOpacities(slate.slate1).opacity80, getOpacities(slateDark.slate1).opacity80],
|
|
@@ -972,6 +996,7 @@ export const space = {
|
|
|
972
996
|
s44: 44,
|
|
973
997
|
s48: 48,
|
|
974
998
|
s56: 56,
|
|
999
|
+
s60: 60,
|
|
975
1000
|
s64: 64,
|
|
976
1001
|
s80: 80,
|
|
977
1002
|
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;
|
|
@@ -64,7 +38,7 @@ const mouths = [
|
|
|
64
38
|
`<svg xmlns="http://www.w3.org/2000/svg" width="32" height="16" viewBox="0 0 32 16" fill="none"><g clip-path="url(#clip0_31_1134)"><path d="M4.23177 12.4853C2.41601 11.1761 1.06315 9.59547 0.249133 7.87572C-0.702621 5.86498 1.22002 4 3.51791 4L7 4C7.55229 4 8 4.44772 8 5V13.0522C8 13.7579 7.28869 14.2398 6.6548 13.9296C5.79179 13.5074 4.97984 13.0247 4.23177 12.4853Z" fill="currentColor"/><path d="M31.7509 7.87572C30.9369 9.59547 29.584 11.1761 27.7682 12.4853C27.0202 13.0247 26.2082 13.5074 25.3452 13.9296C24.7113 14.2398 24 13.7579 24 13.0522L24 5C24 4.44772 24.4477 4 25 4L28.4821 4C30.78 4 32.7026 5.86498 31.7509 7.87572Z" fill="currentColor"/><path d="M16 16C14.564 16 13.1472 15.8662 11.7816 15.6082C11.3227 15.5215 11 15.1143 11 14.6473V5C11 4.44772 11.4477 4 12 4L20 4C20.5523 4 21 4.44772 21 5V14.6473C21 15.1143 20.6773 15.5215 20.2184 15.6082C18.8528 15.8662 17.436 16 16 16Z" fill="currentColor"/></g><defs><clipPath id="clip0_31_1134"><rect width="32" height="16" fill="white"/></clipPath></defs></svg>`,
|
|
65
39
|
];
|
|
66
40
|
|
|
67
|
-
const getColors = _.memoize((v: string) => {
|
|
41
|
+
export const getColors = _.memoize((v: string) => {
|
|
68
42
|
const idx = Math.floor((cyrb53(v) / Math.pow(2, 53)) * colors.length);
|
|
69
43
|
return colors[idx];
|
|
70
44
|
});
|
|
@@ -84,7 +58,6 @@ interface FibermojiPlaceholderProps {
|
|
|
84
58
|
|
|
85
59
|
export const FibermojiPlaceholder: FC<FibermojiPlaceholderProps> = ({size, radius = "50%", title}) => {
|
|
86
60
|
const eyes = useRef<HTMLDivElement>(null);
|
|
87
|
-
|
|
88
61
|
const [fg, bg] = getColors(title ?? "unknown");
|
|
89
62
|
const mouth = getMouth(title ?? "unknown");
|
|
90
63
|
const letters = abbreviateName(title).split("");
|