Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion packages/scribe/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@biblionexus-foundation/scribe-editor",
"version": "0.1.1",
"version": "0.1.2",
"description": "Scripture editor used in Scribe",
"license": "MIT",
"homepage": "https://github.com/BiblioNexus-Foundation/scripture-editors/tree/main/packages/scribe#readme",
Expand Down
5 changes: 5 additions & 0 deletions packages/scribe/src/components/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import LoadingSpinner from "./LoadingSpinner";
import { blackListedChangeTags } from "shared/nodes/scripture/usj/node-constants";
import { deepEqual } from "fast-equals";
import { getUsjMarkerAction } from "../adaptors/usj-marker-action.utils";
import KeyboardShortcutPlugin from "../plugins/KeyboardShortcutPlugin";
import { Toolbar } from "./Toolbar";

/** Forward reference for the editor. */
export type EditorRef = {
Expand Down Expand Up @@ -120,6 +122,7 @@ const Editor = forwardRef(function Editor(

return (
<LexicalComposer initialConfig={initialConfig}>
<Toolbar scrRef={scrRef} autoNumbering={autoNumbering} />
<RichTextPlugin
contentEditable={
<ContentEditable
Expand All @@ -129,6 +132,7 @@ const Editor = forwardRef(function Editor(
placeholder={<LoadingSpinner />}
ErrorBoundary={LexicalErrorBoundary}
/>

{scrRef && (
<UsjNodesMenuPlugin
trigger={"\\"}
Expand All @@ -150,6 +154,7 @@ const Editor = forwardRef(function Editor(
<HistoryPlugin />
<AutoFocusPlugin />
<ContextMenuPlugin />
<KeyboardShortcutPlugin />
<ClipboardPlugin />
<ScriptureReferencePlugin scrRef={scrRef} setScrRef={setScrRef} />
</LexicalComposer>
Expand Down
42 changes: 42 additions & 0 deletions packages/scribe/src/components/Input/Input.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,45 @@
border-radius: 5px;
min-width: 0;
}
.scribe-input-wrapper {
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 10px;
}

.scribe-input-label {
display: flex;
flex: 1;
color: #666;
}

.scribe-input-field {
display: flex;
flex: 2;
border: 1px solid #999;
padding: 7px 10px;
font-size: 16px;
border-radius: 5px;
min-width: 0;
}

.scribe-button {
background-color: #1976d2;
color: white;
border: none;
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
cursor: pointer;
transition: background-color 0.2s;
}

.scribe-button:hover {
background-color: #1565c0;
}

.scribe-button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
120 changes: 27 additions & 93 deletions packages/scribe/src/components/Input/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ const TextInput: React.FC<TextInputProps> = ({
"data-test-id": dataTestId,
type = "text",
}) => (
<div className="Input__wrapper">
<label className="Input__label">{label}</label>
<div className="scribe-input-wrapper">
<label className="scribe-input-label">{label}</label>
<input
type={type}
className="Input__input"
className="scribe-input-field"
placeholder={placeholder}
value={value}
onChange={(e) => onChange(e.target.value)}
Expand All @@ -35,8 +35,7 @@ const TextInput: React.FC<TextInputProps> = ({
type InsertDialogProps = {
activeEditor: LexicalEditor;
onClose: () => void;
//eslint-disable-next-line @typescript-eslint/no-explicit-any
insertFunction: (params: any) => void;
insertFunction: (editor: LexicalEditor, value?: string, noteText?: string) => void;
label: string;
placeholder?: string;
};
Expand All @@ -48,130 +47,65 @@ export const InsertDialog: React.FC<InsertDialogProps> = ({
label,
placeholder,
}) => {
const [inputValues, setInputValues] = useState<{ [key: string]: string }>({});
const [inputValue, setInputValue] = useState("");
const [isDisabled, setIsDisabled] = useState(true);

useEffect(() => {
setIsDisabled(Object.values(inputValues).some((val) => val.trim() === ""));
}, [inputValues]);
setIsDisabled(inputValue.trim() === "");
}, [inputValue]);

const handleChange = (key: string) => (value: string) => {
// console.log({ inputValues });
setInputValues((prev) => ({ ...prev, [key]: value }));
};

const onClick = () => {
// console.log("Inserting Note: ", inputValues);
insertFunction({
editor: activeEditor,
inputValues,
});
setInputValues({});
const handleInsert = () => {
if (label === "Footnote" || label === "Crossref") {
insertFunction(activeEditor, undefined, inputValue); // noteText as third param
} else {
insertFunction(activeEditor, inputValue); // Regular value
}
setInputValue("");
onClose();
};

return (
<>
{label === "Footnote" ? (
// For footnote with multiple fields
<>
<TextInput
placeholder="Text"
label="Text"
onChange={handleChange("ft")}
value={inputValues.ft || ""}
onChange={(val) => setInputValue(val)}
value={inputValue}
data-test-id="note-ft"
/>

<TextInput
placeholder="Origin Reference."
label="Orign Reference"
onChange={handleChange("fr")}
value={inputValues.fr || ""}
data-test-id="note-fr"
/>
<TextInput
placeholder="Quotation"
label="Quotation"
onChange={handleChange("fq")}
value={inputValues.fq || ""}
data-test-id="note-ftquot"
/>
<TextInput
placeholder="Content"
label="Content"
onChange={handleChange("fqa")}
value={inputValues.fqa || ""}
data-test-id="note-fqa"
/>
</>
) : label === "XRef" ? (
<>
<TextInput
placeholder="Note Title"
label="Title"
onChange={handleChange("title")}
value={inputValues.title || ""}
data-test-id="note-title"
/>
<TextInput
placeholder="Note Content"
label="Content"
onChange={handleChange("content")}
value={inputValues.content || ""}
data-test-id="note-content"
/>
<TextInput
placeholder="Author"
label="Author"
onChange={handleChange("author")}
value={inputValues.author || ""}
data-test-id="note-author"
/>
<TextInput
placeholder="Date"
label="Date"
onChange={handleChange("date")}
value={inputValues.date || ""}
data-test-id="note-date"
/>
</>
) : (
// For simple inputs like verse/chapter numbers
<TextInput
placeholder={placeholder ?? "Enter Value"}
label={label}
onChange={handleChange(label.toLowerCase())}
value={inputValues[label.toLowerCase()] || ""}
onChange={setInputValue}
value={inputValue}
data-test-id={`modal-${label.toLowerCase()}`}
type="number"
type={label === "Verse" || label === "Chapter" ? "number" : "text"}
/>
)}
<Button disabled={isDisabled} onClick={onClick}>
Confirm
</Button>
<button className="scribe-button" disabled={isDisabled} onClick={handleInsert}>
Insert
</button>
</>
);
};

type ButtonProps = {
export const Button: React.FC<{
"data-test-id"?: string;
children: ReactNode;
className?: string;
disabled?: boolean;
onClick: () => void;
title?: string;
};

export const Button: React.FC<ButtonProps> = ({
"data-test-id": dataTestId,
children,
className,
onClick,
disabled,
title,
}) => (
}> = ({ "data-test-id": dataTestId, children, className, onClick, disabled, title }) => (
<button
disabled={disabled}
className={`Button__root ${className}`}
className={`scribe-button ${className || ""}`}
onClick={onClick}
title={title}
aria-label={title}
Expand Down
74 changes: 74 additions & 0 deletions packages/scribe/src/components/Toolbar.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/* Toolbar.css */
.toolbar {
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 10;
display: flex;
align-items: center;
justify-content: flex-start;
background-color: #e5e7eb; /* equivalent to bg-gray-200 */
padding: 0.5rem; /* equivalent to px-2 py-2 */
}

.toolbar-buttons {
display: flex;
gap: 0.5rem; /* equivalent to space-x-2 */
}

.scribe-toolbar {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #f0f0f0;
padding: 8px;
border-bottom: 1px solid #ddd;
}

.scribe-toolbar-group {
display: flex;
gap: 8px;
position: relative;
}

.scribe-active {
background-color: #e0e0e0;
border-color: #aaa;
}

.scribe-dropdown {
position: absolute;
top: 100%;
left: 0;
background-color: white;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
z-index: 1000;
min-width: 180px;
margin-top: 4px;
}

.scribe-dropdown-item {
display: block;
width: 100%;
padding: 8px 12px;
text-align: left;
background: none;
border: none;
cursor: pointer;
}

.scribe-dropdown-item:hover {
background-color: #f5f5f5;
}

.scribe-status {
padding: 4px 8px;
background-color: #e8f5e9;
border-radius: 4px;
color: #388e3c;
font-size: 12px;
font-weight: 500;
}
Loading
Loading