Commit graph

635 commits

Author SHA1 Message Date
Danila Poyarkov 031897c73a test(editor): cover auto-layout padding editor 2026-05-14 22:37:16 +03:00
Danila Poyarkov 686ca5326f chore: enforce Vue style and state boundaries 2026-05-14 22:05:43 +03:00
Danila Poyarkov 5acb8ffb6c chore: guard shared UI boundaries 2026-05-14 19:00:51 +03:00
Danila Poyarkov d2c3b1bce8 test(editor): cover auto-layout hover targets 2026-05-14 18:28:04 +03:00
Danila Poyarkov c3fd32a516 feat(editor): add auto-layout hover controls 2026-05-14 18:15:53 +03:00
Danila Poyarkov c00356bc29 fix(demo): make auto-layout text responsive 2026-05-13 06:23:08 +03:00
Danila Poyarkov 9ab6bfa3bf fix(app): restore left panel scrolling 2026-05-13 05:47:32 +03:00
Danila Poyarkov 49620ef26b fix(vue): distinguish layer child drops 2026-05-13 05:10:29 +03:00
Danila Poyarkov 419c77d8de fix(canvas): wait for exact font styles 2026-05-13 04:47:32 +03:00
Danila Poyarkov c38778094d fix(vue): restore layer tree reordering 2026-05-13 04:47:23 +03:00
Danila Poyarkov ccc2b0a52c chore(release): polish asset labels and loaders 2026-05-13 03:44:11 +03:00
Danila Poyarkov 9daf260471 feat(components): render asset detail previews
- Generate PNG previews for the selected component/default variant in the details dialog
- Revoke stale preview URLs and refresh on scene changes
- Assert the rendered preview image in assets e2e coverage
2026-05-12 22:24:16 +03:00
Danila Poyarkov 0a53c91a46 feat(components): add asset details dialog
- Add a Figma-style component details dialog from local Assets
- Show preview, description, library key, documentation link, variant properties, and insert action
- Cover details metadata in the Assets panel e2e test
2026-05-12 22:16:07 +03:00
Danila Poyarkov 880fcf3d5b feat(components): surface library metadata in assets
- Show imported library badges in the local Assets panel
- Display component descriptions and documentation links from Figma metadata
- Cover library metadata rendering in the Assets panel test
2026-05-12 21:56:07 +03:00
Danila Poyarkov 4bf161b983 fix(components): sync instances when switching variants
- Swap instance contents when changing variants instead of only updating componentId
- Recreate instance redo state without stale child IDs
- Insert assets into entered containers using local coordinates
- Fall back to Windows paths when URL parsing fails
2026-05-12 18:43:11 +03:00
Danila Poyarkov 24d3ea748f fix(components): respect default variants in assets
- Insert component set assets using explicit default variant values
- Report duplicate variant value combinations in the assets panel
- Cover default insertion and conflict warnings in Playwright
2026-05-12 18:16:51 +03:00
Danila Poyarkov 57e6ed46cb fix(demo): clean up component assets showcase
- Move the button variant set into a dedicated clean area
- Keep variant labels from overlapping button contents
- Space the components section to avoid collisions
2026-05-12 17:39:02 +03:00
Danila Poyarkov 1ceabf7938 feat(components): add local assets panel
- Add a left-sidebar Assets tab for local components and component sets
- Insert component set assets as instances of the default variant
- Showcase local component set insertion in the demo
- Cover search, empty state, standalone insert, and variant switching with Playwright
2026-05-12 17:30:35 +03:00
Danila Poyarkov ddf415ec30 feat(tauri): support desktop file associations
- Register .fig and .pen files with desktop bundles
- Open associated files on startup and via single-instance handoff
- Reuse the existing Tauri file open flow without broad filesystem scopes
2026-05-12 16:12:16 +03:00
Danila Poyarkov 9e013e60e7 fix(mcp): fix stdio handshake and eval return values
Stdio handshake:
Server now sends { type: register, token } to WebSocket clients on
connection, so the stdio bridge receives the token immediately instead
of deadlocking while both sides wait to receive.

Eval return values (REPL-style):
Add wrapEvalCode() that detects when the last non-empty line is a value
expression and promotes it to a return statement. Bare expressions like
JSON.stringify(result) now return the value instead of undefined.
Single implementation in packages/core/src/tools/analyze/eval-wrap.ts
used by both the tool and the automation bridge.

Co-authored-by: stiff <v.stiff@gmail.com>
Co-authored-by: Jais Pedersen <jais@pedersens.net>
2026-05-11 12:05:43 +03:00
Danila Poyarkov c79c9106fb feat(components): add variant inspector UI
Show variant property dropdowns in the design panel when an instance
of a component set is selected. Switching a dropdown value finds the
matching variant component and updates the instance's componentId.

