{"version":3,"file":"index.cjs","sources":["../src/utils/helpers.ts","../src/services/protocol.ts","../src/services/printerState.ts","../src/services/printer.ts","../src/core/EventEmitter.ts","../src/core/ClientState.ts","../src/services/dithering.ts","../src/services/imageTransforms.ts","../src/services/imageProcessor.ts","../src/core/PrintJob.ts","../src/core/ThermalPrinterClient.ts","../src/utils/bluetooth.ts","../src/adapters/BaseCharacteristicWrapper.ts","../src/adapters/WebBluetoothAdapter.ts","../src/adapters/NodeBluetoothAdapter.ts"],"sourcesContent":["// Utility functions for printer operations\n\n/**\n * CRC8 lookup table for checksum calculation\n */\nconst CRC8_TABLE = [\n  0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24,\n  0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f,\n  0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2,\n  0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, 0x90, 0x97, 0x9e, 0x99,\n  0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, 0xc7,\n  0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4,\n  0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81,\n  0x86, 0x93, 0x94, 0x9d, 0x9a, 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32,\n  0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b,\n  0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 0x89, 0x8e,\n  0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3,\n  0xa4, 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8,\n  0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51,\n  0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02,\n  0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, 0x4e, 0x49, 0x40,\n  0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,\n  0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a,\n  0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91,\n  0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc,\n  0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,\n];\n\n/**\n * Calculate CRC8 checksum for data integrity\n */\nexport function crc8(data: Uint8Array): number {\n  let crc = 0;\n  for (const byte of data) {\n    crc = CRC8_TABLE[(crc ^ byte) & 0xff];\n  }\n  return crc & 0xff;\n}\n\n/**\n * Create a promise that resolves after specified milliseconds\n */\nexport function delay(msecs: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(() => resolve(), msecs));\n}\n","// MXW01 Printer Protocol - Command building and parsing\n\nimport { crc8 } from \"../utils/helpers\";\n\n/**\n * MXW01 Printer command identifiers\n */\nexport const Command = {\n  GetStatus: 0xa1,\n  SetIntensity: 0xa2,\n  PrintRequest: 0xa9,\n  FlushData: 0xad,\n  PrintComplete: 0xaa,\n} as const;\n\n/**\n * Protocol constants\n */\nexport const PROTOCOL = {\n  HEADER_BYTE_1: 0x22,\n  HEADER_BYTE_2: 0x21,\n  TERMINATOR: 0xff,\n} as const;\n\n/**\n * Build a command packet for the MXW01 printer\n * @param command Command identifier\n * @param payload Command payload data\n * @returns Complete command packet with header, payload, CRC, and terminator\n */\nexport function makeCommand(command: number, payload: Uint8Array): Uint8Array {\n  const len = payload.length;\n  const header = new Uint8Array([\n    PROTOCOL.HEADER_BYTE_1,\n    PROTOCOL.HEADER_BYTE_2,\n    command,\n    0x00,\n    len & 0xff,\n    (len >> 8) & 0xff,\n  ]);\n\n  // Concatenate header and payload\n  const cmdWithPayload = new Uint8Array(header.length + payload.length);\n  cmdWithPayload.set(header);\n  cmdWithPayload.set(payload, header.length);\n\n  // Calculate CRC on payload only\n  const crcValue = crc8(payload);\n\n  // Final command: header + payload + CRC + terminator\n  const result = new Uint8Array(cmdWithPayload.length + 2);\n  result.set(cmdWithPayload);\n  result[result.length - 2] = crcValue;\n  result[result.length - 1] = PROTOCOL.TERMINATOR;\n\n  return result;\n}\n\n/**\n * Parse notification message from printer\n * @param message Raw notification data\n * @returns Parsed command ID and payload, or null if invalid\n */\nexport function parseNotification(\n  message: Uint8Array\n): { cmdId: number; payload: Uint8Array } | null {\n  // Validate header\n  if (\n    message[0] !== PROTOCOL.HEADER_BYTE_1 ||\n    message[1] !== PROTOCOL.HEADER_BYTE_2\n  ) {\n    return null;\n  }\n\n  const cmdId = message[2];\n  const len = message[4] | (message[5] << 8);\n  const payload = message.slice(6, 6 + len);\n\n  return { cmdId, payload };\n}\n","// Printer state management\n\nimport { Command } from \"./protocol\";\n\n/**\n * Printer state interface\n */\nexport interface PrinterState {\n  printing: boolean;\n  paper_jam: boolean;\n  out_of_paper: boolean;\n  cover_open: boolean;\n  battery_low: boolean;\n  overheat: boolean;\n}\n\n/**\n * Parse printer state from status response payload\n * @param payload Status response payload\n * @returns Parsed printer state or null if invalid\n */\nexport function parsePrinterState(payload: Uint8Array): PrinterState | null {\n  if (payload.length < 7) {\n    return null;\n  }\n\n  const statusByte = payload[6];\n  return {\n    printing: (statusByte & 0x01) !== 0,\n    paper_jam: (statusByte & 0x02) !== 0,\n    out_of_paper: (statusByte & 0x04) !== 0,\n    cover_open: (statusByte & 0x08) !== 0,\n    battery_low: (statusByte & 0x10) !== 0,\n    overheat: (statusByte & 0x20) !== 0,\n  };\n}\n\n/**\n * Create initial/default printer state\n */\nexport function createDefaultState(): PrinterState {\n  return {\n    printing: false,\n    paper_jam: false,\n    out_of_paper: false,\n    cover_open: false,\n    battery_low: false,\n    overheat: false,\n  };\n}\n\n/**\n * Printer state manager\n * Handles state updates and notification processing\n */\nexport class PrinterStateManager {\n  private state: PrinterState;\n  private printComplete: boolean = false;\n  private pendingResolvers: Map<number, (payload: Uint8Array) => void> =\n    new Map();\n\n  constructor() {\n    this.state = createDefaultState();\n  }\n\n  /**\n   * Get current printer state\n   */\n  getState(): PrinterState {\n    return { ...this.state };\n  }\n\n  /**\n   * Check if print is complete\n   */\n  isPrintComplete(): boolean {\n    return this.printComplete;\n  }\n\n  /**\n   * Reset print complete flag\n   */\n  resetPrintComplete(): void {\n    this.printComplete = false;\n  }\n\n  /**\n   * Process notification and update state\n   * @param cmdId Command ID from notification\n   * @param payload Notification payload\n   */\n  processNotification(cmdId: number, payload: Uint8Array): void {\n    // Check for print complete notification\n    if (cmdId === Command.PrintComplete) {\n      this.printComplete = true;\n    }\n\n    // Update state from status response\n    if (cmdId === Command.GetStatus) {\n      const newState = parsePrinterState(payload);\n      if (newState) {\n        this.state = newState;\n      }\n    }\n\n    // Resolve any pending promise for this command\n    const resolver = this.pendingResolvers.get(cmdId);\n    if (resolver) {\n      resolver(payload);\n      this.pendingResolvers.delete(cmdId);\n    }\n  }\n\n  /**\n   * Wait for notification response\n   * @param cmdId Command ID to wait for\n   * @param timeoutMs Timeout in milliseconds\n   * @returns Promise that resolves with the payload\n   */\n  waitForNotification(cmdId: number, timeoutMs = 10000): Promise<Uint8Array> {\n    return new Promise((resolve, reject) => {\n      const timer = setTimeout(() => {\n        this.pendingResolvers.delete(cmdId);\n        reject(\n          new Error(`Timeout waiting for notification 0x${cmdId.toString(16)}`)\n        );\n      }, timeoutMs);\n\n      this.pendingResolvers.set(cmdId, (payload) => {\n        clearTimeout(timer);\n        resolve(payload);\n      });\n    });\n  }\n}\n","// MXW01 Thermal Printer - Simplified with delegated responsibilities\n\nimport { delay } from \"../utils/helpers\";\nimport { makeCommand, parseNotification, Command } from \"./protocol\";\nimport { PrinterStateManager } from \"./printerState\";\nimport type { PrinterState } from \"./printerState\";\n\nexport const PRINTER_WIDTH = 384;\nexport const PRINTER_WIDTH_BYTES = PRINTER_WIDTH / 8; // 48 bytes\nexport const MIN_DATA_BYTES = 90 * PRINTER_WIDTH_BYTES; // 4320 bytes minimum\n\n// Re-export for backward compatibility\nexport { Command, type PrinterState };\n\n// Type for Bluetooth write functions\nexport type WriteFunction = (data: BufferSource) => Promise<void>;\n\n/**\n * MXW01 Thermal Printer Controller\n * Simplified class that delegates to protocol and state management modules\n */\nexport class MXW01Printer {\n  private controlWrite: WriteFunction;\n  private dataWrite: WriteFunction;\n  private stateManager: PrinterStateManager;\n\n  constructor(controlWrite: WriteFunction, dataWrite: WriteFunction) {\n    this.controlWrite = controlWrite;\n    this.dataWrite = dataWrite;\n    this.stateManager = new PrinterStateManager();\n  }\n\n  /**\n   * Get current printer state\n   */\n  get state(): PrinterState {\n    return this.stateManager.getState();\n  }\n\n  /**\n   * Process incoming notification from printer\n   */\n  notify(message: Uint8Array): void {\n    const parsed = parseNotification(message);\n    if (!parsed) {\n      console.warn(\"Ignoring unexpected notification format\");\n      return;\n    }\n\n    this.stateManager.processNotification(parsed.cmdId, parsed.payload);\n  }\n\n  /**\n   * Set print intensity (darkness)\n   */\n  async setIntensity(intensity = 0x5d): Promise<void> {\n    const command = makeCommand(Command.SetIntensity, Uint8Array.of(intensity));\n    await this.controlWrite(command as BufferSource);\n    await delay(50);\n  }\n\n  /**\n   * Request current printer status\n   */\n  async requestStatus(): Promise<Uint8Array> {\n    const command = makeCommand(Command.GetStatus, Uint8Array.of(0x00));\n    await this.controlWrite(command as BufferSource);\n    return this.stateManager.waitForNotification(Command.GetStatus, 5000);\n  }\n\n  /**\n   * Send print request with number of lines\n   */\n  async printRequest(lines: number, mode = 0): Promise<Uint8Array> {\n    const payload = new Uint8Array(4);\n    payload[0] = lines & 0xff;\n    payload[1] = (lines >> 8) & 0xff;\n    payload[2] = 0x30;\n    payload[3] = mode;\n\n    const command = makeCommand(Command.PrintRequest, payload);\n    await this.controlWrite(command as BufferSource);\n    return this.stateManager.waitForNotification(Command.PrintRequest, 5000);\n  }\n\n  /**\n   * Flush data to printer\n   */\n  async flushData(): Promise<void> {\n    const command = makeCommand(Command.FlushData, Uint8Array.of(0x00));\n    await this.controlWrite(command as BufferSource);\n    await delay(50);\n  }\n\n  /**\n   * Send data chunks to printer\n   */\n  async sendDataChunks(\n    data: Uint8Array,\n    chunkSize = PRINTER_WIDTH_BYTES\n  ): Promise<void> {\n    let pos = 0;\n    while (pos < data.length) {\n      const chunk = data.slice(pos, Math.min(pos + chunkSize, data.length));\n      await this.dataWrite(chunk);\n      pos += chunk.length;\n      await delay(15);\n    }\n  }\n\n  /**\n   * Wait for print completion\n   */\n  async waitForPrintComplete(timeoutMs = 20000): Promise<void> {\n    this.stateManager.resetPrintComplete();\n    const startTime = Date.now();\n\n    while (\n      !this.stateManager.isPrintComplete() &&\n      Date.now() - startTime < timeoutMs\n    ) {\n      await delay(100);\n    }\n\n    if (!this.stateManager.isPrintComplete()) {\n      throw new Error(\"Print timeout: Did not receive completion notification\");\n    }\n  }\n}\n\n/**\n * Encode a row of boolean pixels to binary format\n */\nexport function encode1bppRow(rowBool: boolean[]): Uint8Array {\n  if (rowBool.length !== PRINTER_WIDTH) {\n    throw new Error(\n      `Row length must be ${PRINTER_WIDTH}, got ${rowBool.length}`\n    );\n  }\n\n  const rowBytes = new Uint8Array(PRINTER_WIDTH_BYTES);\n  for (let byteIndex = 0; byteIndex < PRINTER_WIDTH_BYTES; byteIndex++) {\n    let byteVal = 0;\n    for (let bit = 0; bit < 8; bit++) {\n      if (rowBool[byteIndex * 8 + bit]) {\n        byteVal |= 1 << bit;\n      }\n    }\n    rowBytes[byteIndex] = byteVal;\n  }\n\n  return rowBytes;\n}\n\n/**\n * Prepare image data buffer with padding\n */\nexport function prepareImageDataBuffer(imageRowsBool: boolean[][]): Uint8Array {\n  const height = imageRowsBool.length;\n  let buffer = new Uint8Array(0);\n\n  for (let y = 0; y < height; y++) {\n    const rowBytes = encode1bppRow(imageRowsBool[y]);\n    const newBuf = new Uint8Array(buffer.length + rowBytes.length);\n    newBuf.set(buffer);\n    newBuf.set(rowBytes, buffer.length);\n    buffer = newBuf;\n  }\n\n  // Pad to minimum size if needed\n  if (buffer.length < MIN_DATA_BYTES) {\n    const pad = new Uint8Array(MIN_DATA_BYTES - buffer.length);\n    const newBuf = new Uint8Array(buffer.length + pad.length);\n    newBuf.set(buffer);\n    newBuf.set(pad, buffer.length);\n    buffer = newBuf;\n  }\n\n  return buffer;\n}\n","// Generic event emitter for printer events\n\nimport type {\n  PrinterEvent,\n  PrinterEventType,\n  PrinterEventListener,\n} from \"./types\";\n\n/**\n * Simple type-safe event emitter for printer events\n */\nexport class EventEmitter {\n  private listeners: Map<PrinterEventType, Set<PrinterEventListener>> =\n    new Map();\n\n  /**\n   * Subscribe to an event\n   * @param eventType Event type to listen for\n   * @param listener Callback function\n   * @returns Unsubscribe function\n   */\n  on<T extends PrinterEventType>(\n    eventType: T,\n    listener: PrinterEventListener<T>\n  ): () => void {\n    if (!this.listeners.has(eventType)) {\n      this.listeners.set(eventType, new Set());\n    }\n    this.listeners.get(eventType)!.add(listener as any);\n\n    // Return unsubscribe function\n    return () => {\n      const listeners = this.listeners.get(eventType);\n      if (listeners) {\n        listeners.delete(listener as any);\n      }\n    };\n  }\n\n  /**\n   * Emit an event to all listeners\n   * @param event Event to emit\n   */\n  emit(event: PrinterEvent): void {\n    const listeners = this.listeners.get(event.type);\n    if (listeners) {\n      listeners.forEach((listener) => {\n        try {\n          (listener as any)(event);\n        } catch (error) {\n          console.error(\"Error in event listener:\", error);\n        }\n      });\n    }\n  }\n\n  /**\n   * Clear all event listeners\n   */\n  clear(): void {\n    this.listeners.clear();\n  }\n\n  /**\n   * Remove all listeners for a specific event type\n   * @param eventType Event type to clear\n   */\n  clearEventType(eventType: PrinterEventType): void {\n    this.listeners.delete(eventType);\n  }\n}\n","// Centralized state management for ThermalPrinterClient\n\nimport type { PrinterState } from \"./types\";\nimport type { ImageProcessorOptions } from \"../services/imageProcessor\";\n\n/**\n * Client state manager\n * Centralizes all state management for the printer client\n */\nexport class ClientState {\n  private _isConnected = false;\n  private _isPrinting = false;\n  private _printerState: PrinterState | null = null;\n  private _statusMessage = \"Ready to connect printer\";\n  private _ditherMethod: ImageProcessorOptions[\"dither\"] = \"steinberg\";\n  private _printIntensity = 0x5d;\n\n  // Getters\n  get isConnected(): boolean {\n    return this._isConnected;\n  }\n\n  get isPrinting(): boolean {\n    return this._isPrinting;\n  }\n\n  get printerState(): PrinterState | null {\n    return this._printerState;\n  }\n\n  get statusMessage(): string {\n    return this._statusMessage;\n  }\n\n  get ditherMethod(): ImageProcessorOptions[\"dither\"] {\n    return this._ditherMethod;\n  }\n\n  get printIntensity(): number {\n    return this._printIntensity;\n  }\n\n  // Setters with validation\n  setConnected(value: boolean): void {\n    this._isConnected = value;\n  }\n\n  setPrinting(value: boolean): void {\n    this._isPrinting = value;\n  }\n\n  setPrinterState(state: PrinterState | null): void {\n    this._printerState = state;\n  }\n\n  setStatusMessage(message: string): void {\n    this._statusMessage = message;\n  }\n\n  setDitherMethod(method: ImageProcessorOptions[\"dither\"]): void {\n    this._ditherMethod = method;\n  }\n\n  setPrintIntensity(intensity: number): void {\n    if (intensity < 0 || intensity > 255) {\n      throw new Error(\"Print intensity must be between 0 and 255\");\n    }\n    this._printIntensity = intensity;\n  }\n\n  /**\n   * Reset to initial state\n   */\n  reset(): void {\n    this._isConnected = false;\n    this._isPrinting = false;\n    this._printerState = null;\n    this._statusMessage = \"Ready to connect printer\";\n  }\n}\n","// Dithering algorithms for thermal printer image processing\n\n/**\n * Abstract base class for dithering algorithms\n */\nexport abstract class DitherAlgorithm {\n  abstract apply(\n    mono: Uint8ClampedArray,\n    width: number,\n    height: number\n  ): Uint8ClampedArray;\n\n  /**\n   * Get the name of this dithering algorithm\n   */\n  abstract getName(): string;\n}\n\n/**\n * Simple threshold dithering\n */\nexport class ThresholdDither extends DitherAlgorithm {\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  apply(\n    mono: Uint8ClampedArray,\n    _width: number,\n    _height: number\n  ): Uint8ClampedArray {\n    for (let i = 0; i < mono.length; ++i) {\n      mono[i] = mono[i] > 0x80 ? 0xff : 0x00;\n    }\n    return mono;\n  }\n\n  getName(): string {\n    return \"threshold\";\n  }\n}\n\n/**\n * Floyd-Steinberg error diffusion dithering\n */\nexport class SteinbergDither extends DitherAlgorithm {\n  apply(\n    mono: Uint8ClampedArray,\n    width: number,\n    height: number\n  ): Uint8ClampedArray {\n    let p = 0;\n\n    for (let j = 0; j < height; ++j) {\n      for (let i = 0; i < width; ++i) {\n        const oldPixel = mono[p];\n        const newPixel = oldPixel > 0x80 ? 0xff : 0x00;\n        const error = oldPixel - newPixel;\n        mono[p] = newPixel;\n\n        // Distribute error to neighboring pixels\n        if (i < width - 1) {\n          mono[p + 1] += (error * 7) / 16;\n        }\n        if (j < height - 1) {\n          if (i > 0) {\n            mono[p + width - 1] += (error * 3) / 16;\n          }\n          mono[p + width] += (error * 5) / 16;\n          if (i < width - 1) {\n            mono[p + width + 1] += (error) / 16;\n          }\n        }\n        ++p;\n      }\n    }\n\n    return mono;\n  }\n\n  getName(): string {\n    return \"steinberg\";\n  }\n}\n\n/**\n * Bayer matrix dithering\n */\nexport class BayerDither extends DitherAlgorithm {\n  private readonly bayer8 = [\n    0, 48, 12, 60, 3, 51, 15, 63, 32, 16, 44, 28, 35, 19, 47, 31, 8, 56, 4, 52,\n    11, 59, 7, 55, 40, 24, 36, 20, 43, 27, 39, 23, 2, 50, 14, 62, 1, 49, 13,\n    61, 34, 18, 46, 30, 33, 17, 45, 29, 10, 58, 6, 54, 9, 57, 5, 53, 42, 26,\n    38, 22, 41, 25, 37, 21,\n  ];\n  private readonly ditherFactor = 0.6;\n\n  apply(\n    mono: Uint8ClampedArray,\n    width: number,\n    height: number\n  ): Uint8ClampedArray {\n    let p = 0;\n\n    for (let j = 0; j < height; ++j) {\n      for (let i = 0; i < width; ++i) {\n        const bayerValue = this.bayer8[(j % 8) * 8 + (i % 8)];\n        let pixelValue = mono[p];\n        pixelValue = pixelValue + (bayerValue - 32) * this.ditherFactor;\n        pixelValue = Math.max(0, Math.min(255, pixelValue));\n        mono[p] = pixelValue > 128 ? 0xff : 0x00;\n        ++p;\n      }\n    }\n\n    return mono;\n  }\n\n  getName(): string {\n    return \"bayer\";\n  }\n}\n\n/**\n * Atkinson dithering algorithm\n */\nexport class AtkinsonDither extends DitherAlgorithm {\n  apply(\n    mono: Uint8ClampedArray,\n    width: number,\n    height: number\n  ): Uint8ClampedArray {\n    let p = 0;\n\n    for (let j = 0; j < height; ++j) {\n      for (let i = 0; i < width; ++i) {\n        const oldPixel = mono[p];\n        const newPixel = oldPixel > 0x80 ? 0xff : 0x00;\n        const error = (oldPixel - newPixel) >> 3; // Division by 8\n        mono[p] = newPixel;\n\n        // Distribute error to neighboring pixels\n        if (i < width - 1) {\n          mono[p + 1] += error;\n        }\n        if (i < width - 2) {\n          mono[p + 2] += error;\n        }\n        if (j < height - 1) {\n          if (i > 0) {\n            mono[p + width - 1] += error;\n          }\n          mono[p + width] += error;\n          if (i < width - 1) {\n            mono[p + width + 1] += error;\n          }\n        }\n        if (j < height - 2) {\n          mono[p + 2 * width] += error;\n        }\n\n        ++p;\n      }\n    }\n\n    return mono;\n  }\n\n  getName(): string {\n    return \"atkinson\";\n  }\n}\n\n/**\n * Halftone pattern dithering\n */\nexport class HalftoneDither extends DitherAlgorithm {\n  apply(\n    mono: Uint8ClampedArray,\n    width: number,\n    height: number\n  ): Uint8ClampedArray {\n    const spot = 4;\n    const spot_h = spot / 2 + 1;\n    const spot_s = spot * spot;\n\n    for (let j = 0; j < height - spot; j += spot) {\n      for (let i = 0; i < width - spot; i += spot) {\n        let sum = 0;\n        for (let x = 0; x < spot; ++x) {\n          for (let y = 0; y < spot; ++y) {\n            sum += mono[(j + y) * width + i + x];\n          }\n        }\n        const threshold = (1 - sum / spot_s / 0xff) * spot;\n\n        for (let x = 0; x < spot; ++x) {\n          for (let y = 0; y < spot; ++y) {\n            mono[(j + y) * width + i + x] =\n              Math.abs(x - spot_h) >= threshold ||\n              Math.abs(y - spot_h) >= threshold\n                ? 0xff\n                : 0x00;\n          }\n        }\n      }\n\n      // Fill remaining columns\n      for (let i = width - (width % spot); i < width; ++i) {\n        mono[j * width + i] = 0xff;\n      }\n    }\n\n    // Fill remaining rows\n    for (let j = height - (height % spot); j < height; ++j) {\n      for (let i = 0; i < width; ++i) {\n        mono[j * width + i] = 0xff;\n      }\n    }\n\n    return mono;\n  }\n\n  getName(): string {\n    return \"pattern\";\n  }\n}\n\n/**\n * Dithering method type\n */\nexport type DitherMethod =\n  | \"threshold\"\n  | \"steinberg\"\n  | \"bayer\"\n  | \"atkinson\"\n  | \"pattern\";\n\n/**\n * Factory to get dithering algorithm by name\n */\nexport function getDitherAlgorithm(method: DitherMethod): DitherAlgorithm {\n  switch (method) {\n    case \"steinberg\":\n      return new SteinbergDither();\n    case \"bayer\":\n      return new BayerDither();\n    case \"atkinson\":\n      return new AtkinsonDither();\n    case \"pattern\":\n      return new HalftoneDither();\n    case \"threshold\":\n    default:\n      return new ThresholdDither();\n  }\n}\n","// Image transformation utilities (rotate, flip, scale)\n\n/**\n * Rotate an image by 0, 90, 180, or 270 degrees\n * @param data Input image data\n * @param width Input image width\n * @param height Input image height\n * @param angle Rotation angle (0, 90, 180, or 270 degrees)\n * @returns Rotated image data (dimensions may be swapped for 90/270)\n */\nexport function rotate(\n  data: Uint8ClampedArray,\n  width: number,\n  height: number,\n  angle: 0 | 90 | 180 | 270\n): Uint8ClampedArray {\n  if (angle === 0) {\n    return data;\n  }\n\n  const result = new Uint8ClampedArray(data.length);\n\n  switch (angle) {\n    case 90:\n      // Rotate 90° clockwise: output dimensions are swapped (height × width)\n      // Output width = input height, Output height = input width\n      for (let y = 0; y < height; y++) {\n        for (let x = 0; x < width; x++) {\n          // Map input (x, y) to output (height - 1 - y, x)\n          const outX = height - 1 - y;\n          const outY = x;\n          result[outY * height + outX] = data[y * width + x];\n        }\n      }\n      break;\n    case 180:\n      // Rotate 180°: output dimensions remain the same (width × height)\n      for (let y = 0; y < height; y++) {\n        for (let x = 0; x < width; x++) {\n          // Map input (x, y) to output (width - 1 - x, height - 1 - y)\n          const outX = width - 1 - x;\n          const outY = height - 1 - y;\n          result[outY * width + outX] = data[y * width + x];\n        }\n      }\n      break;\n    case 270:\n      // Rotate 270° clockwise (or 90° counter-clockwise): output dimensions are swapped (height × width)\n      // Output width = input height, Output height = input width\n      for (let y = 0; y < height; y++) {\n        for (let x = 0; x < width; x++) {\n          // Map input (x, y) to output (y, width - 1 - x)\n          const outX = y;\n          const outY = width - 1 - x;\n          result[outY * height + outX] = data[y * width + x];\n        }\n      }\n      break;\n  }\n\n  return result;\n}\n\n/**\n * Flip an image horizontally, vertically, or both\n */\nexport function flip(\n  data: Uint8ClampedArray,\n  width: number,\n  height: number,\n  mode: \"none\" | \"h\" | \"v\" | \"both\"\n): Uint8ClampedArray {\n  if (mode === \"none\") {\n    return data;\n  }\n\n  const result = new Uint8ClampedArray(data.length);\n\n  switch (mode) {\n    case \"h\":\n      for (let j = 0; j < height; j++) {\n        for (let i = 0; i < width; i++) {\n          result[j * width + i] = data[j * width + (width - i - 1)];\n        }\n      }\n      break;\n    case \"v\":\n      for (let j = 0; j < height; j++) {\n        for (let i = 0; i < width; i++) {\n          result[j * width + i] = data[(height - j - 1) * width + i];\n        }\n      }\n      break;\n    case \"both\":\n      for (let j = 0; j < height; j++) {\n        for (let i = 0; i < width; i++) {\n          result[j * width + i] = data[(height - j - 1) * width + (width - i - 1)];\n        }\n      }\n      break;\n  }\n\n  return result;\n}\n\n/**\n * Convert RGBA to grayscale with brightness adjustment\n */\nexport function rgbaToGray(\n  rgba: Uint32Array,\n  brightness = 128,\n  alphaAsWhite = true\n): Uint8ClampedArray {\n  const mono = new Uint8ClampedArray(rgba.length);\n\n  for (let i = 0; i < mono.length; ++i) {\n    const n = rgba[i];\n    let r = n & 0xff;\n    let g = (n >> 8) & 0xff;\n    let b = (n >> 16) & 0xff;\n    const alpha = ((n >> 24) & 0xff) / 0xff;\n\n    // Handle transparency\n    if (alpha < 1 && alphaAsWhite) {\n      const a = 1 - alpha;\n      r += (0xff - r) * a;\n      g += (0xff - g) * a;\n      b += (0xff - b) * a;\n    } else {\n      r *= alpha;\n      g *= alpha;\n      b *= alpha;\n    }\n\n    // RGB to grayscale with weighting\n    let gray = r * 0.2125 + g * 0.7154 + b * 0.0721;\n\n    // Brightness adjustment\n    gray += (brightness - 0x80) * (1 - gray / 0xff) * (gray / 0xff) * 2;\n    mono[i] = gray;\n  }\n\n  return mono;\n}\n\n/**\n * Convert grayscale to RGBA\n */\nexport function grayToRgba(\n  mono: Uint8ClampedArray,\n  whiteAsTransparent = false\n): Uint32Array {\n  const rgba = new Uint32Array(mono.length);\n\n  for (let i = 0; i < mono.length; ++i) {\n    const base = mono[i] === 0xff && whiteAsTransparent ? 0 : 0xff000000;\n    rgba[i] = base | (mono[i] << 16) | (mono[i] << 8) | mono[i];\n  }\n\n  return rgba;\n}\n\n/**\n * Crop image data to target dimensions\n * Takes pixels from top-left corner up to target width/height\n */\nexport function cropImageData(\n  source: { data: Uint8ClampedArray; width: number; height: number },\n  targetWidth: number,\n  targetHeight: number\n): { data: Uint8ClampedArray; width: number; height: number } {\n  const croppedWidth = Math.min(targetWidth, source.width);\n  const croppedHeight = Math.min(targetHeight, source.height);\n  const cropped = new Uint8ClampedArray(croppedWidth * croppedHeight * 4);\n\n  for (let y = 0; y < croppedHeight; y++) {\n    for (let x = 0; x < croppedWidth; x++) {\n      const srcIdx = (y * source.width + x) * 4;\n      const dstIdx = (y * croppedWidth + x) * 4;\n\n      cropped[dstIdx] = source.data[srcIdx];\n      cropped[dstIdx + 1] = source.data[srcIdx + 1];\n      cropped[dstIdx + 2] = source.data[srcIdx + 2];\n      cropped[dstIdx + 3] = source.data[srcIdx + 3];\n    }\n  }\n\n  return {\n    data: cropped,\n    width: croppedWidth,\n    height: croppedHeight,\n  };\n}\n\n/**\n * Scale image data to target dimensions using nearest-neighbor interpolation\n */\nexport function scaleImageData(\n  source: { data: Uint8ClampedArray; width: number; height: number },\n  targetWidth: number,\n  targetHeight: number\n): { data: Uint8ClampedArray; width: number; height: number } {\n  const scaled = new Uint8ClampedArray(targetWidth * targetHeight * 4);\n  const xRatio = source.width / targetWidth;\n  const yRatio = source.height / targetHeight;\n\n  for (let y = 0; y < targetHeight; y++) {\n    for (let x = 0; x < targetWidth; x++) {\n      const srcX = Math.floor(x * xRatio);\n      const srcY = Math.floor(y * yRatio);\n      const srcIdx = (srcY * source.width + srcX) * 4;\n      const dstIdx = (y * targetWidth + x) * 4;\n\n      scaled[dstIdx] = source.data[srcIdx];\n      scaled[dstIdx + 1] = source.data[srcIdx + 1];\n      scaled[dstIdx + 2] = source.data[srcIdx + 2];\n      scaled[dstIdx + 3] = source.data[srcIdx + 3];\n    }\n  }\n\n  return {\n    data: scaled,\n    width: targetWidth,\n    height: targetHeight,\n  };\n}\n","// Image processing service for MXW01 thermal printer\n// Simplified to use modular dithering and transformation utilities\n\nimport { getDitherAlgorithm } from \"./dithering\";\nimport { rgbaToGray, grayToRgba, rotate, flip } from \"./imageTransforms\";\nimport type { DitherMethod } from \"./dithering\";\n\n// Re-export for backward compatibility\nexport type { DitherMethod };\n\n/**\n * Image processor options\n */\nexport interface ImageProcessorOptions {\n  dither: DitherMethod;\n  rotate: 0 | 90 | 180 | 270;\n  flip: \"none\" | \"h\" | \"v\" | \"both\";\n  brightness: number;\n}\n\n/**\n * Process an image for thermal printer\n * @param imageData Source image data\n * @param options Processing options\n * @returns Processed image data and binary rows for printing\n */\nexport function processImageForPrinter(\n  imageData: ImageData,\n  options: ImageProcessorOptions\n): {\n  processedData: Uint32Array;\n  width: number;\n  height: number;\n  binaryRows: boolean[][];\n} {\n  // Convert to RGBA array\n  const rgbaData = new Uint32Array(\n    new Uint8ClampedArray(imageData.data).buffer\n  );\n\n  const width = imageData.width;\n  const height = imageData.height;\n\n  // Convert to grayscale with brightness adjustment\n  let mono = rgbaToGray(rgbaData, options.brightness, true);\n\n  // Apply dithering\n  const ditherAlgorithm = getDitherAlgorithm(options.dither);\n  mono = ditherAlgorithm.apply(mono, width, height);\n\n  // Apply flip transformation\n  mono = flip(mono, width, height, options.flip);\n\n  // Apply rotation and determine final dimensions\n  let finalWidth = width;\n  let finalHeight = height;\n\n  // Always pass input dimensions to rotate function\n  mono = rotate(mono, width, height, options.rotate);\n  \n  // For 90° and 270° rotations, dimensions are swapped in the output\n  if (options.rotate === 90 || options.rotate === 270) {\n    finalWidth = height;\n    finalHeight = width;\n  }\n\n  // Convert to RGBA for display\n  const processedData = grayToRgba(mono, true);\n\n  // Create binary rows array for printing\n  // Rows must always be 384 pixels wide (printer requirement)\n  const PRINTER_WIDTH = 384;\n  const binaryRows: boolean[][] = [];\n\n  for (let y = 0; y < finalHeight; y++) {\n    const row: boolean[] = [];\n    \n    // Add actual image pixels\n    for (let x = 0; x < finalWidth; x++) {\n      const idx = y * finalWidth + x;\n      const lum = mono[idx];\n      row.push(lum < 128); // true = black (print), false = white\n    }\n    \n    // Pad with white pixels to reach 384px width if needed\n    while (row.length < PRINTER_WIDTH) {\n      row.push(false); // false = white (no print)\n    }\n    \n    binaryRows.push(row);\n  }\n\n  return {\n    processedData,\n    width: finalWidth,\n    height: finalHeight,\n    binaryRows,\n  };\n}\n","// Print job encapsulation for ThermalPrinterClient\n\nimport { PRINTER_WIDTH, prepareImageDataBuffer } from \"../services/printer\";\nimport { processImageForPrinter } from \"../services/imageProcessor\";\nimport { cropImageData } from \"../services/imageTransforms\";\nimport type { PrinterImageData, PrintOptions } from \"./types\";\nimport type { ImageProcessorOptions } from \"../services/imageProcessor\";\n\n/**\n * Encapsulates a print job with image processing and preparation\n */\nexport class PrintJob {\n  private imageData: PrinterImageData;\n  private options: PrintOptions;\n\n  constructor(imageData: PrinterImageData, options: PrintOptions = {}) {\n    this.imageData = imageData;\n    this.options = options;\n  }\n\n  /**\n   * Process and prepare image for printing\n   * @param defaultDither Default dithering method\n   * @returns Prepared image buffer and metadata\n   */\n  prepare(defaultDither: ImageProcessorOptions[\"dither\"]): {\n    imageBuffer: Uint8Array;\n    numLines: number;\n  } {\n    // Default processing options\n    const processingOptions: ImageProcessorOptions = {\n      dither: this.options.dither ?? defaultDither,\n      brightness: this.options.brightness ?? 128,\n      flip: this.options.flip ?? \"none\",\n      rotate: this.options.rotate ?? 0,\n    };\n\n    // If width <= PRINTER_WIDTH: no modification needed\n    // If width > PRINTER_WIDTH: crop to PRINTER_WIDTH\n    let processedImage = this.imageData;\n    \n    if (this.imageData.width > PRINTER_WIDTH) {\n      processedImage = cropImageData(\n        this.imageData,\n        PRINTER_WIDTH,\n        this.imageData.height\n      ) as any;\n    }\n\n    // Process image for printing (rotation is applied here on the content)\n    const { binaryRows } = processImageForPrinter(\n      processedImage as any,\n      processingOptions\n    );\n\n    // Prepare print buffer\n    const imageBuffer = prepareImageDataBuffer(binaryRows);\n\n    return {\n      imageBuffer,\n      numLines: binaryRows.length,\n    };\n  }\n\n  /**\n   * Get print intensity from options or default\n   * @param defaultIntensity Default intensity value\n   * @returns Print intensity\n   */\n  getIntensity(defaultIntensity: number): number {\n    return this.options.intensity ?? defaultIntensity;\n  }\n}\n","// Platform-agnostic thermal printer client\n// Simplified with delegated responsibilities\n\nimport { MXW01Printer } from \"../services/printer\";\nimport { EventEmitter } from \"./EventEmitter\";\nimport { ClientState } from \"./ClientState\";\nimport { PrintJob } from \"./PrintJob\";\nimport type {\n  BluetoothAdapter,\n  BluetoothDevice,\n  BluetoothConnection,\n  BluetoothServiceInfo,\n  PrinterState,\n  PrinterEventType,\n  PrinterEventListener,\n  PrinterImageData,\n  PrintOptions,\n  ImageProcessorOptions,\n} from \"./types\";\n\n/**\n * Platform-agnostic thermal printer client\n * Works with any BluetoothAdapter implementation (Web Bluetooth, Noble, etc.)\n */\nexport class ThermalPrinterClient {\n  private adapter: BluetoothAdapter;\n  private printer: MXW01Printer | null = null;\n  private connection: (BluetoothConnection & BluetoothServiceInfo) | null = null;\n  private device: BluetoothDevice | null = null;\n  private eventEmitter: EventEmitter;\n  private state: ClientState;\n\n  constructor(adapter: BluetoothAdapter) {\n    if (!adapter.isAvailable()) {\n      throw new Error(\"Bluetooth is not available in this environment\");\n    }\n    this.adapter = adapter;\n    this.eventEmitter = new EventEmitter();\n    this.state = new ClientState();\n  }\n\n  // Public getters delegated to state\n  get isConnected(): boolean {\n    return this.state.isConnected;\n  }\n\n  get isPrinting(): boolean {\n    return this.state.isPrinting;\n  }\n\n  get printerState(): PrinterState | null {\n    return this.state.printerState;\n  }\n\n  get statusMessage(): string {\n    return this.state.statusMessage;\n  }\n\n  get ditherMethod(): ImageProcessorOptions[\"dither\"] {\n    return this.state.ditherMethod;\n  }\n\n  get printIntensity(): number {\n    return this.state.printIntensity;\n  }\n\n  // Public setters delegated to state\n  setDitherMethod(method: ImageProcessorOptions[\"dither\"]): void {\n    this.state.setDitherMethod(method);\n  }\n\n  setPrintIntensity(intensity: number): void {\n    this.state.setPrintIntensity(intensity);\n  }\n\n  /**\n   * Subscribe to events\n   */\n  on<T extends PrinterEventType>(\n    eventType: T,\n    listener: PrinterEventListener<T>\n  ): () => void {\n    return this.eventEmitter.on(eventType, listener);\n  }\n\n  /**\n   * Update status message and emit state change if needed\n   */\n  private updateStatus(message: string, newPrinterState?: PrinterState): void {\n    this.state.setStatusMessage(message);\n\n    if (newPrinterState) {\n      this.state.setPrinterState(newPrinterState);\n      this.eventEmitter.emit({ type: \"stateChange\", state: newPrinterState });\n    }\n  }\n\n  /**\n   * Connect to printer via Bluetooth\n   */\n  async connect(): Promise<void> {\n    try {\n      this.updateStatus(\"Connecting to printer...\");\n\n      // Request and connect to device\n      this.device = await this.adapter.requestDevice();\n      this.connection = await this.adapter.connect(this.device);\n\n      // Initialize printer\n      this.printer = new MXW01Printer(\n        this.connection.controlCharacteristic.writeValueWithoutResponse.bind(\n          this.connection.controlCharacteristic\n        ),\n        this.connection.dataCharacteristic.writeValueWithoutResponse.bind(\n          this.connection.dataCharacteristic\n        )\n      );\n\n      // Setup notifications\n      await this.setupNotifications();\n\n      this.state.setConnected(true);\n      this.updateStatus(\"Printer connected\");\n      this.eventEmitter.emit({ type: \"connected\", device: this.device });\n\n      // Initial status request\n      await this.getStatus();\n    } catch (error) {\n      const err = error as Error;\n      this.updateStatus(`Error: ${err.message}`);\n      this.eventEmitter.emit({ type: \"error\", error: err });\n      throw error;\n    }\n  }\n\n  /**\n   * Setup notification listener\n   */\n  private async setupNotifications(): Promise<void> {\n    if (!this.connection || !this.printer) {\n      throw new Error(\"No connection or printer available\");\n    }\n\n    const notifier = (event: any) => {\n      const characteristic = event.target;\n      const value = characteristic.value;\n      if (value && this.printer) {\n        this.printer.notify(new Uint8Array(value.buffer));\n        this.updateStatus(\"Printer state updated\", { ...this.printer.state });\n      }\n    };\n\n    await this.connection.notifyCharacteristic.startNotifications();\n    this.connection.notifyCharacteristic.addEventListener(\n      \"characteristicvaluechanged\",\n      notifier\n    );\n  }\n\n  /**\n   * Get current printer status\n   */\n  async getStatus(): Promise<PrinterState | null> {\n    if (!this.printer || !this.state.isConnected) {\n      this.updateStatus(\"Printer not connected\");\n      return null;\n    }\n\n    try {\n      await this.printer.requestStatus();\n      const newState = { ...this.printer.state };\n      this.updateStatus(\"Status updated\", newState);\n      return newState;\n    } catch (error) {\n      const err = error as Error;\n      this.updateStatus(`Error: ${err.message}`);\n      this.eventEmitter.emit({ type: \"error\", error: err });\n      return null;\n    }\n  }\n\n  /**\n   * Print from image data\n   */\n  async print(\n    imageData: PrinterImageData,\n    options: PrintOptions = {}\n  ): Promise<void> {\n    if (!this.printer || !this.state.isConnected) {\n      throw new Error(\"Printer not connected\");\n    }\n\n    try {\n      this.state.setPrinting(true);\n      this.updateStatus(\"Preparing to print...\");\n\n      // Create and prepare print job\n      const printJob = new PrintJob(imageData, options);\n      const { imageBuffer, numLines } = printJob.prepare(\n        this.state.ditherMethod\n      );\n      const intensity = printJob.getIntensity(this.state.printIntensity);\n\n      // Configure printer\n      this.updateStatus(\"Configuring printer...\");\n      await this.printer.setIntensity(intensity);\n\n      // Check printer status\n      const status = await this.printer.requestStatus();\n      if (status.length >= 13 && status[12] !== 0) {\n        throw new Error(`Printer error: ${status[13]}`);\n      }\n\n      // Send print request\n      this.updateStatus(\"Sending data...\");\n      const ack = await this.printer.printRequest(numLines, 0);\n      if (!ack || ack[0] !== 0) {\n        throw new Error(\"Print request rejected\");\n      }\n\n      // Send image data\n      await this.printer.sendDataChunks(imageBuffer);\n      await this.printer.flushData();\n\n      // Wait for completion\n      this.updateStatus(\"Printing...\");\n      await this.printer.waitForPrintComplete();\n\n      this.updateStatus(\"Print completed\");\n      await this.getStatus();\n    } catch (error) {\n      const err = error as Error;\n      this.updateStatus(`Error: ${err.message}`);\n      this.eventEmitter.emit({ type: \"error\", error: err });\n      throw error;\n    } finally {\n      this.state.setPrinting(false);\n    }\n  }\n\n  /**\n   * Disconnect from printer\n   */\n  async disconnect(): Promise<void> {\n    if (this.connection?.notifyCharacteristic) {\n      try {\n        await this.connection.notifyCharacteristic.stopNotifications();\n      } catch (error) {\n        console.warn(\"Error stopping notifications:\", error);\n      }\n    }\n\n    if (this.connection) {\n      try {\n        await this.connection.disconnect();\n      } catch (error) {\n        console.warn(\"Error disconnecting:\", error);\n      }\n    }\n\n    this.printer = null;\n    this.connection = null;\n    this.device = null;\n    this.state.reset();\n    this.updateStatus(\"Printer disconnected\");\n    this.eventEmitter.emit({ type: \"disconnected\" });\n  }\n\n  /**\n   * Dispose of the client and clean up resources\n   */\n  dispose(): void {\n    this.disconnect();\n    this.eventEmitter.clear();\n  }\n}\n","// Shared Bluetooth utilities and constants\n\n/**\n * Bluetooth service UUIDs for MXW01 printer\n */\nexport const BLUETOOTH_UUIDS = {\n  // Service UUIDs\n  PRINTER_SERVICE: \"0000ae30-0000-1000-8000-00805f9b34fb\",\n  PRINTER_SERVICE_ALT: \"0000af30-0000-1000-8000-00805f9b34fb\", // macOS alternate\n\n  // Characteristic UUIDs\n  CONTROL: \"0000ae01-0000-1000-8000-00805f9b34fb\",\n  NOTIFY: \"0000ae02-0000-1000-8000-00805f9b34fb\",\n  DATA: \"0000ae03-0000-1000-8000-00805f9b34fb\",\n\n  // Short format for Noble (Node.js)\n  CONTROL_SHORT: \"ae01\",\n  NOTIFY_SHORT: \"ae02\",\n  DATA_SHORT: \"ae03\",\n} as const;\n","// Base characteristic wrapper for Bluetooth adapters\n\nimport type { BluetoothCharacteristic } from \"../core/types\";\n\n/**\n * Base class for wrapping Bluetooth characteristic implementations\n * Provides common functionality for both Web Bluetooth and Noble\n */\nexport abstract class BaseCharacteristicWrapper\n  implements BluetoothCharacteristic\n{\n  protected dataListeners: Map<Function, Function> = new Map();\n\n  abstract writeValueWithoutResponse(data: BufferSource): Promise<void>;\n  abstract startNotifications(): Promise<void>;\n  abstract stopNotifications(): Promise<void>;\n\n  /**\n   * Add event listener (to be implemented by subclasses)\n   */\n  abstract addEventListener(event: string, callback: (event: any) => void): void;\n\n  /**\n   * Remove event listener (to be implemented by subclasses)\n   */\n  abstract removeEventListener(\n    event: string,\n    callback: (event: any) => void\n  ): void;\n\n  /**\n   * Clear all registered listeners\n   */\n  clearListeners(): void {\n    this.dataListeners.clear();\n  }\n}\n","// Web Bluetooth API adapter for browser environments\n\nimport { BLUETOOTH_UUIDS } from \"../utils/bluetooth\";\nimport { BaseCharacteristicWrapper } from \"./BaseCharacteristicWrapper\";\nimport type {\n  BluetoothAdapter,\n  BluetoothDevice as PrinterBluetoothDevice,\n  BluetoothConnection,\n  BluetoothServiceInfo,\n} from \"../core/types\";\n\n/**\n * Wrapper for Web Bluetooth API characteristic to match our interface\n */\nclass WebBluetoothCharacteristicWrapper extends BaseCharacteristicWrapper {\n  constructor(private characteristic: BluetoothRemoteGATTCharacteristic) {\n    super();\n  }\n\n  async writeValueWithoutResponse(data: BufferSource): Promise<void> {\n    await this.characteristic.writeValueWithoutResponse(data);\n  }\n\n  async startNotifications(): Promise<void> {\n    await this.characteristic.startNotifications();\n  }\n\n  async stopNotifications(): Promise<void> {\n    await this.characteristic.stopNotifications();\n  }\n\n  addEventListener(event: string, callback: (event: any) => void): void {\n    this.characteristic.addEventListener(event, callback);\n  }\n\n  removeEventListener(event: string, callback: (event: any) => void): void {\n    this.characteristic.removeEventListener(event, callback);\n  }\n}\n\n/**\n * Web Bluetooth adapter for browser environments\n * Uses the Web Bluetooth API to connect to Bluetooth devices\n */\nexport class WebBluetoothAdapter implements BluetoothAdapter {\n  private device: BluetoothDevice | null = null;\n  private server: BluetoothRemoteGATTServer | null = null;\n\n  /**\n   * Check if Web Bluetooth is available\n   */\n  isAvailable(): boolean {\n    return (\n      typeof navigator !== \"undefined\" &&\n      typeof navigator.bluetooth !== \"undefined\"\n    );\n  }\n\n  /**\n   * Request a Bluetooth device with printer services\n   */\n  async requestDevice(): Promise<PrinterBluetoothDevice> {\n    if (!this.isAvailable()) {\n      throw new Error(\"Web Bluetooth API is not available in this browser\");\n    }\n\n    try {\n      // Request Bluetooth device with support for both standard and macOS UUIDs\n      this.device = await navigator.bluetooth.requestDevice({\n        filters: [\n          { services: [BLUETOOTH_UUIDS.PRINTER_SERVICE] },\n          { services: [BLUETOOTH_UUIDS.PRINTER_SERVICE_ALT] },\n        ],\n        optionalServices: [\n          BLUETOOTH_UUIDS.PRINTER_SERVICE,\n          BLUETOOTH_UUIDS.PRINTER_SERVICE_ALT,\n        ],\n      });\n\n      return {\n        id: this.device.id,\n        name: this.device.name,\n      };\n    } catch (error) {\n      throw new Error(\n        `Failed to request Bluetooth device: ${(error as Error).message}`\n      );\n    }\n  }\n\n  /**\n   * Connect to a Bluetooth device and get service characteristics\n   */\n  async connect(\n    device: PrinterBluetoothDevice\n  ): Promise<BluetoothConnection & BluetoothServiceInfo> {\n    if (!this.device || this.device.id !== device.id) {\n      throw new Error(\"Device not found. Please request device first.\");\n    }\n\n    try {\n      // Connect to GATT server\n      const gatt = this.device.gatt;\n      if (!gatt) {\n        throw new Error(\"GATT not available on device\");\n      }\n      this.server = await gatt.connect();\n      if (!this.server) {\n        throw new Error(\"Failed to connect to GATT server\");\n      }\n\n      // Access printer service - try standard UUID first, then macOS alternate\n      let service: BluetoothRemoteGATTService;\n      try {\n        service = await this.server.getPrimaryService(\n          BLUETOOTH_UUIDS.PRINTER_SERVICE\n        );\n      } catch (error) {\n        console.log(\"Trying alternate UUID for macOS compatibility...\");\n        service = await this.server.getPrimaryService(\n          BLUETOOTH_UUIDS.PRINTER_SERVICE_ALT\n        );\n      }\n\n      // Get characteristics\n      const [controlChar, notifyChar, dataChar] = await Promise.all([\n        service.getCharacteristic(BLUETOOTH_UUIDS.CONTROL),\n        service.getCharacteristic(BLUETOOTH_UUIDS.NOTIFY),\n        service.getCharacteristic(BLUETOOTH_UUIDS.DATA),\n      ]);\n\n      return {\n        device,\n        disconnect: async () => {\n          if (this.server?.connected) {\n            this.server.disconnect();\n          }\n          this.device = null;\n          this.server = null;\n        },\n        controlCharacteristic: new WebBluetoothCharacteristicWrapper(\n          controlChar\n        ),\n        dataCharacteristic: new WebBluetoothCharacteristicWrapper(dataChar),\n        notifyCharacteristic: new WebBluetoothCharacteristicWrapper(notifyChar),\n      };\n    } catch (error) {\n      throw new Error(\n        `Failed to connect to device: ${(error as Error).message}`\n      );\n    }\n  }\n}\n","// Node.js Bluetooth adapter using Noble\n// Requires: @stoprocent/noble\n\nimport { BLUETOOTH_UUIDS } from \"../utils/bluetooth\";\nimport { BaseCharacteristicWrapper } from \"./BaseCharacteristicWrapper\";\nimport type {\n  BluetoothAdapter,\n  BluetoothDevice as PrinterBluetoothDevice,\n  BluetoothConnection,\n  BluetoothServiceInfo,\n} from \"../core/types\";\n\n/**\n * Wrapper for Noble characteristic to match our interface\n */\nclass NobleCharacteristicWrapper extends BaseCharacteristicWrapper {\n  private characteristic: any;\n\n  constructor(characteristic: any) {\n    super();\n    this.characteristic = characteristic;\n  }\n\n  async writeValueWithoutResponse(data: BufferSource): Promise<void> {\n    const buffer = Buffer.from(data as ArrayBuffer);\n    await this.characteristic.writeAsync(buffer, true);\n  }\n\n  async startNotifications(): Promise<void> {\n    await this.characteristic.subscribeAsync();\n  }\n\n  async stopNotifications(): Promise<void> {\n    await this.characteristic.unsubscribeAsync();\n  }\n\n  addEventListener(event: string, callback: (event: any) => void): void {\n    if (event === \"characteristicvaluechanged\") {\n      const dataListener = (data: Buffer) => {\n        callback({\n          target: {\n            value: {\n              buffer: data.buffer.slice(\n                data.byteOffset,\n                data.byteOffset + data.byteLength\n              ),\n            },\n          },\n        });\n      };\n\n      this.dataListeners.set(callback, dataListener);\n      this.characteristic.on(\"data\", dataListener);\n    }\n  }\n\n  removeEventListener(event: string, callback: (event: any) => void): void {\n    if (event === \"characteristicvaluechanged\") {\n      const dataListener = this.dataListeners.get(callback);\n      if (dataListener) {\n        this.characteristic.removeListener(\"data\", dataListener);\n        this.dataListeners.delete(callback);\n      }\n    }\n  }\n}\n\n/**\n * Node.js Bluetooth adapter using Noble\n * Provides native Bluetooth access for Node.js and Bun environments\n *\n * @example\n * ```typescript\n * import { ThermalPrinterClient } from 'react-mxw01-printer';\n * import { NodeBluetoothAdapter } from 'react-mxw01-printer/adapters/node';\n *\n * const adapter = new NodeBluetoothAdapter();\n * const printer = new ThermalPrinterClient(adapter);\n * ```\n *\n * @requires @stoprocent/noble\n */\nexport class NodeBluetoothAdapter implements BluetoothAdapter {\n  private noble: any = null;\n  private peripheral: any = null;\n  private characteristics: {\n    control?: any;\n    notify?: any;\n    data?: any;\n  } = {};\n\n  constructor() {\n    try {\n      // Dynamic import to avoid issues if noble is not installed\n      this.noble = require(\"@stoprocent/noble\");\n    } catch (error) {\n      throw new Error(\n        \"Noble is not installed. Please run: npm install @stoprocent/noble\"\n      );\n    }\n  }\n\n  /**\n   * Check if Bluetooth is available (Noble is loaded)\n   * The powered on state is checked during requestDevice()\n   */\n  isAvailable(): boolean {\n    return this.noble !== null;\n  }\n\n  /**\n   * Scan for and request a Bluetooth printer device\n   * Automatically finds devices with MXW01 printer service UUID\n   */\n  async requestDevice(): Promise<PrinterBluetoothDevice> {\n    return new Promise((resolve, reject) => {\n      const timeout = setTimeout(() => {\n        this.noble.stopScanning();\n        reject(new Error(\"Device scan timeout (30s)\"));\n      }, 30000);\n\n      const onDiscover = (peripheral: any) => {\n        // If Noble discovers it with our filter, it's our printer\n        this.noble.stopScanning();\n        clearTimeout(timeout);\n        this.peripheral = peripheral;\n        this.noble.removeListener(\"discover\", onDiscover);\n\n        resolve({\n          id: peripheral.id || peripheral.uuid,\n          name: peripheral.advertisement.localName || \"MXW01 Printer\",\n        });\n      };\n\n      this.noble.on(\"discover\", onDiscover);\n\n      const startScanning = () => {\n        console.log(\"Scanning for MXW01 printer...\");\n        this.noble.startScanning(\n          [BLUETOOTH_UUIDS.PRINTER_SERVICE, BLUETOOTH_UUIDS.PRINTER_SERVICE_ALT],\n          false\n        );\n      };\n\n      if (this.noble.state === \"poweredOn\") {\n        startScanning();\n      } else {\n        const onStateChange = (state: string) => {\n          if (state === \"poweredOn\") {\n            this.noble.removeListener(\"stateChange\", onStateChange);\n            startScanning();\n          }\n        };\n        this.noble.on(\"stateChange\", onStateChange);\n      }\n    });\n  }\n\n  /**\n   * Connect to a Bluetooth device and get printer service characteristics\n   */\n  async connect(\n    device: PrinterBluetoothDevice\n  ): Promise<BluetoothConnection & BluetoothServiceInfo> {\n    if (!this.peripheral) {\n      throw new Error(\"No peripheral found. Call requestDevice() first.\");\n    }\n\n    try {\n      // Connect to peripheral\n      await this.peripheral.connectAsync();\n      console.log(\"Connected to peripheral\");\n\n      // Discover all services and characteristics (Noble works better without filters)\n      const { characteristics } =\n        await this.peripheral.discoverAllServicesAndCharacteristicsAsync();\n\n      console.log(`Found ${characteristics.length} characteristics`);\n\n      // Find the required characteristics by short UUID (Noble uses short format)\n      this.characteristics.control = characteristics.find(\n        (c: any) => c.uuid === BLUETOOTH_UUIDS.CONTROL_SHORT\n      );\n      this.characteristics.notify = characteristics.find(\n        (c: any) => c.uuid === BLUETOOTH_UUIDS.NOTIFY_SHORT\n      );\n      this.characteristics.data = characteristics.find(\n        (c: any) => c.uuid === BLUETOOTH_UUIDS.DATA_SHORT\n      );\n\n      console.log(\"Control:\", this.characteristics.control ? \"✅\" : \"❌\");\n      console.log(\"Notify:\", this.characteristics.notify ? \"✅\" : \"❌\");\n      console.log(\"Data:\", this.characteristics.data ? \"✅\" : \"❌\");\n\n      // Verify all required characteristics are found\n      if (\n        !this.characteristics.control ||\n        !this.characteristics.notify ||\n        !this.characteristics.data\n      ) {\n        throw new Error(\n          `Missing required characteristics. Found: ${Object.keys(\n            this.characteristics\n          ).join(\", \")}`\n        );\n      }\n\n      const peripheral = this.peripheral;\n\n      return {\n        device,\n        disconnect: async () => {\n          if (peripheral && peripheral.state === \"connected\") {\n            await peripheral.disconnectAsync();\n            console.log(\"Disconnected from peripheral\");\n          }\n          this.peripheral = null;\n          this.characteristics = {};\n        },\n        controlCharacteristic: new NobleCharacteristicWrapper(\n          this.characteristics.control\n        ),\n        dataCharacteristic: new NobleCharacteristicWrapper(\n          this.characteristics.data\n        ),\n        notifyCharacteristic: new NobleCharacteristicWrapper(\n          this.characteristics.notify\n        ),\n      };\n    } catch (error) {\n      // Ensure we disconnect on error\n      if (this.peripheral && this.peripheral.state === \"connected\") {\n        try {\n          await this.peripheral.disconnectAsync();\n        } catch (disconnectError) {\n          console.error(\"Error disconnecting:\", disconnectError);\n        }\n      }\n      throw new Error(\n        `Failed to connect to device: ${(error as Error).message}`\n      );\n    }\n  }\n}\n"],"names":["CRC8_TABLE","crc8","data","crc","byte","delay","msecs","resolve","Command","PROTOCOL","makeCommand","command","payload","len","header","cmdWithPayload","crcValue","result","parseNotification","message","cmdId","parsePrinterState","statusByte","createDefaultState","PrinterStateManager","newState","resolver","timeoutMs","reject","timer","PRINTER_WIDTH","PRINTER_WIDTH_BYTES","MIN_DATA_BYTES","MXW01Printer","controlWrite","dataWrite","parsed","intensity","lines","mode","chunkSize","pos","chunk","startTime","encode1bppRow","rowBool","rowBytes","byteIndex","byteVal","bit","prepareImageDataBuffer","imageRowsBool","height","buffer","y","newBuf","pad","EventEmitter","eventType","listener","listeners","event","error","ClientState","value","state","method","DitherAlgorithm","ThresholdDither","mono","_width","_height","SteinbergDither","width","p","j","i","oldPixel","newPixel","BayerDither","bayerValue","pixelValue","AtkinsonDither","HalftoneDither","sum","x","threshold","getDitherAlgorithm","rotate","angle","outX","outY","flip","rgbaToGray","rgba","brightness","alphaAsWhite","n","r","g","b","alpha","a","gray","grayToRgba","whiteAsTransparent","base","cropImageData","source","targetWidth","targetHeight","croppedWidth","croppedHeight","cropped","srcIdx","dstIdx","processImageForPrinter","imageData","options","rgbaData","finalWidth","finalHeight","processedData","binaryRows","row","idx","lum","PrintJob","defaultDither","processingOptions","processedImage","defaultIntensity","ThermalPrinterClient","adapter","newPrinterState","err","notifier","printJob","imageBuffer","numLines","status","ack","BLUETOOTH_UUIDS","BaseCharacteristicWrapper","WebBluetoothCharacteristicWrapper","characteristic","callback","WebBluetoothAdapter","device","gatt","service","controlChar","notifyChar","dataChar","NobleCharacteristicWrapper","dataListener","NodeBluetoothAdapter","timeout","onDiscover","peripheral","startScanning","onStateChange","characteristics","c","disconnectError"],"mappings":"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"}