Skip to content

Commit

Permalink
chore: convert kanji reference table to React component
Browse files Browse the repository at this point in the history
  • Loading branch information
StarScape committed May 10, 2024
1 parent 0a595e2 commit f0655d6
Show file tree
Hide file tree
Showing 5 changed files with 305 additions and 78 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"zip-src": "tsx scripts/zip-src"
},
"lint-staged": {
"*.ts": [
"*.{js,jsx,ts,tsx}": [
"prettier --write",
"eslint --fix"
],
Expand Down
169 changes: 169 additions & 0 deletions src/content/popup/KanjiReferencesTable.fixture.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import { ReferenceAbbreviation } from '../../common/refs';
import { KanjiReferencesTable } from './KanjiReferencesTable';

const TEST_ENTRY = {
c: '日',
r: {
py: ['ri4'],
on: ['ニチ', 'ジツ'],
kun: ['ひ', '-び', '-か'],
na: [
'あ',
'あき',
'いる',
'く',
'くさ',
'こう',
'す',
'たち',
'に',
'にっ',
'につ',
'へ',
],
},
m: ['day', 'sun', 'Japan', 'counter for days'],
rad: {
x: 72,
b: '⽇',
k: '日',
na: ['ひ'],
m: ['day', 'sun', 'Japan', 'counter for days'],
m_lang: 'en',
},
refs: {
nelson_c: 2097,
nelson_n: 2410,
halpern_njecd: 3027,
halpern_kkld_2ed: 2606,
heisig6: 12,
henshall: 62,
sh_kk2: 5,
kanji_in_context: 16,
busy_people: '1.A',
kodansha_compact: 963,
skip: '3-3-1',
sh_desc: '4c0.1',
conning: 1,
},
misc: {
sc: 4,
gr: 1,
freq: 1,
jlpt: 4,
kk: 10,
wk: 2,
jlptn: 5,
},
m_lang: 'en',
comp: [],
cf: [],
};

function ReferencesVariant({
title,
references,
}: {
title: string;
references: Array<ReferenceAbbreviation>;
}) {
return (
<div>
<h2>{title}</h2>
<KanjiReferencesTable entry={TEST_ENTRY} kanjiReferences={references} />
</div>
);
}

export default function () {
return (
<div
style={{
background: 'var(--bg-color)',
color: 'var(--text-color)',
padding: '18px',
display: 'flex',
flexDirection: 'column',
gap: '40px',
}}
>
<ReferencesVariant
title="Even number of rows (last row filled)"
references={[
'radical',
'nelson_r',
'kk',
'py',
'jlpt',
'unicode',
'conning',
'halpern_njecd',
'halpern_kkld_2ed',
'heisig6',
'henshall',
'sh_kk2',
'nelson_c',
]}
/>

<ReferencesVariant
title="Even number of rows (last row not filled)"
references={[
'radical',
'nelson_r',
'kk',
'py',
'jlpt',
'unicode',
'conning',
'halpern_njecd',
'halpern_kkld_2ed',
'heisig6',
'henshall',
'sh_kk2',
]}
/>

<ReferencesVariant
title="Odd number of rows (last row filled)"
references={[
'radical',
'nelson_r',
'kk',
'py',
'jlpt',
'unicode',
'conning',
'halpern_njecd',
'halpern_kkld_2ed',
'heisig6',
'henshall',
'sh_kk2',
'nelson_c',
'nelson_n',
'skip',
]}
/>

<ReferencesVariant
title="Odd number of rows (last row not filled)"
references={[
'radical',
'nelson_r',
'kk',
'py',
'jlpt',
'unicode',
'conning',
'halpern_njecd',
'halpern_kkld_2ed',
'heisig6',
'henshall',
'sh_kk2',
'nelson_c',
'nelson_n',
]}
/>
</div>
);
}
102 changes: 102 additions & 0 deletions src/content/popup/KanjiReferencesTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { KanjiResult } from '@birchill/jpdict-idb';
import { useMemo } from 'preact/hooks';

import { useLocale } from '../../common/i18n';
import {
getSelectedReferenceLabels,
ReferenceAbbreviation,
} from '../../common/refs';
import { classes } from '../../utils/classes';

import { getReferenceValue } from '../reference-value';

type Props = {
entry: KanjiResult;
kanjiReferences: Array<ReferenceAbbreviation>;
};

export function KanjiReferencesTable({ entry, kanjiReferences }: Props) {
const { t, langTag } = useLocale();

const referenceTableInfo = useMemo(() => {
const referenceNames = getSelectedReferenceLabels(kanjiReferences, t);
const referenceTableInfo = [];
for (const ref of referenceNames) {
// Don't show the Nelson radical if it's the same as the regular radical
// (in which case it will be empty) and we're showing the regular radical.
if (
ref.ref === 'nelson_r' &&
!entry.rad.nelson &&
kanjiReferences.includes('radical')
) {
continue;
}

const value = getReferenceValue(entry, ref.ref, t) || '-';
referenceTableInfo.push({
name: {
lang: ref.lang,
value: ref.short || ref.full,
},
value: {
lang:
ref.ref === 'radical' || ref.ref === 'nelson_r' ? 'ja' : undefined,
value,
},
highlight: false,
});
}

// Now we go through and toggle the styles to get the desired alternating
// effect.
//
// We can't easily use nth-child voodoo here because we need to
// handle unbalanced columns etc. We also can't easily do this in the loop
// where we generate the cells because we don't know how many references we
// will generate at that point.
for (const [index, cellInfo] of [...referenceTableInfo].entries()) {
const row = index % Math.ceil(referenceTableInfo.length / 2);
if (row % 2 === 0) {
cellInfo.highlight = true;
}
}

return referenceTableInfo;
}, [t, kanjiReferences]);

// The layout we want is something in-between what CSS grid and CSS multicol
// can do. See:
//
// https://twitter.com/brianskold/status/1186198347184398336
//
// In the stylesheet we make let the table flow horizontally, but then here
// where we know the number of rows, we update it to produce the desired
// vertical flow.
let gridAutoFlow: string | undefined;
let gridTemplateRows: string | undefined;
if (referenceTableInfo.length > 1) {
gridAutoFlow = 'column';
gridTemplateRows = `repeat(${Math.ceil(
referenceTableInfo.length / 2
)}, minmax(min-content, max-content))`;
}

return (
<div
class="references"
lang={langTag}
style={{ gridAutoFlow, gridTemplateRows }}
>
{referenceTableInfo.map((cellInfo) => (
<div class={classes('ref', cellInfo.highlight && '-highlight')}>
<span class="name" lang={cellInfo.name.lang}>
{cellInfo.name.value}
</span>
<span class="value" lang={cellInfo.value.lang}>
{cellInfo.value.value}
</span>
</div>
))}
</div>
);
}
22 changes: 22 additions & 0 deletions src/content/popup/cosmos.decorator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { RenderableProps } from 'preact';
import { useSelect } from 'react-cosmos/client';

import { I18nProvider } from '../../common/i18n';
import { EmptyProps } from '../../utils/type-helpers';

export default ({ children }: RenderableProps<EmptyProps>) => {
const [locale] = useSelect('locale', {
options: ['en', 'ja', 'zh_hans'],
});

const [themeName] = useSelect('theme', {
options: ['black', 'light', 'blue', 'lightblue', 'yellow'],
defaultValue: 'light',
});

return (
<I18nProvider locale={locale}>
<div className={`theme-${themeName}`}>{children}</div>
</I18nProvider>
);
};
Loading

0 comments on commit f0655d6

Please sign in to comment.