@htmlbricks/hb-page-invoice
v0.76.5
Published
Printable invoice page: shows seller and buyer from headers, invoice date and serial, line items in hb-table with price, quantity, VAT and row totals, plus subtotal, tax and grand total in the invoice currency. When printer is not yes, offers print and op
Readme
hb-page-invoice — integrator guide
Category: commerce · Tags: commerce, invoice, page · Package: @htmlbricks/hb-page-invoice
Summary
Printable invoice layout: seller and buyer blocks from headers, invoice date and serial, line items rendered inside hb-table (price per unit with currency symbol, quantity, line subtotal, VAT amount with rate, line total), and a footer with subtotal, total tax, and grand total. Currency symbol follows headers.country after headers is deserialized (Italy and EU use €, US uses $).
When printer is not yes, the host shows two actions (debounced): print (opens a helper window, injects another hb-page-invoice with printer="yes", loads the bundle, then triggers the browser print dialog) and open in window (fullscreen-style preview in a new window with the same bundle). When printer is yes, those toolbar buttons are hidden—suitable for print-only or embedded previews.
The component registers hb-table at runtime (addComponent for @htmlbricks/hb-table). Nested bundle dependencies include hb-dialog, hb-dialogform, hb-form, many hb-input-* components, hb-paginate, hb-tooltip, and others as listed in extra/docs.ts.
If headers.from or headers.to is missing, the component does not render the invoice body (it shows a minimal error state).
Styling (Bulma)
Markup uses Bulma container, columns / column, and button is-light for the toolbar. Bootstrap Icons are loaded from the CDN via <svelte:head> for the print and fullscreen icons.
Theme via --bulma-* on the host or ancestors; see Bulma CSS variables and extra/docs.ts for defaults.
| Variable | Purpose |
|----------|---------|
| --bulma-text | Default text for headings, addresses, descriptions, and totals. |
| --bulma-border | Optional rules if you extend layout with custom CSS. |
| --bulma-scheme-main | Page background inside the host. |
| --bulma-block-spacing | Vertical block spacing for the invoice section. |
CSS parts
None.
HTML slots
None.
Attributes (snake_case; string values in HTML)
Web component attributes are strings. Pass structured data as JSON strings for headers and items.
| Attribute | Required | Description |
|-----------|----------|-------------|
| id | No | Optional host id (typed on Component; use as needed for DOM or tests). |
| style | No | Optional inline host style string (typed on Component). |
| printer | No | "yes" or "no" (default no). "yes" hides the print / open-in-window toolbar. |
| headers | No | JSON string — see Headers object below. Without valid from / to, the template shows the error branch. |
| items | No | JSON string — array of Item objects below (defaults to [] in the implementation). |
Deserialization and defaults
When headers arrives as a string, it is JSON.parse’d. If date is absent after parse, it is set to the current date. If category is absent, it defaults to "items". If country is absent, it defaults to "it", which also drives the default currency symbol (€ for it / eu, $ for us).
When items is a string, it is parsed to an array.
Boolean-like props follow project conventions: use yes / no for printer in HTML.
Events
None (Events is an empty object in types/webcomponent.type.d.ts).
Data model (TypeScript)
Authoring types live in types/webcomponent.type.d.ts.
Item (IItem)
| Field | Type | Notes |
|-------|------|--------|
| desc | string | Line description (required). |
| unitaryPrice | number | Unit price before tax (required). |
| taxPercentage | number | VAT rate as a percentage (e.g. 22 for 22%) (required). |
| quantity | number | Optional; defaults to 1 in totals and table if omitted. |
| unit | string | Optional unit label; otherwise the price column shows a generic “unità” segment. |
| discount | object | Optional. Shape: type: "gross" \| "item", optional includeVat?: boolean. Present in types and examples; line and footer totals in the current markup sum unitaryPrice * quantity and tax on that amount—they do not subtract this discount object yet. |
Company (ICompany)
Used for from (with extra fields) and to.
| Field | Type | Notes |
|-------|------|--------|
| piva | string | Tax / company id (labelled as VAT in the Italian UI). |
| name | string | Legal or trading name. |
| address | string | Address block. |
| email | string | Email. |
| phone | string | Phone. |
| iban | string | Optional (not shown in the default template). |
Seller (headers.from)
Extends ICompany with:
| Field | Type | Notes |
|-------|------|--------|
| logo | string | Image URL for the header logo. |
| shortName | string | Short name beside the logo. |
Headers (IHeaders)
| Field | Type | Notes |
|-------|------|--------|
| serial | string | Invoice number (required). |
| from | Seller | Required. |
| to | ICompany | Required. |
| country | "it" | "eu" | "us" | Optional; affects default currency when parsed from JSON. |
| date | Date | Optional in object form; set on parse if missing. Displayed as DD/MM/YY via Day.js. |
| expirationDate | Date | Optional in types; not rendered in the current template. |
| category | "items" | "services" | Optional; defaults to items when parsed from JSON; not shown in the current template. |
Root component props (Component)
export type Component = {
id?: string;
style?: string;
printer?: "yes" | "no";
items?: IItem[] | string;
headers?: IHeaders | string;
};Behavior notes
- Table: Child
hb-tableis used withdisablepagination="yes"androws/headerspassed as JSON strings built from the computed row model (Italian column labels in the built-in headers: e.g. “descrizione”, “prezzo”, “quantità”, “iva”, “totale”). - Totals: Subtotal is the sum of
unitaryPrice * (quantity ?? 1)overitems. Tax total is the sum of VAT on each line (rate × line base), rounded to two decimals at the sum level. Grand total is subtotal + tax total. - Print helpers: Consumer apps can reuse
printInvoice/OpenInvoiceWindowfromlibs/utils.ts; they open a window, write minimal HTML with anhb-page-invoiceinstance, and load@htmlbricks/hb-page-invoice@<version>/main.iife.jsfrom jsDelivr (or a localhost Storybook path when the page URL containslocalhost).
Minimal HTML example
<hb-page-invoice
printer="no"
headers='{"serial":"INV-1","date":"2026-04-17T00:00:00.000Z","from":{"piva":"IT123","name":"Seller Srl","address":"Via Roma 1","email":"[email protected]","phone":"+39 02 0000000","logo":"https://example.com/logo.svg","shortName":"Seller"},"to":{"piva":"IT456","name":"Buyer SpA","address":"Corso Italia 2","email":"[email protected]","phone":"+39 011 0000000"}}'
items='[{"desc":"Consulting","unitaryPrice":100,"taxPercentage":22,"quantity":1}]'
></hb-page-invoice>Escape quotes inside JSON attributes as required by your templating environment.
Related files
component.wc.svelte— layout, totals,hb-tableintegration, toolbar.types/webcomponent.type.d.ts— publicComponent/Eventsand invoice shapes.extra/docs.ts— Storybook args,styleSetup, examples, dependency tree.
