Commit graph

855 commits

Author SHA1 Message Date
Danila Poyarkov c141663291 fix(editor): address guide authoring review
- Dispose CanvasKit dash effects and render nested frame guides
- Validate imported guide GUIDs and invalidate stale raw guide metadata
- Resolve frame owners through nested hit ancestry and require primary-button ruler drags
- Share guide preview types through a neutral editor module
2026-08-19 20:13:57 +03:00
Danila Poyarkov adaf6dacb9 fix(canvas): keep guide renderer fixtures complete 2026-08-19 18:10:36 +03:00
Danila Poyarkov f892cb583c feat(editor): add ruler guide authoring foundation
- Preserve page and frame guide GUIDs through .fig conversion
- Add undoable guide add, move, transfer, and remove actions
- Start page/frame guide previews from CanvasKit rulers
- Render warm guide previews with frame-scoped solid lines and dotted continuation
2026-08-19 18:08:48 +03:00
Danila Poyarkov 83a5ea1b42
feat(ai): add HarnessAgent sidecar foundation (#560)
* feat(ai): add HarnessAgent sidecar foundation

* feat(ai): integrate Pi as a Harness provider

* fix(ai): harden Harness provider integration

* fix(ai): address Harness integration review

* fix(ai): align Harness code with project conventions

* fix(ai): preserve Harness sessions on cancellation

* test(ai): cover Harness JSONL framing

* refactor(ai): generalize Harness sidecar adapters

* fix(ci): build Harness sidecar for native checks
2026-08-19 17:41:10 +03:00
Danila Poyarkov 73f0883521 Merge remote-tracking branch 'origin/master' into feat/configurable-snapping-guides 2026-08-19 13:20:21 +03:00
Danila Poyarkov 8e3f904ed4 fix(io): normalize legacy guide arrays safely
- Restore missing or malformed guides as empty arrays during graph hydration
- Keep library revision clones independent while preserving valid guides
2026-08-19 12:53:00 +03:00
Danila Poyarkov 9ef2f63d57 fix(editor): harden snapping edge cases
- Preserve rounded auto-layout preview displacement through drop commits
- Bound imported layout-guide counts and tiny grid steps
- Normalize missing guide arrays in direct graph hydration paths
- Add regression coverage for auto-layout movement and guide limits
2026-08-19 12:33:32 +03:00
Danila Poyarkov 0332b062c5
refactor(canvas): adopt immutable CanvasKit paths (#554)
* refactor(canvas): adopt immutable CanvasKit paths

- Upgrade CanvasKit to 0.41.1 across app, Core, CLI, and Vue peers

- Build mutable geometry with PathBuilder and detach immutable paths for drawing

- Replace in-place strokes, transforms, and boolean operations with immutable results

- Update renderer mocks and path construction tests for the new API

* test(canvas): model immutable path ownership

- Return detached path instances from CanvasKit builder mocks

- Assert shadow ring and combined path disposal

- Preserve recorded vector operations across ownership transfer

* fix(build): align CanvasKit workspace versions
2026-08-18 23:09:45 +03:00
Danila Poyarkov 42b1fa07f0 Merge origin/master into feat/configurable-snapping-guides 2026-08-18 22:05:51 +03:00
Danila Poyarkov 91e759d7fd feat(editor): add configurable snapping and guides
- Snap vector points, moved layers, and resized edges to geometry, objects, guides, and pixels
- Add persistent snapping preferences with browser and native menu controls
- Normalize canvas and layout guides across Scene Graph and .fig conversion
- Clear transient snapping feedback across interrupted interactions
2026-08-18 19:11:48 +03:00
Danila Poyarkov f3973202eb
chore: refresh compatible dependencies (#545)
- Refresh compatible workspace dependencies and lockfiles.\n- Preserve package exports and documentation compatibility.\n- Update affected compatibility tests.
2026-08-18 17:44:40 +03:00
Danila Poyarkov 15bd0ba19f
fix(text): align editing overlays with vertical text (#543)
- Offset selection and caret geometry with the rendered paragraph.\n- Translate text-editing hit testing into paragraph coordinates.\n- Cover every aligned coordinate-mapping path.
2026-08-17 19:32:40 +03:00
rcoenen be272dc4dc
feat(fig): support text on path 2026-08-17 12:00:01 +03:00
Danila Poyarkov 6193b6da7e
feat(code): add live JSX and HTML/CSS editing (#525)
* feat(code): isolate Design JSX execution

- Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker

- Block ambient network capabilities and enforce source, timeout, output, depth, and element limits

- Validate that only bounded plain structured data returns to the application

* feat(code): add editable Design JSX

- Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling

- Convert validated sandbox output into trusted Design JSX helpers before rendering

- Apply or insert JSX as one undoable graph transaction while preserving dirty drafts

* feat(code): localize JSX editor actions

- Add translated-message fallbacks for editing, applying, inserting, and draft state

- Document the editable JSX workflow in the unreleased changelog

* fix(code): satisfy typed sandbox validation

- Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint

* test(code): resolve sandbox probes through app aliases

* fix(code): bound sandbox results before cloning

- Enforce string, array, object, depth, element, and byte limits inside the disposable worker

- Retain host-side validation as a second structured-data boundary

* fix(code): keep JSX and HTML editing modes separate

- Switch generated Tailwind output back to OpenPencil JSX before editing

- Close the JSX editor when opening HTML/CSS import and avoid stacking both editors

* feat(code): support authored Design JSX programs

- Allow local constants, function components, arrays, conditionals, fragments, and multiple roots

- Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections

- Cover multi-root undo, redo, and all-or-nothing rollback

* feat(code): add explicit JSX view mode

- Let authors leave CodeMirror without applying a draft

- Keep the editable surface and HTML/CSS importer mutually exclusive

* feat(code): diagnose unknown JSX vocabulary

- Warn on OpenPencil elements and properties that are absent from the canonical schema

- Surface diagnostics inline through CodeMirror lint markers

* test(code): accept WebKit isolation diagnostics

- Cover the sandbox architecture against Playwright WebKit

- Accept engine-specific wording while preserving the same unavailable-window assertion

* refactor(code): consolidate Design JSX vocabulary

- Drive renderer warnings, completion, and diagnostics from one supported-property schema

- Recognize locally declared components and add focused schema and transform tests

- Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package

* fix(code): support Design JSX variable helpers

* refactor(code): unify JSX sandbox validation

* fix(code): account for complete sandbox output

* fix(code): preserve locked JSX descendants

* fix(code): preserve JSX sibling order

* fix(code): recompute JSX parent layouts

* feat(code): add live code previews

* test(code): centralize graph assertions

* fix(code): harden live preview sessions

* docs: describe live code editing

* fix(code): update editor accessibility labels

* fix(code): use theme-aware error colors

* fix(dev): stop Vite disconnect error loops

* fix(code): clarify live preview status

* fix(ui): avoid tooltip attribute warnings

* test(code): assert semantic preview status

* refactor(code): remove obsolete editor messages

* fix(code): harden preview concurrency and isolation

* fix(code): cancel stale reset previews
2026-08-15 09:48:42 +03:00
Danila Poyarkov d8c968c04a
fix(editor): place nested component instances in world space (#524)
- Derive default instance placement from transformed component bounds
- Convert the target point into the destination parent coordinate space
- Preserve explicit drag-and-drop coordinates and undo snapshots
2026-08-14 21:24:20 +03:00
Danila Poyarkov 29ed07bcc4
refactor(editor): separate canvas view state (#518)
* refactor(editor): separate canvas view state

- Classify shared and view-local editor state explicitly

- Let canvas surfaces render supplied view state and report their viewport

- Preserve the existing one-canvas behavior by default

* fix(canvas): preserve loading render state

* refactor(editor): group state ownership modules

- Move shared and view state into the editor state namespace

- Model the partition with explicit interfaces and default factories

- Derive runtime view keys from the default view object
2026-08-14 21:24:01 +03:00
Danila Poyarkov b93ffea073
feat: add Figma-style variants and component libraries (#512)
Closes #239
2026-08-14 19:31:41 +03:00
Danila Poyarkov c2103ef722
feat(canvas): measure distances between layers (#515)
* feat(canvas): measure distances between layers

- Show temporary Figma-style guides while Option or Alt is held

- Support deep nested targets with Command or Control plus Alt

- Measure transformed world bounds and container padding

* fix(canvas): anchor diagonal measurement guides

- Join diagonal distances at the nearest object corners

- Separate horizontal and vertical value badges

- Crop visual coverage tightly around the measurement overlay

* fix(canvas): cover measurement edge cases

- Draw transformed target outlines and center value pills on guides

- Suppress conflicting hover overlays during measurement mode

- Cover containment, overlap, multi-selection, rotation, and fractional gaps

* fix(canvas): suppress conflicting measurement overlays

- Hide auto-layout hover visuals while distance measurements render

- Assert fractional measurement geometry with numeric tolerance
2026-08-14 18:18:55 +03:00
Danila Poyarkov e19ed6adce Merge remote-tracking branch 'origin/master' into fix-svg-clip-path-import 2026-08-14 13:37:46 +03:00
Danila Poyarkov bcf361f45d fix(io): handle bounded and nested SVG clips
- Carry inherited clip metadata through use expansions
- Map objectBoundingBox clips per painted path bounds
- Apply nested clip regions as ordered vector mask frames
2026-08-14 13:21:46 +03:00
Danila Poyarkov 742522a692 fix(io): preserve SVG clip paths
- Resolve clipPath geometry referenced through use elements
- Import clipped paint runs as editable mask groups
- Cover clipped multicolor SVG imports with a regression test
2026-08-14 12:58:44 +03:00
Danila Poyarkov 3ee3708d71
perf(clipboard): index pasted node children (#511)
- Build parent-to-child indexes once while decoding Figma clipboard data

- Reuse the index for hierarchy traversal and internal component discovery

- Avoid quadratic scans that blocked large flat pastes
2026-08-14 12:37:05 +03:00
Danila Poyarkov 5190a64017
fix(tauri): transfer FIG exports over binary IPC (#509)
- Return native FIG archives as raw IPC responses instead of JSON byte arrays

- Decode the response as an ArrayBuffer and cover the binary contract

- Prevent large desktop exports from multiplying memory use during save
2026-08-13 22:23:37 +03:00
Danila Poyarkov 8294e32f33 feat(ai): add isolated visual inspection
- Route bounded selection renders through the optional Vision model

- Return compact text findings without retaining image data in Design chat history

- Bound MCP and AI image exports by their longest pixel edge
2026-08-13 21:15:44 +03:00
Danila Poyarkov 15ea98d8fb fix(clipboard): report image fetch attempts accurately
Co-authored-by: Joseph Cumines <joeycumines@gmail.com>
2026-08-13 20:33:10 +03:00
Danila Poyarkov 9676bfe31b
Merge pull request #504 from open-pencil/fig-export-memory
perf(fig): reduce export graph cloning
2026-08-13 20:32:21 +03:00
Danila Poyarkov 1eb1f38c78 feat(text): surface missing font substitutions
- Track loaded font provenance and aggregate page-level face fidelity, including synthesized styles and active Inter substitutions
- Add a localized warning banner with retry and affected-layer actions
- Expose get_font_status through the Figma API and MCP tool registry
2026-08-13 18:33:10 +03:00
Danila Poyarkov 6bd319881e perf(fig): reduce export graph cloning
- Clone mutable node shells without duplicating imported binary resources

- Preserve live graph isolation during lazy population
2026-08-13 17:56:37 +03:00
Danila Poyarkov fece63b5b5
Merge pull request #498 from open-pencil/issue-102-multifixture-audit
fix(fig): preserve nested text overrides
2026-08-12 20:58:22 +03:00
Danila Poyarkov a8cf8eb412
fix(tauri): prevent Windows font loading crashes (#497)
* fix(tauri): prevent Windows font loading crashes

- Return native font files over binary Tauri IPC instead of JSON byte arrays

- Resolve desktop script fallbacks without parsing large system fonts in JavaScript

* fix(core): restore quality checks

- Use the shared Vector primitive for render-bound offsets

- Remove unsupported SLICE handling from SceneGraph rescaling

- Drop an unused generated-text test binding

* chore: address font fix review

- Place the release note under the Fixed heading

- Name fallback resolution options and use the shared Tauri constant
2026-08-12 20:09:04 +03:00
Danila Poyarkov cf72b8d1c4 fix(clipboard): preserve pasted instance links
- Share exported GUID assignments across clipboard roots

- Preserve source metadata while applying pasted instance overrides
2026-08-12 20:08:06 +03:00
Danila Poyarkov 3102a60f91
fix(vector): preserve open segments with regions (#496)
- Render segments not referenced by any region loop alongside filled paths\n- Add focused path construction coverage and a canvas visual snapshot\n- Resolve Plugin API type-aware lint findings exposed by the full quality gate
2026-08-12 19:28:37 +03:00
Danila Poyarkov 71bb3b20a6 fix(figma-api): implement layout compatibility gaps
- Match Figma rescale behavior across geometry, typography, effects, and descendants\n- Expose page backgrounds through preserved FIG metadata\n- Return nullable visual render bounds with stroke, effect, and clipping support\n- Cover the Plugin API behavior against live Figma probes
2026-08-12 18:50:25 +03:00
Danila Poyarkov 6f73b28f3d
fix(core): preserve inline SVG primitives (#485)
* fix(core): preserve inline SVG primitives

- Convert parsed circle, ellipse, rect, line, polyline, and polygon children through the shared SVG path pipeline
- Preserve nested presentation attributes, transforms, and JSX-style SVG attribute names
- Cover mixed and primitive-only inline SVG renders

* chore: format merged mobile navigation

* fix(core): disambiguate xmldom document types

- Alias the xmldom Document type so clean CI does not resolve it as the browser DOM type
- Guard the generated SVG document root before collecting paths

* fix(core): preserve inline SVG root styles

- Carry root presentation properties into parsed SVG child conversion
- Apply nested SVG transforms before creating vector networks
- Cover inherited root fills and transformed primitive geometry

* fix(core): scale transformed SVG strokes
2026-08-12 16:02:45 +03:00
Danila Poyarkov 05a36e9672 fix(fig): preserve imported instance links
- Remap component IDs through SceneGraph updates so the instance index stays consistent
- Cover imported instances resolving through the remapped source ID
- Restore source component synchronization for the reporter's .fig file
2026-08-11 18:54:29 +03:00
Danila Poyarkov 7f91594d0c refactor: standardize acronym casing
- Rename first-party API, RPC, JSON, CORS, SVG, JSX, and related identifiers to preserve acronym casing
- Keep upstream and serialized boundary names unchanged
- Add a lint guardrail and migration notes for exported APIs
2026-08-10 15:48:16 +03:00
Danila Poyarkov c1ef116968 Merge remote-tracking branch 'origin/master' into review-pr-477-current 2026-08-10 13:40:22 +03:00
Danila Poyarkov 4986fb8b54 fix(ai): simplify model configuration
- Separate model, connection, and advanced settings

- Resolve capabilities and output limits from provider catalogs

- Keep custom model compatibility declarations explicit
2026-08-10 12:55:35 +03:00
Danila Poyarkov c493bd0872 fix(fig): preserve vector network origin when resizing
- Scale imported vector vertices around their own geometry origin\n- Cover offset geometry and tangent scaling
2026-08-10 12:52:43 +03:00
Danila Poyarkov 751195891f Release v0.14.0 2026-08-10 11:40:44 +03:00
Victor Wads 54abfca334
fix(fig): address instance rendering review 2026-08-10 05:09:03 -03:00
Victor Wads bc79d16ac4
fix(fig): preserve instance text edits on save 2026-08-10 04:30:28 -03:00
Victor Wads e159893ec4
fix(fig): preserve component instance rendering 2026-08-10 04:30:06 -03:00
Danila Poyarkov 02400a84b9 fix(fig): finalize worker cleanup semantics
- Retain worker graphs only for lazy first-page imports\n- Make termination idempotent\n- Wait on deterministic population telemetry in E2E coverage
2026-08-07 14:43:59 +03:00
Danila Poyarkov a5a744843f fix(fig): harden population worker lifecycle
- Register invalidation immediately and release subscriptions on every failure path\n- Bound worker requests and settle parse and population errors consistently\n- Clear stale page loading state and retain current instance override imports
2026-08-07 09:36:46 +03:00
Danila Poyarkov 854e1642d8 feat(fig): prototype lazy population worker
- Populate subsequent lazy pages in a development-only persistent worker
- Journal created, updated, and deleted graph state as field deltas
- Invalidate stale worker replicas after authoritative graph mutations
- Fall back to synchronous population when the worker is unavailable
2026-08-07 09:27:54 +03:00
Danila Poyarkov afc5305e8c fix(canvas): report retained backing failures
- Warn once with the rejected surface dimensions and original CanvasKit error
- Disable repeated cache allocation attempts until the renderer surface is replaced
- Keep direct scene rendering as the visible fallback
2026-08-05 19:10:41 +03:00
Danila Poyarkov 82ef49aa9e fix(canvas): bound retained backing allocations
- Scale retained margins to a fixed device-pixel budget on large viewports
- Fall back to direct scene rendering when CanvasKit rejects an offscreen surface
- Cover the reported wide HiDPI geometry without coupling rendering to a WebGL context
2026-08-05 18:54:18 +03:00
Danila Poyarkov ea7ca7ec7a fix(layout): refresh effective text flow
- Recompute Yoga positions after shaped text changes effective geometry

- Resolve inherited stretch and skip hidden or absolute children

- Share and normalize Plugin API transform matrices
2026-08-05 16:07:11 +03:00
Danila Poyarkov eeefd069e6 fix(figma-api): expose node transforms
- Return rotation and reflection matrices for relative and absolute transforms

- Preserve authoritative imported FIG transforms until geometry is edited

- Cover nested rotation and reflected vector behavior
2026-08-03 20:17:32 +03:00