@fibery/ui-kit 1.37.0 → 1.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/package.json +8 -5
- package/src/actions-menu/actions-menu-item.tsx +18 -6
- 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/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 +5 -3
- package/src/button/button-group.tsx +1 -1
- package/src/button/button.tsx +31 -0
- package/src/button/icon-button.tsx +9 -0
- package/src/button/select-button.tsx +4 -0
- package/src/card-container.tsx +7 -4
- 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/date-range-picker.tsx +6 -3
- package/src/date-picker/relative-date-picker.tsx +6 -2
- 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/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 +21 -12
- package/src/dropdown-menu/index.tsx +8 -1
- package/src/emoji-picker/app-icon-picker.tsx +6 -4
- 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 +10 -1
- package/src/emoji-picker/primitives/footer.tsx +0 -1
- 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/field-icon.tsx +4 -1
- package/src/file-item.tsx +164 -47
- package/src/html-styles.ts +8 -0
- package/src/icons/ast/ActivityFilled.ts +8 -0
- package/src/icons/ast/AiAssistantFilled.ts +8 -0
- 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/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/TypeDate.ts +1 -1
- package/src/icons/ast/index.tsx +12 -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/index.tsx +12 -0
- package/src/icons/svg/activity-filled.svg +4 -0
- package/src/icons/svg/ai-assistant-filled.svg +3 -0
- 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/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/type/date.svg +3 -2
- package/src/images-gallery/images-gallery.tsx +254 -0
- package/src/images-gallery/zoom.tsx +112 -0
- package/src/is-in-popup.ts +1 -1
- 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 +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/online-users.tsx +3 -3
- package/src/palette.ts +1 -1
- 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/select/index.tsx +8 -4
- package/src/select/select-in-popover.tsx +21 -33
- package/src/tab-nav/tab-nav.tsx +35 -9
- 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.tsx +2 -2
- package/src/unit/styles.ts +2 -2
- package/src/use-is-phone.tsx +28 -3
- 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/{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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @fibery/ui-kit
|
|
2
2
|
|
|
3
|
+
## 1.38.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- ab88ef9: add ToggleButtonGroupXComponent
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- ece31af: Move expression-utils to typescript
|
|
12
|
+
- d5b2a71: add RoundTogleButton
|
|
13
|
+
- 0d0530a: add ToggleButton component
|
|
14
|
+
- Updated dependencies [586c255]
|
|
15
|
+
- @fibery/emoji-data@2.7.0
|
|
16
|
+
|
|
3
17
|
## 1.37.0
|
|
4
18
|
|
|
5
19
|
### Minor Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fibery/ui-kit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.38.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"dependencies": {
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
"@radix-ui/react-dropdown-menu": "2.1.1",
|
|
13
13
|
"@radix-ui/react-navigation-menu": "1.2.1",
|
|
14
14
|
"@radix-ui/react-toast": "1.2.2",
|
|
15
|
+
"@radix-ui/react-toggle": "1.1.10",
|
|
16
|
+
"@radix-ui/react-toggle-group": "1.1.11",
|
|
15
17
|
"@radix-ui/react-tooltip": "1.1.3",
|
|
16
18
|
"@types/d3-shape": "^3.1.6",
|
|
17
19
|
"@types/react-select-country-list": "^2.2.3",
|
|
@@ -36,6 +38,7 @@
|
|
|
36
38
|
"react-color": "2.19.3",
|
|
37
39
|
"react-day-picker": "8.1.4",
|
|
38
40
|
"react-intersection-observer": "9.3.5",
|
|
41
|
+
"react-medium-image-zoom": "5.2.10",
|
|
39
42
|
"react-popper": "2.3.0",
|
|
40
43
|
"react-select": "5.3.2",
|
|
41
44
|
"react-select-country-list": "2.2.1",
|
|
@@ -43,7 +46,7 @@
|
|
|
43
46
|
"screenfull": "6.0.1",
|
|
44
47
|
"tabbable": "5.2.1",
|
|
45
48
|
"ua-parser-js": "1.0.39",
|
|
46
|
-
"@fibery/emoji-data": "2.
|
|
49
|
+
"@fibery/emoji-data": "2.7.0",
|
|
47
50
|
"@fibery/helpers": "1.3.3",
|
|
48
51
|
"@fibery/react": "1.4.4"
|
|
49
52
|
},
|
|
@@ -54,7 +57,6 @@
|
|
|
54
57
|
"devDependencies": {
|
|
55
58
|
"@babel/core": "7.23.9",
|
|
56
59
|
"@babel/runtime": "7.23.9",
|
|
57
|
-
"@wyw-in-js/babel-preset": "0.5.5",
|
|
58
60
|
"@testing-library/dom": "8.19.1",
|
|
59
61
|
"@testing-library/jest-dom": "5.16.5",
|
|
60
62
|
"@testing-library/react": "13.4.0",
|
|
@@ -68,6 +70,7 @@
|
|
|
68
70
|
"@types/prop-types": "15.7.5",
|
|
69
71
|
"@types/react": "18.0.26",
|
|
70
72
|
"@types/react-dom": "18.0.10",
|
|
73
|
+
"@wyw-in-js/babel-preset": "0.5.5",
|
|
71
74
|
"csstype": "3.0.8",
|
|
72
75
|
"fs-extra": "10.0.0",
|
|
73
76
|
"glob": "7.1.7",
|
|
@@ -79,8 +82,8 @@
|
|
|
79
82
|
"svgo": "2.8.0",
|
|
80
83
|
"typescript": "5.8.3",
|
|
81
84
|
"unist-util-reduce": "0.2.2",
|
|
82
|
-
"@fibery/
|
|
83
|
-
"@fibery/
|
|
85
|
+
"@fibery/eslint-config": "8.6.1",
|
|
86
|
+
"@fibery/babel-preset": "7.4.0"
|
|
84
87
|
},
|
|
85
88
|
"jest": {
|
|
86
89
|
"testEnvironment": "jsdom",
|
|
@@ -2,12 +2,14 @@ import {stopPropagation} from "@fibery/react/src/stop-propagation";
|
|
|
2
2
|
import {useCallbackRef} from "@fibery/react/src/use-callback-ref";
|
|
3
3
|
import {css, cx} from "@linaria/core";
|
|
4
4
|
import {FunctionComponent, memo, ReactNode, useId} from "react";
|
|
5
|
-
import {border, colors, layout, lineHeight, space, textStyles, themeVars} from "../design-system";
|
|
5
|
+
import {border, colors, layout, layoutVars, lineHeight, space, textStyles, themeVars} from "../design-system";
|
|
6
6
|
import CheckedIcon from "../icons/react/Checked";
|
|
7
7
|
import {IconBaseProps} from "../icons/types";
|
|
8
8
|
import {Spinner} from "../loaders";
|
|
9
|
+
import {mobileRootSelector} from "../mobile-styles";
|
|
9
10
|
import {ShortcutBadge} from "../shortcut-badge";
|
|
10
11
|
import {useTheme} from "../theme-provider";
|
|
12
|
+
import {useIsPhone} from "../use-is-phone";
|
|
11
13
|
import {useActionsMenuContext} from "./contexts/actions-menu-context";
|
|
12
14
|
import {useActiveDangerousRow, useSetActiveDangerousRow} from "./contexts/actions-menu-dangerous-rows";
|
|
13
15
|
|
|
@@ -31,8 +33,11 @@ const descriptionCss = css`
|
|
|
31
33
|
const rowCss = css`
|
|
32
34
|
display: flex;
|
|
33
35
|
align-items: center;
|
|
34
|
-
min-height: ${
|
|
36
|
+
min-height: ${layoutVars.menuItemHeight};
|
|
35
37
|
gap: ${space.s6}px;
|
|
38
|
+
${mobileRootSelector} & {
|
|
39
|
+
gap: ${space.s8}px;
|
|
40
|
+
}
|
|
36
41
|
`;
|
|
37
42
|
|
|
38
43
|
const dangerousItemCss = css`
|
|
@@ -87,20 +92,25 @@ const firstLetterToLowerCase = (str: string) => {
|
|
|
87
92
|
|
|
88
93
|
const RightCorner = ({shortcut, loading, checked}: {shortcut?: string; loading?: boolean; checked?: boolean}) => {
|
|
89
94
|
const theme = useTheme();
|
|
95
|
+
const isPhone = useIsPhone();
|
|
90
96
|
|
|
91
97
|
return loading || shortcut || checked ? (
|
|
92
98
|
<div className={cornerCss}>
|
|
93
99
|
{loading ? <Spinner color={theme.primary} iconSize={16} containerSize={16} /> : null}
|
|
94
100
|
{shortcut ? <ShortcutBadge shortcut={shortcut} /> : null}
|
|
95
|
-
{checked ? <CheckedIcon iconSize={18} color={themeVars.textColor} /> : null}
|
|
101
|
+
{checked ? <CheckedIcon iconSize={isPhone ? 20 : 18} color={themeVars.textColor} /> : null}
|
|
96
102
|
</div>
|
|
97
103
|
) : null;
|
|
98
104
|
};
|
|
99
105
|
|
|
100
|
-
const LeftCorner = ({Icon}: {Icon: FunctionComponent<IconBaseProps> | void}) => {
|
|
106
|
+
const LeftCorner = ({Icon, iconColor}: {Icon: FunctionComponent<IconBaseProps> | void; iconColor?: string}) => {
|
|
107
|
+
const isPhone = useIsPhone();
|
|
101
108
|
return Icon ? (
|
|
102
109
|
<div className={cornerCss}>
|
|
103
|
-
<Icon
|
|
110
|
+
<Icon
|
|
111
|
+
color={`var(--actions-menu-item-icon-color, ${iconColor ?? themeVars.iconColor})`}
|
|
112
|
+
iconSize={isPhone ? 20 : 18}
|
|
113
|
+
/>
|
|
104
114
|
</div>
|
|
105
115
|
) : null;
|
|
106
116
|
};
|
|
@@ -115,6 +125,7 @@ export type ActionsMenuItemProps = {
|
|
|
115
125
|
description?: string;
|
|
116
126
|
/** Icon's component */
|
|
117
127
|
Icon?: FunctionComponent<IconBaseProps>;
|
|
128
|
+
iconColor?: string;
|
|
118
129
|
/** Hint for keyboard shortcut for this action */
|
|
119
130
|
shortcut?: string;
|
|
120
131
|
disabled?: boolean;
|
|
@@ -135,6 +146,7 @@ const ActionsMenuItemComponent: React.FC<
|
|
|
135
146
|
onSelect,
|
|
136
147
|
description,
|
|
137
148
|
Icon,
|
|
149
|
+
iconColor,
|
|
138
150
|
shortcut,
|
|
139
151
|
disabled,
|
|
140
152
|
dangerous,
|
|
@@ -180,7 +192,7 @@ const ActionsMenuItemComponent: React.FC<
|
|
|
180
192
|
)}
|
|
181
193
|
disabled={disabled}
|
|
182
194
|
>
|
|
183
|
-
<LeftCorner Icon={Icon} />
|
|
195
|
+
<LeftCorner Icon={Icon} iconColor={iconColor} />
|
|
184
196
|
<div className={rowContentCss}>
|
|
185
197
|
{dangerous && (
|
|
186
198
|
<div className={cx(hiddenTextCss, showWarning && visibleTextCss)}>
|
|
@@ -22,6 +22,10 @@ export type ActionsMenuProps = {
|
|
|
22
22
|
sideOffset?: number;
|
|
23
23
|
collisionPadding?: number;
|
|
24
24
|
autoFocusOnClose?: boolean;
|
|
25
|
+
/** Show menu in a modal on mobile */
|
|
26
|
+
supportsMobile?: boolean;
|
|
27
|
+
mobileTitle?: string;
|
|
28
|
+
height?: string;
|
|
25
29
|
onEscapeKeyDown?: (event: KeyboardEvent) => void;
|
|
26
30
|
sticky?: DropdownMenuContentProps["sticky"];
|
|
27
31
|
};
|
|
@@ -16,6 +16,7 @@ import {ActionsMenuSubMenu} from "./actions-menu-sub-menu";
|
|
|
16
16
|
import {useActionsMenuContext} from "./contexts/actions-menu-context";
|
|
17
17
|
// eslint-disable-next-line no-restricted-imports
|
|
18
18
|
import {IconBaseProps} from "@fibery/ui-kit/src/icons/types";
|
|
19
|
+
import {useIsPhone} from "../use-is-phone";
|
|
19
20
|
|
|
20
21
|
const [ActionsMenuSubCommandMenuProvider, useActionsMenuSubCommandMenuCtx] = createContext<{
|
|
21
22
|
subMenuOpenRef: RefObject<boolean>;
|
|
@@ -113,18 +114,20 @@ export const ActionsMenuSubCommandMenuRoot: React.FC<React.ComponentPropsWithout
|
|
|
113
114
|
|
|
114
115
|
type ActionsMenuSubCommandMenuInputProps = React.ComponentPropsWithoutRef<typeof CommandMenuInput>;
|
|
115
116
|
export const ActionsMenuSubCommandMenuInput: React.FC<ActionsMenuSubCommandMenuInputProps> = ({
|
|
116
|
-
autoFocus
|
|
117
|
+
autoFocus,
|
|
117
118
|
onKeyDown,
|
|
118
119
|
...otherProps
|
|
119
120
|
}) => {
|
|
121
|
+
const isPhone = useIsPhone();
|
|
120
122
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
123
|
+
const shouldFocus = autoFocus ?? (isPhone ? false : true);
|
|
121
124
|
|
|
122
125
|
useEffect(() => {
|
|
123
126
|
// html autofocus doesn't work reliably in Context Menu
|
|
124
|
-
if (
|
|
127
|
+
if (shouldFocus) {
|
|
125
128
|
setTimeout(() => inputRef.current?.focus(), 0);
|
|
126
129
|
}
|
|
127
|
-
}, [
|
|
130
|
+
}, [shouldFocus]);
|
|
128
131
|
|
|
129
132
|
return (
|
|
130
133
|
<CommandMenuInput
|
|
@@ -136,7 +139,7 @@ export const ActionsMenuSubCommandMenuInput: React.FC<ActionsMenuSubCommandMenuI
|
|
|
136
139
|
}
|
|
137
140
|
onKeyDown?.(e);
|
|
138
141
|
}}
|
|
139
|
-
autoFocus={
|
|
142
|
+
autoFocus={shouldFocus}
|
|
140
143
|
{...otherProps}
|
|
141
144
|
/>
|
|
142
145
|
);
|
|
@@ -6,6 +6,7 @@ import ArrowRight from "../icons/react/ArrowRight";
|
|
|
6
6
|
import {useActionsMenuContext} from "./contexts/actions-menu-context";
|
|
7
7
|
// eslint-disable-next-line no-restricted-imports
|
|
8
8
|
import {IconBaseProps} from "@fibery/ui-kit/src/icons/types";
|
|
9
|
+
import {useIsPhone} from "../use-is-phone";
|
|
9
10
|
|
|
10
11
|
const subTriggerClass = css`
|
|
11
12
|
display: flex;
|
|
@@ -24,6 +25,7 @@ type Props = React.PropsWithChildren<{
|
|
|
24
25
|
open?: boolean;
|
|
25
26
|
onOpenChange?: (v: boolean) => void;
|
|
26
27
|
disabled?: boolean;
|
|
28
|
+
mobileTitle?: string;
|
|
27
29
|
contentClassName?: string;
|
|
28
30
|
container?: HTMLElement | null;
|
|
29
31
|
Icon?: FunctionComponent<IconBaseProps>;
|
|
@@ -37,9 +39,11 @@ const cornerCss = css`
|
|
|
37
39
|
`;
|
|
38
40
|
|
|
39
41
|
const LeftCorner = ({Icon}: {Icon: FunctionComponent<IconBaseProps> | void}) => {
|
|
42
|
+
const isPhone = useIsPhone();
|
|
43
|
+
|
|
40
44
|
return Icon ? (
|
|
41
45
|
<div className={cornerCss}>
|
|
42
|
-
<Icon color={`var(--actions-menu-item-icon-color, ${themeVars.iconColor})`} iconSize={18} />
|
|
46
|
+
<Icon color={`var(--actions-menu-item-icon-color, ${themeVars.iconColor})`} iconSize={isPhone ? 20 : 18} />
|
|
43
47
|
</div>
|
|
44
48
|
) : null;
|
|
45
49
|
};
|
|
@@ -55,14 +59,16 @@ export const ActionsMenuSubMenu: React.FC<Props> = ({
|
|
|
55
59
|
triggerRef,
|
|
56
60
|
children,
|
|
57
61
|
disabled = false,
|
|
62
|
+
mobileTitle = trigger,
|
|
58
63
|
contentClassName,
|
|
59
64
|
Icon,
|
|
60
65
|
onMouseEnter,
|
|
61
66
|
}) => {
|
|
67
|
+
const isPhone = useIsPhone();
|
|
62
68
|
const {MenuPrimitive, container} = useActionsMenuContext();
|
|
63
69
|
|
|
64
70
|
return (
|
|
65
|
-
<MenuPrimitive.Sub open={open} onOpenChange={onOpenChange}>
|
|
71
|
+
<MenuPrimitive.Sub title={mobileTitle} open={open} onOpenChange={onOpenChange}>
|
|
66
72
|
<MenuPrimitive.SubTrigger
|
|
67
73
|
ref={triggerRef}
|
|
68
74
|
className={subTriggerClass}
|
|
@@ -75,7 +81,7 @@ export const ActionsMenuSubMenu: React.FC<Props> = ({
|
|
|
75
81
|
<div className={arrowClass}>
|
|
76
82
|
<ArrowRight
|
|
77
83
|
color={disabled ? themeVars.disabledTextColor : themeVars.iconColor}
|
|
78
|
-
containerSize={10}
|
|
84
|
+
containerSize={isPhone ? 20 : 10}
|
|
79
85
|
aria-hidden
|
|
80
86
|
/>
|
|
81
87
|
</div>
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import {useControllableState} from "@fibery/react/src/use-controllable-state";
|
|
2
2
|
import {css, cx} from "@linaria/core";
|
|
3
|
+
import {useIsPhone} from "../use-is-phone";
|
|
3
4
|
import * as DropdownMenu from "../dropdown-menu";
|
|
5
|
+
import * as ModalMenu from "../modal-menu";
|
|
4
6
|
import {ActionsMenuContextProvider} from "./contexts/actions-menu-context";
|
|
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";
|
|
8
10
|
import {useState} from "react";
|
|
11
|
+
import {useFeatures} from "../features";
|
|
9
12
|
import {ActionsMenuConfirmation, ActionsMenuConfirmationProps} from "./actions-menu-confirmation";
|
|
10
13
|
import {useActionsMenuOpenStateTracker} from "./actions-menu-open-state-tracker";
|
|
11
14
|
|
|
@@ -36,8 +39,12 @@ export const ActionsMenu = ({
|
|
|
36
39
|
contentStyles,
|
|
37
40
|
modal,
|
|
38
41
|
autoFocusOnClose,
|
|
42
|
+
supportsMobile,
|
|
43
|
+
mobileTitle,
|
|
39
44
|
sticky,
|
|
45
|
+
height,
|
|
40
46
|
}: ActionsMenuProps): JSX.Element => {
|
|
47
|
+
const features = useFeatures<{enableMobileMenus: boolean}>();
|
|
41
48
|
const {onMenuOpenChange} = useActionsMenuOpenStateTracker();
|
|
42
49
|
const [isOpen = false, setOpen] = useControllableState({
|
|
43
50
|
value: open,
|
|
@@ -48,26 +55,35 @@ export const ActionsMenu = ({
|
|
|
48
55
|
onMenuOpenChange(value);
|
|
49
56
|
},
|
|
50
57
|
});
|
|
58
|
+
const isPhone = useIsPhone();
|
|
51
59
|
const [confirmation, setConfirmation] = useState<ActionsMenuConfirmationProps | null>(null);
|
|
52
60
|
|
|
61
|
+
const MenuPrimitive = isPhone && features.enableMobileMenus && supportsMobile ? ModalMenu : DropdownMenu;
|
|
62
|
+
|
|
53
63
|
return (
|
|
54
64
|
<ActionsMenuContextProvider
|
|
55
65
|
setOpen={setOpen}
|
|
56
66
|
showConfirmation={setConfirmation}
|
|
57
|
-
MenuPrimitive={
|
|
67
|
+
MenuPrimitive={MenuPrimitive}
|
|
58
68
|
container={container}
|
|
59
69
|
>
|
|
60
|
-
<
|
|
61
|
-
|
|
70
|
+
<MenuPrimitive.Root
|
|
71
|
+
open={isOpen}
|
|
72
|
+
height={height}
|
|
73
|
+
onOpenChange={setOpen}
|
|
74
|
+
modal={modal || false}
|
|
75
|
+
title={mobileTitle}
|
|
76
|
+
>
|
|
77
|
+
<MenuPrimitive.Trigger
|
|
62
78
|
// backward compatibility for dropdown styles
|
|
63
|
-
className={isOpen ? "actions-visible" : "actions-hidden"}
|
|
79
|
+
className={isOpen ? "actions-visible" : "actions-hidden actions-visible-on-mobile"}
|
|
64
80
|
onClick={preventDefaultAndStopPropagation}
|
|
65
81
|
disabled={disabled}
|
|
66
82
|
asChild
|
|
67
83
|
>
|
|
68
84
|
{trigger}
|
|
69
|
-
</
|
|
70
|
-
<
|
|
85
|
+
</MenuPrimitive.Trigger>
|
|
86
|
+
<MenuPrimitive.Content
|
|
71
87
|
align={align}
|
|
72
88
|
sticky={sticky}
|
|
73
89
|
alignOffset={alignOffset}
|
|
@@ -81,8 +97,8 @@ export const ActionsMenu = ({
|
|
|
81
97
|
onCloseAutoFocus={autoFocusOnClose ? undefined : preventDefault}
|
|
82
98
|
>
|
|
83
99
|
<ActionsMenuDangerousRowsProvider open={isOpen}>{children}</ActionsMenuDangerousRowsProvider>
|
|
84
|
-
</
|
|
85
|
-
</
|
|
100
|
+
</MenuPrimitive.Content>
|
|
101
|
+
</MenuPrimitive.Root>
|
|
86
102
|
|
|
87
103
|
{confirmation ? <ActionsMenuConfirmation {...confirmation} /> : null}
|
|
88
104
|
</ActionsMenuContextProvider>
|
package/src/actions-panel.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {Children, forwardRef, ReactElement, ReactNode} from "react";
|
|
2
2
|
import {css} from "@linaria/core";
|
|
3
3
|
import {space} from "./design-system";
|
|
4
|
+
import {useIsPhone} from "./use-is-phone";
|
|
4
5
|
|
|
5
6
|
const gridStyle = css`
|
|
6
7
|
align-items: center;
|
|
@@ -12,10 +13,19 @@ type Props = {
|
|
|
12
13
|
inline?: boolean;
|
|
13
14
|
gap?: number;
|
|
14
15
|
};
|
|
16
|
+
|
|
17
|
+
const getGap = (gap: number | undefined, isPhone: boolean) => {
|
|
18
|
+
if (gap !== undefined) {
|
|
19
|
+
return gap;
|
|
20
|
+
}
|
|
21
|
+
return isPhone ? 0 : space.s4;
|
|
22
|
+
};
|
|
23
|
+
|
|
15
24
|
export const ActionsPanel = forwardRef<HTMLDivElement, Props>(function ActionsPanelComponent(
|
|
16
|
-
{children, inline, gap
|
|
25
|
+
{children, inline, gap},
|
|
17
26
|
ref
|
|
18
27
|
) {
|
|
28
|
+
const isPhone = useIsPhone();
|
|
19
29
|
const childrenArray = Children.toArray(children);
|
|
20
30
|
if (childrenArray.length === 0) {
|
|
21
31
|
return null;
|
|
@@ -27,7 +37,7 @@ export const ActionsPanel = forwardRef<HTMLDivElement, Props>(function ActionsPa
|
|
|
27
37
|
className={gridStyle}
|
|
28
38
|
style={{
|
|
29
39
|
display: inline ? "inline-grid" : "grid",
|
|
30
|
-
gridGap: gap,
|
|
40
|
+
gridGap: getGap(gap, isPhone),
|
|
31
41
|
gridAutoFlow: "column",
|
|
32
42
|
}}
|
|
33
43
|
>
|
package/src/axis-header.tsx
CHANGED
|
@@ -1,24 +1,8 @@
|
|
|
1
1
|
import {css} from "@linaria/core";
|
|
2
|
-
import {
|
|
3
|
-
import cn from "classnames";
|
|
2
|
+
import {default as cn, default as cx} from "classnames";
|
|
4
3
|
import {FC, ReactNode} from "react";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
const axisItemStyle = css`
|
|
9
|
-
${{
|
|
10
|
-
display: "grid",
|
|
11
|
-
gridGap: space.s6,
|
|
12
|
-
minHeight: layout.itemHeight,
|
|
13
|
-
alignItems: "center",
|
|
14
|
-
paddingLeft: space.s8,
|
|
15
|
-
paddingRight: space.s8,
|
|
16
|
-
borderRadius: border.radius6,
|
|
17
|
-
width: "100%",
|
|
18
|
-
...textStyles.heading5,
|
|
19
|
-
}}
|
|
20
|
-
`;
|
|
21
|
-
|
|
4
|
+
import {CountBadge} from "./count-badge";
|
|
5
|
+
import {border, opacity, space, textStyles, themeVars} from "./design-system";
|
|
22
6
|
const axisItemStyleX = css`
|
|
23
7
|
grid-template-columns: auto 1fr auto;
|
|
24
8
|
`;
|
|
@@ -31,11 +15,23 @@ const axisItemHighlightedStyle = css`
|
|
|
31
15
|
|
|
32
16
|
const dimensionToItemStyle = {x: axisItemStyleX, y: axisItemStyleY};
|
|
33
17
|
|
|
18
|
+
const wrapperStyle = css`
|
|
19
|
+
${textStyles.regular};
|
|
20
|
+
display: grid;
|
|
21
|
+
width: 100%;
|
|
22
|
+
grid-template-columns: 1fr auto;
|
|
23
|
+
gap: ${space.s6}px;
|
|
24
|
+
padding: ${space.s6}px;
|
|
25
|
+
`;
|
|
26
|
+
|
|
34
27
|
const axisItemStyleCollapsed = css`
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
28
|
+
writing-mode: vertical-rl;
|
|
29
|
+
display: flex;
|
|
30
|
+
position: sticky;
|
|
31
|
+
top: 0;
|
|
32
|
+
&.${wrapperStyle} {
|
|
33
|
+
padding-block: 0;
|
|
34
|
+
}
|
|
39
35
|
`;
|
|
40
36
|
|
|
41
37
|
function getAdditionalClassName({
|
|
@@ -56,33 +52,61 @@ function getAdditionalClassName({
|
|
|
56
52
|
return dimensionToItemStyle[dimension];
|
|
57
53
|
}
|
|
58
54
|
|
|
59
|
-
const mainContainerWrapperStyle =
|
|
60
|
-
overflow:
|
|
61
|
-
|
|
62
|
-
cursor:
|
|
63
|
-
|
|
64
|
-
opacity: 1
|
|
65
|
-
};
|
|
66
|
-
const mainContainerWrapperClassName = css`
|
|
67
|
-
${mainContainerWrapperStyle}
|
|
55
|
+
const mainContainerWrapperStyle = css`
|
|
56
|
+
overflow: hidden;
|
|
57
|
+
white-space: nowrap;
|
|
58
|
+
cursor: pointer;
|
|
59
|
+
text-overflow: ellipsis;
|
|
60
|
+
opacity: 1;
|
|
68
61
|
`;
|
|
69
62
|
|
|
70
|
-
const mainContainerWrapperCollapsedClassName =
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
63
|
+
const mainContainerWrapperCollapsedClassName = cx(
|
|
64
|
+
mainContainerWrapperStyle,
|
|
65
|
+
css`
|
|
66
|
+
opacity: ${opacity.opacity40};
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
justify-content: flex-start;
|
|
70
|
+
gap: ${space.s12}px;
|
|
71
|
+
`
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const collapsedTextStyle = css`
|
|
75
|
+
overflow: hidden;
|
|
76
|
+
white-space: nowrap;
|
|
77
|
+
text-overflow: ellipsis;
|
|
78
|
+
min-width: 0;
|
|
79
|
+
flex-shrink: 1;
|
|
76
80
|
`;
|
|
77
81
|
|
|
78
82
|
const leftContainerWrapperStyle = css`
|
|
79
83
|
cursor: pointer;
|
|
80
84
|
`;
|
|
81
85
|
|
|
82
|
-
const
|
|
86
|
+
export const leftMainContainerWrapperStyle = css``;
|
|
87
|
+
|
|
88
|
+
export const axisHeaderClassName = css`
|
|
89
|
+
cursor: pointer;
|
|
90
|
+
min-height: ${space.s36}px;
|
|
83
91
|
display: flex;
|
|
92
|
+
justify-content: center;
|
|
84
93
|
flex-direction: column;
|
|
85
|
-
|
|
94
|
+
border-radius: ${border.radius6}px;
|
|
95
|
+
.right-container {
|
|
96
|
+
opacity: 0;
|
|
97
|
+
}
|
|
98
|
+
background-color: var(--board-bg, ${themeVars.boardBg});
|
|
99
|
+
&:hover {
|
|
100
|
+
background-color: ${themeVars.boardAxisBgHover};
|
|
101
|
+
z-index: 20;
|
|
102
|
+
& .${leftMainContainerWrapperStyle} {
|
|
103
|
+
background-color: transparent;
|
|
104
|
+
}
|
|
105
|
+
.right-container {
|
|
106
|
+
visibility: visible;
|
|
107
|
+
opacity: 1;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
86
110
|
`;
|
|
87
111
|
|
|
88
112
|
interface AxisHeaderProps {
|
|
@@ -90,12 +114,12 @@ interface AxisHeaderProps {
|
|
|
90
114
|
dimension: "x" | "y";
|
|
91
115
|
collapsed?: boolean;
|
|
92
116
|
highlighted?: boolean;
|
|
93
|
-
showLeftContainerWhenCollapsed?: boolean;
|
|
94
117
|
bottomContainer?: ReactNode;
|
|
95
118
|
leftContainer?: ReactNode;
|
|
96
119
|
rightContainer?: ReactNode;
|
|
97
120
|
children: ReactNode;
|
|
98
121
|
onCollapse?: () => void;
|
|
122
|
+
count?: number;
|
|
99
123
|
}
|
|
100
124
|
|
|
101
125
|
export const AxisHeader: FC<AxisHeaderProps> = ({
|
|
@@ -107,54 +131,90 @@ export const AxisHeader: FC<AxisHeaderProps> = ({
|
|
|
107
131
|
bottomContainer,
|
|
108
132
|
collapsed,
|
|
109
133
|
highlighted,
|
|
110
|
-
showLeftContainerWhenCollapsed,
|
|
111
134
|
onCollapse,
|
|
135
|
+
count,
|
|
112
136
|
}) => {
|
|
113
|
-
const
|
|
114
|
-
const backgroundColor = getThemeValue(theme.mode, {
|
|
115
|
-
dark: themeVars.panelContentBg,
|
|
116
|
-
light: themeVars.panelContentBg,
|
|
117
|
-
});
|
|
137
|
+
const leftContainerWrapper = <div className={leftContainerWrapperStyle}>{leftContainer}</div>;
|
|
118
138
|
|
|
119
|
-
const
|
|
120
|
-
<div
|
|
121
|
-
{
|
|
139
|
+
const rightContainerWrapper = (
|
|
140
|
+
<div
|
|
141
|
+
className={cn(
|
|
142
|
+
"right-container",
|
|
143
|
+
css`
|
|
144
|
+
display: flex;
|
|
145
|
+
align-items: center;
|
|
146
|
+
`
|
|
147
|
+
)}
|
|
148
|
+
>
|
|
149
|
+
{rightContainer}
|
|
122
150
|
</div>
|
|
123
151
|
);
|
|
124
152
|
|
|
125
|
-
const rightContainerWrapper = <div>{rightContainer}</div>;
|
|
126
|
-
|
|
127
153
|
const mainContainerWrapper = (
|
|
128
|
-
<div
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
154
|
+
<div className={collapsed ? mainContainerWrapperCollapsedClassName : mainContainerWrapperStyle}>
|
|
155
|
+
{collapsed ? <div className={collapsedTextStyle}>{children}</div> : children}
|
|
156
|
+
{count !== undefined && collapsed && (
|
|
157
|
+
<CountBadge
|
|
158
|
+
count={count}
|
|
159
|
+
className={css`
|
|
160
|
+
writing-mode: horizontal-tb;
|
|
161
|
+
`}
|
|
162
|
+
/>
|
|
163
|
+
)}
|
|
133
164
|
</div>
|
|
134
165
|
);
|
|
135
166
|
return (
|
|
136
|
-
<
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
167
|
+
<div
|
|
168
|
+
data-testid={`axis-header-${dimension}`}
|
|
169
|
+
onClick={onCollapse}
|
|
170
|
+
className={cn(
|
|
171
|
+
className,
|
|
172
|
+
axisHeaderClassName,
|
|
173
|
+
dimension === "y" &&
|
|
174
|
+
css`
|
|
175
|
+
position: sticky;
|
|
176
|
+
left: 0;
|
|
177
|
+
display: inline-flex;
|
|
178
|
+
z-index: 3;
|
|
179
|
+
background-color: transparent;
|
|
180
|
+
`,
|
|
181
|
+
dimension === "y" &&
|
|
182
|
+
highlighted &&
|
|
183
|
+
css`
|
|
184
|
+
display: flex;
|
|
185
|
+
width: 100%;
|
|
186
|
+
`,
|
|
187
|
+
collapsed &&
|
|
188
|
+
dimension === "x" &&
|
|
189
|
+
css`
|
|
190
|
+
position: sticky;
|
|
191
|
+
top: 0;
|
|
192
|
+
z-index: 2;
|
|
193
|
+
background-color: transparent;
|
|
194
|
+
`
|
|
195
|
+
)}
|
|
196
|
+
>
|
|
197
|
+
<div className={cn(wrapperStyle, getAdditionalClassName({dimension, highlighted, collapsed}))}>
|
|
198
|
+
<>
|
|
199
|
+
<div
|
|
200
|
+
className={cn(
|
|
201
|
+
leftMainContainerWrapperStyle,
|
|
202
|
+
css`
|
|
203
|
+
display: grid;
|
|
204
|
+
grid-template-columns: auto 1fr;
|
|
205
|
+
gap: ${space.s8}px;
|
|
206
|
+
padding-inline: ${space.s4}px;
|
|
207
|
+
align-items: center;
|
|
208
|
+
`
|
|
209
|
+
)}
|
|
210
|
+
>
|
|
151
211
|
{leftContainerWrapper}
|
|
152
212
|
{mainContainerWrapper}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
213
|
+
</div>
|
|
214
|
+
{rightContainerWrapper}
|
|
215
|
+
</>
|
|
156
216
|
</div>
|
|
157
217
|
{bottomContainer}
|
|
158
|
-
</
|
|
218
|
+
</div>
|
|
159
219
|
);
|
|
160
220
|
};
|
package/src/box.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import {styled} from "@linaria/react";
|
|
|
3
3
|
import cx from "classnames";
|
|
4
4
|
import {CSSProperties, forwardRef, HTMLProps, ReactNode, Ref, useCallback, useMemo, useState} from "react";
|
|
5
5
|
import {border, getLinearGradient, getOpacities, space, textStyles, themeVars, transition} from "./design-system";
|
|
6
|
-
import {useClickOutside} from "./
|
|
6
|
+
import {useClickOutside} from "./popover/use-click-outside";
|
|
7
7
|
|
|
8
8
|
export const getBg = (backgroundColors: string[]) => {
|
|
9
9
|
if (backgroundColors) {
|