diff --git a/ts_web/elements/viewer.ts b/ts_web/elements/viewer.ts index 0bfdb65..56ad083 100644 --- a/ts_web/elements/viewer.ts +++ b/ts_web/elements/viewer.ts @@ -12,6 +12,7 @@ import { } from "@design.estate/dees-element"; import { demoFunc } from "./viewer.demo.js"; import { DeDocument } from "./document.js"; +import "./page.js"; // Import DePage for thumbnail rendering import "@design.estate/dees-catalog"; @@ -91,6 +92,19 @@ export class DeDocumentViewer extends DeesElement { @state() accessor currentPageDisplay: string = "1 / 1"; + // Sidebar state + @state() + accessor showThumbnails: boolean = true; + + @state() + accessor sidebarWidth: number = 140; + + @state() + accessor isResizingSidebar: boolean = false; + + @state() + accessor thumbnailPages: number[] = []; + public static styles = [ cssManager.defaultStyles, css` @@ -107,6 +121,124 @@ export class DeDocumentViewer extends DeesElement { --dropdown-shadow: ${cssManager.bdTheme("0 4px 16px rgba(0,0,0,0.15)", "0 4px 16px rgba(0,0,0,0.4)")}; --slider-track: ${cssManager.bdTheme("#ddd", "#444")}; --slider-fill: ${cssManager.bdTheme("#0066cc", "#4d9fff")}; + --sidebar-min-width: 100px; + --sidebar-max-width: 300px; + } + + /* Sidebar Styles */ + .sidebar { + position: absolute; + left: 0; + top: var(--toolbar-height); + bottom: 0; + background: var(--toolbar-bg); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border-right: 1px solid var(--toolbar-border); + display: flex; + flex-direction: column; + z-index: 50; + box-sizing: border-box; + } + + .sidebar--collapsed { + width: 0 !important; + overflow: hidden; + border-right: none; + } + + .sidebar--resizing { + transition: none !important; + user-select: none; + } + + .sidebar__header { + padding: 10px 12px; + font-size: 11px; + font-weight: 600; + color: var(--text-secondary); + border-bottom: 1px solid var(--toolbar-border); + text-transform: uppercase; + letter-spacing: 0.5px; + flex-shrink: 0; + } + + .sidebar__thumbnails { + flex: 1; + overflow-y: auto; + overflow-x: hidden; + padding: 8px; + display: flex; + flex-direction: column; + gap: 12px; + } + + .thumbnail { + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; + cursor: pointer; + padding: 4px; + border-radius: 6px; + transition: background 0.15s ease; + flex-shrink: 0; + } + + .thumbnail:hover { + background: var(--button-hover); + } + + .thumbnail--active { + background: var(--button-active); + } + + .thumbnail--active .thumbnail__preview { + outline: 2px solid var(--accent-color); + outline-offset: 2px; + } + + .thumbnail__preview { + width: 100%; + aspect-ratio: 210 / 297; + background: ${cssManager.bdTheme("#fff", "#2a2a2a")}; + box-shadow: ${cssManager.bdTheme("0 1px 4px rgba(0,0,0,0.15)", "0 1px 4px rgba(0,0,0,0.4)")}; + border-radius: 2px; + overflow: hidden; + position: relative; + } + + .thumbnail__label { + font-size: 11px; + color: var(--text-secondary); + font-weight: 500; + } + + .sidebar__resize-handle { + position: absolute; + top: 0; + right: -4px; + bottom: 0; + width: 8px; + cursor: ew-resize; + background: transparent; + z-index: 60; + } + + .sidebar__resize-handle::after { + content: ''; + position: absolute; + top: 0; + left: 3px; + bottom: 0; + width: 2px; + background: transparent; + transition: background 0.15s ease; + } + + .sidebar__resize-handle:hover::after, + .sidebar--resizing .sidebar__resize-handle::after { + background: var(--accent-color); } .maincontainer { @@ -413,6 +545,11 @@ export class DeDocumentViewer extends DeesElement { overflow-y: scroll; overflow-x: auto; overscroll-behavior: contain; + transition: left 0.2s ease; + } + + .viewport--with-sidebar { + left: var(--current-sidebar-width, 140px); } .viewport--centered { @@ -429,6 +566,16 @@ export class DeDocumentViewer extends DeesElement { .spacing-slider-container { display: none; } + /* Collapse sidebar by default on tablet */ + .sidebar { + width: 0 !important; + } + .sidebar--collapsed { + width: 0 !important; + } + .viewport--with-sidebar { + left: 0 !important; + } `), // Phone styles cssManager.cssForPhone(css` @@ -453,13 +600,30 @@ export class DeDocumentViewer extends DeesElement { .controls__section { gap: 2px; } + /* Hide sidebar and toggle on phone */ + .sidebar { + display: none !important; + } + .sidebar-toggle { + display: none !important; + } + .viewport--with-sidebar { + left: 0 !important; + } `), ]; public render(): TemplateResult { + const viewportClasses = [ + "viewport", + this.zoomMode !== "auto" ? "viewport--centered" : "", + this.showThumbnails ? "viewport--with-sidebar" : "", + ].filter(Boolean).join(" "); + return html` -
-
+
+ ${this.renderSidebar()} +
${this.letterData ? html` + + + +
+ `; + } + + private getThumbnailScale(): number { + const previewWidth = this.sidebarWidth - 24; // Account for padding + return previewWidth / plugins.shared.A4_WIDTH; + } + private renderZoomControls(): TemplateResult { return html`
+ + + + +