diff --git a/pages/diff.tsx b/pages/diff.tsx new file mode 100644 index 000000000..a406e2b76 --- /dev/null +++ b/pages/diff.tsx @@ -0,0 +1,10 @@ +import * as React from 'react'; + +import { AppDiff } from '../src/apps/diff/AppDiff'; + +import { withLayout } from '~/common/layout/withLayout'; + + +export default function DiffPage() { + return withLayout({ type: 'optima' }, ); +} \ No newline at end of file diff --git a/src/apps/AppSmallContainer.tsx b/src/apps/AppSmallContainer.tsx index e4d70aa56..b5a307fe5 100644 --- a/src/apps/AppSmallContainer.tsx +++ b/src/apps/AppSmallContainer.tsx @@ -5,7 +5,7 @@ import { Box, Container, Typography } from '@mui/joy'; export function AppSmallContainer({ title, description, children }: { title: string; - description: string; + description: React.ReactNode; children: React.ReactNode; }) { return ( diff --git a/src/apps/diff/AppDiff.tsx b/src/apps/diff/AppDiff.tsx new file mode 100644 index 000000000..662f6c25c --- /dev/null +++ b/src/apps/diff/AppDiff.tsx @@ -0,0 +1,178 @@ +import * as React from 'react'; + +import type { SxProps } from '@mui/joy/styles/types'; +import { Box, Card, Divider, IconButton, Textarea, Tooltip, Typography } from '@mui/joy'; +import SwapHorizIcon from '@mui/icons-material/SwapHoriz'; + +import { RenderTextDiff, useSanityTextDiffs } from '~/modules/blocks/textdiff/RenderTextDiff'; + +import { themeScalingMap } from '~/common/app.theme'; +import { useIsMobile } from '~/common/components/useMatchMedia'; +import { useUIPreferencesStore } from '~/common/state/store-ui'; + +import { AppSmallContainer } from '../AppSmallContainer'; +import { GlobalShortcutDefinition, useGlobalShortcuts } from '~/common/components/useGlobalShortcuts'; +import { countWords } from '~/common/util/textUtils'; + + +export function AppDiff() { + + // state + const [text1, setText1] = React.useState('This is the Original text...'); + const [text2, setText2] = React.useState('This is the Modified text...'); + const [isSwapping, setIsSwapping] = React.useState(false); + + + // external state + const isMobile = useIsMobile(); + const contentScaling = useUIPreferencesStore(state => state.contentScaling); + const diffs = useSanityTextDiffs(text2 || '', text1 || '', true); + + // memos + const handleSwap = React.useCallback(() => { + setIsSwapping(true); + setTimeout(() => { + const temp = text1; + setText1(text2); + setText2(temp); + setIsSwapping(false); + }, 200); // sync this with the transition duration + }, [text1, text2]); + + const scaledTypographySx: SxProps = React.useMemo(() => ({ + fontSize: themeScalingMap[contentScaling]?.blockFontSize ?? undefined, + lineHeight: themeScalingMap[contentScaling]?.blockLineHeight ?? 1.75, + }), [contentScaling]); + + // this is a repetition.. shall move this to a shared root component + const shortcuts = React.useMemo((): GlobalShortcutDefinition[] => [ + ['+', true, true, false, useUIPreferencesStore.getState().increaseContentScaling], + ['-', true, true, false, useUIPreferencesStore.getState().decreaseContentScaling], + ], []); + useGlobalShortcuts(shortcuts); + + const c1 = text1?.length || 0; + const c2 = text2?.length || 0; + const w1 = countWords(text1); + const w2 = countWords(text2); + + + return ( + + + + + + +