@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.
- package/CHANGELOG.md +19 -0
- package/config/jest/testFrameworkSetup.js +1 -1
- package/package.json +23 -22
- package/src/abbreviate-name.ts +42 -0
- package/src/actions-menu/actions-menu-item.tsx +14 -5
- package/src/actions-menu/actions-menu-props.tsx +1 -0
- package/src/actions-menu/actions-menu.tsx +4 -1
- package/src/actions-menu/context-actions-menu.tsx +22 -0
- 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/button/base-button.tsx +2 -0
- package/src/button/button.tsx +4 -4
- package/src/button/icon-button.tsx +3 -3
- package/src/card-container.tsx +3 -2
- package/src/checkbox.tsx +17 -0
- package/src/collapsible/index.tsx +4 -2
- package/src/collapsible-section.tsx +3 -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/single-date-input.tsx +5 -1
- package/src/date-picker/styles.ts +20 -0
- package/src/design-system.ts +26 -1
- package/src/dropdown-menu/index.tsx +11 -1
- package/src/emoji-picker/emoji-picker-preview-footer.tsx +4 -0
- package/src/emoji-picker/emoji.tsx +4 -3
- package/src/emoji-picker/primitives/emoji.tsx +49 -51
- package/src/emoji-picker/primitives/footer.tsx +6 -0
- package/src/emoji-picker/primitives/search.tsx +8 -0
- package/src/emoji-picker/primitives/skin-tone.tsx +12 -2
- package/src/fibermoji-placeholder.tsx +2 -29
- package/src/file-item-2.tsx +566 -0
- package/src/file-item.tsx +196 -162
- package/src/header-layout.tsx +11 -0
- package/src/html-styles.ts +13 -4
- package/src/icons/ast/Back.ts +1 -1
- package/src/icons/ast/ExtensionFiles.ts +1 -1
- package/src/icons/ast/FileArchive.ts +8 -0
- package/src/icons/ast/FileBroken.ts +8 -0
- package/src/icons/ast/FileDocument.ts +8 -0
- package/src/icons/ast/FileImage.ts +8 -0
- package/src/icons/ast/FilePresentation.ts +8 -0
- package/src/icons/ast/FileTable.ts +8 -0
- package/src/icons/ast/FileUpload.ts +1 -1
- package/src/icons/ast/FileVideo.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/ViewGallery.ts +8 -0
- package/src/icons/ast/index.tsx +11 -0
- package/src/icons/react/FileArchive.tsx +13 -0
- package/src/icons/react/FileBroken.tsx +13 -0
- package/src/icons/react/FileDocument.tsx +13 -0
- package/src/icons/react/FileImage.tsx +13 -0
- package/src/icons/react/FilePresentation.tsx +13 -0
- package/src/icons/react/FileTable.tsx +13 -0
- package/src/icons/react/FileVideo.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 +11 -0
- package/src/icons/svg/back.svg +3 -1
- package/src/icons/svg/extension/files.svg +3 -1
- package/src/icons/svg/file-archive.svg +3 -0
- package/src/icons/svg/file-broken.svg +3 -0
- package/src/icons/svg/file-document.svg +3 -0
- package/src/icons/svg/file-image.svg +3 -0
- package/src/icons/svg/file-presentation.svg +3 -0
- package/src/icons/svg/file-table.svg +3 -0
- package/src/icons/svg/file-upload.svg +3 -6
- package/src/icons/svg/file-video.svg +3 -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/view-gallery.svg +4 -0
- package/src/images-gallery/images-gallery-fall-through-provider.tsx +11 -0
- package/src/images-gallery/images-gallery.tsx +13 -10
- package/src/images-gallery/zoom.tsx +13 -2
- package/src/images-gallery-2/images-gallery-2.tsx +522 -0
- package/src/images-gallery-2/slide-buttons.tsx +271 -0
- package/src/images-gallery-2/zoom.tsx +35 -0
- package/src/kbd.tsx +46 -0
- package/src/loading-sausage.tsx +2 -2
- package/src/modal-menu/modal-menu-item.tsx +10 -2
- package/src/modal-menu/modal-menu-trigger.tsx +19 -2
- package/src/notification-dot.tsx +16 -7
- package/src/platform-symbols.ts +9 -0
- package/src/platform.ts +2 -0
- package/src/popover/index.tsx +31 -8
- package/src/popover/modifiers.tsx +26 -19
- package/src/reactions/reaction-button.tsx +323 -101
- package/src/reactions/reaction-picker.tsx +14 -1
- 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/select-control-settings-context.tsx +11 -2
- package/src/select/select-in-popover.tsx +10 -7
- package/src/select/styles.ts +21 -1
- package/src/tab-nav/tab-nav.tsx +1 -1
- package/src/toggle.tsx +8 -0
- package/src/tooltip.tsx +28 -19
- package/src/type-badge.tsx +5 -2
- package/src/unit/unit-with-tooltip.tsx +1 -1
- package/src/use-is-phone.tsx +34 -6
- package/src/shortcut-badge.tsx +0 -29
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @fibery/ui-kit
|
|
2
2
|
|
|
3
|
+
## 1.38.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 91fc1ea: Bump react to 18.3.1
|
|
8
|
+
- Updated dependencies [91fc1ea]
|
|
9
|
+
- @fibery/react@1.4.6
|
|
10
|
+
|
|
11
|
+
## 1.38.1
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- db89c7a: Add Gallery View
|
|
16
|
+
- 00766c6: switch to pnpm catalogs. Update to latest
|
|
17
|
+
- Updated dependencies [00766c6]
|
|
18
|
+
- @fibery/emoji-data@2.7.1
|
|
19
|
+
- @fibery/helpers@1.3.4
|
|
20
|
+
- @fibery/react@1.4.5
|
|
21
|
+
|
|
3
22
|
## 1.38.0
|
|
4
23
|
|
|
5
24
|
### Minor Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import "@testing-library/jest-dom
|
|
1
|
+
import "@testing-library/jest-dom";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fibery/ui-kit",
|
|
3
|
-
"version": "1.38.
|
|
3
|
+
"version": "1.38.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"dependencies": {
|
|
@@ -31,59 +31,60 @@
|
|
|
31
31
|
"lodash": "4.17.21",
|
|
32
32
|
"md5": "2.2.1",
|
|
33
33
|
"moment": "2.29.4",
|
|
34
|
+
"photoswipe": "5.4.4",
|
|
34
35
|
"popper-max-size-modifier": "0.2.0",
|
|
35
36
|
"prop-types": "15.7.2",
|
|
36
37
|
"rc-input-number": "8.5.0",
|
|
37
38
|
"rc-progress": "3.4.1",
|
|
38
39
|
"react-color": "2.19.3",
|
|
39
|
-
"react-day-picker": "8.1
|
|
40
|
+
"react-day-picker": "8.10.1",
|
|
40
41
|
"react-intersection-observer": "9.3.5",
|
|
41
42
|
"react-medium-image-zoom": "5.2.10",
|
|
42
43
|
"react-popper": "2.3.0",
|
|
43
44
|
"react-select": "5.3.2",
|
|
44
45
|
"react-select-country-list": "2.2.1",
|
|
45
|
-
"react-virtuoso": "4.
|
|
46
|
-
"screenfull": "6.0.
|
|
46
|
+
"react-virtuoso": "4.14.1",
|
|
47
|
+
"screenfull": "6.0.2",
|
|
47
48
|
"tabbable": "5.2.1",
|
|
48
49
|
"ua-parser-js": "1.0.39",
|
|
49
|
-
"@fibery/emoji-data": "2.7.
|
|
50
|
-
"@fibery/helpers": "1.3.
|
|
51
|
-
"@fibery/react": "1.4.
|
|
50
|
+
"@fibery/emoji-data": "2.7.1",
|
|
51
|
+
"@fibery/helpers": "1.3.4",
|
|
52
|
+
"@fibery/react": "1.4.6"
|
|
52
53
|
},
|
|
53
54
|
"peerDependencies": {
|
|
54
|
-
"react": "
|
|
55
|
-
"react-dom": "
|
|
55
|
+
"react": "18.3.1",
|
|
56
|
+
"react-dom": "18.3.1"
|
|
56
57
|
},
|
|
57
58
|
"devDependencies": {
|
|
58
|
-
"@babel/core": "7.
|
|
59
|
-
"@babel/runtime": "7.
|
|
59
|
+
"@babel/core": "7.28.5",
|
|
60
|
+
"@babel/runtime": "7.28.4",
|
|
60
61
|
"@testing-library/dom": "8.19.1",
|
|
61
|
-
"@testing-library/jest-dom": "
|
|
62
|
+
"@testing-library/jest-dom": "6.9.1",
|
|
62
63
|
"@testing-library/react": "13.4.0",
|
|
63
64
|
"@testing-library/user-event": "13.5.0",
|
|
64
65
|
"@types/chroma-js": "2.1.3",
|
|
65
66
|
"@types/color-hash": "1.0.2",
|
|
66
67
|
"@types/history": "4.7.11",
|
|
67
68
|
"@types/invariant": "2.2.34",
|
|
68
|
-
"@types/jest": "
|
|
69
|
+
"@types/jest": "30.0.0",
|
|
69
70
|
"@types/lodash": "4.14.172",
|
|
70
71
|
"@types/prop-types": "15.7.5",
|
|
71
|
-
"@types/react": "18.
|
|
72
|
-
"@types/react-dom": "18.
|
|
72
|
+
"@types/react": "18.3.12",
|
|
73
|
+
"@types/react-dom": "18.3.1",
|
|
73
74
|
"@wyw-in-js/babel-preset": "0.5.5",
|
|
74
75
|
"csstype": "3.0.8",
|
|
75
76
|
"fs-extra": "10.0.0",
|
|
76
77
|
"glob": "7.1.7",
|
|
77
|
-
"jest": "
|
|
78
|
-
"jest-junit": "
|
|
79
|
-
"react": "18.
|
|
80
|
-
"react-dom": "18.
|
|
78
|
+
"jest": "30.2.0",
|
|
79
|
+
"jest-junit": "16.0.0",
|
|
80
|
+
"react": "18.3.1",
|
|
81
|
+
"react-dom": "18.3.1",
|
|
81
82
|
"svg-parser": "2.0.4",
|
|
82
83
|
"svgo": "2.8.0",
|
|
83
|
-
"typescript": "5.
|
|
84
|
+
"typescript": "5.9.3",
|
|
84
85
|
"unist-util-reduce": "0.2.2",
|
|
85
|
-
"@fibery/
|
|
86
|
-
"@fibery/
|
|
86
|
+
"@fibery/babel-preset": "7.4.1",
|
|
87
|
+
"@fibery/eslint-config": "8.6.2"
|
|
87
88
|
},
|
|
88
89
|
"jest": {
|
|
89
90
|
"testEnvironment": "jsdom",
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const preservedNameEmojis = ["🤖", "👻", "🧮", "🪄", "🔌", "🔗", "🔒"];
|
|
2
|
+
|
|
3
|
+
export const abbreviateName = (name?: string | null) => {
|
|
4
|
+
if (name === undefined) {
|
|
5
|
+
return "…";
|
|
6
|
+
}
|
|
7
|
+
if (name && preservedNameEmojis.includes(name)) {
|
|
8
|
+
return name;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Check if name looks like "Surname, Name"
|
|
12
|
+
const hasComma = (name || "").includes(",");
|
|
13
|
+
|
|
14
|
+
const cleaned = (name || "")
|
|
15
|
+
.replace(/\p{Emoji_Presentation}|\p{Emoji}\uFE0F?/gu, "") // remove emojis
|
|
16
|
+
.replace(/[^\p{L}\p{M}'\-\s,]+/gu, " ") // keep comma to detect order before removing
|
|
17
|
+
.trim();
|
|
18
|
+
|
|
19
|
+
// Split on whitespace and commas
|
|
20
|
+
let parts = cleaned.split(/[,\s]+/).filter(Boolean);
|
|
21
|
+
|
|
22
|
+
// If there was a comma, assume it's "Surname, Name" and reverse
|
|
23
|
+
if (hasComma && parts.length > 1) {
|
|
24
|
+
parts = parts.reverse();
|
|
25
|
+
}
|
|
26
|
+
let result: string;
|
|
27
|
+
if (parts.length === 1) {
|
|
28
|
+
// Take the first two codepoints (safer for emoji / astral / surrogate pairs)
|
|
29
|
+
result = [...parts[0]].slice(0, 2).join("");
|
|
30
|
+
} else {
|
|
31
|
+
// Take the first codepoint of the first two parts and upper-case
|
|
32
|
+
result = parts
|
|
33
|
+
.slice(0, 2)
|
|
34
|
+
.map((p) => {
|
|
35
|
+
const first = [...p][0] || "";
|
|
36
|
+
return first.toUpperCase();
|
|
37
|
+
})
|
|
38
|
+
.join("");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return result || "?";
|
|
42
|
+
};
|
|
@@ -7,11 +7,12 @@ import CheckedIcon from "../icons/react/Checked";
|
|
|
7
7
|
import {IconBaseProps} from "../icons/types";
|
|
8
8
|
import {Spinner} from "../loaders";
|
|
9
9
|
import {mobileRootSelector} from "../mobile-styles";
|
|
10
|
-
import {
|
|
10
|
+
import {Kbd, KbdGroup} from "../kbd";
|
|
11
11
|
import {useTheme} from "../theme-provider";
|
|
12
12
|
import {useIsPhone} from "../use-is-phone";
|
|
13
13
|
import {useActionsMenuContext} from "./contexts/actions-menu-context";
|
|
14
14
|
import {useActiveDangerousRow, useSetActiveDangerousRow} from "./contexts/actions-menu-dangerous-rows";
|
|
15
|
+
import _ from "lodash";
|
|
15
16
|
|
|
16
17
|
const hiddenTextCss = css`
|
|
17
18
|
visibility: hidden;
|
|
@@ -90,14 +91,22 @@ const firstLetterToLowerCase = (str: string) => {
|
|
|
90
91
|
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
91
92
|
};
|
|
92
93
|
|
|
93
|
-
const RightCorner = ({shortcut, loading, checked}: {shortcut?: string; loading?: boolean; checked?: boolean}) => {
|
|
94
|
+
const RightCorner = ({shortcut, loading, checked}: {shortcut?: string[]; loading?: boolean; checked?: boolean}) => {
|
|
94
95
|
const theme = useTheme();
|
|
95
96
|
const isPhone = useIsPhone();
|
|
96
97
|
|
|
97
|
-
|
|
98
|
+
const shortcuts = _.isArray(shortcut) ? shortcut : shortcut ? [shortcut] : null;
|
|
99
|
+
|
|
100
|
+
return loading || shortcuts || checked ? (
|
|
98
101
|
<div className={cornerCss}>
|
|
99
102
|
{loading ? <Spinner color={theme.primary} iconSize={16} containerSize={16} /> : null}
|
|
100
|
-
{
|
|
103
|
+
{shortcuts ? (
|
|
104
|
+
<KbdGroup>
|
|
105
|
+
{shortcuts.map((item) => (
|
|
106
|
+
<Kbd key={item}>{item}</Kbd>
|
|
107
|
+
))}
|
|
108
|
+
</KbdGroup>
|
|
109
|
+
) : null}
|
|
101
110
|
{checked ? <CheckedIcon iconSize={isPhone ? 20 : 18} color={themeVars.textColor} /> : null}
|
|
102
111
|
</div>
|
|
103
112
|
) : null;
|
|
@@ -127,7 +136,7 @@ export type ActionsMenuItemProps = {
|
|
|
127
136
|
Icon?: FunctionComponent<IconBaseProps>;
|
|
128
137
|
iconColor?: string;
|
|
129
138
|
/** Hint for keyboard shortcut for this action */
|
|
130
|
-
shortcut?: string;
|
|
139
|
+
shortcut?: string[];
|
|
131
140
|
disabled?: boolean;
|
|
132
141
|
/** Whether the action requires confirmation */
|
|
133
142
|
dangerous?: boolean;
|
|
@@ -5,6 +5,7 @@ import {ContentProps} from "../dropdown-menu";
|
|
|
5
5
|
export type ActionsMenuProps = {
|
|
6
6
|
/** Clicking on this node will open actions menu. Make sure that trigger forwards ref AND props to html element */
|
|
7
7
|
trigger: ReactNode;
|
|
8
|
+
triggerEvent?: "click" | "context-menu";
|
|
8
9
|
children: ReactNode;
|
|
9
10
|
align?: ContentProps["align"];
|
|
10
11
|
disabled?: boolean;
|
|
@@ -23,6 +23,7 @@ const wideCss = css`
|
|
|
23
23
|
|
|
24
24
|
export const ActionsMenu = ({
|
|
25
25
|
trigger,
|
|
26
|
+
triggerEvent = "click",
|
|
26
27
|
wide,
|
|
27
28
|
align = "start",
|
|
28
29
|
alignOffset,
|
|
@@ -77,7 +78,9 @@ export const ActionsMenu = ({
|
|
|
77
78
|
<MenuPrimitive.Trigger
|
|
78
79
|
// backward compatibility for dropdown styles
|
|
79
80
|
className={isOpen ? "actions-visible" : "actions-hidden actions-visible-on-mobile"}
|
|
80
|
-
onClick={preventDefaultAndStopPropagation}
|
|
81
|
+
onClick={triggerEvent === "click" ? preventDefaultAndStopPropagation : undefined}
|
|
82
|
+
onContextMenu={triggerEvent === "context-menu" ? preventDefaultAndStopPropagation : undefined}
|
|
83
|
+
triggerEvent={triggerEvent}
|
|
81
84
|
disabled={disabled}
|
|
82
85
|
asChild
|
|
83
86
|
>
|
|
@@ -2,6 +2,8 @@ import _ from "lodash";
|
|
|
2
2
|
import {useControllableState} from "@fibery/react/src/use-controllable-state";
|
|
3
3
|
import {ActionsMenuContextProvider} from "./contexts/actions-menu-context";
|
|
4
4
|
import * as ContextMenu from "../context-menu";
|
|
5
|
+
import {ActionsMenu} from "./actions-menu";
|
|
6
|
+
import {useIsPhone} from "../use-is-phone";
|
|
5
7
|
import {ActionsMenuDangerousRowsProvider} from "./contexts/actions-menu-dangerous-rows";
|
|
6
8
|
import {ActionsMenuProps} from "./actions-menu-props";
|
|
7
9
|
import {preventDefault} from "@fibery/react/src/prevent-default";
|
|
@@ -14,11 +16,31 @@ export const ContextActionsMenu = ({
|
|
|
14
16
|
trigger,
|
|
15
17
|
children,
|
|
16
18
|
disabled,
|
|
19
|
+
mobileTitle,
|
|
20
|
+
supportsMobile,
|
|
17
21
|
autoFocusOnClose = true,
|
|
18
22
|
}: ActionsMenuProps): JSX.Element => {
|
|
23
|
+
const isPhone = useIsPhone();
|
|
19
24
|
const [isOpen = false, setOpen] = useControllableState({value: open, onChange: onOpenChange});
|
|
20
25
|
const [confirmation, setConfirmation] = useState<ActionsMenuConfirmationProps | null>(null);
|
|
21
26
|
|
|
27
|
+
// Special mode - on mobile, open context menu in modal
|
|
28
|
+
if (isPhone && supportsMobile) {
|
|
29
|
+
return (
|
|
30
|
+
<ActionsMenu
|
|
31
|
+
open={open}
|
|
32
|
+
onOpenChange={onOpenChange}
|
|
33
|
+
mobileTitle={mobileTitle}
|
|
34
|
+
supportsMobile
|
|
35
|
+
// Extra div is important here to not loose the original onClick handler
|
|
36
|
+
trigger={<div>{trigger}</div>}
|
|
37
|
+
triggerEvent="context-menu"
|
|
38
|
+
>
|
|
39
|
+
{children}
|
|
40
|
+
</ActionsMenu>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
22
44
|
return (
|
|
23
45
|
<ActionsMenuContextProvider setOpen={setOpen} showConfirmation={setConfirmation} MenuPrimitive={ContextMenu}>
|
|
24
46
|
<ContextMenu.Root onOpenChange={onOpenChange}>
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import {useSize} from "@fibery/react/src/use-size";
|
|
2
2
|
import React, {ComponentProps, forwardRef, useEffect, useRef, useState} from "react";
|
|
3
3
|
import {duration, transition} from "./design-system";
|
|
4
|
-
import cx from "classnames";
|
|
5
4
|
import _ from "lodash";
|
|
6
5
|
import {useComposedRefs} from "@fibery/react/src/use-composed-refs";
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
type AnimatedHeightContainerProps = ComponentProps<"div"> & {
|
|
9
8
|
noAnimation?: boolean;
|
|
10
|
-
|
|
9
|
+
onTransitionStart?: (event: TransitionEvent) => void;
|
|
10
|
+
onTransitionEnd?: (event: TransitionEvent) => void;
|
|
11
|
+
};
|
|
11
12
|
|
|
12
13
|
export const AnimatedHeightContainer = forwardRef<HTMLDivElement, AnimatedHeightContainerProps>(
|
|
13
|
-
function AnimatedHeightContainerComponent(
|
|
14
|
+
function AnimatedHeightContainerComponent(
|
|
15
|
+
{className, noAnimation = false, onTransitionStart = _.noop, onTransitionEnd = _.noop, children, ...otherProps},
|
|
16
|
+
ref
|
|
17
|
+
) {
|
|
14
18
|
const measuredContainer = useRef<HTMLDivElement | null>(null);
|
|
15
19
|
const size = useSize(measuredContainer);
|
|
16
20
|
|
|
@@ -60,6 +64,21 @@ export const AnimatedHeightContainer = forwardRef<HTMLDivElement, AnimatedHeight
|
|
|
60
64
|
return cleanup;
|
|
61
65
|
}, [animating]);
|
|
62
66
|
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
const element = containerRef.current;
|
|
69
|
+
if (!element) {
|
|
70
|
+
return () => {};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
element.addEventListener("transitionstart", onTransitionStart);
|
|
74
|
+
element.addEventListener("transitionend", onTransitionEnd);
|
|
75
|
+
|
|
76
|
+
return () => {
|
|
77
|
+
element.removeEventListener("transitionstart", onTransitionStart);
|
|
78
|
+
element.removeEventListener("transitionend", onTransitionEnd);
|
|
79
|
+
};
|
|
80
|
+
}, [onTransitionStart, onTransitionEnd]);
|
|
81
|
+
|
|
63
82
|
const style = animating
|
|
64
83
|
? {
|
|
65
84
|
...otherProps.style,
|
|
@@ -74,7 +93,7 @@ export const AnimatedHeightContainer = forwardRef<HTMLDivElement, AnimatedHeight
|
|
|
74
93
|
};
|
|
75
94
|
|
|
76
95
|
return (
|
|
77
|
-
<div ref={composedRef} className={
|
|
96
|
+
<div ref={composedRef} className={className} {...otherProps} style={style}>
|
|
78
97
|
<div ref={measuredContainer}>{children}</div>
|
|
79
98
|
</div>
|
|
80
99
|
);
|
package/src/antd/ant-upload.tsx
CHANGED
|
@@ -27,7 +27,7 @@ export const antUploadStyle = css`
|
|
|
27
27
|
alignItems: "stretch",
|
|
28
28
|
alignContent: "stretch",
|
|
29
29
|
},
|
|
30
|
-
"& .ant-upload.ant-upload-drag, .ant-upload.ant-upload-select-picture-card": {
|
|
30
|
+
"& .ant-upload:where(.ant-upload-drag), .ant-upload:where(.ant-upload-select-picture-card)": {
|
|
31
31
|
border: `1px dashed ${themeVars.separator}`,
|
|
32
32
|
position: "relative",
|
|
33
33
|
backgroundColor: themeVars.transparent,
|
package/src/antd/input.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import {getWrapper} from "./get-wrapper";
|
|
|
2
2
|
import Input from "antd/lib/input";
|
|
3
3
|
import "antd/lib/input/style/css";
|
|
4
4
|
import {css} from "@linaria/core";
|
|
5
|
+
import {mobileRootSelector} from "../mobile-styles";
|
|
5
6
|
import {opacity, textStyles, themeVars} from "../design-system";
|
|
6
7
|
|
|
7
8
|
import {inputStyles} from "./styles";
|
|
@@ -24,6 +25,9 @@ export const transparentInputStyle = css`
|
|
|
24
25
|
transition: "none",
|
|
25
26
|
...textStyles.regular,
|
|
26
27
|
...textStyles.numeric.tabularOff,
|
|
28
|
+
[`${mobileRootSelector} &`]: {
|
|
29
|
+
...textStyles.big,
|
|
30
|
+
},
|
|
27
31
|
},
|
|
28
32
|
"& textarea.ant-input": {
|
|
29
33
|
fontVariant: "inherit",
|
package/src/avatar.tsx
CHANGED
|
@@ -5,33 +5,7 @@ import {getDarkenColor, getObjectColorMemoized, textStyles, themeVars} from "./d
|
|
|
5
5
|
import {FibermojiPlaceholder} from "./fibermoji-placeholder";
|
|
6
6
|
import {getShiftStyle} from "./icons/get-shift-style";
|
|
7
7
|
import {useFeatures} from "./features";
|
|
8
|
-
|
|
9
|
-
const preservedNameEmojis = ["🤖", "👻", "🧮", "🪄", "🔌", "🔗", "🔒"];
|
|
10
|
-
|
|
11
|
-
export const abbreviateName = (name?: string) => {
|
|
12
|
-
if (name === undefined) {
|
|
13
|
-
return "…";
|
|
14
|
-
}
|
|
15
|
-
if (preservedNameEmojis.includes(name)) {
|
|
16
|
-
return name;
|
|
17
|
-
}
|
|
18
|
-
const filteredName = (name || "").replace(/[!~.\-@[\]]/g, "").trim();
|
|
19
|
-
const match = filteredName.match(/\p{Letter}[\p{Letter} ]+/gu);
|
|
20
|
-
const processedName = match ? match[0] : "";
|
|
21
|
-
const parts = processedName.split(" ").filter((part) => part !== "");
|
|
22
|
-
let result;
|
|
23
|
-
if (parts.length === 1) {
|
|
24
|
-
result = processedName.slice(0, 2);
|
|
25
|
-
} else {
|
|
26
|
-
result = parts
|
|
27
|
-
.filter((part, index) => index < 2)
|
|
28
|
-
.map((part) => {
|
|
29
|
-
return part[0].toUpperCase();
|
|
30
|
-
})
|
|
31
|
-
.join("");
|
|
32
|
-
}
|
|
33
|
-
return result || "?";
|
|
34
|
-
};
|
|
8
|
+
import {abbreviateName} from "./abbreviate-name";
|
|
35
9
|
|
|
36
10
|
export const getContainerStyle = _.memoize((containerSize) => {
|
|
37
11
|
return {
|
package/src/button/button.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import {forwardRef} from "react";
|
|
|
3
3
|
import {border, fontWeight, space, textStyles} from "../design-system";
|
|
4
4
|
import {iconSizeVar} from "../icons/Icon";
|
|
5
5
|
import SpinnerIcon from "../icons/react/Spinner";
|
|
6
|
-
import {BaseButton, BaseButtonProps, ButtonSize} from "./base-button";
|
|
6
|
+
import {BaseButton, BaseButtonProps, ButtonSize, xLargeButtonHeight} from "./base-button";
|
|
7
7
|
import {useIsSupportHardwareKeyboard} from "../use-is-support-hardware-keyboard";
|
|
8
8
|
import {useIsPhone} from "../use-is-phone";
|
|
9
9
|
|
|
@@ -145,12 +145,11 @@ const buttonSize = {
|
|
|
145
145
|
}
|
|
146
146
|
`,
|
|
147
147
|
xLarge: css`
|
|
148
|
-
font-size: ${textStyles.
|
|
148
|
+
font-size: ${textStyles.heading4.fontSize}px;
|
|
149
149
|
line-height: 20px;
|
|
150
|
-
letter-spacing: ${textStyles.heading3.letterSpacing};
|
|
151
150
|
|
|
152
151
|
border-radius: ${border.radius6}px;
|
|
153
|
-
min-height:
|
|
152
|
+
min-height: ${xLargeButtonHeight}px;
|
|
154
153
|
padding: ${space.s6}px ${space.s12}px;
|
|
155
154
|
gap: ${space.s6}px;
|
|
156
155
|
|
|
@@ -205,6 +204,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
205
204
|
ref={ref}
|
|
206
205
|
disabled={disabled || pending}
|
|
207
206
|
className={cx(
|
|
207
|
+
"notranslate",
|
|
208
208
|
className,
|
|
209
209
|
button,
|
|
210
210
|
buttonSize[supportMobile && isPhone ? "large" : size],
|
|
@@ -3,7 +3,7 @@ import {forwardRef} from "react";
|
|
|
3
3
|
import {border, space} from "../design-system";
|
|
4
4
|
import {iconSizeVar} from "../icons/Icon";
|
|
5
5
|
import Spinner from "../icons/react/Spinner";
|
|
6
|
-
import {BaseButton, BaseButtonProps, ButtonSize} from "./base-button";
|
|
6
|
+
import {BaseButton, BaseButtonProps, ButtonSize, xLargeButtonHeight} from "./base-button";
|
|
7
7
|
import {useIsPhone} from "../use-is-phone";
|
|
8
8
|
|
|
9
9
|
export type IconButtonProps = {
|
|
@@ -55,8 +55,8 @@ export const iconButtonSizes = {
|
|
|
55
55
|
xLarge: css`
|
|
56
56
|
padding: ${space.s6}px;
|
|
57
57
|
|
|
58
|
-
min-width:
|
|
59
|
-
min-height:
|
|
58
|
+
min-width: ${xLargeButtonHeight}px;
|
|
59
|
+
min-height: ${xLargeButtonHeight}px;
|
|
60
60
|
border-radius: ${border.radius6}px;
|
|
61
61
|
|
|
62
62
|
${iconSizeVar}: 24px;
|
package/src/card-container.tsx
CHANGED
|
@@ -247,7 +247,8 @@ const floatingStyles = {
|
|
|
247
247
|
};
|
|
248
248
|
|
|
249
249
|
const coverClassName = css`
|
|
250
|
-
|
|
250
|
+
// box padding -1px to go below the outline
|
|
251
|
+
margin: ${-space.s5}px;
|
|
251
252
|
|
|
252
253
|
&:empty {
|
|
253
254
|
display: none;
|
|
@@ -255,7 +256,7 @@ const coverClassName = css`
|
|
|
255
256
|
`;
|
|
256
257
|
|
|
257
258
|
const coverWithContentClassName = css`
|
|
258
|
-
border-bottom: ${themeVars.
|
|
259
|
+
border-bottom: ${themeVars.shortcutBorder};
|
|
259
260
|
margin-bottom: 0;
|
|
260
261
|
`;
|
|
261
262
|
|
package/src/checkbox.tsx
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "react";
|
|
15
15
|
import {colors, getDarkenColor, getOpacities, layout, space, textStyles, ThemeColors, themeVars} from "./design-system";
|
|
16
16
|
import {smallHtmlStylesClass} from "./html-styles";
|
|
17
|
+
import {mobileRootSelector} from "./mobile-styles";
|
|
17
18
|
|
|
18
19
|
const checkboxColor = `--fibery-checkbox-color`;
|
|
19
20
|
const checkboxColorVar = `var(${checkboxColor})`;
|
|
@@ -36,6 +37,10 @@ const backgroundStyle = css`
|
|
|
36
37
|
box-shadow: 0 0 0 1.5px ${borderColorVar};
|
|
37
38
|
background-color: ${themeVars.panelBg};
|
|
38
39
|
|
|
40
|
+
${mobileRootSelector} & {
|
|
41
|
+
box-shadow: 0 0 0 1.6px ${borderColorVar};
|
|
42
|
+
}
|
|
43
|
+
|
|
39
44
|
.${smallHtmlStylesClass} & {
|
|
40
45
|
width: ${layout.checkboxSize - 2}px;
|
|
41
46
|
height: ${layout.checkboxSize - 2}px;
|
|
@@ -53,6 +58,9 @@ const checkboxRootStyle = css`
|
|
|
53
58
|
& input[type="checkbox"]:checked + .${backgroundStyle} {
|
|
54
59
|
background-color: ${checkboxColorVar};
|
|
55
60
|
box-shadow: 0 0 0 1.5px ${checkboxColorVar} !important;
|
|
61
|
+
${mobileRootSelector} & {
|
|
62
|
+
box-shadow: 0 0 0 1.6px ${checkboxColorVar} !important;
|
|
63
|
+
}
|
|
56
64
|
}
|
|
57
65
|
|
|
58
66
|
& input[type="checkbox"]:indeterminate + .${backgroundStyle} {
|
|
@@ -66,15 +74,24 @@ const checkboxRootStyle = css`
|
|
|
66
74
|
&:hover input[type="checkbox"]:checked:not(:disabled) + .${backgroundStyle} {
|
|
67
75
|
background-color: ${darkenColorVar};
|
|
68
76
|
box-shadow: 0 0 0 1.5px ${darkenColorVar};
|
|
77
|
+
${mobileRootSelector} & {
|
|
78
|
+
box-shadow: 0 0 0 1.6px ${darkenColorVar};
|
|
79
|
+
}
|
|
69
80
|
}
|
|
70
81
|
|
|
71
82
|
&:hover input[type="checkbox"]:checked:focus:not(:disabled) + .${backgroundStyle} {
|
|
72
83
|
background-color: ${darkenColorVar};
|
|
73
84
|
box-shadow: 0 0 0 1.5px ${darkenColorVar}, 0 0 0 4px ${focusColorVar};
|
|
85
|
+
${mobileRootSelector} & {
|
|
86
|
+
box-shadow: 0 0 0 1.6px ${darkenColorVar}, 0 0 0 4px ${focusColorVar};
|
|
87
|
+
}
|
|
74
88
|
}
|
|
75
89
|
|
|
76
90
|
& input[type="checkbox"]:focus + .${backgroundStyle} {
|
|
77
91
|
box-shadow: 0 0 0 1.5px ${checkboxColorVar}, 0 0 0 4px ${focusColorVar};
|
|
92
|
+
${mobileRootSelector} & {
|
|
93
|
+
box-shadow: 0 0 0 1.6px ${checkboxColorVar}, 0 0 0 4px ${focusColorVar};
|
|
94
|
+
}
|
|
78
95
|
}
|
|
79
96
|
|
|
80
97
|
.${smallHtmlStylesClass} & {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {styled} from "@linaria/react";
|
|
2
2
|
import * as Collapsible from "@radix-ui/react-collapsible";
|
|
3
3
|
|
|
4
|
+
export type CollapsibleRootProps = Collapsible.CollapsibleProps;
|
|
5
|
+
|
|
4
6
|
export const CollapsibleRoot = Collapsible.Root;
|
|
5
7
|
|
|
6
8
|
export const CollapsibleTrigger = Collapsible.Trigger;
|
|
@@ -34,10 +36,10 @@ export const CollapsibleContent = styled(Collapsible.Content)`
|
|
|
34
36
|
|
|
35
37
|
@media (prefers-reduced-motion: no-preference) {
|
|
36
38
|
&[data-state="open"] {
|
|
37
|
-
animation: slideDown
|
|
39
|
+
animation: slideDown 150ms ease-out;
|
|
38
40
|
}
|
|
39
41
|
&[data-state="closed"] {
|
|
40
|
-
animation: slideUp
|
|
42
|
+
animation: slideUp 150ms ease-out;
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
`;
|
|
@@ -25,6 +25,7 @@ type Props = {
|
|
|
25
25
|
children: ReactNode;
|
|
26
26
|
badge?: ReactNode;
|
|
27
27
|
keepChildren?: boolean;
|
|
28
|
+
className?: string;
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
export const CollapsibleSection = ({
|
|
@@ -35,6 +36,7 @@ export const CollapsibleSection = ({
|
|
|
35
36
|
onCollapsedChange,
|
|
36
37
|
children,
|
|
37
38
|
badge,
|
|
39
|
+
className,
|
|
38
40
|
}: Props) => {
|
|
39
41
|
const [isCollapsed, setIsCollapsed] = useControllableState({
|
|
40
42
|
value: collapsed,
|
|
@@ -71,7 +73,7 @@ export const CollapsibleSection = ({
|
|
|
71
73
|
const regularHeader = label && <div className={headerCss}>{label}</div>;
|
|
72
74
|
|
|
73
75
|
return (
|
|
74
|
-
<div>
|
|
76
|
+
<div className={className}>
|
|
75
77
|
{collapsible ? collapsibleHeader : regularHeader}
|
|
76
78
|
<div style={{display: collapsible && isCollapsed ? "none" : "block"}}>{children}</div>
|
|
77
79
|
</div>
|
|
@@ -2,7 +2,8 @@ import moment from "moment";
|
|
|
2
2
|
import {useMemo} from "react";
|
|
3
3
|
import {Select} from "../select";
|
|
4
4
|
import {SelectControlSettingsProvider} from "../select/select-control-settings-context";
|
|
5
|
-
import {timeFormat as defaultTimeFormat} from "../design-system";
|
|
5
|
+
import {timeFormat as defaultTimeFormat, space} from "../design-system";
|
|
6
|
+
import {useIsPhone} from "../use-is-phone";
|
|
6
7
|
|
|
7
8
|
const step = 30;
|
|
8
9
|
|
|
@@ -26,6 +27,8 @@ export const AutoComplete = ({
|
|
|
26
27
|
menuIsOpen: boolean;
|
|
27
28
|
position: number;
|
|
28
29
|
}) => {
|
|
30
|
+
const isPhone = useIsPhone();
|
|
31
|
+
|
|
29
32
|
const options = useMemo(
|
|
30
33
|
() =>
|
|
31
34
|
Array.from({length: (24 * 60) / step}, (value, index) => {
|
|
@@ -61,12 +64,15 @@ export const AutoComplete = ({
|
|
|
61
64
|
...props,
|
|
62
65
|
zIndex: 1000000,
|
|
63
66
|
position: "absolute",
|
|
64
|
-
width: "auto",
|
|
65
|
-
top: position,
|
|
67
|
+
width: isPhone ? `calc(100vw - ${2 * space.s12}px)` : "auto",
|
|
68
|
+
top: isPhone ? space.s18 : position,
|
|
66
69
|
margin: 0,
|
|
67
|
-
left: 100,
|
|
70
|
+
left: isPhone ? -space.s12 : 100,
|
|
71
|
+
}),
|
|
72
|
+
menuList: (props) => ({
|
|
73
|
+
...props,
|
|
74
|
+
width: isPhone ? "auto" : 100,
|
|
68
75
|
}),
|
|
69
|
-
menuList: (props) => ({...props, width: 100}),
|
|
70
76
|
}}
|
|
71
77
|
/>
|
|
72
78
|
</SelectControlSettingsProvider>
|
|
@@ -2,6 +2,7 @@ import {css} from "@linaria/core";
|
|
|
2
2
|
import cx from "classnames";
|
|
3
3
|
import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState} from "react";
|
|
4
4
|
import {MonthChangeEventHandler} from "react-day-picker";
|
|
5
|
+
import {mobileRootSelector} from "../mobile-styles";
|
|
5
6
|
import {AntTransparentInput} from "../antd/input";
|
|
6
7
|
import {AntTransparentTextArea} from "../antd/input";
|
|
7
8
|
import {inputOverrides} from "../antd/styles";
|
|
@@ -292,6 +293,9 @@ export const DateRangeInput = forwardRef<
|
|
|
292
293
|
display: flex;
|
|
293
294
|
margin-bottom: ${space.s12 + space.s6}px;
|
|
294
295
|
padding-right: ${space.s12 - 2}px;
|
|
296
|
+
${mobileRootSelector} & {
|
|
297
|
+
min-height: ${space.s44}px;
|
|
298
|
+
}
|
|
295
299
|
`,
|
|
296
300
|
{[selectedStyle]: selected, [disabledStyle]: disabled}
|
|
297
301
|
)}
|
|
@@ -335,7 +339,7 @@ export const DateRangeInput = forwardRef<
|
|
|
335
339
|
/>
|
|
336
340
|
</div>
|
|
337
341
|
{allowClear && inputValue !== "" && (
|
|
338
|
-
<IconButton onClick={onClear} size={"tiny"}>
|
|
342
|
+
<IconButton onClick={onClear} size={"tiny"} supportMobile>
|
|
339
343
|
<RemoveIcon />
|
|
340
344
|
</IconButton>
|
|
341
345
|
)}
|