Skip to content

Commit

Permalink
feat: add syntax colors to indicate pauses in source (#408)
Browse files Browse the repository at this point in the history
* feat: add syntax colors to indicate pauses in source

* refactor: clean up lint error
  • Loading branch information
bhajneet authored Jan 3, 2023
1 parent 9648cfa commit 4990f99
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 78 deletions.
80 changes: 76 additions & 4 deletions frontend/src/components/AsciiGurmukhi.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { ReactNode } from 'react'
import { stripVishraams } from 'gurmukhi-utils'
import { createUseStyles } from 'react-jss'

import theme from '../helpers/theme'

type AsciiGurmukhiProps = {
children?: ReactNode,
form?: Form,
text: string,
}

export const enum Form {
plain,
continuous,
syntactical,
}

const useStyles = createUseStyles( {
Expand All @@ -11,14 +20,77 @@ const useStyles = createUseStyles( {
fontSize: '1.05em',
fontWeight: 700,
},

heavy: {
color: theme.HeavyVishraam,
},

medium: {
color: theme.MediumVishraam,
},

light: {
color: theme.LightVishraam,
},

'@media (prefers-color-scheme: dark)': {
heavy: {
color: theme.HeavyVishraamDarkScheme,
},

medium: {
color: theme.MediumVishraamDarkScheme,
},

light: {
color: theme.LightVishraamDarkScheme,
},
},
} )

const AsciiGurmukhi = ( { children }: AsciiGurmukhiProps ) => {
const SyntacticalGurmukhi = ( { text }: { text: string } ) => {
const classes = useStyles()

return (
<span className={classes.AsciiGurmukhi}>
{children}
{text.split( ' ' ).map( ( word, index, array ) => {
if ( word.endsWith( ';' ) ) {
return <span className={classes.heavy}>{`${word.slice( 0, -1 )} `}</span>
}
if ( word.endsWith( ',' ) ) {
return <span className={classes.medium}>{`${word.slice( 0, -1 )} `}</span>
}
if ( word.endsWith( '.' ) ) {
return <span className={classes.light}>{`${word.slice( 0, -1 )} `}</span>
}
if ( index === array.length - 1 ) {
return word
}
return `${word} `
} )}
</span>
)
}

const AsciiGurmukhi = ( { form = Form.plain, text }: AsciiGurmukhiProps ) => {
const classes = useStyles()

if ( form === Form.continuous ) {
return (
<span className={classes.AsciiGurmukhi}>
{stripVishraams( text ).replaceAll( ' ', '' )}
</span>
)
}

if ( form === Form.syntactical ) {
return <SyntacticalGurmukhi text={text} />
}

// if ( form === Form.plain )
return (
<span className={classes.AsciiGurmukhi}>
{stripVishraams( text )}
</span>
)
}
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/helpers/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ const theme = {
Gap: '0.5rem',
BlankSpace: '0.2rem',

Shader: 'rgba(0% 0% 0% / 8%)',
Highlighter: 'rgba(100% 100% 100% / 8%)',

Separator: 'rgba(87.02% 86.48% 85.43% / 40%)', // lch(88% 1.5 85)
SeparatorDarkScheme: 'rgba(28.38% 27.48% 27.77% / 40%)', // lch(30% 1.125 355)

Expand Down Expand Up @@ -59,6 +62,14 @@ const theme = {

Red: 'rgb(83.05% 24% 29.82%)', // lch(50% 66 25)
RedDarkScheme: 'rgb(100% 52.49% 52.68%)', // lch(70% 53 25)

HeavyVishraam: 'rgb(55.17% 30% 13.76%)', // lch(40% 44 55)
MediumVishraam: 'rgb(9.32% 42.55% 19.52%)', // lch(40% 44 145)
LightVishraam: 'rgb(53% 27.31% 53.51%)', // lch(40% 44 295)

HeavyVishraamDarkScheme: 'rgb(68.3% 53.37% 44.51%)', // lch(40% 44 55)
MediumVishraamDarkScheme: 'rgb(45.94% 60.18% 47.63%)', // lch(40% 44 145)
LightVishraamDarkScheme: 'rgb(57.97% 54.89% 70.53%)', // lch(40% 44 295)
}

export default theme
2 changes: 1 addition & 1 deletion frontend/src/screens/Collections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const Collections = ( { setVisibleCollections }: CollectionsProps ) => {
key={id}
onClick={() => handleOnClick( `/sources/${id}/page/1/line/0` )}
>
<AsciiGurmukhi>{nameGurmukhi}</AsciiGurmukhi>
<AsciiGurmukhi text={nameGurmukhi} />
<ChevronRight />
</Row>
) )}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/screens/LineView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ const LineView = ( { sources }: LineViewProps ) => {
target="_blank"
rel="noreferrer"
>
<AsciiGurmukhi>{word}</AsciiGurmukhi>
<AsciiGurmukhi text={word} />
</a>
<span className={`${classes.headerDivSpan} ${classes.headerSpan}`}>{toSyllabicSymbols( word )}</span>
</div>
Expand Down
130 changes: 58 additions & 72 deletions frontend/src/screens/SourceView.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable jsx-a11y/click-events-have-key-events */

import { stripVishraams } from 'gurmukhi-utils'
import { useAtomValue } from 'jotai'
import { mapValues } from 'lodash'
import { SkipBack, SkipForward } from 'lucide-react'
Expand All @@ -11,7 +10,7 @@ import { Link, useLocation, useNavigate, useParams } from 'react-router-dom'
import useSWR from 'swr'
import { useDebounce } from 'use-debounce'

import AsciiGurmukhi from '../components/AsciiGurmukhi'
import AsciiGurmukhi, { Form } from '../components/AsciiGurmukhi'
import Button from '../components/Button'
import Content from '../components/Content'
import Error from '../components/Error'
Expand All @@ -33,26 +32,35 @@ const useStyles = createUseStyles( {
bottom: 0,
zIndex: 0,
borderTop: '1px solid rgba(0,0,0,0.1)',
background: '#E3E0DC',
background: theme.Shader,
width: '100%',
'& + $sourceContent': {
paddingBottom: `calc(${theme.Gutter})`,
},
},

line: {
marginLeft: '0.2em',
padding: [ theme.Gap, theme.BlankSpace ],
borderRadius: theme.Gap,
outline: [ '2px', 'solid', 'transparent' ],
transition: theme.Normally,
'&:first-child': {
marginLeft: 0,
},
'&:hover': {
color: theme.Blue,
backgroundColor: theme.Shader,
},
},

active: {
color: theme.Blue,
'& > span > span': {
filter: 'brightness(1.25) saturate(1.25)',
},
},

focused: {
color: theme.Teal,
outlineColor: theme.Blue,
},

controlsContent: {
Expand All @@ -65,11 +73,20 @@ const useStyles = createUseStyles( {
'@media (prefers-color-scheme: dark)': {
line: {
'&:hover': {
color: theme.BlueDarkScheme,
backgroundColor: theme.Highlighter,
},
},
active: {
color: theme.BlueDarkScheme,
'& > span > span': {
filter: 'brightness(1.25) saturate(1.5)',
},
},
focused: {
color: theme.TealDarkScheme,
outlineColor: theme.BlueDarkScheme,
},
sourceControls: {
background: theme.Highlighter,
},
},

Expand All @@ -86,12 +103,12 @@ const useStyles = createUseStyles( {
type SourceViewParams = 'page' | 'source' | 'line'

const KEY_MAP = {
previousLine: [ 'shift+tab', 'left' ],
nextLine: [ 'tab', 'right' ],
activatePreviousLine: [ 'left' ],
activateNextLine: [ 'right' ],
focusPreviousLine: [ 'shift+tab' ],
focusNextLine: [ 'tab' ],
firstLine: [ 'home' ],
lastLine: [ 'end' ],
// belowLine: [ 'down' ],
// aboveLine: [ 'up' ],
openLine: [ 'enter' ],
previousPage: [ 'shift+left', 'pageup' ],
nextPage: [ 'shift+right', 'pagedown' ],
Expand Down Expand Up @@ -152,12 +169,17 @@ const SourceView = ( { sources }: SourceViewProps ) => {

const { length, pageNameGurmukhi } = sources.find( ( { id } ) => id === source ) ?? {}

const focusLine = ( line: number ) => {
const activateLine = ( line: number ) => {
navigate( `/sources/${source}/page/${page}/line/${line}`, { replace: true } )

lineRefs.current[ line ].scrollIntoView( { block: 'center' } )
}

const focusLine = ( line: number ) => {
lineRefs.current[ line ].focus()
lineRefs.current[ line ].scrollIntoView( { block: 'center' } )
}

const goToPage = ( nextPage: number ) => {
if ( nextPage && nextPage !== rawPage ) navigate( `/sources/${source}/page/${nextPage}/line/0`, { replace: true } )
}
Expand All @@ -170,12 +192,22 @@ const SourceView = ( { sources }: SourceViewProps ) => {
if ( rawPage > 1 ) goToPage( rawPage - 1 )
}

const nextLine = () => {
const activateNextLine = () => {
if ( rawLine < lines!.length - 1 ) activateLine( rawLine + 1 )
else nextPage()
}

const activatePreviousLine = () => {
if ( rawLine > 0 ) activateLine( rawLine - 1 )
else previousPage()
}

const focusNextLine = () => {
if ( rawLine < lines!.length - 1 ) focusLine( rawLine + 1 )
else nextPage()
}

const previousLine = () => {
const focusPreviousLine = () => {
if ( rawLine > 0 ) focusLine( rawLine - 1 )
else previousPage()
}
Expand All @@ -185,59 +217,13 @@ const SourceView = ( { sources }: SourceViewProps ) => {

const onLineEnter = () => navigate( `${location.pathname}/view` )

const belowLine = () => {
const lineRef = lineRefs.current[ rawLine ]
const { offsetTop, offsetLeft } = lineRef
const { scrollY } = window

// Scroll element into view
lineRef.scrollIntoView( { block: 'center' } )

// Calculate element's relative y position to viewport
const styles = getComputedStyle( lineRef )
const [ lineHeight ] = styles.lineHeight.split( 'px' )
const relativeY = offsetTop - scrollY

// Get below the line element and index
const element = document.elementFromPoint( offsetLeft + 4, +lineHeight + relativeY )

const [ index ] = Object
.entries( lineRefs.current )
.find( ( [ , line ] ) => line === element )
|| [ line ]

focusLine( +index )
}

const aboveLine = () => {
const lineRef = lineRefs.current[ line ]
const { offsetTop, offsetLeft } = lineRef
const { scrollY } = window

// Scroll element into view
lineRef.scrollIntoView( { block: 'center' } )

// Calculate element's relative y position to viewport
const relativeY = offsetTop - scrollY

// Get above the line element and index
const element = document.elementFromPoint( offsetLeft + 4, relativeY - 4 )

const [ index ] = Object
.entries( lineRefs.current )
.find( ( [ , line ] ) => line === element )
?? [ line ]

focusLine( +index )
}

const handlers = {
previousLine,
nextLine,
activatePreviousLine,
activateNextLine,
focusPreviousLine,
focusNextLine,
firstLine,
lastLine,
belowLine,
aboveLine,
previousPage,
nextPage,
openLine: onLineEnter,
Expand All @@ -259,14 +245,14 @@ const SourceView = ( { sources }: SourceViewProps ) => {
</Button>
</Link>

<AsciiGurmukhi>
{pageNameGurmukhi ? `${pageNameGurmukhi} ` : ''}
{rawPage}
<span>
{pageNameGurmukhi ? <AsciiGurmukhi text={`${pageNameGurmukhi} `} /> : ''}
<AsciiGurmukhi text={rawPage.toString()} />
{' '}
/
{' '}
{length}
</AsciiGurmukhi>
<AsciiGurmukhi text={length.toString()} />
</span>

<Link to={page < length! ? `/sources/${source}/page/${page + 1}/line/0` : ''}>
<Button disabled={page >= length!}>
Expand All @@ -289,11 +275,11 @@ const SourceView = ( { sources }: SourceViewProps ) => {
key={id}
to={`/sources/${source}/page/${page}/line/${index}/view`}
ref={( ref ) => { lineRefs.current[ index ] = ref! }}
className={`${classes.line} ${rawLine === index ? classes.focused : ''}`}
className={`${classes.line} ${rawLine === index ? classes.active : ''}`}
style={{ fontSize: `${zoomValue}rem` }}
data-cy="go-to-home-value"
>
<AsciiGurmukhi>{stripVishraams( gurmukhi )}</AsciiGurmukhi>
<AsciiGurmukhi form={Form.syntactical} text={gurmukhi} />
</Link>
) )}
</GlobalHotKeys>
Expand Down

0 comments on commit 4990f99

Please sign in to comment.