import { Classes } from '@blueprintjs/core';
import styled from '@emotion/styled';
import { useField, useStore } from '@tanstack/react-form';
import { useCallback, useMemo, useState } from 'react';
import { FaRegTrashAlt } from 'react-icons/fa';
import {
Button,
FieldGroupSVGTextStyleFields,
TableDragRowHandler,
createTableColumnHelper,
withForm,
} from 'react-science/ui';
import type { z } from 'zod';
import { useChartData } from '../../../../context/ChartContext.js';
import { getSpectraObjectPaths } from '../../../../utility/getSpectraObjectPaths.js';
import {
CellActions,
CellActionsButton,
CellCheckbox,
CellInput,
TableSettings,
} from '../ui/table.js';
import { TableSection } from '../ui/table_section.js';
import type { infoBlockFieldTabValidationWithUUID } from '../validation/title_block_tab_validation.js';
import { defaultGeneralSettingsFormValues } from '../validation.js';
export const TitleBlockTab = withForm({
defaultValues: defaultGeneralSettingsFormValues,
render: ({ form }) => {
const { Section, AppField } = form;
return (
<>
>
);
},
});
type Field = z.input;
function getEmptyField(): Field {
return {
label: '',
format: '',
jpath: '',
visible: true,
uuid: crypto.randomUUID(),
};
}
const TableFields = withForm({
defaultValues: defaultGeneralSettingsFormValues,
render: function Fields({ form }) {
const { Field } = form;
const fields = useField({
form,
name: 'infoBlock.fields',
mode: 'array',
});
const { removeValue, setValue, pushValue, name } = fields;
const [autoFocus, setAutoFocus] = useState('');
function onAddField() {
const value = getEmptyField();
pushValue(value, { dontRunListeners: true });
setAutoFocus(value.uuid);
}
const { data } = useChartData();
const { datalist } = useMemo(() => getSpectraObjectPaths(data), [data]);
const onDeleteAt = useCallback(
(index: number) => {
removeValue(index);
},
[removeValue],
);
const columns = useMemo(() => {
const columnHelper = createTableColumnHelper();
return [
columnHelper.display({
id: 'dnd',
header: '',
meta: {
tdStyle: { textAlign: 'center' },
},
cell: () => ,
}),
columnHelper.accessor('label', {
header: () => 'Label',
cell: ({ row: { index, original } }) => (
{(field) => (
{
field.handleBlur();
setAutoFocus('');
}}
intent={!field.state.meta.isValid ? 'danger' : undefined}
/>
)}
),
}),
columnHelper.accessor('jpath', {
header: 'Field',
cell: ({ row: { index } }) => (
{(field) => (
)}
),
}),
columnHelper.accessor('format', {
header: 'Format',
cell: ({ row: { index } }) => (
{(field) => (
)}
),
}),
columnHelper.accessor('visible', {
header: 'Visible',
meta: {
tdStyle: { textAlign: 'center' },
},
cell: ({ row: { index } }) => (
{(field) => (
field.handleChange(e.currentTarget.checked)}
/>
)}
),
}),
columnHelper.display({
id: 'actions',
header: '',
meta: {
thStyle: {
width: '60px',
},
},
cell: ({ row: { index } }) => {
return (
onDeleteAt(index)}
>
);
},
}),
];
}, [Field, autoFocus, datalist, name, onDeleteAt]);
const onRowOrderChanged = useCallback(
(value: Field[]) => {
setValue(value);
},
[setValue],
);
// It seems fields.setValue don't always trigger rerender
// so fields.state.value can de-sync and cause weird behavior with DnD reorder.
const fieldsData = useStore(fields.store, (s) => s.value);
return (
Add Field
}
>
);
},
});
function getRowId(row: Field) {
return row.uuid;
}
const TableDragRowHandlerStyled = styled(TableDragRowHandler)`
margin: 0 2px;
`;