refactor: readonly inputs in cuesheet

This commit is contained in:
Carlos Valente
2025-08-02 06:44:55 +02:00
committed by Carlos Valente
parent ed4d3ba265
commit 765d5d97cf
7 changed files with 66 additions and 21 deletions
@@ -10,7 +10,12 @@
padding-inline: 0.5em;
outline: none;
&:hover:not(:disabled) {
&::placeholder {
color: $gray-500;
letter-spacing: 0;
}
&:hover:not(:disabled):not(:read-only) {
background-color: $gray-1100;
}
@@ -25,9 +30,8 @@
cursor: not-allowed;
}
&::placeholder {
color: $gray-500;
letter-spacing: 0;
&:read-only::placeholder {
opacity: 0;
}
}
@@ -9,9 +9,13 @@
border-radius: $component-border-radius-md;
border: 1px solid transparent;
padding-inline: 0.5em;
outline: none;
&::placeholder {
color: $gray-500;
letter-spacing: 0;
}
&:hover:not(:disabled) {
background-color: $gray-1100;
}
@@ -26,21 +30,21 @@
cursor: not-allowed;
}
&::placeholder {
color: $gray-500;
letter-spacing: 0;
&:read-only::placeholder {
opacity: 0;
}
}
.subtle {
background-color: $gray-1200;
padding-top: 0.5em;
padding-inline: 0.5em;
padding-top: 0.25em;
}
.ghosted {
background-color: transparent;
padding: 0;
padding-top: 0.5em;
padding-top: 0.25em;
}
.fluid {
@@ -1,8 +1,8 @@
.imageInput {
&::placeholder {
&:not(:read-only)::placeholder {
opacity: 0.2;
}
&:hover::placeholder {
&:not(:read-only):hover::placeholder {
opacity: 1;
}
}
@@ -7,12 +7,13 @@ import style from './EditableImage.module.scss';
interface EditableImageProps {
initialValue: string;
readOnly?: boolean;
updateValue: (newValue: string) => void;
}
export default memo(EditableImage);
function EditableImage({ initialValue, updateValue }: EditableImageProps) {
function EditableImage({ initialValue, readOnly, updateValue }: EditableImageProps) {
const handleUpdate = (newValue: string) => {
if (newValue === initialValue) {
return;
@@ -35,6 +36,9 @@ function EditableImage({ initialValue, updateValue }: EditableImageProps) {
variant='ghosted'
className={style.imageInput}
fluid
readOnly={readOnly}
// we disable the field to prevent receiving focus
disabled={readOnly}
placeholder='Paste image URL'
onBlur={(event) => handleUpdate(event.currentTarget.value)}
onKeyDown={(event) => {
@@ -49,12 +53,14 @@ function EditableImage({ initialValue, updateValue }: EditableImageProps) {
return (
<div className={style.imageCell}>
<div className={style.overlay}>
<Button onClick={openInNewTab}>Preview</Button>
<Button variant='subtle-destructive' onClick={() => handleUpdate('')}>
Delete
</Button>
</div>
{!readOnly && (
<div className={style.overlay}>
<Button onClick={openInNewTab}>Preview</Button>
<Button variant='subtle-destructive' onClick={() => handleUpdate('')}>
Delete
</Button>
</div>
)}
{Boolean(initialValue) && <img loading='lazy' src={initialValue} className={style.image} />}
</div>
);
@@ -0,0 +1,6 @@
.ghostedText {
min-height: 2rem;
padding: 0;
padding-top: 0.25em;
width: 100%;
}
@@ -0,0 +1,7 @@
import { PropsWithChildren } from 'react';
import style from './GhostedText.module.scss';
export default function GhostedText({ children }: PropsWithChildren) {
return <div className={style.ghostedText}>{children}</div>;
}
@@ -10,6 +10,7 @@ import { AppMode } from '../../../../ontimeConfig';
import DurationInput from './DurationInput';
import EditableImage from './EditableImage';
import FlagCell from './FlagCell';
import GhostedText from './GhostedText';
import MultiLineCell from './MultiLineCell';
import MutedText from './MutedText';
import SingleLineCell from './SingleLineCell';
@@ -139,6 +140,11 @@ function MakeMultiLineField({ row, column, table }: CellContext<OntimeEntry, unk
return null;
}
const canWrite = column.columnDef.meta?.canWrite;
if (!canWrite) {
return <GhostedText>{initialValue}</GhostedText>;
}
return <MultiLineCell initialValue={initialValue as string} handleUpdate={update} />;
}
@@ -155,8 +161,9 @@ function LazyImage({ row, column, table }: CellContext<OntimeEntry, unknown>) {
return null;
}
const canWrite = column.columnDef.meta?.canWrite;
const initialValue = event.custom[column.id];
return <EditableImage initialValue={initialValue} updateValue={update} />;
return <EditableImage initialValue={initialValue} updateValue={update} readOnly={!canWrite} />;
}
function MakeSingleLineField({ row, column, table }: CellContext<OntimeEntry, unknown>) {
@@ -173,6 +180,11 @@ function MakeSingleLineField({ row, column, table }: CellContext<OntimeEntry, un
return null;
}
const canWrite = column.columnDef.meta?.canWrite;
if (!canWrite) {
return <GhostedText>{initialValue}</GhostedText>;
}
return <SingleLineCell initialValue={initialValue as string} handleUpdate={update} />;
}
@@ -197,9 +209,15 @@ function MakeCustomField({ row, column, table }: CellContext<OntimeEntry, unknow
return null;
}
// fields will not contain the field if there is no value set by the user
// entries will not contain the field if there is no value set by the user
// event if there is no initial value, we still render the cell
const initialValue = event.custom[column.id] ?? '';
const canWrite = column.columnDef.meta?.canWrite;
if (!canWrite) {
return <GhostedText>{initialValue}</GhostedText>;
}
return <MultiLineCell initialValue={initialValue} handleUpdate={update} />;
}