From a6330d3b08d684a0a8f538b134d4c013fe0c817f Mon Sep 17 00:00:00 2001 From: Gaspard Beernaert Date: Tue, 3 Feb 2026 07:35:50 +0100 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74438=20[oled-?= =?UTF-8?q?i2c-bus]=20Add=20type=20definitions=20by=20@gasp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/oled-i2c-bus/.npmignore | 5 + types/oled-i2c-bus/index.d.ts | 418 +++++++++++++++++++++++ types/oled-i2c-bus/oled-i2c-bus-tests.ts | 273 +++++++++++++++ types/oled-i2c-bus/package.json | 21 ++ types/oled-i2c-bus/tsconfig.json | 14 + 5 files changed, 731 insertions(+) create mode 100644 types/oled-i2c-bus/.npmignore create mode 100644 types/oled-i2c-bus/index.d.ts create mode 100644 types/oled-i2c-bus/oled-i2c-bus-tests.ts create mode 100644 types/oled-i2c-bus/package.json create mode 100644 types/oled-i2c-bus/tsconfig.json diff --git a/types/oled-i2c-bus/.npmignore b/types/oled-i2c-bus/.npmignore new file mode 100644 index 00000000000000..93e307400a5456 --- /dev/null +++ b/types/oled-i2c-bus/.npmignore @@ -0,0 +1,5 @@ +* +!**/*.d.ts +!**/*.d.cts +!**/*.d.mts +!**/*.d.*.ts diff --git a/types/oled-i2c-bus/index.d.ts b/types/oled-i2c-bus/index.d.ts new file mode 100644 index 00000000000000..2c1f01bcd901ef --- /dev/null +++ b/types/oled-i2c-bus/index.d.ts @@ -0,0 +1,418 @@ +/// + +import { I2CBus } from 'i2c-bus' + +/** + * OLED display controller for I2C connected monochrome OLED screens. + * Supports SSD1306 and SH1106 driver chips. + */ +declare class Oled { + /** Display width in pixels */ + readonly WIDTH: number + /** Display height in pixels */ + readonly HEIGHT: number + /** Current driver type */ + readonly DRIVER: Oled.DriverType + + /** + * Creates a new OLED display instance. + * + * @param i2c - An open I2C bus instance from the i2c-bus package + * @param opts - Configuration options for the display + * + * @example + * ```javascript + * const i2c = require('i2c-bus'); + * const Oled = require('oled-i2c-bus'); + * + * const i2cBus = i2c.openSync(1); + * const oled = new Oled(i2cBus, { + * width: 128, + * height: 64, + * address: 0x3C, + * driver: 'SSD1306' + * }); + * ``` + */ + constructor(i2c: I2CBus, opts: Oled.OledOptions) + + // ==================== Display Control ==================== + + /** + * Turns the display on. + */ + turnOnDisplay(): void + + /** + * Turns the display off. + */ + turnOffDisplay(): void + + /** + * Dims or restores the display contrast. + * + * @param bool - true to dim the display, false to restore normal contrast + */ + dimDisplay(bool: boolean): void + + /** + * Inverts the display colors. + * Black becomes white, white becomes black. + * + * @param bool - true for inverted state, false for normal colors + */ + invertDisplay(bool: boolean): void + + /** + * Activates scrolling for the display content. + * Note: SH1106 does not support scrolling. + * + * @param dir - Direction of scrolling: 'left', 'right', 'left diagonal', or 'right diagonal' + * @param start - Starting row of scrolling area + * @param stop - End row of scrolling area + * + * @example + * ```javascript + * // Scroll entire 128x32 screen to the left + * oled.startScroll('left', 0, 15); + * ``` + */ + startScroll(dir: Oled.ScrollDirection, start: number, stop: number): void + + /** + * Stops all current scrolling behavior. + */ + stopScroll(): void + + /** + * Sends the entire framebuffer to the OLED display. + * Synchronizes the internal buffer with the display. + * Usually called automatically by drawing methods when sync is true. + */ + update(): void + + // ==================== Drawing Methods ==================== + + /** + * Clears all pixels on the display (fills with black). + * + * @param sync - If true, updates the display immediately. Default: true + */ + clearDisplay(sync?: boolean): void + + /** + * Sets the cursor position for text writing. + * Call this before writeString() to set the starting position. + * + * @param x - X coordinate (column) + * @param y - Y coordinate (row) + */ + setCursor(x: number, y: number): void + + /** + * Draws a byte at a specific page and column. + * Low-level method for direct buffer manipulation. + * + * @param page - Page number (0 to HEIGHT/8 - 1) + * @param col - Column number (0 to WIDTH - 1) + * @param byte - Byte value to write + */ + drawPageCol(page: number, col: number, byte: number): void + + /** + * Draws a byte at a specific page and segment. + * Low-level method for direct buffer manipulation. + * + * @param page - Page number (0 to HEIGHT/8 - 1) + * @param seg - Segment number (0 to WIDTH - 1) + * @param byte - Byte value to write + * @param sync - If true, updates the display immediately. Default: false + */ + drawPageSeg(page: number, seg: number, byte: number, sync?: boolean): void + + /** + * Draws one or more pixels on the display. + * + * @param pixels - Single pixel [x, y, color] or array of pixels [[x, y, color], ...] + * @param sync - If true, updates the display immediately. Default: true + * + * @example + * ```javascript + * // Draw a single pixel + * oled.drawPixel([64, 32, 1]); + * + * // Draw multiple pixels + * oled.drawPixel([ + * [0, 0, 1], + * [127, 0, 1], + * [64, 32, 1] + * ]); + * ``` + */ + drawPixel(pixels: Oled.Pixel | Oled.Pixel[], sync?: boolean): void + + /** + * Draws a line using Bresenham's line algorithm. + * + * @param x0 - Start X coordinate + * @param y0 - Start Y coordinate + * @param x1 - End X coordinate + * @param y1 - End Y coordinate + * @param color - Pixel color (0 for off/black, 1 for on/white) + * @param sync - If true, updates the display immediately. Default: true + * + * @example + * ```javascript + * oled.drawLine(0, 0, 127, 63, 1); + * ``` + */ + drawLine( + x0: number, + y0: number, + x1: number, + y1: number, + color: Oled.Color, + sync?: boolean, + ): void + + /** + * Draws a filled rectangle. + * + * @param x - Top-left X coordinate + * @param y - Top-left Y coordinate + * @param w - Width in pixels + * @param h - Height in pixels + * @param color - Fill color (0 for off/black, 1 for on/white) + * @param sync - If true, updates the display immediately. Default: true + * + * @example + * ```javascript + * oled.fillRect(10, 10, 50, 30, 1); + * ``` + */ + fillRect( + x: number, + y: number, + w: number, + h: number, + color: Oled.Color, + sync?: boolean, + ): void + + /** + * Writes a string of text to the display. + * Use setCursor() before this to set the starting position. + * + * @param font - Font object (e.g., from oled-font-5x7 or oled-font-pack) + * @param size - Font size multiplier (1 = normal, 2 = double, etc.) + * @param string - Text to display + * @param color - Text color (0 for off/black, 1 for on/white) + * @param wrap - If true, wraps text at screen edge + * @param sync - If true, updates the display immediately. Default: true + * + * @example + * ```javascript + * const font = require('oled-font-5x7'); + * oled.setCursor(0, 0); + * oled.writeString(font, 1, 'Hello World!', 1, true); + * ``` + */ + writeString( + font: Oled.Font, + size: number, + string: string, + color: Oled.Color, + wrap: boolean, + sync?: boolean, + ): void + + /** + * Draws an RGBA image at the specified coordinates. + * Transparent pixels are skipped. + * Any pixel with RGB color becomes white, (0,0,0) becomes black. + * + * @param image - RGBA image object (compatible with pngjs) + * @param dx - Destination X coordinate + * @param dy - Destination Y coordinate + * @param sync - If true, updates the display immediately. Default: true + * + * @example + * ```javascript + * const PNG = require('pngjs').PNG; + * const fs = require('fs'); + * + * fs.createReadStream('image.png') + * .pipe(new PNG({ filterType: 4 })) + * .on('parsed', function() { + * oled.drawRGBAImage(this, 0, 0, true); + * }); + * ``` + */ + drawRGBAImage( + image: Oled.RGBAImage, + dx: number, + dy: number, + sync?: boolean, + ): void + + /** + * Draws a bitmap from raw pixel data. + * The bitmap must be monochrome and match the display dimensions. + * + * @param pixels - Array of pixel values (0 or 1) + * @param sync - If true, updates the display immediately. Default: true + * + * @example + * ```javascript + * const pngparse = require('pngparse'); + * pngparse.parseFile('image.png', function(err, image) { + * oled.drawBitmap(image.data); + * }); + * ``` + */ + drawBitmap(pixels: number[], sync?: boolean): void + + // ==================== Indicator Methods ==================== + + /** + * Draws a battery level indicator icon. + * Shows 0-3 bars based on percentage level. + * + * @param x - Start X coordinate + * @param y - Start Y coordinate + * @param percentage - Battery level (0-100) + * + * @example + * ```javascript + * oled.battery(100, 0, 75); // Shows 3 bars + * ``` + */ + battery(x: number, y: number, percentage: number): void + + /** + * Draws a Bluetooth icon. + * + * @param x - Start X coordinate + * @param y - Start Y coordinate + */ + bluetooth(x: number, y: number): void + + /** + * Draws a WiFi signal strength indicator icon. + * Shows 0-3 bars based on signal percentage. + * + * @param x - Start X coordinate + * @param y - Start Y coordinate + * @param percentage - Signal strength (0-100) + * + * @example + * ```javascript + * oled.wifi(110, 0, 80); // Shows 3 bars + * ``` + */ + wifi(x: number, y: number, percentage: number): void + + /** + * Displays an image with optional animation. + * A wrapper for drawRGBAImage with additional features. + * + * @param x - Start X coordinate (ignored when animated is true) + * @param y - Start Y coordinate (ignored when animated is true) + * @param image - Full path to image or filename in resources folder + * @param font - Font object for error messages + * @param clear - If true, clears display before drawing + * @param reset - If true, stops all animations + * @param animated - If true, enables bouncing animation + * @param wrapping - If true, wraps error message text + * + * @example + * ```javascript + * const font = require('oled-font-5x7'); + * oled.image(0, 0, 'logo.png', font, true, false, false, true); + * ``` + */ + image( + x: number, + y: number, + image: string, + font: Oled.Font, + clear: boolean, + reset: boolean, + animated: boolean, + wrapping: boolean, + ): void +} + +declare namespace Oled { + /** + * Color value for drawing operations. + * 0 = off/black, 1 or any truthy value = on/white + * Can also use string 'BLACK' or 'WHITE' + */ + type Color = number | boolean | 'BLACK' | 'WHITE' + + /** + * Scroll direction for startScroll method. + */ + type ScrollDirection = 'left' | 'right' | 'left diagonal' | 'right diagonal' + + /** + * Supported OLED driver types. + */ + type DriverType = 'SSD1306' | 'SH1106' + + /** + * A single pixel definition: [x, y, color] + */ + type Pixel = [number, number, Color] + + /** + * Font object structure used by writeString method. + * Compatible with oled-font-5x7 and oled-font-pack packages. + */ + interface Font { + /** Width of each character in pixels */ + width: number + /** Height of each character in pixels */ + height: number + /** Array of character lookup strings */ + lookup: string[] + /** Array of font bitmap data */ + fontData: number[] + } + + /** + * RGBA Image structure compatible with pngjs. + * Used by drawRGBAImage method. + */ + interface RGBAImage { + /** Width of the image in pixels */ + width: number + /** Height of the image in pixels */ + height: number + /** Raw RGBA pixel data buffer (4 bytes per pixel) */ + data: Buffer | Uint8Array + } + + /** + * Options for initializing the OLED display. + */ + interface OledOptions { + /** Width of the display in pixels. Default: 128 */ + width?: number + /** Height of the display in pixels. Default: 64 */ + height?: number + /** I2C address of the display. Default: 0x3C */ + address?: number + /** I2C bus number. Default: 1 */ + bus?: number + /** Driver type: 'SSD1306' or 'SH1106'. Default: 'SSD1306' */ + driver?: DriverType + /** Line spacing in pixels for text. Default: 1 */ + linespacing?: number + /** Letter spacing in pixels for text. Default: 1 */ + letterspacing?: number + } +} + +export = Oled diff --git a/types/oled-i2c-bus/oled-i2c-bus-tests.ts b/types/oled-i2c-bus/oled-i2c-bus-tests.ts new file mode 100644 index 00000000000000..aba20996116026 --- /dev/null +++ b/types/oled-i2c-bus/oled-i2c-bus-tests.ts @@ -0,0 +1,273 @@ +import Oled = require('oled-i2c-bus') +import { openSync } from 'i2c-bus' + +// Test: Constructor with minimal options +function testConstructorMinimal(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, {}) + + // Verify readonly properties exist + const width: number = oled.WIDTH + const height: number = oled.HEIGHT + const driver: string = oled.DRIVER +} + +// Test: Constructor with full options +function testConstructorFull(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { + width: 128, + height: 64, + address: 0x3c, + bus: 1, + driver: 'SSD1306', + linespacing: 1, + letterspacing: 1, + }) +} + +// Test: Constructor with SH1106 driver +function testConstructorSH1106(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { + width: 128, + height: 64, + driver: 'SH1106', + }) +} + +// Test: Display control methods +function testDisplayControl(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + oled.turnOnDisplay() + oled.turnOffDisplay() + oled.dimDisplay(true) + oled.dimDisplay(false) + oled.invertDisplay(true) + oled.invertDisplay(false) + oled.startScroll('left', 0, 15) + oled.startScroll('right', 0, 15) + oled.startScroll('left diagonal', 0, 15) + oled.startScroll('right diagonal', 0, 15) + oled.stopScroll() + oled.update() +} + +// Test: Clear display +function testClearDisplay(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + oled.clearDisplay() + oled.clearDisplay(true) + oled.clearDisplay(false) +} + +// Test: Cursor +function testCursor(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + oled.setCursor(0, 0) + oled.setCursor(64, 32) +} + +// Test: Low-level page/segment drawing +function testPageDrawing(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + oled.drawPageCol(0, 0, 0xff) + oled.drawPageSeg(0, 0, 0xff) + oled.drawPageSeg(0, 0, 0xff, true) + oled.drawPageSeg(0, 0, 0xff, false) +} + +// Test: Draw pixels +function testDrawPixel(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + // Single pixel + oled.drawPixel([64, 32, 1]) + oled.drawPixel([64, 32, 0]) + oled.drawPixel([64, 32, true]) + oled.drawPixel([64, 32, false]) + + // Multiple pixels + oled.drawPixel([ + [0, 0, 1], + [127, 0, 1], + [0, 63, 1], + [127, 63, 1], + ]) + + // With sync parameter + oled.drawPixel([64, 32, 1], true) + oled.drawPixel([64, 32, 1], false) +} + +// Test: Draw line +function testDrawLine(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + oled.drawLine(0, 0, 127, 63, 1) + oled.drawLine(0, 0, 127, 63, 0) + oled.drawLine(0, 0, 127, 63, 1, true) + oled.drawLine(0, 0, 127, 63, 1, false) +} + +// Test: Fill rectangle +function testFillRect(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + oled.fillRect(10, 10, 50, 30, 1) + oled.fillRect(10, 10, 50, 30, 0) + oled.fillRect(10, 10, 50, 30, 1, true) + oled.fillRect(10, 10, 50, 30, 1, false) +} + +// Test: Write string +function testWriteString(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + // Mock font object matching oled-font-5x7 structure + const font: Oled.Font = { + width: 5, + height: 7, + lookup: ['A', 'B', 'C'], + fontData: [0x00, 0x00, 0x00, 0x00, 0x00], + } + + oled.setCursor(0, 0) + oled.writeString(font, 1, 'Hello World!', 1, true) + oled.writeString(font, 2, 'Big Text', 1, false) + oled.writeString(font, 1, 'With sync', 1, true, true) + oled.writeString(font, 1, 'Without sync', 1, true, false) +} + +// Test: Draw RGBA image +function testDrawRGBAImage(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + // Mock RGBA image (compatible with pngjs) + const image: Oled.RGBAImage = { + width: 32, + height: 32, + data: Buffer.alloc(32 * 32 * 4), + } + + oled.drawRGBAImage(image, 0, 0) + oled.drawRGBAImage(image, 48, 16, true) + oled.drawRGBAImage(image, 48, 16, false) +} + +// Test: Draw bitmap +function testDrawBitmap(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + const pixels: number[] = new Array(128 * 64).fill(0) + oled.drawBitmap(pixels) + oled.drawBitmap(pixels, true) + oled.drawBitmap(pixels, false) +} + +// Test: Battery indicator +function testBattery(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + oled.battery(100, 0, 100) // Full battery + oled.battery(100, 0, 75) // 3 bars + oled.battery(100, 0, 50) // 2 bars + oled.battery(100, 0, 25) // 1 bar + oled.battery(100, 0, 5) // 0 bars +} + +// Test: Bluetooth icon +function testBluetooth(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + oled.bluetooth(0, 0) +} + +// Test: WiFi indicator +function testWifi(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + oled.wifi(110, 0, 100) // Full signal + oled.wifi(110, 0, 75) // 3 bars + oled.wifi(110, 0, 50) // 2 bars + oled.wifi(110, 0, 25) // 1 bar + oled.wifi(110, 0, 5) // 0 bars +} + +// Test: Image method +function testImage(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { width: 128, height: 64 }) + + const font: Oled.Font = { + width: 5, + height: 7, + lookup: ['A', 'B', 'C'], + fontData: [0x00, 0x00, 0x00, 0x00, 0x00], + } + + // Display static image + oled.image(0, 0, 'logo.png', font, true, false, false, true) + + // Display animated image + oled.image(0, 0, 'logo.png', font, true, false, true, true) + + // Reset animations + oled.image(0, 0, '', font, true, true, false, false) +} + +// Test: Complete workflow example +function testCompleteWorkflow(): void { + const i2cBus = openSync(1) + const oled = new Oled(i2cBus, { + width: 128, + height: 64, + address: 0x3c, + driver: 'SSD1306', + }) + + // Initialize display + oled.clearDisplay(true) + oled.turnOnDisplay() + + // Draw some content + oled.fillRect(0, 0, oled.WIDTH, 10, 1, false) + + const font: Oled.Font = { + width: 5, + height: 7, + lookup: ['H', 'e', 'l', 'o', ' ', 'W', 'r', 'd', '!'], + fontData: new Array(45).fill(0), + } + + oled.setCursor(2, 2) + oled.writeString(font, 1, 'Hello World!', 0, false, false) + + // Draw battery and wifi indicators + oled.battery(100, 0, 75) + oled.wifi(80, 0, 80) + oled.bluetooth(60, 0) + + // Update display + oled.update() + + // Cleanup + oled.turnOffDisplay() +} diff --git a/types/oled-i2c-bus/package.json b/types/oled-i2c-bus/package.json new file mode 100644 index 00000000000000..a50863037a25e9 --- /dev/null +++ b/types/oled-i2c-bus/package.json @@ -0,0 +1,21 @@ +{ + "private": true, + "name": "@types/oled-i2c-bus", + "version": "1.0.9999", + "projects": [ + "https://github.com/baltazorr/oled-i2c-bus" + ], + "dependencies": { + "@types/i2c-bus": "*", + "@types/node": "*" + }, + "devDependencies": { + "@types/oled-i2c-bus": "workspace:." + }, + "owners": [ + { + "name": "Gaspard", + "githubUsername": "gasp" + } + ] +} \ No newline at end of file diff --git a/types/oled-i2c-bus/tsconfig.json b/types/oled-i2c-bus/tsconfig.json new file mode 100644 index 00000000000000..59ea5b94d6facb --- /dev/null +++ b/types/oled-i2c-bus/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es6"], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": ["index.d.ts", "oled-i2c-bus-tests.ts"] +} From 8b5952e6cf75b5723ce6ee85627c5fb1c61f991f Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Tue, 3 Feb 2026 06:36:32 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=A4=96=20dprint=20fmt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/oled-i2c-bus/index.d.ts | 810 +++++++++++------------ types/oled-i2c-bus/oled-i2c-bus-tests.ts | 378 +++++------ types/oled-i2c-bus/package.json | 2 +- 3 files changed, 595 insertions(+), 595 deletions(-) diff --git a/types/oled-i2c-bus/index.d.ts b/types/oled-i2c-bus/index.d.ts index 2c1f01bcd901ef..5aca463d001c90 100644 --- a/types/oled-i2c-bus/index.d.ts +++ b/types/oled-i2c-bus/index.d.ts @@ -1,418 +1,418 @@ /// -import { I2CBus } from 'i2c-bus' +import { I2CBus } from "i2c-bus"; /** * OLED display controller for I2C connected monochrome OLED screens. * Supports SSD1306 and SH1106 driver chips. */ declare class Oled { - /** Display width in pixels */ - readonly WIDTH: number - /** Display height in pixels */ - readonly HEIGHT: number - /** Current driver type */ - readonly DRIVER: Oled.DriverType - - /** - * Creates a new OLED display instance. - * - * @param i2c - An open I2C bus instance from the i2c-bus package - * @param opts - Configuration options for the display - * - * @example - * ```javascript - * const i2c = require('i2c-bus'); - * const Oled = require('oled-i2c-bus'); - * - * const i2cBus = i2c.openSync(1); - * const oled = new Oled(i2cBus, { - * width: 128, - * height: 64, - * address: 0x3C, - * driver: 'SSD1306' - * }); - * ``` - */ - constructor(i2c: I2CBus, opts: Oled.OledOptions) - - // ==================== Display Control ==================== - - /** - * Turns the display on. - */ - turnOnDisplay(): void - - /** - * Turns the display off. - */ - turnOffDisplay(): void - - /** - * Dims or restores the display contrast. - * - * @param bool - true to dim the display, false to restore normal contrast - */ - dimDisplay(bool: boolean): void - - /** - * Inverts the display colors. - * Black becomes white, white becomes black. - * - * @param bool - true for inverted state, false for normal colors - */ - invertDisplay(bool: boolean): void - - /** - * Activates scrolling for the display content. - * Note: SH1106 does not support scrolling. - * - * @param dir - Direction of scrolling: 'left', 'right', 'left diagonal', or 'right diagonal' - * @param start - Starting row of scrolling area - * @param stop - End row of scrolling area - * - * @example - * ```javascript - * // Scroll entire 128x32 screen to the left - * oled.startScroll('left', 0, 15); - * ``` - */ - startScroll(dir: Oled.ScrollDirection, start: number, stop: number): void - - /** - * Stops all current scrolling behavior. - */ - stopScroll(): void - - /** - * Sends the entire framebuffer to the OLED display. - * Synchronizes the internal buffer with the display. - * Usually called automatically by drawing methods when sync is true. - */ - update(): void - - // ==================== Drawing Methods ==================== - - /** - * Clears all pixels on the display (fills with black). - * - * @param sync - If true, updates the display immediately. Default: true - */ - clearDisplay(sync?: boolean): void - - /** - * Sets the cursor position for text writing. - * Call this before writeString() to set the starting position. - * - * @param x - X coordinate (column) - * @param y - Y coordinate (row) - */ - setCursor(x: number, y: number): void - - /** - * Draws a byte at a specific page and column. - * Low-level method for direct buffer manipulation. - * - * @param page - Page number (0 to HEIGHT/8 - 1) - * @param col - Column number (0 to WIDTH - 1) - * @param byte - Byte value to write - */ - drawPageCol(page: number, col: number, byte: number): void - - /** - * Draws a byte at a specific page and segment. - * Low-level method for direct buffer manipulation. - * - * @param page - Page number (0 to HEIGHT/8 - 1) - * @param seg - Segment number (0 to WIDTH - 1) - * @param byte - Byte value to write - * @param sync - If true, updates the display immediately. Default: false - */ - drawPageSeg(page: number, seg: number, byte: number, sync?: boolean): void - - /** - * Draws one or more pixels on the display. - * - * @param pixels - Single pixel [x, y, color] or array of pixels [[x, y, color], ...] - * @param sync - If true, updates the display immediately. Default: true - * - * @example - * ```javascript - * // Draw a single pixel - * oled.drawPixel([64, 32, 1]); - * - * // Draw multiple pixels - * oled.drawPixel([ - * [0, 0, 1], - * [127, 0, 1], - * [64, 32, 1] - * ]); - * ``` - */ - drawPixel(pixels: Oled.Pixel | Oled.Pixel[], sync?: boolean): void - - /** - * Draws a line using Bresenham's line algorithm. - * - * @param x0 - Start X coordinate - * @param y0 - Start Y coordinate - * @param x1 - End X coordinate - * @param y1 - End Y coordinate - * @param color - Pixel color (0 for off/black, 1 for on/white) - * @param sync - If true, updates the display immediately. Default: true - * - * @example - * ```javascript - * oled.drawLine(0, 0, 127, 63, 1); - * ``` - */ - drawLine( - x0: number, - y0: number, - x1: number, - y1: number, - color: Oled.Color, - sync?: boolean, - ): void - - /** - * Draws a filled rectangle. - * - * @param x - Top-left X coordinate - * @param y - Top-left Y coordinate - * @param w - Width in pixels - * @param h - Height in pixels - * @param color - Fill color (0 for off/black, 1 for on/white) - * @param sync - If true, updates the display immediately. Default: true - * - * @example - * ```javascript - * oled.fillRect(10, 10, 50, 30, 1); - * ``` - */ - fillRect( - x: number, - y: number, - w: number, - h: number, - color: Oled.Color, - sync?: boolean, - ): void - - /** - * Writes a string of text to the display. - * Use setCursor() before this to set the starting position. - * - * @param font - Font object (e.g., from oled-font-5x7 or oled-font-pack) - * @param size - Font size multiplier (1 = normal, 2 = double, etc.) - * @param string - Text to display - * @param color - Text color (0 for off/black, 1 for on/white) - * @param wrap - If true, wraps text at screen edge - * @param sync - If true, updates the display immediately. Default: true - * - * @example - * ```javascript - * const font = require('oled-font-5x7'); - * oled.setCursor(0, 0); - * oled.writeString(font, 1, 'Hello World!', 1, true); - * ``` - */ - writeString( - font: Oled.Font, - size: number, - string: string, - color: Oled.Color, - wrap: boolean, - sync?: boolean, - ): void - - /** - * Draws an RGBA image at the specified coordinates. - * Transparent pixels are skipped. - * Any pixel with RGB color becomes white, (0,0,0) becomes black. - * - * @param image - RGBA image object (compatible with pngjs) - * @param dx - Destination X coordinate - * @param dy - Destination Y coordinate - * @param sync - If true, updates the display immediately. Default: true - * - * @example - * ```javascript - * const PNG = require('pngjs').PNG; - * const fs = require('fs'); - * - * fs.createReadStream('image.png') - * .pipe(new PNG({ filterType: 4 })) - * .on('parsed', function() { - * oled.drawRGBAImage(this, 0, 0, true); - * }); - * ``` - */ - drawRGBAImage( - image: Oled.RGBAImage, - dx: number, - dy: number, - sync?: boolean, - ): void - - /** - * Draws a bitmap from raw pixel data. - * The bitmap must be monochrome and match the display dimensions. - * - * @param pixels - Array of pixel values (0 or 1) - * @param sync - If true, updates the display immediately. Default: true - * - * @example - * ```javascript - * const pngparse = require('pngparse'); - * pngparse.parseFile('image.png', function(err, image) { - * oled.drawBitmap(image.data); - * }); - * ``` - */ - drawBitmap(pixels: number[], sync?: boolean): void - - // ==================== Indicator Methods ==================== - - /** - * Draws a battery level indicator icon. - * Shows 0-3 bars based on percentage level. - * - * @param x - Start X coordinate - * @param y - Start Y coordinate - * @param percentage - Battery level (0-100) - * - * @example - * ```javascript - * oled.battery(100, 0, 75); // Shows 3 bars - * ``` - */ - battery(x: number, y: number, percentage: number): void - - /** - * Draws a Bluetooth icon. - * - * @param x - Start X coordinate - * @param y - Start Y coordinate - */ - bluetooth(x: number, y: number): void - - /** - * Draws a WiFi signal strength indicator icon. - * Shows 0-3 bars based on signal percentage. - * - * @param x - Start X coordinate - * @param y - Start Y coordinate - * @param percentage - Signal strength (0-100) - * - * @example - * ```javascript - * oled.wifi(110, 0, 80); // Shows 3 bars - * ``` - */ - wifi(x: number, y: number, percentage: number): void - - /** - * Displays an image with optional animation. - * A wrapper for drawRGBAImage with additional features. - * - * @param x - Start X coordinate (ignored when animated is true) - * @param y - Start Y coordinate (ignored when animated is true) - * @param image - Full path to image or filename in resources folder - * @param font - Font object for error messages - * @param clear - If true, clears display before drawing - * @param reset - If true, stops all animations - * @param animated - If true, enables bouncing animation - * @param wrapping - If true, wraps error message text - * - * @example - * ```javascript - * const font = require('oled-font-5x7'); - * oled.image(0, 0, 'logo.png', font, true, false, false, true); - * ``` - */ - image( - x: number, - y: number, - image: string, - font: Oled.Font, - clear: boolean, - reset: boolean, - animated: boolean, - wrapping: boolean, - ): void + /** Display width in pixels */ + readonly WIDTH: number; + /** Display height in pixels */ + readonly HEIGHT: number; + /** Current driver type */ + readonly DRIVER: Oled.DriverType; + + /** + * Creates a new OLED display instance. + * + * @param i2c - An open I2C bus instance from the i2c-bus package + * @param opts - Configuration options for the display + * + * @example + * ```javascript + * const i2c = require('i2c-bus'); + * const Oled = require('oled-i2c-bus'); + * + * const i2cBus = i2c.openSync(1); + * const oled = new Oled(i2cBus, { + * width: 128, + * height: 64, + * address: 0x3C, + * driver: 'SSD1306' + * }); + * ``` + */ + constructor(i2c: I2CBus, opts: Oled.OledOptions); + + // ==================== Display Control ==================== + + /** + * Turns the display on. + */ + turnOnDisplay(): void; + + /** + * Turns the display off. + */ + turnOffDisplay(): void; + + /** + * Dims or restores the display contrast. + * + * @param bool - true to dim the display, false to restore normal contrast + */ + dimDisplay(bool: boolean): void; + + /** + * Inverts the display colors. + * Black becomes white, white becomes black. + * + * @param bool - true for inverted state, false for normal colors + */ + invertDisplay(bool: boolean): void; + + /** + * Activates scrolling for the display content. + * Note: SH1106 does not support scrolling. + * + * @param dir - Direction of scrolling: 'left', 'right', 'left diagonal', or 'right diagonal' + * @param start - Starting row of scrolling area + * @param stop - End row of scrolling area + * + * @example + * ```javascript + * // Scroll entire 128x32 screen to the left + * oled.startScroll('left', 0, 15); + * ``` + */ + startScroll(dir: Oled.ScrollDirection, start: number, stop: number): void; + + /** + * Stops all current scrolling behavior. + */ + stopScroll(): void; + + /** + * Sends the entire framebuffer to the OLED display. + * Synchronizes the internal buffer with the display. + * Usually called automatically by drawing methods when sync is true. + */ + update(): void; + + // ==================== Drawing Methods ==================== + + /** + * Clears all pixels on the display (fills with black). + * + * @param sync - If true, updates the display immediately. Default: true + */ + clearDisplay(sync?: boolean): void; + + /** + * Sets the cursor position for text writing. + * Call this before writeString() to set the starting position. + * + * @param x - X coordinate (column) + * @param y - Y coordinate (row) + */ + setCursor(x: number, y: number): void; + + /** + * Draws a byte at a specific page and column. + * Low-level method for direct buffer manipulation. + * + * @param page - Page number (0 to HEIGHT/8 - 1) + * @param col - Column number (0 to WIDTH - 1) + * @param byte - Byte value to write + */ + drawPageCol(page: number, col: number, byte: number): void; + + /** + * Draws a byte at a specific page and segment. + * Low-level method for direct buffer manipulation. + * + * @param page - Page number (0 to HEIGHT/8 - 1) + * @param seg - Segment number (0 to WIDTH - 1) + * @param byte - Byte value to write + * @param sync - If true, updates the display immediately. Default: false + */ + drawPageSeg(page: number, seg: number, byte: number, sync?: boolean): void; + + /** + * Draws one or more pixels on the display. + * + * @param pixels - Single pixel [x, y, color] or array of pixels [[x, y, color], ...] + * @param sync - If true, updates the display immediately. Default: true + * + * @example + * ```javascript + * // Draw a single pixel + * oled.drawPixel([64, 32, 1]); + * + * // Draw multiple pixels + * oled.drawPixel([ + * [0, 0, 1], + * [127, 0, 1], + * [64, 32, 1] + * ]); + * ``` + */ + drawPixel(pixels: Oled.Pixel | Oled.Pixel[], sync?: boolean): void; + + /** + * Draws a line using Bresenham's line algorithm. + * + * @param x0 - Start X coordinate + * @param y0 - Start Y coordinate + * @param x1 - End X coordinate + * @param y1 - End Y coordinate + * @param color - Pixel color (0 for off/black, 1 for on/white) + * @param sync - If true, updates the display immediately. Default: true + * + * @example + * ```javascript + * oled.drawLine(0, 0, 127, 63, 1); + * ``` + */ + drawLine( + x0: number, + y0: number, + x1: number, + y1: number, + color: Oled.Color, + sync?: boolean, + ): void; + + /** + * Draws a filled rectangle. + * + * @param x - Top-left X coordinate + * @param y - Top-left Y coordinate + * @param w - Width in pixels + * @param h - Height in pixels + * @param color - Fill color (0 for off/black, 1 for on/white) + * @param sync - If true, updates the display immediately. Default: true + * + * @example + * ```javascript + * oled.fillRect(10, 10, 50, 30, 1); + * ``` + */ + fillRect( + x: number, + y: number, + w: number, + h: number, + color: Oled.Color, + sync?: boolean, + ): void; + + /** + * Writes a string of text to the display. + * Use setCursor() before this to set the starting position. + * + * @param font - Font object (e.g., from oled-font-5x7 or oled-font-pack) + * @param size - Font size multiplier (1 = normal, 2 = double, etc.) + * @param string - Text to display + * @param color - Text color (0 for off/black, 1 for on/white) + * @param wrap - If true, wraps text at screen edge + * @param sync - If true, updates the display immediately. Default: true + * + * @example + * ```javascript + * const font = require('oled-font-5x7'); + * oled.setCursor(0, 0); + * oled.writeString(font, 1, 'Hello World!', 1, true); + * ``` + */ + writeString( + font: Oled.Font, + size: number, + string: string, + color: Oled.Color, + wrap: boolean, + sync?: boolean, + ): void; + + /** + * Draws an RGBA image at the specified coordinates. + * Transparent pixels are skipped. + * Any pixel with RGB color becomes white, (0,0,0) becomes black. + * + * @param image - RGBA image object (compatible with pngjs) + * @param dx - Destination X coordinate + * @param dy - Destination Y coordinate + * @param sync - If true, updates the display immediately. Default: true + * + * @example + * ```javascript + * const PNG = require('pngjs').PNG; + * const fs = require('fs'); + * + * fs.createReadStream('image.png') + * .pipe(new PNG({ filterType: 4 })) + * .on('parsed', function() { + * oled.drawRGBAImage(this, 0, 0, true); + * }); + * ``` + */ + drawRGBAImage( + image: Oled.RGBAImage, + dx: number, + dy: number, + sync?: boolean, + ): void; + + /** + * Draws a bitmap from raw pixel data. + * The bitmap must be monochrome and match the display dimensions. + * + * @param pixels - Array of pixel values (0 or 1) + * @param sync - If true, updates the display immediately. Default: true + * + * @example + * ```javascript + * const pngparse = require('pngparse'); + * pngparse.parseFile('image.png', function(err, image) { + * oled.drawBitmap(image.data); + * }); + * ``` + */ + drawBitmap(pixels: number[], sync?: boolean): void; + + // ==================== Indicator Methods ==================== + + /** + * Draws a battery level indicator icon. + * Shows 0-3 bars based on percentage level. + * + * @param x - Start X coordinate + * @param y - Start Y coordinate + * @param percentage - Battery level (0-100) + * + * @example + * ```javascript + * oled.battery(100, 0, 75); // Shows 3 bars + * ``` + */ + battery(x: number, y: number, percentage: number): void; + + /** + * Draws a Bluetooth icon. + * + * @param x - Start X coordinate + * @param y - Start Y coordinate + */ + bluetooth(x: number, y: number): void; + + /** + * Draws a WiFi signal strength indicator icon. + * Shows 0-3 bars based on signal percentage. + * + * @param x - Start X coordinate + * @param y - Start Y coordinate + * @param percentage - Signal strength (0-100) + * + * @example + * ```javascript + * oled.wifi(110, 0, 80); // Shows 3 bars + * ``` + */ + wifi(x: number, y: number, percentage: number): void; + + /** + * Displays an image with optional animation. + * A wrapper for drawRGBAImage with additional features. + * + * @param x - Start X coordinate (ignored when animated is true) + * @param y - Start Y coordinate (ignored when animated is true) + * @param image - Full path to image or filename in resources folder + * @param font - Font object for error messages + * @param clear - If true, clears display before drawing + * @param reset - If true, stops all animations + * @param animated - If true, enables bouncing animation + * @param wrapping - If true, wraps error message text + * + * @example + * ```javascript + * const font = require('oled-font-5x7'); + * oled.image(0, 0, 'logo.png', font, true, false, false, true); + * ``` + */ + image( + x: number, + y: number, + image: string, + font: Oled.Font, + clear: boolean, + reset: boolean, + animated: boolean, + wrapping: boolean, + ): void; } declare namespace Oled { - /** - * Color value for drawing operations. - * 0 = off/black, 1 or any truthy value = on/white - * Can also use string 'BLACK' or 'WHITE' - */ - type Color = number | boolean | 'BLACK' | 'WHITE' - - /** - * Scroll direction for startScroll method. - */ - type ScrollDirection = 'left' | 'right' | 'left diagonal' | 'right diagonal' - - /** - * Supported OLED driver types. - */ - type DriverType = 'SSD1306' | 'SH1106' - - /** - * A single pixel definition: [x, y, color] - */ - type Pixel = [number, number, Color] - - /** - * Font object structure used by writeString method. - * Compatible with oled-font-5x7 and oled-font-pack packages. - */ - interface Font { - /** Width of each character in pixels */ - width: number - /** Height of each character in pixels */ - height: number - /** Array of character lookup strings */ - lookup: string[] - /** Array of font bitmap data */ - fontData: number[] - } - - /** - * RGBA Image structure compatible with pngjs. - * Used by drawRGBAImage method. - */ - interface RGBAImage { - /** Width of the image in pixels */ - width: number - /** Height of the image in pixels */ - height: number - /** Raw RGBA pixel data buffer (4 bytes per pixel) */ - data: Buffer | Uint8Array - } - - /** - * Options for initializing the OLED display. - */ - interface OledOptions { - /** Width of the display in pixels. Default: 128 */ - width?: number - /** Height of the display in pixels. Default: 64 */ - height?: number - /** I2C address of the display. Default: 0x3C */ - address?: number - /** I2C bus number. Default: 1 */ - bus?: number - /** Driver type: 'SSD1306' or 'SH1106'. Default: 'SSD1306' */ - driver?: DriverType - /** Line spacing in pixels for text. Default: 1 */ - linespacing?: number - /** Letter spacing in pixels for text. Default: 1 */ - letterspacing?: number - } + /** + * Color value for drawing operations. + * 0 = off/black, 1 or any truthy value = on/white + * Can also use string 'BLACK' or 'WHITE' + */ + type Color = number | boolean | "BLACK" | "WHITE"; + + /** + * Scroll direction for startScroll method. + */ + type ScrollDirection = "left" | "right" | "left diagonal" | "right diagonal"; + + /** + * Supported OLED driver types. + */ + type DriverType = "SSD1306" | "SH1106"; + + /** + * A single pixel definition: [x, y, color] + */ + type Pixel = [number, number, Color]; + + /** + * Font object structure used by writeString method. + * Compatible with oled-font-5x7 and oled-font-pack packages. + */ + interface Font { + /** Width of each character in pixels */ + width: number; + /** Height of each character in pixels */ + height: number; + /** Array of character lookup strings */ + lookup: string[]; + /** Array of font bitmap data */ + fontData: number[]; + } + + /** + * RGBA Image structure compatible with pngjs. + * Used by drawRGBAImage method. + */ + interface RGBAImage { + /** Width of the image in pixels */ + width: number; + /** Height of the image in pixels */ + height: number; + /** Raw RGBA pixel data buffer (4 bytes per pixel) */ + data: Buffer | Uint8Array; + } + + /** + * Options for initializing the OLED display. + */ + interface OledOptions { + /** Width of the display in pixels. Default: 128 */ + width?: number; + /** Height of the display in pixels. Default: 64 */ + height?: number; + /** I2C address of the display. Default: 0x3C */ + address?: number; + /** I2C bus number. Default: 1 */ + bus?: number; + /** Driver type: 'SSD1306' or 'SH1106'. Default: 'SSD1306' */ + driver?: DriverType; + /** Line spacing in pixels for text. Default: 1 */ + linespacing?: number; + /** Letter spacing in pixels for text. Default: 1 */ + letterspacing?: number; + } } -export = Oled +export = Oled; diff --git a/types/oled-i2c-bus/oled-i2c-bus-tests.ts b/types/oled-i2c-bus/oled-i2c-bus-tests.ts index aba20996116026..cbb35cf07efc2d 100644 --- a/types/oled-i2c-bus/oled-i2c-bus-tests.ts +++ b/types/oled-i2c-bus/oled-i2c-bus-tests.ts @@ -1,273 +1,273 @@ -import Oled = require('oled-i2c-bus') -import { openSync } from 'i2c-bus' +import Oled = require("oled-i2c-bus"); +import { openSync } from "i2c-bus"; // Test: Constructor with minimal options function testConstructorMinimal(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, {}) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, {}); - // Verify readonly properties exist - const width: number = oled.WIDTH - const height: number = oled.HEIGHT - const driver: string = oled.DRIVER + // Verify readonly properties exist + const width: number = oled.WIDTH; + const height: number = oled.HEIGHT; + const driver: string = oled.DRIVER; } // Test: Constructor with full options function testConstructorFull(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { - width: 128, - height: 64, - address: 0x3c, - bus: 1, - driver: 'SSD1306', - linespacing: 1, - letterspacing: 1, - }) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { + width: 128, + height: 64, + address: 0x3c, + bus: 1, + driver: "SSD1306", + linespacing: 1, + letterspacing: 1, + }); } // Test: Constructor with SH1106 driver function testConstructorSH1106(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { - width: 128, - height: 64, - driver: 'SH1106', - }) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { + width: 128, + height: 64, + driver: "SH1106", + }); } // Test: Display control methods function testDisplayControl(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) - - oled.turnOnDisplay() - oled.turnOffDisplay() - oled.dimDisplay(true) - oled.dimDisplay(false) - oled.invertDisplay(true) - oled.invertDisplay(false) - oled.startScroll('left', 0, 15) - oled.startScroll('right', 0, 15) - oled.startScroll('left diagonal', 0, 15) - oled.startScroll('right diagonal', 0, 15) - oled.stopScroll() - oled.update() + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); + + oled.turnOnDisplay(); + oled.turnOffDisplay(); + oled.dimDisplay(true); + oled.dimDisplay(false); + oled.invertDisplay(true); + oled.invertDisplay(false); + oled.startScroll("left", 0, 15); + oled.startScroll("right", 0, 15); + oled.startScroll("left diagonal", 0, 15); + oled.startScroll("right diagonal", 0, 15); + oled.stopScroll(); + oled.update(); } // Test: Clear display function testClearDisplay(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); - oled.clearDisplay() - oled.clearDisplay(true) - oled.clearDisplay(false) + oled.clearDisplay(); + oled.clearDisplay(true); + oled.clearDisplay(false); } // Test: Cursor function testCursor(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); - oled.setCursor(0, 0) - oled.setCursor(64, 32) + oled.setCursor(0, 0); + oled.setCursor(64, 32); } // Test: Low-level page/segment drawing function testPageDrawing(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); - oled.drawPageCol(0, 0, 0xff) - oled.drawPageSeg(0, 0, 0xff) - oled.drawPageSeg(0, 0, 0xff, true) - oled.drawPageSeg(0, 0, 0xff, false) + oled.drawPageCol(0, 0, 0xff); + oled.drawPageSeg(0, 0, 0xff); + oled.drawPageSeg(0, 0, 0xff, true); + oled.drawPageSeg(0, 0, 0xff, false); } // Test: Draw pixels function testDrawPixel(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) - - // Single pixel - oled.drawPixel([64, 32, 1]) - oled.drawPixel([64, 32, 0]) - oled.drawPixel([64, 32, true]) - oled.drawPixel([64, 32, false]) - - // Multiple pixels - oled.drawPixel([ - [0, 0, 1], - [127, 0, 1], - [0, 63, 1], - [127, 63, 1], - ]) - - // With sync parameter - oled.drawPixel([64, 32, 1], true) - oled.drawPixel([64, 32, 1], false) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); + + // Single pixel + oled.drawPixel([64, 32, 1]); + oled.drawPixel([64, 32, 0]); + oled.drawPixel([64, 32, true]); + oled.drawPixel([64, 32, false]); + + // Multiple pixels + oled.drawPixel([ + [0, 0, 1], + [127, 0, 1], + [0, 63, 1], + [127, 63, 1], + ]); + + // With sync parameter + oled.drawPixel([64, 32, 1], true); + oled.drawPixel([64, 32, 1], false); } // Test: Draw line function testDrawLine(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); - oled.drawLine(0, 0, 127, 63, 1) - oled.drawLine(0, 0, 127, 63, 0) - oled.drawLine(0, 0, 127, 63, 1, true) - oled.drawLine(0, 0, 127, 63, 1, false) + oled.drawLine(0, 0, 127, 63, 1); + oled.drawLine(0, 0, 127, 63, 0); + oled.drawLine(0, 0, 127, 63, 1, true); + oled.drawLine(0, 0, 127, 63, 1, false); } // Test: Fill rectangle function testFillRect(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); - oled.fillRect(10, 10, 50, 30, 1) - oled.fillRect(10, 10, 50, 30, 0) - oled.fillRect(10, 10, 50, 30, 1, true) - oled.fillRect(10, 10, 50, 30, 1, false) + oled.fillRect(10, 10, 50, 30, 1); + oled.fillRect(10, 10, 50, 30, 0); + oled.fillRect(10, 10, 50, 30, 1, true); + oled.fillRect(10, 10, 50, 30, 1, false); } // Test: Write string function testWriteString(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) - - // Mock font object matching oled-font-5x7 structure - const font: Oled.Font = { - width: 5, - height: 7, - lookup: ['A', 'B', 'C'], - fontData: [0x00, 0x00, 0x00, 0x00, 0x00], - } - - oled.setCursor(0, 0) - oled.writeString(font, 1, 'Hello World!', 1, true) - oled.writeString(font, 2, 'Big Text', 1, false) - oled.writeString(font, 1, 'With sync', 1, true, true) - oled.writeString(font, 1, 'Without sync', 1, true, false) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); + + // Mock font object matching oled-font-5x7 structure + const font: Oled.Font = { + width: 5, + height: 7, + lookup: ["A", "B", "C"], + fontData: [0x00, 0x00, 0x00, 0x00, 0x00], + }; + + oled.setCursor(0, 0); + oled.writeString(font, 1, "Hello World!", 1, true); + oled.writeString(font, 2, "Big Text", 1, false); + oled.writeString(font, 1, "With sync", 1, true, true); + oled.writeString(font, 1, "Without sync", 1, true, false); } // Test: Draw RGBA image function testDrawRGBAImage(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) - - // Mock RGBA image (compatible with pngjs) - const image: Oled.RGBAImage = { - width: 32, - height: 32, - data: Buffer.alloc(32 * 32 * 4), - } - - oled.drawRGBAImage(image, 0, 0) - oled.drawRGBAImage(image, 48, 16, true) - oled.drawRGBAImage(image, 48, 16, false) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); + + // Mock RGBA image (compatible with pngjs) + const image: Oled.RGBAImage = { + width: 32, + height: 32, + data: Buffer.alloc(32 * 32 * 4), + }; + + oled.drawRGBAImage(image, 0, 0); + oled.drawRGBAImage(image, 48, 16, true); + oled.drawRGBAImage(image, 48, 16, false); } // Test: Draw bitmap function testDrawBitmap(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); - const pixels: number[] = new Array(128 * 64).fill(0) - oled.drawBitmap(pixels) - oled.drawBitmap(pixels, true) - oled.drawBitmap(pixels, false) + const pixels: number[] = new Array(128 * 64).fill(0); + oled.drawBitmap(pixels); + oled.drawBitmap(pixels, true); + oled.drawBitmap(pixels, false); } // Test: Battery indicator function testBattery(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) - - oled.battery(100, 0, 100) // Full battery - oled.battery(100, 0, 75) // 3 bars - oled.battery(100, 0, 50) // 2 bars - oled.battery(100, 0, 25) // 1 bar - oled.battery(100, 0, 5) // 0 bars + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); + + oled.battery(100, 0, 100); // Full battery + oled.battery(100, 0, 75); // 3 bars + oled.battery(100, 0, 50); // 2 bars + oled.battery(100, 0, 25); // 1 bar + oled.battery(100, 0, 5); // 0 bars } // Test: Bluetooth icon function testBluetooth(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); - oled.bluetooth(0, 0) + oled.bluetooth(0, 0); } // Test: WiFi indicator function testWifi(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) - - oled.wifi(110, 0, 100) // Full signal - oled.wifi(110, 0, 75) // 3 bars - oled.wifi(110, 0, 50) // 2 bars - oled.wifi(110, 0, 25) // 1 bar - oled.wifi(110, 0, 5) // 0 bars + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); + + oled.wifi(110, 0, 100); // Full signal + oled.wifi(110, 0, 75); // 3 bars + oled.wifi(110, 0, 50); // 2 bars + oled.wifi(110, 0, 25); // 1 bar + oled.wifi(110, 0, 5); // 0 bars } // Test: Image method function testImage(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { width: 128, height: 64 }) + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { width: 128, height: 64 }); - const font: Oled.Font = { - width: 5, - height: 7, - lookup: ['A', 'B', 'C'], - fontData: [0x00, 0x00, 0x00, 0x00, 0x00], - } + const font: Oled.Font = { + width: 5, + height: 7, + lookup: ["A", "B", "C"], + fontData: [0x00, 0x00, 0x00, 0x00, 0x00], + }; - // Display static image - oled.image(0, 0, 'logo.png', font, true, false, false, true) + // Display static image + oled.image(0, 0, "logo.png", font, true, false, false, true); - // Display animated image - oled.image(0, 0, 'logo.png', font, true, false, true, true) + // Display animated image + oled.image(0, 0, "logo.png", font, true, false, true, true); - // Reset animations - oled.image(0, 0, '', font, true, true, false, false) + // Reset animations + oled.image(0, 0, "", font, true, true, false, false); } // Test: Complete workflow example function testCompleteWorkflow(): void { - const i2cBus = openSync(1) - const oled = new Oled(i2cBus, { - width: 128, - height: 64, - address: 0x3c, - driver: 'SSD1306', - }) - - // Initialize display - oled.clearDisplay(true) - oled.turnOnDisplay() - - // Draw some content - oled.fillRect(0, 0, oled.WIDTH, 10, 1, false) - - const font: Oled.Font = { - width: 5, - height: 7, - lookup: ['H', 'e', 'l', 'o', ' ', 'W', 'r', 'd', '!'], - fontData: new Array(45).fill(0), - } - - oled.setCursor(2, 2) - oled.writeString(font, 1, 'Hello World!', 0, false, false) - - // Draw battery and wifi indicators - oled.battery(100, 0, 75) - oled.wifi(80, 0, 80) - oled.bluetooth(60, 0) - - // Update display - oled.update() - - // Cleanup - oled.turnOffDisplay() + const i2cBus = openSync(1); + const oled = new Oled(i2cBus, { + width: 128, + height: 64, + address: 0x3c, + driver: "SSD1306", + }); + + // Initialize display + oled.clearDisplay(true); + oled.turnOnDisplay(); + + // Draw some content + oled.fillRect(0, 0, oled.WIDTH, 10, 1, false); + + const font: Oled.Font = { + width: 5, + height: 7, + lookup: ["H", "e", "l", "o", " ", "W", "r", "d", "!"], + fontData: new Array(45).fill(0), + }; + + oled.setCursor(2, 2); + oled.writeString(font, 1, "Hello World!", 0, false, false); + + // Draw battery and wifi indicators + oled.battery(100, 0, 75); + oled.wifi(80, 0, 80); + oled.bluetooth(60, 0); + + // Update display + oled.update(); + + // Cleanup + oled.turnOffDisplay(); } diff --git a/types/oled-i2c-bus/package.json b/types/oled-i2c-bus/package.json index a50863037a25e9..0f44e32a9f9cc7 100644 --- a/types/oled-i2c-bus/package.json +++ b/types/oled-i2c-bus/package.json @@ -18,4 +18,4 @@ "githubUsername": "gasp" } ] -} \ No newline at end of file +} From 66d4b7d2fced2e4451c633615cdeef79e3ef2525 Mon Sep 17 00:00:00 2001 From: ikeyan Date: Tue, 3 Feb 2026 17:23:29 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74422=20[node/?= =?UTF-8?q?stream/web]=20Fix=20type=20of=20byobRequest=20by=20@ikeyan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/node/node-tests/stream.ts | 17 +++++++++++++++++ types/node/v20/stream/web.d.ts | 2 +- types/node/v20/test/stream.ts | 17 +++++++++++++++++ types/node/v22/stream/web.d.ts | 2 +- types/node/v22/test/stream.ts | 17 +++++++++++++++++ types/node/v24/stream/web.d.ts | 2 +- types/node/v24/test/stream.ts | 17 +++++++++++++++++ 7 files changed, 71 insertions(+), 3 deletions(-) diff --git a/types/node/node-tests/stream.ts b/types/node/node-tests/stream.ts index edfe453a870a1d..380fa49dd4deeb 100644 --- a/types/node/node-tests/stream.ts +++ b/types/node/node-tests/stream.ts @@ -816,6 +816,23 @@ async function testTransferringStreamWithPostMessage() { byobReader.releaseLock(); } +{ + const stream = new ReadableStream({ + type: "bytes", + pull(controller) { + const req = controller.byobRequest; + if (!req?.view) return; + (req.view as Uint8Array).set([42], 0); + req.respond(1); + controller.close(); + }, + }); + const reader = stream.getReader({ mode: "byob" }); + reader.read(new Uint8Array(new ArrayBuffer(8))).then(({ done, value }) => { + console.log(done, value); + }); +} + async function testStreamComposeExample1() { const removeSpaces = new Transform({ transform(chunk, encoding, callback) { diff --git a/types/node/v20/stream/web.d.ts b/types/node/v20/stream/web.d.ts index 1b713a94165b14..039ddc9ae3604d 100644 --- a/types/node/v20/stream/web.d.ts +++ b/types/node/v20/stream/web.d.ts @@ -238,7 +238,7 @@ declare module "stream/web" { new(): ReadableStreamBYOBRequest; }; interface ReadableByteStreamController { - readonly byobRequest: undefined; + readonly byobRequest: ReadableStreamBYOBRequest | null; readonly desiredSize: number | null; close(): void; enqueue(chunk: ArrayBufferView): void; diff --git a/types/node/v20/test/stream.ts b/types/node/v20/test/stream.ts index 49291f80180058..ddaed9ca892c8f 100644 --- a/types/node/v20/test/stream.ts +++ b/types/node/v20/test/stream.ts @@ -824,3 +824,20 @@ async function testTransferringStreamWithPostMessage() { // $ExpectType void byobReader.releaseLock(); } + +{ + const stream = new ReadableStream({ + type: "bytes", + pull(controller) { + const req = controller.byobRequest; + if (!req?.view) return; + (req.view as Uint8Array).set([42], 0); + req.respond(1); + controller.close(); + }, + }); + const reader = stream.getReader({ mode: "byob" }); + reader.read(new Uint8Array(new ArrayBuffer(8))).then(({ done, value }) => { + console.log(done, value); + }); +} diff --git a/types/node/v22/stream/web.d.ts b/types/node/v22/stream/web.d.ts index 881e29c089fdb1..8d348a398cd250 100644 --- a/types/node/v22/stream/web.d.ts +++ b/types/node/v22/stream/web.d.ts @@ -241,7 +241,7 @@ declare module "stream/web" { new(): ReadableStreamBYOBRequest; }; interface ReadableByteStreamController { - readonly byobRequest: undefined; + readonly byobRequest: ReadableStreamBYOBRequest | null; readonly desiredSize: number | null; close(): void; enqueue(chunk: ArrayBufferView): void; diff --git a/types/node/v22/test/stream.ts b/types/node/v22/test/stream.ts index 0935601ed71bdc..fb7916597def0a 100644 --- a/types/node/v22/test/stream.ts +++ b/types/node/v22/test/stream.ts @@ -828,3 +828,20 @@ async function testTransferringStreamWithPostMessage() { // $ExpectType void byobReader.releaseLock(); } + +{ + const stream = new ReadableStream({ + type: "bytes", + pull(controller) { + const req = controller.byobRequest; + if (!req?.view) return; + (req.view as Uint8Array).set([42], 0); + req.respond(1); + controller.close(); + }, + }); + const reader = stream.getReader({ mode: "byob" }); + reader.read(new Uint8Array(new ArrayBuffer(8))).then(({ done, value }) => { + console.log(done, value); + }); +} diff --git a/types/node/v24/stream/web.d.ts b/types/node/v24/stream/web.d.ts index bc7c011c3823da..136886052666e0 100644 --- a/types/node/v24/stream/web.d.ts +++ b/types/node/v24/stream/web.d.ts @@ -237,7 +237,7 @@ declare module "stream/web" { new(): ReadableStreamBYOBRequest; }; interface ReadableByteStreamController { - readonly byobRequest: undefined; + readonly byobRequest: ReadableStreamBYOBRequest | null; readonly desiredSize: number | null; close(): void; enqueue(chunk: ArrayBufferView): void; diff --git a/types/node/v24/test/stream.ts b/types/node/v24/test/stream.ts index 54de806f70122a..c021751a2bceef 100644 --- a/types/node/v24/test/stream.ts +++ b/types/node/v24/test/stream.ts @@ -831,3 +831,20 @@ async function testTransferringStreamWithPostMessage() { // $ExpectType void byobReader.releaseLock(); } + +{ + const stream = new ReadableStream({ + type: "bytes", + pull(controller) { + const req = controller.byobRequest; + if (!req?.view) return; + (req.view as Uint8Array).set([42], 0); + req.respond(1); + controller.close(); + }, + }); + const reader = stream.getReader({ mode: "byob" }); + reader.read(new Uint8Array(new ArrayBuffer(8))).then(({ done, value }) => { + console.log(done, value); + }); +} From 6a5c63375f3c46040b62b852dfb5b4bd3b4c27a1 Mon Sep 17 00:00:00 2001 From: Alexander Brandon Coles Date: Tue, 3 Feb 2026 05:35:43 -0300 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74439=20[@hotw?= =?UTF-8?q?ired/turbo]=20Add=20missing=20types,=20update=20for=208.0.23=20?= =?UTF-8?q?by=20@myabc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Claude Opus 4.5 --- .../hotwired__turbo/hotwired__turbo-tests.ts | 121 ++++++- types/hotwired__turbo/index.d.ts | 304 +++++++++++++++++- 2 files changed, 417 insertions(+), 8 deletions(-) diff --git a/types/hotwired__turbo/hotwired__turbo-tests.ts b/types/hotwired__turbo/hotwired__turbo-tests.ts index 3ea7a89377bec7..ec30cf42b88978 100644 --- a/types/hotwired__turbo/hotwired__turbo-tests.ts +++ b/types/hotwired__turbo/hotwired__turbo-tests.ts @@ -1,4 +1,17 @@ -import { StreamActions, visit } from "@hotwired/turbo"; +import { + cache, + config, + connectStreamSource, + disconnectStreamSource, + navigator, + renderStreamMessage, + session, + start, + StreamActions, + StreamMessage, + StreamSource, + visit, +} from "@hotwired/turbo"; const turboFrame = document.querySelector("turbo-frame")!; @@ -114,3 +127,109 @@ document.addEventListener("turbo:submit-end", function(event) { event.detail.fetchResponse; } }); + +// Test start() function +start(); +Turbo.start(); + +// Test session.adapter +// $ExpectType BrowserAdapter +session.adapter; +session.adapter.formSubmissionStarted(); +session.adapter.formSubmissionFinished(); +Turbo.session.adapter.formSubmissionStarted(); +Turbo.session.adapter.formSubmissionFinished(); + +// Test navigator.submitForm +const form = document.querySelector("form")!; +navigator.submitForm(form); +navigator.submitForm(form, document.querySelector("button")!); +Turbo.navigator.submitForm(form); +Turbo.navigator.submitForm(form, document.querySelector("button")!); + +// Test cache methods +cache.clear(); +cache.resetCacheControl(); +cache.exemptPageFromCache(); +cache.exemptPageFromPreview(); +Turbo.cache.clear(); +Turbo.cache.resetCacheControl(); +Turbo.cache.exemptPageFromCache(); +Turbo.cache.exemptPageFromPreview(); + +// Test config.drive +// $ExpectType boolean +config.drive.enabled; +// $ExpectType number +config.drive.progressBarDelay; +config.drive.progressBarDelay = 1000; +// $ExpectType Set +config.drive.unvisitableExtensions; + +// Test config.drive.enabled assignment +config.drive.enabled = false; +config.drive.enabled = true; + +// Test config.drive.unvisitableExtensions Set modification +config.drive.unvisitableExtensions.add(".custom"); +config.drive.unvisitableExtensions.delete(".pdf"); + +// Test config.forms +// $ExpectType "on" | "off" | "optin" +config.forms.mode; +config.forms.mode = "optin"; +config.forms.mode = "on"; +config.forms.mode = "off"; +// @ts-expect-error +config.forms.mode = "invalid"; + +// Test Turbo.config +Turbo.config.drive.progressBarDelay = 300; +Turbo.config.forms.mode = "optin"; + +// Test config.forms.confirm is optional (undefined by default, can be set to undefined) +// $ExpectType ((message: string, element: HTMLFormElement, submitter: HTMLElement | null) => Promise) | undefined +config.forms.confirm; +config.forms.confirm = undefined; + +// Test config.forms.confirm assignment +config.forms.confirm = async (message, element, submitter) => { + return window.confirm(message); +}; + +// Test StreamElement.templateElement and templateContent +// $ExpectType HTMLTemplateElement +turboStream.templateElement; +// $ExpectType DocumentFragment +turboStream.templateContent; + +// @ts-expect-error - templateElement is readonly +turboStream.templateElement = document.createElement("template"); +// @ts-expect-error - templateContent is readonly +turboStream.templateContent = document.createDocumentFragment(); + +const eventSource = new EventSource("https://example.com/stream"); +const webSocket = new WebSocket("wss://example.com/stream"); + +const streamSource: StreamSource = eventSource; +connectStreamSource(streamSource); +disconnectStreamSource(streamSource); +connectStreamSource(eventSource); +disconnectStreamSource(eventSource); +connectStreamSource(webSocket); +disconnectStreamSource(webSocket); + +// @ts-expect-error +connectStreamSource({}); + +const streamMessage = new StreamMessage(document.createDocumentFragment()); +renderStreamMessage(""); +renderStreamMessage(streamMessage); +Turbo.renderStreamMessage(""); +Turbo.renderStreamMessage(streamMessage); + +// $ExpectType "text/vnd.turbo-stream.html" +StreamMessage.contentType; + +// $ExpectType StreamMessage +StreamMessage.wrap(""); diff --git a/types/hotwired__turbo/index.d.ts b/types/hotwired__turbo/index.d.ts index d5232a06bce928..8bacdec62669a3 100644 --- a/types/hotwired__turbo/index.d.ts +++ b/types/hotwired__turbo/index.d.ts @@ -13,10 +13,13 @@ export class FrameElement extends HTMLElement { } export class StreamElement extends HTMLElement { + static renderElement(newElement: StreamElement): Promise; + connectedCallback(): Promise; render(): Promise; disconnect(): void; removeDuplicateTargetChildren(): void; + removeDuplicateTargetSiblings(): void; /** * The current action. @@ -38,6 +41,41 @@ export class StreamElement extends HTMLElement { * Reads the request-id attribute */ readonly requestId: string; + + /** + * Gets the main `