diff --git a/README.md b/README.md index dfa122b..107c89d 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ A simple, joyful drawing experience: - **Pressure ink** — a freehand pen whose width breathes with stylus pressure, or with velocity for mouse users; strokes taper like a real pen - **Highlighter** that soaks into the paper (and glows on dark boards) -- **Shapes** — rectangle, ellipse, triangle, diamond, hexagon, star — with a +- **Shapes** — rectangle, ellipse, triangle, diamond, hexagon, star, cloud — with a seeded hand-drawn wobble, four fill styles, and editable labels - **Arrows** with draggable bend, lines, text, sticky notes - **Images** — paste, drag-drop, or pick; auto-downscaled and stored in-document @@ -48,8 +48,9 @@ A simple, joyful drawing experience: - **Undo/redo** — one entry per gesture, however many events it took - **Light & dark themes**, twelve named colors that resolve per theme, and a theme switch built into the board menu -- **Grid backdrops** — ruled lines or dotted intersections, spacing that adapts - to the zoom and fades in rather than popping +- **Grid backdrops** — plain, ruled lines, notebook rules, dots, crosses + (blueprint), and isometric; default is `lines`; spacing adapts to the zoom + and fades in rather than popping - **PNG export** — whole board or selection, on paper or transparent - **A responsive floating toolbar** that sheds tools gracefully as the frame narrows — or hide it and build your own from the headless API diff --git a/packages/core/README.md b/packages/core/README.md index edfdab1..e9621a7 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -24,7 +24,7 @@ import '@quickdrawjs/core/quickdraw.css' const board = createQuickdraw({ container: document.getElementById('board'), theme: 'light', // or 'dark' - grid: 'lines', // 'none' (default) | 'lines' | 'dots' + grid: 'lines', // 'none' | 'lines' (default) | 'ruled' | 'dots' | 'crosses' | 'iso' }) // the document store emits a diff after every change @@ -49,7 +49,7 @@ without you building any chrome: ```js board.editor.setTheme('dark') // emits 'theme' -board.editor.setGrid('dots') // 'none' | 'lines' | 'dots', emits 'grid' +board.editor.setGrid('dots') // 'none' | 'lines' (default) | 'ruled' | 'dots' | 'crosses' | 'iso', emits 'grid' board.editor.clearBoard() // one undoable step (⇧⌘⌫) // mirror in-board switches into your own app state diff --git a/packages/core/test/type-drift.test.js b/packages/core/test/type-drift.test.js new file mode 100644 index 0000000..2f2343e --- /dev/null +++ b/packages/core/test/type-drift.test.js @@ -0,0 +1,29 @@ +import { readFileSync } from 'node:fs' +import { resolve, dirname } from 'node:path' +import { fileURLToPath } from 'node:url' +import { describe, it, expect } from 'vitest' +import { GEO_IDS, GRID_IDS } from '../src/palette.js' + +const __dirname = dirname(fileURLToPath(import.meta.url)) +const dts = readFileSync(resolve(__dirname, '../types/index.d.ts'), 'utf8') + +function parseUnion(typeName) { + const re = new RegExp(`export type ${typeName}\\s*=\\s*([^\\n]+)`) + const m = dts.match(re) + if (!m) throw new Error(`${typeName} not found in types/index.d.ts`) + return m[1] + .split('|') + .map((s) => s.trim().replace(/^'|'$/g, '')) + .filter(Boolean) + .sort() +} + +describe('type declarations stay in sync with palette.js', () => { + it('GeoId union matches GEO_IDS', () => { + expect(parseUnion('GeoId')).toEqual([...GEO_IDS].sort()) + }) + + it('GridId union matches GRID_IDS', () => { + expect(parseUnion('GridId')).toEqual([...GRID_IDS].sort()) + }) +}) diff --git a/packages/core/types/index.d.ts b/packages/core/types/index.d.ts index 595f061..bd5cbe2 100644 --- a/packages/core/types/index.d.ts +++ b/packages/core/types/index.d.ts @@ -14,9 +14,9 @@ export type SizeId = 's' | 'm' | 'l' | 'xl' export type DashId = 'draw' | 'solid' | 'dashed' | 'dotted' export type FillId = 'none' | 'semi' | 'solid' | 'pattern' export type FontId = 'draw' | 'sans' | 'serif' | 'mono' -export type GeoId = 'rectangle' | 'ellipse' | 'triangle' | 'diamond' | 'hexagon' | 'star' +export type GeoId = 'rectangle' | 'ellipse' | 'triangle' | 'diamond' | 'hexagon' | 'star' | 'cloud' export type ThemeId = 'light' | 'dark' -export type GridId = 'none' | 'lines' | 'dots' +export type GridId = 'none' | 'lines' | 'ruled' | 'dots' | 'crosses' | 'iso' export interface Bounds { x: number; y: number; w: number; h: number } export interface Camera { x: number; y: number; z: number } @@ -236,7 +236,7 @@ export class Editor { setTool(tool: ToolId): void setGeoKind(kind: GeoId): void setTheme(id: ThemeId | string): void - /** 'none' | 'lines' | 'dots' — the backdrop behind the drawing. */ + /** 'none' | 'lines' | 'ruled' | 'dots' | 'crosses' | 'iso' — the backdrop behind the drawing. */ setGrid(id: GridId): void setReadonly(ro: boolean): void setPenMode(on: boolean): void diff --git a/packages/react-native/types/index.d.ts b/packages/react-native/types/index.d.ts index 701e6f4..7373480 100644 --- a/packages/react-native/types/index.d.ts +++ b/packages/react-native/types/index.d.ts @@ -34,7 +34,7 @@ export interface QuickdrawRef { export interface QuickdrawProps { theme?: ThemeId | string - /** 'none' | 'lines' | 'dots' — the backdrop. Live-switchable. */ + /** 'none' | 'lines' | 'ruled' | 'dots' | 'crosses' | 'iso' — the backdrop. Live-switchable. */ grid?: GridId readonly?: boolean hideUi?: boolean diff --git a/packages/react/types/index.d.ts b/packages/react/types/index.d.ts index 11bee60..ae65d23 100644 --- a/packages/react/types/index.d.ts +++ b/packages/react/types/index.d.ts @@ -13,7 +13,7 @@ export interface QuickdrawRef { export interface QuickdrawProps { /** 'light' | 'dark' — live-switchable. */ theme?: ThemeId | string - /** 'none' | 'lines' | 'dots' — the backdrop. Live-switchable. */ + /** 'none' | 'lines' | 'ruled' | 'dots' | 'crosses' | 'iso' — the backdrop. Live-switchable. */ grid?: GridId /** Lock input (also hides the toolbar). */ readonly?: boolean