@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
@@ -5,6 +5,8 @@ import {GroupHeadingProps, GroupProps, MenuListProps} from "react-select";
5
5
  import {ItemContent, Virtuoso, VirtuosoHandle} from "react-virtuoso";
6
6
  import {layout} from "../../../src/design-system";
7
7
  import {GroupBase, ReactSelectRefContext} from "../util";
8
+ import {useSelectControlSettings} from "../select-control-settings-context";
9
+ import {useIsPhone} from "../../use-is-phone";
8
10
 
9
11
  const PADDING_BLOCK_HEIGHT = 6;
10
12
 
@@ -72,6 +74,8 @@ export function MenuListVirtualized<
72
74
  Group extends GroupBase<Option> = GroupBase<Option>
73
75
  >(props: MenuListProps<Option, IsMulti, Group>) {
74
76
  const {children, focusedOption, innerRef, maxHeight, theme, getStyles, cx, selectProps} = props;
77
+ const isPhone = useIsPhone();
78
+ const {inPopover} = useSelectControlSettings();
75
79
  const virtuoso = useRef<VirtuosoHandle>(null);
76
80
 
77
81
  // options props come non-filtered, and we have insufficient info (props) to render groups and options from here.
@@ -195,8 +199,8 @@ export function MenuListVirtualized<
195
199
  ref={virtuoso}
196
200
  // in reality only HTMLDiveElement | null will appear here. We do not use Virtuoso's useWindowScroll prop
197
201
  scrollerRef={innerRef as (ref: HTMLElement | Window | null) => void}
198
- style={{height: menuHeight}}
199
- fixedItemHeight={layout.menuItemHeight}
202
+ style={isPhone && inPopover ? undefined : {height: menuHeight}}
203
+ fixedItemHeight={isPhone ? layout.mobileMenuItemHeight : layout.menuItemHeight}
200
204
  data={flattenChildren}
201
205
  totalCount={flattenChildren.length}
202
206
  itemContent={drawListElement}
@@ -7,9 +7,13 @@ import {ListRowContent, ListRowSurface} from "../../lists/list-row-surface";
7
7
  import {TooltipIfOverflown} from "../../tooltip-if-overflown";
8
8
  import {GroupBase} from "../index";
9
9
  import {isPureTextChildren} from "../util";
10
+ import {mobileRootSelector} from "../../mobile-styles";
10
11
 
11
12
  export const OptionNulledVitualizedStyles = {
12
13
  height: layout.menuItemHeight,
14
+ [`${mobileRootSelector} &`]: {
15
+ height: layout.mobileMenuItemHeight,
16
+ },
13
17
  };
14
18
  export const OptionNulledStyles = {
15
19
  minHeight: layout.menuItemHeight,
@@ -1,6 +1,10 @@
1
1
  import {createContext, ReactNode, useContext, useMemo} from "react";
2
2
 
3
- const SelectControlSettings = createContext<{getPopupContainerElement?: () => HTMLElement | null; zIndex?: number}>({});
3
+ const SelectControlSettings = createContext<{
4
+ getPopupContainerElement?: () => HTMLElement | null;
5
+ zIndex?: number;
6
+ inPopover?: boolean;
7
+ }>({});
4
8
 
5
9
  // Overrides zIndex and getPopupContainerElement for all selects, except select-in-popover.
6
10
  // It has more priority than "menuPortalTarget" prop. Use at your own risk!
@@ -8,12 +12,17 @@ export function SelectControlSettingsProvider({
8
12
  children,
9
13
  getPopupContainerElement,
10
14
  zIndex,
15
+ inPopover = false,
11
16
  }: {
12
17
  children: ReactNode;
13
18
  getPopupContainerElement?: () => HTMLElement | null;
14
19
  zIndex?: number;
20
+ inPopover?: boolean;
15
21
  }) {
16
- const settings = useMemo(() => ({getPopupContainerElement, zIndex}), [getPopupContainerElement, zIndex]);
22
+ const settings = useMemo(
23
+ () => ({getPopupContainerElement, zIndex, inPopover}),
24
+ [getPopupContainerElement, zIndex, inPopover]
25
+ );
17
26
  return <SelectControlSettings.Provider value={settings}>{children}</SelectControlSettings.Provider>;
18
27
  }
19
28
 
@@ -15,7 +15,7 @@ import React, {
15
15
  } from "react";
16
16
  import {inputOverrides} from "../antd/styles";
17
17
  import {border, space, textStyles} from "../design-system";
18
- import {Popover} from "../popover";
18
+ import {Popover, Placement} from "../popover";
19
19
  import {useIsPhone} from "../use-is-phone";
20
20
  import {MenuTransparent} from "./components/menu";
21
21
  import {
@@ -60,6 +60,8 @@ export const popupClassName = css`
60
60
  max-width: 440px;
61
61
  `;
62
62
  const mobileClassName = css`
63
+ display: grid;
64
+ min-height: 0;
63
65
  padding-top: ${space.s12}px;
64
66
  padding-left: ${space.s12}px;
65
67
  padding-right: ${space.s12}px;
@@ -161,6 +163,7 @@ type Props<T, U extends boolean, V extends GroupBase<T>> = {
161
163
  forbidValuesClearInCollnMode?: boolean;
162
164
  otherSelectProps?: Record<string, unknown>;
163
165
  isOptionDisabled?: (option: T) => boolean;
166
+ popoverPlacement?: Placement;
164
167
  };
165
168
 
166
169
  function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
@@ -200,6 +203,7 @@ function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
200
203
  otherSelectProps,
201
204
  forbidValuesClearInCollnMode,
202
205
  isOptionDisabled,
206
+ popoverPlacement = "bottom-start",
203
207
  } = props;
204
208
  const [visible, setVisible] = useControllableState({
205
209
  value: menuIsOpen,
@@ -208,6 +212,7 @@ function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
208
212
  return value ? onMenuOpen?.() : onMenuClose?.();
209
213
  },
210
214
  });
215
+ const isPhone = useIsPhone();
211
216
  const blurTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
212
217
  const selectRef = useRef<SelectInstance<T, U, V>>(null);
213
218
  const [triggerElement, setTriggerElement] = useState<HTMLDivElement | null>(null);
@@ -268,8 +273,8 @@ function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
268
273
  }, [disabled, onMenuOpen, setVisible]);
269
274
 
270
275
  const styles = useMemo(() => {
271
- return combineStyles<T, U, V>([makeSelectInPopoverStyles(), selectStyles]);
272
- }, [selectStyles]);
276
+ return combineStyles<T, U, V>([makeSelectInPopoverStyles(isPhone), selectStyles]);
277
+ }, [selectStyles, isPhone]);
273
278
 
274
279
  const onTriggerClick: React.MouseEventHandler = useCallback(
275
280
  (event) => {
@@ -306,8 +311,6 @@ function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
306
311
  [onHide, onSelectKeyDown, visible]
307
312
  );
308
313
 
309
- const isPhone = useIsPhone();
310
-
311
314
  const onBlur: React.FocusEventHandler<HTMLDivElement> = useCallback(() => {
312
315
  if (isPhone) {
313
316
  return;
@@ -370,13 +373,13 @@ function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
370
373
  popupContainerClassName={popupContainerClassName}
371
374
  popupClassName={cx(popupClassName, popupStyles)}
372
375
  mobilePopupContentClassName={mobileClassName}
373
- placement="bottom-start"
376
+ placement={popoverPlacement}
374
377
  >
375
378
  {title && !isPhone && <div className={titleClassName}>{title}</div>}
376
379
  {/*Usually we set popupContainerElement for react-select via context (SelectControlSettingsProvider). But here we render react-select in popover.*/}
377
380
  {/*Render target in controlled by Popover here. So we just override SelectControlContext here and set popupContainerElement to undefined. */}
378
381
  {/*So in dom react-select will be a child of popover. */}
379
- <SelectControlSettingsProvider getPopupContainerElement={undefined}>
382
+ <SelectControlSettingsProvider inPopover={true} getPopupContainerElement={undefined}>
380
383
  <ReactSelect<T, U, V>
381
384
  ref={selectRef}
382
385
  styles={styles}
@@ -158,13 +158,23 @@ export const makeSingleLineStyles = <T, U extends boolean, V extends GroupBase<T
158
158
  control: makeControlStyle<T, U, V>({isSingleLine: true}).control,
159
159
  });
160
160
 
161
- export const makeSelectInPopoverStyles = <T, U extends boolean, V extends GroupBase<T>>(): StylesConfig<T, U, V> => ({
161
+ export const makeSelectInPopoverStyles = <T, U extends boolean, V extends GroupBase<T>>(
162
+ isPhone: boolean
163
+ ): StylesConfig<T, U, V> => ({
162
164
  container: (props) => ({
163
165
  ...props,
164
166
  minWidth: 180,
165
167
  width: "100%",
166
168
  paddingTop: space.s6,
167
169
  paddingInline: space.s6,
170
+ ...(isPhone
171
+ ? {
172
+ display: "grid",
173
+ gridTemplateRows: "auto 1fr",
174
+ minHeight: 0,
175
+ paddingBottom: space.s20,
176
+ }
177
+ : {}),
168
178
  }),
169
179
  option: (props) => ({
170
180
  ...props,
@@ -182,6 +192,16 @@ export const makeSelectInPopoverStyles = <T, U extends boolean, V extends GroupB
182
192
  width: `calc(100% - ${space.s2 * 2}px)`,
183
193
  borderRadius: border.radius4,
184
194
  }),
195
+ menuList: (props) => {
196
+ if (isPhone) {
197
+ return {
198
+ ...props,
199
+ maxHeight: "100%",
200
+ height: "100%",
201
+ };
202
+ }
203
+ return props;
204
+ },
185
205
  menu: (props) => ({
186
206
  ...props,
187
207
  minWidth: 100,
@@ -40,7 +40,7 @@ const tabNavItemWide = css`
40
40
  flex: 1 0 0;
41
41
  `;
42
42
 
43
- const tabButton = css`
43
+ export const tabButton = css`
44
44
  all: unset;
45
45
  display: flex;
46
46
  align-items: center;
package/src/toggle.tsx CHANGED
@@ -5,6 +5,7 @@ import {ComponentProps, FC, ReactNode} from "react";
5
5
  import {space, textStyles, transition} from "./design-system";
6
6
  import _ from "lodash";
7
7
  import SpinnerIcon from "./icons/react/Spinner";
8
+ import {mobileRootSelector} from "./mobile-styles";
8
9
 
9
10
  const toggleIconHeightVar = "--fibery-toggle-icon-height";
10
11
  const toggleIconWidthVar = "--fibery-toggle-icon-width";
@@ -32,6 +33,7 @@ const Input = styled.input<{outlineColor: string}>`
32
33
  `;
33
34
 
34
35
  const Label = styled.div<{labelPosition: "last" | "first"; disabled?: boolean}>`
36
+ display: flex;
35
37
  margin-left: ${({labelPosition}) => (labelPosition === "last" ? `${space.s8}px` : 0)};
36
38
  margin-right: ${({labelPosition}) => (labelPosition === "first" ? `${space.s8}px` : 0)};
37
39
  opacity: ${({disabled}) => (disabled ? 0.5 : 1)};
@@ -94,10 +96,16 @@ const toggleSize = {
94
96
  large: css`
95
97
  ${textStyles.regular}
96
98
  ${toggleIconHeightVar}: 18px;
99
+ ${mobileRootSelector} & {
100
+ ${textStyles.big}
101
+ }
97
102
  `,
98
103
  "extra-large": css`
99
104
  ${textStyles.regular}
100
105
  ${toggleIconHeightVar}: 20px;
106
+ ${mobileRootSelector} & {
107
+ ${textStyles.big}
108
+ }
101
109
  `,
102
110
  };
103
111
  const toggleSizeStyle = css`
package/src/tooltip.tsx CHANGED
@@ -2,7 +2,6 @@ import {css, cx} from "@linaria/core";
2
2
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
3
3
  import {forwardRef, type ReactNode, type SyntheticEvent} from "react";
4
4
  import {border, fontWeight, lineHeight, space, themeVars, tooltipDelay} from "./design-system";
5
- import {ShortcutBadge} from "./shortcut-badge";
6
5
 
7
6
  const isFlagPresent = (flag: string) => new RegExp(`[?&]${flag}\\b`).test(window.location.search);
8
7
 
@@ -76,33 +75,43 @@ const whiteBgStyle = css`
76
75
  `;
77
76
 
78
77
  export const TooltipTitle = ({children}: {children: ReactNode}) => <div className={titleStyle}>{children}</div>;
78
+
79
79
  export const TooltipDescription = ({children}: {children: ReactNode}) => (
80
80
  <div className={descriptionStyle}>{children}</div>
81
81
  );
82
82
 
83
- export const TooltipContent = ({title, shortcut}: {title: string; shortcut?: string}) => (
84
- <div
85
- className={css`
86
- display: flex;
87
- flex-direction: column;
88
- align-items: center;
89
- gap: ${space.s4}px;
90
- `}
91
- >
92
- <TooltipTitle>{title}</TooltipTitle>
93
- {shortcut ? (
94
- <TooltipDescription>
95
- <ShortcutBadge shortcut={shortcut} />
96
- </TooltipDescription>
97
- ) : null}
98
- </div>
99
- );
83
+ export const TooltipContent = ({
84
+ direction = "horizontal",
85
+ className,
86
+ ...rest
87
+ }: {direction?: "horizontal" | "vertical"} & React.ComponentProps<"div">) => {
88
+ return (
89
+ <div
90
+ className={cx(
91
+ className,
92
+ direction === "horizontal"
93
+ ? css`
94
+ display: flex;
95
+ align-items: center;
96
+ gap: ${space.s8}px;
97
+ `
98
+ : css`
99
+ display: flex;
100
+ flex-direction: column;
101
+ align-items: center;
102
+ gap: ${space.s4}px;
103
+ `
104
+ )}
105
+ {...rest}
106
+ />
107
+ );
108
+ };
100
109
 
101
110
  export const TooltipProvider: React.FC<TooltipPrimitive.TooltipProviderProps> = (props) => (
102
111
  <TooltipPrimitive.Provider disableHoverableContent skipDelayDuration={150} {...props} />
103
112
  );
104
113
 
105
- export type TooltipProps = Omit<TooltipPrimitive.TooltipTriggerProps, "title"> & {
114
+ export type TooltipProps = Omit<TooltipPrimitive.TooltipTriggerProps, "title" | "content"> & {
106
115
  title?: ReactNode;
107
116
  description?: ReactNode;
108
117
  tooltipContentStyle?: string;
@@ -150,6 +150,7 @@ type TypeBadgeProps = {
150
150
  tooltip?: ReactNode;
151
151
  faded?: boolean;
152
152
  big?: boolean;
153
+ style?: CSSProperties;
153
154
  vertical?: boolean;
154
155
  className?: string;
155
156
  noTooltip?: boolean; // pass true to force disable tooltip for abbr
@@ -173,6 +174,7 @@ export const TypeBadge = memo(
173
174
  vertical = false,
174
175
  className,
175
176
  noTooltip,
177
+ style,
176
178
  },
177
179
  ref
178
180
  ) {
@@ -206,7 +208,8 @@ export const TypeBadge = memo(
206
208
  light2: baseColor,
207
209
  });
208
210
 
209
- const style = {
211
+ const resultingStyle = {
212
+ ...style,
210
213
  [colorProp]: baseColor ? textBadgeColor : colors.inversedTextColor,
211
214
  //[colorProp]: baseColor ? getTextColor(baseColor) : colors.inversedTextColor,
212
215
  [colorBackgroundProp]: backgroundBadgeColor || colors.shades.opacity25,
@@ -220,7 +223,7 @@ export const TypeBadge = memo(
220
223
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
221
224
  // @ts-ignore
222
225
  ref={ref}
223
- style={style}
226
+ style={resultingStyle}
224
227
  className={cx(
225
228
  typeBadgeStyle,
226
229
  big ? bigTypeBadgeStaticStyle : compact ? compactTypeBadgeStaticStyle : normalTypeBadgeStaticStyle,
@@ -31,7 +31,7 @@ export const UnitWithTooltip = ({children, title, description}: Props) => {
31
31
  // Had to use additional way to validate if we are still over unit
32
32
  if (isHoveredRef.current && unitElementRef.current && unitElementRef.current.matches(":hover")) {
33
33
  setShouldDisplayTooltip(true);
34
- const intervalId = setInterval(() => {
34
+ const intervalId = window.setInterval(() => {
35
35
  if (isHoveredRef.current && unitElementRef.current) {
36
36
  if (!unitElementRef.current.matches(":hover")) {
37
37
  isHoveredRef.current = false;
@@ -1,7 +1,8 @@
1
- import {ReactNode} from "react";
1
+ import {ReactNode, useLayoutEffect} from "react";
2
2
  import {createContext} from "@fibery/react/src/create-context";
3
3
  import {useIsMediaQueryMatched} from "./use-is-media-query-matched";
4
4
  import {getMediaQueryList} from "./media-query-utils";
5
+ import {mobileRootClassName} from "./mobile-styles";
5
6
 
6
7
  const [Provider, useIsPhone] = createContext<boolean>("PhoneContext", false);
7
8
 
@@ -23,15 +24,42 @@ function isVerticalMobileBreakpointDisabled() {
23
24
  return urlParams.has("no-vertical-mobile-breakpoint");
24
25
  }
25
26
 
26
- const phoneMediaQuery = isVerticalMobileBreakpointDisabled()
27
- ? "(max-width: 440px)"
28
- : "(max-width: 440px), (max-height: 440px)";
27
+ export const isPhoneApp = Boolean(
28
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
29
+ // @ts-ignore - injected by consumer app
30
+ window.__FIBERY_MOBILE_APP_API
31
+ );
32
+
33
+ export const phoneMediaQuery = isVerticalMobileBreakpointDisabled()
34
+ ? "(max-width: 450px)"
35
+ : "(max-width: 450px), (max-height: 450px)";
29
36
 
30
37
  export function isPhoneMode() {
31
- return getMediaQueryList(phoneMediaQuery).matches;
38
+ return isPhoneApp || getMediaQueryList(phoneMediaQuery).matches;
32
39
  }
33
40
 
34
41
  export function IsPhoneProvider({children}: {children: ReactNode}) {
35
42
  const isPhone = useIsMediaQueryMatched(phoneMediaQuery);
36
- return <Provider value={isPhone}>{children}</Provider>;
43
+ useLayoutEffect(() => {
44
+ const htmlElement = document.querySelector("html");
45
+ if (!htmlElement || isPhoneApp) {
46
+ if (htmlElement) {
47
+ htmlElement.classList.add(mobileRootClassName);
48
+ return () => {
49
+ htmlElement.classList.remove(mobileRootClassName);
50
+ };
51
+ }
52
+ // eslint-disable-next-line consistent-return
53
+ return;
54
+ }
55
+ if (isPhone) {
56
+ htmlElement.classList.add(mobileRootClassName);
57
+ } else {
58
+ htmlElement.classList.remove(mobileRootClassName);
59
+ }
60
+ return () => {
61
+ htmlElement.classList.remove(mobileRootClassName);
62
+ };
63
+ }, [isPhone]);
64
+ return <Provider value={isPhoneApp || isPhone}>{children}</Provider>;
37
65
  }
@@ -1,29 +0,0 @@
1
- import {css, cx} from "@linaria/core";
2
- import {textStyles, border, space, lineHeight, themeVars} from "./design-system";
3
- import {useIsSupportHardwareKeyboard} from "./use-is-support-hardware-keyboard";
4
-
5
- export const shortcutCss = css`
6
- ${{
7
- ...textStyles.small,
8
- ...textStyles.numeric.tabularOn,
9
- borderRadius: border.radius4,
10
- border: themeVars.shortcutBorderColor,
11
- color: themeVars.shortcutTextColor,
12
- paddingTop: space.s2,
13
- paddingBottom: space.s2,
14
- paddingLeft: space.s4,
15
- paddingRight: space.s4,
16
- lineHeight: lineHeight.nowrap,
17
- whiteSpace: "nowrap",
18
- display: "inline-block",
19
- userSelect: "none",
20
- }}
21
- `;
22
-
23
- export const ShortcutBadge = ({className, shortcut}: {className?: string; shortcut: string}): JSX.Element | null => {
24
- const isSupportHardwareKeyboard = useIsSupportHardwareKeyboard();
25
- if (!isSupportHardwareKeyboard) {
26
- return null;
27
- }
28
- return <div className={cx(shortcutCss, className)}>{shortcut}</div>;
29
- };