@fibery/ui-kit 1.37.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.
Files changed (194) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/config/jest/testFrameworkSetup.js +1 -1
  3. package/package.json +20 -16
  4. package/src/abbreviate-name.ts +42 -0
  5. package/src/actions-menu/actions-menu-item.tsx +32 -11
  6. package/src/actions-menu/actions-menu-props.tsx +5 -0
  7. package/src/actions-menu/actions-menu-sub-command-menu.tsx +7 -4
  8. package/src/actions-menu/actions-menu-sub-menu.tsx +9 -3
  9. package/src/actions-menu/actions-menu.tsx +28 -9
  10. package/src/actions-menu/context-actions-menu.tsx +22 -0
  11. package/src/actions-panel.tsx +12 -2
  12. package/src/animated-height-container.tsx +24 -5
  13. package/src/antd/ant-upload.tsx +1 -1
  14. package/src/antd/input.tsx +4 -0
  15. package/src/avatar.tsx +1 -27
  16. package/src/axis-header.tsx +136 -76
  17. package/src/box.tsx +1 -1
  18. package/src/breadcrumb.tsx +78 -0
  19. package/src/button/actions-button-compact.tsx +4 -1
  20. package/src/button/base-button.tsx +7 -3
  21. package/src/button/button-group.tsx +1 -1
  22. package/src/button/button.tsx +33 -1
  23. package/src/button/icon-button.tsx +10 -1
  24. package/src/button/select-button.tsx +4 -0
  25. package/src/card-container.tsx +10 -6
  26. package/src/checkbox.tsx +17 -0
  27. package/src/collapsible-section.tsx +3 -1
  28. package/src/color-picker/swatch.tsx +1 -0
  29. package/src/command-menu/index.tsx +3 -3
  30. package/src/context-menu/index.tsx +10 -1
  31. package/src/date-picker/autocomplete.tsx +11 -5
  32. package/src/date-picker/date-range-input.tsx +5 -1
  33. package/src/date-picker/date-range-picker-popup-content.tsx +31 -13
  34. package/src/date-picker/date-range-picker.tsx +6 -3
  35. package/src/date-picker/relative-date-picker.tsx +6 -2
  36. package/src/date-picker/single-date-input.tsx +5 -1
  37. package/src/date-picker/single-date-picker.tsx +8 -5
  38. package/src/date-picker/styles.ts +52 -26
  39. package/src/date-picker/types.ts +3 -1
  40. package/src/day-select/day-select.tsx +21 -75
  41. package/src/day-select/iso-week-day-select.tsx +1 -1
  42. package/src/day-select/mount-day-select.tsx +2 -2
  43. package/src/day-select/week-day-select.tsx +1 -5
  44. package/src/design-system.ts +45 -12
  45. package/src/dropdown-menu/index.tsx +19 -2
  46. package/src/emoji-picker/app-icon-picker.tsx +6 -4
  47. package/src/emoji-picker/emoji-picker-preview-footer.tsx +5 -1
  48. package/src/emoji-picker/emoji-picker.tsx +3 -0
  49. package/src/emoji-picker/emoji.tsx +5 -3
  50. package/src/emoji-picker/icon-emoji-picker.tsx +10 -1
  51. package/src/emoji-picker/primitives/emoji.tsx +49 -51
  52. package/src/emoji-picker/primitives/footer.tsx +5 -0
  53. package/src/emoji-picker/primitives/search.tsx +8 -0
  54. package/src/emoji-picker/primitives/skin-tone.tsx +12 -1
  55. package/src/emoji-picker/use-responsive-emoji-size.ts +11 -0
  56. package/src/emoji-picker/utils/emoji-set.ts +2 -1
  57. package/src/empty-state/empty-state.tsx +6 -0
  58. package/src/fibermoji-placeholder.tsx +1 -27
  59. package/src/field-icon.tsx +4 -1
  60. package/src/file-item-2.tsx +408 -0
  61. package/src/file-item.tsx +215 -47
  62. package/src/header-layout.tsx +11 -0
  63. package/src/html-styles.ts +21 -4
  64. package/src/icons/ast/ActivityFilled.ts +8 -0
  65. package/src/icons/ast/AiAssistantFilled.ts +8 -0
  66. package/src/icons/ast/Back.ts +1 -1
  67. package/src/icons/ast/CollapseAllHorizontal.ts +8 -0
  68. package/src/icons/ast/DateRange.ts +1 -1
  69. package/src/icons/ast/EntityCreateFilled.ts +8 -0
  70. package/src/icons/ast/ExpandAllHorizontal.ts +8 -0
  71. package/src/icons/ast/ExtensionFiles.ts +1 -1
  72. package/src/icons/ast/FileUpload.ts +1 -1
  73. package/src/icons/ast/GlobeUnpublish.ts +8 -0
  74. package/src/icons/ast/HomeFilled.ts +8 -0
  75. package/src/icons/ast/KeyboardHideDown.ts +8 -0
  76. package/src/icons/ast/LayoutMultiple.ts +8 -0
  77. package/src/icons/ast/RicheditorHistoryRedo.ts +1 -1
  78. package/src/icons/ast/RicheditorHistoryUndo.ts +1 -1
  79. package/src/icons/ast/SearchFilled.ts +8 -0
  80. package/src/icons/ast/SettingsFilled.ts +8 -0
  81. package/src/icons/ast/SlideMenuFilled.ts +8 -0
  82. package/src/icons/ast/SwitchToMention.ts +8 -0
  83. package/src/icons/ast/SwitchToText.ts +8 -0
  84. package/src/icons/ast/SwitchToWidget.ts +8 -0
  85. package/src/icons/ast/TypeDate.ts +1 -1
  86. package/src/icons/ast/ViewGallery.ts +8 -0
  87. package/src/icons/ast/index.tsx +16 -0
  88. package/src/icons/react/ActivityFilled.tsx +13 -0
  89. package/src/icons/react/AiAssistantFilled.tsx +13 -0
  90. package/src/icons/react/CollapseAllHorizontal.tsx +13 -0
  91. package/src/icons/react/EntityCreateFilled.tsx +13 -0
  92. package/src/icons/react/ExpandAllHorizontal.tsx +13 -0
  93. package/src/icons/react/GlobeUnpublish.tsx +13 -0
  94. package/src/icons/react/HomeFilled.tsx +13 -0
  95. package/src/icons/react/KeyboardHideDown.tsx +13 -0
  96. package/src/icons/react/LayoutMultiple.tsx +13 -0
  97. package/src/icons/react/SearchFilled.tsx +13 -0
  98. package/src/icons/react/SettingsFilled.tsx +13 -0
  99. package/src/icons/react/SlideMenuFilled.tsx +13 -0
  100. package/src/icons/react/SwitchToMention.tsx +13 -0
  101. package/src/icons/react/SwitchToText.tsx +13 -0
  102. package/src/icons/react/SwitchToWidget.tsx +13 -0
  103. package/src/icons/react/ViewGallery.tsx +13 -0
  104. package/src/icons/react/index.tsx +16 -0
  105. package/src/icons/svg/activity-filled.svg +4 -0
  106. package/src/icons/svg/ai-assistant-filled.svg +3 -0
  107. package/src/icons/svg/back.svg +3 -1
  108. package/src/icons/svg/collapse-all-horizontal.svg +3 -0
  109. package/src/icons/svg/date-range.svg +3 -3
  110. package/src/icons/svg/entity-create-filled.svg +4 -0
  111. package/src/icons/svg/expand-all-horizontal.svg +3 -0
  112. package/src/icons/svg/extension/files.svg +3 -1
  113. package/src/icons/svg/file-upload.svg +3 -6
  114. package/src/icons/svg/globe-unpublish.svg +4 -0
  115. package/src/icons/svg/home-filled.svg +3 -0
  116. package/src/icons/svg/keyboard-hide-down.svg +1 -0
  117. package/src/icons/svg/layout-multiple.svg +3 -0
  118. package/src/icons/svg/richeditor/history/redo.svg +3 -2
  119. package/src/icons/svg/richeditor/history/undo.svg +3 -2
  120. package/src/icons/svg/search-filled.svg +3 -0
  121. package/src/icons/svg/settings-filled.svg +3 -0
  122. package/src/icons/svg/slide-menu-filled.svg +1 -0
  123. package/src/icons/svg/switch-to-mention.svg +3 -0
  124. package/src/icons/svg/switch-to-text.svg +4 -0
  125. package/src/icons/svg/switch-to-widget.svg +4 -0
  126. package/src/icons/svg/type/date.svg +3 -2
  127. package/src/icons/svg/view-gallery.svg +4 -0
  128. package/src/images-gallery/images-gallery-fall-through-provider.tsx +11 -0
  129. package/src/images-gallery/images-gallery.tsx +257 -0
  130. package/src/images-gallery/zoom.tsx +123 -0
  131. package/src/images-gallery-2/images-gallery-2.tsx +442 -0
  132. package/src/images-gallery-2/slide-buttons.tsx +230 -0
  133. package/src/images-gallery-2/zoom.tsx +35 -0
  134. package/src/is-in-popup.ts +1 -1
  135. package/src/kbd.tsx +46 -0
  136. package/src/layout-styles.ts +21 -1
  137. package/src/lists/actions-menu-row-surface.tsx +3 -1
  138. package/src/lists/list-row-surface.tsx +7 -1
  139. package/src/mobile-keyboard-aware-popup.tsx +87 -0
  140. package/src/mobile-styles.ts +8 -0
  141. package/src/modal-menu/contexts/modal-menu-context.tsx +22 -0
  142. package/src/modal-menu/contexts/modal-submenu-context.tsx +16 -0
  143. package/src/modal-menu/index.tsx +14 -0
  144. package/src/modal-menu/modal-menu-content.tsx +68 -0
  145. package/src/modal-menu/modal-menu-group.tsx +10 -0
  146. package/src/modal-menu/modal-menu-item.tsx +45 -0
  147. package/src/modal-menu/modal-menu-label.tsx +24 -0
  148. package/src/modal-menu/modal-menu-root.tsx +57 -0
  149. package/src/modal-menu/modal-menu-separator.tsx +14 -0
  150. package/src/modal-menu/modal-menu-trigger.tsx +54 -0
  151. package/src/modal-menu/modal-submenu-content.tsx +49 -0
  152. package/src/modal-menu/modal-submenu-trigger.tsx +34 -0
  153. package/src/modal-menu/modal-submenu.tsx +17 -0
  154. package/src/notification-dot.tsx +16 -7
  155. package/src/online-users.tsx +3 -3
  156. package/src/palette.ts +1 -1
  157. package/src/platform-symbols.ts +9 -0
  158. package/src/platform.ts +2 -0
  159. package/src/popover/index.tsx +710 -0
  160. package/src/popover/mobile-popup-context.tsx +29 -0
  161. package/src/{popup → popover}/modifiers.tsx +25 -25
  162. package/src/{popup → popover}/popup-modifiers-context.ts +3 -3
  163. package/src/reactions/reaction-button.tsx +342 -135
  164. package/src/reactions/reaction-picker.tsx +51 -44
  165. package/src/reactions/reactions.tsx +11 -1
  166. package/src/reactions/tootltip.tsx +55 -0
  167. package/src/rich-text-embed-error.tsx +2 -1
  168. package/src/select/components/group-heading.tsx +8 -0
  169. package/src/select/components/menu-list-virtualized.tsx +6 -2
  170. package/src/select/components/option.tsx +4 -0
  171. package/src/select/index.tsx +8 -4
  172. package/src/select/select-control-settings-context.tsx +11 -2
  173. package/src/select/select-in-popover.tsx +30 -39
  174. package/src/select/styles.ts +21 -1
  175. package/src/tab-nav/tab-nav.tsx +36 -10
  176. package/src/toast/primitives.tsx +8 -1
  177. package/src/toggle-button/round-toggle-button.tsx +23 -0
  178. package/src/toggle-button/toggle-button-group.tsx +34 -0
  179. package/src/toggle-button/toggle-button.tsx +164 -0
  180. package/src/toggle.tsx +11 -3
  181. package/src/tooltip.tsx +29 -20
  182. package/src/type-badge.tsx +5 -2
  183. package/src/unit/styles.ts +2 -2
  184. package/src/unit/unit-with-tooltip.tsx +1 -1
  185. package/src/use-is-phone.tsx +50 -4
  186. package/src/use-is-support-hover.ts +1 -1
  187. package/src/use-on-screen-keyboard-data.tsx +66 -0
  188. package/src/workflow-progress-icon.tsx +16 -22
  189. package/src/popup/index.tsx +0 -383
  190. package/src/shortcut-badge.tsx +0 -29
  191. /package/src/{popup → popover}/popup-stack-context.tsx +0 -0
  192. /package/src/{popup → popover}/reference.ts +0 -0
  193. /package/src/{popup → popover}/styles.ts +0 -0
  194. /package/src/{popup → popover}/use-click-outside.ts +0 -0
