Skip to content

POS Receipt Slip

An infinite/auto height receipt slip (80mm width) for a cafe diner featuring an SVG bear logo, 20 line items with Thai typography, subtotals, and 7% tax calculations.

Source Code (receipt.ts)
typescript
import { MheePDF, Table, Text, PDFType0FontObject } from "mheepdf";

// 1. Load TrueType Fonts (TTF) for multilingual rendering using HTTP URLs
const fontRegular = await PDFType0FontObject.fromUrl("/resources/fonts/THSarabunNew.ttf");
const fontBold = await PDFType0FontObject.fromUrl("/resources/fonts/THSarabunNew Bold.ttf");
const fontSans = await PDFType0FontObject.fromUrl("/resources/fonts/GoogleSans_17pt-Regular.ttf");

// 2. Initialize MheePDF Document with 72mm printable width (for 80mm thermal paper) and auto height
// 72mm = 72 * (72 / 25.4) = 204.09 pt
const width = 72 * (72 / 25.4);
export const pdf = new MheePDF({
  pageSize: [width, "auto"],
  margin: 10,
  defaultFont: fontRegular,
  fonts: [fontRegular, fontBold, fontSans],
  defaultFontSize: 8,
  defaultLineHeight: 12,
  compress: false,
});

// 3. Define Cute Bear Logo in SVG format
const svgLogo = `
<svg width="128" height="128" style="enable-background:new 0 0 128 128;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <g>
    <g>
      <path d="M127.55,66.02c-0.51-8.7-2.97-17.53-7.01-25.55c0.14-0.18,0.27-0.37,0.4-0.56l0.39-0.56 c0.9-1.42,1.61-2.95,2.24-4.5c2.88-7.21,2.94-15.27-0.69-21.16c-2.56-4.17-12.73-14.98-28.77-5.85c-3.78,2.16-7.29,2.3-9.29,2.14 c-6.68-2.03-13.79-3.07-20.84-3.06c-7.68-0.02-15.43,1.21-22.63,3.62c-2.02,0.14-5.47-0.05-9.15-2.15 c-16.04-9.14-26.2,1.68-28.78,5.85c-1.11,1.8-1.94,4-2.37,6.07C0.26,24.26,0.6,28.65,1.75,32.5c0.62,2.05,1.53,3.98,2.49,5.9 c0.62,1.27,1.27,2.53,2.06,3.69c0.08,0.13,0.14,0.25,0.21,0.37C3.05,49.94,0.9,58.03,0.44,66.02 c-0.95,16.27,1.9,32.65,15.06,43.97c7.29,6.26,16.35,10.52,25.7,12.81c3.55,0.88,12.72,2.92,22.35,2.92 c9.61,0,19.69-2.04,23.24-2.92c9.34-2.29,18.41-6.54,25.7-12.81C125.65,98.68,128.52,82.29,127.55,66.02z" style="fill:#855C52;"/>
      <ellipse cx="28.25" cy="70.8" rx="6.76" ry="8.1" style="fill:#2F2F2F;"/>
      <path d="M63.68,109.12c-13.41,0-24.26-4.85-24.26-19.76c0-14.92,10.85-27.01,24.26-27.01 c13.4,0,24.28,12.09,24.28,27.01C87.96,104.27,77.08,109.12,63.68,109.12z" style="fill:#FFFFFF;"/>
      <path d="M99.03,78.9c-3.72,0-6.76-3.62-6.76-8.09c0-4.48,3.04-8.1,6.76-8.1c3.74,0,6.77,3.63,6.77,8.1 C105.8,75.28,102.77,78.9,99.03,78.9z" style="fill:#2F2F2F;"/>
      <path d="M63.68,89.04c6.36,0,11.52-4.15,11.52-9.27c0-5.13-5.16-9.27-11.52-9.27s-11.5,4.15-11.5,9.27 C52.18,84.89,57.32,89.04,63.68,89.04z" style="fill:#2F2F2F;"/>
      <path d="M73.94,94.87c-0.13,0.18-3.15,4.34-10.26,4.34c-7.06,0-10.09-4.13-10.23-4.34 c-0.7-1-2.07-1.27-3.09-0.58c-1.02,0.69-1.28,2.08-0.59,3.09c0.17,0.26,4.36,6.27,13.91,6.27c9.56,0,13.75-6.02,13.93-6.27 c0.68-1.01,0.43-2.37-0.58-3.07C76.03,93.62,74.64,93.88,73.94,94.87z" style="fill:#2F2F2F;"/>
    </g>
    <path d="M29.62,21.2c-1.27,1.34-3.22,2.54-4.15,3.38c-2.08,1.88-3.65,4.35-5.12,6.71 c-2.13,3.41-4.84,1.32-6.3-1.34c-0.17-0.3-0.32-0.61-0.46-0.92c-0.54-1.29-0.83-2.7-0.83-4.1c0-5.69,4.55-10.29,10.15-10.29 c1.92,0,4.21,0.75,5.91,1.77c0.17,0.1,0.38,0.19,0.53,0.3C31.56,18.19,30.98,19.77,29.62,21.2z" style="fill:#B89278;"/>
    <path d="M113.71,29.03c-0.05,0.12-0.11,0.25-0.18,0.38c-1.38,2.9-4.31,5.52-6.58,1.89 c-1.48-2.36-3.04-4.83-5.12-6.71c-0.93-0.84-2.89-2.04-4.16-3.38c-1.35-1.43-1.93-3.01,0.28-4.49c0.27-0.18,0.58-0.34,0.9-0.51 c1.67-0.91,3.76-1.56,5.54-1.56c5.61,0,10.15,4.6,10.15,10.29C114.53,26.34,114.26,27.74,113.71,29.03z" style="fill:#B89278;"/>
  </g>
</svg>
`;

