Major update for v1 and tests

This commit is contained in:
khalid@traclabs.com
2026-05-23 03:28:58 -05:00
parent 628a6765f4
commit b1fb6fa3aa
1748 changed files with 27723 additions and 1854 deletions

89
src/constants/products.js Normal file
View File

@@ -0,0 +1,89 @@
/**
* Product type configuration for the Pawfectly Yours editor.
*
* The frontend rendering is parameterized by these objects so that the same
* editor code can drive shirts, magnets, earrings, stickers, and so on. Only
* code reads this — there is intentionally no UI for picking the active
* product.
*
* Coordinate systems
* ──────────────────
* Every product has TWO coordinate systems:
*
* 1. **Design coordinates** (`canvasSize`) — the integer space in which
* individual elements (images, text, stickers) live. Element x/y/width/
* height are in these units. The server export pipeline scales from
* `canvasSize` to the final 4500×4500 print resolution.
*
* 2. **Product SVG coordinates** (`productSvg.width / .height`) — the
* viewBox of the product mockup that's drawn behind the design canvas.
* The `printZone` field positions the design canvas inside the product
* mockup, in these units.
*
* Keeping `canvasSize` at 300 (the historical value) means existing templates
* and the server-side export math do not need to change. The visual fit
* (canvas overlapping the print zone of the product) is achieved by CSS
* scaling the rendered Konva Stage at runtime.
*/
export const PRODUCT_TYPES = {
shirt: {
id: 'shirt',
label: 'T-Shirt',
canvasSize: 300,
// Where on the product mockup the design canvas should overlay, in
// product SVG coordinates. Sized roughly to a real DTG print zone for
// a youth-medium tee.
//
// Note: the product SVG's viewBox is offset (starts at 40, 50) to crop
// empty margin around the shirt outline. printZone coords are in that
// same viewBox space — i.e. (90, 130) is what the chest landed at
// after the crop, not the path's raw (130, 180).
printZone: { x: 90, y: 130, width: 220, height: 220 },
productSvg: {
// Component name (looked up by DesignCanvas) and the dimensions of its
// viewBox. Must match the actual SVG.
component: 'shirt',
width: 400,
height: 470,
},
background: {
// 'color' = user can pick from SHIRT_COLORS
// 'fixed' = use background.color as a constant fill
mode: 'color',
defaultColorId: 'white',
},
},
// Reference shapes for future products. None of these are wired into the
// UI yet, but the DesignCanvas/ProductSVG plumbing is ready to handle them.
//
// magnet: {
// id: 'magnet',
// label: 'Magnet',
// canvasSize: 300,
// printZone: { x: 30, y: 30, width: 240, height: 240 },
// productSvg: { component: 'magnet', width: 300, height: 300 },
// background: { mode: 'fixed', color: '#f4f1ee' },
// },
// earring: { ... },
// sticker: { ... },
};
/**
* Which product the editor is currently configured for. Change this constant
* to point at a different `PRODUCT_TYPES` entry. There's intentionally no UI
* exposure — switching products is a code change.
*/
export const ACTIVE_PRODUCT_ID = 'shirt';
export function getActiveProduct() {
const product = PRODUCT_TYPES[ACTIVE_PRODUCT_ID];
if (!product) {
throw new Error(
`Unknown ACTIVE_PRODUCT_ID="${ACTIVE_PRODUCT_ID}". `
+ `Valid ids: ${Object.keys(PRODUCT_TYPES).join(', ')}`
);
}
return product;
}