@fibery/ui-kit 1.36.2 → 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.
- package/CHANGELOG.md +20 -0
- package/package.json +8 -5
- package/src/action-badge.tsx +5 -4
- package/src/actions-menu/actions-menu-confirmation.tsx +1 -12
- package/src/actions-menu/actions-menu-item.tsx +19 -7
- package/src/actions-menu/actions-menu-props.tsx +4 -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 +24 -8
- package/src/actions-panel.tsx +12 -2
- package/src/antd/ant-modal.tsx +17 -2
- package/src/antd/input.tsx +4 -3
- package/src/app-icon-with-fallback.tsx +5 -8
- package/src/app-icon-wrapper.tsx +4 -4
- package/src/appIcons.json +20 -0
- package/src/axis-header.tsx +136 -76
- package/src/badge.tsx +14 -7
- package/src/beta-badge.tsx +12 -8
- package/src/box.tsx +1 -1
- package/src/breadcrumb.tsx +78 -0
- package/src/button/actions-button-compact.tsx +5 -2
- package/src/button/base-button.tsx +7 -4
- package/src/button/button-group.tsx +1 -1
- package/src/button/button.tsx +120 -2
- package/src/button/icon-button.tsx +13 -2
- package/src/button/select-button.tsx +27 -8
- package/src/card-container.tsx +36 -69
- package/src/card-hidden-link.tsx +52 -0
- package/src/collapsible-section.tsx +13 -3
- package/src/color-picker/index.js +65 -60
- package/src/color-picker/swatch.tsx +29 -14
- package/src/command-menu/index.tsx +5 -5
- package/src/context-menu/index.tsx +10 -1
- package/src/count-badge.tsx +57 -0
- package/src/date-picker/date-range-input.tsx +1 -1
- package/src/date-picker/date-range-picker.tsx +6 -3
- package/src/date-picker/fake-date-input.tsx +1 -1
- package/src/date-picker/relative-date-picker.tsx +7 -3
- package/src/date-picker/single-date-input.tsx +1 -1
- package/src/date-picker/single-date-picker.tsx +8 -5
- package/src/date-picker/styles.ts +32 -26
- package/src/date-picker/types.ts +3 -1
- package/src/date-picker/utils.ts +9 -2
- 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 +91 -51
- package/src/dropdown-menu/index.tsx +8 -1
- package/src/emoji-picker/app-icon-picker.tsx +6 -4
- package/src/emoji-picker/emoji-picker-content-with-color.tsx +3 -9
- package/src/emoji-picker/emoji-picker-preview-footer.tsx +1 -1
- package/src/emoji-picker/emoji-picker.tsx +3 -0
- package/src/emoji-picker/emoji.tsx +2 -1
- package/src/emoji-picker/icon-emoji-picker.tsx +83 -68
- package/src/emoji-picker/primitives/footer.tsx +0 -1
- package/src/emoji-picker/primitives/header.tsx +1 -0
- package/src/emoji-picker/primitives/search.tsx +12 -13
- package/src/emoji-picker/primitives/skin-tone.tsx +1 -0
- 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/error-alert/error-alert.tsx +19 -7
- package/src/field-app-icon.tsx +29 -0
- package/src/field-container.tsx +4 -2
- package/src/field-icon.tsx +29 -0
- package/src/field-type-icon.tsx +82 -0
- package/src/file-item.tsx +164 -47
- package/src/guide-link.tsx +4 -3
- package/src/hint.tsx +10 -1
- package/src/html-styles.ts +23 -13
- package/src/icons/ast/ActivityFilled.ts +8 -0
- package/src/icons/ast/AiAssistantFilled.ts +8 -0
- package/src/icons/ast/AiFiberyBuild.ts +8 -0
- package/src/icons/ast/Anthropic.ts +1 -1
- package/src/icons/ast/Apple.ts +8 -0
- package/src/icons/ast/ArrowBottom.ts +1 -1
- package/src/icons/ast/ArrowForward.ts +1 -1
- package/src/icons/ast/ArrowLeft.ts +1 -1
- package/src/icons/ast/ArrowRight.ts +1 -1
- package/src/icons/ast/ArrowTop.ts +1 -1
- package/src/icons/ast/CollapseAllHorizontal.ts +8 -0
- package/src/icons/ast/Crosshair.ts +8 -0
- package/src/icons/ast/DateRange.ts +1 -1
- package/src/icons/ast/Document.ts +8 -0
- package/src/icons/ast/EntityCreate.ts +8 -0
- package/src/icons/ast/EntityCreateFilled.ts +8 -0
- package/src/icons/ast/ExpandAll.ts +8 -0
- package/src/icons/ast/ExpandAllHorizontal.ts +8 -0
- package/src/icons/ast/FiberyDesktopApp.ts +8 -0
- package/src/icons/ast/FileDownload.ts +8 -0
- package/src/icons/ast/GlobeUnpublish.ts +8 -0
- package/src/icons/ast/GraduationCapFilled.ts +8 -0
- package/src/icons/ast/Home.ts +1 -1
- package/src/icons/ast/HomeFilled.ts +8 -0
- package/src/icons/ast/ImportFilled.ts +8 -0
- package/src/icons/ast/IntegrationsFilled.ts +8 -0
- package/src/icons/ast/KeyboardHideDown.ts +8 -0
- package/src/icons/ast/LayoutMultiple.ts +8 -0
- package/src/icons/ast/LocationEdit.ts +8 -0
- package/src/icons/ast/MessagePlus.ts +8 -0
- package/src/icons/ast/OpenAi.ts +1 -1
- package/src/icons/ast/RicheditorHistoryRedo.ts +1 -1
- package/src/icons/ast/RicheditorHistoryUndo.ts +1 -1
- package/src/icons/ast/RicheditorMarkHighlight.ts +8 -0
- package/src/icons/ast/RicheditorMarkStrike.ts +1 -1
- package/src/icons/ast/RicheditorMarkUnderline.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/SpaceApp.ts +8 -0
- package/src/icons/ast/SpaceGenerate.ts +8 -0
- package/src/icons/ast/SpaceScratch.ts +8 -0
- package/src/icons/ast/SpaceTemplate.ts +8 -0
- package/src/icons/ast/TableLayout.ts +8 -0
- package/src/icons/ast/TemplatesFilled.ts +8 -0
- package/src/icons/ast/ThumbsDown.ts +8 -0
- package/src/icons/ast/ThumbsUp.ts +8 -0
- package/src/icons/ast/TypeDate.ts +1 -1
- package/src/icons/ast/ViewDashboard.ts +8 -0
- package/src/icons/ast/WarningTriangleFilled.ts +8 -0
- package/src/icons/ast/Windows.ts +8 -0
- package/src/icons/ast/index.tsx +37 -0
- package/src/icons/react/ActivityFilled.tsx +13 -0
- package/src/icons/react/AiAssistantFilled.tsx +13 -0
- package/src/icons/react/AiFiberyBuild.tsx +13 -0
- package/src/icons/react/Apple.tsx +13 -0
- package/src/icons/react/CollapseAllHorizontal.tsx +13 -0
- package/src/icons/react/Crosshair.tsx +13 -0
- package/src/icons/react/Document.tsx +13 -0
- package/src/icons/react/EntityCreate.tsx +13 -0
- package/src/icons/react/EntityCreateFilled.tsx +13 -0
- package/src/icons/react/ExpandAll.tsx +13 -0
- package/src/icons/react/ExpandAllHorizontal.tsx +13 -0
- package/src/icons/react/FiberyDesktopApp.tsx +13 -0
- package/src/icons/react/FileDownload.tsx +13 -0
- package/src/icons/react/GlobeUnpublish.tsx +13 -0
- package/src/icons/react/GraduationCapFilled.tsx +13 -0
- package/src/icons/react/HomeFilled.tsx +13 -0
- package/src/icons/react/ImportFilled.tsx +13 -0
- package/src/icons/react/IntegrationsFilled.tsx +13 -0
- package/src/icons/react/KeyboardHideDown.tsx +13 -0
- package/src/icons/react/LayoutMultiple.tsx +13 -0
- package/src/icons/react/LocationEdit.tsx +13 -0
- package/src/icons/react/MessagePlus.tsx +13 -0
- package/src/icons/react/RicheditorMarkHighlight.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/SpaceApp.tsx +13 -0
- package/src/icons/react/SpaceGenerate.tsx +13 -0
- package/src/icons/react/SpaceScratch.tsx +13 -0
- package/src/icons/react/SpaceTemplate.tsx +13 -0
- package/src/icons/react/TableLayout.tsx +13 -0
- package/src/icons/react/TemplatesFilled.tsx +13 -0
- package/src/icons/react/ThumbsDown.tsx +13 -0
- package/src/icons/react/ThumbsUp.tsx +13 -0
- package/src/icons/react/ViewDashboard.tsx +13 -0
- package/src/icons/react/WarningTriangleFilled.tsx +13 -0
- package/src/icons/react/Windows.tsx +13 -0
- package/src/icons/react/index.tsx +37 -0
- package/src/icons/svg/activity-filled.svg +4 -0
- package/src/icons/svg/ai-assistant-filled.svg +3 -0
- package/src/icons/svg/ai-fibery-build.svg +24 -0
- package/src/icons/svg/anthropic.svg +2 -14
- package/src/icons/svg/apple.svg +4 -0
- package/src/icons/svg/arrow-bottom.svg +1 -1
- package/src/icons/svg/arrow-forward.svg +1 -1
- package/src/icons/svg/arrow-left.svg +1 -1
- package/src/icons/svg/arrow-right.svg +1 -1
- package/src/icons/svg/arrow-top.svg +1 -1
- package/src/icons/svg/collapse-all-horizontal.svg +3 -0
- package/src/icons/svg/crosshair.svg +4 -0
- package/src/icons/svg/date-range.svg +3 -3
- package/src/icons/svg/document.svg +4 -0
- package/src/icons/svg/entity-create-filled.svg +4 -0
- package/src/icons/svg/entity-create.svg +3 -0
- package/src/icons/svg/expand-all-horizontal.svg +3 -0
- package/src/icons/svg/expand-all.svg +3 -0
- package/src/icons/svg/fibery-desktop-app.svg +101 -0
- package/src/icons/svg/file-download.svg +4 -0
- package/src/icons/svg/globe-unpublish.svg +4 -0
- package/src/icons/svg/go-to.svg +1 -3
- package/src/icons/svg/graduation-cap-filled.svg +4 -0
- package/src/icons/svg/home-filled.svg +3 -0
- package/src/icons/svg/home.svg +4 -2
- package/src/icons/svg/import-filled.svg +4 -0
- package/src/icons/svg/integrations-filled.svg +4 -0
- package/src/icons/svg/keyboard-hide-down.svg +1 -0
- package/src/icons/svg/layout-multiple.svg +3 -0
- package/src/icons/svg/location-edit.svg +13 -0
- package/src/icons/svg/message-plus.svg +4 -0
- package/src/icons/svg/open-ai.svg +2 -7
- package/src/icons/svg/open-as-page.svg +2 -3
- package/src/icons/svg/richeditor/history/redo.svg +3 -2
- package/src/icons/svg/richeditor/history/undo.svg +3 -2
- package/src/icons/svg/richeditor/mark/code.svg +4 -5
- package/src/icons/svg/richeditor/mark/em.svg +3 -2
- package/src/icons/svg/richeditor/mark/highlight.svg +3 -0
- package/src/icons/svg/richeditor/mark/strike.svg +3 -2
- package/src/icons/svg/richeditor/mark/strong.svg +3 -2
- package/src/icons/svg/richeditor/mark/underline.svg +4 -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/space-app.svg +3 -0
- package/src/icons/svg/space-generate.svg +3 -0
- package/src/icons/svg/space-scratch.svg +3 -0
- package/src/icons/svg/space-template.svg +3 -0
- package/src/icons/svg/table-layout.svg +3 -0
- package/src/icons/svg/templates-filled.svg +6 -0
- package/src/icons/svg/thumbs-down.svg +3 -0
- package/src/icons/svg/thumbs-up.svg +3 -0
- package/src/icons/svg/type/date.svg +3 -2
- package/src/icons/svg/view-dashboard.svg +5 -0
- package/src/icons/svg/warning-triangle-filled.svg +3 -0
- package/src/icons/svg/windows.svg +15 -0
- package/src/images-gallery/images-gallery.tsx +254 -0
- package/src/images-gallery/zoom.tsx +112 -0
- package/src/integration-compact-info-button.tsx +3 -1
- package/src/is-in-popup.ts +1 -1
- package/src/layout-styles.ts +43 -0
- package/src/lists/actions-menu-row-surface.tsx +3 -1
- package/src/lists/list-row-surface.tsx +9 -2
- package/src/loaders.tsx +6 -6
- package/src/logo.tsx +16 -9
- package/src/mobile-keyboard-aware-popup.tsx +87 -0
- package/src/mobile-styles.ts +10 -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 +37 -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 +37 -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/new-badge.tsx +4 -7
- package/src/number-input/text-area-auto-sized.tsx +47 -0
- package/src/number-input/text-input-auto-sized.tsx +49 -0
- package/src/online-users.tsx +3 -3
- package/src/palette.ts +50 -50
- package/src/popover/index.tsx +687 -0
- package/src/popover/mobile-popup-context.tsx +29 -0
- package/src/{popup → popover}/modifiers.tsx +0 -7
- package/src/{popup → popover}/popup-modifiers-context.ts +3 -3
- package/src/reactions/reaction-button.tsx +30 -45
- package/src/reactions/reaction-picker.tsx +39 -45
- package/src/rich-text-embed-error.tsx +2 -2
- package/src/select/{custom-select-partials → components}/menu.tsx +13 -7
- package/src/select/{custom-select-partials → components}/no-option-message.tsx +0 -1
- package/src/select/constants.ts +1 -0
- package/src/select/index.tsx +143 -148
- package/src/select/select-in-popover.tsx +119 -138
- package/src/select/styles.ts +60 -24
- package/src/shortcut-badge.tsx +1 -0
- package/src/tab-nav/tab-nav.tsx +47 -28
- package/src/theme-provider.tsx +9 -1
- 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 +3 -3
- package/src/tooltip-if-overflown.tsx +9 -3
- package/src/tooltip.tsx +2 -2
- package/src/unit/index.tsx +9 -1
- package/src/unit/loading-unit-value.tsx +1 -0
- package/src/unit/maybe-unit-value.tsx +3 -3
- package/src/unit/primitive.tsx +58 -42
- package/src/unit/styles.ts +10 -14
- package/src/unit/types.ts +4 -2
- package/src/unit/unit-button-group.tsx +6 -11
- package/src/unit/unit-content.tsx +13 -5
- package/src/unit/unit-with-title.tsx +6 -1
- package/src/unit/unit-with-tooltip.tsx +24 -9
- package/src/use-is-phone.tsx +37 -0
- 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 +17 -23
- package/src/number-input/text-area-with-autosize.tsx +0 -91
- package/src/number-input/text-inline-input-with-autosize.tsx +0 -60
- package/src/popup/index.tsx +0 -382
- package/src/use-is-phone.ts +0 -5
- /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
- /package/src/select/{custom-select-partials → components}/clear-indicator.tsx +0 -0
- /package/src/select/{custom-select-partials → components}/drop-down-indicator.tsx +0 -0
- /package/src/select/{custom-select-partials → components}/group-heading.tsx +0 -0
- /package/src/select/{custom-select-partials → components}/menu-list-virtualized.tsx +0 -0
- /package/src/select/{custom-select-partials → components}/option.tsx +0 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import {ReactNode, useCallback, useEffect, useMemo, useReducer, useRef, useState} from "react";
|
|
2
|
+
import _ from "lodash";
|
|
3
|
+
import {createContext} from "@fibery/react/src/create-context";
|
|
4
|
+
import {useIsPhone} from "../use-is-phone";
|
|
5
|
+
import {safeAreaInsetBottomVar} from "../mobile-styles";
|
|
6
|
+
import {buttonGroup, ButtonGroup} from "../button/button-group";
|
|
7
|
+
import {IconButton} from "../button/icon-button";
|
|
8
|
+
import ArrowRight from "../icons/react/ArrowRight";
|
|
9
|
+
import ArrowLeft from "../icons/react/ArrowLeft";
|
|
10
|
+
import {css} from "@linaria/core";
|
|
11
|
+
import cx from "classnames";
|
|
12
|
+
|
|
13
|
+
type Registry = Map<string, {zoomed: boolean; setZoomed: (zoomed: boolean) => void}>;
|
|
14
|
+
|
|
15
|
+
const [ImagesGalleryRegistryProvider, useImagesGalleryRegistry] = createContext(
|
|
16
|
+
"ImagesGalleryRegistryContext",
|
|
17
|
+
new Map()
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export {useImagesGalleryRegistry};
|
|
21
|
+
|
|
22
|
+
type Methods = {
|
|
23
|
+
setVisible: (visible: boolean) => void;
|
|
24
|
+
setActivated: (activated: boolean) => void;
|
|
25
|
+
update: () => void;
|
|
26
|
+
nextImage: () => void;
|
|
27
|
+
prevImage: () => void;
|
|
28
|
+
};
|
|
29
|
+
const [ImagesGalleryMethodsProvider, useImagesGalleryMethods] = createContext<Methods>("ImagesGalleryMethodsProvider", {
|
|
30
|
+
setVisible: _.noop,
|
|
31
|
+
setActivated: _.noop,
|
|
32
|
+
update: _.noop,
|
|
33
|
+
nextImage: _.noop,
|
|
34
|
+
prevImage: _.noop,
|
|
35
|
+
});
|
|
36
|
+
type State = {visible: boolean; activated: boolean; _inc: number};
|
|
37
|
+
|
|
38
|
+
const [ImagesGalleryStateProvider, useImagesGalleryState] = createContext<State>("ImagesGalleryStateContext", {
|
|
39
|
+
visible: false,
|
|
40
|
+
activated: false,
|
|
41
|
+
_inc: 0,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
export {useImagesGalleryMethods, useImagesGalleryState};
|
|
45
|
+
|
|
46
|
+
type Actions = {type: "set-visible"; payload: boolean} | {type: "set-activated"; payload: boolean} | {type: "inc"};
|
|
47
|
+
|
|
48
|
+
function initialState(): State {
|
|
49
|
+
return {visible: false, activated: false, _inc: 0};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function imagesGalleryReducer(state: State, action: Actions) {
|
|
53
|
+
if (action.type === "set-visible") {
|
|
54
|
+
return {...state, visible: action.payload};
|
|
55
|
+
}
|
|
56
|
+
if (action.type === "set-activated") {
|
|
57
|
+
return {...state, activated: action.payload};
|
|
58
|
+
}
|
|
59
|
+
if (action.type === "inc") {
|
|
60
|
+
return {...state, _inc: state._inc + 1};
|
|
61
|
+
}
|
|
62
|
+
return state;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const controlsGroupStyle = css`
|
|
66
|
+
&.${buttonGroup} {
|
|
67
|
+
display: none;
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
|
|
71
|
+
export function Controls() {
|
|
72
|
+
const imagesRegistry = useImagesGalleryRegistry();
|
|
73
|
+
const {visible} = useImagesGalleryState();
|
|
74
|
+
const isPhone = useIsPhone();
|
|
75
|
+
const {prevImage, nextImage, setVisible} = useImagesGalleryMethods();
|
|
76
|
+
// Determine if there is a zoomed image and its position in the registry
|
|
77
|
+
let activeNext = true;
|
|
78
|
+
let activePrev = true;
|
|
79
|
+
let i = 0;
|
|
80
|
+
for (const image of imagesRegistry.values()) {
|
|
81
|
+
if (image.zoomed) {
|
|
82
|
+
if (i === 0) {
|
|
83
|
+
activePrev = false;
|
|
84
|
+
}
|
|
85
|
+
if (i === imagesRegistry.size - 1) {
|
|
86
|
+
activeNext = false;
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
i++;
|
|
91
|
+
}
|
|
92
|
+
const visibleState = visible || isPhone;
|
|
93
|
+
if (imagesRegistry.size > 1) {
|
|
94
|
+
const size = isPhone ? "xLarge" : "small";
|
|
95
|
+
return (
|
|
96
|
+
<div
|
|
97
|
+
className={css`
|
|
98
|
+
position: fixed;
|
|
99
|
+
bottom: max(var(${safeAreaInsetBottomVar}), 12px);
|
|
100
|
+
left: 0;
|
|
101
|
+
right: 0;
|
|
102
|
+
display: grid;
|
|
103
|
+
align-items: center;
|
|
104
|
+
justify-content: center;
|
|
105
|
+
&:hover .${controlsGroupStyle}.${buttonGroup} {
|
|
106
|
+
display: flex;
|
|
107
|
+
}
|
|
108
|
+
`}
|
|
109
|
+
>
|
|
110
|
+
<ButtonGroup
|
|
111
|
+
className={cx(
|
|
112
|
+
controlsGroupStyle,
|
|
113
|
+
visibleState &&
|
|
114
|
+
css`
|
|
115
|
+
&.${controlsGroupStyle}.${buttonGroup} {
|
|
116
|
+
display: flex;
|
|
117
|
+
}
|
|
118
|
+
`
|
|
119
|
+
)}
|
|
120
|
+
>
|
|
121
|
+
<IconButton
|
|
122
|
+
variant={"outline"}
|
|
123
|
+
size={size}
|
|
124
|
+
onClick={() => {
|
|
125
|
+
prevImage();
|
|
126
|
+
setVisible(true);
|
|
127
|
+
}}
|
|
128
|
+
disabled={!activePrev}
|
|
129
|
+
>
|
|
130
|
+
<ArrowLeft />
|
|
131
|
+
</IconButton>
|
|
132
|
+
<IconButton
|
|
133
|
+
variant={"outline"}
|
|
134
|
+
size={size}
|
|
135
|
+
onClick={() => {
|
|
136
|
+
nextImage();
|
|
137
|
+
setVisible(true);
|
|
138
|
+
}}
|
|
139
|
+
disabled={!activeNext}
|
|
140
|
+
>
|
|
141
|
+
<ArrowRight />
|
|
142
|
+
</IconButton>
|
|
143
|
+
</ButtonGroup>
|
|
144
|
+
</div>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function ImagesGalleryProvider({children}: {children: ReactNode}) {
|
|
151
|
+
const [imagesRegistry] = useState<Registry>(() => new Map());
|
|
152
|
+
const timeoutRef = useRef<ReturnType<typeof setTimeout>>();
|
|
153
|
+
const [galleryState, dispatchState] = useReducer(imagesGalleryReducer, [], initialState);
|
|
154
|
+
const setVisible = useCallback((visible: boolean) => dispatchState({type: "set-visible", payload: visible}), []);
|
|
155
|
+
const setActivated = useCallback(
|
|
156
|
+
(activated: boolean) => dispatchState({type: "set-activated", payload: activated}),
|
|
157
|
+
[]
|
|
158
|
+
);
|
|
159
|
+
const update = useCallback(() => dispatchState({type: "inc"}), []);
|
|
160
|
+
const {visible} = galleryState;
|
|
161
|
+
const timeout = 3000;
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
if (visible) {
|
|
164
|
+
clearTimeout(timeoutRef.current);
|
|
165
|
+
timeoutRef.current = setTimeout(() => {
|
|
166
|
+
setVisible(false);
|
|
167
|
+
}, timeout);
|
|
168
|
+
}
|
|
169
|
+
return () => {
|
|
170
|
+
clearTimeout(timeoutRef.current);
|
|
171
|
+
};
|
|
172
|
+
}, [setVisible, visible]);
|
|
173
|
+
const nextImage = useCallback(() => {
|
|
174
|
+
let i = 0;
|
|
175
|
+
for (const image of imagesRegistry.values()) {
|
|
176
|
+
if (image.zoomed) {
|
|
177
|
+
if (i === imagesRegistry.size - 1) {
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
image.setZoomed(false);
|
|
181
|
+
const nextImage = Array.from(imagesRegistry.values())[i + 1];
|
|
182
|
+
nextImage.setZoomed(true);
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
i++;
|
|
186
|
+
}
|
|
187
|
+
clearTimeout(timeoutRef.current);
|
|
188
|
+
timeoutRef.current = setTimeout(() => {
|
|
189
|
+
setVisible(false);
|
|
190
|
+
}, timeout);
|
|
191
|
+
}, [imagesRegistry, setVisible]);
|
|
192
|
+
|
|
193
|
+
const prevImage = useCallback(() => {
|
|
194
|
+
let i = 0;
|
|
195
|
+
for (const image of imagesRegistry.values()) {
|
|
196
|
+
if (image.zoomed) {
|
|
197
|
+
if (i === 0) {
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
image.setZoomed(false);
|
|
201
|
+
const prevImage = Array.from(imagesRegistry.values())[i - 1];
|
|
202
|
+
prevImage.setZoomed(true);
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
i++;
|
|
206
|
+
}
|
|
207
|
+
clearTimeout(timeoutRef.current);
|
|
208
|
+
timeoutRef.current = setTimeout(() => {
|
|
209
|
+
setVisible(false);
|
|
210
|
+
}, timeout);
|
|
211
|
+
}, [imagesRegistry, setVisible]);
|
|
212
|
+
|
|
213
|
+
const methods = useMemo(
|
|
214
|
+
() => ({setVisible, setActivated, update, nextImage, prevImage}),
|
|
215
|
+
[setVisible, setActivated, update, nextImage, prevImage]
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
useEffect(() => {
|
|
219
|
+
const listener = (evt: KeyboardEvent) => {
|
|
220
|
+
const hasActive = Array.from(imagesRegistry.values()).some((image) => image.zoomed);
|
|
221
|
+
if (!hasActive) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (evt.key === "Escape") {
|
|
225
|
+
for (const image of imagesRegistry.values()) {
|
|
226
|
+
if (image.zoomed) {
|
|
227
|
+
image.setZoomed(false);
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (evt.key === "ArrowRight") {
|
|
233
|
+
nextImage();
|
|
234
|
+
}
|
|
235
|
+
if (evt.key === "ArrowLeft") {
|
|
236
|
+
prevImage();
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
document.addEventListener("keydown", listener, {capture: true});
|
|
240
|
+
return () => {
|
|
241
|
+
document.removeEventListener("keydown", listener, {capture: true});
|
|
242
|
+
};
|
|
243
|
+
}, [imagesRegistry, nextImage, prevImage]);
|
|
244
|
+
|
|
245
|
+
return (
|
|
246
|
+
<>
|
|
247
|
+
<ImagesGalleryRegistryProvider value={imagesRegistry}>
|
|
248
|
+
<ImagesGalleryMethodsProvider value={methods}>
|
|
249
|
+
<ImagesGalleryStateProvider value={galleryState}>{children}</ImagesGalleryStateProvider>
|
|
250
|
+
</ImagesGalleryMethodsProvider>
|
|
251
|
+
</ImagesGalleryRegistryProvider>
|
|
252
|
+
</>
|
|
253
|
+
);
|
|
254
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import {css} from "@linaria/core";
|
|
2
|
+
import React, {ReactNode, useCallback} from "react";
|
|
3
|
+
import {Controlled} from "react-medium-image-zoom";
|
|
4
|
+
import "react-medium-image-zoom/dist/styles.css";
|
|
5
|
+
import {themeVars} from "../design-system";
|
|
6
|
+
import {IconButton} from "../button/icon-button";
|
|
7
|
+
import Close from "../icons/react/Close";
|
|
8
|
+
import {Controls, useImagesGalleryMethods} from "./images-gallery";
|
|
9
|
+
import {useIsPhone} from "../use-is-phone";
|
|
10
|
+
|
|
11
|
+
const dialogCss = css`
|
|
12
|
+
:global() {
|
|
13
|
+
[data-rmiz-modal-overlay="hidden"] {
|
|
14
|
+
background-color: transparent;
|
|
15
|
+
}
|
|
16
|
+
[data-rmiz-modal-overlay="visible"] {
|
|
17
|
+
background-color: ${themeVars.colorBgEditorImageZoomed};
|
|
18
|
+
}
|
|
19
|
+
[data-rmiz-content="found"] > img {
|
|
20
|
+
cursor: auto;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
type ModalState = "LOADED" | "LOADING" | "UNLOADED" | "UNLOADING";
|
|
26
|
+
|
|
27
|
+
const ZoomContent = ({
|
|
28
|
+
img,
|
|
29
|
+
modalState,
|
|
30
|
+
onUnzoom,
|
|
31
|
+
}: {
|
|
32
|
+
img: React.ReactElement | null;
|
|
33
|
+
modalState: ModalState;
|
|
34
|
+
onUnzoom: (e: Event) => void;
|
|
35
|
+
}) => {
|
|
36
|
+
const imagesGalleryMethods = useImagesGalleryMethods();
|
|
37
|
+
const isPhone = useIsPhone();
|
|
38
|
+
|
|
39
|
+
const button = modalState === "LOADED" && (
|
|
40
|
+
<IconButton
|
|
41
|
+
size={isPhone ? "xLarge" : "small"}
|
|
42
|
+
color="neutral"
|
|
43
|
+
variant="ghost"
|
|
44
|
+
className={css`
|
|
45
|
+
position: absolute;
|
|
46
|
+
inset: 20px 20px auto auto;
|
|
47
|
+
z-index: 1;
|
|
48
|
+
`}
|
|
49
|
+
onClick={onUnzoom as () => void}
|
|
50
|
+
>
|
|
51
|
+
<Close />
|
|
52
|
+
</IconButton>
|
|
53
|
+
);
|
|
54
|
+
return (
|
|
55
|
+
<>
|
|
56
|
+
<div
|
|
57
|
+
onMouseMove={() => {
|
|
58
|
+
imagesGalleryMethods.setVisible(true);
|
|
59
|
+
}}
|
|
60
|
+
className={css`
|
|
61
|
+
position: absolute;
|
|
62
|
+
inset: 0;
|
|
63
|
+
`}
|
|
64
|
+
>
|
|
65
|
+
{img}
|
|
66
|
+
{button}
|
|
67
|
+
</div>
|
|
68
|
+
<Controls />
|
|
69
|
+
</>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
type Props = {
|
|
74
|
+
zoomed: boolean;
|
|
75
|
+
onZoomedChange: (value: boolean) => void;
|
|
76
|
+
children: ReactNode;
|
|
77
|
+
className?: string;
|
|
78
|
+
openOnClick?: boolean;
|
|
79
|
+
zoomImg?: {src: string; alt?: string};
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const Zoom = (props: Props) => {
|
|
83
|
+
const {zoomed, onZoomedChange, children, className, openOnClick, zoomImg} = props;
|
|
84
|
+
const imagesGalleryMethods = useImagesGalleryMethods();
|
|
85
|
+
const onClick = useCallback(() => {
|
|
86
|
+
if (zoomed) {
|
|
87
|
+
onZoomedChange(false);
|
|
88
|
+
} else if (openOnClick) {
|
|
89
|
+
onZoomedChange(true);
|
|
90
|
+
}
|
|
91
|
+
}, [zoomed, onZoomedChange, openOnClick]);
|
|
92
|
+
|
|
93
|
+
const onDoubleClick = useCallback(() => {
|
|
94
|
+
if (!zoomed) {
|
|
95
|
+
onZoomedChange(true);
|
|
96
|
+
}
|
|
97
|
+
}, [zoomed, onZoomedChange]);
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<div className={className} onClick={onClick} onDoubleClick={openOnClick ? undefined : onDoubleClick}>
|
|
101
|
+
<Controlled
|
|
102
|
+
zoomImg={zoomImg}
|
|
103
|
+
onZoomChange={imagesGalleryMethods.update}
|
|
104
|
+
classDialog={dialogCss}
|
|
105
|
+
isZoomed={zoomed}
|
|
106
|
+
ZoomContent={ZoomContent}
|
|
107
|
+
>
|
|
108
|
+
{children}
|
|
109
|
+
</Controlled>
|
|
110
|
+
</div>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
@@ -34,7 +34,9 @@ export const IntegrationCompactInfoButton: React.FC<{
|
|
|
34
34
|
if (error) {
|
|
35
35
|
iconNode = <WarningIcon color={colors.errorButtonColor} iconSize={18} containerSize={24} />;
|
|
36
36
|
} else if (loading) {
|
|
37
|
-
iconNode =
|
|
37
|
+
iconNode = (
|
|
38
|
+
<Spinner color={colors.accentTextColor} backgroundColor={colors.mainBg} iconSize={16} containerSize={24} />
|
|
39
|
+
);
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
const className = cx(buttonCss, loading && loadingCss);
|
package/src/is-in-popup.ts
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {css} from "@linaria/core";
|
|
2
|
+
import {
|
|
3
|
+
layout,
|
|
4
|
+
listRowSurfaceFontSizeVar,
|
|
5
|
+
sidebarMenuItemHeightVar,
|
|
6
|
+
sidebarMenuIconSizeVar,
|
|
7
|
+
textStyles,
|
|
8
|
+
menuItemHeightVar,
|
|
9
|
+
} from "./design-system";
|
|
10
|
+
import {
|
|
11
|
+
keyboardHeightVar,
|
|
12
|
+
keyboardInsetBottomVar,
|
|
13
|
+
mobileRootClassName,
|
|
14
|
+
safeAreaInsetLeftVar,
|
|
15
|
+
safeAreaInsetRightVar,
|
|
16
|
+
safeAreaInsetTopVar,
|
|
17
|
+
safeAreaInsetBottomVar,
|
|
18
|
+
} from "./mobile-styles";
|
|
19
|
+
|
|
20
|
+
export const layoutStyles = css`
|
|
21
|
+
:global() {
|
|
22
|
+
html:root {
|
|
23
|
+
${safeAreaInsetLeftVar}: var(--app-safe-area-inset-left, env(safe-area-inset-left));
|
|
24
|
+
${safeAreaInsetRightVar}: var(--app-safe-area-inset-right, env(safe-area-inset-right));
|
|
25
|
+
${safeAreaInsetTopVar}: var(--app-safe-area-inset-top, env(safe-area-inset-top));
|
|
26
|
+
${safeAreaInsetBottomVar}: var(--app-safe-area-inset-bottom, env(safe-area-inset-bottom));
|
|
27
|
+
${keyboardInsetBottomVar}: var(--app-current-keyboard-height, 0px);
|
|
28
|
+
${keyboardHeightVar}: 350px;
|
|
29
|
+
|
|
30
|
+
${menuItemHeightVar}: ${layout.menuItemHeight}px;
|
|
31
|
+
${sidebarMenuItemHeightVar}: ${layout.newMenuItemHeight}px;
|
|
32
|
+
${sidebarMenuIconSizeVar}: ${layout.newMenuIconSize}px;
|
|
33
|
+
${listRowSurfaceFontSizeVar}: ${textStyles.regular.fontSize}px;
|
|
34
|
+
|
|
35
|
+
&.${mobileRootClassName} {
|
|
36
|
+
${menuItemHeightVar}: ${layout.mobileMenuItemHeight}px;
|
|
37
|
+
${sidebarMenuItemHeightVar}: ${layout.mobileSidebarMenuItemHeight}px;
|
|
38
|
+
${sidebarMenuIconSizeVar}: ${layout.mobileSidebarIconSize}px;
|
|
39
|
+
${listRowSurfaceFontSizeVar}: ${textStyles.big.fontSize}px;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
@@ -7,6 +7,7 @@ import {useActionsMenuContext} from "../actions-menu";
|
|
|
7
7
|
import {ActionsMenuItemProps} from "../actions-menu/actions-menu-item";
|
|
8
8
|
import {useActiveDangerousRow, useSetActiveDangerousRow} from "../actions-menu/contexts/actions-menu-dangerous-rows";
|
|
9
9
|
import {colors, layout, lineHeight, space, textStyles, themeVars} from "../design-system";
|
|
10
|
+
import {useIsSupportHover} from "../use-is-support-hover";
|
|
10
11
|
import {
|
|
11
12
|
ListRowContent,
|
|
12
13
|
ListRowContentProps,
|
|
@@ -66,6 +67,7 @@ export const actionMenuItemSurface = css`
|
|
|
66
67
|
export const ActionMenuItemSurface = forwardRef<HTMLDivElement, ActionMenuItemSurfaceProps>(
|
|
67
68
|
({testId, className, loading, selected, hovered, focused, title, disabled, children, dangerous, ...props}, ref) => {
|
|
68
69
|
const id = useId();
|
|
70
|
+
const platformSupportsHover = useIsSupportHover();
|
|
69
71
|
const activeDangerousRow = useActiveDangerousRow();
|
|
70
72
|
const showWarning = activeDangerousRow === id;
|
|
71
73
|
const onSelect = useCallbackRef(props.onSelect || _.noop);
|
|
@@ -100,7 +102,7 @@ export const ActionMenuItemSurface = forwardRef<HTMLDivElement, ActionMenuItemSu
|
|
|
100
102
|
listRowSurfaceStylesBase,
|
|
101
103
|
actionMenuItemSurface,
|
|
102
104
|
className,
|
|
103
|
-
hovered === undefined && NATURAL_HOVER_CLASS,
|
|
105
|
+
platformSupportsHover && hovered === undefined && NATURAL_HOVER_CLASS,
|
|
104
106
|
focused === undefined && NATURAL_FOCUS_CLASS,
|
|
105
107
|
focused && "focus",
|
|
106
108
|
disabled && "done",
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {css, cx} from "@linaria/core";
|
|
2
2
|
import {ForwardedRef, forwardRef, HTMLAttributes, PropsWithChildren, ReactNode} from "react";
|
|
3
|
-
import {border, space, textStyles, themeVars, transition} from "../design-system";
|
|
3
|
+
import {border, layoutVars, space, textStyles, themeVars, transition} from "../design-system";
|
|
4
|
+
import {useIsSupportHover} from "../use-is-support-hover";
|
|
5
|
+
import {mobileRootSelector} from "../mobile-styles";
|
|
4
6
|
|
|
5
7
|
interface ListRowSurfaceBase extends HTMLAttributes<HTMLDivElement> {
|
|
6
8
|
testId?: string;
|
|
@@ -28,6 +30,7 @@ export const listRowSurfaceStylesBase = css`
|
|
|
28
30
|
padding: 0 ${space.s4}px;
|
|
29
31
|
column-gap: ${space.s4}px;
|
|
30
32
|
${{...textStyles.regular}};
|
|
33
|
+
font-size: ${layoutVars.listRowSurfaceFontSize};
|
|
31
34
|
color: ${themeVars.textColor};
|
|
32
35
|
border-radius: ${border.radius6}px;
|
|
33
36
|
transition: background-color ${transition};
|
|
@@ -151,6 +154,7 @@ export const listRowSurfaceStatesDark = css`
|
|
|
151
154
|
|
|
152
155
|
export const ListRowSurface = forwardRef<HTMLDivElement, ListRowSurfaceProps>(
|
|
153
156
|
({selected, focused, darker, hovered, done, className, children, ...rest}, ref) => {
|
|
157
|
+
const platformSupportsHover = useIsSupportHover();
|
|
154
158
|
return (
|
|
155
159
|
<div
|
|
156
160
|
{...rest}
|
|
@@ -158,7 +162,7 @@ export const ListRowSurface = forwardRef<HTMLDivElement, ListRowSurfaceProps>(
|
|
|
158
162
|
listRowSurfaceStylesBase,
|
|
159
163
|
darker ? listRowSurfaceStatesDark : listRowSurfaceStatesDefault,
|
|
160
164
|
className,
|
|
161
|
-
hovered === undefined && NATURAL_HOVER_CLASS,
|
|
165
|
+
platformSupportsHover && hovered === undefined && NATURAL_HOVER_CLASS,
|
|
162
166
|
focused === undefined && NATURAL_FOCUS_CLASS,
|
|
163
167
|
focused && "focus",
|
|
164
168
|
hovered && "hover",
|
|
@@ -203,6 +207,9 @@ const ListRowContentSegment = css`
|
|
|
203
207
|
min-width: 0; // allows ellipsis in flex contexts :)
|
|
204
208
|
max-width: 100%;
|
|
205
209
|
width: 100%;
|
|
210
|
+
${mobileRootSelector} & {
|
|
211
|
+
${textStyles.big}
|
|
212
|
+
}
|
|
206
213
|
`;
|
|
207
214
|
export const ListRowContent = forwardRef<HTMLDivElement, ListRowContentProps>(
|
|
208
215
|
(
|
package/src/loaders.tsx
CHANGED
|
@@ -105,7 +105,7 @@ const ContainerSpinner = styled.div<{containerSize: number}>`
|
|
|
105
105
|
`;
|
|
106
106
|
|
|
107
107
|
type Props = {
|
|
108
|
-
|
|
108
|
+
iconSize?: number;
|
|
109
109
|
containerSize?: number;
|
|
110
110
|
width?: number;
|
|
111
111
|
color?: string;
|
|
@@ -114,7 +114,7 @@ type Props = {
|
|
|
114
114
|
|
|
115
115
|
export const Spinner = memo<Props>(
|
|
116
116
|
({
|
|
117
|
-
|
|
117
|
+
iconSize = 20,
|
|
118
118
|
containerSize = 15,
|
|
119
119
|
width = 2,
|
|
120
120
|
color = themeVars.iconColor,
|
|
@@ -122,14 +122,14 @@ export const Spinner = memo<Props>(
|
|
|
122
122
|
}) => {
|
|
123
123
|
const style = useMemo(() => {
|
|
124
124
|
return {
|
|
125
|
-
width:
|
|
126
|
-
height:
|
|
127
|
-
...getShiftStyle({elementSize:
|
|
125
|
+
width: iconSize,
|
|
126
|
+
height: iconSize,
|
|
127
|
+
...getShiftStyle({elementSize: iconSize, containerSize}),
|
|
128
128
|
borderWidth: width,
|
|
129
129
|
borderColor: backgroundColor,
|
|
130
130
|
borderTopColor: color,
|
|
131
131
|
};
|
|
132
|
-
}, [backgroundColor, color, containerSize,
|
|
132
|
+
}, [backgroundColor, color, containerSize, iconSize, width]);
|
|
133
133
|
|
|
134
134
|
return (
|
|
135
135
|
<ContainerSpinner containerSize={containerSize}>
|
package/src/logo.tsx
CHANGED
|
@@ -10,40 +10,47 @@ export const Logo: FC<LogoProps> = ({size = 40}) => {
|
|
|
10
10
|
return (
|
|
11
11
|
<svg width={size} height={size} viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
|
|
12
12
|
<path
|
|
13
|
-
d="
|
|
13
|
+
d="M3.5181 14.7077C2.61266 14.1545 2.35441 12.906 2.93813 12.0346L9.86469 1.75412C10.4517 0.956677 11.5947 0.758115 12.4123 1.3202C13.2317 1.88362 13.468 3.02927 12.9497 3.87537L6.02318 14.156C5.48027 14.9614 4.35607 15.2196 3.5181 14.7077Z"
|
|
14
14
|
fill="#4FC5B3"
|
|
15
15
|
/>
|
|
16
16
|
<path
|
|
17
|
-
d="M12.
|
|
17
|
+
d="M12.9561 5.1453L14.9917 4.99099C15.7033 4.93713 16.4005 5.30922 16.7552 5.93053C17.2619 6.8181 16.9569 7.99294 16.0715 8.50971L7.20312 13.6839L12.9561 5.1453Z"
|
|
18
18
|
fill="#4FC5B3"
|
|
19
19
|
/>
|
|
20
20
|
<path
|
|
21
|
-
d="M7.
|
|
21
|
+
d="M7.78663 15.671L7.39941 14.4001L9.43178 13.2144L11.1651 13.9031L11.3653 14.5581C11.6625 15.5343 11.1102 16.6129 10.1313 16.9189C9.14845 17.2223 8.08489 16.6471 7.78663 15.671Z"
|
|
22
22
|
fill="#4FC5B3"
|
|
23
23
|
/>
|
|
24
24
|
<path
|
|
25
|
-
d="
|
|
25
|
+
d="M14.3627 10.3369L10.2197 12.7541L13.6316 14.1098C14.7147 14.5312 15.9366 13.8227 16.1475 12.6966C16.3113 11.8216 15.8264 10.9185 14.9964 10.5884L14.3627 10.3369Z"
|
|
26
26
|
fill="#4FC5B3"
|
|
27
27
|
/>
|
|
28
28
|
<path
|
|
29
|
-
d="M6.
|
|
29
|
+
d="M6.38255 5.64331L3.69375 9.63411C3.41895 9.65492 3.14154 9.69117 2.86569 9.69117C1.86572 9.69255 1.03376 8.8668 0.997336 7.87321C0.960913 6.87944 1.73006 5.99385 2.72749 5.92037L6.38255 5.64331Z"
|
|
30
30
|
fill="#4FC5B3"
|
|
31
31
|
/>
|
|
32
32
|
<path
|
|
33
|
-
d="M7.
|
|
33
|
+
d="M7.31897 1.94643L8.21539 2.92332L6.84973 4.95028L5.10078 5.08672L4.57821 4.51563C3.88603 3.76067 3.93057 2.54616 4.67816 1.84536C5.42435 1.14589 6.62812 1.19291 7.31897 1.94643Z"
|
|
34
34
|
fill="#4FC5B3"
|
|
35
35
|
/>
|
|
36
36
|
</svg>
|
|
37
37
|
);
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
const logoPadding = (layout.newMenuIconSize - layout.logoSize) / 2;
|
|
41
|
-
|
|
42
40
|
export const logoContainerStyle = css`
|
|
43
41
|
${{
|
|
44
|
-
padding: logoPadding,
|
|
45
42
|
width: layout.newMenuIconSize,
|
|
46
43
|
height: layout.newMenuIconSize,
|
|
47
44
|
lineHeight: 0,
|
|
48
45
|
}}
|
|
49
46
|
`;
|
|
47
|
+
|
|
48
|
+
export const mobileLogoSize = 28;
|
|
49
|
+
|
|
50
|
+
export const mobileLogoContainerStyle = css`
|
|
51
|
+
${{
|
|
52
|
+
width: mobileLogoSize,
|
|
53
|
+
height: mobileLogoSize,
|
|
54
|
+
lineHeight: 0,
|
|
55
|
+
}}
|
|
56
|
+
`;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import {ReactNode, useEffect, useRef} from "react";
|
|
2
|
+
import {createPortal} from "react-dom";
|
|
3
|
+
import _ from "lodash";
|
|
4
|
+
import {css, cx} from "@linaria/core";
|
|
5
|
+
import {border, space, themeVars} from "./design-system";
|
|
6
|
+
import {keyboardInsetBottomVar, safeAreaInsetBottomVar} from "./mobile-styles";
|
|
7
|
+
|
|
8
|
+
export const mobileKeyboardAwarePopupZIndex = 1001;
|
|
9
|
+
|
|
10
|
+
export function MobileKeyboardAwarePopup({children, className}: {children: ReactNode; className?: string}) {
|
|
11
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const viewport = window.visualViewport;
|
|
14
|
+
if (!viewport) {
|
|
15
|
+
return _.noop;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const manualKeyboardModeHandler = document.documentElement.classList.contains("fibery-manual-keyboard-mode");
|
|
19
|
+
|
|
20
|
+
let pendingUpdate = false;
|
|
21
|
+
const layoutViewport = document.getElementById("root") as HTMLDivElement;
|
|
22
|
+
const timeoutId = setTimeout(() => {
|
|
23
|
+
if (viewport.offsetTop >= 0 && ref.current) {
|
|
24
|
+
ref.current.style.transform = `translateY(${
|
|
25
|
+
manualKeyboardModeHandler
|
|
26
|
+
? viewport.offsetTop
|
|
27
|
+
: viewport.height - layoutViewport.getBoundingClientRect().height + viewport.offsetTop
|
|
28
|
+
}px)`;
|
|
29
|
+
}
|
|
30
|
+
}, 0);
|
|
31
|
+
|
|
32
|
+
function viewportHandler() {
|
|
33
|
+
clearTimeout(timeoutId);
|
|
34
|
+
if (pendingUpdate) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
pendingUpdate = true;
|
|
38
|
+
|
|
39
|
+
requestAnimationFrame(() => {
|
|
40
|
+
pendingUpdate = false;
|
|
41
|
+
|
|
42
|
+
if (viewport && viewport.offsetTop >= 0 && ref.current) {
|
|
43
|
+
ref.current.style.transform = `translateY(${
|
|
44
|
+
manualKeyboardModeHandler
|
|
45
|
+
? viewport.offsetTop
|
|
46
|
+
: viewport.height - layoutViewport.getBoundingClientRect().height + viewport.offsetTop
|
|
47
|
+
}px)`;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
viewport.addEventListener("scroll", viewportHandler);
|
|
53
|
+
viewport.addEventListener("resize", viewportHandler);
|
|
54
|
+
return () => {
|
|
55
|
+
clearTimeout(timeoutId);
|
|
56
|
+
viewport.removeEventListener("scroll", viewportHandler);
|
|
57
|
+
viewport.removeEventListener("resize", viewportHandler);
|
|
58
|
+
};
|
|
59
|
+
}, []);
|
|
60
|
+
return createPortal(
|
|
61
|
+
<div
|
|
62
|
+
ref={ref}
|
|
63
|
+
className={cx(
|
|
64
|
+
css`
|
|
65
|
+
box-shadow: ${themeVars.shadow200};
|
|
66
|
+
background-color: ${themeVars.actionMenuBg};
|
|
67
|
+
position: fixed;
|
|
68
|
+
bottom: max(max(var(${keyboardInsetBottomVar}), var(${safeAreaInsetBottomVar})), 8px);
|
|
69
|
+
left: 0;
|
|
70
|
+
right: 0;
|
|
71
|
+
z-index: ${mobileKeyboardAwarePopupZIndex};
|
|
72
|
+
transform: translateY(0px);
|
|
73
|
+
border-radius: ${border.radius16}px;
|
|
74
|
+
border: 1px solid ${themeVars.separatorColor};
|
|
75
|
+
margin: 0 ${space.s8}px;
|
|
76
|
+
.fibery-manual-keyboard-mode & {
|
|
77
|
+
margin-bottom: 8px;
|
|
78
|
+
}
|
|
79
|
+
`,
|
|
80
|
+
className
|
|
81
|
+
)}
|
|
82
|
+
>
|
|
83
|
+
{children}
|
|
84
|
+
</div>,
|
|
85
|
+
document.body
|
|
86
|
+
);
|
|
87
|
+
}
|