Covers all 7 nav sections with layout descriptions, all 11 dialog types,
recurring widget patterns (split pane, tabbed view, table, gallery, card,
field editor, modal dialog, non-modal overlay, full-page sub-view, canvas,
lightbox) with every instance listed, complete template inventory (41 entries),
and a primitive taxonomy for a future higher-level UI representation.
Linked from CLAUDE.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers: file map, KV prefix table, all data model shapes, full API
route index, frontend section layout, image file lifecycle, code style
preferences, git conventions, and a pointer to future-plans.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Default view: processed image (full size in dialog), or placeholder if
not yet processed. Name and type selector always visible at top.
- "Adjust corners…" button reveals the canvas editor (lazy-loaded on
first click, so there's no canvas allocation cost on open).
- "← Back to image" returns to the image view.
- Corners are only re-processed on Save if the canvas was opened.
- Tabs reduced to Fields | Contents (Corners is no longer a tab).
- Added preview image CSS; btn-link style for the back button.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- build_field_editor() helper: reusable field row editor shared by
bin editor, bin type dialog (open_component_dialog still uses its own)
- open_bin_editor: tabs (Corners|Fields|Contents), field editor on
Fields tab, content list on Contents tab, save always persists fields
- open_bin_type_dialog: field editor appended below existing form fields
- render_bin_contents / open_bin_content_dialog: content item CRUD
(component ref or free-text name, quantity, notes); add/edit/delete
update all_bins immediately without closing the editor
- bc-cancel / bc-save handlers registered in init()
- bin-content-row CSS
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- t-dialog-bin-editor: tabs (Corners|Fields|Contents), field rows, contents list
- t-bin-content-row: row template for bin content items
- t-dialog-bin-content: dialog for adding/editing component or free-text items
- t-dialog-bin-type: append field rows section below existing form fields
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- bins: fields:{} and contents:[] on all new records
- bin types: fields:{} on all new records
- PUT /api/bins/:id accepts fields
- PUT /api/bin-types/:id accepts fields
- POST/PUT/DELETE /api/bins/:id/contents for content items
(type: 'component'|'item', component_id or name, quantity, notes)
- api.mjs: add_bin_content, update_bin_content, delete_bin_content
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Left click now exclusively drags corner/edge handles.
Middle click pans the view. preventDefault on mousedown
suppresses the browser's autoscroll activation on middle click.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Generalized 'Duplicate bin type' to 'Duplicate any entity' covering
components, bins, bin types, grids, templates, inventory, source images
- Clarified that bins (not just bin types) should carry generic fields
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Instead of applying raw 2D delta, project cursor movement onto the
outward normal of each edge so the edge can only be pushed/pulled
perpendicular to itself. Prevents shearing when dragging a side handle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Canvas width now read via getBoundingClientRect after setting style.width=100%,
avoiding the parentElement.clientWidth padding issue that made css_w exceed
the actual rendered width and broke hit-testing
- All handle drags (corners + midpoints) now use relative delta via drag_prev_img
instead of absolute cursor position, preventing handle teleport on grab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a source image file is deleted without going through the API
(e.g. the old bin delete bug), the KV entry remains and shows a
broken image. The new maintenance action scans all source image
entries, removes any whose file is missing on disk, and reports
how many were cleaned up.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Source images are shared entities managed through the Images gallery.
Deleting a bin should only remove the processed output (image_filename),
not the source.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bin types store a name, physical W×H in mm, and optional description.
When editing a bin, a type can be selected from a dropdown; this
pre-fills and locks the dimension inputs. Custom dimensions remain
available when no type is selected.
- lib/storage.mjs: bin type CRUD with bt: prefix
- server.mjs: /api/bin-types CRUD routes; type_id accepted on bin
create/update routes; DELETE protected if any bin references the type;
type dims copied onto bin when type_id is set
- public/lib/api.mjs: bin type wrappers; rename_bin → update_bin (accepts
any fields)
- public/templates.html: Types tab in bins section; t-bin-type-row;
t-dialog-bin-type; type selector in bin editor dialog
- public/app.mjs: all_bin_types state loaded at startup; render_bin_types_list();
open_bin_type_dialog(); type selector in open_bin_editor(); /bins/types routing
- public/style.css: bin types list styles
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When de-perspectiving a bin photo taken at an angle, inferring the
output size from the quadrilateral shape squishes the result. Entering
real-world W×H (mm) lets the server use the correct aspect ratio,
scaled to the same resolution as the inferred size.
- Bin editor dialog: W×H number inputs, pre-filled from saved phys_w/phys_h
- PUT /api/bins/:id/corners: accepts optional phys_w/phys_h; when provided,
derives bin_w/bin_h from the physical aspect ratio at equivalent area
- phys_w/phys_h stored on the bin record for re-use on next edit
- future-plans.md: bin types note (reusable dimensions per model)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
showModal() must be called before load_image() so the canvas has its
correct layout dimensions when parentElement.clientWidth is read.
Calling it after caused css_w to be computed against an unlaid-out
dialog, making drawn handle positions not match hit-test positions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New top-level nav section showing all source images in a list view
with checkboxes to edit the uses array (grid, bin) per image. Allows
correcting wrongly-tagged images without code changes.
Server PUT /api/source-images/:id was already in place; re-added the
frontend API wrapper that was prematurely removed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removing toggle interactivity from use badges — they were confusing
and the wrong place to manage uses. The uses array is now managed
automatically by upload context. Badges are plain spans.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bins section now mirrors the grids section with two tabs:
- Bins: gallery of processed bin records
- Sources: source images tagged with uses=['bin'], with upload and
'+ Bin' button to create a bin record from an existing source image
Server: POST /api/bins/from-source accepts source_id, creates bin
record and adds 'bin' to the source image's uses array.
URL state: /bins → bins tab, /bins/sources → sources tab.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Inactive badges (uses not present on a source image) are now hidden
rather than shown at low opacity, which was visually noisy and
confusing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- lib/storage.mjs: bin CRUD with bin: prefix
- lib/grid-image.mjs: compute_bin_size() capped at 1024px
- server.mjs: POST/GET/PUT/DELETE /api/bins routes; PUT /api/bins/:id/corners
re-processes image via process_grid_image with rows=1 cols=1
- public/lib/api.mjs: bin API wrappers including upload_bin()
- public/index.html: Bins nav button
- public/templates.html: t-section-bins, t-bin-card, t-dialog-bin-editor
- public/app.mjs: render_bins(), open_bin_editor() using Grid_Setup,
save/cancel wiring in init()
- public/style.css: bin gallery and card styles
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace check-then-read with read-and-catch-ENOENT. The existsSync
pattern is redundant and slightly misleading; other errors still
propagate.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Drag indices 4-7 correspond to top/right/bottom/left edge midpoints.
Dragging a midpoint applies the delta to both adjacent corners, making
it easier to align bins with rounded corners where corner handles may
be obscured.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>