Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
74be691
feat: add experimental assignment list panel
hamed-musallam Oct 19, 2026
929d0e8
refactor: support custom row highlight IDs in TanStackTable
hamed-musallam Oct 20, 2026
7f3ec64
refactor: extract reusable ACS formatting options helper
hamed-musallam Oct 20, 2026
1e5192f
feat: display per-spectrum chemical shifts in assignment table
hamed-musallam Oct 20, 2026
e87ce69
refactor: align assignment panel layout with other panels
hamed-musallam Oct 20, 2026
ff66993
chore: remove useless export
hamed-musallam Oct 20, 2026
b9ed043
fix: remove spectrum header and trailing period from assignment ACS c…
hamed-musallam Oct 20, 2026
8aae653
refactor: apply default ACS options to assignment shifts
hamed-musallam Oct 21, 2026
5dfd4f7
refactor: combine assignment spectra by nucleus
hamed-musallam Oct 21, 2026
9ba340e
feat: show assignment coverage badges by nucleus
hamed-musallam Oct 21, 2026
baae589
refactor: remove tooltip wrapper from assignment column header
hamed-musallam Oct 21, 2026
dfba9a9
refactor: replace "Expand all" switch with expand/collapse menu
hamed-musallam Oct 21, 2026
1031e01
feat: show hydrogen labels on collapsed assignment rows
hamed-musallam Oct 21, 2026
3b49740
feat: copy to clipboard and export assignments to CSV
hamed-musallam Oct 22, 2026
b65d24d
refactor: assignment panel utilities and table cells
hamed-musallam Oct 22, 2026
68f99f2
refactor: remove delta symbol from assignment values and headers
hamed-musallam Oct 22, 2026
a8acf28
refactor: reduce column width for atom labels to 50px
hamed-musallam Oct 22, 2026
c058099
refactor: use shift only (D) formatting for carbon assignments
hamed-musallam Oct 22, 2026
29a6b09
refactor: simplify assignment shift formatting
hamed-musallam Oct 22, 2026
6174362
refactor: copy assignments as TSV while keeping export as CSV
hamed-musallam Oct 22, 2026
cc9d7b3
refactor: rename 'assignment list' panel to 'assignment summary'
hamed-musallam Oct 22, 2026
c31b219
chore: fix prettier
hamed-musallam Oct 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/component/elements/tanstack_table/elements/table_row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
table,
highlightedSource = 'UNKNOWN',
getHighlightExtra,
getHighlightIDs,
onContextMenuSelect,
contextMenu,
onClick,
Expand All @@ -121,13 +122,16 @@
}) as HighlightEventSource,
[highlightedSource, row.original, getHighlightExtra],
);
const highlight = useHighlight(getIDs(row), data);
const highlight = useHighlight(
getHighlightIDs?.(row.original) ?? getIDs(row),
data,
);

useEffect(() => {
return () => {
highlight.hide();
};
// TODO: avoid this hack.

Check warning on line 134 in src/component/elements/tanstack_table/elements/table_row.tsx

View workflow job for this annotation

GitHub Actions / nodejs / lint-eslint

Unexpected 'todo' comment: 'TODO: avoid this hack.'
// eslint-disable-next-line @eslint-react/exhaustive-deps
}, []);

