@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.
- package/CHANGELOG.md +25 -0
- package/config/jest/testFrameworkSetup.js +1 -1
- package/package.json +20 -16
- package/src/abbreviate-name.ts +42 -0
- package/src/actions-menu/actions-menu-item.tsx +32 -11
- package/src/actions-menu/actions-menu-props.tsx +5 -0
- package/src/actions-menu/actions-menu-sub-command-menu.tsx +7 -4
- package/src/actions-menu/actions-menu-sub-menu.tsx +9 -3
- package/src/actions-menu/actions-menu.tsx +28 -9
- package/src/actions-menu/context-actions-menu.tsx +22 -0
- package/src/actions-panel.tsx +12 -2
- package/src/animated-height-container.tsx +24 -5
- package/src/antd/ant-upload.tsx +1 -1
- package/src/antd/input.tsx +4 -0
- package/src/avatar.tsx +1 -27
- package/src/axis-header.tsx +136 -76
- package/src/box.tsx +1 -1
- package/src/breadcrumb.tsx +78 -0
- package/src/button/actions-button-compact.tsx +4 -1
- package/src/button/base-button.tsx +7 -3
- package/src/button/button-group.tsx +1 -1
- package/src/button/button.tsx +33 -1
- package/src/button/icon-button.tsx +10 -1
- package/src/button/select-button.tsx +4 -0
- package/src/card-container.tsx +10 -6
- package/src/checkbox.tsx +17 -0
- package/src/collapsible-section.tsx +3 -1
- package/src/color-picker/swatch.tsx +1 -0
- package/src/command-menu/index.tsx +3 -3
- package/src/context-menu/index.tsx +10 -1
- package/src/date-picker/autocomplete.tsx +11 -5
- package/src/date-picker/date-range-input.tsx +5 -1
- package/src/date-picker/date-range-picker-popup-content.tsx +31 -13
- package/src/date-picker/date-range-picker.tsx +6 -3
- package/src/date-picker/relative-date-picker.tsx +6 -2
- package/src/date-picker/single-date-input.tsx +5 -1
- package/src/date-picker/single-date-picker.tsx +8 -5
- package/src/date-picker/styles.ts +52 -26
- package/src/date-picker/types.ts +3 -1
- package/src/day-select/day-select.tsx +21 -75
- package/src/day-select/iso-week-day-select.tsx +1 -1
- package/src/day-select/mount-day-select.tsx +2 -2
- package/src/day-select/week-day-select.tsx +1 -5
- package/src/design-system.ts +45 -12
- package/src/dropdown-menu/index.tsx +19 -2
- package/src/emoji-picker/app-icon-picker.tsx +6 -4
- package/src/emoji-picker/emoji-picker-preview-footer.tsx +5 -1
- package/src/emoji-picker/emoji-picker.tsx +3 -0
- package/src/emoji-picker/emoji.tsx +5 -3
- package/src/emoji-picker/icon-emoji-picker.tsx +10 -1
- package/src/emoji-picker/primitives/emoji.tsx +49 -51
- package/src/emoji-picker/primitives/footer.tsx +5 -0
- package/src/emoji-picker/primitives/search.tsx +8 -0
- package/src/emoji-picker/primitives/skin-tone.tsx +12 -1
- package/src/emoji-picker/use-responsive-emoji-size.ts +11 -0
- package/src/emoji-picker/utils/emoji-set.ts +2 -1
- package/src/empty-state/empty-state.tsx +6 -0
- package/src/fibermoji-placeholder.tsx +1 -27
- package/src/field-icon.tsx +4 -1
- package/src/file-item-2.tsx +408 -0
- package/src/file-item.tsx +215 -47
- package/src/header-layout.tsx +11 -0
- package/src/html-styles.ts +21 -4
- package/src/icons/ast/ActivityFilled.ts +8 -0
- package/src/icons/ast/AiAssistantFilled.ts +8 -0
- package/src/icons/ast/Back.ts +1 -1
- package/src/icons/ast/CollapseAllHorizontal.ts +8 -0
- package/src/icons/ast/DateRange.ts +1 -1
- package/src/icons/ast/EntityCreateFilled.ts +8 -0
- package/src/icons/ast/ExpandAllHorizontal.ts +8 -0
- package/src/icons/ast/ExtensionFiles.ts +1 -1
- package/src/icons/ast/FileUpload.ts +1 -1
- package/src/icons/ast/GlobeUnpublish.ts +8 -0
- package/src/icons/ast/HomeFilled.ts +8 -0
- package/src/icons/ast/KeyboardHideDown.ts +8 -0
- package/src/icons/ast/LayoutMultiple.ts +8 -0
- package/src/icons/ast/RicheditorHistoryRedo.ts +1 -1
- package/src/icons/ast/RicheditorHistoryUndo.ts +1 -1
- package/src/icons/ast/SearchFilled.ts +8 -0
- package/src/icons/ast/SettingsFilled.ts +8 -0
- package/src/icons/ast/SlideMenuFilled.ts +8 -0
- package/src/icons/ast/SwitchToMention.ts +8 -0
- package/src/icons/ast/SwitchToText.ts +8 -0
- package/src/icons/ast/SwitchToWidget.ts +8 -0
- package/src/icons/ast/TypeDate.ts +1 -1
- package/src/icons/ast/ViewGallery.ts +8 -0
- package/src/icons/ast/index.tsx +16 -0
- package/src/icons/react/ActivityFilled.tsx +13 -0
- package/src/icons/react/AiAssistantFilled.tsx +13 -0
- package/src/icons/react/CollapseAllHorizontal.tsx +13 -0
- package/src/icons/react/EntityCreateFilled.tsx +13 -0
- package/src/icons/react/ExpandAllHorizontal.tsx +13 -0
- package/src/icons/react/GlobeUnpublish.tsx +13 -0
- package/src/icons/react/HomeFilled.tsx +13 -0
- package/src/icons/react/KeyboardHideDown.tsx +13 -0
- package/src/icons/react/LayoutMultiple.tsx +13 -0
- package/src/icons/react/SearchFilled.tsx +13 -0
- package/src/icons/react/SettingsFilled.tsx +13 -0
- package/src/icons/react/SlideMenuFilled.tsx +13 -0
- package/src/icons/react/SwitchToMention.tsx +13 -0
- package/src/icons/react/SwitchToText.tsx +13 -0
- package/src/icons/react/SwitchToWidget.tsx +13 -0
- package/src/icons/react/ViewGallery.tsx +13 -0
- package/src/icons/react/index.tsx +16 -0
- package/src/icons/svg/activity-filled.svg +4 -0
- package/src/icons/svg/ai-assistant-filled.svg +3 -0
- package/src/icons/svg/back.svg +3 -1
- package/src/icons/svg/collapse-all-horizontal.svg +3 -0
- package/src/icons/svg/date-range.svg +3 -3
- package/src/icons/svg/entity-create-filled.svg +4 -0
- package/src/icons/svg/expand-all-horizontal.svg +3 -0
- package/src/icons/svg/extension/files.svg +3 -1
- package/src/icons/svg/file-upload.svg +3 -6
- package/src/icons/svg/globe-unpublish.svg +4 -0
- package/src/icons/svg/home-filled.svg +3 -0
- package/src/icons/svg/keyboard-hide-down.svg +1 -0
- package/src/icons/svg/layout-multiple.svg +3 -0
- package/src/icons/svg/richeditor/history/redo.svg +3 -2
- package/src/icons/svg/richeditor/history/undo.svg +3 -2
- package/src/icons/svg/search-filled.svg +3 -0
- package/src/icons/svg/settings-filled.svg +3 -0
- package/src/icons/svg/slide-menu-filled.svg +1 -0
- package/src/icons/svg/switch-to-mention.svg +3 -0
- package/src/icons/svg/switch-to-text.svg +4 -0
- package/src/icons/svg/switch-to-widget.svg +4 -0
- package/src/icons/svg/type/date.svg +3 -2
- package/src/icons/svg/view-gallery.svg +4 -0
- package/src/images-gallery/images-gallery-fall-through-provider.tsx +11 -0
- package/src/images-gallery/images-gallery.tsx +257 -0
- package/src/images-gallery/zoom.tsx +123 -0
- package/src/images-gallery-2/images-gallery-2.tsx +442 -0
- package/src/images-gallery-2/slide-buttons.tsx +230 -0
- package/src/images-gallery-2/zoom.tsx +35 -0
- package/src/is-in-popup.ts +1 -1
- package/src/kbd.tsx +46 -0
- package/src/layout-styles.ts +21 -1
- package/src/lists/actions-menu-row-surface.tsx +3 -1
- package/src/lists/list-row-surface.tsx +7 -1
- package/src/mobile-keyboard-aware-popup.tsx +87 -0
- package/src/mobile-styles.ts +8 -0
- package/src/modal-menu/contexts/modal-menu-context.tsx +22 -0
- package/src/modal-menu/contexts/modal-submenu-context.tsx +16 -0
- package/src/modal-menu/index.tsx +14 -0
- package/src/modal-menu/modal-menu-content.tsx +68 -0
- package/src/modal-menu/modal-menu-group.tsx +10 -0
- package/src/modal-menu/modal-menu-item.tsx +45 -0
- package/src/modal-menu/modal-menu-label.tsx +24 -0
- package/src/modal-menu/modal-menu-root.tsx +57 -0
- package/src/modal-menu/modal-menu-separator.tsx +14 -0
- package/src/modal-menu/modal-menu-trigger.tsx +54 -0
- package/src/modal-menu/modal-submenu-content.tsx +49 -0
- package/src/modal-menu/modal-submenu-trigger.tsx +34 -0
- package/src/modal-menu/modal-submenu.tsx +17 -0
- package/src/notification-dot.tsx +16 -7
- package/src/online-users.tsx +3 -3
- package/src/palette.ts +1 -1
- package/src/platform-symbols.ts +9 -0
- package/src/platform.ts +2 -0
- package/src/popover/index.tsx +710 -0
- package/src/popover/mobile-popup-context.tsx +29 -0
- package/src/{popup → popover}/modifiers.tsx +25 -25
- package/src/{popup → popover}/popup-modifiers-context.ts +3 -3
- package/src/reactions/reaction-button.tsx +342 -135
- package/src/reactions/reaction-picker.tsx +51 -44
- package/src/reactions/reactions.tsx +11 -1
- package/src/reactions/tootltip.tsx +55 -0
- package/src/rich-text-embed-error.tsx +2 -1
- package/src/select/components/group-heading.tsx +8 -0
- package/src/select/components/menu-list-virtualized.tsx +6 -2
- package/src/select/components/option.tsx +4 -0
- package/src/select/index.tsx +8 -4
- package/src/select/select-control-settings-context.tsx +11 -2
- package/src/select/select-in-popover.tsx +30 -39
- package/src/select/styles.ts +21 -1
- package/src/tab-nav/tab-nav.tsx +36 -10
- package/src/toast/primitives.tsx +8 -1
- package/src/toggle-button/round-toggle-button.tsx +23 -0
- package/src/toggle-button/toggle-button-group.tsx +34 -0
- package/src/toggle-button/toggle-button.tsx +164 -0
- package/src/toggle.tsx +11 -3
- package/src/tooltip.tsx +29 -20
- package/src/type-badge.tsx +5 -2
- package/src/unit/styles.ts +2 -2
- package/src/unit/unit-with-tooltip.tsx +1 -1
- package/src/use-is-phone.tsx +50 -4
- package/src/use-is-support-hover.ts +1 -1
- package/src/use-on-screen-keyboard-data.tsx +66 -0
- package/src/workflow-progress-icon.tsx +16 -22
- package/src/popup/index.tsx +0 -383
- package/src/shortcut-badge.tsx +0 -29
- /package/src/{popup → popover}/popup-stack-context.tsx +0 -0
- /package/src/{popup → popover}/reference.ts +0 -0
- /package/src/{popup → popover}/styles.ts +0 -0
- /package/src/{popup → popover}/use-click-outside.ts +0 -0
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import {EmojiItem} from "@fibery/emoji-data";
|
|
2
|
-
import {measureScrollbar} from "@fibery/helpers/utils/measure-scrollbar";
|
|
3
2
|
import {useControllableState} from "@fibery/react/src/use-controllable-state";
|
|
4
3
|
import {css} from "@linaria/core";
|
|
5
4
|
import {CSSProperties, type FC, useCallback, useState} from "react";
|
|
6
5
|
import {IconButton} from "../button/icon-button";
|
|
7
6
|
import {layout, space, themeVars} from "../design-system";
|
|
8
7
|
import {type EmojiPickerProps} from "../emoji-picker/emoji-picker";
|
|
8
|
+
import {useResponsiveEmojiSize} from "../emoji-picker/use-responsive-emoji-size";
|
|
9
9
|
import AddReactions from "../icons/react/AddReactions";
|
|
10
|
-
import {
|
|
10
|
+
import {Popover} from "../popover";
|
|
11
|
+
import {ToggleButton} from "../toggle-button/toggle-button";
|
|
11
12
|
import {Tooltip} from "../tooltip";
|
|
13
|
+
import {mobileRootSelector} from "../mobile-styles";
|
|
12
14
|
import {useIsPhone} from "../use-is-phone";
|
|
13
|
-
import {reactionButtonCss} from "./reaction-button";
|
|
14
15
|
|
|
15
16
|
type Props = {
|
|
16
17
|
mode: "default" | "in-row";
|
|
@@ -28,6 +29,14 @@ const popupContainerCss = css`
|
|
|
28
29
|
z-index: ${zIndex};
|
|
29
30
|
`;
|
|
30
31
|
|
|
32
|
+
const buttonCss = css`
|
|
33
|
+
${mobileRootSelector} & {
|
|
34
|
+
min-width: ${space.s28}px;
|
|
35
|
+
height: ${space.s28}px;
|
|
36
|
+
padding-inline: ${space.s8}px;
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
|
|
31
40
|
const popupCss = css`
|
|
32
41
|
//background-color: transparent;
|
|
33
42
|
//box-shadow: none;
|
|
@@ -52,7 +61,7 @@ const pickerOffset: [number, number] = [0, space.s4];
|
|
|
52
61
|
export const ReactionPicker = ({mode, onSelect, open, onOpenChange, EmojiPicker}: Props): JSX.Element => {
|
|
53
62
|
const [isOpen = false, setOpen] = useControllableState({value: open, onChange: onOpenChange});
|
|
54
63
|
const [triggerDomElement, setTriggerDomElement] = useState<HTMLButtonElement | null>(null);
|
|
55
|
-
const
|
|
64
|
+
const emojiSize = useResponsiveEmojiSize();
|
|
56
65
|
const onEmojiSelect = useCallback(
|
|
57
66
|
(emojiData: EmojiItem) => {
|
|
58
67
|
onSelect(emojiData.colons);
|
|
@@ -61,66 +70,64 @@ export const ReactionPicker = ({mode, onSelect, open, onOpenChange, EmojiPicker}
|
|
|
61
70
|
[onSelect, setOpen]
|
|
62
71
|
);
|
|
63
72
|
|
|
73
|
+
const isPhone = useIsPhone();
|
|
74
|
+
|
|
64
75
|
return (
|
|
65
76
|
<div>
|
|
66
77
|
<Tooltip side="bottom" title="Add reaction">
|
|
67
78
|
{mode === "in-row" ? (
|
|
68
|
-
<
|
|
79
|
+
<ToggleButton
|
|
80
|
+
className={buttonCss}
|
|
69
81
|
ref={setTriggerDomElement}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
82
|
+
onClick={() => setOpen(!isOpen)}
|
|
83
|
+
aria-expanded={isOpen}
|
|
84
|
+
aria-pressed={undefined}
|
|
85
|
+
style={{
|
|
86
|
+
// TODO: add IconToggleButton? or a separate prop?
|
|
87
|
+
width: "24px",
|
|
88
|
+
justifyContent: "center",
|
|
89
|
+
paddingInline: 0,
|
|
73
90
|
}}
|
|
74
|
-
className={reactionButtonCss}
|
|
75
91
|
>
|
|
76
|
-
<AddReactions
|
|
77
|
-
</
|
|
92
|
+
<AddReactions iconSize={isPhone ? 20 : 16} />
|
|
93
|
+
</ToggleButton>
|
|
78
94
|
) : (
|
|
79
95
|
<IconButton
|
|
80
96
|
ref={setTriggerDomElement}
|
|
97
|
+
aria-expanded={isOpen}
|
|
81
98
|
onClick={() => {
|
|
82
99
|
setOpen(!isOpen);
|
|
83
100
|
}}
|
|
84
101
|
size="small"
|
|
102
|
+
supportMobile
|
|
85
103
|
>
|
|
86
104
|
<AddReactions />
|
|
87
105
|
</IconButton>
|
|
88
106
|
)}
|
|
89
107
|
</Tooltip>
|
|
90
|
-
{
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
placement="auto"
|
|
103
|
-
offset={pickerOffset}
|
|
104
|
-
popupContainerClassName={popupContainerCss}
|
|
105
|
-
popupClassName={popupCss}
|
|
106
|
-
open={isOpen}
|
|
107
|
-
triggerDomElement={triggerDomElement}
|
|
108
|
-
trigger={<></>}
|
|
109
|
-
renderInPortal
|
|
110
|
-
onOpen={() => setOpen(true)}
|
|
111
|
-
onClose={() => setOpen(false)}
|
|
112
|
-
>
|
|
113
|
-
<EmojiPicker
|
|
114
|
-
emojiSize={
|
|
115
|
-
isPhone
|
|
116
|
-
? Math.min(Math.floor((document.body.clientWidth - 24 - measureScrollbar() - 9 * 12) / 9), 40)
|
|
117
|
-
: 20
|
|
108
|
+
<Popover.Root open={isOpen} onOpen={() => setOpen(true)} onClose={() => setOpen(false)}>
|
|
109
|
+
<Popover.Trigger reference={triggerDomElement}></Popover.Trigger>
|
|
110
|
+
<Popover.Portal>
|
|
111
|
+
<Popover.Content
|
|
112
|
+
supportMobile
|
|
113
|
+
mobilePopupStyle={
|
|
114
|
+
{
|
|
115
|
+
"--fibery-emoji-container-width": "100%",
|
|
116
|
+
"--fibery-emoji-grid-height": "auto",
|
|
117
|
+
"--fibery-emoji-content-max-height": "auto",
|
|
118
|
+
zIndex: zIndex,
|
|
119
|
+
} as CSSProperties
|
|
118
120
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
title={"Add reaction"}
|
|
122
|
+
placement="auto"
|
|
123
|
+
offset={pickerOffset}
|
|
124
|
+
popupContainerClassName={popupContainerCss}
|
|
125
|
+
popupClassName={popupCss}
|
|
126
|
+
>
|
|
127
|
+
<EmojiPicker emojiSize={emojiSize} showSkinTones onSelect={onEmojiSelect} />
|
|
128
|
+
</Popover.Content>
|
|
129
|
+
</Popover.Portal>
|
|
130
|
+
</Popover.Root>
|
|
124
131
|
</div>
|
|
125
132
|
);
|
|
126
133
|
};
|
|
@@ -4,6 +4,7 @@ import {ReactionPicker} from "./reaction-picker";
|
|
|
4
4
|
import {EmojiPickerProps} from "../emoji-picker/emoji-picker";
|
|
5
5
|
import {space} from "../design-system";
|
|
6
6
|
import {type FC} from "react";
|
|
7
|
+
import {mobileRootSelector} from "../mobile-styles";
|
|
7
8
|
|
|
8
9
|
type Props = {
|
|
9
10
|
reactions: Array<Reaction>;
|
|
@@ -16,13 +17,22 @@ const blockReactionsCss = css`
|
|
|
16
17
|
display: flex;
|
|
17
18
|
flex-wrap: wrap;
|
|
18
19
|
gap: ${space.s4}px;
|
|
20
|
+
${mobileRootSelector} & {
|
|
21
|
+
gap: ${space.s6}px;
|
|
22
|
+
}
|
|
19
23
|
`;
|
|
20
24
|
|
|
21
25
|
export const Reactions: React.FC<Props> = ({reactions, onSelect, readonly, EmojiPicker}) => {
|
|
22
26
|
return (
|
|
23
27
|
<div className={blockReactionsCss}>
|
|
24
28
|
{reactions.map((reaction) => (
|
|
25
|
-
<ReactionButton
|
|
29
|
+
<ReactionButton
|
|
30
|
+
reactions={reactions}
|
|
31
|
+
disabled={readonly}
|
|
32
|
+
key={reaction.key}
|
|
33
|
+
reaction={reaction}
|
|
34
|
+
onSelect={onSelect}
|
|
35
|
+
/>
|
|
26
36
|
))}
|
|
27
37
|
{!readonly ? <ReactionPicker EmojiPicker={EmojiPicker} mode={"in-row"} onSelect={onSelect} /> : null}
|
|
28
38
|
</div>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {css, cx} from "@linaria/core";
|
|
2
|
+
import {border, space, themeVars} from "../design-system";
|
|
3
|
+
import {Emoji} from "../emoji-picker/emoji";
|
|
4
|
+
import {useIsPhone} from "../use-is-phone";
|
|
5
|
+
import {ReactNode} from "react";
|
|
6
|
+
|
|
7
|
+
export const EmojiTooltipTitle = ({emoji}: {emoji: string}) => {
|
|
8
|
+
return (
|
|
9
|
+
<div
|
|
10
|
+
className={css`
|
|
11
|
+
padding-top: ${space.s6}px;
|
|
12
|
+
padding-left: ${space.s6}px;
|
|
13
|
+
padding-right: ${space.s6}px;
|
|
14
|
+
display: flex;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
`}
|
|
17
|
+
>
|
|
18
|
+
<div
|
|
19
|
+
className={css`
|
|
20
|
+
display: flex;
|
|
21
|
+
background-color: ${themeVars.whiteColor};
|
|
22
|
+
padding: ${space.s4}px;
|
|
23
|
+
border-radius: ${border.radius4}px;
|
|
24
|
+
`}
|
|
25
|
+
>
|
|
26
|
+
<Emoji emoji={emoji} size={64} />
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const EmojiTooltipDescription = ({children}: {children: ReactNode}) => {
|
|
33
|
+
const isPhone = useIsPhone();
|
|
34
|
+
return (
|
|
35
|
+
<div
|
|
36
|
+
className={cx(
|
|
37
|
+
css`
|
|
38
|
+
padding-top: ${space.s8}px;
|
|
39
|
+
padding-bottom: ${space.s6}px;
|
|
40
|
+
padding-left: ${space.s6}px;
|
|
41
|
+
padding-right: ${space.s6}px;
|
|
42
|
+
text-align: center;
|
|
43
|
+
word-wrap: break-word;
|
|
44
|
+
color: ${themeVars.whiteColor};
|
|
45
|
+
`,
|
|
46
|
+
!isPhone &&
|
|
47
|
+
css`
|
|
48
|
+
max-width: 200px;
|
|
49
|
+
`
|
|
50
|
+
)}
|
|
51
|
+
>
|
|
52
|
+
{children}
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
@@ -4,6 +4,7 @@ import {layout, space, textStyles, themeVars} from "../../design-system";
|
|
|
4
4
|
import {TooltipIfOverflown} from "../../tooltip-if-overflown";
|
|
5
5
|
import {GroupBase} from "../index";
|
|
6
6
|
import {isPureTextChildren} from "../util";
|
|
7
|
+
import {mobileRootSelector} from "../../mobile-styles";
|
|
7
8
|
|
|
8
9
|
export const groupHeadingNulledStyles = {
|
|
9
10
|
paddingLeft: "",
|
|
@@ -15,6 +16,9 @@ export const groupHeadingNulledStyles = {
|
|
|
15
16
|
...textStyles.small,
|
|
16
17
|
color: "",
|
|
17
18
|
height: layout.menuItemHeight,
|
|
19
|
+
[`${mobileRootSelector} &`]: {
|
|
20
|
+
height: layout.mobileMenuItemHeight,
|
|
21
|
+
},
|
|
18
22
|
};
|
|
19
23
|
const groupHeadingClass = css`
|
|
20
24
|
min-height: ${layout.menuItemHeight}px;
|
|
@@ -26,6 +30,10 @@ const groupHeadingClass = css`
|
|
|
26
30
|
white-space: nowrap;
|
|
27
31
|
overflow: hidden;
|
|
28
32
|
text-overflow: ellipsis;
|
|
33
|
+
${mobileRootSelector} & {
|
|
34
|
+
min-height: ${layout.mobileMenuItemHeight}px;
|
|
35
|
+
font-size: ${textStyles.regular.fontSize}px;
|
|
36
|
+
}
|
|
29
37
|
`;
|
|
30
38
|
const groupHeadingContentClass = css`
|
|
31
39
|
white-space: nowrap;
|
|
@@ -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,
|
package/src/select/index.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import BaseSelect, {
|
|
|
7
7
|
createFilter,
|
|
8
8
|
MenuListProps,
|
|
9
9
|
MenuProps,
|
|
10
|
+
ControlProps,
|
|
10
11
|
mergeStyles,
|
|
11
12
|
MultiValue,
|
|
12
13
|
MultiValueProps,
|
|
@@ -44,6 +45,7 @@ export type {
|
|
|
44
45
|
GroupBase,
|
|
45
46
|
MenuListProps,
|
|
46
47
|
MenuProps,
|
|
48
|
+
ControlProps,
|
|
47
49
|
MultiValue,
|
|
48
50
|
MultiValueProps,
|
|
49
51
|
OnChangeValue,
|
|
@@ -53,6 +55,8 @@ export type {
|
|
|
53
55
|
SingleValue,
|
|
54
56
|
SingleValueProps,
|
|
55
57
|
StylesConfig,
|
|
58
|
+
SelectInstance,
|
|
59
|
+
BaseSelectProps,
|
|
56
60
|
};
|
|
57
61
|
|
|
58
62
|
export {reactSelectComponents as components, MenuListVirtualized, createFilter};
|
|
@@ -207,8 +211,8 @@ export const Select = forwardRef(function Select<
|
|
|
207
211
|
[onKeyDown, menuOpenState]
|
|
208
212
|
);
|
|
209
213
|
|
|
210
|
-
const
|
|
211
|
-
const
|
|
214
|
+
const selectRef = useRef<SelectInstance<T, U, V> | null>(null);
|
|
215
|
+
const composedRef = useComposedRefs(forwardedRef, selectRef);
|
|
212
216
|
|
|
213
217
|
const selectComponents = useSelectComponents({
|
|
214
218
|
components,
|
|
@@ -221,9 +225,9 @@ export const Select = forwardRef(function Select<
|
|
|
221
225
|
const combinedStyles = useSelectStyles({virtualized, zIndex, styles});
|
|
222
226
|
|
|
223
227
|
return (
|
|
224
|
-
<ReactSelectRefContext.Provider value={
|
|
228
|
+
<ReactSelectRefContext.Provider value={selectRef as RefObject<SelectInstance>}>
|
|
225
229
|
<BaseSelect<T, U, V>
|
|
226
|
-
ref={
|
|
230
|
+
ref={composedRef}
|
|
227
231
|
// There are places, where it is useful to override menuPortalTarget globally for all selects.
|
|
228
232
|
// When you are already in some popup. e.g. user input in buttons, relation filter popover.
|
|
229
233
|
menuPortalTarget={getPopupContainerElement ? getPopupContainerElement() : menuPortalTarget}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import {createContext, ReactNode, useContext, useMemo} from "react";
|
|
2
2
|
|
|
3
|
-
const SelectControlSettings = createContext<{
|
|
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(
|
|
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
|
|
|
@@ -5,6 +5,7 @@ import React, {
|
|
|
5
5
|
ForwardedRef,
|
|
6
6
|
forwardRef,
|
|
7
7
|
ReactNode,
|
|
8
|
+
RefObject,
|
|
8
9
|
useCallback,
|
|
9
10
|
useEffect,
|
|
10
11
|
useImperativeHandle,
|
|
@@ -14,7 +15,7 @@ import React, {
|
|
|
14
15
|
} from "react";
|
|
15
16
|
import {inputOverrides} from "../antd/styles";
|
|
16
17
|
import {border, space, textStyles} from "../design-system";
|
|
17
|
-
import {
|
|
18
|
+
import {Popover, Placement} from "../popover";
|
|
18
19
|
import {useIsPhone} from "../use-is-phone";
|
|
19
20
|
import {MenuTransparent} from "./components/menu";
|
|
20
21
|
import {
|
|
@@ -33,6 +34,7 @@ import {ButtonColor, ButtonVariant} from "../button/base-button";
|
|
|
33
34
|
import {makeSelectInPopoverStyles} from "./styles";
|
|
34
35
|
import {SelectInstance} from "react-select";
|
|
35
36
|
import {SELECT_IN_POPOVER_VALUE_MAX_HEIGHT} from "./constants";
|
|
37
|
+
import {Wrap} from "@fibery/react/src/wrap";
|
|
36
38
|
|
|
37
39
|
const offset = [0, space.s4] as [number, number];
|
|
38
40
|
const popupHeightVH = 45;
|
|
@@ -58,12 +60,15 @@ export const popupClassName = css`
|
|
|
58
60
|
max-width: 440px;
|
|
59
61
|
`;
|
|
60
62
|
const mobileClassName = css`
|
|
63
|
+
display: grid;
|
|
64
|
+
min-height: 0;
|
|
61
65
|
padding-top: ${space.s12}px;
|
|
62
66
|
padding-left: ${space.s12}px;
|
|
63
67
|
padding-right: ${space.s12}px;
|
|
64
68
|
`;
|
|
65
69
|
|
|
66
|
-
const
|
|
70
|
+
const triggerCss = css`
|
|
71
|
+
min-width: 0;
|
|
67
72
|
border-radius: ${border.radius6}px;
|
|
68
73
|
|
|
69
74
|
&:focus {
|
|
@@ -109,7 +114,7 @@ export type TriggerProps = {
|
|
|
109
114
|
|
|
110
115
|
const TriggerDefault = ({innerRef, children, onClick, onKeyDown}: TriggerProps) => {
|
|
111
116
|
return (
|
|
112
|
-
<div ref={innerRef} onClick={onClick} onKeyDown={onKeyDown} tabIndex={0} className={
|
|
117
|
+
<div ref={innerRef} onClick={onClick} onKeyDown={onKeyDown} tabIndex={0} className={triggerCss}>
|
|
113
118
|
{children}
|
|
114
119
|
</div>
|
|
115
120
|
);
|
|
@@ -119,9 +124,9 @@ export type SelectComponents<T, U extends boolean, V extends GroupBase<T>> = Sel
|
|
|
119
124
|
Trigger?: ComponentType<TriggerProps>;
|
|
120
125
|
};
|
|
121
126
|
|
|
122
|
-
type SelectInPopoverRef<T, U extends boolean, V extends GroupBase<T>> = {
|
|
127
|
+
export type SelectInPopoverRef<T, U extends boolean, V extends GroupBase<T>> = {
|
|
123
128
|
valueRef: HTMLDivElement | null;
|
|
124
|
-
selectRef: SelectInstance<T, U, V
|
|
129
|
+
selectRef: RefObject<SelectInstance<T, U, V>>;
|
|
125
130
|
};
|
|
126
131
|
|
|
127
132
|
type Props<T, U extends boolean, V extends GroupBase<T>> = {
|
|
@@ -158,6 +163,7 @@ type Props<T, U extends boolean, V extends GroupBase<T>> = {
|
|
|
158
163
|
forbidValuesClearInCollnMode?: boolean;
|
|
159
164
|
otherSelectProps?: Record<string, unknown>;
|
|
160
165
|
isOptionDisabled?: (option: T) => boolean;
|
|
166
|
+
popoverPlacement?: Placement;
|
|
161
167
|
};
|
|
162
168
|
|
|
163
169
|
function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
|
|
@@ -197,8 +203,8 @@ function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
|
|
|
197
203
|
otherSelectProps,
|
|
198
204
|
forbidValuesClearInCollnMode,
|
|
199
205
|
isOptionDisabled,
|
|
206
|
+
popoverPlacement = "bottom-start",
|
|
200
207
|
} = props;
|
|
201
|
-
const [triggerElement, setTriggerElement] = useState<HTMLDivElement | null>(null);
|
|
202
208
|
const [visible, setVisible] = useControllableState({
|
|
203
209
|
value: menuIsOpen,
|
|
204
210
|
defaultValue: false,
|
|
@@ -206,22 +212,15 @@ function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
|
|
|
206
212
|
return value ? onMenuOpen?.() : onMenuClose?.();
|
|
207
213
|
},
|
|
208
214
|
});
|
|
215
|
+
const isPhone = useIsPhone();
|
|
209
216
|
const blurTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
|
|
210
217
|
const selectRef = useRef<SelectInstance<T, U, V>>(null);
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
useImperativeHandle(
|
|
214
|
-
forwardedRef,
|
|
215
|
-
() =>
|
|
216
|
-
({
|
|
217
|
-
valueRef: ref.current,
|
|
218
|
-
selectRef: selectRef.current,
|
|
219
|
-
} as {valueRef: HTMLDivElement; selectRef: SelectInstance<T, U, V> | null})
|
|
220
|
-
);
|
|
218
|
+
const [triggerElement, setTriggerElement] = useState<HTMLDivElement | null>(null);
|
|
221
219
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
220
|
+
useImperativeHandle(forwardedRef, () => ({
|
|
221
|
+
valueRef: triggerElement,
|
|
222
|
+
selectRef,
|
|
223
|
+
}));
|
|
225
224
|
|
|
226
225
|
useEffect(() => {
|
|
227
226
|
if (blurTimeoutRef.current) {
|
|
@@ -274,8 +273,8 @@ function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
|
|
|
274
273
|
}, [disabled, onMenuOpen, setVisible]);
|
|
275
274
|
|
|
276
275
|
const styles = useMemo(() => {
|
|
277
|
-
return combineStyles<T, U, V>([makeSelectInPopoverStyles(), selectStyles]);
|
|
278
|
-
}, [selectStyles]);
|
|
276
|
+
return combineStyles<T, U, V>([makeSelectInPopoverStyles(isPhone), selectStyles]);
|
|
277
|
+
}, [selectStyles, isPhone]);
|
|
279
278
|
|
|
280
279
|
const onTriggerClick: React.MouseEventHandler = useCallback(
|
|
281
280
|
(event) => {
|
|
@@ -312,8 +311,6 @@ function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
|
|
|
312
311
|
[onHide, onSelectKeyDown, visible]
|
|
313
312
|
);
|
|
314
313
|
|
|
315
|
-
const isPhone = useIsPhone();
|
|
316
|
-
|
|
317
314
|
const onBlur: React.FocusEventHandler<HTMLDivElement> = useCallback(() => {
|
|
318
315
|
if (isPhone) {
|
|
319
316
|
return;
|
|
@@ -356,9 +353,9 @@ function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
|
|
|
356
353
|
};
|
|
357
354
|
|
|
358
355
|
return (
|
|
359
|
-
|
|
356
|
+
<Popover.Root open={visible} onOpen={() => onShow()} onClose={() => onHide()}>
|
|
360
357
|
<Trigger
|
|
361
|
-
innerRef={
|
|
358
|
+
innerRef={setTriggerElement}
|
|
362
359
|
menuOpened={visible}
|
|
363
360
|
disabled={disabled}
|
|
364
361
|
valueSelected={Boolean(value)}
|
|
@@ -367,28 +364,22 @@ function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
|
|
|
367
364
|
>
|
|
368
365
|
{renderValue ? renderValue() : null}
|
|
369
366
|
</Trigger>
|
|
370
|
-
{
|
|
371
|
-
|
|
367
|
+
<Popover.Trigger reference={triggerElement} />
|
|
368
|
+
<Wrap with={Popover.Portal} if={renderInPortal} getPopupContainer={getPopupContainer}>
|
|
369
|
+
<Popover.Content
|
|
372
370
|
supportMobile
|
|
373
371
|
title={title}
|
|
374
372
|
offset={offset}
|
|
375
373
|
popupContainerClassName={popupContainerClassName}
|
|
376
374
|
popupClassName={cx(popupClassName, popupStyles)}
|
|
377
375
|
mobilePopupContentClassName={mobileClassName}
|
|
378
|
-
placement=
|
|
379
|
-
renderInPortal={renderInPortal}
|
|
380
|
-
open={visible}
|
|
381
|
-
onOpen={() => onShow()}
|
|
382
|
-
onClose={() => onHide()}
|
|
383
|
-
trigger={<></>}
|
|
384
|
-
triggerDomElement={triggerElement}
|
|
385
|
-
getPopupContainer={getPopupContainer}
|
|
376
|
+
placement={popoverPlacement}
|
|
386
377
|
>
|
|
387
378
|
{title && !isPhone && <div className={titleClassName}>{title}</div>}
|
|
388
379
|
{/*Usually we set popupContainerElement for react-select via context (SelectControlSettingsProvider). But here we render react-select in popover.*/}
|
|
389
380
|
{/*Render target in controlled by Popover here. So we just override SelectControlContext here and set popupContainerElement to undefined. */}
|
|
390
381
|
{/*So in dom react-select will be a child of popover. */}
|
|
391
|
-
<SelectControlSettingsProvider getPopupContainerElement={undefined}>
|
|
382
|
+
<SelectControlSettingsProvider inPopover={true} getPopupContainerElement={undefined}>
|
|
392
383
|
<ReactSelect<T, U, V>
|
|
393
384
|
ref={selectRef}
|
|
394
385
|
styles={styles}
|
|
@@ -423,9 +414,9 @@ function SelectInPopoverInner<T, U extends boolean, V extends GroupBase<T>>(
|
|
|
423
414
|
isOptionDisabled={isOptionDisabled}
|
|
424
415
|
/>
|
|
425
416
|
</SelectControlSettingsProvider>
|
|
426
|
-
</
|
|
427
|
-
|
|
428
|
-
|
|
417
|
+
</Popover.Content>
|
|
418
|
+
</Wrap>
|
|
419
|
+
</Popover.Root>
|
|
429
420
|
);
|
|
430
421
|
}
|
|
431
422
|
|
package/src/select/styles.ts
CHANGED
|
@@ -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>>(
|
|
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,
|