@@ -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;
@@ -152,8 +168,8 @@ export const themeColors = {
152
168
 
153
169
  // Shadows and effects / Elevation
154
170
  shadow50: [
155
- `0px 0px 0px 0.5px ${getOpacities(slate.slate12).opacity5}`,
156
- `0px 0px 0px 0.5px ${getOpacities(slateDark.slate12).opacity15}`,
171
+ `0px 0px 0px 1px ${getOpacities(slate.slate12).opacity5}`,
172
+ `0px 0px 0px 1px ${getOpacities(slateDark.slate12).opacity10}`,
157
173
  ],
158
174
  shadow100: [
159
175
  `0px 1px 4px 0px ${getOpacities(slate.slate12).opacity5}`,
@@ -231,7 +247,9 @@ export const themeColors = {
231
247
  mainBg: [slate.slate3, slateDark.slateBase],
232
248
  panelBg: [whiteA.whiteA0, slateDark.slate1],
233
249
  panelContentBg: [slate.slate2, slateDark.slate1],
250
+ panelContentBgOpacity80: [getOpacities(slate.slate2).opacity80, getOpacities(slateDark.slate1).opacity80],
234
251
  colorBgRelationContainer: [slate.slate2, slateDark.slate1],
252
+ colorBgAISidebarContent: [slate.slate1, slateDark.slate1],
235
253
  pageBg: [whiteA.whiteA0, slateDark.slate1],
236
254
  pageContentBg: [whiteA.whiteA0, slateDark.slate2],
237
255
  colorBgPopup: [whiteA.whiteA0, slateDark.slate4],
@@ -244,6 +262,8 @@ export const themeColors = {
244
262
  menuFooterHoverColor: [getOpacities(whiteA.whiteA0).opacity60, slateDark.slate4],
245
263
  menuIconColor: [getOpacities(slate.slate12).opacity70, getOpacities(slateDark.slate12).opacity70],
246
264
  menuSelectedIconColor: [getOpacities(slate.slate1).opacity90, getOpacities(slate.slate1).opacity90],
265
+
266
+ // Text, links colors
247
267
  textColor: [slateDark.slate5, slate.slate6],
248
268
  textSelectionColor: [getOpacities(blue.blue10).opacity20, getOpacities(blueDark.blue10).opacity40],
249
269
  accentTextColor: [slate.slate10, slateDark.slate10],
@@ -263,6 +283,8 @@ export const themeColors = {
263
283
  codeColor: [red.red9, red.red8],
264
284
  codeBgColor: [slate.slate3, slateDark.slate4],
265
285
  codeBlockBgColor: [slate.slate3, slateDark.slate4],
286
+ addedDiffTextColor: [teal.teal9, tealDark.teal11],
287
+ removedDiffTextColor: [red.red11, redDark.red11],
266
288
 
267
289
  // Entity
268
290
  entityNodeColor: [slateDark.slate3, slate.slate8],
@@ -480,7 +502,7 @@ export const themeColors = {
480
502
  colorBgMenuItemSelectedFocused: [indigo.indigo6, indigoDark.indigo5],
481
503
  colorBgFieldEditorContainer: [slate.slate2, slateDark.slate3],
482
504
  colorBgFieldEditorLinkEqualSign: [slate.slate6, slateDark.slate2],
483
- allowedDropColor: [getOpacities(slate.slate3).opacity80, getOpacities(slateDark.slate3).opacity80],
505
+ allowedDropColor: [slate.slate4, slateDark.slate4],
484
506
  relationViewBgColor: [slate.slate2, slateDark.slate3],
485
507
 
486
508
  mySpaceIconColor: [swatches["gray-light"], swatches["gray-light"]],
@@ -569,7 +591,17 @@ export const themeColors = {
569
591
  richTextTableBorder: [blackA.blackA5, whiteA.whiteA7],
570
592
 
571
593
  // Drag and drop
572
- colorBgDropLine: [indigo.indigo7, indigoDark.indigo7],
594
+ colorBgDropLine: [indigo.indigo8, indigoDark.indigo8],
595
+
596
+ // Views
597
+ viewBg: [slate.slate1, slateDark.slate1],
598
+ viewSecondaryBg: [slate.slate2, slateDark.slate2],
599
+ viewHighlightBg: [indigo.indigo3, indigoDark.indigo3],
600
+
601
+ // Board
602
+ boardBg: [slate.slate1, slateDark.slate1],
603
+ boardBgWithOpacity80: [getOpacities(slate.slate1).opacity80, getOpacities(slateDark.slate1).opacity80],
604
+ boardAxisBgHover: [slate.slate4, slateDark.slate4],
573
605
 
574
606
  // Grid
575
607
  gridHeaderBgColor: [slate.slate2, slateDark.slate3],
@@ -684,8 +716,8 @@ export const themeColors = {
684
716
  colorBorderNeutralFocusRing: [getOpacities(slate.slate9).opacity30, getOpacities(slate.slate9).opacity30],
685
717
  colorBorderDestructiveFocusRing: [getOpacities(red.red9).opacity30, getOpacities(red.red9).opacity30],
686
718
 
687
- colorBgReactionsDefault: [slate.slate3, slateDark.slate6],
688
- colorBgReactionsHover: [whiteA.whiteA0, slateDark.slate2],
719
+ colorBgReactionsDefault: [whiteA.whiteA0, slateDark.slate2],
720
+ colorBgReactionsHover: [slate.slate3, slateDark.slate6],
689
721
  colorBorderReactionsHover: [slate.slate8, slateDark.slate9],
690
722
  colorBgReactionsSelectedDefault: [indigo.indigo3, indigoDark.indigo8],
691
723
  colorBorderReactionsSelectedDefault: [indigo.indigo8, indigoDark.indigo8],
@@ -706,7 +738,7 @@ export const themeColors = {
706
738
  colorTextEntityAvatarHover: [indigo.indigo9, indigoDark.indigo9],
707
739
 
708
740
  // Text editor
709
- colorBgEditorImageZoomed: [getOpacities(slate.slate3).opacity90, getOpacities(slateDark.slate6).opacity90],
741
+ colorBgEditorImageZoomed: [slate.slate3, slateDark.slate6],
710
742
 
711
743
  //Whiteboard
712
744
  instrumentsMenuBg: [getOpacities(whiteA.whiteA0).opacity100, getOpacities(slateDark.slate4).opacity100],
@@ -807,15 +839,12 @@ function getTypeColors(themeColor: string, theme: ThemeMode) {
807
839
  } catch (e) {
808
840
  color = brandColors.green;
809
841
  }
810
- const boardBg = chroma(color).luminance(0.85).desaturate(0.2).set("hsl.h", "+2");
811
842
 
812
843
  const lightTypeColors = {
813
844
  primary: color,
814
845
  opacity: getOpacities(color),
815
846
  darkenPrimary: getDarkenColor(color),
816
847
  brightenPrimary: chroma(color).luminance(0.92).desaturate(0.1).alpha(0.98).css(),
817
- boardBg: boardBg.hex(),
818
- boardBgOverlay: boardBg.alpha(0.8).css(),
819
848
  headerBg: chroma(color).luminance(0.7).desaturate(0.5).set("hsl.h", "+2").css(),
820
849
  detailsBg: chroma(color).alpha(0.5).luminance(0.85).hex(),
821
850
  focus: chroma(color).alpha(0.25).css(),
@@ -827,8 +856,6 @@ function getTypeColors(themeColor: string, theme: ThemeMode) {
827
856
  opacity: getOpacities(color),
828
857
  darkenPrimary: getDarkenColor(color),
829
858
  brightenPrimary: chroma(color).luminance(0.92).desaturate(0.1).alpha(0.98).css(),
830
- boardBg: boardBg.hex(),
831
- boardBgOverlay: boardBg.alpha(0.8).css(),
832
859
  headerBg: chroma(color).luminance(0.7).desaturate(0.5).set("hsl.h", "+2").css(),
833
860
  detailsBg: chroma(color).alpha(0.03).luminance(0.8).desaturate(0.8).darken(0.1).hex(),
834
861
  focus: chroma(color).alpha(0.25).css(),
@@ -951,6 +978,7 @@ export const space = {
951
978
  s2: 2,
952
979
  s3: 3,
953
980
  s4: 4,
981
+ s5: 5,
954
982
  s6: 6,
955
983
  s8: 8,
956
984
  s10: 10,
@@ -967,6 +995,7 @@ export const space = {
967
995
  s44: 44,
968
996
  s48: 48,
969
997
  s56: 56,
998
+ s60: 60,
970
999
  s64: 64,
971
1000
  s80: 80,
972
1001
  s96: 96,
@@ -990,11 +1019,13 @@ export const layout = {
990
1019
  menuGroupHeaderIndent: 28, // I'm ok
991
1020
  menuItemLevelIndent: 24,
992
1021
  listItemHeight: 38,
1022
+ mobileListItemHeight: 44,
993
1023
  itemHeight: 36,
994
1024
  itemWithSubtitleHeight: 52,
995
1025
  groupTitleHeight: 30,
996
1026
  enumItemHeight: 32,
997
1027
  menuItemHeight: 32,
1028
+ mobileMenuItemHeight: 44,
998
1029
  newMenuItemHeight: 28, // I'm ok
999
1030
  mobileSidebarMenuItemHeight: 44,
1000
1031
  newMenuIconSize: 18,
@@ -1026,11 +1057,13 @@ export const layout = {
1026
1057
  unitHeight: 18,
1027
1058
  } as const;
1028
1059
 
1060
+ export const menuItemHeightVar = `--${varPrefix}-layout-menuItemHeight`;
1029
1061
  export const sidebarMenuItemHeightVar = `--${varPrefix}-layout-sidebarMenuItemHeight`;
1030
1062
  export const sidebarMenuIconSizeVar = `--${varPrefix}-layout-sidebarMenuIconSize`;
1031
1063
  export const listRowSurfaceFontSizeVar = `--${varPrefix}-layout-listRowSurfaceFontSize`;
1032
1064
 
1033
1065
  export const layoutVars = {
1066
+ menuItemHeight: `var(${menuItemHeightVar})`,
1034
1067
  sidebarMenuItemHeight: `var(${sidebarMenuItemHeightVar})`,
1035
1068
  sidebarMenuIconSize: `var(${sidebarMenuIconSizeVar})`,
1036
1069
  listRowSurfaceFontSize: `var(${listRowSurfaceFontSizeVar})`,
@@ -4,12 +4,23 @@ import {styled} from "@linaria/react";
4
4
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
5
5
  import {forwardRef} from "react";
6
6
  import {border, layout, space, textStyles, themeVars} from "../design-system";
7
+ import {mobileRootSelector} from "../mobile-styles";
7
8
 
8
9
  export const Root = (dropdownMenuProps: DropdownMenuPrimitive.DropdownMenuProps) => (
9
10
  <DropdownMenuPrimitive.Root dir="ltr" modal={false} {...dropdownMenuProps} />
10
11
  );
11
12
 
12
- 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
+ });
13
24
 
14
25
  const rowItemStyles = {
15
26
  ...textStyles.regular,
@@ -22,7 +33,7 @@ const rowItemStyles = {
22
33
  margin: `0px ${space.s4}px`,
23
34
  cursor: "pointer",
24
35
 
25
- "&:hover,&[data-highlighted]": {
36
+ '&:hover,&[data-highlighted],&[aria-expanded="true"]': {
26
37
  marginLeft: 4,
27
38
  marginRight: 4,
28
39
  backgroundColor: themeVars.colorBgActionsMenuItemHover,
@@ -37,6 +48,12 @@ const rowItemStyles = {
37
48
  backgroundColor: "unset",
38
49
  },
39
50
  },
51
+
52
+ [`${mobileRootSelector} &`]: {
53
+ ...textStyles.big,
54
+ minHeight: layout.mobileMenuItemHeight,
55
+ padding: `0px ${space.s12}px`,
56
+ },
40
57
  };
41
58
 
42
59
  const dropdownMenuContentStyles = css`
@@ -12,6 +12,7 @@ const i18n = {search: "Search icon...", notfound: "No Icons Found"};
12
12
 
13
13
  export type AppIconPickerProps = {
14
14
  color?: string;
15
+ emojiSize?: number;
15
16
  getHoverColor?: (color: string) => string | undefined;
16
17
  colors?: string[];
17
18
  onColorSelect?: (c: $TSFixMe) => void;
@@ -27,6 +28,7 @@ export const AppIconPicker: React.FC<AppIconPickerProps> = ({
27
28
  onColorSelect,
28
29
  getHoverColor,
29
30
  autoFocus = true,
31
+ emojiSize = 20,
30
32
  }) => {
31
33
  const themeMode = useThemeMode();
32
34
 
@@ -35,8 +37,8 @@ export const AppIconPicker: React.FC<AppIconPickerProps> = ({
35
37
  <svg
36
38
  style={{
37
39
  display: "block",
38
- width: 20,
39
- height: 20,
40
+ width: emojiSize,
41
+ height: emojiSize,
40
42
  fill: color ? getIconColor(themeMode, color) : undefined,
41
43
  }}
42
44
  viewBox="0 0 24 24"
@@ -44,12 +46,12 @@ export const AppIconPicker: React.FC<AppIconPickerProps> = ({
44
46
  <use href={(emoji as CustomEmoji).imageUrl} />
45
47
  </svg>
46
48
  ),
47
- [color, themeMode]
49
+ [color, themeMode, emojiSize]
48
50
  );
49
51
 
50
52
  return (
51
53
  <EmojiPickerRoot i18n={i18n} onEmojiSelect={onSelect}>
52
- <EmojiPickerContent emojiHoverColor={color ? getHoverColor?.(color) : undefined} emojiSize={20}>
54
+ <EmojiPickerContent emojiHoverColor={color ? getHoverColor?.(color) : undefined} emojiSize={emojiSize}>
53
55
  <LazyIconDataStore fallback={<div style={{height: "302px"}}></div>}>
54
56
  <EmojiPickerContentWithColor
55
57
  color={color}
@@ -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;
@@ -70,7 +71,7 @@ export const EmojiPickerPreviewFooter: React.FC<{
70
71
  {emojiPreview ? (
71
72
  <EmojiPreview emoji={emojiPreview.emoji} />
72
73
  ) : onAddCustomEmoji ? (
73
- <Button variant="outline" color="neutral" size="small" onClick={onAddCustomEmoji}>
74
+ <Button variant="outline" color="neutral" size="small" supportMobile onClick={onAddCustomEmoji}>
74
75
  Add Emoji
75
76
  </Button>
76
77
  ) : null}
@@ -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(),
@@ -19,6 +19,7 @@ export type EmojiPickerProps = {
19
19
  onSelect: (emoji: EmojiItem) => void;
20
20
  showSkinTones?: boolean;
21
21
  searchRef?: React.RefObject<HTMLInputElement>;
22
+ searchAutofocus?: boolean;
22
23
  };
23
24
  export const EmojiPicker: React.FC<EmojiPickerProps> = ({
24
25
  onSelect,
@@ -30,6 +31,7 @@ export const EmojiPicker: React.FC<EmojiPickerProps> = ({
30
31
  getHoverColor,
31
32
  showSkinTones,
32
33
  searchRef,
34
+ searchAutofocus,
33
35
  emojiSize = 20,
34
36
  }) => {
35
37
  const showFooter = Boolean(onAddCustomEmoji) || showSkinTones;
@@ -43,6 +45,7 @@ export const EmojiPicker: React.FC<EmojiPickerProps> = ({
43
45
  getHoverColor={getHoverColor}
44
46
  onColorSelect={onColorSelect}
45
47
  searchRef={searchRef}
48
+ searchAutofocus={searchAutofocus}
46
49
  />
47
50
 
48
51
  {showFooter ? (
@@ -1,8 +1,10 @@
1
+ import {isAndroid} from "../is-android";
1
2
  import {Emoji as EmojiPrimitive, EmojiProps as EmojiPrimitiveProps} from "./primitives/emoji";
2
3
  import {isApple} from "./utils/emoji-set";
3
4
  import {detectEmojiSupportLevel} from "./utils/emoji-support";
5
+ import {forwardRef} from "react";
4
6
 
5
7
  export type EmojiProps = EmojiPrimitiveProps;
6
- export const Emoji: React.FC<EmojiPrimitiveProps> = (props) => {
7
- return <EmojiPrimitive version={detectEmojiSupportLevel()} native={isApple()} {...props} />;
8
- };
8
+ export const Emoji = forwardRef<HTMLSpanElement, EmojiPrimitiveProps>((props, ref) => {
9
+ return <EmojiPrimitive ref={ref} version={detectEmojiSupportLevel()} native={isApple() || isAndroid()} {...props} />;
10
+ });
@@ -69,6 +69,7 @@ export const IconEmojiPicker: React.FC<IconEmojiPickerProps> = ({
69
69
  label: "Icons",
70
70
  children: (
71
71
  <AppIconPicker
72
+ emojiSize={emojiSize}
72
73
  color={color}
73
74
  onColorSelect={showColorPickerOnTabs.includes("icons") ? onColorSelect : undefined}
74
75
  getHoverColor={getHoverColor}
@@ -86,6 +87,7 @@ export const IconEmojiPicker: React.FC<IconEmojiPickerProps> = ({
86
87
  className={css`
87
88
  display: flex;
88
89
  flex-direction: column;
90
+ height: 100%;
89
91
  `}
90
92
  >
91
93
  <TabNavRoot className={tabNavRootStyle}>
@@ -106,7 +108,14 @@ export const IconEmojiPicker: React.FC<IconEmojiPickerProps> = ({
106
108
  </TabNavList>
107
109
  {onReset && (
108
110
  <TabNavItem>
109
- <Button size="small" variant="ghost" color="neutral" iconStart={<EmojiDelete />} onClick={onReset}>
111
+ <Button
112
+ size="small"
113
+ variant="ghost"
114
+ color="neutral"
115
+ iconStart={<EmojiDelete />}
116
+ onClick={onReset}
117
+ supportMobile
118
+ >
110
119
  {resetLabel}
111
120
  </Button>
112
121
  </TabNavItem>
@@ -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,5 +1,6 @@
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;
@@ -9,6 +10,10 @@ const footerCss = css`
9
10
 
10
11
  display: flex;
11
12
  align-items: center;
13
+
14
+ ${mobileRootSelector} & {
15
+ height: 68px;
16
+ }
12
17
  `;
13
18
 
14
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,7 +86,7 @@ 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);
@@ -0,0 +1,11 @@
1
+ import {useMemo} from "react";
2
+ import {measureScrollbar} from "@fibery/helpers/utils/measure-scrollbar";
3
+ import {useIsPhone} from "../use-is-phone";
4
+
5
+ export const useResponsiveEmojiSize = () => {
6
+ const isPhone = useIsPhone();
7
+ return useMemo(
8
+ () => (isPhone ? Math.min(Math.floor((document.body.clientWidth - 24 - measureScrollbar() - 9 * 12) / 9), 40) : 20),
9
+ [isPhone]
10
+ );
11
+ };
@@ -1,5 +1,6 @@
1
1
  import {SpritesheetSet} from "@fibery/emoji-data";
2
+ import {isAndroid} from "../../is-android";
2
3
 
3
4
  export const isApple = () => /Mac|iPhone|iPad/.test(navigator.userAgent);
4
5
 
5
- export const getEmojiSet = (): SpritesheetSet => (isApple() ? "apple" : "twitter");
6
+ export const getEmojiSet = (): SpritesheetSet => (isApple() ? "apple" : isAndroid() ? "google" : "twitter");
@@ -1,5 +1,6 @@
1
1
  import {css, cx} from "@linaria/core";
2
2
  import {fontWeight, space, textStyles, themeVars} from "../design-system";
3
+ import {mobileRootSelector} from "../mobile-styles";
3
4
 
4
5
  const emptyStateCss = css`
5
6
  display: flex;
@@ -31,7 +32,12 @@ const headingCss = css`
31
32
  font-weight: ${fontWeight.semibold};
32
33
  color: ${themeVars.textColor};
33
34
  margin: 0;
35
+
36
+ ${mobileRootSelector} & {
37
+ ${textStyles.heading4}
38
+ }
34
39
  `;
40
+
35
41
  const descriptionCss = css`
36
42
  ${textStyles.regular};
37
43
  color: ${themeVars.accentTextColor};
@@ -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;