diff --git a/packages/design/src/components/color-picker/AlphaSlider.tsx b/packages/design/src/components/color-picker/AlphaSlider.tsx index 41f496fe19..cba98da051 100644 --- a/packages/design/src/components/color-picker/AlphaSlider.tsx +++ b/packages/design/src/components/color-picker/AlphaSlider.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import { hsvToRgb } from './color-conversion'; interface IAlphaSliderProps { @@ -29,16 +29,19 @@ export function AlphaSlider({ hsv, alpha, onChange, onChanged }: IAlphaSliderPro const sliderRef = useRef(null); const thumbRef = useRef(null); - const thumbSize = useMemo(() => { - return thumbRef.current?.clientWidth ?? 0; - }, [thumbRef.current]); - const calculateAlpha = useCallback((clientX: number) => { const slider = sliderRef.current; if (!slider) return; + const thumbSize = thumbRef.current?.clientWidth ?? 0; + const rect = slider.getBoundingClientRect(); const maxX = rect.width - thumbSize; + if (maxX <= 0) { + onChange(0); + return; + } + const x = Math.max(0, Math.min(clientX - rect.left, maxX)); onChange(Math.round(x / maxX * 100) / 100); }, [onChange]); @@ -69,7 +72,11 @@ export function AlphaSlider({ hsv, alpha, onChange, onChanged }: IAlphaSliderPro const getThumbPosition = () => { const safeAlpha = Math.min(Math.max(alpha * 100, 0), 100); - return `${(safeAlpha / 100) * (100 - (thumbSize / sliderRef.current?.clientWidth! * 100))}%`; + const thumbSize = thumbRef.current?.clientWidth ?? 0; + const sliderWidth = sliderRef.current?.clientWidth ?? 0; + const thumbOffsetPercent = sliderWidth > 0 ? (thumbSize / sliderWidth) * 100 : 0; + + return `${(safeAlpha / 100) * (100 - thumbOffsetPercent)}%`; }; const color = hsvToRgb(...hsv); diff --git a/packages/design/src/components/color-picker/HueSlider.tsx b/packages/design/src/components/color-picker/HueSlider.tsx index e9004e3a0d..46191e6c03 100644 --- a/packages/design/src/components/color-picker/HueSlider.tsx +++ b/packages/design/src/components/color-picker/HueSlider.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; interface IHueSliderProps { hsv: [number, number, number]; @@ -27,22 +27,24 @@ export function HueSlider({ hsv, onChange, onChanged }: IHueSliderProps) { const sliderRef = useRef(null); const thumbRef = useRef(null); - const thumbSize = useMemo(() => { - return thumbRef.current?.clientWidth ?? 0; - }, []); - const calculateHue = useCallback((clientX: number) => { const slider = sliderRef.current; if (!slider) return; + const thumbSize = thumbRef.current?.clientWidth ?? 0; + const rect = slider.getBoundingClientRect(); const maxX = rect.width - thumbSize; + if (maxX <= 0) { + onChange(0, hsv[1], hsv[2]); + return; + } const x = Math.max(0, Math.min(clientX - rect.left, maxX)); const newHue = Math.round((x / maxX) * 360); onChange(newHue, hsv[1], hsv[2]); - }, [hsv, thumbSize, onChange]); + }, [hsv, onChange]); const handlePointerMove = useCallback((e: PointerEvent) => { e.stopPropagation(); @@ -71,7 +73,11 @@ export function HueSlider({ hsv, onChange, onChanged }: IHueSliderProps) { const getThumbPosition = () => { const safeHue = Math.min(Math.max(hsv[0], 0), 360); - return `${(safeHue / 360) * (100 - (thumbSize / sliderRef.current?.clientWidth! * 100))}%`; + const thumbSize = thumbRef.current?.clientWidth ?? 0; + const sliderWidth = sliderRef.current?.clientWidth ?? 0; + const thumbOffsetPercent = sliderWidth > 0 ? (thumbSize / sliderWidth) * 100 : 0; + + return `${(safeHue / 360) * (100 - thumbOffsetPercent)}%`; }; return ( diff --git a/packages/design/src/components/radio/Radio.tsx b/packages/design/src/components/radio/Radio.tsx index d25fb0469f..31c3009b7e 100644 --- a/packages/design/src/components/radio/Radio.tsx +++ b/packages/design/src/components/radio/Radio.tsx @@ -50,7 +50,7 @@ export interface IRadioProps { export function Radio(props: IRadioProps) { const { children, checked, value, disabled = false, onChange } = props; - const inputRef = useRef(null); + const inputRef = useRef(null!); function handleChange(e: React.ChangeEvent) { e.stopPropagation(); @@ -60,7 +60,7 @@ export function Radio(props: IRadioProps) { if (typeof value !== 'undefined') { onChange && onChange(value); } else { - const checked = inputRef?.current?.checked!; + const checked = inputRef.current.checked; onChange && onChange(checked); } } diff --git a/packages/docs-ui/src/commands/commands/table/doc-table-insert.command.ts b/packages/docs-ui/src/commands/commands/table/doc-table-insert.command.ts index b2abc8983e..662c488cdc 100644 --- a/packages/docs-ui/src/commands/commands/table/doc-table-insert.command.ts +++ b/packages/docs-ui/src/commands/commands/table/doc-table-insert.command.ts @@ -297,8 +297,11 @@ export const DocTableInsertColumnCommand: ICommand e.onBeforePasteImage)?.onBeforePasteImage!) ?? fileToBase64; + const onBeforePasteImage = this._clipboardHooks.find((e) => e.onBeforePasteImage)?.onBeforePasteImage ?? fileToBase64; await Promise.all(files.map(async (file, index) => { const image = await onBeforePasteImage(file); diff --git a/packages/docs-ui/src/services/clipboard/udm-to-html/convertor.ts b/packages/docs-ui/src/services/clipboard/udm-to-html/convertor.ts index 31be93a79d..0d9359146c 100644 --- a/packages/docs-ui/src/services/clipboard/udm-to-html/convertor.ts +++ b/packages/docs-ui/src/services/clipboard/udm-to-html/convertor.ts @@ -254,7 +254,7 @@ function processNode(node: DataStreamTreeNode, doc: IDocumentData, result: IHtml case DataStreamTreeNodeType.PARAGRAPH: { const { children, startIndex, endIndex } = node; - const paragraph = doc.body?.paragraphs!.find((p) => p.startIndex === endIndex) ?? {} as IParagraph; + const paragraph = doc.body?.paragraphs?.find((p) => p.startIndex === endIndex) ?? {} as IParagraph; const { paragraphStyle = {} } = paragraph; const { spaceAbove, spaceBelow, lineSpacing } = paragraphStyle; const style = []; diff --git a/packages/engine-render/src/components/docs/layout/block/paragraph/layout-ruler.ts b/packages/engine-render/src/components/docs/layout/block/paragraph/layout-ruler.ts index dff7f3466a..501fa2d752 100644 --- a/packages/engine-render/src/components/docs/layout/block/paragraph/layout-ruler.ts +++ b/packages/engine-render/src/components/docs/layout/block/paragraph/layout-ruler.ts @@ -368,10 +368,9 @@ function _divideOperator( } else { newGlyphGroup = [spanGroupCached[0]]; } - const column = currentLine.parent; + const column = currentLine.parent!; - // eslint-disable-next-line ts/no-non-null-asserted-optional-chain - const { paragraphStart: lineIsStart } = column?.lines.pop()!; // Delete the previous line and recalculate according to the maximum content height + const { paragraphStart: lineIsStart } = column.lines.pop()!; // Delete the previous line and recalculate according to the maximum content height _lineOperator( ctx, diff --git a/packages/sheets-formula-ui/src/views/range-selector/hooks/use-ranges-highlight.ts b/packages/sheets-formula-ui/src/views/range-selector/hooks/use-ranges-highlight.ts index 966a4adb2e..f600ee8ddc 100644 --- a/packages/sheets-formula-ui/src/views/range-selector/hooks/use-ranges-highlight.ts +++ b/packages/sheets-formula-ui/src/views/range-selector/hooks/use-ranges-highlight.ts @@ -27,7 +27,7 @@ import { useDocHight } from '../../formula-editor/hooks/use-highlight'; export function useRangesHighlight(editor: Nullable, focusing: boolean, unitId: string, subUnitId: string) { const lexerTreeBuilder = useDependency(LexerTreeBuilder); const highlightDoc = useDocHight(''); - const change = useObservable(editor?.getDocumentDataModel()!.change$); + const change = useObservable(editor?.getDocumentDataModel()?.change$); const [sequenceNodes, setSequenceNodes] = useState<(string | ISequenceNode)[]>([]); const markSelectionService = useDependency(IMarkSelectionService); const last = useRef(''); diff --git a/packages/sheets-formula-ui/src/views/range-selector/index.tsx b/packages/sheets-formula-ui/src/views/range-selector/index.tsx index 29837450f0..20aa583244 100644 --- a/packages/sheets-formula-ui/src/views/range-selector/index.tsx +++ b/packages/sheets-formula-ui/src/views/range-selector/index.tsx @@ -270,7 +270,7 @@ export function RangeSelector(props: IRangeSelectorProps) { const handleOpenModal = useEvent(() => { blurEditor(); - setRangeSelectorRanges(parseRanges(editor?.getDocumentDataModel()!.getPlainText() ?? '')); + setRangeSelectorRanges(parseRanges(editor?.getDocumentDataModel()?.getPlainText() ?? '')); setPopupVisible(true); }); @@ -294,12 +294,12 @@ export function RangeSelector(props: IRangeSelectorProps) { setRangeSelectorRanges([]); setPopupVisible(false); }, - getValue: () => editor?.getDocumentDataModel()!.getPlainText() ?? '', + getValue: () => editor?.getDocumentDataModel()?.getPlainText() ?? '', }; }, [blurEditor, editor, editorService, selectorRef, sequenceNodesRef]); useEffect(() => { - onVerify?.(verifyRange(sequenceNodes), editor?.getDocumentDataModel()!.getPlainText() ?? ''); + onVerify?.(verifyRange(sequenceNodes), editor?.getDocumentDataModel()?.getPlainText() ?? ''); }, [sequenceNodes]); useEffect(() => { diff --git a/packages/sheets-ui/src/views/editor-container/EditorContainer.tsx b/packages/sheets-ui/src/views/editor-container/EditorContainer.tsx index 7ff3871b4c..316fcfb571 100644 --- a/packages/sheets-ui/src/views/editor-container/EditorContainer.tsx +++ b/packages/sheets-ui/src/views/editor-container/EditorContainer.tsx @@ -21,7 +21,6 @@ import { DeviceInputEventType } from '@univerjs/engine-render'; import { ComponentManager, DISABLE_AUTO_FOCUS_KEY, MetaKeys, useDependency, useEvent, useObservable, useSidebarClick } from '@univerjs/ui'; import * as React from 'react'; import { useEffect, useRef, useState } from 'react'; - import { SetCellEditVisibleArrowOperation, SetCellEditVisibleOperation } from '../../commands/operations/cell-edit.operation'; import { EMBEDDING_FORMULA_EDITOR_COMPONENT_KEY } from '../../common/keys'; import { IEditorBridgeService } from '../../services/editor-bridge.service'; @@ -124,7 +123,7 @@ export const EditorContainer: React.FC = () => { useSidebarClick(handleClickSideBar); - const keyCodeConfig = useKeyEventConfig(isRefSelecting, editState?.unitId!); + const keyCodeConfig = useKeyEventConfig(isRefSelecting, editState?.unitId); const onMoveInEditor = useEvent((keycode: KeyCode, metaKey: MetaKeys) => { commandService.executeCommand(SetCellEditVisibleArrowOperation.id, { diff --git a/packages/sheets-ui/src/views/editor-container/hooks.ts b/packages/sheets-ui/src/views/editor-container/hooks.ts index 6b332b33cb..ffe6e08153 100644 --- a/packages/sheets-ui/src/views/editor-container/hooks.ts +++ b/packages/sheets-ui/src/views/editor-container/hooks.ts @@ -22,7 +22,7 @@ import { useMemo } from 'react'; import { SetCellEditVisibleOperation } from '../../commands/operations/cell-edit.operation'; import { IEditorBridgeService } from '../../services/editor-bridge.service'; -export function useKeyEventConfig(isRefSelecting: React.MutableRefObject<0 | 1 | 2>, unitId: string) { +export function useKeyEventConfig(isRefSelecting: React.MutableRefObject<0 | 1 | 2>, unitId?: string) { const editorBridgeService = useDependency(IEditorBridgeService); const commandService = useDependency(ICommandService); @@ -34,12 +34,16 @@ export function useKeyEventConfig(isRefSelecting: React.MutableRefObject<0 | 1 | ], handler: (keycode: KeyCode) => { if (keycode === KeyCode.ENTER || keycode === KeyCode.ESC || keycode === KeyCode.TAB) { + if (unitId == null) { + return; + } + editorBridgeService.disableForceKeepVisible(); commandService.syncExecuteCommand(SetCellEditVisibleOperation.id, { visible: false, eventType: DeviceInputEventType.Keyboard, keycode, - unitId: unitId!, + unitId, }); } }, diff --git a/packages/sheets-ui/src/views/formula-bar/FormulaBar.tsx b/packages/sheets-ui/src/views/formula-bar/FormulaBar.tsx index 186f483e8e..399b615597 100644 --- a/packages/sheets-ui/src/views/formula-bar/FormulaBar.tsx +++ b/packages/sheets-ui/src/views/formula-bar/FormulaBar.tsx @@ -83,7 +83,7 @@ export function FormulaBar(props: IProps) { const workbook = useObservable(() => univerInstanceService.getCurrentTypeOfUnit$(UniverInstanceType.UNIVER_SHEET), undefined, undefined, [])!; const isRefSelecting = useRef<0 | 1 | 2>(0); const editState = useObservable(editorBridgeService.currentEditCellState$); - const keyCodeConfig = useKeyEventConfig(isRefSelecting, editState?.unitId ?? ''); + const keyCodeConfig = useKeyEventConfig(isRefSelecting, editState?.unitId); const FormulaEditor = componentManager.get(EMBEDDING_FORMULA_EDITOR_COMPONENT_KEY); const formulaAuxUIParts = useComponentsOfPart(SheetsUIPart.FORMULA_AUX); const contextService = useDependency(IContextService); diff --git a/packages/sheets/src/commands/commands/delete-range-move-up.command.ts b/packages/sheets/src/commands/commands/delete-range-move-up.command.ts index e34f40a525..9c4b1ba57e 100644 --- a/packages/sheets/src/commands/commands/delete-range-move-up.command.ts +++ b/packages/sheets/src/commands/commands/delete-range-move-up.command.ts @@ -54,9 +54,10 @@ export const DeleteRangeMoveUpCommand: ICommand = { if (!target) return false; const { unitId, subUnitId, workbook, worksheet } = target; - let range = params?.range; + let range: IRange | undefined = params?.range; if (!range) { - range = selectionManagerService.getCurrentLastSelection()?.range!; + const currentSelection = selectionManagerService.getCurrentLastSelection(); + range = currentSelection?.range as IRange | undefined; } if (!range) return false; diff --git a/packages/thread-comment-ui/src/views/thread-comment-tree/index.tsx b/packages/thread-comment-ui/src/views/thread-comment-tree/index.tsx index 49cad76db6..eb2af9e3b2 100644 --- a/packages/thread-comment-ui/src/views/thread-comment-tree/index.tsx +++ b/packages/thread-comment-ui/src/views/thread-comment-tree/index.tsx @@ -503,17 +503,21 @@ export const ThreadCommentTree = (props: IThreadCommentTreeProps) => { unitId={unitId} subUnitId={subUnitId} onSave={async ({ text, attachments }) => { + if (!currentUser?.userID || !comments?.root) { + throw new Error('[ThreadCommentTree] No current user or root comment found'); + } + const comment: IThreadComment = { text, attachments, dT: getDT(), id: generateRandomId(), ref: refStr!, - personId: currentUser?.userID!, + personId: currentUser?.userID, parentId: comments?.root.id, unitId, subUnitId, - threadId: comments?.root.threadId!, + threadId: comments?.root.threadId, }; if (onAddComment?.(comment) === false) {