63 Commits

Author SHA1 Message Date
3adbfffb9d Spur label: position at 75% height in the wide bottom portion
Center text at 75% of trapezoid height where the shape is widest,
using the actual width at that height for proper fit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:32:23 +04:00
762e65e9a6 Spur label: center at the wide end of the trapezoid
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:31:35 +04:00
35aa0bf7dc Position spur label in the wider area of the trapezoid
Center text at vertical midpoint, shifted right toward the wider end
where there's more horizontal space. Uses 55% of the mid-height width
as center position and 85% as available width.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:31:11 +04:00
6b94339af2 Fix spur label: position at wider end, correct mirrored angle calculation
- Move text to 65% from top (wider end) so it fits without shrinking
- Fix effective angle for mirrored symbols: use (360-rot) to determine
  if flip is needed, preventing incorrect upside-down detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:28:04 +04:00
072c80e886 Fix spur label sizing: use narrow end width so text fits inside trapezoid
Position text at 40% from top (toward narrow end) and constrain width
to the narrower edge so text never overflows the trapezoid shape.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:26:16 +04:00
3506d6164d Fix spur/mirrored symbol text: counter-mirror so text stays readable
Mirrored symbols need text counter-mirrored (scale -1,1) to prevent
backwards text. Restored mirror fix that was incorrectly removed.
Applied to both canvas renderer and SVG export.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:24:49 +04:00
f6b298254b Use inline style for text bold/font in SVG export (Ignition compat)
Ignition strips font-weight/font-family/font-size as separate SVG
attributes but preserves them inside style="..." CSS. Moved all text
styling to inline style for conveyance labels and BCN/SOL/PDP symbols.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:19:59 +04:00
86f51f2534 Fix BCN/SOL/PDP text centering for Ignition compatibility
Replace dominant-baseline="central" (unsupported in Ignition) with
manual y offset (10 -> 12.8) for proper vertical centering of text
inside these symbol boxes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:16:34 +04:00
c69d4080fa Mirror labels with their symbols instead of counter-mirroring
Labels now follow the mirrored shape naturally — text mirrors
along with the conveyor/shape as the user expects.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:11:01 +04:00
533465be3c Fix text readability: always right-side up on all conveyance types
Canvas renderer:
- Straight/spur: flip text 180 when rotation is 91-269 deg
- Mirror: counter-scale text so it doesn't read backwards
- Curved: compute world angle (sym rotation + tangent), flip if upside-down

SVG export:
- Curved text now includes rotation transform along the arc tangent
- Straight text includes rotation correction for readability
- All text stays grouped with its shape for proper transform inheritance

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:09:40 +04:00
ea367df42a Fix SVG export: group shape+text, preserve rotation, stroke-width 1px
- Wrap each conveyance shape + its label text in a <g> element so
  rotation/mirror transforms apply to both shape and text together
- Change stroke-width from 0.5 to 1 on all conveyance and PE shapes
  (both canvas renderer and SVG export)
- Text is now inside the group, inheriting the transform — no more
  floating unrotated labels

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:06:49 +04:00
e3a0e422e6 Redesign toolbar, palette, and dock UI
Toolbar:
- Compact project/MCM selectors always visible at top
- Action bar (SVG, JSON, Import, Clear) as compact button strip
- Cleaner section toggles with minimal chrome
- Inline settings rows (W/H and Grid/Gap on one line each)
- Narrower width (220px vs 240px)

Palette:
- Group headers are collapsible (start collapsed to save space)
- Small symbols (Controls, Sensors, I/O, Other) use 2-column grid
- Conveyance keeps list layout (wider items)
- Lighter, less cluttered item styling
- Custom scrollbar

