@melite/image-mask-studio 0.1.4-alpha → 0.1.5-pre-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/lib/ui/BboxLeafCanvas.js +3 -2
- package/lib/ui/PaintLeafCanvas.js +2 -1
- package/lib/ui/paintCopy.d.ts +34 -0
- package/lib/ui/paintCopy.js +32 -0
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Leaf-face carrier of the retired mask card's studio surfaces — paint and bbox canvases embedded in modifier leaves.
|
|
3
|
+
kind: package-library
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @melite/image-mask-studio
|
|
7
|
+
|
|
8
|
+
`@melite/image-mask-studio` carries the two studio surfaces the mask card's modifier leaves embed: the brush canvas (`./paint-canvas`) and the rectangle canvas (`./bbox-canvas`). The card itself is retired at parity (CONTRACT D — no cardPackages row remains); the package is DEMOTED to a leaf-face carrier and the takeover client is gone. The root door is dependency-free leaf data both canvases share.
|
|
9
|
+
|
|
10
|
+
## Contract
|
|
11
|
+
|
|
12
|
+
- `./paint-canvas` — `PaintLeafCanvas`, the brush canvas a paint mod leaf embeds. Strokes render on a transparent overlay so the saved PNG's alpha IS the stroke shape — the `LoadImageMask` lane reads exactly that alpha; the view fits at 640. Committed strokes report live through `onChange`, and a paint-over seeds from the existing payload. A commit-gate ref mirror keeps pointerup from committing a blank payload.
|
|
13
|
+
- `./bbox-canvas` — `BboxLeafCanvas`, the rectangle canvas a bbox mod leaf embeds. The drawn box reports image-pixel coordinates (naturals, not view pixels), stays clearable (`onChange(null)`), and still takes a rectangle over the blank fitted 1024 canvas when no image is staged.
|
|
14
|
+
- `.` — `paintInk.ts`, the shared leaf data (the stroke ink constants), importable under plain Node with no React.
|
|
15
|
+
- `./package.json` — the manifest.
|
|
16
|
+
|
|
17
|
+
Both canvases port from the retired modal; the leaf's own Add/Save/Cancel owns commit.
|
|
18
|
+
|
|
19
|
+
## Model Experience
|
|
20
|
+
|
|
21
|
+
### Request context and condition
|
|
22
|
+
|
|
23
|
+
The canvases author mask payloads for other cards' runs; they never run anything.
|
|
24
|
+
|
|
25
|
+
#### What the model sees
|
|
26
|
+
|
|
27
|
+
None — the package contributes no model-visible input.
|
|
28
|
+
|
|
29
|
+
#### Token effect
|
|
30
|
+
|
|
31
|
+
zero-direct — the package contributes no prompt or schema to any language-model context.
|
|
32
|
+
|
|
33
|
+
#### KV Cache effect
|
|
34
|
+
|
|
35
|
+
independent — nothing here appends to or reshapes a session cache.
|
|
36
|
+
|
|
37
|
+
## Known Limitations and Deferred Work
|
|
38
|
+
|
|
39
|
+
- **The card is retired (CONTRACT D)** — no cardPackages row exists; the package survives only as the leaf-face carrier.
|
|
40
|
+
- **No takeover client** — the former modal studio surface is gone; the leaves are the only remaining faces.
|
package/lib/ui/BboxLeafCanvas.js
CHANGED
|
@@ -18,6 +18,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
18
18
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
19
19
|
import { Button } from "@deepseek-ai/dsh-client-ui-primitives";
|
|
20
20
|
import { PAINT_STROKE_INK } from "../paintInk.js";
|
|
21
|
+
import { paintCopy } from "./paintCopy.js";
|
|
21
22
|
const FIT = 640;
|
|
22
23
|
const loadImage = (url) => new Promise((resolve) => {
|
|
23
24
|
if (url === "") {
|
|
@@ -189,7 +190,7 @@ export function BboxLeafCanvas(props) {
|
|
|
189
190
|
onChange(null);
|
|
190
191
|
};
|
|
191
192
|
return (_jsxs("div", { "data-bbox-leaf-canvas": "embedded", style: { display: "flex", flexDirection: "column", gap: 8 }, children: [_jsx("canvas", { ref: viewRef, "data-testid": "bbox-leaf-view", "data-bbox-canvas": "view", style: { maxWidth: "100%", cursor: "crosshair", touchAction: "none", borderRadius: 4, display: "block" }, onPointerDown: onDown, onPointerMove: onMove, onPointerUp: onUp, onPointerCancel: onUp }), _jsxs("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [_jsx("span", { style: { opacity: 0.7, fontSize: 12, flex: 1 }, children: rect !== null && rect.w >= 1 && rect.h >= 1
|
|
192
|
-
?
|
|
193
|
-
:
|
|
193
|
+
? paintCopy.bboxSize({ w: rect.w, h: rect.h })
|
|
194
|
+
: paintCopy.bboxHint }), _jsx(Button, { variant: "ghost", onClick: clear, children: paintCopy.clearBoxAction })] })] }));
|
|
194
195
|
}
|
|
195
196
|
//# sourceMappingURL=BboxLeafCanvas.js.map
|
|
@@ -16,6 +16,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
16
16
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
17
17
|
import { Button, Input } from "@deepseek-ai/dsh-client-ui-primitives";
|
|
18
18
|
import { PAINT_STROKE_INK } from "../paintInk.js";
|
|
19
|
+
import { paintCopy } from "./paintCopy.js";
|
|
19
20
|
const FIT = 640;
|
|
20
21
|
/** Load an image element from a URL (null while loading/failed —
|
|
21
22
|
* the canvas degrades to the blank 1024 fit, never a crash). */
|
|
@@ -213,7 +214,7 @@ export function PaintLeafCanvas(props) {
|
|
|
213
214
|
redraw();
|
|
214
215
|
onChange("");
|
|
215
216
|
};
|
|
216
|
-
return (_jsxs("div", { "data-paint-leaf-canvas": "embedded", style: { display: "flex", flexDirection: "column", gap: 8 }, children: [_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [_jsxs("label", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
217
|
+
return (_jsxs("div", { "data-paint-leaf-canvas": "embedded", style: { display: "flex", flexDirection: "column", gap: 8 }, children: [_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [_jsxs("label", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [paintCopy.brushLabel, _jsx(Input, { type: "range", "aria-label": paintCopy.brushSizeAria, min: 4, max: 128, step: 2, value: String(brushSize), onChange: (e) => { setBrushSize(Number(e.target.value)); } }), _jsx("span", { style: { width: 28, textAlign: "right" }, children: brushSize })] }), _jsx("span", { style: { opacity: 0.7, fontSize: 12, flex: 1 }, children: hasStrokes ? paintCopy.strokesHint : paintCopy.paintHint }), _jsx(Button, { variant: "ghost", onClick: clearPaint, children: paintCopy.clearAction })] }), _jsx("canvas", { ref: viewRef, "data-testid": "paint-leaf-view", style: {
|
|
217
218
|
display: viewSize === null ? "none" : "block",
|
|
218
219
|
maxWidth: "100%",
|
|
219
220
|
border: "1px solid var(--dsw-alias-border-l2)",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* paintCopy.ts — THE PAINT LEAF COPY DICTIONARY. Client UI copy is locale-owned —
|
|
3
|
+
* presentation code owns no copy literals; it consumes them here through the typed
|
|
4
|
+
* seat. A second locale plugs into this dictionary without touching a single leaf
|
|
5
|
+
* component.
|
|
6
|
+
*
|
|
7
|
+
* THE BOUND: static user-visible FACES of the paint + bbox leaf canvases live here
|
|
8
|
+
* (labels, hints, aria names, clear actions, the bbox size readout). Canvas DATA —
|
|
9
|
+
* the stroke ink (paintInk.ts), data-testid hooks, classNames, and numeric control
|
|
10
|
+
* seats (min/max/step) — rides the components, never this dictionary.
|
|
11
|
+
*/
|
|
12
|
+
/** The typed dictionary. Keys are stable copy ids. */
|
|
13
|
+
export declare const paintCopy: {
|
|
14
|
+
/** The brush-size slider's visible label. */
|
|
15
|
+
readonly brushLabel: "Brush";
|
|
16
|
+
/** The brush-size slider's accessible name. */
|
|
17
|
+
readonly brushSizeAria: "Brush size";
|
|
18
|
+
/** The paint hint once strokes landed (alpha = the mask). */
|
|
19
|
+
readonly strokesHint: "strokes paint the mask (alpha = the mask)";
|
|
20
|
+
/** The paint hint before the first stroke. */
|
|
21
|
+
readonly paintHint: "drag on the image to paint the mask";
|
|
22
|
+
/** The paint toolbar's clear action. */
|
|
23
|
+
readonly clearAction: "Clear";
|
|
24
|
+
/** The bbox size readout in view pixels. */
|
|
25
|
+
readonly bboxSize: (p: {
|
|
26
|
+
w: number;
|
|
27
|
+
h: number;
|
|
28
|
+
}) => string;
|
|
29
|
+
/** The bbox hint before a box is drawn. */
|
|
30
|
+
readonly bboxHint: "drag on the image to scope the selection";
|
|
31
|
+
/** The bbox toolbar's clear action. */
|
|
32
|
+
readonly clearBoxAction: "Clear box";
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=paintCopy.d.ts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* paintCopy.ts — THE PAINT LEAF COPY DICTIONARY. Client UI copy is locale-owned —
|
|
3
|
+
* presentation code owns no copy literals; it consumes them here through the typed
|
|
4
|
+
* seat. A second locale plugs into this dictionary without touching a single leaf
|
|
5
|
+
* component.
|
|
6
|
+
*
|
|
7
|
+
* THE BOUND: static user-visible FACES of the paint + bbox leaf canvases live here
|
|
8
|
+
* (labels, hints, aria names, clear actions, the bbox size readout). Canvas DATA —
|
|
9
|
+
* the stroke ink (paintInk.ts), data-testid hooks, classNames, and numeric control
|
|
10
|
+
* seats (min/max/step) — rides the components, never this dictionary.
|
|
11
|
+
*/
|
|
12
|
+
/** The typed dictionary. Keys are stable copy ids. */
|
|
13
|
+
// v8 ignore next -- exercised key-by-key by the copy wall's census arm
|
|
14
|
+
export const paintCopy = {
|
|
15
|
+
/** The brush-size slider's visible label. */
|
|
16
|
+
brushLabel: "Brush",
|
|
17
|
+
/** The brush-size slider's accessible name. */
|
|
18
|
+
brushSizeAria: "Brush size",
|
|
19
|
+
/** The paint hint once strokes landed (alpha = the mask). */
|
|
20
|
+
strokesHint: "strokes paint the mask (alpha = the mask)",
|
|
21
|
+
/** The paint hint before the first stroke. */
|
|
22
|
+
paintHint: "drag on the image to paint the mask",
|
|
23
|
+
/** The paint toolbar's clear action. */
|
|
24
|
+
clearAction: "Clear",
|
|
25
|
+
/** The bbox size readout in view pixels. */
|
|
26
|
+
bboxSize: (p) => `box ${Math.round(p.w)}×${Math.round(p.h)} (view px)`,
|
|
27
|
+
/** The bbox hint before a box is drawn. */
|
|
28
|
+
bboxHint: "drag on the image to scope the selection",
|
|
29
|
+
/** The bbox toolbar's clear action. */
|
|
30
|
+
clearBoxAction: "Clear box",
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=paintCopy.js.map
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
2
|
+
"version": "0.1.5-pre-alpha",
|
|
3
3
|
"license": "SSPL-1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "the mask-studio carrier, DEMOTED (CONTRACT D — the card retired at parity): ui/ survives as the leaf-face carrier (paint + bbox); the takeover client is gone",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.1",
|
|
23
23
|
"react": "^19.3.0",
|
|
24
|
-
"@melite/contracts": "0.1.
|
|
24
|
+
"@melite/contracts": "0.1.5-pre-alpha"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@testing-library/jest-dom": "*",
|