feat: add local OneNote and ONEPKG reader
This commit is contained in:
70
src/components/FileDropZone.tsx
Normal file
70
src/components/FileDropZone.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import { useRef, useState, type ChangeEvent, type DragEvent } from 'react';
|
||||
|
||||
interface FileDropZoneProps {
|
||||
disabled?: boolean;
|
||||
onFile(file: File): void;
|
||||
}
|
||||
|
||||
export function FileDropZone({ disabled = false, onFile }: FileDropZoneProps) {
|
||||
const input = useRef<HTMLInputElement>(null);
|
||||
const [dragging, setDragging] = useState(false);
|
||||
|
||||
const selectFile = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
const file = event.target.files?.[0];
|
||||
event.target.value = '';
|
||||
if (file) onFile(file);
|
||||
};
|
||||
|
||||
const dropFile = (event: DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
setDragging(false);
|
||||
if (disabled) return;
|
||||
const file = event.dataTransfer.files[0];
|
||||
if (file) onFile(file);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`drop-zone${dragging ? ' drop-zone--active' : ''}`}
|
||||
onDragEnter={(event) => {
|
||||
event.preventDefault();
|
||||
if (!disabled) setDragging(true);
|
||||
}}
|
||||
onDragOver={(event) => event.preventDefault()}
|
||||
onDragLeave={(event) => {
|
||||
if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {
|
||||
setDragging(false);
|
||||
}
|
||||
}}
|
||||
onDrop={dropFile}
|
||||
data-testid="file-drop-zone"
|
||||
>
|
||||
<p className="drop-zone__eyebrow">Private, local-first reader</p>
|
||||
<h2>Open a OneNote file</h2>
|
||||
<p>
|
||||
Inspect a <code>.one</code> section or <code>.onepkg</code> notebook
|
||||
package without sending it to a server.
|
||||
</p>
|
||||
<input
|
||||
ref={input}
|
||||
className="visually-hidden"
|
||||
type="file"
|
||||
accept=".one,.onepkg"
|
||||
disabled={disabled}
|
||||
onChange={selectFile}
|
||||
aria-label="Choose a OneNote file"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="primary-button"
|
||||
disabled={disabled}
|
||||
onClick={() => input.current?.click()}
|
||||
>
|
||||
Choose OneNote file
|
||||
</button>
|
||||
<span className="drop-zone__hint">
|
||||
or drop one .one or .onepkg file here
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user