@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.
Files changed (111) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/config/jest/testFrameworkSetup.js +1 -1
  3. package/package.json +23 -22
  4. package/src/abbreviate-name.ts +42 -0
  5. package/src/actions-menu/actions-menu-item.tsx +14 -5
  6. package/src/actions-menu/actions-menu-props.tsx +1 -0
  7. package/src/actions-menu/actions-menu.tsx +4 -1
  8. package/src/actions-menu/context-actions-menu.tsx +22 -0
  9. package/src/animated-height-container.tsx +24 -5
  10. package/src/antd/ant-upload.tsx +1 -1
  11. package/src/antd/input.tsx +4 -0
  12. package/src/avatar.tsx +1 -27
  13. package/src/button/base-button.tsx +2 -0
  14. package/src/button/button.tsx +4 -4
  15. package/src/button/icon-button.tsx +3 -3
  16. package/src/card-container.tsx +3 -2
  17. package/src/checkbox.tsx +17 -0
  18. package/src/collapsible/index.tsx +4 -2
  19. package/src/collapsible-section.tsx +3 -1
  20. package/src/date-picker/autocomplete.tsx +11 -5
  21. package/src/date-picker/date-range-input.tsx +5 -1
  22. package/src/date-picker/date-range-picker-popup-content.tsx +31 -13
  23. package/src/date-picker/single-date-input.tsx +5 -1
  24. package/src/date-picker/styles.ts +20 -0
  25. package/src/design-system.ts +26 -1
  26. package/src/dropdown-menu/index.tsx +11 -1
  27. package/src/emoji-picker/emoji-picker-preview-footer.tsx +4 -0
  28. package/src/emoji-picker/emoji.tsx +4 -3
  29. package/src/emoji-picker/primitives/emoji.tsx +49 -51
  30. package/src/emoji-picker/primitives/footer.tsx +6 -0
  31. package/src/emoji-picker/primitives/search.tsx +8 -0
  32. package/src/emoji-picker/primitives/skin-tone.tsx +12 -2
  33. package/src/fibermoji-placeholder.tsx +2 -29
  34. package/src/file-item-2.tsx +566 -0
  35. package/src/file-item.tsx +196 -162
  36. package/src/header-layout.tsx +11 -0
  37. package/src/html-styles.ts +13 -4
  38. package/src/icons/ast/Back.ts +1 -1
  39. package/src/icons/ast/ExtensionFiles.ts +1 -1
  40. package/src/icons/ast/FileArchive.ts +8 -0
  41. package/src/icons/ast/FileBroken.ts +8 -0
  42. package/src/icons/ast/FileDocument.ts +8 -0
  43. package/src/icons/ast/FileImage.ts +8 -0
  44. package/src/icons/ast/FilePresentation.ts +8 -0
  45. package/src/icons/ast/FileTable.ts +8 -0
  46. package/src/icons/ast/FileUpload.ts +1 -1
  47. package/src/icons/ast/FileVideo.ts +8 -0
  48. package/src/icons/ast/SwitchToMention.ts +8 -0
  49. package/src/icons/ast/SwitchToText.ts +8 -0
  50. package/src/icons/ast/SwitchToWidget.ts +8 -0
  51. package/src/icons/ast/ViewGallery.ts +8 -0
  52. package/src/icons/ast/index.tsx +11 -0
  53. package/src/icons/react/FileArchive.tsx +13 -0
  54. package/src/icons/react/FileBroken.tsx +13 -0
  55. package/src/icons/react/FileDocument.tsx +13 -0
  56. package/src/icons/react/FileImage.tsx +13 -0
  57. package/src/icons/react/FilePresentation.tsx +13 -0
  58. package/src/icons/react/FileTable.tsx +13 -0
  59. package/src/icons/react/FileVideo.tsx +13 -0
  60. package/src/icons/react/SwitchToMention.tsx +13 -0
  61. package/src/icons/react/SwitchToText.tsx +13 -0
  62. package/src/icons/react/SwitchToWidget.tsx +13 -0
  63. package/src/icons/react/ViewGallery.tsx +13 -0
  64. package/src/icons/react/index.tsx +11 -0
  65. package/src/icons/svg/back.svg +3 -1
  66. package/src/icons/svg/extension/files.svg +3 -1
  67. package/src/icons/svg/file-archive.svg +3 -0
  68. package/src/icons/svg/file-broken.svg +3 -0
  69. package/src/icons/svg/file-document.svg +3 -0
  70. package/src/icons/svg/file-image.svg +3 -0
  71. package/src/icons/svg/file-presentation.svg +3 -0
  72. package/src/icons/svg/file-table.svg +3 -0
  73. package/src/icons/svg/file-upload.svg +3 -6
  74. package/src/icons/svg/file-video.svg +3 -0
  75. package/src/icons/svg/switch-to-mention.svg +3 -0
  76. package/src/icons/svg/switch-to-text.svg +4 -0
  77. package/src/icons/svg/switch-to-widget.svg +4 -0
  78. package/src/icons/svg/view-gallery.svg +4 -0
  79. package/src/images-gallery/images-gallery-fall-through-provider.tsx +11 -0
  80. package/src/images-gallery/images-gallery.tsx +13 -10
  81. package/src/images-gallery/zoom.tsx +13 -2
  82. package/src/images-gallery-2/images-gallery-2.tsx +522 -0
  83. package/src/images-gallery-2/slide-buttons.tsx +271 -0
  84. package/src/images-gallery-2/zoom.tsx +35 -0
  85. package/src/kbd.tsx +46 -0
  86. package/src/loading-sausage.tsx +2 -2
  87. package/src/modal-menu/modal-menu-item.tsx +10 -2
  88. package/src/modal-menu/modal-menu-trigger.tsx +19 -2
  89. package/src/notification-dot.tsx +16 -7
  90. package/src/platform-symbols.ts +9 -0
  91. package/src/platform.ts +2 -0
  92. package/src/popover/index.tsx +31 -8
  93. package/src/popover/modifiers.tsx +26 -19
  94. package/src/reactions/reaction-button.tsx +323 -101
  95. package/src/reactions/reaction-picker.tsx +14 -1
  96. package/src/reactions/reactions.tsx +11 -1
  97. package/src/reactions/tootltip.tsx +55 -0
  98. package/src/rich-text-embed-error.tsx +2 -1
  99. package/src/select/components/group-heading.tsx +8 -0
  100. package/src/select/components/menu-list-virtualized.tsx +6 -2
  101. package/src/select/components/option.tsx +4 -0
  102. package/src/select/select-control-settings-context.tsx +11 -2
  103. package/src/select/select-in-popover.tsx +10 -7
  104. package/src/select/styles.ts +21 -1
  105. package/src/tab-nav/tab-nav.tsx +1 -1
  106. package/src/toggle.tsx +8 -0
  107. package/src/tooltip.tsx +28 -19
  108. package/src/type-badge.tsx +5 -2
  109. package/src/unit/unit-with-tooltip.tsx +1 -1
  110. package/src/use-is-phone.tsx +34 -6
  111. 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
