@fibery/ui-kit 1.37.0 → 1.38.0

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 (139) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/package.json +8 -5
  3. package/src/actions-menu/actions-menu-item.tsx +18 -6
  4. package/src/actions-menu/actions-menu-props.tsx +4 -0
  5. package/src/actions-menu/actions-menu-sub-command-menu.tsx +7 -4
  6. package/src/actions-menu/actions-menu-sub-menu.tsx +9 -3
  7. package/src/actions-menu/actions-menu.tsx +24 -8
  8. package/src/actions-panel.tsx +12 -2
  9. package/src/axis-header.tsx +136 -76
  10. package/src/box.tsx +1 -1
  11. package/src/breadcrumb.tsx +78 -0
  12. package/src/button/actions-button-compact.tsx +4 -1
  13. package/src/button/base-button.tsx +5 -3
  14. package/src/button/button-group.tsx +1 -1
  15. package/src/button/button.tsx +31 -0
  16. package/src/button/icon-button.tsx +9 -0
  17. package/src/button/select-button.tsx +4 -0
  18. package/src/card-container.tsx +7 -4
  19. package/src/color-picker/swatch.tsx +1 -0
  20. package/src/command-menu/index.tsx +3 -3
  21. package/src/context-menu/index.tsx +10 -1
  22. package/src/date-picker/date-range-picker.tsx +6 -3
  23. package/src/date-picker/relative-date-picker.tsx +6 -2
  24. package/src/date-picker/single-date-picker.tsx +8 -5
  25. package/src/date-picker/styles.ts +32 -26
  26. package/src/date-picker/types.ts +3 -1
  27. package/src/day-select/day-select.tsx +21 -75
  28. package/src/day-select/iso-week-day-select.tsx +1 -1
  29. package/src/day-select/mount-day-select.tsx +2 -2
  30. package/src/day-select/week-day-select.tsx +1 -5
  31. package/src/design-system.ts +21 -12
  32. package/src/dropdown-menu/index.tsx +8 -1
  33. package/src/emoji-picker/app-icon-picker.tsx +6 -4
  34. package/src/emoji-picker/emoji-picker-preview-footer.tsx +1 -1
  35. package/src/emoji-picker/emoji-picker.tsx +3 -0
  36. package/src/emoji-picker/emoji.tsx +2 -1
  37. package/src/emoji-picker/icon-emoji-picker.tsx +10 -1
  38. package/src/emoji-picker/primitives/footer.tsx +0 -1
  39. package/src/emoji-picker/primitives/skin-tone.tsx +1 -0
  40. package/src/emoji-picker/use-responsive-emoji-size.ts +11 -0
  41. package/src/emoji-picker/utils/emoji-set.ts +2 -1
  42. package/src/empty-state/empty-state.tsx +6 -0
  43. package/src/field-icon.tsx +4 -1
  44. package/src/file-item.tsx +164 -47
  45. package/src/html-styles.ts +8 -0
  46. package/src/icons/ast/ActivityFilled.ts +8 -0
  47. package/src/icons/ast/AiAssistantFilled.ts +8 -0
  48. package/src/icons/ast/CollapseAllHorizontal.ts +8 -0
  49. package/src/icons/ast/DateRange.ts +1 -1
  50. package/src/icons/ast/EntityCreateFilled.ts +8 -0
  51. package/src/icons/ast/ExpandAllHorizontal.ts +8 -0
  52. package/src/icons/ast/GlobeUnpublish.ts +8 -0
  53. package/src/icons/ast/HomeFilled.ts +8 -0
  54. package/src/icons/ast/KeyboardHideDown.ts +8 -0
  55. package/src/icons/ast/LayoutMultiple.ts +8 -0
  56. package/src/icons/ast/RicheditorHistoryRedo.ts +1 -1
  57. package/src/icons/ast/RicheditorHistoryUndo.ts +1 -1
  58. package/src/icons/ast/SearchFilled.ts +8 -0
  59. package/src/icons/ast/SettingsFilled.ts +8 -0
  60. package/src/icons/ast/SlideMenuFilled.ts +8 -0
  61. package/src/icons/ast/TypeDate.ts +1 -1
  62. package/src/icons/ast/index.tsx +12 -0
  63. package/src/icons/react/ActivityFilled.tsx +13 -0
  64. package/src/icons/react/AiAssistantFilled.tsx +13 -0
  65. package/src/icons/react/CollapseAllHorizontal.tsx +13 -0
  66. package/src/icons/react/EntityCreateFilled.tsx +13 -0
  67. package/src/icons/react/ExpandAllHorizontal.tsx +13 -0
  68. package/src/icons/react/GlobeUnpublish.tsx +13 -0
  69. package/src/icons/react/HomeFilled.tsx +13 -0
  70. package/src/icons/react/KeyboardHideDown.tsx +13 -0
  71. package/src/icons/react/LayoutMultiple.tsx +13 -0
  72. package/src/icons/react/SearchFilled.tsx +13 -0
  73. package/src/icons/react/SettingsFilled.tsx +13 -0
  74. package/src/icons/react/SlideMenuFilled.tsx +13 -0
  75. package/src/icons/react/index.tsx +12 -0
  76. package/src/icons/svg/activity-filled.svg +4 -0
  77. package/src/icons/svg/ai-assistant-filled.svg +3 -0
  78. package/src/icons/svg/collapse-all-horizontal.svg +3 -0
  79. package/src/icons/svg/date-range.svg +3 -3
  80. package/src/icons/svg/entity-create-filled.svg +4 -0
  81. package/src/icons/svg/expand-all-horizontal.svg +3 -0
  82. package/src/icons/svg/globe-unpublish.svg +4 -0
  83. package/src/icons/svg/home-filled.svg +3 -0
  84. package/src/icons/svg/keyboard-hide-down.svg +1 -0
  85. package/src/icons/svg/layout-multiple.svg +3 -0
  86. package/src/icons/svg/richeditor/history/redo.svg +3 -2
  87. package/src/icons/svg/richeditor/history/undo.svg +3 -2
  88. package/src/icons/svg/search-filled.svg +3 -0
  89. package/src/icons/svg/settings-filled.svg +3 -0
  90. package/src/icons/svg/slide-menu-filled.svg +1 -0
  91. package/src/icons/svg/type/date.svg +3 -2
  92. package/src/images-gallery/images-gallery.tsx +254 -0
  93. package/src/images-gallery/zoom.tsx +112 -0
  94. package/src/is-in-popup.ts +1 -1
  95. package/src/layout-styles.ts +21 -1
  96. package/src/lists/actions-menu-row-surface.tsx +3 -1
  97. package/src/lists/list-row-surface.tsx +7 -1
  98. package/src/mobile-keyboard-aware-popup.tsx +87 -0
  99. package/src/mobile-styles.ts +8 -0
  100. package/src/modal-menu/contexts/modal-menu-context.tsx +22 -0
  101. package/src/modal-menu/contexts/modal-submenu-context.tsx +16 -0
  102. package/src/modal-menu/index.tsx +14 -0
  103. package/src/modal-menu/modal-menu-content.tsx +68 -0
  104. package/src/modal-menu/modal-menu-group.tsx +10 -0
  105. package/src/modal-menu/modal-menu-item.tsx +37 -0
  106. package/src/modal-menu/modal-menu-label.tsx +24 -0
  107. package/src/modal-menu/modal-menu-root.tsx +57 -0
  108. package/src/modal-menu/modal-menu-separator.tsx +14 -0
  109. package/src/modal-menu/modal-menu-trigger.tsx +37 -0
  110. package/src/modal-menu/modal-submenu-content.tsx +49 -0
  111. package/src/modal-menu/modal-submenu-trigger.tsx +34 -0
  112. package/src/modal-menu/modal-submenu.tsx +17 -0
  113. package/src/online-users.tsx +3 -3
  114. package/src/palette.ts +1 -1
  115. package/src/popover/index.tsx +687 -0
  116. package/src/popover/mobile-popup-context.tsx +29 -0
  117. package/src/{popup → popover}/modifiers.tsx +0 -7
  118. package/src/{popup → popover}/popup-modifiers-context.ts +3 -3
  119. package/src/reactions/reaction-button.tsx +30 -45
  120. package/src/reactions/reaction-picker.tsx +39 -45
  121. package/src/select/index.tsx +8 -4
  122. package/src/select/select-in-popover.tsx +21 -33
  123. package/src/tab-nav/tab-nav.tsx +35 -9
  124. package/src/toast/primitives.tsx +8 -1
  125. package/src/toggle-button/round-toggle-button.tsx +23 -0
  126. package/src/toggle-button/toggle-button-group.tsx +34 -0
  127. package/src/toggle-button/toggle-button.tsx +164 -0
  128. package/src/toggle.tsx +3 -3
  129. package/src/tooltip.tsx +2 -2
  130. package/src/unit/styles.ts +2 -2
  131. package/src/use-is-phone.tsx +28 -3
  132. package/src/use-is-support-hover.ts +1 -1
  133. package/src/use-on-screen-keyboard-data.tsx +66 -0
  134. package/src/workflow-progress-icon.tsx +16 -22
  135. package/src/popup/index.tsx +0 -383
  136. /package/src/{popup → popover}/popup-stack-context.tsx +0 -0
  137. /package/src/{popup → popover}/reference.ts +0 -0
  138. /package/src/{popup → popover}/styles.ts +0 -0
  139. /package/src/{popup → popover}/use-click-outside.ts +0 -0
