diff --git a/src/lib/components/forms/EditNote.svelte b/src/lib/components/forms/EditNote.svelte index 314afe99d..ba3bbc60e 100644 --- a/src/lib/components/forms/EditNote.svelte +++ b/src/lib/components/forms/EditNote.svelte @@ -46,13 +46,7 @@ Positioning and generating coordinates should happen outside of this form. } -
+
- - diff --git a/src/lib/components/viewer/AnnotationLayer.svelte b/src/lib/components/viewer/AnnotationLayer.svelte index 58f3206cc..ae8b6412e 100644 --- a/src/lib/components/viewer/AnnotationLayer.svelte +++ b/src/lib/components/viewer/AnnotationLayer.svelte @@ -27,6 +27,7 @@ Assumes it's a child of a ViewerContext getCurrentMode, getCurrentNote, getDocument, + getNewNote, isEmbedded, } from "$lib/components/viewer/ViewerContext.svelte"; import { getNotes, getViewerHref } from "$lib/utils/viewer"; @@ -40,8 +41,8 @@ Assumes it's a child of a ViewerContext const embed = isEmbedded(); const mode = getCurrentMode(); const currentNote = getCurrentNote(); + const newNote = getNewNote(); - let newNote: Nullable & BBox> = null; let drawStart: Nullable<[x: number, y: number]> = null; let drawing = false; @@ -49,7 +50,7 @@ Assumes it's a child of a ViewerContext $: notes = getNotes(document)[page_number]?.filter((note) => !isPageLevel(note)) ?? []; $: writing = $mode === "annotating"; - $: activeNote = Boolean($currentNote) || (Boolean(newNote) && !drawing); + $: activeNote = Boolean($currentNote) || (Boolean($newNote) && !drawing); $: edit_page_note = writing && Boolean($currentNote) && @@ -70,18 +71,20 @@ Assumes it's a child of a ViewerContext } function startDrawingBox(e: PointerEvent) { - if ($currentNote || newNote) return; + closeNote(); drawing = true; $currentNote = null; + $newNote = null; const [x, y] = getLayerPosition(e); drawStart = [x, y]; // when starting, the note is a 0px shape - newNote = { + $newNote = { x1: x, x2: x, y1: y, y2: y, + page_number, }; } @@ -94,24 +97,25 @@ Assumes it's a child of a ViewerContext const movingRight = x > startX; const movingDown = y > startY; - const x1 = movingRight ? newNote.x1 : x; - const x2 = movingRight ? x : newNote.x2; - const y1 = movingDown ? newNote.y1 : y; - const y2 = movingDown ? y : newNote.y2; + const x1 = movingRight ? $newNote.x1 : x; + const x2 = movingRight ? x : $newNote.x2; + const y1 = movingDown ? $newNote.y1 : y; + const y2 = movingDown ? y : $newNote.y2; - newNote = { + $newNote = { x1, x2, y1, y2, + page_number, }; } function finishDrawingBox(e: PointerEvent) { if (!newNote || !drawing) return; - newNote = { - ...newNote, + $newNote = { + ...$newNote, // now initialize some note values page_number, title: "", @@ -123,17 +127,27 @@ Assumes it's a child of a ViewerContext drawing = false; } + function positionNote(note: BBox, offset: number) { + const isLastPage = page_number + 1 === document.page_count; + if (isLastPage && note.y2 > 0.5) { + return `bottom: calc(calc(100% - ${note.y1 * 100}%) + ${offset}rem);`; + } else { + return `top: calc(${note.y2 * 100}% + ${offset}rem);`; + } + } + function openNote(e: MouseEvent, note: NoteType) { const target = e.target as HTMLAnchorElement; const href = target?.href || getViewerHref({ document, note, mode: $mode, embed }); $currentNote = note; + $newNote = null; pushState(href, { note }); } function closeNote() { drawing = false; - newNote = null; + $newNote = null; $currentNote = null; const href = getViewerHref({ document, mode: $mode, embed }); pushState(href, {}); @@ -192,6 +206,7 @@ Assumes it's a child of a ViewerContext {note.title} - {#if note.id === $currentNote?.id} + {/each} + + {#if $currentNote && !Boolean($newNote) && $currentNote.page_number === page_number} +
{#if writing} -
- onEditNoteSuccess(e, note)} - /> -
+ onEditNoteSuccess(e, $currentNote)} + /> {:else} -
- -
+ {/if} - {/if} - {/each} +
+ {/if} - {#if newNote} + {#if $newNote && $newNote.page_number === page_number}
{#if !drawing}
onEditNoteSuccess(e, undefined)} /> @@ -278,6 +296,11 @@ Assumes it's a child of a ViewerContext pointer-events: all; } + /* .notes.activeNote { + cursor: default; + pointer-events: all; + } */ + .notes :global(*) { pointer-events: all; } @@ -294,37 +317,31 @@ Assumes it's a child of a ViewerContext scroll-margin-top: 6rem; } - .note-reading { + .note { position: absolute; left: -1.5rem; width: 44rem; max-width: 100%; z-index: var(--z-note); + background: var(--white); + border: 1px solid var(--gray-2); + box-shadow: var(--shadow-2); } - .note-form { - position: absolute; - left: -1.5rem; - width: 44rem; - max-width: 100%; - z-index: var(--z-note); - pointer-events: all; - } - - .notes.activeNote { - cursor: auto; - pointer-events: none; + .card { + padding: 1rem; } .box { position: absolute; - border: 1px solid var(--note-private); + border: 4px solid transparent; + border-color: color-mix(in srgb, var(--note-private), var(--gray-4)); background: var(--note-private); opacity: 0.75; mix-blend-mode: multiply; pointer-events: stroke; padding: 0.5rem; - border-radius: 0.25rem; + border-radius: 0.125rem; /* if we make boxes editable cursor: grab; @@ -334,44 +351,49 @@ Assumes it's a child of a ViewerContext } .box.public { - border-color: var(--note-public); + border-color: color-mix(in srgb, var(--note-public), var(--gray-4)); background: var(--note-public); } .box.organization { - border-color: var(--note-org); + border-color: color-mix(in srgb, var(--note-org), var(--gray-4)); background: var(--note-org); } .box.private { - border-color: var(--note-private); + border-color: color-mix(in srgb, var(--note-private), var(--gray-4)); background: var(--note-private); } a.note-highlight { - border-radius: 0.25rem; + border: 4px solid transparent; + border-radius: 0.125rem; color: transparent; position: absolute; opacity: 0.5; pointer-events: all; mix-blend-mode: multiply; - - border: 0.5rem solid var(--gray-4); /* pointer-events: none; */ } a.note-highlight.public { background-color: var(--note-public); - border-color: var(--note-public); + &.active { + border-color: color-mix(in srgb, var(--yellow-3), var(--gray-4)); + } } a.note-highlight.private { background-color: var(--note-private); - border-color: var(--note-private); + &.active { + border-color: color-mix(in srgb, var(--note-private), var(--gray-4)); + } } a.note-highlight.organization { background-color: var(--note-org); - border-color: var(--note-org); + &.active { + border-color: color-mix(in srgb, var(--note-org), var(--gray-4)); + } } diff --git a/src/lib/components/viewer/Note.svelte b/src/lib/components/viewer/Note.svelte index 1e28750c6..e4a6ac980 100644 --- a/src/lib/components/viewer/Note.svelte +++ b/src/lib/components/viewer/Note.svelte @@ -251,43 +251,13 @@ diff --git a/src/lib/components/viewer/Notes.svelte b/src/lib/components/viewer/Notes.svelte index b3c1f8edc..8585a41b3 100644 --- a/src/lib/components/viewer/Notes.svelte +++ b/src/lib/components/viewer/Notes.svelte @@ -26,13 +26,13 @@ Assumes it's a child of a ViewerContext
{#each notes as note} {:else} @@ -51,24 +51,39 @@ Assumes it's a child of a ViewerContext display: flex; flex-flow: column; align-items: center; - gap: 3rem; + gap: 2rem; margin: 0 auto; max-width: 38.0625rem; + padding: 2rem 0; + } + + .card { + border: 1px solid var(--gray-2); + box-shadow: var(--shadow-2); } .note-wrapper { display: flex; flex-direction: column; - gap: 0.75rem; } - h4, - h4 a { - text-decoration: none; - font-weight: var(--font-regular); + header { + display: flex; + padding: 0.5rem; + gap: 1rem; + justify-content: space-between; + align-items: center; + align-self: stretch; } - h4 a:hover { - text-decoration: underline; + a.pageNumber { + flex: 0 0 auto; + color: var(--gray-4, #5c717c); + font-size: var(--font-sm); + font-weight: var(--font-regular); + text-decoration: none; + &:hover { + text-decoration: underline; + } } diff --git a/src/lib/components/viewer/ViewerContext.svelte b/src/lib/components/viewer/ViewerContext.svelte index 715a4dcfc..c330bdd3b 100644 --- a/src/lib/components/viewer/ViewerContext.svelte +++ b/src/lib/components/viewer/ViewerContext.svelte @@ -11,6 +11,7 @@ layouts, stories, and tests. Note, ViewerMode, Zoom, + BBox, } from "$lib/api/types"; import { afterNavigate } from "$app/navigation"; @@ -59,7 +60,11 @@ layouts, stories, and tests. return getContext("embed") ?? false; } - export function getCurrentNote(): Readable { + export function getNewNote(): Writable & BBox>> { + return getContext("newNote"); + } + + export function getCurrentNote(): Writable> { return getContext("currentNote"); } @@ -119,6 +124,7 @@ layouts, stories, and tests. setContext("asset_url", asset_url); setContext("embed", embed); setContext("query", query); + setContext("newNote", writable(null)); setContext("currentNote", writable(note)); setContext("currentPage", writable(page)); setContext("currentMode", writable(mode)); @@ -170,9 +176,10 @@ layouts, stories, and tests. afterNavigate(() => { // refresh stores from URL state const { hash } = $pageStore.url; + const hashPage = pageFromHash(hash); $currentMode = mode; $currentNote = $currentDoc.notes.find(noteMatchingPageHash) ?? null; - if (shouldPaginate(mode)) { + if (shouldPaginate(mode) && $currentPage !== hashPage) { scrollToHash(hash); } }); diff --git a/src/lib/components/viewer/stories/Viewer.stories.svelte b/src/lib/components/viewer/stories/Viewer.stories.svelte index 3d66f8116..98ef6bf6c 100644 --- a/src/lib/components/viewer/stories/Viewer.stories.svelte +++ b/src/lib/components/viewer/stories/Viewer.stories.svelte @@ -65,6 +65,18 @@ + ({ ...note, edit_access: true })), + }, + }} +/>