Spaces:
Sleeping
Sleeping
| import { | |
| BOARD_TO_ON_CHANGE, | |
| ListRender, | |
| PlaitElement, | |
| Viewport, | |
| createBoard, | |
| withBoard, | |
| withHandPointer, | |
| withHistory, | |
| withHotkey, | |
| withMoving, | |
| withOptions, | |
| withRelatedFragment, | |
| withSelection, | |
| PlaitBoard, | |
| type PlaitPlugin, | |
| type PlaitBoardOptions, | |
| type Selection, | |
| ThemeColorMode, | |
| BOARD_TO_AFTER_CHANGE, | |
| PlaitOperation, | |
| PlaitTheme, | |
| isFromScrolling, | |
| setIsFromScrolling, | |
| getSelectedElements, | |
| updateViewportOffset, | |
| initializeViewBox, | |
| withI18n, | |
| updateViewBox, | |
| FLUSHING, | |
| BoardTransforms, | |
| } from '@plait/core'; | |
| import { BoardChangeData } from './plugins/board'; | |
| import { useCallback, useEffect, useRef, useState } from 'react'; | |
| import { withReact } from './plugins/with-react'; | |
| import { PlaitCommonElementRef, withImage, withText } from '@plait/common'; | |
| import { BoardContext, BoardContextValue } from './hooks/use-board'; | |
| import React from 'react'; | |
| import { withPinchZoom } from './plugins/with-pinch-zoom-plugin'; | |
| export type WrapperProps = { | |
| value: PlaitElement[]; | |
| children: React.ReactNode; | |
| options: PlaitBoardOptions; | |
| plugins: PlaitPlugin[]; | |
| viewport?: Viewport; | |
| theme?: PlaitTheme; | |
| onChange?: (data: BoardChangeData) => void; | |
| onSelectionChange?: (selection: Selection | null) => void; | |
| onValueChange?: (value: PlaitElement[]) => void; | |
| onViewportChange?: (value: Viewport) => void; | |
| onThemeChange?: (value: ThemeColorMode) => void; | |
| }; | |
| export const Wrapper: React.FC<WrapperProps> = ({ | |
| value, | |
| children, | |
| options, | |
| plugins, | |
| viewport, | |
| theme, | |
| onChange, | |
| onSelectionChange, | |
| onValueChange, | |
| onViewportChange, | |
| onThemeChange, | |
| }) => { | |
| const [context, setContext] = useState<BoardContextValue>(() => { | |
| const board = initializeBoard(value, options, plugins, viewport, theme); | |
| const listRender = initializeListRender(board); | |
| return { | |
| v: 0, | |
| board, | |
| listRender, | |
| }; | |
| }); | |
| const { board, listRender } = context; | |
| const onContextChange = useCallback(() => { | |
| if (onChange) { | |
| const data: BoardChangeData = { | |
| children: board.children, | |
| operations: board.operations, | |
| viewport: board.viewport, | |
| selection: board.selection, | |
| theme: board.theme, | |
| }; | |
| onChange(data); | |
| } | |
| const hasSelectionChanged = board.operations.some((o) => | |
| PlaitOperation.isSetSelectionOperation(o) | |
| ); | |
| const hasViewportChanged = board.operations.some((o) => | |
| PlaitOperation.isSetViewportOperation(o) | |
| ); | |
| const hasThemeChanged = board.operations.some((o) => | |
| PlaitOperation.isSetThemeOperation(o) | |
| ); | |
| const hasChildrenChanged = | |
| board.operations.length > 0 && | |
| !board.operations.every( | |
| (o) => | |
| PlaitOperation.isSetSelectionOperation(o) || | |
| PlaitOperation.isSetViewportOperation(o) || | |
| PlaitOperation.isSetThemeOperation(o) | |
| ); | |
| if (onValueChange && hasChildrenChanged) { | |
| onValueChange(board.children); | |
| } | |
| if (onSelectionChange && hasSelectionChanged) { | |
| onSelectionChange(board.selection); | |
| } | |
| if (onViewportChange && hasViewportChanged) { | |
| onViewportChange(board.viewport); | |
| } | |
| if (onThemeChange && hasThemeChanged) { | |
| onThemeChange(board.theme.themeColorMode); | |
| } | |
| setContext((prevContext) => ({ | |
| v: prevContext.v + 1, | |
| board, | |
| listRender, | |
| })); | |
| }, [board, onChange, onSelectionChange, onValueChange]); | |
| useEffect(() => { | |
| BOARD_TO_ON_CHANGE.set(board, () => { | |
| const isOnlySetSelection = | |
| board.operations.length && | |
| board.operations.every((op) => op.type === 'set_selection'); | |
| if (isOnlySetSelection) { | |
| listRender.update(board.children, { | |
| board: board, | |
| parent: board, | |
| parentG: PlaitBoard.getElementHost(board), | |
| }); | |
| return; | |
| } | |
| const isSetViewport = | |
| board.operations.length && | |
| board.operations.some((op) => op.type === 'set_viewport'); | |
| if (isSetViewport && isFromScrolling(board)) { | |
| setIsFromScrolling(board, false); | |
| listRender.update(board.children, { | |
| board: board, | |
| parent: board, | |
| parentG: PlaitBoard.getElementHost(board), | |
| }); | |
| return; | |
| } | |
| listRender.update(board.children, { | |
| board: board, | |
| parent: board, | |
| parentG: PlaitBoard.getElementHost(board), | |
| }); | |
| if (isSetViewport) { | |
| initializeViewBox(board); | |
| } else { | |
| updateViewBox(board); | |
| } | |
| updateViewportOffset(board); | |
| const selectedElements = getSelectedElements(board); | |
| selectedElements.forEach((element) => { | |
| const elementRef = | |
| PlaitElement.getElementRef<PlaitCommonElementRef>(element); | |
| elementRef.updateActiveSection(); | |
| }); | |
| }); | |
| BOARD_TO_AFTER_CHANGE.set(board, () => { | |
| onContextChange(); | |
| }); | |
| return () => { | |
| BOARD_TO_ON_CHANGE.delete(board); | |
| BOARD_TO_AFTER_CHANGE.delete(board); | |
| }; | |
| }, [board]); | |
| const isFirstRender = useRef(true); | |
| useEffect(() => { | |
| if (isFirstRender.current) { | |
| isFirstRender.current = false; | |
| return; | |
| } | |
| if (value !== context.board.children && !FLUSHING.get(board)) { | |
| board.children = value; | |
| listRender.update(board.children, { | |
| board: board, | |
| parent: board, | |
| parentG: PlaitBoard.getElementHost(board), | |
| }); | |
| BoardTransforms.fitViewport(board); | |
| } | |
| }, [value]); | |
| return ( | |
| <BoardContext.Provider value={context}>{children}</BoardContext.Provider> | |
| ); | |
| }; | |
| const initializeBoard = ( | |
| value: PlaitElement[], | |
| options: PlaitBoardOptions, | |
| plugins: PlaitPlugin[], | |
| viewport?: Viewport, | |
| theme?: PlaitTheme | |
| ) => { | |
| let board = withRelatedFragment( | |
| withHotkey( | |
| withHandPointer( | |
| withHistory( | |
| withSelection( | |
| withMoving( | |
| withBoard( | |
| withI18n( | |
| withOptions( | |
| withReact(withImage(withText(createBoard(value, options)))) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ); | |
| plugins.forEach((plugin: any) => { | |
| board = plugin(board); | |
| }); | |
| withPinchZoom(board); | |
| if (viewport) { | |
| board.viewport = viewport; | |
| } | |
| if (theme) { | |
| board.theme = theme; | |
| } | |
| return board; | |
| }; | |
| const initializeListRender = (board: PlaitBoard) => { | |
| const listRender = new ListRender(board); | |
| return listRender; | |
| }; | |