Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
174 commits
Select commit Hold shift + click to select a range
226cf63
Start Figma editor interaction and presentation review
wieslawsoltes Oct 31, 2026
279be58
Give the native editor chrome a clearer hierarchy and move zoom into …
wieslawsoltes Oct 31, 2026
16d50e1
Reuse filtered layer rows across unrelated edits and idle refreshes
wieslawsoltes Oct 31, 2026
1913213
Expose native zoom presets and fit commands in the header flyout
wieslawsoltes Oct 31, 2026
9685854
Separate layer locking and visibility into accessible row actions
wieslawsoltes Oct 31, 2026
b604b2e
Match click, drag, constraint and center-origin behavior for drawing …
wieslawsoltes Oct 31, 2026
2e4203f
Select visible layer ranges with Shift and toggle individual rows wit…
wieslawsoltes Oct 31, 2026
caace4e
Keep canvas panning off the picking path and route zoom through nativ…
wieslawsoltes Oct 31, 2026
c182562
Exercise click drawing, constrained arrows and gesture cancellation t…
wieslawsoltes Oct 31, 2026
6da11b7
Drive camera gestures, zoom commands and the native picker in browser…
wieslawsoltes Oct 31, 2026
357a7de
Validate browser coverage and provenance against the standalone edito…
wieslawsoltes Oct 31, 2026
15c99c3
Group native toolbar tools into flyouts and remember the last tool in…
wieslawsoltes Oct 31, 2026
c2d869d
Insert artwork into the frame under the pointer while preserving its …
wieslawsoltes Oct 31, 2026
f970dde
Preserve the active page and avoid rewriting unchanged page controls
wieslawsoltes Oct 31, 2026
56907f8
Keep the canvas usable in narrow windows with switchable native panels
wieslawsoltes Oct 31, 2026
0a24761
Use native text-field adorners for compact, labeled geometry controls
wieslawsoltes Oct 31, 2026
cc1d86f
Manipulate directed line and arrow endpoints with explicit handles
wieslawsoltes Oct 31, 2026
4b8f3e1
Query visible frame captions from the spatial index and borrow page r…
wieslawsoltes Oct 31, 2026
4559219
Focus zoom input after popup attachment and clear temporary hand stat…
wieslawsoltes Oct 31, 2026
8d1286c
Reflect edit-mode tool changes in the toolbar selection
wieslawsoltes Oct 31, 2026
1ebf108
Cancel an active drawing when switching tools and tolerate removed li…
wieslawsoltes Oct 31, 2026
4d30e24
Document shape modifiers, layer selection and compact panels
wieslawsoltes Oct 31, 2026
28cf17d
Exercise range and toggle selection through native layer-row pointer …
wieslawsoltes Oct 31, 2026
2c42940
Refresh the editor preview from the native Vello framebuffer
wieslawsoltes Oct 31, 2026
41bee30
Verify compact drawers preserve camera and selection across native re…
wieslawsoltes Oct 31, 2026
d81c92c
Invalidate filtered component results when an unlisted child changes
wieslawsoltes Oct 31, 2026
ac82d36
Describe the browser checks that will run on the pull request
wieslawsoltes Oct 31, 2026
717cdc0
Model slice viewports and crop SVG exports in slice-local coordinates
wieslawsoltes Oct 31, 2026
de9b4fd
Navigate and run quick actions from a pinned native search field
wieslawsoltes Oct 31, 2026
829b821
Author and edit named slices using indexed canvas guides and native r…
wieslawsoltes Oct 31, 2026
dd9ae94
Scale selected layer subtrees uniformly about a world-space pivot
wieslawsoltes Oct 31, 2026
a413805
Keep export slices outside artwork stroke preparation
wieslawsoltes Oct 31, 2026
7c8d73c
Scale selection proportionally with captured edge and corner drags
wieslawsoltes Oct 31, 2026
44b4a4e
Add Scale to native move tools and expose anchored proportional dimen…
wieslawsoltes Oct 31, 2026
232677d
Exercise native and browser scale-tool entry points and cancellation
wieslawsoltes Oct 31, 2026
a106818
Export overlapping artwork as individually named transparent PNG and …
wieslawsoltes Oct 31, 2026
fda6250
Verify Scale across affine parents, component updates, vector network…
wieslawsoltes Oct 31, 2026
a7125aa
Exercise quick-action filtering, Enter, arrows and Escape through the…
wieslawsoltes Oct 31, 2026
2c8cc9d
Reuse eligible scale bounds between pointer events and handle zero-ex…
wieslawsoltes Oct 31, 2026
f977b70
Show slice export bounds and verify keyboard creation and actual PNG …
wieslawsoltes Oct 31, 2026
4417b43
Preview visible layers on the artboard from native layer rows
wieslawsoltes Oct 31, 2026
eb237f9
Keep headless editing tests from reading or writing a real autosave
wieslawsoltes Oct 31, 2026
e6767ce
Preserve the PNG API and give slices independent placement and sequen…
wieslawsoltes Oct 31, 2026
b6cfb2c
Document proportional scaling, inspector anchors and layer previews
wieslawsoltes Oct 31, 2026
1f52d65
Exercise the slice gesture after the headless camera has fitted its page
wieslawsoltes Oct 31, 2026
a8fc0f0
Locate pinned action search outside the scrolling result list
wieslawsoltes Oct 31, 2026
abb7fde
Package multiple named slice exports into one stored ZIP
wieslawsoltes Oct 31, 2026
33a56db
Check rotated slice coordinates in the decoded native PNG
wieslawsoltes Oct 31, 2026
7588c9b
Keep slice clipping explicit when embedding SVG and expose supported …
wieslawsoltes Oct 31, 2026
c5b6ed6
Skip quadratic sibling scans for page and slice SVG exports
wieslawsoltes Oct 31, 2026
9662239
Give each scale anchor a distinct hit target and render the search ma…
wieslawsoltes Oct 31, 2026
c2b1d97
Scale tiled paint periods with layer geometry across fills, strokes, …
wieslawsoltes Oct 31, 2026
323bf42
Show the verified native Scale workspace in the editor preview
wieslawsoltes Oct 31, 2026
dc51756
Avoid rescanning earlier suffixes in large batches of identically nam…
wieslawsoltes Oct 31, 2026
9bf49c5
Verify keyboard scale and downloaded slice pixels through real browse…
wieslawsoltes Oct 31, 2026
0f2b57f
Verify all nine scale anchors retain their full native hit targets
wieslawsoltes Oct 31, 2026
0bc3b54
Send nested selection double-clicks within the native gesture window
wieslawsoltes Oct 31, 2026
fd0495f
Ellipsize frame and slice captions to their transformed screen width
wieslawsoltes Oct 31, 2026
6dc7aa3
Check caption pixels stay inside their artboard at phone zoom
wieslawsoltes Oct 31, 2026
1647ac4
Illustrate the compact editor and its zoom-aware artboard captions
wieslawsoltes Oct 31, 2026
c454eb7
Use FerroUI's thread-local abstraction for isolated native test sessions
wieslawsoltes Oct 31, 2026
174d106
Keep contextual inspector actions in a compact, accessible header
wieslawsoltes Oct 31, 2026
259fbab
Keep the active dock tool legible and expose native keyboard navigation
wieslawsoltes Oct 31, 2026
9fc1357
Rename a selected layer in place through its virtualized native row
wieslawsoltes Oct 31, 2026
8c6ee73
Verify real dock state colors, keyboard traversal and remembered tool…
wieslawsoltes Oct 31, 2026
cdb1160
Show document context in the compact header and dismiss drawers witho…
wieslawsoltes Oct 31, 2026
9ca911a
Document keyboard access to the floating drawing toolbar
wieslawsoltes Oct 31, 2026
43694b3
Show common and mixed inspector values across selected layers
wieslawsoltes Oct 31, 2026
72e422f
Preserve the mixed-side padding hint for individual layout frames
wieslawsoltes Oct 31, 2026
abfdae8
Show mixed inspector choices and constraint pins consistently
wieslawsoltes Oct 31, 2026
b3697ae
Reveal a selected layer from Quick Actions and retain independent edits
wieslawsoltes Oct 31, 2026
049d0fb
Exercise inline rename, undo, cancellation and virtualized row reveal
wieslawsoltes Oct 31, 2026
beceeec
Keep constraint controls enabled for editable mixed selections
wieslawsoltes Oct 31, 2026
d50bce9
Guard pending layer names across scoped edits and document replacement
wieslawsoltes Oct 31, 2026
707a9d7
Make mixed visibility and locking converge in one inspector action
wieslawsoltes Oct 31, 2026
513b0bf
Keep mixed values and editor hints legible against the field surface
wieslawsoltes Oct 31, 2026
0daaa3d
Use the full hint brush in native Fluent form templates
wieslawsoltes Oct 31, 2026
880e535
Exercise compact drawer dismissal, title updates and protected canvas…
wieslawsoltes Oct 31, 2026
bc27899
Keep the selected drawer glyph legible on its native accent surface
wieslawsoltes Oct 31, 2026
bfbe79e
Wait for the first measured artboard before fitting a restored document
wieslawsoltes Oct 31, 2026
2701f1f
Show multi-selection and compact layer editing in the editor previews
wieslawsoltes Oct 31, 2026
de7eb6f
Drive mixed inspector values and native toolbar focus from Chromium
wieslawsoltes Oct 31, 2026
49a331e
Make layer search keyboard accessible and preserve page tree disclosure
wieslawsoltes Nov 1, 2026
fa63a58
Rank quick actions by shortcut and name across editor menus
wieslawsoltes Nov 1, 2026
63ef477
Exercise layer search and disclosure with native keyboard and pointer…
wieslawsoltes Nov 1, 2026
4d3a269
Exercise immediate palette activation and stable phone search layout
wieslawsoltes Nov 1, 2026
60a1662
Search the active page in a single traversal while preserving layer o…
wieslawsoltes Nov 1, 2026
5a53fd1
Scope canvas resize previews to a leaf and retain constraint history …
wieslawsoltes Nov 1, 2026
2933eca
Resize a selected layer from its edges in transformed local coordinates
wieslawsoltes Nov 1, 2026
4f427d1
Drive Move-tool edge resize and cancellation through the native pointer
wieslawsoltes Nov 1, 2026
d6826f0
Verify filtered layer paths and canvas focus through the browser inpu…
wieslawsoltes Nov 1, 2026
36658c4
Keep measured fractional dimensions and scale feedback readable at th…
wieslawsoltes Nov 1, 2026
1b48147
Avoid moving native result rows when filtering preserves their order
wieslawsoltes Nov 1, 2026
c887993
Avoid copying stored expansion state when filtering the layer tree
wieslawsoltes Nov 1, 2026
ab274a6
Align handle feedback with editability and exercise side resizing in …
wieslawsoltes Nov 1, 2026
3138a2d
Retain shaped canvas readout text across camera and hover frames
wieslawsoltes Nov 1, 2026
30312b8
Exercise keyboard find and layered Escape in the 390-pixel drawer
wieslawsoltes Nov 1, 2026
732095b
Format transformed resize geometry and regression coverage
wieslawsoltes Nov 1, 2026
7134597
Anchor the action search and keep keyboard focus inside the palette
wieslawsoltes Nov 1, 2026
66c0aec
Fit seven touch targets on a narrow dock using native tool-family menus
wieslawsoltes Nov 1, 2026
2f70934
Verify narrow dock sizing and tool selection through native input
wieslawsoltes Nov 1, 2026
ad1507d
Show native phone workflows and document directional resize gestures
wieslawsoltes Nov 1, 2026
dc89c36
Illustrate transformed resize feedback and link the mobile editing pr…
wieslawsoltes Nov 1, 2026
6c59142
Run the browser edge-resize assertion with its geometry and history h…
wieslawsoltes Nov 1, 2026
411ad82
Disambiguate side resizing from geometry-aware clicks on transparent …
wieslawsoltes Nov 1, 2026
ff5eef2
Give prototype preview a native touch-accessible playback bar
wieslawsoltes Nov 1, 2026
95e7502
Apply batch dimension edits to original layer sizes in one reversible…
wieslawsoltes Nov 1, 2026
4467671
Give Pages native checked rows, inline renaming, and stable page reor…
wieslawsoltes Nov 1, 2026
a2f7201
Preserve untouched variable links across parent and child dimension o…
wieslawsoltes Nov 1, 2026
8484535
Evaluate arithmetic and per-layer geometry expressions in native insp…
wieslawsoltes Nov 1, 2026
b4234d2
Measure selection gaps and parent insets with transient canvas rulers
wieslawsoltes Nov 1, 2026
9cd7649
Exercise native distance rulers, stationary modifiers and canvas focus
wieslawsoltes Nov 1, 2026
e041d54
Exercise native geometry equations, mixed rollback and exact dimensio…
wieslawsoltes Nov 1, 2026
cb8e536
Distinguish flush edges from overlapping bounds and update deep measu…
wieslawsoltes Nov 1, 2026
9e3bf4a
Disable locked geometry fields and verify nested constraint and vecto…
wieslawsoltes Nov 1, 2026
4514c7e
Show parent inset measurements on the rendered Orbit balance card
wieslawsoltes Nov 1, 2026
51ff328
Verify deep measurement picking switches without pointer motion
wieslawsoltes Nov 1, 2026
5c5ea8f
Keep one page tab stop and exercise page actions through native input…
wieslawsoltes Nov 1, 2026
1830dd0
Show page management in the compact editor guide
wieslawsoltes Nov 1, 2026
acd55b4
Verify physical Undo immediately after moving a page from its menu
wieslawsoltes Nov 1, 2026
991204b
Keep inspector geometry overrides when refreshing component instance …
wieslawsoltes Nov 1, 2026
05d2f57
Exercise native Back, Restart and Done on a phone-sized prototype
wieslawsoltes Nov 1, 2026
676da7e
Fit the full prototype frame on narrow and rotated viewports
wieslawsoltes Nov 1, 2026
2d11caf
Show the native prototype player and mixed inspector calculation
wieslawsoltes Nov 1, 2026
7015eb4
Keep native corner radius and resize handles ahead of Alt measurements
wieslawsoltes Nov 1, 2026
880ae52
Nudge exact per-layer geometry from native inspector fields
wieslawsoltes Nov 1, 2026
5149edc
Preview deep marquee selection and preserve the drag origin
wieslawsoltes Nov 1, 2026
5e854b9
Apply the release sample to canvas moves before committing history
wieslawsoltes Nov 1, 2026
4d0eca0
Navigate prototype frames, overlays and history from the player
wieslawsoltes Nov 1, 2026
b125e48
Restore prototype scroll history and launch the first visible screen
wieslawsoltes Nov 1, 2026
4372a42
Restore each page camera across navigation, resize and history
wieslawsoltes Nov 1, 2026
13caf18
Duplicate artwork with Option-drag and repeat the placed spacing
wieslawsoltes Nov 1, 2026
d7e65a7
Resolve mixed text formatting consistently across editable layers
wieslawsoltes Nov 1, 2026
584fe26
Preview multi-layer regex renames with reversible numbering
wieslawsoltes Nov 1, 2026
94307b1
Focus bulk rename on its opening keystroke and verify native dialog n…
wieslawsoltes Nov 1, 2026
d8a0335
Hit test rounded and smoothed clips when choosing a drag destination
wieslawsoltes Nov 1, 2026
a968b67
Polish batch rename controls and preview for phone-sized editors
wieslawsoltes Nov 1, 2026
7a6a46d
Specify the regex syntax in the batch rename guide
wieslawsoltes Nov 1, 2026
6d325a9
Drive browser regressions from the active tool and fitted prototype c…
wieslawsoltes Nov 1, 2026
5d0c581
Minimize sidebars or hide editor chrome while keeping canvas tools ac…
wieslawsoltes Nov 2, 2026
3e81f98
Resize multiple free layers from their original world geometry
wieslawsoltes Nov 2, 2026
03b33e2
Expose shared Move handles and live modifier feedback for multiple la…
wieslawsoltes Nov 2, 2026
77e265f
Document the shared Move resize handles and modifier keys
wieslawsoltes Nov 2, 2026
bedd93f
Scrub inspector geometry with live native input and exact undo
wieslawsoltes Nov 2, 2026
38526c7
Move layer subtrees atomically in explicit panel order
wieslawsoltes Nov 2, 2026
6ba14cc
Compare persisted scrubs independent of JSON whitespace
wieslawsoltes Nov 2, 2026
0683cc7
Snap shared resize handles to layout guides and scope history to affe…
wieslawsoltes Nov 2, 2026
c1ca6ea
Drag Layers rows between siblings and into nested groups
wieslawsoltes Nov 2, 2026
47852f8
Keep workspace toggles accessible during touch, draft validation and …
wieslawsoltes Nov 2, 2026
42f7d4d
Require distinct editable roots for shared resize handles
wieslawsoltes Nov 2, 2026
9b30b8d
Restore geometry bindings when a scrub returns to its origin
wieslawsoltes Nov 2, 2026
95a7057
Capture scrubbed geometry before validating vector resizes
wieslawsoltes Nov 2, 2026
4123dda
Exercise scrub ownership and rollback after a partial resize
wieslawsoltes Nov 2, 2026
7b526cf
Reach canvas-only workspace recovery with native F6 navigation
wieslawsoltes Nov 2, 2026
44aafc8
Wrap auto-width text at its manually resized selection bounds
wieslawsoltes Nov 2, 2026
f85fed1
Cancel stale scrubs before refreshing focused inspector fields
wieslawsoltes Nov 2, 2026
bbb9c4e
Integrate scrub lifecycle handlers and native control styles
wieslawsoltes Nov 2, 2026
4a5c467
Merge main and validate the FerroUI update with editor export depende…
wieslawsoltes Nov 2, 2026
9fd20f1
Cancel a captured inspector scrub before handling TextBox drafts
wieslawsoltes Nov 2, 2026
b43bc5a
Wait for the arranged workspace before testing canvas coordinates
wieslawsoltes Nov 2, 2026
9df3f41
Notify visible readouts when a canvas resize preview changes geometry
wieslawsoltes Nov 2, 2026
9d5b0b6
Refresh visible geometry readouts once per frame during canvas resize
wieslawsoltes Nov 2, 2026
1a9ea40
Keep selection dimension readouts clear of the arranged tool dock
wieslawsoltes Nov 2, 2026
60177c2
Refine canvas rotation, frame and page guides, inspector scrubbing, a…
wieslawsoltes Nov 2, 2026
3b38d50
Keep exact guide editing usable on phones and find the enclosing fram…
wieslawsoltes Nov 2, 2026
5a9733e
Show Alt-drag guide distances and preserve rounded rectangles in SVG …
wieslawsoltes Nov 2, 2026
bd30ec7
Preserve active inspector scrubs across Chromium pointer-lock handoff…
wieslawsoltes Nov 2, 2026
e2f8bd7
Preserve document references and affine geometry in page, nudge and f…
wieslawsoltes Nov 2, 2026
0a55719
Add native outline inspection, page management, adjustable nudge dist…
wieslawsoltes Nov 2, 2026
3fc7c5c
Paint the page drop indicator at the target edge and verify outline s…
wieslawsoltes Nov 2, 2026
18b4211
Merge main and its updated FerroUI timer API into the editor polish b…
wieslawsoltes Nov 2, 2026
5d0c316
Keep edge scrolling attached to the current FerroUI timer subscription
wieslawsoltes Nov 2, 2026
183151b
Keep page tooltips clear of repeat drag targets and synchronize phone…
wieslawsoltes Nov 2, 2026
0d9de5f
Distinguish touch scrolling, held page reordering and page actions on…
wieslawsoltes Nov 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ browser (WebAssembly): the same editor, controls, document model and scene rende

