Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b43baccd62 | |||
| 035c6ab621 | |||
| 3617caec1f | |||
| 9e879893af | |||
| c487ac341e | |||
| 393a235526 |
18
changelog.md
18
changelog.md
@@ -1,5 +1,23 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-12-11 - 2.2.3 - fix(contentinvoice)
|
||||
Use shared translation.TranslationKey type in DeContentInvoice.translateKey and remove local import
|
||||
|
||||
- Replaced local TranslationKey import with plugins.shared.translation.TranslationKey to ensure type consistency
|
||||
- Updated DeContentInvoice.translateKey parameter type to reference the shared translation type
|
||||
- Removed an unused type import from ts_web/elements/contentinvoice.ts
|
||||
|
||||
## 2025-12-11 - 2.2.0 - feat(viewer)
|
||||
Add pagination metadata and thumbnail offset rendering for viewer thumbnails
|
||||
|
||||
- Expose per-page pagination metadata (IPagePaginationInfo) from DeDocument during rendering (pageNumber, startOffset, contentLength).
|
||||
- DeDocument now collects pagination info while paginating and dispatches a 'pagination-complete' CustomEvent with pageCount and paginationInfo (bubbled & composed).
|
||||
- DeContentInvoice: add renderStartOffset and renderContentLength properties and applyOffsetTrimming to support rendering trimmed content (used for thumbnails).
|
||||
- DeDocumentViewer: listen for 'pagination-complete', store paginationInfo, and render thumbnail previews by mounting DeContentInvoice instances with precomputed offsets to produce accurate thumbnails.
|
||||
- Viewer: wire thumbnail generation to use per-page offsets so thumbnails show exactly the content slice for each page.
|
||||
- Demo data: extended demo invoice items in ts_shared/demoletter.ts to better exercise pagination and thumbnail rendering.
|
||||
- Remove registry override from .npmrc (previously pointed to registry.npmjs.org).
|
||||
|
||||
## 2025-12-11 - 2.1.1 - fix(viewer)
|
||||
Improve sidebar resizing UX and update deps
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@design.estate/dees-document",
|
||||
"version": "2.1.1",
|
||||
"version": "2.2.3",
|
||||
"private": false,
|
||||
"description": "A sophisticated framework for dynamically generating and rendering business documents like invoices with modern web technologies, featuring PDF creation, templating, and automation.",
|
||||
"main": "dist_ts_web/index.js",
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@design.estate/dees-document',
|
||||
version: '2.1.1',
|
||||
version: '2.2.3',
|
||||
description: 'A sophisticated framework for dynamically generating and rendering business documents like invoices with modern web technologies, featuring PDF creation, templating, and automation.'
|
||||
}
|
||||
|
||||
@@ -237,6 +237,86 @@ export const demoLetter: plugins.tsclass.finance.TInvoice = {
|
||||
vatPercentage: 0,
|
||||
position: 20,
|
||||
},
|
||||
{
|
||||
name: "Consulting Services",
|
||||
unitQuantity: 5,
|
||||
unitNetPrice: 150,
|
||||
unitType: "hours",
|
||||
vatPercentage: 19,
|
||||
position: 21,
|
||||
},
|
||||
{
|
||||
name: "Development Work",
|
||||
unitQuantity: 12,
|
||||
unitNetPrice: 120,
|
||||
unitType: "hours",
|
||||
vatPercentage: 19,
|
||||
position: 22,
|
||||
},
|
||||
{
|
||||
name: "Project Management",
|
||||
unitQuantity: 3,
|
||||
unitNetPrice: 180,
|
||||
unitType: "hours",
|
||||
vatPercentage: 19,
|
||||
position: 23,
|
||||
},
|
||||
{
|
||||
name: "Technical Support",
|
||||
unitQuantity: 8,
|
||||
unitNetPrice: 90,
|
||||
unitType: "hours",
|
||||
vatPercentage: 7,
|
||||
position: 24,
|
||||
},
|
||||
{
|
||||
name: "Documentation",
|
||||
unitQuantity: 4,
|
||||
unitNetPrice: 75,
|
||||
unitType: "hours",
|
||||
vatPercentage: 7,
|
||||
position: 25,
|
||||
},
|
||||
{
|
||||
name: "Code Review",
|
||||
unitQuantity: 6,
|
||||
unitNetPrice: 110,
|
||||
unitType: "hours",
|
||||
vatPercentage: 19,
|
||||
position: 26,
|
||||
},
|
||||
{
|
||||
name: "Testing & QA",
|
||||
unitQuantity: 10,
|
||||
unitNetPrice: 95,
|
||||
unitType: "hours",
|
||||
vatPercentage: 19,
|
||||
position: 27,
|
||||
},
|
||||
{
|
||||
name: "Infrastructure Setup",
|
||||
unitQuantity: 2,
|
||||
unitNetPrice: 250,
|
||||
unitType: "hours",
|
||||
vatPercentage: 19,
|
||||
position: 28,
|
||||
},
|
||||
{
|
||||
name: "Training Session",
|
||||
unitQuantity: 4,
|
||||
unitNetPrice: 200,
|
||||
unitType: "hours",
|
||||
vatPercentage: 7,
|
||||
position: 29,
|
||||
},
|
||||
{
|
||||
name: "Maintenance Package",
|
||||
unitQuantity: 1,
|
||||
unitNetPrice: 500,
|
||||
unitType: "units",
|
||||
vatPercentage: 19,
|
||||
position: 30,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@design.estate/dees-document',
|
||||
version: '2.1.1',
|
||||
version: '2.2.3',
|
||||
description: 'A sophisticated framework for dynamically generating and rendering business documents like invoices with modern web technologies, featuring PDF creation, templating, and automation.'
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
import * as plugins from "../plugins.js";
|
||||
|
||||
import { dedocumentSharedStyle } from "../style.js";
|
||||
import type { TranslationKey } from "../../ts_shared/translation.js";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
@@ -49,6 +48,13 @@ export class DeContentInvoice extends DeesElement {
|
||||
})
|
||||
accessor documentSettings: plugins.shared.interfaces.IDocumentSettings;
|
||||
|
||||
// Offset-based rendering properties for thumbnails
|
||||
@property({ type: Number })
|
||||
accessor renderStartOffset: number = null;
|
||||
|
||||
@property({ type: Number })
|
||||
accessor renderContentLength: number = null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
domtools.DomTools.setupDomTools();
|
||||
@@ -296,7 +302,7 @@ export class DeContentInvoice extends DeesElement {
|
||||
}
|
||||
}
|
||||
|
||||
public translateKey(key: TranslationKey): string {
|
||||
public translateKey(key: plugins.shared.translation.TranslationKey): string {
|
||||
return plugins.shared.translation.translate(
|
||||
this.documentSettings.languageCode,
|
||||
key
|
||||
@@ -307,7 +313,29 @@ export class DeContentInvoice extends DeesElement {
|
||||
_changedProperties: Map<string | number | symbol, unknown>
|
||||
) {
|
||||
super.firstUpdated(_changedProperties);
|
||||
this.attachInvoiceDom();
|
||||
await this.attachInvoiceDom();
|
||||
|
||||
// Apply offset-based trimming if specified (used for thumbnails)
|
||||
if (this.renderStartOffset !== null && this.renderContentLength !== null) {
|
||||
await this.applyOffsetTrimming();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply pre-computed pagination offsets for thumbnail rendering
|
||||
*/
|
||||
private async applyOffsetTrimming(): Promise<void> {
|
||||
// Trim from start
|
||||
if (this.renderStartOffset > 0) {
|
||||
await this.trimStartToOffset(this.renderStartOffset);
|
||||
}
|
||||
|
||||
// Trim from end to match content length
|
||||
let currentLength = await this.getContentLength();
|
||||
while (currentLength > this.renderContentLength) {
|
||||
await this.trimEndByOne();
|
||||
currentLength = await this.getContentLength();
|
||||
}
|
||||
}
|
||||
|
||||
private renderPaymentTerms(): TemplateResult {
|
||||
|
||||
@@ -26,6 +26,12 @@ import { DeContentInvoice } from "./contentinvoice.js";
|
||||
|
||||
import { demoFunc } from "./document.demo.js";
|
||||
|
||||
export interface IPagePaginationInfo {
|
||||
pageNumber: number;
|
||||
startOffset: number;
|
||||
contentLength: number;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"dedocument-dedocument": DeDocument;
|
||||
@@ -142,10 +148,12 @@ export class DeDocument extends DeesElement {
|
||||
null;
|
||||
public latestRenderedLetterData: plugins.tsclass.business.TLetter = null;
|
||||
public cleanupStore: any[] = [];
|
||||
public paginationInfo: IPagePaginationInfo[] = [];
|
||||
|
||||
public async renderDocument() {
|
||||
this.latestDocumentSettings = this.documentSettings;
|
||||
this.latestRenderedLetterData = this.letterData;
|
||||
this.paginationInfo = [];
|
||||
|
||||
const cleanUpStoreCurrentRender = [];
|
||||
const cleanUpStoreNextRender = [];
|
||||
@@ -198,7 +206,16 @@ export class DeDocument extends DeesElement {
|
||||
newPageOverflows = await newPage.checkOverflow();
|
||||
}
|
||||
currentContentOffset = await currentContent.getContentLength();
|
||||
const pageStartOffset = overallContentOffset;
|
||||
overallContentOffset = overallContentOffset + currentContentOffset;
|
||||
|
||||
// Track pagination info for this page
|
||||
this.paginationInfo.push({
|
||||
pageNumber: pageCounter,
|
||||
startOffset: pageStartOffset,
|
||||
contentLength: currentContentOffset,
|
||||
});
|
||||
|
||||
if (trimmed === 0) {
|
||||
complete = true;
|
||||
}
|
||||
@@ -234,6 +251,16 @@ export class DeDocument extends DeesElement {
|
||||
}
|
||||
}
|
||||
this.adjustDePageScaling();
|
||||
|
||||
// Emit event with pagination info for thumbnails
|
||||
this.dispatchEvent(new CustomEvent('pagination-complete', {
|
||||
detail: {
|
||||
pageCount: pageCounter,
|
||||
paginationInfo: this.paginationInfo,
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}));
|
||||
}
|
||||
|
||||
async updated(
|
||||
|
||||
@@ -11,8 +11,9 @@ import {
|
||||
type TemplateResult,
|
||||
} from "@design.estate/dees-element";
|
||||
import { demoFunc } from "./viewer.demo.js";
|
||||
import { DeDocument } from "./document.js";
|
||||
import { DeDocument, type IPagePaginationInfo } from "./document.js";
|
||||
import "./page.js"; // Import DePage for thumbnail rendering
|
||||
import "./contentinvoice.js"; // Import DeContentInvoice for thumbnail content
|
||||
|
||||
import "@design.estate/dees-catalog";
|
||||
|
||||
@@ -105,6 +106,9 @@ export class DeDocumentViewer extends DeesElement {
|
||||
@state()
|
||||
accessor thumbnailPages: number[] = [];
|
||||
|
||||
@state()
|
||||
accessor paginationInfo: IPagePaginationInfo[] = [];
|
||||
|
||||
// Zoom animation
|
||||
private zoomAnimationId: number | null = null;
|
||||
|
||||
@@ -667,8 +671,10 @@ export class DeDocumentViewer extends DeesElement {
|
||||
<div class="${sidebarClasses}" style="width: ${this.sidebarWidth}px;">
|
||||
<div class="sidebar__header">Pages</div>
|
||||
<div class="sidebar__thumbnails">
|
||||
${this.thumbnailPages.map(
|
||||
(_, i) => html`
|
||||
${this.thumbnailPages.map((_, i) => {
|
||||
const pageInfo = this.paginationInfo[i];
|
||||
|
||||
return html`
|
||||
<div
|
||||
class="thumbnail ${currentPage === i + 1 ? "thumbnail--active" : ""}"
|
||||
@click=${() => this.scrollToPage(i + 1)}
|
||||
@@ -689,13 +695,20 @@ export class DeDocumentViewer extends DeesElement {
|
||||
.documentSettings=${this.documentSettings}
|
||||
.pageNumber=${i + 1}
|
||||
.pageTotalNumber=${this.thumbnailPages.length}
|
||||
></dedocument-page>
|
||||
>${pageInfo ? html`
|
||||
<dedocument-contentinvoice
|
||||
.letterData=${this.letterData as unknown as plugins.tsclass.finance.TInvoice}
|
||||
.documentSettings=${this.documentSettings}
|
||||
.renderStartOffset=${pageInfo.startOffset}
|
||||
.renderContentLength=${pageInfo.contentLength}
|
||||
></dedocument-contentinvoice>
|
||||
` : null}</dedocument-page>
|
||||
</div>
|
||||
</div>
|
||||
<span class="thumbnail__label">${i + 1}</span>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
`;
|
||||
})}
|
||||
</div>
|
||||
<div
|
||||
class="sidebar__resize-handle"
|
||||
@@ -1216,6 +1229,15 @@ export class DeDocumentViewer extends DeesElement {
|
||||
setTimeout(() => this.updateDisplayZoom(), 200);
|
||||
}
|
||||
|
||||
// Listen for pagination-complete event from DeDocument
|
||||
this.addEventListener('pagination-complete', (e: CustomEvent) => {
|
||||
this.paginationInfo = e.detail.paginationInfo;
|
||||
const pageCount = e.detail.pageCount;
|
||||
if (pageCount !== this.thumbnailPages.length) {
|
||||
this.thumbnailPages = Array.from({ length: pageCount }, (_, i) => i);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle viewport resize and scroll
|
||||
const viewport = this.shadowRoot?.querySelector(".viewport");
|
||||
if (viewport) {
|
||||
|
||||
Reference in New Issue
Block a user