// Add Logo
pdf.addImage(svgLogo, { width: 40, align: "center" });
pdf.addText("\n");

// Add Header Information
pdf.addText("MHEE CAFE & RESTAURANT", { font: fontSans, fontSize: 11, align: "center" });
pdf.addText("หมีคาเฟ่ - สาขาใหญ่ กรุงเทพฯ", { font: fontBold, fontSize: 10, align: "center" });
pdf.addText("123 ถ.สุขุมวิท แขวงคลองเตย เขตคลองเตย กทม. 10110", {
  font: fontRegular,
  fontSize: 7,
  align: "center",
});
pdf.addText("Tel: 02-123-4567 | TAX ID: 0105560123456", {
  font: fontRegular,
  fontSize: 7,
  align: "center",
});
pdf.addText("ใบเสร็จรับเงิน / ใบกำกับภาษีอย่างย่อ", { font: fontBold, fontSize: 8, align: "center" });
pdf.addText("TAX INVOICE (ABB.)", { font: fontSans, fontSize: 7, align: "center" });

// Separator
pdf.addLine({ color: "#64748b", dash: "dashed", height: 10 });

// Metadata Table
const metaTable = new Table({
  columns: ["*", "*"],
  borderWidth: 0,
  padding: 1,
});
metaTable.addRow([
  new Text("Date: 25/06/2026 18:30", { font: fontRegular, fontSize: 7 }),
  new Text("Table: T05 (10 Pax)", { font: fontRegular, fontSize: 7, align: "right" }),
]);
metaTable.addRow([
  new Text("Receipt: #ABB-20260625-08", { font: fontRegular, fontSize: 7 }),
  new Text("Cashier: Mhee Som", { font: fontRegular, fontSize: 7, align: "right" }),
]);
pdf.add(metaTable);

// Separator
pdf.addLine({ color: "#64748b", dash: "dashed", height: 10 });

// Items Table Header
const itemsTable = new Table({
  columns: ["*", 20, 45],
  borderWidth: 0,
  padding: { top: 2, bottom: 2, left: 0, right: 0 },
  aligns: ["left", "center", "right"],
});
itemsTable.addRow([
  new Text("รายการ / Description", { font: fontBold, fontSize: 7.5 }),
  new Text("Qty", { font: fontBold, fontSize: 7.5, align: "center" }),
  new Text("บาท / Amt", { font: fontBold, fontSize: 7.5, align: "right" }),
]);

