Commit graph

1846 commits

Author SHA1 Message Date
Kayshen-X 88cc8e94d8 fix(variables): clamp variant-header hover wash to its hit column
A long variant name could make the fit-content variant-header hover wash
wider than its column and bleed into the neighbouring variant column. Clamp
the wash right edge to the hit column (`col_w.min(176)`), matching the
size-checkbox / footer clamps. Wash regression tests moved to a sibling
variables_panel/wash_tests.rs (keeps tests.rs under the 800-line cap) with a
new long-variant clamp case.
2026-06-20 23:35:22 +08:00
Kayshen-X d41cf9c61f fix(panels): anchor caret blink on per-frame search inputs
The component/icon/font/image search boxes rebuild their TextInputState
from the filter String each frame; with_text left the blink anchor at 0,
so the caret could be in its hidden phase right after a keystroke. touch()
the rebuilt state with now_ms so the caret stays steadily visible while
the box is focused (codex review follow-up).
2026-06-20 23:26:21 +08:00
Kayshen-X 81f6d126ab fix(panels): make the icon picker list scroll
The picker loads up to 120 local + remote icons but only ever painted a
fixed ~9-row window + a load-more button, so the rest were unreachable
(no scroll) and the window left a blank gap at the bottom. Render the
list as a real scrolling viewport instead: clip to the list area, shift
all loaded rows by the wheel offset, cull off-screen rows, load-more last.

Wire scrolling through every active path — a shared try_scroll_icon_picker
called from both hosts' apply_wheel AND apply_pan_gesture (trackpad) — and
reset the offset to the top on every search edit (type / backspace /
select-all-clear) so a new filter starts at row 0.
2026-06-20 23:22:33 +08:00
Kayshen-X 5af58072e8 fix(panels): hug-content hover washes + grayed top-bar compound icons
- property / variables panels: shrink the size-checkbox, alignment,
  variant-header and add-variable hover washes to hug their content
  (+ small L/R padding), clamped to the hit rect so long locales can't
  bleed into a neighbouring control; left-align the add-variable footer
  pill so it no longer floats in from the panel's left.
- top bar: paint the folder + globe compound buttons via the shared ghost
  feedback (muted at rest, foreground on hover) instead of SelectTrigger's
  always-foreground icon, matching the sibling icon buttons.

Hit targets are unchanged; only the painted highlight / colour shifts.
Wash regression tests split into property_panel_wash_tests.rs to keep the
test file under the 800-line cap.
2026-06-20 23:21:42 +08:00
Kayshen-X 3617954122 refactor(panels): render image search/generate popovers via unified TextInputView
Migrate the image-node Search query + Generate prompt off hand-rolled
draw_text + manual caret onto the shared paint_text_input_view helper. A
jian TextInputState is rebuilt from each String per frame; the open
popover reads as focused. The generate prompt renders single-line at the
top of its textarea box (multi-line wrapping stays a follow-up). Caret is
now family-aware (no drift) and shares one implementation.
2026-06-20 22:32:58 +08:00
Kayshen-X 9b77f170c8 refactor(git): render masked HTTPS credential via unified TextInputView
Route the Remotes-section HTTPS credential field through the unified
TextInputView with mask: Some(&mask_credential) (new
paint_text_input_view_masked helper), deleting the ~90-line hand-rolled
masked renderer + masked_byte_for_source_byte caret remap in
git_panel_remotes. The token still shows as user:•••• with a correct,
family-aware caret. Other TextInputView call sites pass mask: None.

