refactor(design): refactor Dialog & Confirm (#5048)

Co-authored-by: GitHub Actions <actions@github.com>
This commit is contained in:
白熱
2025-04-20 01:18:25 +08:00
committed by GitHub
co-authored by GitHub Actions
parent b59f35bf0b
commit ee65b104e6
106 changed files with 1349 additions and 1497 deletions
+4 -3
View File
@@ -25,7 +25,7 @@
},
"dependencies": {
"@typescript-eslint/parser": "^8.30.1",
"@vitejs/plugin-react": "^4.3.4",
"@vitejs/plugin-react": "^4.4.0",
"@vitejs/plugin-vue": "^5.2.3",
"@vitest/coverage-istanbul": "^3.1.1",
"autoprefixer": "^10.4.21",
@@ -37,9 +37,10 @@
"sort-keys": "^5.1.0",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss": "^3.4.17",
"vite": "^6.3.0",
"tailwindcss-rem-to-px": "^0.1.1",
"vite": "^6.3.2",
"vite-plugin-dts": "^4.5.3",
"vite-plugin-external": "^6.1.0",
"vite-plugin-external": "^6.2.1",
"vitest": "^3.1.1"
},
"devDependencies": {
@@ -16,6 +16,7 @@
import type { Config } from 'tailwindcss';
import scrollbar from 'tailwind-scrollbar';
import remToPx from 'tailwindcss-rem-to-px';
const config: Omit<Config, 'content'> = {
prefix: 'univer-',
@@ -159,10 +160,18 @@ const config: Omit<Config, 'content'> = {
900: '#751A3D',
},
},
boxShadow: {
sm: '0px 1px 2px 0px rgba(30, 40, 77, 0.08)',
md: '0px 1px 6px -2px rgba(30, 40, 77, 0.08), 0px 2px 6px -1px rgba(30, 40, 77, 0.10)',
lg: '0px 4px 6px 0px rgba(30, 40, 77, 0.05), 0px 10px 15px -3px rgba(30, 40, 77, 0.10)',
xl: '0px 10px 10px 0px rgba(30, 40, 77, 0.04), 0px 20px 24px -5px rgba(30, 40, 77, 0.10)',
'2xl': '0px 24px 50px -12px rgba(30, 40, 77, 0.24)',
},
},
},
plugins: [
scrollbar,
remToPx,
],
};
Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 70 KiB