// 20 Menu Items (Big Dinner)
const items = [
  { name: "แกงส้มชะอมกุ้ง / Sour Curry w. Shrimp", qty: 1, price: 180 },
  { name: "ปลากะพงทอดน้ำปลา / Fried Seabass", qty: 1, price: 450 },
  { name: "ต้มยำกุ้งมะพร้าวอ่อน / Spicy Shrimp Soup", qty: 1, price: 250 },
  { name: "ผัดไทยกุ้งสด / Pad Thai w. Fresh Shrimp", qty: 2, price: 120 },
  { name: "ปูดองน้ำปลา / Pickled Crab", qty: 1, price: 350 },
  { name: "ผัดผักบุ้งไฟแดง / Stir-Fried Morning Glory", qty: 1, price: 80 },
  { name: "ข้าวผัดปูจานใหญ่ / Crab Fried Rice (L)", qty: 1, price: 220 },
  { name: "คอหมูย่าง / Grilled Pork Neck", qty: 2, price: 100 },
  { name: "ส้มตำไทยไข่เค็ม / Papaya Salad w. Egg", qty: 2, price: 85 },
  { name: "ลาบหมู / Spicy Minced Pork Salad", qty: 1, price: 90 },
  { name: "ทอดมันกุ้ง / Deep Fried Shrimp Cakes", qty: 1, price: 150 },
  { name: "ยำวุ้นเส้นทะเล / Spicy Seafood Glass Noodle", qty: 1, price: 140 },
  { name: "หอยนางรมสด / Fresh Oysters", qty: 6, price: 60 },
  { name: "ข้าวสวย (โถ) / Steamed Rice (Bowl)", qty: 1, price: 60 },
  { name: "น้ำมะพร้าวปั่น / Coconut Smoothie", qty: 4, price: 75 },
  { name: "ชาไทยเย็น / Iced Thai Milk Tea", qty: 3, price: 60 },
  { name: "เบียร์สิงห์ / Singha Beer", qty: 3, price: 95 },
  { name: "บัวลอยมะพร้าวอ่อน / Rice Balls in Coconut Milk", qty: 4, price: 50 },
  { name: "ข้าวเหนียวมะม่วง / Mango Sticky Rice", qty: 2, price: 120 },
  { name: "น้ำเปล่าและน้ำแข็ง / Water & Ice Bucket", qty: 1, price: 50 },
];

let subtotal = 0;
for (const item of items) {
  const amt = item.qty * item.price;
  subtotal += amt;
  itemsTable.addRow([
    new Text(item.name, { font: fontRegular, fontSize: 7 }),
    new Text(item.qty.toString(), { font: fontRegular, fontSize: 7, align: "center" }),
    new Text(amt.toFixed(2), { font: fontRegular, fontSize: 7, align: "right" }),
  ]);
}
pdf.add(itemsTable);

// Separator
pdf.addLine({ color: "#64748b", dash: "dashed", height: 10 });

// Summary calculations
const vatRate = 0.07;
const vat = subtotal * vatRate;
const total = subtotal + vat;

const summaryTable = new Table({
  columns: ["*", 70, 45],
  borderWidth: 0,
  padding: 1,
  aligns: ["left", "right", "right"],
});
summaryTable.addRow(["", "Subtotal:", subtotal.toFixed(2)]);
summaryTable.addRow(["", "VAT (7%):", vat.toFixed(2)]);
summaryTable.addRow([
  "",
  new Text("Total / ยอดรวม:", { font: fontBold, fontSize: 8 }),
  new Text(total.toFixed(2), { font: fontBold, fontSize: 8, align: "right" }),
]);
pdf.add(summaryTable);

// Separator
pdf.addLine({ color: "#64748b", dash: "dashed", height: 10 });

// Footer thank you messages
pdf.addText("Thank you / ขอบคุณที่มาอุดหนุน", { font: fontBold, fontSize: 8.5, align: "center" });
pdf.addText("Please come again next time!", {
  font: fontSans,
  fontSize: 7,
  align: "center",
  color: "#475569",
});
pdf.addText("\n");
pdf.addText("Powered by MheePDF", {
  font: fontSans,
  fontSize: 6.5,
  align: "center",
  color: "#94a3b8",
});
PDF Preview

Released under the MIT License.