Add PDF editor toolbar with navigation and zoom controls
Introduced a `SenderPdfImageEditorToolbar` component to enhance the PDF editor with navigation, zoom, and action controls. Updated `SenderPdfImageEditor.razor` to display the toolbar when `PageCount > 0`. Added parameters (`CurrentPage`, `TotalPages`, `ZoomPercent`) and computed properties to manage and display toolbar state dynamically. Styled the toolbar in `envelope-viewer.css` with grid-based layout, responsive design, and hover/disabled states for buttons. Adjusted styles for smaller screens to improve usability.
This commit is contained in:
@@ -5,13 +5,20 @@
|
||||
@inject IStringLocalizer<Resource> UiLocalizer
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
@if (PageCount > 0)
|
||||
{
|
||||
<SenderPdfImageEditorToolbar CurrentPage="1"
|
||||
TotalPages="@PageCount"
|
||||
ZoomPercent="112" />
|
||||
}
|
||||
|
||||
<div class="pdf-editor-wrapper sender-image-editor sender-editor-pdf-viewer"
|
||||
style="cursor: @(IsPlacementMode ? "crosshair" : (_isDragging ? "grabbing" : "default"));"
|
||||
@onclick="HandleClickAsync"
|
||||
@onmousemove="OnEditorMouseMoveAsync"
|
||||
@onmouseup="OnEditorMouseUp"
|
||||
@onmouseleave="OnEditorMouseUp">
|
||||
@if (PageCount <= 0)
|
||||
@if (PageCount <= 0)
|
||||
{
|
||||
<div class="sender-image-editor__empty">@L("SenderEditor_NoPagesToDisplay", "Keine Seiten zur Anzeige verfügbar.")</div>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
<div class="sender-image-toolbar" @onclick:stopPropagation="true">
|
||||
<div class="sender-image-toolbar__group sender-image-toolbar__group--nav" role="group" aria-label="Page navigation">
|
||||
<button type="button" class="sender-image-toolbar__icon-btn" title="First page" disabled>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M8 6V18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
||||
<path d="M16 7L11 12L16 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button type="button" class="sender-image-toolbar__icon-btn" title="Previous page" disabled>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M15 7L10 12L15 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div class="sender-image-toolbar__value-box" aria-hidden="true">
|
||||
<span>@CurrentPageDisplay of @TotalPagesDisplay</span>
|
||||
</div>
|
||||
|
||||
<button type="button" class="sender-image-toolbar__icon-btn sender-image-toolbar__icon-btn--caret" title="Page selector" disabled>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M6 9L12 15L18 9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button type="button" class="sender-image-toolbar__icon-btn" title="Next page" disabled>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M9 7L14 12L9 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button type="button" class="sender-image-toolbar__icon-btn" title="Last page" disabled>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M16 6V18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
||||
<path d="M8 7L13 12L8 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="sender-image-toolbar__group sender-image-toolbar__group--zoom" role="group" aria-label="Zoom controls">
|
||||
<button type="button" class="sender-image-toolbar__icon-btn" title="Zoom out" disabled>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M6 12H18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div class="sender-image-toolbar__value-box" aria-hidden="true">
|
||||
<span>@ZoomPercentDisplay%</span>
|
||||
</div>
|
||||
|
||||
<button type="button" class="sender-image-toolbar__icon-btn sender-image-toolbar__icon-btn--caret" title="Zoom presets" disabled>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M6 9L12 15L18 9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button type="button" class="sender-image-toolbar__icon-btn" title="Zoom in" disabled>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M12 6V18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
||||
<path d="M6 12H18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="sender-image-toolbar__group sender-image-toolbar__group--actions" role="group" aria-label="Document actions">
|
||||
<button type="button" class="sender-image-toolbar__icon-btn" title="Print" disabled>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M7 9V4H17V9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
<rect x="5" y="9" width="14" height="8" rx="2" stroke="currentColor" stroke-width="2" />
|
||||
<path d="M7 14H17V20H7V14Z" stroke="currentColor" stroke-width="2" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button type="button" class="sender-image-toolbar__icon-btn" title="Download PDF" disabled>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M12 4V14" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
||||
<path d="M8 10L12 14L16 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
<path d="M5 18H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public int CurrentPage { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public int TotalPages { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public int ZoomPercent { get; set; } = 112;
|
||||
|
||||
private int CurrentPageDisplay => CurrentPage > 0 ? CurrentPage : 0;
|
||||
private int TotalPagesDisplay => TotalPages > 0 ? TotalPages : 0;
|
||||
private int ZoomPercentDisplay => ZoomPercent > 0 ? ZoomPercent : 100;
|
||||
}
|
||||
@@ -61,6 +61,80 @@
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.sender-image-toolbar {
|
||||
max-width: 980px;
|
||||
margin: 0 auto 1rem;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto;
|
||||
gap: 0.75rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sender-image-toolbar__group {
|
||||
min-height: 4.8rem;
|
||||
background: #ffffff;
|
||||
border: 1px solid #d6deef;
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.6rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.3rem;
|
||||
box-shadow: 0 6px 16px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.sender-image-toolbar__group--nav {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.sender-image-toolbar__group--zoom {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sender-image-toolbar__group--actions {
|
||||
justify-content: center;
|
||||
gap: 0.45rem;
|
||||
padding-inline: 0.75rem;
|
||||
}
|
||||
|
||||
.sender-image-toolbar__icon-btn {
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
border: 0;
|
||||
border-radius: 0.45rem;
|
||||
background: transparent;
|
||||
color: #1f2a44;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.sender-image-toolbar__icon-btn:disabled {
|
||||
opacity: 0.42;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.sender-image-toolbar__icon-btn--caret {
|
||||
width: 2.1rem;
|
||||
}
|
||||
|
||||
.sender-image-toolbar__value-box {
|
||||
min-width: 9rem;
|
||||
height: 2.5rem;
|
||||
border: 1px solid #d5dceb;
|
||||
border-radius: 0.45rem;
|
||||
background: #f8fafc;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 0 0.8rem;
|
||||
color: #233252;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
.sender-image-editor__pages {
|
||||
max-width: 980px;
|
||||
margin: 0 auto;
|
||||
@@ -1174,6 +1248,19 @@ body.resizing {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
.sender-image-toolbar {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.sender-image-toolbar__group {
|
||||
min-height: 3.9rem;
|
||||
}
|
||||
|
||||
.sender-image-toolbar__value-box {
|
||||
min-width: 7.5rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.pdf-thumbnails {
|
||||
width: 180px;
|
||||
border-radius: 0 0 0 16px;
|
||||
|
||||
Reference in New Issue
Block a user