+5 -1
View File
@@ -138,7 +138,11 @@ function createNewInstance() {
// If we are running in e2e platform, we should immediately register the debugger plugin.
if (IS_E2E) {
univer.registerPlugin(UniverDebuggerPlugin);
univer.registerPlugin(UniverDebuggerPlugin, {
performanceMonitor: {
enabled: false,
},
});
}
const injector = univer.__getInjector();
+7 -7
View File
@@ -49,19 +49,19 @@
"@antfu/eslint-config": "4.12.0",
"@commitlint/cli": "^19.8.0",
"@commitlint/config-conventional": "^19.8.0",
"@eslint-react/eslint-plugin": "^1.47.3",
"@playwright/test": "^1.51.1",
"@eslint-react/eslint-plugin": "^1.48.4",
"@playwright/test": "^1.52.0",
"@release-it-plugins/workspaces": "^4.2.0",
"@release-it/conventional-changelog": "^9.0.4",
"@storybook/react": "8.6.12",
"@types/fs-extra": "^11.0.4",
"@types/node": "^22.14.0",
"@types/react": "^19.1.0",
"@types/node": "^22.14.1",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2",
"@univerjs-infra/shared": "workspace:*",
"@univerjs/design": "workspace:*",
"@vitejs/plugin-react": "^4.3.4",
"eslint": "9.24.0",
"@vitejs/plugin-react": "^4.4.0",
"eslint": "9.25.0",
"eslint-plugin-format": "^1.0.1",
"eslint-plugin-header": "^3.1.1",
"eslint-plugin-jsdoc": "^50.6.9",
@@ -73,7 +73,7 @@
"fs-extra": "^11.3.0",
"husky": "^9.1.7",
"lint-staged": "^15.5.1",
"posthog-node": "^4.11.5",
"posthog-node": "^4.12.0",
"react": "19.1.0",
"react-dom": "19.1.0",
"release-it": "^17.11.0",
@@ -81,7 +81,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -85,7 +85,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1",
"vue": "^3.5.13"
}
@@ -14,9 +14,9 @@
* limitations under the License.
*/
import type { IAccessor, ICommand } from '@univerjs/core';
import { CommandType } from '@univerjs/core';
import { IConfirmService } from '@univerjs/ui';
import type { IAccessor, ICommand } from '@univerjs/core';
export interface IUIComponentCommandParams {
value: string;
@@ -14,9 +14,9 @@
* limitations under the License.
*/
import type { IAccessor, ICommand } from '@univerjs/core';
import { CommandType } from '@univerjs/core';
import { IDialogService } from '@univerjs/ui';
import type { IAccessor, ICommand } from '@univerjs/core';
export interface IUIComponentCommandParams {
value: string;
@@ -39,7 +39,12 @@ export const DialogOperation: ICommand = {
preservePositionOnDestroy: true,
width: 350,
onClose() {
dialogService.close('draggable');
// dialogService.close('draggable');
},
onOpenChange(open: boolean) {
if (!open) {
dialogService.close('draggable');
}
},
});
} else {
@@ -50,7 +55,12 @@ export const DialogOperation: ICommand = {
title: { title: 'Dialog Title' },
draggable: false,
onClose() {
dialogService.close('dialog1');
// dialogService.close('dialog1');
},
onOpenChange(open: boolean) {
if (!open) {
dialogService.close('dialog1');
}
},
});
}
@@ -22,6 +22,9 @@ export const configSymbol = Symbol(DEBUGGER_PLUGIN_CONFIG_KEY);
export interface IUniverDebuggerConfig {
menu?: MenuConfig;
performanceMonitor?: {
enabled: boolean;
};
}
export const defaultPluginConfig: IUniverDebuggerConfig = {};
+7 -3
View File
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import type { Dependency } from '@univerjs/core';
import type { IUniverDebuggerConfig } from './controllers/config.schema';
import { IConfigService, Inject, Injector, merge, Plugin, registerDependencies, touchDependencies } from '@univerjs/core';
import { DEBUGGER_PLUGIN_CONFIG_KEY, defaultPluginConfig } from './controllers/config.schema';
@@ -49,14 +50,17 @@ export class UniverDebuggerPlugin extends Plugin {
}
override onStarting(): void {
registerDependencies(this._injector, [
[PerformanceMonitorController],
const dependencies: Dependency[] = [
[DarkModeController],
[DebuggerController],
[MultiUnitsController],
[E2EController],
[UniverWatermarkMenuController],
]);
];
if (this._config.performanceMonitor?.enabled !== false) {
dependencies.push([PerformanceMonitorController]);
}
registerDependencies(this._injector, dependencies);
touchDependencies(this._injector, [
[E2EController],
@@ -77,7 +77,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -73,7 +73,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -86,7 +86,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -61,7 +61,7 @@
"devDependencies": {
"@univerjs-infra/shared": "workspace:*",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -78,7 +78,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -75,7 +75,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -80,7 +80,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -94,7 +94,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -70,7 +70,7 @@
"@univerjs/sheets": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+6 -7
View File
@@ -68,23 +68,22 @@
"react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
},
"dependencies": {
"@radix-ui/react-dropdown-menu": "^2.1.7",
"@radix-ui/react-popover": "^1.1.7",
"@radix-ui/react-separator": "^1.1.3",
"@radix-ui/react-dialog": "^1.1.10",
"@radix-ui/react-dropdown-menu": "^2.1.10",
"@radix-ui/react-popover": "^1.1.10",
"@radix-ui/react-separator": "^1.1.4",
"@radix-ui/react-slot": "^1.2.0",
"@radix-ui/react-tooltip": "^1.2.0",
"@radix-ui/react-tooltip": "^1.2.3",
"@rc-component/trigger": "^2.2.6",
"@univerjs/icons": "^0.3.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"dayjs": "^1.11.13",
"rc-dialog": "^9.6.0",
"rc-dropdown": "^4.2.1",
"rc-menu": "^9.16.0",
"rc-picker": "^4.9.0",
"rc-select": "^14.16.4",
"rc-virtual-list": "^3.16.1",
"react-draggable": "^4.4.6",
"react-grid-layout": "^1.5.1",
"react-transition-group": "^4.4.5",
"tailwind-merge": "^3.2.0"
@@ -102,7 +101,7 @@
"tailwindcss": "^3.4.17",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -89,3 +89,5 @@ export const Button = forwardRef<HTMLButtonElement, IButtonProps>(
);
}
);
Button.displayName = 'Button';
@@ -20,7 +20,6 @@ import React, { useContext } from 'react';
import { Button } from '../button/Button';
import { ConfigContext } from '../config-provider/ConfigProvider';
import { Dialog } from '../dialog/Dialog';
import styles from './index.module.less';
export interface IConfirmProps {
children: React.ReactNode;
@@ -67,7 +66,7 @@ function Footer(props: { locale: ILocale['design']; cancelText?: string; confirm
const { locale, cancelText, confirmText, onClose, onConfirm } = props;
return (
<footer className={styles.confirmFooter}>
<footer className="univer-flex univer-items-center univer-justify-end univer-gap-2">
<Button onClick={onClose}>{cancelText ?? locale?.Confirm.cancel}</Button>
<Button variant="primary" onClick={onConfirm}>
{confirmText ?? locale?.Confirm.confirm}
@@ -83,7 +82,7 @@ export function Confirm(props: IConfirmProps) {
return (
<Dialog
visible={visible}
open={visible}
title={title}
footer={(
<Footer
@@ -1,7 +0,0 @@
.confirm {
&-footer {
display: flex;
gap: var(--margin-sm);
justify-content: flex-end;
}
}
@@ -15,7 +15,6 @@
*/
import type { Meta } from '@storybook/react';
import { CloseSingle } from '@univerjs/icons';
import React, { useState } from 'react';
import { Button } from '../button/Button';
@@ -36,20 +35,15 @@ export const DialogBasic = {
render() {
const [visible, setVisible] = useState(false);
function handleToggleVisible() {
setVisible(!visible);
}
return (
<>
<Button onClick={handleToggleVisible}>open dialog</Button>
<Button onClick={() => setVisible(true)}>open dialog</Button>
<Dialog
visible={visible}
open={visible}
title="hello world"
closeIcon={<CloseSingle />}
showOk
showCancel
onClose={handleToggleVisible}
onOpenChange={setVisible}
>
xxxx
</Dialog>
@@ -62,22 +56,17 @@ export const DialogDraggable = {
render() {
const [visible, setVisible] = useState(false);
function handleToggleVisible() {
setVisible(!visible);
}
return (
<>
<Button onClick={handleToggleVisible}>open dialog</Button>
<Button onClick={() => setVisible(true)}>open dialog</Button>
<Dialog
visible={visible}
open={visible}
title="hello world"
closeIcon={<CloseSingle />}
draggable
destroyOnClose
preservePositionOnDestroy
defaultPosition={{ x: 100, y: 100 }}
onClose={handleToggleVisible}
onClose={() => setVisible(false)}
>
xxxx
</Dialog>
+231 -134
View File
@@ -14,30 +14,26 @@
* limitations under the License.
*/
import type { ModalStyles } from 'rc-dialog/lib/IDialogPropTypes';
import type { DraggableData, DraggableEvent, DraggableEventHandler } from 'react-draggable';
import { CloseSingle } from '@univerjs/icons';
import RcDialog from 'rc-dialog';
import React, { useContext, useRef, useState } from 'react';
import Draggable from 'react-draggable';
import type { CSSProperties, MouseEvent as ReactMouseEvent, ReactNode } from 'react';
import { useCallback, useContext, useEffect, useRef, useState } from 'react';
import { clsx } from '../../helper/clsx';
import { Button } from '../button';
import { ConfigContext } from '../config-provider/ConfigProvider';
import styles from './index.module.less';
import { DialogContent, DialogDescription, DialogFooter, DialogHeader, Dialog as DialogProvider, DialogTitle } from './DialogPrimitive';
export interface IDialogProps {
children: React.ReactNode;
children: ReactNode;
/**
* The style of the dialog.
*/
style?: React.CSSProperties;
style?: CSSProperties;
/**
* Whether the dialog is visible.
* @default false
*/
visible?: boolean;
open?: boolean;
/**
* The width of the dialog.
@@ -47,7 +43,7 @@ export interface IDialogProps {
/**
* The title of the dialog.
*/
title?: React.ReactNode;
title?: ReactNode;
/**
* Whether the dialog can be dragged. If a dialog is draggable, the backdrop would be hidden and
@@ -57,11 +53,6 @@ export interface IDialogProps {
*/
draggable?: boolean;
/**
* The close icon of the dialog.
*/
closeIcon?: React.ReactNode;
/**
* The default position of the dialog.
*/
@@ -82,12 +73,7 @@ export interface IDialogProps {
/**
* The footer of the dialog.
*/
footer?: React.ReactNode;
/**
* Callback when the dialog is closed.
*/
onClose?: () => void;
footer?: ReactNode;
/**
* Whether the dialog should show a mask.
@@ -99,11 +85,6 @@ export interface IDialogProps {
*/
className?: string;
/**
* The style of the customize.
*/
dialogStyles?: ModalStyles;
/**
* whether show close button
*/
@@ -120,6 +101,16 @@ export interface IDialogProps {
*/
keyboard?: boolean;
/**
* The callback function when the open state changes.
*/
onOpenChange?: (open: boolean) => void;
/**
* The callback function when the dialog is closed.
*/
onClose?: () => void;
showOk?: boolean;
showCancel?: boolean;
@@ -127,143 +118,249 @@ export interface IDialogProps {
onCancel?: () => void;
}
function useDraggable(
options: {
defaultPosition?: { x: number; y: number };
enabled?: boolean;
} = {}
) {
const getCenteredPosition = useCallback(() => {
const { innerWidth, innerHeight } = window;
const defaultWidth = 0;
const defaultHeight = 0;
return {
x: Math.max(0, (innerWidth - defaultWidth) / 2),
y: Math.max(0, (innerHeight - defaultHeight) / 2),
};
}, []);
const { defaultPosition = getCenteredPosition(), enabled = false } = options;
const [position, setPosition] = useState(defaultPosition);
const [isDragging, setIsDragging] = useState(false);
const elementRef = useRef<HTMLElement | null>(null);
const startPosRef = useRef({ x: 0, y: 0 });
const startClientRef = useRef({ x: 0, y: 0 });
const initializedRef = useRef(false);
useEffect(() => {
if (!elementRef.current || initializedRef.current || options.defaultPosition) return;
const { width, height } = elementRef.current.getBoundingClientRect();
const { innerWidth, innerHeight } = window;
const centeredX = Math.max(0, (innerWidth - width) / 2);
const centeredY = Math.max(0, (innerHeight - height) / 2);
setPosition({ x: centeredX, y: centeredY });
startPosRef.current = { x: centeredX, y: centeredY };
initializedRef.current = true;
}, [options.defaultPosition]);
const calculateBounds = useCallback((clientX: number, clientY: number) => {
if (!elementRef.current) return { x: clientX, y: clientY };
const rect = elementRef.current.getBoundingClientRect();
const { clientWidth, clientHeight } = document.documentElement;
let newX = startPosRef.current.x + (clientX - startClientRef.current.x);
let newY = startPosRef.current.y + (clientY - startClientRef.current.y);
if (newX < 0) newX = 0;
if (newY < 0) newY = 0;
if (newX + rect.width > clientWidth) newX = clientWidth - rect.width;
if (newY + rect.height > clientHeight) newY = clientHeight - rect.height;
return { x: newX, y: newY };
}, []);
const startDrag = useCallback((e: ReactMouseEvent<HTMLElement> | MouseEvent) => {
if (!enabled) return;
e.preventDefault();
e.stopPropagation();
startPosRef.current = { ...position };
startClientRef.current = { x: e.clientX, y: e.clientY };
setIsDragging(true);
document.body.style.userSelect = 'none';
}, [enabled, position]);
const onDrag = useCallback((e: MouseEvent) => {
if (!isDragging) return;
e.preventDefault();
e.stopPropagation();
const newPosition = calculateBounds(e.clientX, e.clientY);
setPosition(newPosition);
}, [isDragging, calculateBounds]);
const endDrag = useCallback(() => {
setIsDragging(false);
document.body.style.userSelect = '';
}, []);
useEffect(() => {
if (enabled) {
document.addEventListener('mousemove', onDrag);
document.addEventListener('mouseup', endDrag);
return () => {
document.removeEventListener('mousemove', onDrag);
document.removeEventListener('mouseup', endDrag);
};
}
}, [enabled, onDrag, endDrag]);
return {
position,
isDragging,
elementRef,
setElementRef: (el: HTMLElement | null) => {
elementRef.current = el;
if (el && !initializedRef.current && !options.defaultPosition) {
const { width, height } = el.getBoundingClientRect();
const { innerWidth, innerHeight } = window;
const centeredX = Math.max(0, (innerWidth - width) / 2);
const centeredY = Math.max(0, (innerHeight - height) / 2);
setPosition({ x: centeredX, y: centeredY });
startPosRef.current = { x: centeredX, y: centeredY };
initializedRef.current = true;
}
},
handleMouseDown: startDrag,
};
}
export function Dialog(props: IDialogProps) {
const {
className,
children,
style,
visible = false,
open = false,
title,
width,
draggable = false,
closeIcon = <CloseSingle />,
defaultPosition,
destroyOnClose = false,
preservePositionOnDestroy = false,
footer: propFooter,
onClose,
mask,
mask = true,
keyboard = true,
dialogStyles,
closable,
maskClosable,
closable = true,
maskClosable = true,
showOk,
showCancel,
onOpenChange,
onClose,
onOk,
onCancel,
} = props;
const { locale } = useContext(ConfigContext);
const [dragDisabled, setDragDisabled] = useState(false);
const [positionOffset, setPositionOffset] = useState<{ x: number; y: number } | null>(null);
const { mountContainer } = useContext(ConfigContext);
const TitleIfDraggable = draggable
? (
<div
className={styles.dialogTitleContent}
style={{
width: '100%',
cursor: 'pointer',
...dialogStyles?.header,
}}
onMouseOver={() => {
if (dragDisabled) {
setDragDisabled(false);
}
}}
onMouseOut={() => {
setDragDisabled(true);
}}
onFocus={() => {
// empty
}}
onBlur={() => {
// empty
}}
>
{title}
</div>
)
: (
<div className={styles.dialogTitleContent}>{title}</div>
);
const { position, isDragging, setElementRef, handleMouseDown } = useDraggable({ defaultPosition, enabled: draggable });
const footer = propFooter ?? (showCancel || showOk
const footer = propFooter ?? (showOk || showCancel
? (
<div>
<Button className="univer-mr-2" onClick={onCancel ?? onClose}>{locale?.Confirm?.cancel ?? 'Cancel'}</Button>
<Button variant="primary" onClick={onOk}>{locale?.Confirm?.confirm ?? 'Ok'}</Button>
<div className="univer-flex univer-justify-end univer-gap-2">
{showCancel && (
<Button onClick={onCancel}>
{locale?.Confirm?.cancel ?? 'Cancel'}
</Button>
)}
{showOk && (
<Button variant="primary" onClick={onOk}>
{locale?.Confirm?.confirm ?? 'OK'}
</Button>
)}
</div>
)
: null);
const modalRender = (modal: React.ReactNode) => {
const [bounds, setBounds] = useState({ left: 0, top: 0, bottom: 0, right: 0 });
const draggleRef = useRef<HTMLDivElement>(null!);
const handleContentRef = useCallback((node: HTMLDivElement | null) => {
if (node && draggable) {
setElementRef(node);
}
}, [draggable, setElementRef]);
function handleStop(_event: MouseEvent, data: DraggableData) {
if (preservePositionOnDestroy) {
setPositionOffset({ x: data.x, y: data.y });
}
const handleOpenChange = useCallback((isOpen: boolean) => {
if (!maskClosable && !isOpen) {
return;
}
const position = positionOffset || defaultPosition || { x: 0, y: 0 };
onOpenChange?.(isOpen);
const onStart = (_event: DraggableEvent, uiData: DraggableData) => {
const { clientWidth, clientHeight } = window.document.documentElement;
const targetRect = draggleRef.current?.getBoundingClientRect();
if (!targetRect) {
return;
}
if (!isOpen) {
onClose?.();
}
}, [onClose, onOpenChange]);
setBounds({
left: -targetRect.left + uiData.x,
right: clientWidth - (targetRect.right - uiData.x),
top: -targetRect.top + uiData.y,
bottom: clientHeight - (targetRect.bottom - uiData.y),
});
};
function handleClickClose() {
onOpenChange?.(false);
onClose?.();
}
return draggable
? (
<Draggable
disabled={dragDisabled}
defaultPosition={position}
bounds={bounds}
nodeRef={draggleRef}
onStart={(event, uiData) => onStart(event, uiData)}
onStop={handleStop as DraggableEventHandler}
>
<div ref={draggleRef}>{modal}</div>
</Draggable>
)
: modal;
};
const needMask = mask ?? !draggable;
return mountContainer && (
<RcDialog
className={className}
width={width}
prefixCls={styles.dialog}
rootClassName={!needMask ? styles.dialogRootDraggable : styles.dialogRoot}
getContainer={() => mountContainer}
visible={visible}
title={TitleIfDraggable}
modalRender={modalRender}
closeIcon={closeIcon}
destroyOnClose={destroyOnClose}
footer={footer}
mask={needMask}
style={style}
onClose={onClose}
styles={dialogStyles}
closable={closable}
maskClosable={maskClosable}
keyboard={keyboard}
return (
<DialogProvider
open={open}
onOpenChange={handleOpenChange}
modal={mask !== false}
>
{children}
</RcDialog>
<DialogContent
ref={handleContentRef}
className={clsx(className, {
'!univer-animate-none': draggable,
})}
style={{
...style,
width: width ? (typeof width === 'number' ? `${width}px` : width) : undefined,
...(draggable
? {
position: 'absolute',
margin: 0,
left: 0,
top: 0,
transform: `translate(${position.x}px, ${position.y}px)`,
transition: isDragging ? 'none' : undefined,
cursor: isDragging ? 'grabbing' : undefined,
}
: {}),
}}
closable={closable}
onClickClose={handleClickClose}
>
<DialogHeader
className={clsx({
'!univer-hidden': !title,
})}
data-drag-handle={draggable ? 'true' : undefined}
style={{
cursor: draggable ? 'grab' : undefined,
userSelect: draggable ? 'none' : undefined,
touchAction: draggable ? 'none' : undefined,
}}
onMouseDown={draggable ? handleMouseDown : undefined}
>
<DialogTitle>{title}</DialogTitle>
<DialogDescription className="univer-hidden" />
</DialogHeader>
{children}
{footer && (
<DialogFooter>
{footer}
</DialogFooter>
)}
</DialogContent>
</DialogProvider>
);
}
@@ -0,0 +1,177 @@
/**
* Copyright 2023-present DreamNum Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { ComponentPropsWithoutRef, ElementRef, HTMLAttributes } from 'react';
import { Close, Content, Description, Overlay, Portal, Root, Title, Trigger } from '@radix-ui/react-dialog';
import { CloseSingle } from '@univerjs/icons';
import { forwardRef } from 'react';
import { clsx } from '../../helper/clsx';
const Dialog = Root;
const DialogTrigger = Trigger;
const DialogPortal = Portal;
const DialogClose = Close;
const DialogOverlay = forwardRef<
ElementRef<typeof Overlay>,
ComponentPropsWithoutRef<typeof Overlay>
>(({ className, ...props }, ref) => (
<Overlay
ref={ref}
className={clsx(
`
univer-fixed univer-inset-0 univer-z-[1050] univer-bg-black/80
data-[state=closed]:univer-animate-out data-[state=closed]:univer-fade-out-0
data-[state=open]:univer-animate-in data-[state=open]:univer-fade-in-0
`,
className
)}
{...props}
/>
));
DialogOverlay.displayName = Overlay.displayName;
interface IDialogContentProps {
closable?: boolean;
onClickClose?: () => void;
}
const DialogContent = forwardRef<
ElementRef<typeof Content>,
ComponentPropsWithoutRef<typeof Content> & IDialogContentProps
>(({ className, children, closable = true, onClickClose, ...props }, ref) => (
<DialogPortal>
<DialogOverlay />
<Content
ref={ref}
className={clsx(
`
univer-fixed univer-left-1/2 univer-top-1/2 univer-z-[1050] univer-box-border univer-grid
univer-w-full univer-max-w-lg -univer-translate-x-1/2 -univer-translate-y-1/2 univer-gap-4
univer-border univer-border-solid univer-border-gray-200 univer-bg-white univer-px-6 univer-py-4
univer-text-gray-500 univer-shadow-md univer-duration-200
dark:univer-border-gray-600 dark:univer-bg-gray-700 dark:univer-text-gray-400
data-[state=closed]:univer-animate-out data-[state=closed]:univer-fade-out-0
data-[state=closed]:univer-zoom-out-95 data-[state=closed]:univer-slide-out-to-left-1/2
data-[state=closed]:univer-slide-out-to-top-[48%]
data-[state=open]:univer-animate-in data-[state=open]:univer-fade-in-0
data-[state=open]:univer-zoom-in-95 data-[state=open]:univer-slide-in-from-left-1/2
data-[state=open]:univer-slide-in-from-top-[48%]
sm:univer-rounded-lg
`,
className
)}
{...props}
>
{children}
{closable && (
<Close
className={`
univer-absolute univer-right-4 univer-top-4 univer-size-6 univer-cursor-pointer univer-rounded-sm
univer-border-none univer-bg-transparent univer-p-0 univer-transition-opacity
disabled:univer-pointer-events-none
hover:univer-opacity-100
`}
onClick={onClickClose}
>
<CloseSingle className="univer-size-4 univer-text-gray-400" />
<span className="univer-sr-only">Close</span>
</Close>
)}
</Content>
</DialogPortal>
));
DialogContent.displayName = Content.displayName;
const DialogHeader = ({
className,
...props
}: HTMLAttributes<HTMLDivElement>) => (
<div
className={clsx(
`
univer-flex univer-flex-col univer-space-y-1.5 univer-text-center
sm:univer-text-left
`,
className
)}
{...props}
/>
);
DialogHeader.displayName = 'DialogHeader';
const DialogFooter = ({
className,
...props
}: HTMLAttributes<HTMLDivElement>) => (
<div
className={clsx(
`
univer-flex univer-flex-col-reverse
sm:univer-flex-row sm:univer-justify-end sm:univer-space-x-2
`,
className
)}
{...props}
/>
);
DialogFooter.displayName = 'DialogFooter';
const DialogTitle = forwardRef<
ElementRef<typeof Title>,
ComponentPropsWithoutRef<typeof Title>
>(({ className, ...props }, ref) => (
<Title
ref={ref}
className={clsx(
`
univer-my-0 univer-text-lg univer-font-semibold univer-leading-none univer-tracking-tight
univer-text-gray-900
dark:univer-text-white
`,
className
)}
{...props}
/>
));
DialogTitle.displayName = Title.displayName;
const DialogDescription = forwardRef<
ElementRef<typeof Description>,
ComponentPropsWithoutRef<typeof Description>
>(({ className, ...props }, ref) => (
<Description
ref={ref}
className={clsx('univer-text-sm univer-text-gray-500', className)}
{...props}
/>
));
DialogDescription.displayName = Description.displayName;
export {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogOverlay,
DialogPortal,
DialogTitle,
DialogTrigger,
};
@@ -1,205 +0,0 @@
.dialog {
position: relative;
width: 640px;
margin: 10% auto;
&-wrap {
position: fixed;
z-index: 1050;
inset: 0;
overflow: hidden;
outline: 0;
-webkit-overflow-scrolling: touch;
}
&-title {
margin: 0;
font-size: var(--font-size-lg);
font-weight: 500;
&-content {
padding: 24px 28px 20px;
box-sizing: border-box;
}
}
&-content {
pointer-events: all;
position: relative;
color: rgb(var(--text-color));
background-color: rgb(var(--bg-color-secondary));
background-clip: padding-box;
border: 1px solid rgb(var(--border-color));
border-radius: var(--border-radius-lg);
box-shadow: var(--box-shadow-base);
}
&-close {
cursor: pointer;
position: absolute;
top: 24px;
right: 28px;
padding: 0;
font-size: var(--font-size-lg);
font-weight: 500;
line-height: 1;
color: rgb(var(--grey-500));
text-decoration: none;
opacity: 0.2;
background: transparent;
border: 0;
&:hover {
text-decoration: none;
opacity: 1;
}
}
&-header {
box-sizing: border-box;
color: rgb(var(--text-color));
border-radius: var(--border-radius-lg) var(--border-radius-lg) 0 0;
}
&-body {
padding: 0 28px 20px;
}
&-footer {
padding: 0 28px 24px;
text-align: right;
border-radius: 0 0 5px 5px;
}
.effect() {
animation-duration: 0.3s;
animation-fill-mode: both;
}
&-zoom-enter,
&-zoom-appear {
opacity: 0;
animation-play-state: paused;
animation-timing-function: cubic-bezier(0.08, 0.82, 0.17, 1);
.effect();
}
&-zoom-leave {
.effect();
animation-play-state: paused;
animation-timing-function: cubic-bezier(0.6, 0.04, 0.98, 0.34);
}
&-zoom-enter&-zoom-enter-active,
&-zoom-appear&-zoom-appear-active {
animation-name: dialog-zoom-in;
animation-play-state: running;
}
&-zoom-leave&-zoom-leave-active {
animation-name: dialog-zoom-out;
animation-play-state: running;
}
@keyframes dialog-zoom-in {
0% {
transform: scale(0, 0);
opacity: 0;
}
100% {
transform: scale(1, 1);
opacity: 1;
}
}
@keyframes dialog-zoom-out {
0% {
transform: scale(1, 1);
}
100% {
transform: scale(0, 0);
opacity: 0;
}
}
&-mask {
position: fixed;
z-index: 1050;
inset: 0;
height: 100%;
background-color: rgb(0 0 0 / 50%);
&-hidden {
display: none;
}
}
.fade-effect() {
animation-duration: 0.3s;
animation-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2);
animation-fill-mode: both;
}
&-fade-enter,
&-fade-appear {
opacity: 0;
.fade-effect();
animation-play-state: paused;
}
&-fade-leave {
.fade-effect();
animation-play-state: paused;
}
&-fade-enter&-fade-enter-active,
&-fade-appear&-fade-appear-active {
animation-name: dialog-fade-in;
animation-play-state: running;
}
&-fade-leave&-fade-leave-active {
animation-name: dialog-fade-out;
animation-play-state: running;
}
@keyframes dialog-fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes dialog-fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
&-root-draggable {
pointer-events: none;
}
}
@@ -48,6 +48,7 @@ function PopoverContent({
univer-rounded-md univer-border univer-border-solid univer-border-gray-200 univer-bg-white
univer-text-gray-900 univer-shadow-md univer-outline-hidden univer-scrollbar-thin
univer-scrollbar-track-gray-50 univer-scrollbar-thumb-gray-300
dark:univer-bg-gray-900
data-[side=bottom]:univer-slide-in-from-top-2
data-[side=left]:univer-slide-in-from-right-2
data-[side=right]:univer-slide-in-from-left-2
@@ -59,4 +59,5 @@ const TooltipContent = forwardRef<
</Content>
</Portal>
));
export { TooltipContent, TooltipPrimitive, TooltipProvider, TooltipTrigger };
+1 -1
View File
@@ -85,7 +85,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -62,7 +62,7 @@
"devDependencies": {
"@univerjs-infra/shared": "workspace:*",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -82,7 +82,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -61,7 +61,7 @@
"devDependencies": {
"@univerjs-infra/shared": "workspace:*",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -75,7 +75,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -85,7 +85,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -76,7 +76,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -97,7 +97,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -68,7 +68,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -81,7 +81,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -220,7 +220,6 @@ export class DrawingRenderService {
const dialog = this._dialogService.open({
width: Math.max(adjustSize.width, 200),
id: dialogId,
style: { margin: '0', top: '50%', left: '50%', transform: 'translate(-50%, -50%)' },
children: {
label: {
name: COMPONENT_IMAGE_VIEWER,
@@ -232,7 +231,7 @@ export class DrawingRenderService {
},
},
destroyOnClose: true,
draggable: false,
closable: false,
onClose: () => {
this._dialogService.close(dialogId);
dialog.dispose();
@@ -29,8 +29,12 @@ export const ImageViewer: React.FC<IImageViewerProps> = (props: IImageViewerProp
}
return (
<div>
<img src={src} alt="Univer Image Viewer" style={{ width: '100%', height: '100%', position: 'relative' }} />
<div className="univer-py-2">
<img
className="univer-relative univer-block univer-size-full"
src={src}
alt="Univer Image Viewer"
/>
</div>
);
};
+1 -1
View File
@@ -66,7 +66,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -83,7 +83,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -60,7 +60,7 @@
"devDependencies": {
"@univerjs-infra/shared": "workspace:*",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -73,7 +73,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
},
"browser": {
+1 -1
View File
@@ -81,7 +81,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -55,7 +55,7 @@ const FIND_REPLACE_DIALOG_ID = 'DESKTOP_FIND_REPLACE_DIALOG';
const FIND_REPLACE_PANEL_WIDTH = 350;
const FIND_REPLACE_PANEL_RIGHT_PADDING = 20;
const FIND_REPLACE_PANEL_TOP_PADDING = -90;
const FIND_REPLACE_PANEL_TOP_PADDING = 64;
export class FindReplaceController extends RxDisposable {
constructor(
@@ -131,6 +131,8 @@ export class FindReplaceController extends RxDisposable {
title: { title: this._localeService.t('find-replace.dialog.title') },
children: { label: 'FindReplaceDialog' },
destroyOnClose: true,
mask: false,
maskClosable: false,
defaultPosition: getFindReplaceDialogDefaultPosition(),
preservePositionOnDestroy: true,
onClose: () => this.closePanel(),
@@ -161,7 +163,7 @@ export class FindReplaceController extends RxDisposable {
function getFindReplaceDialogDefaultPosition(): { x: number; y: number } {
const { innerWidth } = window;
const x = (innerWidth - FIND_REPLACE_PANEL_WIDTH) / 2 - FIND_REPLACE_PANEL_RIGHT_PADDING;
const x = (innerWidth - FIND_REPLACE_PANEL_WIDTH) - FIND_REPLACE_PANEL_RIGHT_PADDING;
const y = FIND_REPLACE_PANEL_TOP_PADDING;
return { x, y };
@@ -174,7 +174,7 @@ export const ReplaceDialog = forwardRef(function ReplaceDIalogImpl(_props, ref)
}, [findCompleted, matchesCount, messageService, localeService]);
return (
<>
<div className="univer-theme">
<FormLayout label={localeService.t('find-replace.dialog.find')}>
<SearchInput
findCompleted={findCompleted}
@@ -238,7 +238,7 @@ export const ReplaceDialog = forwardRef(function ReplaceDIalogImpl(_props, ref)
<Button disabled={replaceAllDisabled} onClick={onClickReplaceAllButton}>{localeService.t('find-replace.dialog.replace-all')}</Button>
</span>
</div>
</>
</div>
);
});
+1 -1
View File
@@ -77,7 +77,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -66,7 +66,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -66,7 +66,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -91,7 +91,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -83,7 +83,7 @@
"@univerjs/icons-svg": "^0.3.2",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -92,7 +92,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -91,7 +91,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -85,7 +85,7 @@
"less": "^4.3.0",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -98,7 +98,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -63,7 +63,7 @@
"@univerjs-infra/shared": "workspace:*",
"@univerjs/sheets": "workspace:*",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -85,7 +85,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -97,7 +97,7 @@ export function FilterPanel() {
<Button variant="link" onClick={onClearCriteria} disabled={clearFilterDisabled}>
{localeService.t('sheets-filter.panel.clear-filter')}
</Button>
<span className={styles.sheetsFilterPanelFooterPrimaryButtons}>
<span className="univer-space-x-2">
<Button variant="default" onClick={onCancel}>
{localeService.t('sheets-filter.panel.cancel')}
</Button>
@@ -160,14 +160,6 @@
overflow: hidden;
justify-content: space-between;
&-primary-buttons {
display: flex;
> .button {
margin-left: 12px;
}
}
}
.select {
+1 -1
View File
@@ -79,7 +79,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -88,7 +88,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -98,7 +98,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -21,7 +21,7 @@ import { ICommandService, LocaleService, RichTextBuilder } from '@univerjs/core'
import { Button, Dialog, Input, Tooltip } from '@univerjs/design';
import { IEditorService, RichTextEditor } from '@univerjs/docs-ui';
import { deserializeRangeWithSheet, LexerTreeBuilder, matchToken, sequenceNodeType, serializeRange, serializeRangeWithSheet } from '@univerjs/engine-formula';
import { CloseSingle, DeleteSingle, IncreaseSingle, SelectRangeSingle } from '@univerjs/icons';
import { DeleteSingle, IncreaseSingle, SelectRangeSingle } from '@univerjs/icons';
import { SetSelectionsOperation } from '@univerjs/sheets';
import { useDependency, useEvent } from '@univerjs/ui';
import { useEffect, useRef, useState } from 'react';
@@ -68,7 +68,17 @@ export interface IRangeSelectorDialogProps {
}
export function RangeSelectorDialog(props: IRangeSelectorDialogProps) {
const { visible, initialValue, unitId, subUnitId, maxRangeCount = Infinity, supportAcrossSheet, onConfirm, onClose, onShowBySelection } = props;
const {
visible,
initialValue,
unitId,
subUnitId,
maxRangeCount = Infinity,
supportAcrossSheet,
onConfirm,
onClose,
onShowBySelection,
} = props;
const localeService = useDependency(LocaleService);
const lexerTreeBuilder = useDependency(LexerTreeBuilder);
const [ranges, setRanges] = useState<string[]>([]);
@@ -142,10 +152,11 @@ export function RangeSelectorDialog(props: IRangeSelectorDialogProps) {
return (
<Dialog
width="328px"
visible={visible}
open={visible}
title={localeService.t('rangeSelector.title')}
draggable
closeIcon={<CloseSingle />}
mask={false}
maskClosable={false}
footer={(
<footer>
<Button onClick={onClose}>{localeService.t('rangeSelector.cancel')}</Button>
+1 -1
View File
@@ -87,7 +87,7 @@
"@univerjs/docs": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -63,7 +63,7 @@
"devDependencies": {
"@univerjs-infra/shared": "workspace:*",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -100,7 +100,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -80,7 +80,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -87,7 +87,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -81,7 +81,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -84,7 +84,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -17,7 +17,7 @@
import { LocaleService } from '@univerjs/core';
import { Radio, RadioGroup } from '@univerjs/design';
import { useDependency } from '@univerjs/ui';
import React, { useState } from 'react';
import { useState } from 'react';
import styles from './index.module.less';
export interface IExtendConfirmProps {
@@ -28,8 +28,11 @@ export const ExtendConfirm = (props: IExtendConfirmProps) => {
const [extend, setExtend] = useState<string>('0');
const localeService = useDependency(LocaleService);
return (
<div className={styles.extendConfirmContent}>
<div className="extend-confirm-desc">{localeService.t('sheets-sort.dialog.sort-reminder-desc')}</div>
<div className="univer-text-sm univer-theme">
<div className="extend-confirm-desc">
{localeService.t('sheets-sort.dialog.sort-reminder-desc')}
</div>
<RadioGroup
className={styles.extendConfirmRadioGroup}
value={extend}
@@ -1,6 +1,3 @@
.extend-confirm-content {
font-size: 14px;
}
.extend-confirm-radio-group {
margin-top: 16px;
}
+1 -1
View File
@@ -80,7 +80,7 @@
"devDependencies": {
"@univerjs-infra/shared": "workspace:*",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -84,7 +84,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -79,7 +79,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -100,7 +100,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
@@ -71,14 +71,20 @@ export class SheetPermissionCheckUIController extends Disposable {
private _haveNotPermissionHandle(errorMsg: string) {
const dialogProps = {
id: UNIVER_SHEET_PERMISSION_ALERT_DIALOG_ID,
title: { title: '' },
title: { title: 'permission.dialog.alert' },
children: {
label: UNIVER_SHEET_PERMISSION_ALERT_DIALOG,
errorMsg,
},
width: 320,
destroyOnClose: true,
onClose: () => this._dialogService.close(UNIVER_SHEET_PERMISSION_ALERT_DIALOG_ID),
showOk: true,
onClose: () => {
this._dialogService.close(UNIVER_SHEET_PERMISSION_ALERT_DIALOG_ID);
},
onOk: () => {
this._dialogService.close(UNIVER_SHEET_PERMISSION_ALERT_DIALOG_ID);
},
className: 'sheet-permission-user-dialog',
};
if (this._permissionService.getShowComponents()) {
@@ -1,28 +0,0 @@
.sheet-permission-alert-dialog {
padding: var(--padding-xl) 24px;
&-title {
font-size: var(--font-size-lg);
font-weight: 500;
margin-bottom: var(--margin-base);
}
}
.sheet-permission-alert-dialog-button {
margin-top: var(--margin-lg);
display: flex;
justify-content: flex-end;
}
// @ybzky todo need more freedom to modify container style schemes
:global(.sheet-permission-user-dialog .univer-dialog-close) {
display: none;
}
:global(.sheet-permission-user-dialog .univer-dialog-header) {
display: none;
}
:global(.sheet-permission-user-dialog .univer-dialog-body) {
padding: 0;
}
@@ -15,28 +15,16 @@
*/
import { LocaleService } from '@univerjs/core';
import { Button } from '@univerjs/design';
import { IDialogService, useDependency } from '@univerjs/ui';
import styles from './index.module.less';
import { UNIVER_SHEET_PERMISSION_ALERT_DIALOG_ID } from './interface';
import { useDependency } from '@univerjs/ui';
export const AlertDialog = ({ errorMsg }: { errorMsg: string }) => {
const localeService = useDependency(LocaleService);
const dialogService = useDependency(IDialogService);
return (
<div className={styles.sheetPermissionAlertDialog}>
<h1 className={styles.sheetPermissionAlertDialogTitle}>{localeService.t('permission.dialog.alert')}</h1>
<p>{errorMsg || localeService.t('permission.dialog.alertContent')}</p>
<div className={styles.sheetPermissionAlertDialogButton}>
<Button
variant="primary"
onClick={() => {
dialogService.close(UNIVER_SHEET_PERMISSION_ALERT_DIALOG_ID);
}}
>
{localeService.t('permission.button.confirm')}
</Button>
</div>
<div>
<p className="univer-m-0">
{errorMsg || localeService.t('permission.dialog.alertContent')}
</p>
</div>
);
};
@@ -66,6 +66,7 @@ export const PermissionDetailUserPart = (props: IPermissionDetailUserPartProps)
children: { label: UNIVER_SHEET_PERMISSION_USER_DIALOG },
width: 280,
destroyOnClose: true,
closable: false,
onClose: () => dialogService.close(UNIVER_SHEET_PERMISSION_USER_DIALOG_ID),
className: 'sheet-permission-user-dialog',
});
@@ -1,16 +1,3 @@
.sheet-permission-user-dialog-wrapper {
height: 329px;
padding: var(--padding-base);
box-sizing: content-box;
}
.sheet-permission-user-dialog-search {
&-input {
width: 256px;
height: 32px;
}
}
.sheet-permission-user-list {
height: 240px;
overflow-y: auto;
@@ -24,13 +11,6 @@
height: 100%;
}
.sheet-permission-user-list-empty-text {
width: 240px;
word-wrap: break-word;
color: rgb(var(--grey-400));
font-size: 13px;
}
.sheet-permission-user-item {
display: flex;
align-items: center;
@@ -59,34 +39,8 @@
background-color: rgb(var(--grey-200));
}
.sheet-permission-user-dialog-footer {
height: 36px;
padding: var(--padding-xs) 0;
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: var(--margin-xs);
height: 28px;
&-confirm {
margin-left: var(--margin-sm);
}
}
.sheet-permission-user-dialog-button {
height: 28px;
line-height: 28px;
padding: 0px var(--padding-base);
}
:global(.sheet-permission-user-dialog .univer-dialog-close) {
display: none;
}
:global(.sheet-permission-user-dialog .univer-dialog-header) {
display: none;
}
:global(.sheet-permission-user-dialog .univer-dialog-body) {
padding: 0;
}
@@ -49,11 +49,11 @@ export const SheetPermissionUserDialog = () => {
};
return (
<div className={styles.sheetPermissionUserDialogWrapper}>
<div>
<div className={styles.sheetPermissionUserDialogSearch}>
<Input
className="univer-w-full"
placeholder={localeService.t('permission.dialog.search')}
className={styles.sheetPermissionUserDialogSearchInput}
value={inputValue}
onChange={(v) => setInputValue(v)}
/>
@@ -64,7 +64,11 @@ export const SheetPermissionUserDialog = () => {
<>
{searchUserList?.map((item) => {
return (
<div key={item.subject?.userID} className={styles.sheetPermissionUserItem} onClick={() => handleChangeUser(item)}>
<div
key={item.subject?.userID}
className={styles.sheetPermissionUserItem}
onClick={() => handleChangeUser(item)}
>
<Avatar src={item.subject?.avatar} size={24} />
<div className={styles.sheetPermissionUserItemName}>{item.subject?.name}</div>
{selectUserInfo?.findIndex((v) => v.subject?.userID === item.subject?.userID) !== -1 && (<div><CheckMarkSingle /></div>)}
@@ -75,16 +79,24 @@ export const SheetPermissionUserDialog = () => {
)
: (
<div className={styles.sheetPermissionUserListEmpty}>
<img width={240} height={120} src={UserEmptyBase64} alt="" />
<p className={styles.sheetPermissionUserListEmptyText}>{localeService.t('permission.dialog.userEmpty')}</p>
<img
className="univer-w-full"
src={UserEmptyBase64}
alt="empty list"
draggable={false}
/>
<p className="univer-text-[13px] univer-text-gray-400">
{localeService.t('permission.dialog.userEmpty')}
</p>
</div>
)}
</div>
<div className={styles.sheetPermissionSplit} />
<div className={styles.sheetPermissionUserDialogFooter}>
<Button className={styles.sheetPermissionUserDialogButton} onClick={() => dialogService.close(UNIVER_SHEET_PERMISSION_USER_DIALOG_ID)}>
<div className="univer-flex univer-items-center univer-justify-end univer-gap-1 univer-py-1">
<Button
className={styles.sheetPermissionUserDialogButton}
onClick={() => dialogService.close(UNIVER_SHEET_PERMISSION_USER_DIALOG_ID)}
>
{localeService.t('permission.button.cancel')}
</Button>
<Button
+1 -1
View File
@@ -97,7 +97,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -90,7 +90,7 @@
"@univerjs/network": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -86,7 +86,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -64,7 +64,7 @@
"devDependencies": {
"@univerjs-infra/shared": "workspace:*",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -60,7 +60,7 @@
"devDependencies": {
"@univerjs-infra/shared": "workspace:*",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -81,7 +81,7 @@
"rxjs": "^7.8.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -66,7 +66,7 @@
"@univerjs-infra/shared": "workspace:*",
"rxjs": "^7.8.1",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1"
}
}
+1 -1
View File
@@ -102,7 +102,7 @@
"tailwindcss": "^3.4.17",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.8.3",
"vite": "^6.3.0",
"vite": "^6.3.2",
"vitest": "^3.1.1",
"vue": "^3.5.13"
}
@@ -40,6 +40,7 @@ export class DesktopDialogService extends Disposable implements IDialogService {
override dispose(): void {
super.dispose();
this._dialogOptions = [];
this._dialogOptions$.complete();
}
@@ -47,12 +48,12 @@ export class DesktopDialogService extends Disposable implements IDialogService {
if (this._dialogOptions.find((item) => item.id === option.id)) {
this._dialogOptions = this._dialogOptions.map((item) => ({
...(item.id === option.id ? option : item),
visible: item.id === option.id ? true : item.visible,
open: item.id === option.id ? true : item.open,
}));
} else {
this._dialogOptions.push({
...option,
visible: true,
open: true,
});
}
@@ -67,7 +68,7 @@ export class DesktopDialogService extends Disposable implements IDialogService {
close(id: string) {
this._dialogOptions = this._dialogOptions.map((item) => ({
...item,
visible: item.id === id ? false : item.visible,
open: item.id === id ? false : item.open,
}));
this._dialogOptions$.next([...this._dialogOptions]);
@@ -77,7 +78,7 @@ export class DesktopDialogService extends Disposable implements IDialogService {
const expectIdSet = new Set(expectIds);
this._dialogOptions = this._dialogOptions.map((item) => ({
...item,
visible: expectIdSet.has(item.id) ? item.visible : false,
open: expectIdSet.has(item.id) ? item.open : false,
}));
this._dialogOptions$.next([...this._dialogOptions]);
}
@@ -17,7 +17,7 @@
import type { IDialogProps } from '@univerjs/design';
import type { IDialogPartMethodOptions } from './interface';
import { Dialog } from '@univerjs/design';
import React, { useEffect, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { CustomLabel } from '../../../components/custom-label/CustomLabel';
import { IDialogService } from '../../../services/dialog/dialog.service';
import { useDependency } from '../../../utils/di';
@@ -34,13 +34,13 @@ export function DialogPart() {
});
return () => subscription.unsubscribe();
}, [dialogService]);
}, []);
const attrs = dialogOptions.map((options) => {
const { children, title, closeIcon, footer, ...restProps } = options;
const attrs = useMemo(() => dialogOptions.map((options) => {
const { children, title, footer, ...restProps } = options;
const dialogProps = restProps as IDialogProps & { id: string };
for (const key of ['children', 'title', 'closeIcon', 'footer']) {
for (const key of ['children', 'title', 'footer']) {
const k = key as keyof IDialogPartMethodOptions;
const props = options[k] as any;
@@ -50,7 +50,9 @@ export function DialogPart() {
}
return dialogProps;
});
}), [dialogOptions]);
return <>{attrs?.map((options) => <Dialog key={options.id} {...options} />)}</>;
return attrs?.map((options) => (
<Dialog key={options.id} {...options} />
));
}

Some files were not shown because too many files have changed in this diff Show More