Files
odysseus/static/js/editor/tools/pen-path.js
T
pewdiepie-archdaemonandClaude Opus 5.5 5fac693c1c feat(photo-editor): Ajax Image Editor client (Photoshop-parity tools)
Photoshop-parity editor client: layers, selection/masking, brushes,
smart filters, LUT import, Quick Edit, mobile gestures, workspaces,
batch operations, and the service-worker versioning (v978->v1006).

Source: vendor/photocraft (ad1cff44) photo-editor client files, merged
onto upstream/dev (a8c147b2). Conflict resolution documented in
pr_work/A_conflicts.md; editor files taken from vendor/photocraft
(upstream's editor is an earlier snapshot of the same feature).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 11:57:35 +00:00

69 lines
1.6 KiB
JavaScript

/**
* Vector pen / path tool — click to drop anchors, double-click (or the
* Finish button / Enter) to close the path. The draft is rendered live as
* a `shape` layer of type `path`; the caller owns layer creation, geometry
* updates and cleanup so this module stays free of editor state.
*/
export function createPenPathTool({
saveState = () => {},
canvasCoords = () => ({ x: 0, y: 0 }),
mainCanvas = null,
ensurePathLayer = () => null,
drawPath = () => {},
commitPath = () => {},
cancelPath = () => {},
composite = () => {},
syncToolClearIndicators = () => {},
} = {}) {
let draft = null;
function addPoint(e) {
const point = canvasCoords(e, mainCanvas);
if (!Number.isFinite(point?.x) || !Number.isFinite(point?.y)) return false;
if (!draft) {
saveState('Add path');
const layer = ensurePathLayer();
if (!layer) return false;
draft = { layer, points: [point] };
} else {
draft.points.push(point);
}
drawPath(draft.layer, draft.points);
composite();
return true;
}
function begin(e) {
addPoint(e);
if (e && e.detail >= 2) finish();
return true;
}
function drag() {}
function end() {}
function finish() {
if (!draft) return false;
if (draft.points.length >= 2) {
commitPath(draft.layer, draft.points);
} else {
cancelPath(draft.layer);
}
draft = null;
composite();
syncToolClearIndicators();
return true;
}
function cancel() {
if (!draft) return false;
cancelPath(draft.layer);
draft = null;
composite();
return true;
}
return { begin, drag, end, finish, cancel, hasDraft: () => !!draft };
}