**Open it in the browser:** https://ferroui.github.io/FerroDesign/

![FerroDesign editing the Orbit mobile banking document in the browser](docs/images/ferrodesign-editor.png)
![FerroDesign inspecting two selected banking screens with shared and mixed property values](docs/images/ferrodesign-editor.png)

The editor has pages and layers, an infinite canvas, layout guides, editable vector networks, rich text
with paragraph formatting, image cropping, effects and masks, continuous corners, variable-width
Expand Down Expand Up @@ -73,8 +73,9 @@ cargo test --locked -p ferrodesign-app --lib -- --test-threads=1
node --test tests/*.test.mjs
```

The browser validation scenarios drive the built site in Chromium with Playwright
(`npm ci && node tests/browser.mjs`, see `scripts/browser_ci.py` for the groups); they are not part of CI.
Run `npm ci && node tests/browser.mjs` to drive the built site in Chromium. Pull requests run all
scenario groups in Software2D, the WebGL2 smoke group, and the browser storage checks. The full
matrix also runs on the nightly schedule. See [the scenario groups](scripts/browser-ci-groups.json).

## License

Expand Down
2 changes: 2 additions & 0 deletions crates/ferrodesign-app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ name = "ferrodesign-app"
path = "src/main.rs"

[dependencies]
regex = "1"
zip = { version = "9.2.0", default-features = false }
ferrodesign-core = { path = "../ferrodesign-core" }
ferroui-base = { path = "../../FerroUI/src/FerroUI.Base", features = ["markup-functions"] }
ferroui-controls = { path = "../../FerroUI/src/FerroUI.Controls" }
Expand Down
6 changes: 3 additions & 3 deletions crates/ferrodesign-app/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ impl ApplicationImpl for App {
.and_then(|l| l.as_classic_desktop_style_application_lifetime())
{
let window = Window::new();
window.set_title(Some("FerroDesign · Orbit".into()));
window.set_title(Some("FerroDesign".into()));
window.set_width(1500.0);
window.set_height(960.0);
window.set_min_width(980.0);
window.set_min_height(650.0);
window.set_min_width(360.0);
window.set_min_height(420.0);
window.set_content(Some(Control::boxed(shell.root.clone())));
let weak = Rc::downgrade(&shell);
window.closing(move |event| {
Expand Down
Loading
Loading