Danila Poyarkov
7d1e7cb86e
Update Z.ai and MiniMax model lists
...
# Conflicts:
# CHANGELOG.md
2026-03-28 15:29:22 +03:00
Danila Poyarkov
76767c5ea3
Update Z.ai and MiniMax model lists
2026-03-28 15:26:37 +03:00
Danila Poyarkov
e396df3224
Add .pen document import
...
Co-authored-by: Anton Soldatov <eddclyde@yandex.ru>
2026-03-28 13:57:32 +03:00
Danila Poyarkov
0001802dda
Add shared IO format registry
2026-03-28 01:58:05 +03:00
Ilya Nikitin
cbae1eaccf
lint:
...
- Add parentheses in bezier-math.ts ternary conditions
- Add parentheses in editor.ts align calculation expression
2026-03-27 21:44:59 +05:00
Ilya Nikitin
0ff5a87ccb
update pen tool space drag spec
...
Adds a new scenario to the pen tool specifications defining the behavior for relocating the active vertex with spacebar during a curve drag, including asserting that the cursor remains a crosshair instead of switching to the hand tool.
Made-with: Cursor
2026-03-27 21:27:45 +05:00
Ilya Nikitin
455f04d6f1
Merge branch 'up_master' into feat/vector-editor
...
# Conflicts:
# src/composables/use-keyboard.ts
2026-03-27 19:33:07 +05:00
Ilya Nikitin
cedd88813b
Use KeyboardEvent.code instead of KeyboardEvent.key across editor and input handling.
2026-03-27 17:13:35 +03:00
Ilya Nikitin
ae2fbccf01
fix(components): update Lucide icon names in properties sections
...
Ensure proper semantic alignment between icon names and their visual representation
2026-03-27 17:09:34 +03:00
Ilya Nikitin
e393ca7a07
fix(properties): update Lucide icon names for alignment and flip controls
...
Ensure proper semantic alignment between icon names and their visual representation
2026-03-27 17:09:02 +03:00
Danila Poyarkov
c1d7fc80b0
Fix property panel visibility toggles, independent corners/stroke sides, extract shared ColorStyleRow
...
- Fix fill/stroke/effect/appearance visibility eye toggle (stale clone reads)
- Fix independent corner radii toggle not showing 4 inputs
- Fix stroke sides toggle: replace dropdown with direct toggle like corners
- Copy uniform weight to all sides when expanding stroke sides
- Batch multi-selection visibility toggles into single undo entry
- Extract ColorStyleRow shared by FillSection and StrokeSection
- Replace useFillVariableBinding/useStrokeVariableBinding with useColorVariableBinding(kind)
- AppearanceSection uses useAppearance() directly instead of slot wrapper
- Add sceneVersion dependency to useNodeProps and PropertyListRoot computeds
- Add E2E tests for visibility toggles and corner/stroke side toggles
2026-03-27 17:06:33 +03:00
Ilya Nikitin
2b92916881
feat(vector): add anchor point alignment for selected vertices
...
Align selected anchor points relative to each other in vector edit mode. The standard alignment buttons in the position panel now operate on selected vertices when 2 or more are selected, enabling precise vector path editing workflows.
2026-03-26 11:55:56 +05:00
Ilya Nikitin
6ad25297df
Merge branch 'up_master' into feat/vector-editor
...
# Conflicts:
# CHANGELOG.md
# src/composables/use-keyboard.ts
2026-03-26 02:45:30 +05:00
Ilya Nikitin
b1997e413f
feat(vector): add vector curve editor with enhanced pen tool
...
- Add bezier math utilities for VectorNetwork manipulation
- Enable resuming pen drawing from existing open path endpoints
- Allow closing open paths by dragging endpoints together
- Add comprehensive vector editing capabilities for curves and paths
2026-03-26 02:28:55 +05:00
Danila Poyarkov
e03038f4bf
Translate collaboration share popover
2026-03-25 21:48:38 +03:00
Danila Poyarkov
4b9cd54983
Translate more editor UI surfaces
2026-03-25 18:47:23 +03:00
Danila Poyarkov
9f296b7357
Translate chat setup and code panel strings
2026-03-25 18:40:17 +03:00
Danila Poyarkov
2f646ffcaf
Translate more visible UI strings
2026-03-25 18:26:03 +03:00
Danila Poyarkov
77032ab092
Translate visible panel chrome for Russian locale
2026-03-25 18:12:09 +03:00
Danila Poyarkov
9220ef399b
Handle checkbox submenu items in app menu
2026-03-25 18:07:24 +03:00
Danila Poyarkov
cf16857a76
Add locale picker to app menu
2026-03-25 18:05:58 +03:00
Danila Poyarkov
6bfc5c2189
Rename toggleUI i18n key
2026-03-25 17:40:26 +03:00
Danila Poyarkov
ea4676d991
Finish i18n pass for menus and tool labels
...
Localize remaining menu state labels like Hide/Show and Lock/Unlock,
wire toolbar tool/action labels through the i18n stores, and localize
the app menu UI toggle tooltip.
Replace template-string JSON imports with an explicit locale loader map
so published package builds have stable locale asset references.
2026-03-25 17:39:47 +03:00
Danila Poyarkov
eb2891233a
Wire i18n into commands, menus, and add locale files
...
Commands and menu models now read labels from nanostores i18n
messages instead of hardcoded English strings. App menu rebuilt
to use i18n directly instead of matching on localized labels.
Added locale files: de, es, fr, it, pl (ru was added earlier).
All 6 translations plus English base cover menus, commands, tools,
panels, pages, and dialogs.
2026-03-25 17:05:11 +03:00
Danila Poyarkov
2b3219e106
Add i18n to Vue SDK with nanostores
...
nanostores + @nanostores/i18n + @nanostores/vue (~6 KB total).
English base translations defined inline in messages.ts, other
locales loaded on demand from JSON. Grouped by domain: menu,
commands, tools, panels, pages, dialogs.
useI18n() composable returns reactive translation objects plus
locale controls. Russian locale included as first translation.
Browser language auto-detected, user preference persisted in
localStorage.
2026-03-25 16:17:03 +03:00
TKman
c52f88e34c
feat: add spacebar hold to temporarily activate Hand (pan) tool
...
Hold Spacebar to temporarily switch to the Hand tool for panning,
release to return to the previously active tool. This matches the
standard Figma UX pattern.
- Uses separate keydown/keyup event listeners for reliable handling
- Guards against text editing mode and key repeat
- References state.activeTool for correct tool state
Fixes #147
2026-03-24 23:47:56 +03:00
Danila Poyarkov
2956507783
Fix switch_page not persisting across MCP tool calls
...
Each RPC tool call created a fresh FigmaAPI instance, so switch_page
set currentPageId on a throwaway object. Sync the page change back
to the editor store after tool execution.
Fixes #112
2026-03-24 23:47:55 +03:00
Danila Poyarkov
bceddd759f
Guard keyboard shortcuts during canvas text editing
...
Backspace/Delete and tool shortcuts (V, R, F, T, etc.) fired during
canvas text editing because the guard only checked for DOM input/textarea
focus, not the canvas TextEditor state. Add editingTextId check to both
the onEventFired handler and the plain() shortcut helper.
2026-03-24 23:47:55 +03:00
Danila Poyarkov
80a2855bb3
Fix review issues in undo and Vue SDK
2026-03-24 18:15:40 +03:00
Danila Poyarkov
1da5483fec
Format remaining SDK refactor files
2026-03-24 17:02:01 +03:00
Danila Poyarkov
07af72ab24
Fix imported fig rendering and file open regressions
2026-03-24 16:52:45 +03:00
Danila Poyarkov
0a770248a2
Reorganize Vue SDK modules by domain
2026-03-24 09:50:31 +03:00
Danila Poyarkov
74bb119579
Extract Vue SDK editor controls and pickers
2026-03-24 09:50:28 +03:00
Danila Poyarkov
329dd301bd
Align app UI primitives with shared ui overrides
2026-03-24 09:50:20 +03:00
Danila Poyarkov
0c30d044b2
Extract Vue SDK commands and menu model
2026-03-24 09:50:17 +03:00
Danila Poyarkov
29b63842fa
Integrate SDK composables into all app components
...
FillPicker: useFillPicker() replaces inline category/switch logic
PagesPanel: usePageList() replaces inline pages computed
VariablesDialog: useVariables() replaces 11 inline CRUD functions
CanvasMenu: inline editor.copySelectionAs* instead of wrapper fns
Toolbar: ToolbarRoot + ToolbarItem wrapping tool buttons
28/42 app components now use SDK. Remaining 14 are legitimately
app-specific (chat, collab, mobile layout) or generic UI widgets
(select, toast, tip — no editor logic needed).
2026-03-17 20:39:45 +03:00
Danila Poyarkov
fb2bfb5827
SDK rewrite: delete 15 useless wrappers, replace with composables
...
Deleted 15 fake headless component folders (slot-prop wrappers with
no provide/inject, no DOM, no ARIA). Replaced with 9 composables:
- usePosition, useLayout, useAppearance, useTypography
- useExport, useVariables, useFillPicker, useGradientStops, usePageList
Kept 6 real headless component families with provide/inject + DOM:
- Canvas (WebGL surface lifecycle)
- ScrubInput (pointer capture + input + display)
- Toolbar (wraps Reka UI Toolbar)
- LayerTree (wraps Reka UI Tree + Atlaskit DnD)
- PropertyList (array CRUD via inject)
- GradientEditor (pointer capture for stop drag)
App components updated: use composables directly instead of wrapping
in Root components. -1047 net lines, cleaner separation.
2026-03-17 20:22:41 +03:00
Danila Poyarkov
c36456d820
Fix loader not removed — add onReady callback to dismiss #loader
...
The loader div from index.html was never dismissed after the SDK
migration because use-canvas.ts moved to the SDK (which correctly
doesn't touch app-specific DOM). Added onReady callback in
EditorCanvas.vue to fade out and remove the loader.
2026-03-17 19:25:06 +03:00
Danila Poyarkov
43694aaeb3
Fix runtime errors: TooltipProvider scope, provideEditor in EditorView
...
Browser validation found 2 runtime issues:
1. TooltipProvider only wrapped EditorView, but <Tip> components in
AppToast rendered outside it → moved TooltipProvider to App.vue
to wrap everything including toasts.
2. SDK components call useEditor() but the app never provided the
editor via the SDK's injection system → added provideEditor(store)
in EditorView.vue so SDK primitives can access the editor.
Validated: zero console errors, canvas renders, demo shapes visible.
2026-03-17 17:33:04 +03:00
Danila Poyarkov
92c49f80f4
Self-review fixes: CanvasContext types, toast out of SDK, last graph access
...
- CanvasContext hit test return types: unknown → SceneNode | null
- Move toast.ts from SDK to app (src/utils/toast.ts) — singleton
with unguarded window access doesn't belong in headless SDK
- ExportSection: store.graph.getNode → store.getNode
- ImageFillPicker: store.graph.images.get → store.getImage (new method)
- Add getImage(hash) to core editor create.ts
Zero store.graph access from components. Zero toast in SDK.
2026-03-17 17:13:33 +03:00
Danila Poyarkov
d3aa511056
Self-review fixes: VueUse adoption, tailwind-variants recipes
...
VueUse:
- useClipboard({ copiedDuring }) in CodePanel, CollabPanel \u2014 replaces
manual copied ref + setTimeout pattern
- useDebounceFn in stores/editor.ts \u2014 replaces manual clearTimeout +
setTimeout for autosave
- onScopeDispose in ExportSection \u2014 replaces onUnmounted for URL cleanup
Tailwind-variants:
- New iconButton() recipe (sm/md) \u2014 replaces 15+ repeated button class strings
- New sectionWrapper() + sectionLabel() \u2014 replaces 12 repeated section classes
- Applied across all 10 property section components
2026-03-17 16:48:12 +03:00
Danila Poyarkov
ced083439e
Complete SDK plan: all 21 component families built
...
New SDK components (7):
- ColorPickerRoot — color state, swatch CSS, update handler
- ColorInputRoot — hex string, updateFromHex handler
- FontPickerRoot — font families, search/filter, selection
- ImageFillControlsRoot — image preview, file picker, scale mode
- GradientEditorBar — pointer capture drag for stop bar
- GradientEditorStop — per-stop data + update handlers
- PageControlsRoot — page background color
- VariablesIndicatorRoot — collection/variable counts
- VariablesEditorRoot — collections, variables, CRUD, search/filter
App components rewritten to compose from SDK:
- ColorPicker, ColorInput, FontPicker, ImageFillPicker
- GradientEditor (script: ~100 → imports only)
- PageSection, VariablesSection
Full SDK inventory: 21 component families, 35 Vue files, 48 TS files.
Every item from SDK-PLAN.md is now implemented.
2026-03-17 16:21:26 +03:00
Danila Poyarkov
2a69ef956f
SDK: AppearanceControls, TypographyControls, EffectsSection via PropertyListRoot
...
New SDK components:
- AppearanceControlsRoot — corner radius, visibility, opacity, blend mode
- TypographyControlsRoot — font family/weight/size, alignment, formatting
toggles, missing font detection, font loading
EffectsSection rewritten to compose from PropertyListRoot \u2014 effect CRUD
via SDK, scrub tracking stays in app component.
All property sections now use SDK headless primitives:
- PositionSection → PositionControlsRoot
- LayoutSection → LayoutControlsRoot
- AppearanceSection → AppearanceControlsRoot
- TypographySection → TypographyControlsRoot
- FillSection → PropertyListRoot
- StrokeSection → PropertyListRoot
- EffectsSection → PropertyListRoot
- ExportSection → ExportControlsRoot
2026-03-17 15:59:43 +03:00
Danila Poyarkov
2757e9e6ec
Fix PR review: critical bugs, package config, remaining title attrs
...
Critical fixes:
- useSceneComputed: watchEffect on state.sceneVersion as fallback
when replaceGraph() swaps the emitter (bridge stayed on old graph)
- useLayerDrag: capture monitorForElements() cleanup, onScopeDispose
(was leaking global listeners on tab switch)
Package fixes:
- packages/vue: sideEffects: false for tree-shaking
- Build: --noEmit → --emitDeclarationOnly (was skipping .d.ts)
- canvaskit-wasm peerDep: optional via peerDependenciesMeta
- use-canvas.ts: onUnmounted → onScopeDispose
Remaining title= attrs migrated to <Tip>:
- AppMenu toggle UI, TypographySection missing font, ProviderSettings
2026-03-17 15:30:28 +03:00
Danila Poyarkov
6ffe201bec
StrokeSection: compose from PropertyListRoot (388→180 lines)
...
Stroke CRUD (add/remove/toggle/update color+weight) now uses
PropertyListRoot from SDK. Stroke-specific logic (sides, align,
border weights) stays in app component as functions taking activeNode.
2026-03-17 15:08:34 +03:00
Danila Poyarkov
8ba8c48a4c
Migrate all title= attributes to Reka UI Tooltip via <Tip>
...
Replace 30 title= attributes across 15 component files with <Tip>
wrappers for proper Reka UI Tooltip behavior (positioning, delay,
animation, accessibility).
Remaining 2: TypographySection missing-font icon (non-interactive),
AppMenu toggle-UI button (browser menu context).
2026-03-17 12:22:25 +03:00
Danila Poyarkov
92857aed45
Add LayoutControlsRoot SDK primitive, LayoutSection 556→119 lines
...
New SDK component LayoutControls/LayoutControlsRoot.vue (189 lines):
- Layout sizing logic (width/height sizing, flex vs auto-layout vs grid)
- Alignment grid computation (3x3 for flex)
- Grid track CRUD (add/remove/update columns and rows)
- Padding management (uniform + per-side toggle)
- Sizing options derived from layout context
App LayoutSection.vue is now template-only (119 lines) — composes
LayoutControlsRoot with Tailwind styling + Lucide icons.
2026-03-17 12:10:27 +03:00
Danila Poyarkov
a8e8e63a55
Replace void sceneVersion hacks with useSceneComputed composable
...
Add useSceneComputed() to SDK — wraps a function in a computed()
that depends on sceneVersion internally. Eliminates the anti-pattern
of 'void editor.state.sceneVersion' at the top of computed blocks.
Updated 8 files: EditorMenuRoot, ExportControlsRoot, PageListRoot,
useSelectionState, PagesPanel, CodePanel, VariablesDialog,
VariablesSection.
Zero void-sceneVersion hacks remaining in components.
2026-03-17 11:48:03 +03:00
Danila Poyarkov
513b16983f
Clean remaining component leaks: requestRender, graph access, variable queries
...
Editor API additions:
- bindVariable/unbindVariable in nodes.ts (with undo + requestRender)
- setPageColor in pages.ts (state + requestRender)
- getVariablesByType, getVariable, getCollection, resolveColorVariable,
getVariablesForCollection, getCollections, getCollectionCount,
getVariableCount in variables.ts (read-through to graph)
- getNode, getChildren, getPages in create.ts (read-through to graph)
Removed:
- 5 redundant requestRender() after updateNodeWithUndo
- All store.graph.* access from components (was in 7 files, now 0)
Remaining requestRender (1 file): EffectsSection uses updateNode
(without undo) which correctly needs manual render trigger.
2026-03-17 11:38:32 +03:00
Danila Poyarkov
0fbaf1c24e
Adopt Reka UI Tooltip/ToggleGroup, VueUse useClipboard
...
Reka UI:
- Tip.vue — reusable tooltip wrapping Reka UI Tooltip primitives
- TooltipProvider in EditorView.vue with 400ms delay
- PositionSection: 9 title= attrs → <Tip> wrappers
- TypographySection: alignment → ToggleGroup (single),
formatting (bold/italic/underline/strikethrough) → ToggleGroup
(multiple). Keyboard nav + ARIA for free.
VueUse:
- useClipboard replaces navigator.clipboard.writeText in
CodePanel, CollabPanel, MobileHud, CanvasMenu
2026-03-17 11:30:25 +03:00