Expand Down
2 changes: 2 additions & 0 deletions src/component/elements/tanstack_table/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ function TanStackTableInner<TData extends TanStackRowData>(
columns,
highlightedSource,
getHighlightExtra,
getHighlightIDs,
contextMenu = [],
onContextMenuSelect,
onScroll,
Expand Down Expand Up @@ -265,6 +266,7 @@ function TanStackTableInner<TData extends TanStackRowData>(
const highlightSourceProps = {
highlightedSource,
getHighlightExtra,
getHighlightIDs,
} as TanStackTableHighlightSourceProps<TData>;

return (
Expand Down
2 changes: 2 additions & 0 deletions src/component/elements/tanstack_table/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export type TanStackTableHeaderGroup<TData extends TanStackRowData> =
HeaderGroup<TanStackTableFeatures, TData>;

export type TanStackTableHighlightSourceProps<TData extends TanStackRowData> = {
getHighlightIDs?: (row: TData) => string[];
} & {
[K in HighlightEventSourceType]: HighlightEventSourceExtra<K> extends never
? { highlightedSource?: K; getHighlightExtra?: never }
: {
Expand Down
1 change: 1 addition & 0 deletions src/component/highlight/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ interface HighlightEventSourceMap {
MULTIPLE_ANALYSIS_ZONE: { colKey: string };
DATABASE: { ranges: Range[]; jcampURL: string; baseURL: string };
ATOM: never;
ASSIGNMENT_TABLE: never;
UNKNOWN: never;
}

Expand Down
26 changes: 19 additions & 7 deletions src/component/hooks/use_publication_strings.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import type { ACSExportOptions, Spectrum } from '@zakodium/nmrium-core';
import type {
ACSExportOptions,
Spectrum1D,
Spectrum,
} from '@zakodium/nmrium-core';
import { assertSpectrum1D, isSpectrum1D } from '@zakodium/nmrium-core';
import type { RangesToACSOptions } from 'nmr-processing';
import { rangesToACS } from 'nmr-processing';
Expand Down Expand Up @@ -39,8 +43,7 @@ export function buildPublicationString(options: BuildPublicationStringOptions) {
info,
ranges: { values },
} = spectrum;
const { originFrequency, nucleus } = info;
const { signalKind, format, couplingFormat, ...otherOptions } = acs;
const { signalKind } = acs;

const ranges =
signalKind === 'all'
Expand All @@ -49,17 +52,26 @@ export function buildPublicationString(options: BuildPublicationStringOptions) {
range.signals?.some((signal) => signal.kind === 'signal'),
);

const rangesToACSOptions: RangesToACSOptions = {
return rangesToACS(ranges, getRangesToACSOptions(info, acs));
}

export function getRangesToACSOptions(
info: Pick<Spectrum1D['info'], 'nucleus' | 'originFrequency'>,
acs: ACSExportOptions,
): RangesToACSOptions {
const { originFrequency, nucleus } = info;
const { signalKind, format, couplingFormat, ...otherOptions } = acs;
const options: RangesToACSOptions = {
nucleus,
observedFrequency: originFrequency,
...otherOptions,
format: '',
};

if (format !== 'D') {
rangesToACSOptions.format = format;
rangesToACSOptions.couplingFormat = couplingFormat;
options.format = format;
options.couplingFormat = couplingFormat;
}

return rangesToACS(ranges, rangesToACSOptions);
return options;
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ export default function useAtomAssignment() {
const currentDiaIDsToHighlight = useMemo(() => {
const { highlighted, sourceData } = highlightData.highlight;

if (sourceData?.type === 'ASSIGNMENT_TABLE') {
return highlighted;
}

let currentSpectrum = spectrum;

if (
Expand Down
59 changes: 38 additions & 21 deletions src/component/panels/Panels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import { memo } from 'react';
import { Accordion, Toolbar } from 'react-science/ui';

import { usePreferences } from '../context/PreferencesContext.js';
import useCheckExperimentalFeature from '../hooks/useCheckExperimentalFeature.js';

import type { AccordionItem } from './accordionItems.js';
import { AssignmentSummaryPanel } from './assignment-summary/AssignmentSummaryPanel.js';
import { useAccordionItems } from './hooks/useAccordionItems.js';
import { useGetPanelOptions } from './hooks/useGetPanelOptions.js';
import { useTogglePanel } from './hooks/useTogglePanel.js';
Expand All @@ -18,6 +20,7 @@ const Container = styled.div`
`;

function PanelsInner() {
const isExperimental = useCheckExperimentalFeature();
const getPanelPreferences = useGetPanelOptions();

const { dispatch } = usePreferences();
Expand All @@ -38,27 +41,41 @@ function PanelsInner() {
return (
<Container>
<Accordion>
{displayedPanels.map((item) => {
const { title, component, id } = item;
return (
<Accordion.Item
unmountChildren
id={id}
key={title}
title={title}
open={isOpened(item)}
onOpenChange={(isOpened) => {
dispatch({
type: 'TOGGLE_PANEL',
payload: { id, options: { open: isOpened } },
});
}}
renderToolbar={() => <RightButtons id={id} />}
>
{component}
</Accordion.Item>
);
})}
{[
...displayedPanels.map((item) => {
const { title, component, id } = item;
return (
<Accordion.Item
unmountChildren
id={id}
key={title}
title={title}
open={isOpened(item)}
onOpenChange={(isOpened) => {
dispatch({
type: 'TOGGLE_PANEL',
payload: { id, options: { open: isOpened } },
});
}}
renderToolbar={() => <RightButtons id={id} />}
>
{component}
</Accordion.Item>
);
}),
...(isExperimental
? [
<Accordion.Item
key="assignment-summary"
id="assignment-summary"
title="Assignment summary"
unmountChildren
>
<AssignmentSummaryPanel />
</Accordion.Item>,
]
: []),
]}
</Accordion>
</Container>
);
Expand Down
Loading
Loading