Bumps vendor/jian to c451e16 (TextInputView::mask).
2026-06-20 22:26:28 +08:00
Kayshen-X a728a0b8ae refactor(panels): render component/icon/font search via unified TextInputView
Migrate the component-browser, icon-picker, and font-family-picker search
fields off hand-rolled draw_text + manual caret onto the shared
paint_text_input_view helper. A jian TextInputState is rebuilt from each
filter String per frame (with select-all carried through where present),
so the caret is family-aware (no drift) and shares one implementation;
the panels thread now_ms for the caret blink (for_editor_at).
2026-06-20 22:07:38 +08:00
Kayshen-X ddef8360cb refactor(variables): render search box via unified TextInputView
Add a general paint_text_input_view helper (placeholder + focused params;
paint_text_input_view_value now delegates to it) and route the variables
search/filter box through it instead of a hand-rolled draw_text + manual
fill_rect caret. The search_input TextInputState was already rebuilt each
frame, so this is render-only — the caret now uses the family-aware
measure (no drift) and shares one implementation.
2026-06-20 21:57:02 +08:00
Kayshen-X 11431e1a18 refactor(store): reuse jian_core::color, drop op-editor-core color_convert
The colour maths now lives once in jian_core::color; op-editor-core
re-exports it through color_picker (so crate::color_picker::parse_hex_rgb
and op_editor_core::* paths are unchanged) and deletes its duplicate
color_convert module. Bumps vendor/jian to 3404ad8.
2026-06-20 21:41:17 +08:00
Kayshen-X d706222f4e feat(panels): editable R/G/B fields in the colour picker
Click an R/G/B box to edit that channel as a 0..255 value through the
unified TextInputView; the host routes keystrokes via color_picker_rgb_*
(now_ms-threaded, digit-gated, 3-char cap) and live-applies by splicing
the channel into the current RGB and committing through set_hsv.
ColorPickerState gains rgb_focus + rgb_input; active_text_input + the
text-input gate resolve it; press dispatch focuses/blurs hex vs rgb.

Extracts the hex+rgb edit state machines into color_picker_edit.rs to
keep color_picker.rs under the 800-line cap. Bumps vendor/jian to d11d54e.
2026-06-20 21:27:08 +08:00
Kayshen-X da6e7cd228 refactor(panels): drive colour-picker hex bar through unified TextInputState
The picker hex field now stores a jian TextInputState (hex_input) seeded
on focus and edited via the same caret-aware insert/backspace gating as
the property-panel hex input, instead of a hand-rolled String draft +
manual caret. ColorPickerState carries hex_input; the host threads now_ms
for the caret blink and routes keystrokes through color_picker_hex_char/
backspace(now_ms); active_text_input() resolves the picker hex so its
blink drives the redraw. Fixes the caret drift and removes the picker's
last hand-rolled input.

Bumps vendor/jian to cce4523.
2026-06-20 20:57:10 +08:00
Kayshen-X 0c2af63b4e fix(canvas): resolve named draw family in caret measurement
Implement Painter::measure_text_family on the native skia backend
(NativeBackend::measure_text_family_styled segments per-codepoint
against the real family, exactly like draw_text) and forward it through
NativeFrameBackend + BaselineAdjustingBackend so the family-aware
measure reaches skia through the wrappers. Fixes the ~6px caret drift
in every TextInputView/TextArea chrome input (property pills, chat, git,
settings) — measure now uses the same typeface paint does.

Bumps vendor/jian to 19fb00b (Painter::measure_text_family).
2026-06-20 20:29:41 +08:00
Kayshen-X e1f13d2afb refactor(variables): split color_picker.rs under the 800-line cap
Editable hex input pushed color_picker.rs to 979 lines. Extract the two
self-contained helper clusters into siblings:
- color_convert.rs — pure HSV/RGB/hex math (re-exported through
  color_picker so crate::color_picker::parse_hex_rgb callers are unchanged)
- color_picker_snapshot.rs — variable/fill/effect hex extraction for the
  history-change check (pub(crate))

color_picker.rs is now 769 lines; no behaviour change, 17 picker tests green.
2026-06-20 19:43:42 +08:00
Kayshen-X 1744b2aa8a feat(panels): editable hex input in the colour picker
Click the picker's hex bar to focus it, then type a #RRGGBB value
(or paste one char at a time): the bar shows the live draft + caret,
Enter/Escape/outside-click commit-and-blur, and a valid hex re-seeds
HSV so the SV box + hue handle follow. Keystrokes route through the
text-input gate so they don't leak into chat/shortcuts.