- <div
112
- className={css`
113
- background-color: ${themeVars.inputDisabledBgColor};
114
- border-radius: ${border.radius6}px;
115
- padding: ${space.s4}px ${space.s8}px;
116
- ${textStyles.small}
117
- text-align: center;
118
- color: ${themeVars.disabledTextColor};
119
- margin-top: ${space.s12}px;
120
- `}
121
- >
122
- {duration}
123
- </div>
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
  }
@@ -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
- shortcutBorderColor: [
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 = DropdownMenuPrimitive.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: React.FC<EmojiPrimitiveProps> = (props) => {
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 {FC} from "react";
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: FC<EmojiProps> = ({
62
- emoji: idOrColons,
63
- size,
64
- version = 14,
65
- fallback = "hidden",
66
- skin,
67
- native,
68
- showTitle = false,
69
- }) => {
70
- const emoji = useEmojiDataStoreSelector((store) => store.get(idOrColons, {skin}));
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
- let emojiNode: React.ReactNode;
71
+ let emojiNode: React.ReactNode;
77
72
 
78
- if ("native" in emoji) {
79
- if (native && version >= emoji.version) {
80
- emojiNode = emoji.native;
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={emptyPixel}
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
- const style = size ? {fontSize: size, width: size, height: size} : {};
102
+ const style = size ? {fontSize: size, width: size, height: size} : {};
108
103
 
109
- return (
110
- <span
111
- style={style}
112
- title={showTitle ? getTitle(emoji) : undefined}
113
- className={cx(emojiWrapperCss, size && emojiWrapperSizedCss)}
114
- aria-label={emoji.name}
115
- >
116
- {emojiNode}
117
- </span>
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("");