- VariantSection.vue with property dropdowns using AppSelect
- Bridge variant actions to the editor return object
- i18n for en, ru, zh-CN

Ref #239
2026-05-07 19:48:59 +03:00
Danila Poyarkov ad88364562 feat(variables): bind min/max size constraints to variables
Wire VariableScrubInput for minWidth, maxWidth, minHeight, maxHeight
in the size controls panel. Uses the after-variable slot to preserve
the existing select dropdown suffix alongside the variable binding UI.
2026-05-07 14:32:36 +03:00
Danila Poyarkov a6da185e54 refactor: eliminate HTMLInputElement template casts
- Add shared DOM event helpers to Vue SDK (inputValue, inputNumberValue,
  blurTarget, selectTarget) in packages/vue/src/shared/dom-events.ts
- Export from @open-pencil/vue for app consumption
- Replace all template `as HTMLInputElement` casts with helper calls:
  ColorPickerPanel fields, PickerSlider, GradientEditor, ColorInput,
  CollabPanel, AppMenu, ScrubInputRoot
- Fix useInlineRename to use instanceof guards instead of casts
- Fix document name rename to accept Event directly
2026-05-07 10:24:46 +03:00
Danila Poyarkov 0a268f0a65 feat(variables): add inspector bindings for typography properties
- Add lineHeight, letterSpacing, fontWeight, paragraphSpacing,
  paragraphIndent to NumberBindingPath
- Wire lineHeight and letterSpacing inputs in TypographySection
  to VariableScrubInput with variable binding support
2026-05-07 09:50:52 +03:00
Danila Poyarkov 506b5f81e1 refactor(variables): reuse useInlineRename for dialog renaming
- Reuse useInlineRename composable for collection and mode renaming
- Accept Event in useInlineRename.commit to eliminate template casts
- Remove HTMLInputElement casts from PagesPanel and LayerTree blur handlers
- Remove hand-rolled rename state from dialog composable
2026-05-07 00:02:13 +03:00
Danila Poyarkov 107e9f3d51 feat(variables): add mode management and collection deletion
Core:
- Add addMode, removeMode, renameMode, setDefaultMode to SceneGraph
- Add editor actions with full undo: addMode, removeMode, renameMode,
  setDefaultMode, duplicateMode, setActiveMode

Vue SDK:
- Wire all mode and collection actions through SDK helpers
- Add mode rename state to dialog composable
- Remove HTMLInputElement casts from commit handlers

UI:
- Mode management lives in the table column headers (Figma-style):
  double-click to rename, right-click for context menu (rename,
  duplicate, set as default, delete), + button after last mode column
- Collection ⋯ dropdown menu with rename and delete
- Use shared menu UI styles throughout
- i18n for en, ru, zh-CN
2026-05-06 21:36:04 +03:00
Danila Poyarkov 738d199e8a refactor: remove ugly type intersection casts
- Add optional nodeEditState, cursorCanvas, and pen resume fields to core EditorState
- Add parent field to LintNode instead of repeated intersection casts
- Use typed LintPathNode for node path traversal
- Replace autosave useDebounceFn cancel hack with watchDebounced
- Simplify AppEditorState to extend EditorState without Omit+intersection
- Remove PenState intersection type alias
- Use in-operator check for optional setViewportSize
2026-05-06 16:08:36 +03:00
Danila Poyarkov 7dce333200 docs: document event bus and wire app consumers
- Update CHANGELOG.md with event bus, test restructuring, and lint hardening
- Document EditorEvents table and conventions in AGENTS.md
- Wire collab graph sync to editor event bus instead of SceneGraph.onNodeEvents
- Wire collab awareness zoom to viewport:changed instead of Vue watcher
- Wire collab selection broadcasting to selection:changed instead of Vue watcher
2026-05-06 15:38:45 +03:00
Danila Poyarkov 1835903e56 feat(editor): add event bus for editor lifecycle events
Wire nanoevents-based event bus to the editor core:

- EditorEvents type with render, graph, selection, tool, page, viewport events
- All node mutations (create/update/delete/reparent/reorder) forwarded from SceneGraph
- Selection changes routed through setSelectedIds() with diff detection
- Tool changes routed through setActiveTool() with change detection
- Page switches emit page:changed
- Viewport pan/zoom/fit/zoomTo emit viewport:changed
- Graph replacement emits graph:replaced
- Typed onEditorEvent() subscription on the Editor return object
- useEditorEvent() Vue composable with automatic scope cleanup
- Replace all direct state.selectedIds/state.activeTool mutations in core, app, and SDK
2026-05-06 15:25:27 +03:00
Danila Poyarkov bbf122a5c5 chore(tests): route store access through browser bridge
- Expose window.openPencil.getStore() instead of a direct store property
- Update E2E helpers and specs to use the bridge getter
- Add lint coverage preventing direct window.openPencil.store access
2026-05-06 12:19:39 +03:00
Danila Poyarkov f7b20a8f38 chore(tests): namespace browser test hooks
- Move test-only write-count, mock-handle, and saved-open globals under window.openPencil.test
- Keep external Tauri and Vite injected globals separate from app-owned browser bridge hooks
- Validate check plus autosave and chat E2E coverage
2026-05-06 10:49:46 +03:00
Danila Poyarkov 8719274cc9 chore(app): clarify browser bridge naming
- Rename window-api to browser-bridge to describe the app-to-browser test hook boundary
- Rename the chat transport hook to exposeChatTransportOverride and window.openPencil.setChatTransport
2026-05-06 10:43:15 +03:00
Danila Poyarkov 8ec70330b4 chore(lint): centralize OpenPencil window API
- Route browser globals through src/app/window-api.ts instead of private __OPEN_PENCIL fields
- Move E2E tests to the public window.openPencil test API
- Add an oxlint rule banning direct window.__OPEN_PENCIL* access
2026-05-06 10:38:03 +03:00
Danila Poyarkov c3f5189f8f style: tighten import grouping
- Configure oxfmt custom import groups for workspace, app, package, and test aliases
- Keep type imports grouped with their matching source category instead of one global tail group
- Expand the format script to cover formatter config, Vite files, and scripts
2026-05-06 02:22:08 +03:00
Danila Poyarkov ddb1db8175 style: format imports 2026-05-06 02:16:37 +03:00
Danila Poyarkov 792f0e87cf fix(app): use color parser for theme CSS colors
- Remove hand-rolled rgb/rgba parsing from shell theme handling
- Parse ruler CSS custom properties through the shared core color helper
2026-05-06 02:15:39 +03:00
Danila Poyarkov bef03e3804 fix(app): avoid pre-init theme warnings
- Add a nullable active editor store accessor for optional app-bound updates
- Skip canvas theme repainting until an editor store exists
- Guard FontPicker focus handling against non-element component refs
2026-05-06 02:14:33 +03:00
Danila Poyarkov 51eae14e4b chore(tests): remove targeted non-null assertions
- Add shared test helpers for required nodes and child ids
- Clean non-null assertions from noisy render, nudge, text undo, and fig roundtrip tests
- Enforce the non-null assertion ban for the cleaned test files
- Remove stale eslint disables around empty functions and broad mock transport typing
2026-05-06 01:14:50 +03:00
Danila Poyarkov fae190a673 chore(lint): remove unsafe test casts
- Enforce explicit-any and TypeScript suppression bans in tests
- Remove remaining broad any casts from engine and e2e coverage
- Split markdown ambient declarations from typed browser globals
2026-05-06 00:42:45 +03:00
Danila Poyarkov 68d15440b1 feat(app): add variable type creation menu 2026-05-05 23:49:20 +03:00
Danila Poyarkov 3bd01095eb test(app): cover remaining Tauri integrations 2026-05-05 22:45:14 +03:00
Danila Poyarkov 057b3a02b7 test(app): cover Tauri process helpers 2026-05-05 22:32:24 +03:00
Danila Poyarkov 020b55a8ae test(app): cover Tauri file actions 2026-05-05 22:24:57 +03:00
Danila Poyarkov cc216c79db test(app): cover font settings UI 2026-05-05 22:12:33 +03:00
Danila Poyarkov 0f9b69d051 test(app): expand Tauri helper coverage 2026-05-05 22:07:02 +03:00
Danila Poyarkov dac6f171e3 feat(app): add font cache management hooks 2026-05-05 21:50:31 +03:00
Danila Poyarkov 768b527155 feat(core): add font fallback manifest 2026-05-05 21:35:12 +03:00
Danila Poyarkov 25ea361fd7
feat(app): cache downloaded fonts
- Add a downloaded font cache hook to FontManager
- Store Tauri font downloads under AppLocalData with manifest validation
- Prefer cached downloads before system font lookup on desktop
- Skip opt-in heavy .fig parsing tests in PR CI
2026-05-05 21:14:38 +03:00
Danila Poyarkov f29da6c5cd refactor(vue): clean up primitive UI APIs
- Replace one-off class props with typed ui objects

- Group renderless slot actions and remove DOM ref callback plumbing

- Make local font access and typography font loading explicit capability objects
2026-05-05 20:57:13 +03:00
Danila Poyarkov 9c11c5b075
refactor(core): centralize font loading
- Replace loose font service functions with a FontManager instance
- Route renderer provider lifecycle and font caches through the manager
- Request browser local font access from the font picker interaction
2026-05-05 18:59:54 +03:00