Bumps vendor/jian to ce19bed (ColorPicker::HexInput hit + draft render).
2026-06-20 19:29:47 +08:00
Kayshen-X 521e44c92c test(web): add rust web browser smoke 2026-06-20 19:24:59 +08:00
Kayshen-X 26c39966e7 fix(editor): uniform card bg + jian-standard button_hover row washes
A consistency audit found per-item/per-token hover regressions from the
jian migration: provider cards gave ClaudeCode a permanent muted fill
while others were transparent (now all transparent + one button_hover
wash); layer-panel page/layer rows, the flex padding-mode popover rows,
and the builtin-preset rows washed with theme.muted instead of the
jian-standard theme.button_hover. Hover now reads identically across the
chrome.
2026-06-20 19:13:52 +08:00
Kayshen-X 153e3f72a8 feat(variables): per-row hover on the theme-preset dropdown
The preset dropdown tracked no live row hover (a documented gap). Add a
variables_preset_menu_hover state, update it on cursor-move via the
existing ThemePresetMenu hit-test (swallowing moves over the menu like a
top-most overlay), and paint a jian button_hover wash on the hovered row
(inset a few px so it reads as a padded highlight, not edge-to-edge).
2026-06-20 19:02:16 +08:00
Kayshen-X 34dcd0547f fix(editor): color picker swallows cursor moves over its panel
apply_cursor_move only handled the picker while dragging; an open-but-idle
picker fell through to the canvas hover layer, so hovering the picker
bled selection/hover feedback onto the nodes behind it. Swallow moves
whose point is inside the picker panel (clear lower-overlay hover + return),
matching the design-md / modal overlay behaviour.
2026-06-20 18:44:44 +08:00
Kayshen-X bb03388dfa fix(editor): keep agent_settings_acp under 800 + saved edit-card height
Move the card-form geometry (type_toggle_rect / field_input_rect /
form_actions_y / form_card_h + their constants) into the
agent_settings_acp_helpers sibling so agent_settings_acp.rs drops back
under the 800-line cap (829 -> 784). A saved card being edited shows no
Save/Cancel row, so card_height wraps just the fields (form_actions_y),
not the draft's action-row tail — restoring the Local saved-edit height
(332) the previous commit inflated to 370.
2026-06-20 18:36:44 +08:00
Kayshen-X 05410a262d fix(editor): ACP remote-agent card shrinks to its fields + disabled save reads neutral
The ACP draft/editing card height + Save/Cancel row position now derive
from the connection type's field set, so a Remote agent (Display name +
URL) no longer leaves a tall empty gap below the URL field that Local's
(Command/Args/Env) layout reserved. The disabled Save button renders as a
neutral Outline (white in light mode) instead of a washed-out pale-primary
fill.
2026-06-20 18:25:31 +08:00
Kayshen-X 934aef334d fix(editor): borderless top-bar icon dropdowns + git commit-input baseline
The TopBar globe + file-menu SelectTriggers now pass bordered:false (no
Outline box, just the icon+chevron with a hover wash); the form-field
dropdowns keep the border. The git commit-message TextArea (ready +
status panels) now paints through BaselineAdjustingBackend so its text
sits on the baseline instead of clipping at the top. Bumps vendor/jian.
2026-06-20 18:05:12 +08:00
Kayshen-X 18fd0000dd fix(editor): bump vendor/jian for consistent baseline contract
jian a53a61c: ColorPicker's box-centered labels now route through
centered_text_baseline_y like every other component; non-box-centered
placements (RGB captions, Dialog title) and the host-baselined input
glyph layers are documented exceptions.
2026-06-20 17:01:02 +08:00
Kayshen-X 3f7ed3dc7e fix(editor): bump vendor/jian for text-baseline fix
jian dc15ea7: component labels (buttons, tabs, toggles, badges, menus,
dropdowns, tooltips, accordions) now position text by the BASELINE
(center + font_size*0.35) instead of the (height - font_size)/2 top-left
form, so they no longer render ~font_size too high in the editor chrome.
Input glyph layers stay top-relative (the host's BaselineAdjustingBackend
handles their baseline).
2026-06-20 16:49:34 +08:00
Kayshen-X 25a9b7f9a4 refactor(editor): absorb design-md markdown parser into jian markdown
The Design-MD panel's markdown parser (block structure + inline
bold/code/#HEX styling + run wrapping) moves to jian components::markdown;
design_md_markdown.rs becomes a thin re-export so the panel's block
renderer is unchanged. ~300 fewer lines of OP-domain parsing. Bumps
vendor/jian to 94f8315.
2026-06-20 15:18:13 +08:00
Kayshen-X 32ae68a248 refactor(editor): absorb the HSV color picker into jian ColorPicker
The floating color picker's rendering, layout, hit-test and HSV<->RGB
math now live in jian ColorPicker; color_picker.rs shrinks to a wrapper
that owns the property-panel-relative anchor (rect), the EditorState
plumbing and the drag dispatch, re-exporting hsv_to_rgb / rgb_to_hsv /
ColorPickerHit / PICKER_* so the hosts import them unchanged. ~330 fewer
lines of OP-specific paint. Bumps vendor/jian to 9580247.
2026-06-20 15:11:33 +08:00
Kayshen-X 7040e5592a fix(editor): variables axis-tab paint walks theme_tab_advance_width
Review found the axis-tab paint (jian content_rects, advance = width+gap)
drifted 6px from the hit walker (theme_tab_advance_width) for tabs to the
right of an inline-renaming axis, where the two advances differ. Feed
content_rects the host's per-tab advances (theme_tab_advance_width for
variables; width+CHIP_GAP for the framework chip) so paint and hit share
the same advance source and can't drift in any state. Bumps vendor/jian
to f0fbf70.
2026-06-20 15:00:40 +08:00
Kayshen-X fd5a65ebae refactor(editor): absorb the variables axis-tab strip into jian Tabs
The theme-axis tab strip renders through jian Tabs content-width mode
(Text active style + trailing chevron on the active axis, which doubles
as the axis-value dropdown trigger) instead of a hand-rolled label loop.
The host keeps the inline-rename overlay (an opaque input over the
renaming tab), the +Add / Preset / Close buttons, and the theme_tab_rect
hit walker — whose geometry matches content_rects for normal tabs.
2026-06-20 14:35:41 +08:00
Kayshen-X bceefb5b68 refactor(editor): absorb the framework chip strip into jian Tabs
The scrollable, variable-width framework chip carousel now lays out via
jian Tabs::content_rects and renders via Tabs::paint_content (PrimaryPill
active style) instead of a hand-rolled chip loop; the host keeps its
deterministic width fn, scroll state, clip band and chevrons. Both paint
and hit go through the jian layout, so they stay aligned. Bumps
vendor/jian to ed15b1e (Tabs content-width flexibility).
2026-06-20 14:29:26 +08:00
Kayshen-X 0a7a5e8263 refactor(editor): route divider helpers through jian Separator
paint_section_divider (11 call sites), paint_hairline (4), and the two
paint_divider helpers (7) now draw through jian Separator — the canonical
1px-line primitive — instead of ad-hoc fill_rect; the top-bar one is a
vertical separator. First OP consumer of jian Separator; ~22 dividers
share one primitive with no caller changes.
2026-06-20 14:12:34 +08:00
Kayshen-X b3fd06ee57 refactor(editor): extract ai-chat label/feedback helpers to keep file under 800
The IconButton migration pushed ai_chat_panel.rs to 801 lines (over the
repo's 800-line cap). Move draw_label / chat_neutral_hover_color /
chat_neutral_feedback_color into the ai_chat_panel_controls sibling
(backend trait already in scope there) and re-export them, so callers
and tests are unchanged. ai_chat_panel.rs is now 780 lines.
2026-06-20 13:43:35 +08:00
Kayshen-X d64fc3c344 refactor(editor): sink remaining icon buttons to jian IconButton
The AI-chat header (New Chat / maximize), component-browser header
(close + export/import kit), icon-picker close, and figma-import close
buttons now render through jian IconButton instead of hand-rolled
paint_ghost_button_feedback + draw_icon. Drops the now-orphaned
paint_header_btn_bg helper; host hit-tests are unchanged.
2026-06-20 13:28:41 +08:00
Kayshen-X dc67272bad refactor(editor): render fill/effect color swatches via jian Swatch
The gradient-stop and shadow-color swatches now paint through jian
Swatch (alpha-aware checker + fill) instead of the local paint_alpha_checker
+ separate fill; drops paint_alpha_checker and its public re-export.
Bumps vendor/jian to 9c13e8d (checker now theme-independent, so the
transparency pattern stays visible in dark mode).
2026-06-20 13:05:03 +08:00
Kayshen-X 8a8c97f90a fix(editor): align text-align toggle hit rects with paint + refresh stale tests
Codex/multi-agent review found the text h/v-align ToggleGroup hit rects
sat 14px (LH_LS_LABEL_H) above where they paint: text_action_rects
omitted the 行高/字间距 caption row that paint_text_section and
push_text_input_rects both include, so the bottom half of each align
toggle was a dead zone and the band above misfired. Add the missing
LH_LS_LABEL_H term. Also refresh two tests left stale by the jian Button
migration (kit-dropdown pressed-feedback radius 4→6; code Export-bundle
hover wash now jian Ghost's button_hover, not a boosted alpha).
2026-06-20 12:57:32 +08:00
Kayshen-X f3e7a149ef refactor(editor): render property checkboxes/radio via jian Checkbox/Radio
The widget + size-section check rows and the flex gap-alignment radio
now paint through jian Checkbox / Radio (first consumers) instead of
hand-rolled box+check / ring+dot; row hit-tests are unchanged.
2026-06-20 12:27:22 +08:00
Kayshen-X 962cfae904 refactor(editor): drop dead duplicate paint_flex_section
property_panel_sections::paint_flex_section was an unreferenced leftover
from when the flex section moved to property_panel_flex (the only wired
paint_flex_section). Removes the stale gapped-cell duplicate.
2026-06-20 12:21:08 +08:00
Kayshen-X 9ec653265c refactor(editor): migrate flex-direction toggle to jian ToggleGroup
The Free/Vertical/Horizontal layout-direction icon selector renders
through jian ToggleGroup (icon segments, font_size 14 → 18px icons) over
the same footprint; its hit walker switches to the continuous even cells
ToggleGroup paints so paint + hit stay aligned.
2026-06-20 12:19:17 +08:00
Kayshen-X be2c359402 refactor(editor): migrate text align toggles to jian ToggleGroup
The horizontal/vertical text-align icon selectors render through jian
ToggleGroup (icon segments, font_size 12 → 16px icons); their hit cells
switch from gapped to the continuous even cells ToggleGroup paints so
paint + hit stay aligned.
2026-06-20 12:16:26 +08:00
Kayshen-X c0e7ab60de refactor(editor): migrate text-growth toggle to jian ToggleGroup
The Auto/Fixed-width/Fixed-width+height text-growth selector renders
through jian ToggleGroup; its hit walker switches from gapped cells to
the continuous even cells ToggleGroup paints, so paint + hit stay aligned
with no inter-cell dead zones.
2026-06-20 12:14:18 +08:00
Kayshen-X 4045ffc163 refactor(editor): migrate image-fill mode control to jian ToggleGroup
The Contain/Cover/Stretch mode selector renders through jian ToggleGroup
(even cells aligned with its existing full-cell hit walker) instead of a
hand-rolled muted track + inset chip loop; active cell fills primary.
2026-06-20 12:11:12 +08:00
Kayshen-X 5e7302222b refactor(editor): migrate builtin-agent kind toggle to jian ToggleGroup
The Anthropic/OpenAI kind segmented control now renders + hit-tests
through jian ToggleGroup (segment_at) instead of a hand-rolled cell
loop + kind_option_rect. Drops the KindOption.slot indirection and the
kind_option_rect helper; single-option presets render full-width.
Bumps vendor/jian to 3b5db91.
2026-06-20 12:05:41 +08:00
Kayshen-X 2096a1f444 refactor(editor): adopt jian Button icon_paths + migrate code icon buttons
All op-editor-ui jian Button call sites move from icon_d to icon_paths.
The code panel's Generate / Export-bundle icon+label buttons and the
Design-MD action buttons now render through jian Button with full
multi-subpath icons (sparkles / braces / wand), dropping the local
paint_centered_icon_label hand-rolling + paint_primary_hover_overlay.
Bumps vendor/jian to 9998df9.
2026-06-20 11:54:56 +08:00
Kayshen-X 9f70adede7 refactor(editor): migrate export/code/image CTA buttons to jian Button
Export-section, export-dialog (Cancel→Outline, Export→Primary), image
generate-popover (Apply→Primary, Retry→Outline) and the code-panel
full-width action button now render through jian Button instead of
hand-rolled fill_round_rect + hover overlay + centered draw_text. The
solid-fill hover-darken now lives in the component, so per-button hover
state threads straight through. Bumps vendor/jian to 330feb4.
2026-06-20 11:47:55 +08:00
Kayshen-X 03e37f4613 refactor(editor): migrate provider-card connect/disconnect to jian Button
Connect renders through jian Button Primary (centered label, primary
fill) and Disconnect through the new DestructiveOutline variant (red
border + red label) instead of hand-rolled fill_round_rect + centered
draw_text. Bumps vendor/jian to 9e47bd3.
2026-06-20 11:38:42 +08:00
Kayshen-X 9c645584ff refactor(editor): migrate fill-type + design-md buttons to jian components
Fill section head-row fill-type dropdown now renders through jian
SelectTrigger (Outline box + chevron + own hover/press feedback)
instead of a hand-rolled label+glyph; the Design-MD empty-state action
buttons render through jian Button (Secondary, muted fill) so the CTA
affordance and feedback are the component's concern, not the panel's.
Drops the now-dead label_char_w helper.
2026-06-20 11:34:04 +08:00
Kayshen-X c887413074 refactor(editor): sink top_bar + settings + export dropdowns/buttons to jian
TopBar globe + file-menu triggers -> SelectTrigger (icon variant); agent-settings ProviderSelect/ProviderField + property-panel export format/scale dropdowns -> SelectTrigger (text); git_panel_diff glyph buttons -> jian Button(label). Removed the obsolete locale-glyph centering helper+const+test (SelectTrigger owns that now). SKIPPED (correctly): brand-logo buttons, the TopBar agent chip (compound), git branch button (multi-path icon + left-aligned). 6-agent workflow + central verify.
2026-06-20 11:27:25 +08:00
Kayshen-X c10a6638a9 chore(editor): SelectTrigger icon_paths field; bump jian 2026-06-20 11:16:46 +08:00
Kayshen-X d4cd38333f refactor(editor): sink component-browser kit dropdown to jian SelectTrigger
The kit-filter dropdown trigger (feedback wash + border + truncated label + chevron) now renders via jian SelectTrigger — one component call, feedback/label/chevron all internal. Demonstrates the dropdown 收口 pattern. Bumps vendor/jian to 144eb50.
2026-06-20 11:09:16 +08:00
Kayshen-X 27d5d0aae1 refactor(editor): sink scattered icon buttons to jian IconButton
top_bar paint_icon_button, design_md icon_button, and the align-toolbar align-icon row now render via jian IconButton instead of hand-rolling feedback + draw_icon. Their hover/active rendering is now the component's concern. align-toolbar idle icons go muted_foreground (shadcn toolbar look). Left compound (icon+chevron/brand-logo), labelled, and text-glyph buttons untouched — they aren't single lucide-icon buttons.
2026-06-20 11:01:34 +08:00
Kayshen-X a9bf1448a3 refactor(editor): toolbar icon buttons use jian IconButton; drop OP copy
toolbar's paint_button now renders jian IconButton (icon.paths() -> generic d-strings); removed the OP-local IconButton struct + paint_icon_button helpers from button.rs (the component now lives in jian). Bumps vendor/jian to 346eeb3. Other scattered icon buttons migrate next.
2026-06-20 10:54:40 +08:00
Kayshen-X 8eef1188ce refactor(editor): unify toolbar icon buttons into one paint_icon_button helper
Adds button::paint_icon_button (full icon button = hover/pressed/active feedback on jian Button + centred icon) and paint_icon_button_feedback (the bg+active funnel). toolbar's paint_button now delegates to it instead of hand-rolling active-fill + ghost-feedback + draw_icon separately. All toolbar icon buttons (tool buttons + shape slot) now funnel hover/active rendering through one place. Active highlight now jian Button Primary (r6). Removed dead BUTTON_RADIUS.
2026-06-20 10:38:42 +08:00