@@ -152,8 +152,8 @@ export const themeColors = {
152
152
 
153
153
  // Shadows and effects / Elevation
154
154
  shadow50: [
155
- `0px 0px 0px 0.5px ${getOpacities(slate.slate12).opacity5}`,
156
- `0px 0px 0px 0.5px ${getOpacities(slateDark.slate12).opacity15}`,
155
+ `0px 0px 0px 1px ${getOpacities(slate.slate12).opacity5}`,
156
+ `0px 0px 0px 1px ${getOpacities(slateDark.slate12).opacity10}`,
157
157
  ],
158
158
  shadow100: [
159
159
  `0px 1px 4px 0px ${getOpacities(slate.slate12).opacity5}`,
@@ -231,7 +231,9 @@ export const themeColors = {
231
231
  mainBg: [slate.slate3, slateDark.slateBase],
232
232
  panelBg: [whiteA.whiteA0, slateDark.slate1],
233
233
  panelContentBg: [slate.slate2, slateDark.slate1],
234
+ panelContentBgOpacity80: [getOpacities(slate.slate2).opacity80, getOpacities(slateDark.slate1).opacity80],
234
235
  colorBgRelationContainer: [slate.slate2, slateDark.slate1],
236
+ colorBgAISidebarContent: [slate.slate1, slateDark.slate1],
235
237
  pageBg: [whiteA.whiteA0, slateDark.slate1],
236
238
  pageContentBg: [whiteA.whiteA0, slateDark.slate2],
237
239
  colorBgPopup: [whiteA.whiteA0, slateDark.slate4],
@@ -263,6 +265,8 @@ export const themeColors = {
263
265
  codeColor: [red.red9, red.red8],
264
266
  codeBgColor: [slate.slate3, slateDark.slate4],
265
267
  codeBlockBgColor: [slate.slate3, slateDark.slate4],
268
+ addedDiffTextColor: [teal.teal9, tealDark.teal11],
269
+ removedDiffTextColor: [red.red11, redDark.red11],
266
270
 
267
271
  // Entity
268
272
  entityNodeColor: [slateDark.slate3, slate.slate8],
@@ -480,7 +484,7 @@ export const themeColors = {
480
484
  colorBgMenuItemSelectedFocused: [indigo.indigo6, indigoDark.indigo5],
481
485
  colorBgFieldEditorContainer: [slate.slate2, slateDark.slate3],
482
486
  colorBgFieldEditorLinkEqualSign: [slate.slate6, slateDark.slate2],
483
- allowedDropColor: [getOpacities(slate.slate3).opacity80, getOpacities(slateDark.slate3).opacity80],
487
+ allowedDropColor: [slate.slate4, slateDark.slate4],
484
488
  relationViewBgColor: [slate.slate2, slateDark.slate3],
485
489
 
486
490
  mySpaceIconColor: [swatches["gray-light"], swatches["gray-light"]],
@@ -569,7 +573,12 @@ export const themeColors = {
569
573
  richTextTableBorder: [blackA.blackA5, whiteA.whiteA7],
570
574
 
571
575
  // Drag and drop
572
- colorBgDropLine: [indigo.indigo7, indigoDark.indigo7],
576
+ colorBgDropLine: [indigo.indigo8, indigoDark.indigo8],
577
+
578
+ // Board
579
+ boardBg: [slate.slate1, slateDark.slate1],
580
+ boardBgWithOpacity80: [getOpacities(slate.slate1).opacity80, getOpacities(slateDark.slate1).opacity80],
581
+ boardAxisBgHover: [slate.slate4, slateDark.slate4],
573
582
 
574
583
  // Grid
575
584
  gridHeaderBgColor: [slate.slate2, slateDark.slate3],
@@ -684,8 +693,8 @@ export const themeColors = {
684
693
  colorBorderNeutralFocusRing: [getOpacities(slate.slate9).opacity30, getOpacities(slate.slate9).opacity30],
685
694
  colorBorderDestructiveFocusRing: [getOpacities(red.red9).opacity30, getOpacities(red.red9).opacity30],
686
695
 
687
- colorBgReactionsDefault: [slate.slate3, slateDark.slate6],
688
- colorBgReactionsHover: [whiteA.whiteA0, slateDark.slate2],
696
+ colorBgReactionsDefault: [whiteA.whiteA0, slateDark.slate2],
697
+ colorBgReactionsHover: [slate.slate3, slateDark.slate6],
689
698
  colorBorderReactionsHover: [slate.slate8, slateDark.slate9],
690
699
  colorBgReactionsSelectedDefault: [indigo.indigo3, indigoDark.indigo8],
691
700
  colorBorderReactionsSelectedDefault: [indigo.indigo8, indigoDark.indigo8],
@@ -706,7 +715,7 @@ export const themeColors = {
706
715
  colorTextEntityAvatarHover: [indigo.indigo9, indigoDark.indigo9],
707
716
 
708
717
  // Text editor
709
- colorBgEditorImageZoomed: [getOpacities(slate.slate3).opacity90, getOpacities(slateDark.slate6).opacity90],
718
+ colorBgEditorImageZoomed: [slate.slate3, slateDark.slate6],
710
719
 
711
720
  //Whiteboard
712
721
  instrumentsMenuBg: [getOpacities(whiteA.whiteA0).opacity100, getOpacities(slateDark.slate4).opacity100],
@@ -807,15 +816,12 @@ function getTypeColors(themeColor: string, theme: ThemeMode) {
807
816
  } catch (e) {
808
817
  color = brandColors.green;
809
818
  }
810
- const boardBg = chroma(color).luminance(0.85).desaturate(0.2).set("hsl.h", "+2");
811
819
 
812
820
  const lightTypeColors = {
813
821
  primary: color,
814
822
  opacity: getOpacities(color),
815
823
  darkenPrimary: getDarkenColor(color),
816
824
  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
825
  headerBg: chroma(color).luminance(0.7).desaturate(0.5).set("hsl.h", "+2").css(),
820
826
  detailsBg: chroma(color).alpha(0.5).luminance(0.85).hex(),
821
827
  focus: chroma(color).alpha(0.25).css(),
@@ -827,8 +833,6 @@ function getTypeColors(themeColor: string, theme: ThemeMode) {
827
833
  opacity: getOpacities(color),
828
834
  darkenPrimary: getDarkenColor(color),
829
835
  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
836
  headerBg: chroma(color).luminance(0.7).desaturate(0.5).set("hsl.h", "+2").css(),
833
837
  detailsBg: chroma(color).alpha(0.03).luminance(0.8).desaturate(0.8).darken(0.1).hex(),
834
838
  focus: chroma(color).alpha(0.25).css(),
@@ -951,6 +955,7 @@ export const space = {
951
955
  s2: 2,
952
956
  s3: 3,
953
957
  s4: 4,
958
+ s5: 5,
954
959
  s6: 6,
955
960
  s8: 8,
956
961
  s10: 10,
@@ -990,11 +995,13 @@ export const layout = {
990
995
  menuGroupHeaderIndent: 28, // I'm ok
991
996
  menuItemLevelIndent: 24,
992
997
  listItemHeight: 38,
998
+ mobileListItemHeight: 44,
993
999
  itemHeight: 36,
994
1000
  itemWithSubtitleHeight: 52,
995
1001
  groupTitleHeight: 30,
996
1002
  enumItemHeight: 32,
997
1003
  menuItemHeight: 32,
1004
+ mobileMenuItemHeight: 44,
998
1005
  newMenuItemHeight: 28, // I'm ok
999
1006
  mobileSidebarMenuItemHeight: 44,
1000
1007
  newMenuIconSize: 18,
@@ -1026,11 +1033,13 @@ export const layout = {
1026
1033
  unitHeight: 18,
1027
1034
  } as const;
1028
1035
 
1036
+ export const menuItemHeightVar = `--${varPrefix}-layout-menuItemHeight`;
1029
1037
  export const sidebarMenuItemHeightVar = `--${varPrefix}-layout-sidebarMenuItemHeight`;
1030
1038
  export const sidebarMenuIconSizeVar = `--${varPrefix}-layout-sidebarMenuIconSize`;
1031
1039
  export const listRowSurfaceFontSizeVar = `--${varPrefix}-layout-listRowSurfaceFontSize`;
1032
1040
 
1033
1041
  export const layoutVars = {
1042
+ menuItemHeight: `var(${menuItemHeightVar})`,
1034
1043
  sidebarMenuItemHeight: `var(${sidebarMenuItemHeightVar})`,
1035
1044
  sidebarMenuIconSize: `var(${sidebarMenuIconSizeVar})`,
1036
1045
  listRowSurfaceFontSize: `var(${listRowSurfaceFontSizeVar})`,
@@ -4,6 +4,7 @@ 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} />
@@ -22,7 +23,7 @@ const rowItemStyles = {
22
23
  margin: `0px ${space.s4}px`,
23
24
  cursor: "pointer",
24
25
 
25
- "&:hover,&[data-highlighted]": {
26
+ '&:hover,&[data-highlighted],&[aria-expanded="true"]': {
26
27
  marginLeft: 4,
27
28
  marginRight: 4,
28
29
  backgroundColor: themeVars.colorBgActionsMenuItemHover,
@@ -37,6 +38,12 @@ const rowItemStyles = {
37
38
  backgroundColor: "unset",
38
39
  },
39
40
  },
41
+
42
+ [`${mobileRootSelector} &`]: {
43
+ ...textStyles.big,
44
+ minHeight: layout.mobileMenuItemHeight,
45
+ padding: `0px ${space.s12}px`,
46
+ },
40
47
  };
41
48
 
42
49
  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}
@@ -70,7 +70,7 @@ export const EmojiPickerPreviewFooter: React.FC<{
70
70
  {emojiPreview ? (
71
71
  <EmojiPreview emoji={emojiPreview.emoji} />
72
72
  ) : onAddCustomEmoji ? (
73
- <Button variant="outline" color="neutral" size="small" onClick={onAddCustomEmoji}>
73
+ <Button variant="outline" color="neutral" size="small" supportMobile onClick={onAddCustomEmoji}>
74
74
  Add Emoji
75
75
  </Button>
76
76
  ) : null}
@@ -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,9 @@
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";
4
5
 
5
6
  export type EmojiProps = EmojiPrimitiveProps;
6
7
  export const Emoji: React.FC<EmojiPrimitiveProps> = (props) => {
7
- return <EmojiPrimitive version={detectEmojiSupportLevel()} native={isApple()} {...props} />;
8
+ return <EmojiPrimitive version={detectEmojiSupportLevel()} native={isApple() || isAndroid()} {...props} />;
8
9
  };
@@ -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>
@@ -5,7 +5,6 @@ const footerCss = css`
5
5
  position: relative;
6
6
  border-top: 1px solid var(--fibery-color-separatorColor);
7
7
  padding: ${space.s6}px ${space.s12}px;
8
- height: 40px;
9
8
 
10
9
  display: flex;
11
10
  align-items: center;
@@ -82,6 +82,7 @@ export const EmojiPickerSkinTone: React.FC<EmojiPickerSkinToneProps> = ({classNa
82
82
  }
83
83
  setOpened(!opened);
84
84
  }}
85
+ supportMobile
85
86
  className={css`
86
87
  &:hover:not(:disabled),
87
88
  &:focus-visible {
@@ -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};
@@ -18,8 +18,11 @@ export function FieldIcon({
18
18
  if (iconName && isAppIcon(iconName)) {
19
19
  return <FieldAppIcon iconName={iconName} color={color} containerSize={containerSize} iconSize={iconSize} />;
20
20
  }
21
+
22
+ const defaultSize = containerSize || iconSize;
23
+
21
24
  return (
22
- <Suspense fallback={null}>
25
+ <Suspense fallback={<div style={{width: defaultSize, height: defaultSize}} />}>
23
26
  <FieldTypeIconLazy iconName={iconName} color={color} containerSize={containerSize} iconSize={iconSize} />
24
27
  </Suspense>
25
28
  );
package/src/file-item.tsx CHANGED
@@ -1,10 +1,15 @@
1
1
  import {css, cx} from "@linaria/core";
2
- import {PureComponent} from "react";
2
+ import {PureComponent, useEffect, useState} from "react";
3
3
  import {ActionsMenu, ActionsMenuItem} from "./actions-menu";
4
4
  import {ActionsButtonCompact} from "./button/actions-button-compact";
5
5
  import {Item} from "./item";
6
6
  import {border, colors, fontWeight, space, textStyles, themeVars} from "./design-system";
7
7
  import {makeButtonColors} from "./button/make-button-colors";
8
+ import {IconButton} from "./button/icon-button";
9
+ import ZoomIn from "./icons/react/RicheditorImageZoom";
10
+ import {Tooltip} from "./tooltip";
11
+ import {Zoom} from "./images-gallery/zoom";
12
+ import {useImagesGalleryMethods, useImagesGalleryRegistry} from "./images-gallery/images-gallery";
8
13
 
9
14
  const fileItemStyle = css`
10
15
  ${{
@@ -50,7 +55,7 @@ const imageOverlayStyle = css`
50
55
  borderRadius: border.radius6,
51
56
  "&:hover": {
52
57
  backgroundPosition: "0% 0%",
53
- color: colors.inversedTextColor,
58
+ color: themeVars.inversedTextColor,
54
59
  },
55
60
  }}
56
61
  `;
@@ -65,15 +70,71 @@ export type FileItemType = {
65
70
  name: string;
66
71
  url: string;
67
72
  thumbnailUrl: string | null;
73
+ previewUrl: string | null;
68
74
  status?: string;
69
75
  };
70
76
 
71
77
  export type FileItemProps = {
72
78
  data: FileItemType;
73
- onRemoveClick: (x: FileItemType) => void;
79
+ onRemoveClick?: (x: FileItemType) => void;
74
80
  disabled?: boolean;
75
81
  };
76
82
 
83
+ function ImageZoom({thumbnailUrl, url}: {thumbnailUrl: string; url: string}) {
84
+ const [zoomed, setZoomed] = useState(false);
85
+ const imagesRegistry = useImagesGalleryRegistry();
86
+ const galleryMethods = useImagesGalleryMethods();
87
+ useEffect(() => {
88
+ imagesRegistry.set(thumbnailUrl, {zoomed: false, setZoomed});
89
+ }, [imagesRegistry, thumbnailUrl]);
90
+ useEffect(() => {
91
+ if (zoomed) {
92
+ galleryMethods.setActivated(true);
93
+ }
94
+ const imageData = imagesRegistry.get(thumbnailUrl);
95
+ if (imageData) {
96
+ imageData.zoomed = zoomed;
97
+ } else {
98
+ imagesRegistry.set(thumbnailUrl, {zoomed, setZoomed});
99
+ }
100
+ }, [galleryMethods, zoomed, thumbnailUrl, imagesRegistry]);
101
+ return (
102
+ <div
103
+ className={css`
104
+ position: relative;
105
+ `}
106
+ >
107
+ <Zoom
108
+ zoomImg={{src: url}}
109
+ openOnClick={true}
110
+ className={css`
111
+ position: absolute;
112
+ outline: none;
113
+ bottom: 0;
114
+ top: 0;
115
+ left: 0;
116
+ right: 0;
117
+ cursor: zoom-in;
118
+ `}
119
+ zoomed={zoomed}
120
+ onZoomedChange={setZoomed}
121
+ >
122
+ <div role="img" style={{backgroundImage: `url(${thumbnailUrl})`, outline: "none"}} />
123
+ </Zoom>
124
+ <Tooltip title={"Zoom in"}>
125
+ <IconButton
126
+ style={makeButtonColors(colors.inversedTextColor, "ghost")}
127
+ onClick={() => setZoomed(true)}
128
+ size={"small"}
129
+ supportMobile={true}
130
+ >
131
+ <ZoomIn />
132
+ </IconButton>
133
+ </Tooltip>
134
+ </div>
135
+ );
136
+ }
137
+
77
138
  export class FileItem extends PureComponent<FileItemProps> {
78
139
  _renderStatus() {
79
140
  const {status} = this.props.data;
@@ -91,61 +152,117 @@ export class FileItem extends PureComponent<FileItemProps> {
91
152
  }
92
153
 
93
154
  render() {
94
- const {name, url, thumbnailUrl, status} = this.props.data;
95
-
155
+ const {name, url, thumbnailUrl, status, previewUrl} = this.props.data;
96
156
  const isActive = status === "uploading" || status === "deleting";
97
157
  const isBackgroundReady = thumbnailUrl && !isActive;
98
-
99
158
  return (
100
- <a
101
- href={url}
102
- rel="noopener noreferrer nofollow"
103
- target="_blank"
104
- style={isBackgroundReady ? {backgroundImage: `url(${thumbnailUrl})`} : {}}
159
+ <div
105
160
  className={cx(
106
- fileItemStyle,
107
- isActive &&
161
+ css`
162
+ position: relative;
163
+ height: 100%;
164
+ `,
165
+ isBackgroundReady &&
108
166
  css`
109
- ${{backgroundColor: themeVars.entityCardSelectedColor}}
167
+ &:hover .${overlayStyle} {
168
+ background-position: 0 0;
169
+ color: ${themeVars.inversedTextColor};
170
+ }
110
171
  `
111
172
  )}
112
173
  >
113
- <div className={cx(overlayStyle, isBackgroundReady ? imageOverlayStyle : fileOverlayStyle)}>
114
- <Item
115
- multiline
116
- textClassName={nameStyle}
117
- rightContainer={
118
- <ActionsMenu
119
- trigger={
120
- <ActionsButtonCompact
121
- style={isBackgroundReady ? makeButtonColors(colors.inversedTextColor, "ghost") : undefined}
122
- />
123
- }
124
- >
125
- <a download={name} href={url}>
126
- <ActionsMenuItem>Download</ActionsMenuItem>
127
- </a>
128
- <ActionsMenuItem
129
- onSelect={() => this.props.onRemoveClick(this.props.data)}
130
- dangerous
131
- disabled={this.props.disabled}
132
- >
133
- Delete
134
- </ActionsMenuItem>
135
- </ActionsMenu>
174
+ {/* eslint-disable-next-line jsx-a11y/anchor-has-content */}
175
+ <a
176
+ href={url}
177
+ className={css`
178
+ &::before {
179
+ bottom: 0;
180
+ content: "";
181
+ display: block;
182
+ left: 0;
183
+ position: absolute;
184
+ right: 0;
185
+ top: 0;
136
186
  }
137
- >
138
- <div
139
- className={css`
140
- ${fontWeight}
141
- `}
187
+ `}
188
+ rel="noopener noreferrer nofollow"
189
+ target="_blank"
190
+ />
191
+ <div
192
+ style={isBackgroundReady ? {backgroundImage: `url(${thumbnailUrl})`} : {}}
193
+ className={cx(
194
+ fileItemStyle,
195
+ isActive &&
196
+ css`
197
+ ${{backgroundColor: themeVars.entityCardSelectedColor}}
198
+ `
199
+ )}
200
+ >
201
+ <div className={cx(overlayStyle, isBackgroundReady ? imageOverlayStyle : fileOverlayStyle)}>
202
+ <Item
203
+ multiline
204
+ textClassName={nameStyle}
205
+ rightContainer={
206
+ <div
207
+ className={css`
208
+ display: flex;
209
+ align-items: center;
210
+ gap: ${space.s4}px;
211
+ `}
212
+ >
213
+ {previewUrl ? <ImageZoom url={url} thumbnailUrl={previewUrl} /> : null}
214
+ <ActionsMenu
215
+ trigger={
216
+ <ActionsButtonCompact
217
+ className={css`
218
+ z-index: 1;
219
+ `}
220
+ style={isBackgroundReady ? makeButtonColors(colors.inversedTextColor, "ghost") : undefined}
221
+ />
222
+ }
223
+ >
224
+ <a download={name} href={url}>
225
+ <ActionsMenuItem>Download</ActionsMenuItem>
226
+ </a>
227
+ <ActionsMenuItem
228
+ onSelect={() => this.props.onRemoveClick?.(this.props.data)}
229
+ dangerous
230
+ disabled={this.props.disabled}
231
+ >
232
+ Delete
233
+ </ActionsMenuItem>
234
+ </ActionsMenu>
235
+ </div>
236
+ }
142
237
  >
143
- {this._renderStatus()}
144
- </div>
145
- {name}
146
- </Item>
238
+ <div
239
+ className={css`
240
+ ${fontWeight}
241
+ `}
242
+ >
243
+ {this._renderStatus()}
244
+ </div>
245
+ <a
246
+ className={css`
247
+ position: relative;
248
+ z-index: 1;
249
+ color: inherit;
250
+ text-decoration: none;
251
+ &:hover {
252
+ text-decoration: none;
253
+ color: inherit;
254
+ }
255
+ `}
256
+ href={url}
257
+ target={"_blank"}
258
+ rel="noreferrer"
259
+ >
260
+ {name}
261
+ </a>
262
+ </Item>
263
+ </div>
147
264
  </div>
148
- </a>
265
+ </div>
149
266
  );
150
267
  }
151
268
  }
@@ -226,9 +226,13 @@ const htmlStyles = {
226
226
  },
227
227
  "& > *:first-child": {
228
228
  marginTop: 0,
229
+ paddingTop: space.s3,
230
+ paddingBottom: space.s3,
229
231
  },
230
232
  "& > *:last-child": {
231
233
  marginBottom: 0,
234
+ paddingTop: space.s3,
235
+ paddingBottom: space.s3,
232
236
  },
233
237
  "& > .fibery-rich-text-image-block:last-child": {
234
238
  marginBottom: space.s4,
@@ -433,9 +437,13 @@ const smallHtmlStyles = {
433
437
  },
434
438
  "& > *:first-child": {
435
439
  marginTop: 0,
440
+ paddingTop: space.s2,
441
+ paddingBottom: space.s2,
436
442
  },
437
443
  "& > *:last-child": {
438
444
  marginBottom: 0,
445
+ paddingTop: space.s2,
446
+ paddingBottom: space.s2,
439
447
  },
440
448
  "& > .fibery-rich-text-image-block:last-child": {
441
449
  marginBottom: space.s2,
@@ -0,0 +1,8 @@
1
+
2
+ // This icon file is generated automatically.
3
+
4
+ import { IconDefinition } from '../types';
5
+
6
+ const ActivityFilled: IconDefinition = {"icon":{"type":"root","children":[{"type":"element","tagName":"svg","properties":{"viewBox":"0 0 20 20"},"children":[{"type":"element","tagName":"path","properties":{"d":"M12.4 16.5c.192 0 .288 0 .355.05.053.04.094.117.099.183.005.084-.041.155-.134.296a3.247 3.247 0 0 1-5.439 0c-.092-.141-.139-.212-.133-.296a.273.273 0 0 1 .098-.183c.067-.05.163-.05.355-.05h4.8ZM10 2c1.51 0 2.966.559 4.048 1.568 1.083 1.012 1.702 2.395 1.702 3.849 0 2.105.529 3.55 1.117 4.514.273.445.484.761.641.995l.065.097c.076.114.153.23.21.332.028.05.064.12.092.2a.898.898 0 0 1 .052.38c-.01.105-.031.287-.135.473a1.151 1.151 0 0 1-.335.365.94.94 0 0 1-.299.145 1.501 1.501 0 0 1-.205.042c-.12.017-.259.025-.404.03-.28.01-.669.01-1.155.01H4.607c-.487 0-.875 0-1.156-.01a4.065 4.065 0 0 1-.404-.03 1.498 1.498 0 0 1-.205-.042.942.942 0 0 1-.299-.145 1.151 1.151 0 0 1-.335-.365 1.157 1.157 0 0 1-.135-.473.895.895 0 0 1 .053-.38c.029-.08.064-.15.093-.2.056-.101.133-.218.209-.332l.065-.097c.157-.234.368-.55.64-.995.589-.964 1.117-2.409 1.117-4.514 0-1.454.62-2.837 1.703-3.849C7.035 2.56 8.491 2 10 2Z"},"children":[]}],"metadata":""}]},"name":"activity-filled"};
7
+
8
+ export default ActivityFilled;
@@ -0,0 +1,8 @@
1
+
2
+ // This icon file is generated automatically.
3
+
4
+ import { IconDefinition } from '../types';
5
+
6
+ const AiAssistantFilled: IconDefinition = {"icon":{"type":"root","children":[{"type":"element","tagName":"svg","properties":{"viewBox":"0 0 20 20"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","clipRule":"evenodd","d":"M3.374.262a.398.398 0 0 0-.75.006l-.548 1.607a.317.317 0 0 1-.207.2l-1.59.493a.395.395 0 0 0-.006.754l1.595.524a.317.317 0 0 1 .202.202l.552 1.68c.119.36.629.364.753.006l.587-1.69a.317.317 0 0 1 .199-.197l1.568-.526a.395.395 0 0 0-.006-.752l-1.564-.494a.317.317 0 0 1-.203-.195L3.374.262Zm-.562 14.956a.332.332 0 0 0-.626.006l-.456 1.338a.264.264 0 0 1-.172.168l-1.325.41a.33.33 0 0 0-.006.628l1.33.437c.08.027.142.089.168.169l.46 1.399c.099.3.524.304.628.005l.488-1.409a.264.264 0 0 1 .166-.163l1.308-.439a.33.33 0 0 0-.006-.626l-1.303-.412a.264.264 0 0 1-.17-.162l-.484-1.349Zm9.183-12.814c-.336-.936-1.663-.924-1.983.017l-1.47 4.33a1.2 1.2 0 0 1-.78.76L3.506 8.835c-.975.304-.986 1.68-.017 2l4.273 1.41a1.2 1.2 0 0 1 .764.767l1.482 4.53c.314.957 1.662.968 1.99.017l1.578-4.566a1.2 1.2 0 0 1 .752-.745l4.202-1.415c.963-.324.95-1.689-.017-1.996L14.326 7.51a1.2 1.2 0 0 1-.766-.74l-1.565-4.365Z"},"children":[]}],"metadata":""}]},"name":"ai-assistant-filled"};
7
+
8
+ export default AiAssistantFilled;