refactor(design): refactor Dialog & Confirm (#5048)
Co-authored-by: GitHub Actions <actions@github.com>
@@ -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,
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 70 KiB |
@@ -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();
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 = {};
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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} />
|
||||
));
|
||||
}
|
||||
|
||||