Color scheme:
- Shifted from navy/red (#16213e/#e94560) to slate/blue (#111827/#3b82f6)
- Better contrast and more professional feel
- DeviceDock updated to match

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 20:49:45 +04:00
1e67c3de47 Add SVG import, JSON export, and embed layout data in SVG export
- SVG export now embeds layout JSON as HTML comment for re-import
- New loadLayoutSVG() extracts embedded data from exported SVGs
- Import accepts both .json and .svg files
- New exportJSON() saves layout as MCM_layout.json
- JSON export button added to toolbar

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 20:45:05 +04:00
37f3700a18 Name SVG export after current MCM (e.g. MCM09_Detailed_View.svg)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 20:42:39 +04:00
bf0eced44c Fix SVG export labels: absolute coords, no transforms (Ignition compat)
Ignition strips SVG transforms from text elements, causing labels to
float to wrong positions. Now all text uses pre-computed absolute x/y
coordinates without any transform attributes. Also fixes positioning
for curved (at arc midpoint), spur (trapezoid center), and induction
(strip center) symbols.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 20:36:50 +04:00
6a38ecaa27 Fix SVG export label alignment for all conveyance types
- Curved: position at arc midpoint with rotation along curve
- Spur: center in trapezoid shape, not bounding box
- All: use dy offset instead of dominant-baseline for reliable centering

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 20:31:00 +04:00
896198c9d4 Fix label placement for curved and spur symbols
- Curved: position text at arc band midpoint, rotated along the curve
- Spur: center text in the trapezoid shape, not the bounding box

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 18:28:16 +04:00
2f5c43a07c Allow conveyor device labels to drop on spurs/curves/inductions/extendos
isTypeCompatible now matches by conveyance family, not just SVG file.
Conveyor family includes: conveyor, spur, curved_conv, induction, extendo.
Chute family includes: chute, tipper, curved_chute.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 18:26:39 +04:00
07cee1c151 Add internal labels for conveyance symbols (canvas + SVG export)
Parse labels like UL17_22_VFD into stacked text: "UL" / "17-22".
Bold black Arial, targets 14px but auto-scales down to fit with
consistent padding. Strips _VFD suffix, splits prefix from numbers.
If full text doesn't fit, strips the letter prefix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 18:23:19 +04:00
09cafa4577 Fix shift-drag vertical movement, PE shape outline and hit-testing
- Fix shift-drag: require 8px movement before locking axis, use strict
  greater-than to avoid horizontal bias at small deltas
- Add PE shape-following outline for selection/hover/collision highlights
- Add PE shape-aware hit-testing (arrow + beam + receiver zones with margin)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 18:06:22 +04:00
67cbf5c6ea Fix shift-drag jitter: lock axis once instead of re-evaluating each frame
The axis constraint was recalculated every mouse move, causing the symbol
to jerk between horizontal and vertical near the 45-degree diagonal.
Now the axis locks on first movement and stays locked until shift is released.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 18:03:04 +04:00
b68622a63a Update PE default size to 46x14 to match reference layout
Also add previous 30x14 default to migration table so existing
PEs at either old size get updated on load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 18:01:08 +04:00
271f646e1d Export overlay devices (PE, FIO/SIO, DPM, PDP, MCM) on top of conveyance
Split SVG export into two passes: base conveyance symbols first, then
overlay devices rendered last so they appear on top in the exported SVG.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 18:00:01 +04:00
94c57b4708 Export conveyors/extendos/photoeyes as programmatic SVG paths
Replaces embedded SVG export (which used non-uniform scale transforms
that stretched strokes) with programmatic path/rect elements matching
the canvas renderer. Consistent 0.5px stroke at any size.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:58:17 +04:00
b0648f06b6 Add symbol size migration: update outdated defaults on load
When loading saved state, symbols with known outdated default sizes
(e.g., photoeye 56x20) are migrated to current defaults (30x14).
Only exact matches of old defaults are migrated — user-resized
symbols keep their custom dimensions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:36:05 +04:00
006692de32 Fix palette thumbnails: white-fill curved SVGs + invert filter for dark bg
- Change all curved conveyor/chute SVGs from black to white fill
- Add CSS filter:invert(1) to palette thumbnails so white-fill symbols
  remain visible on the dark palette background

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:30:33 +04:00
39290bc153 Add xlsx as explicit dependency (was missing from package.json)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:24:35 +04:00
f8a26b4dd3 Fix all TypeScript errors: readonly cast, pdfjs types, vite config types
- Cast EPC defaultWaypoints readonly tuple to EpcWaypoint[] in collision.ts
- Fix pdfjs render() call with canvas property
- Remove unused @ts-expect-error directive
- Add @types/node and type annotations for vite.config.ts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:23:51 +04:00
c01173aa7b Draw conveyors/chutes/tippers/extendos programmatically for consistent stroke
SVG-based rendering caused non-uniform stroke scaling when symbols were
stretched. Now conveyor, chute, tipper are drawn as canvas rects, and
extendo is drawn as a canvas path with fixed left bracket proportions.
All use consistent 0.5px stroke regardless of size.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:22:14 +04:00
775c6e2e99 Make conveyors/chutes/inductions/extendos/spurs white; fix PE stroke and size
- Change all conveyance SVGs from black fill to white fill with black stroke
- Update programmatic rendering (curves, induction, spur) to white fill
- Replace PE 3-slice rendering with programmatic canvas paths for
  consistent stroke width at any size
- Reduce PE default size from 56x20 to 30x14 to fit around conveyor devices
- Update SVG export to match new white fills

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 17:17:09 +04:00
20b9547578 Fix EPC export: match end box position and stroke width to canvas renderer
- Right box x offset: 0 → -rb.w (extend backward, matching canvas)
- Stroke width: hardcoded 0.3 → EPC_CONFIG.lineWidth (1.5, matching line)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:50:53 +04:00
595c47fbf8 Rotate EPC end box 90°: swap dimensions to match start icon orientation
End box was 10×20 (tall/narrow perpendicular to line), now 20×10
(wide/squat along line), matching the start icon's landscape proportions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:48:26 +04:00
e4c67b165b Fix EPC end box collision and bounds to match 90° rotation
Rotate the direction vector -90° for the right box in collision
detection and bounds calculation to match the perpendicular
rendering orientation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:38:37 +04:00
a4884b4e9b Fix EPC SVG export: match stroke width and right box position; rotate end 90°
- Right box stroke now uses EPC_CONFIG.lineWidth (1.5) instead of 0.3
- Right box positioned at -rb.w (backward) matching canvas renderer
- End box rotated 90° (perpendicular to line) in canvas, export, and hit-testing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:38:07 +04:00
d721f47757 Improve EPC clickability: shape-accurate hit testing with generous margin
Replace bounding-box hit test with proper shape-aware check that tests
proximity to line segments and oriented end boxes with 8px hit margin,
making the thin EPC much easier to select and drag.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:27:30 +04:00
82bb1b46c8 Make EPC start/end outline thickness match the connecting line (1.5px)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:26:09 +04:00
db12a30701 Fix EPC jump on mouseup: stop shifting origin in recalcEpcBounds
Just expand w/h to cover the full waypoint extent without moving
sym.x/y. The origin-shifting math was causing the symbol to jump
in the direction of waypoint movement on mouse release.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:20:33 +04:00
c3da2da20d Fix EPC symbol jump on mouseup: preserve rotation center when updating bounds
recalcEpcBounds now properly normalizes the bounding box to start at
(0,0) in local space, adjusting sym.x/y to compensate so the world
position and rotation center stay constant. Handles rotated symbols
by rotating the center offset into world space.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:18:54 +04:00
eb4a570a70 Fix EPC waypoint jumping: defer bounds recalc to mouseup
Updating sym.w/h mid-drag shifted the rotation center used by
toSymbolLocal, causing waypoints to jump. Now recalcEpcBounds
only runs on mouseup, keeping the coordinate transform stable.
Also removed the endpoint slide constraint that was causing
instability due to using the moving position as direction source.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:17:18 +04:00
81e0bd0f3d Stabilize EPC waypoint dragging: constrain endpoints to slide along segment
- First/last waypoints now only extend/shorten along their segment direction,
  preventing unwanted rotation of the end boxes
- Middle waypoints remain freely draggable for direction changes
- Add default middle waypoint so new EPCs have 3 control points

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:14:25 +04:00
c9a8dd8f5b Fix EPC rendering: thicker line, consistent strokes, correct end rotation
- Increase EPC line width from 0.4 to 1.5 for visibility
- Increase right box stroke from 0.3 to 1.0 to match left icon stroke
- Fix right box to extend behind last waypoint (like left icon), not forward

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:11:09 +04:00
db19535f39 Make BCN, SOL, PDP symbols consistent: same viewBox, font, and size
All three now use identical 20x20 viewBox, 19x19 rect, font-size 8,
centered text with dominant-baseline="central". Updated symbol defs
to match the new 20x20 dimensions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 19:20:49 +04:00
34ec2a8450 Fix BCN, SOL, PDP symbol text: center properly and fit inside box
Reduced font sizes and used dominant-baseline="central" with y at
the vertical center so text is centered both horizontally and
vertically inside the box without overlapping the border.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 19:19:12 +04:00
84bd2f2978 Add default MCM symbol to every MCM's device list
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 19:18:10 +04:00
224aad4408 Fix reversed resize direction on mirrored symbols
When a symbol is mirrored, negate the horizontal drag delta and swap
the left/right handle identity so resizing matches the visual direction.
Also fixes spur handle resize with mirrored spurs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 19:12:33 +04:00
4f1d680406 Merge device dock into single smart list: drop to place or assign ID
- Remove tabs, single unified device list grouped by type
- Drop on empty space → places new symbol with device ID
- Drop on existing symbol → assigns the device ID as label
- Drop-target highlight shown when hovering over existing symbols
- Always sorted ascending by device type

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 19:07:42 +04:00
d09ffd4a22 Fix spur/induction collision polygons to account for mirrored state
Collision detection now mirrors spur trapezoid and induction arrow
vertices when the symbol is mirrored, matching the visual appearance.
Previously the collision polygon stayed unmirrored causing false
positives/misaligned collision zones.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 19:05:53 +04:00
31ea4c0908 Add shift+drag to constrain movement to horizontal or vertical axis
Holding Shift while dragging locks movement to the dominant axis
(whichever has the larger delta from drag start). Works for both
single and multi-selection moves.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 18:59:51 +04:00
b4e3a7d6ff Always sort IDs tab ascending by device type, not just when searching
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 18:46:10 +04:00
da17f95a33 Add symbol icons to IDs tab and sort search results by device type
- Each ID entry now shows a small SVG icon of its symbol type
- Device type name shown as subtle suffix
- Search results sorted ascending by device type, then by ID
- Search also matches device type name

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 18:45:19 +04:00