@pixerate/editor 0.194.0 → 0.196.0
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/dist/image-editor/controller.d.cts +7 -0
- package/dist/image-editor/controller.d.ts +7 -0
- package/dist/image-editor/index.cjs +573 -136
- package/dist/image-editor/index.js +447 -10
- package/dist/image-editor/selection/gesture.d.cts +12 -0
- package/dist/image-editor/selection/gesture.d.ts +12 -0
- package/dist/image-editor/selection/index.d.cts +1 -0
- package/dist/image-editor/selection/index.d.ts +1 -0
- package/dist/image-editor/selection/magnetic.d.cts +60 -0
- package/dist/image-editor/selection/magnetic.d.ts +60 -0
- package/dist/image-editor/selection/tool-options.d.cts +7 -1
- package/dist/image-editor/selection/tool-options.d.ts +7 -1
- package/dist/vector/controller.d.cts +6 -0
- package/dist/vector/controller.d.ts +6 -0
- package/dist/vector/index.cjs +94 -1
- package/dist/vector/index.d.cts +1 -0
- package/dist/vector/index.d.ts +1 -0
- package/dist/vector/index.js +93 -0
- package/dist/vector/layers.d.cts +32 -0
- package/dist/vector/layers.d.ts +32 -0
- package/package.json +1 -1
- package/skills/pixerate-image-editor/SKILL.md +2 -1
- package/skills/pixerate-image-selection-masking/SKILL.md +12 -2
package/dist/vector/index.js
CHANGED
|
@@ -9464,6 +9464,32 @@ var VectorEditorController = class _VectorEditorController {
|
|
|
9464
9464
|
this.change(labels[op], () => this.setDoc(reorder(this.doc.nodes)));
|
|
9465
9465
|
return { ok: true };
|
|
9466
9466
|
}
|
|
9467
|
+
/**
|
|
9468
|
+
* Moves a node to `index` among its siblings (bottom to top, 0 the bottom), as dragging it in
|
|
9469
|
+
* a layers panel does. Clipping groups and blends keep their order: their mask and keys are
|
|
9470
|
+
* placed by position.
|
|
9471
|
+
*/
|
|
9472
|
+
reorderNode(id, index) {
|
|
9473
|
+
const node = this.getNode(id);
|
|
9474
|
+
if (!node) return { ok: false, message: `No node "${id}".` };
|
|
9475
|
+
let parent = null;
|
|
9476
|
+
walkVectorNodes(this.doc.nodes, (n2, p) => {
|
|
9477
|
+
if (n2.id === id) parent = p;
|
|
9478
|
+
});
|
|
9479
|
+
const group = parent;
|
|
9480
|
+
if (group && (isVectorMaskGroup(group) || isVectorBlendGroup(group))) {
|
|
9481
|
+
return { ok: false, message: "The order inside a clipping group or blend is fixed." };
|
|
9482
|
+
}
|
|
9483
|
+
const siblings = group ? group.children : this.doc.nodes;
|
|
9484
|
+
const from = siblings.findIndex((n2) => n2.id === id);
|
|
9485
|
+
const to = Math.max(0, Math.min(siblings.length - 1, Math.round(index)));
|
|
9486
|
+
if (from === to) return { ok: true };
|
|
9487
|
+
const next = [...siblings];
|
|
9488
|
+
next.splice(from, 1);
|
|
9489
|
+
next.splice(to, 0, node);
|
|
9490
|
+
this.change("Move Layer", () => group ? this.replaceNode(group.id, { ...group, children: next }) : this.setDoc(next));
|
|
9491
|
+
return { ok: true };
|
|
9492
|
+
}
|
|
9467
9493
|
/**
|
|
9468
9494
|
* Combines the selected paths (two or more) into one with a boolean operation. `subtract`
|
|
9469
9495
|
* removes the upper shapes from the lowest one. The result takes the lowest shape's style
|
|
@@ -18559,6 +18585,68 @@ function createVectorEditorDocument(controller) {
|
|
|
18559
18585
|
}
|
|
18560
18586
|
});
|
|
18561
18587
|
}
|
|
18588
|
+
|
|
18589
|
+
// src/vector/layers.ts
|
|
18590
|
+
var VECTOR_LAYER_KIND_LABELS = {
|
|
18591
|
+
path: "Path",
|
|
18592
|
+
connector: "Connector",
|
|
18593
|
+
lens: "Lens",
|
|
18594
|
+
text: "Text",
|
|
18595
|
+
instance: "Symbol",
|
|
18596
|
+
group: "Group",
|
|
18597
|
+
frame: "Frame",
|
|
18598
|
+
mask: "Clipping Group",
|
|
18599
|
+
blend: "Blend",
|
|
18600
|
+
boolean: "Live Boolean",
|
|
18601
|
+
symmetry: "Symmetry"
|
|
18602
|
+
};
|
|
18603
|
+
function vectorLayerKind(node) {
|
|
18604
|
+
if (node.type === "text") return "text";
|
|
18605
|
+
if (node.type === "instance") return "instance";
|
|
18606
|
+
if (node.type === "path") return isVectorConnector(node) ? "connector" : isVectorLens(node) ? "lens" : "path";
|
|
18607
|
+
if (isVectorFrame(node)) return "frame";
|
|
18608
|
+
if (isVectorMaskGroup(node)) return "mask";
|
|
18609
|
+
if (isVectorBlendGroup(node)) return "blend";
|
|
18610
|
+
if (node.liveBoolean) return "boolean";
|
|
18611
|
+
if (isVectorSymmetryGroup(node)) return "symmetry";
|
|
18612
|
+
return "group";
|
|
18613
|
+
}
|
|
18614
|
+
function vectorLayerName(node) {
|
|
18615
|
+
const name = node.name?.trim();
|
|
18616
|
+
if (name) return name;
|
|
18617
|
+
if (node.type === "text") {
|
|
18618
|
+
const text = node.text.replace(/\s+/g, " ").trim();
|
|
18619
|
+
if (text) return text.length > 40 ? `${text.slice(0, 39)}\u2026` : text;
|
|
18620
|
+
}
|
|
18621
|
+
return VECTOR_LAYER_KIND_LABELS[vectorLayerKind(node)];
|
|
18622
|
+
}
|
|
18623
|
+
function vectorLayerChildren(node) {
|
|
18624
|
+
return node.type === "group" ? node.children.filter((child) => !child.blendStep) : [];
|
|
18625
|
+
}
|
|
18626
|
+
function vectorLayerRows(nodes, expanded = () => false) {
|
|
18627
|
+
const rows = [];
|
|
18628
|
+
const visit = (list, depth, parentId) => {
|
|
18629
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
18630
|
+
const node = list[i];
|
|
18631
|
+
const children = vectorLayerChildren(node);
|
|
18632
|
+
const open = children.length > 0 && expanded(node.id);
|
|
18633
|
+
rows.push({
|
|
18634
|
+
id: node.id,
|
|
18635
|
+
name: vectorLayerName(node),
|
|
18636
|
+
kind: vectorLayerKind(node),
|
|
18637
|
+
depth,
|
|
18638
|
+
parentId,
|
|
18639
|
+
visible: node.visible !== false,
|
|
18640
|
+
locked: !!node.locked,
|
|
18641
|
+
childCount: children.length,
|
|
18642
|
+
expanded: open
|
|
18643
|
+
});
|
|
18644
|
+
if (open) visit(children, depth + 1, node.id);
|
|
18645
|
+
}
|
|
18646
|
+
};
|
|
18647
|
+
visit(nodes, 0, null);
|
|
18648
|
+
return rows;
|
|
18649
|
+
}
|
|
18562
18650
|
export {
|
|
18563
18651
|
DEFAULT_VECTOR_BLEND_DISTANCE,
|
|
18564
18652
|
DEFAULT_VECTOR_BLEND_STEPS,
|
|
@@ -18625,6 +18713,7 @@ export {
|
|
|
18625
18713
|
VECTOR_HORIZONTAL_RESIZING,
|
|
18626
18714
|
VECTOR_HORIZONTAL_RESIZING_LABELS,
|
|
18627
18715
|
VECTOR_INK_MAX_CORNERS,
|
|
18716
|
+
VECTOR_LAYER_KIND_LABELS,
|
|
18628
18717
|
VECTOR_LENS_LABELS,
|
|
18629
18718
|
VECTOR_LENS_SPECS,
|
|
18630
18719
|
VECTOR_LENS_TYPES,
|
|
@@ -19127,6 +19216,10 @@ export {
|
|
|
19127
19216
|
vectorInkShapeName,
|
|
19128
19217
|
vectorInstanceDrawn,
|
|
19129
19218
|
vectorInstanceGroup,
|
|
19219
|
+
vectorLayerChildren,
|
|
19220
|
+
vectorLayerKind,
|
|
19221
|
+
vectorLayerName,
|
|
19222
|
+
vectorLayerRows,
|
|
19130
19223
|
vectorLensColorMap,
|
|
19131
19224
|
vectorLensDrawn,
|
|
19132
19225
|
vectorLiveBooleanSteps,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The vector document as a layers panel shows it: one row per node, top first, groups indented
|
|
3
|
+
* with their children when expanded. Hosts draw the rows themselves and act on them with the
|
|
4
|
+
* controller (`select`, `setVisible`, `setLocked`, `rename`, `reorderNode`).
|
|
5
|
+
*/
|
|
6
|
+
import type { VectorNode } from './types.cjs';
|
|
7
|
+
/** What a layer is, for its icon and its default name. */
|
|
8
|
+
export type VectorLayerKind = 'path' | 'connector' | 'lens' | 'text' | 'instance' | 'group' | 'frame' | 'mask' | 'blend' | 'boolean' | 'symmetry';
|
|
9
|
+
export declare const VECTOR_LAYER_KIND_LABELS: Record<VectorLayerKind, string>;
|
|
10
|
+
export interface VectorLayerRow {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
kind: VectorLayerKind;
|
|
14
|
+
/** 0 for the document's own nodes. */
|
|
15
|
+
depth: number;
|
|
16
|
+
parentId: string | null;
|
|
17
|
+
visible: boolean;
|
|
18
|
+
locked: boolean;
|
|
19
|
+
/** Children the row can show (a blend's generated steps are not counted). */
|
|
20
|
+
childCount: number;
|
|
21
|
+
expanded: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function vectorLayerKind(node: VectorNode): VectorLayerKind;
|
|
24
|
+
/** The node's name, else its text (for text), else its kind. */
|
|
25
|
+
export declare function vectorLayerName(node: VectorNode): string;
|
|
26
|
+
/** A group's children as the layers panel lists them: a blend's generated steps are left out. */
|
|
27
|
+
export declare function vectorLayerChildren(node: VectorNode): VectorNode[];
|
|
28
|
+
/**
|
|
29
|
+
* The rows for `nodes` (bottom to top, as documents keep them), top first. A group's children
|
|
30
|
+
* follow it, indented, when `expanded` says so.
|
|
31
|
+
*/
|
|
32
|
+
export declare function vectorLayerRows(nodes: readonly VectorNode[], expanded?: (id: string) => boolean): VectorLayerRow[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The vector document as a layers panel shows it: one row per node, top first, groups indented
|
|
3
|
+
* with their children when expanded. Hosts draw the rows themselves and act on them with the
|
|
4
|
+
* controller (`select`, `setVisible`, `setLocked`, `rename`, `reorderNode`).
|
|
5
|
+
*/
|
|
6
|
+
import type { VectorNode } from './types.js';
|
|
7
|
+
/** What a layer is, for its icon and its default name. */
|
|
8
|
+
export type VectorLayerKind = 'path' | 'connector' | 'lens' | 'text' | 'instance' | 'group' | 'frame' | 'mask' | 'blend' | 'boolean' | 'symmetry';
|
|
9
|
+
export declare const VECTOR_LAYER_KIND_LABELS: Record<VectorLayerKind, string>;
|
|
10
|
+
export interface VectorLayerRow {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
kind: VectorLayerKind;
|
|
14
|
+
/** 0 for the document's own nodes. */
|
|
15
|
+
depth: number;
|
|
16
|
+
parentId: string | null;
|
|
17
|
+
visible: boolean;
|
|
18
|
+
locked: boolean;
|
|
19
|
+
/** Children the row can show (a blend's generated steps are not counted). */
|
|
20
|
+
childCount: number;
|
|
21
|
+
expanded: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function vectorLayerKind(node: VectorNode): VectorLayerKind;
|
|
24
|
+
/** The node's name, else its text (for text), else its kind. */
|
|
25
|
+
export declare function vectorLayerName(node: VectorNode): string;
|
|
26
|
+
/** A group's children as the layers panel lists them: a blend's generated steps are left out. */
|
|
27
|
+
export declare function vectorLayerChildren(node: VectorNode): VectorNode[];
|
|
28
|
+
/**
|
|
29
|
+
* The rows for `nodes` (bottom to top, as documents keep them), top first. A group's children
|
|
30
|
+
* follow it, indented, when `expanded` says so.
|
|
31
|
+
*/
|
|
32
|
+
export declare function vectorLayerRows(nodes: readonly VectorNode[], expanded?: (id: string) => boolean): VectorLayerRow[];
|
package/package.json
CHANGED
|
@@ -252,7 +252,8 @@ in the source frame at the document's bit depth, colour mode and profile. Read
|
|
|
252
252
|
| `select_rect` | Rectangular marquee: `x`, `y`, `width`, `height` (natural px), `mode` (replace, add, subtract, intersect), `feather` px, `antiAlias`. Returns the summary. |
|
|
253
253
|
| `select_ellipse` | Elliptical marquee inscribed in `x`, `y`, `width`, `height`; same options. A feathered ellipse makes a vignette. Returns the summary. |
|
|
254
254
|
| `select_line` | Single row or column marquee: `orientation` `row` (at y) or `column` (at x), `position` in natural px, `mode`. A 1 px line across the image. Returns the summary. |
|
|
255
|
-
| `
|
|
255
|
+
| `quick_select` | Quick Selection: `strokes` (brush paths of `{x, y}`), `size` (diameter, default 30), `mode`, `sampleAllLayers`, `enhanceEdge`. Each stroke grows out to its region's edges; with `replace` the first replaces and the rest add. Paint inside the area, then check and fix with `add` / `subtract` strokes. Returns the summary. |
|
|
256
|
+
| `select_polygon` | The lasso: `points` (at least 3 `{x, y}` along the outline, closed automatically), `mode`, `feather`, `antiAlias`; `snapToEdges: {width, contrast}` makes it the Magnetic Lasso (points snap to edges, the outline follows them). Trace a subject's contour, not its box. Returns the summary (plus `outlinePoints` when snapped). |
|
|
256
257
|
| `magic_wand` | Select similar colour from `x`, `y`: `tolerance` 0..255 (default 32), `contiguous` (default true), `distance` `rgb` or `perceptual`, `sampleMerged`, `sample` (`composite` or `active-layer`), `mode`, `feather`. For flat backdrops and solid colours. Returns the summary. |
|
|
257
258
|
| `select_color_range` | Color Range, soft: `samples` (`[{color, x?, y?}]`) or a `preset` (reds … magentas, highlights, midtones, shadows, skinTones); `fuzziness` (samples 0..200, default 40; tone presets' falloff, default 20), `localized` px radius around positioned samples, `invert`, `sample`, `mode`, `feather`. Returns the summary. |
|
|
258
259
|
| `load_selection_from_image` | Load a mask image (`image` data URL or URL; white = selected) by `channel` (luminance, alpha, red, green, blue), with `threshold`, `invert`, `mode`. For AI or saved mattes; then `refine_selection`. Returns the summary. |
|
|
@@ -96,7 +96,9 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
|
|
|
96
96
|
| Subject | Method |
|
|
97
97
|
| --- | --- |
|
|
98
98
|
| Geometric areas: a frame, a screen, a band | `select_rect` / `select_ellipse`, with `feather` for soft transitions |
|
|
99
|
-
| A subject with a clear outline (product, person, animal) | `select_subject` if the host has a model; else `select_polygon`
|
|
99
|
+
| A subject with a clear outline (product, person, animal) | `select_subject` if the host has a model; else `select_polygon` with `snapToEdges` (12–30 points within `width` of the edge), then `refine_selection` |
|
|
100
|
+
| An area or subject that differs from its surroundings (a shirt, a sky, a car) | `quick_select` with strokes painted inside it, away from the edge (`size` a fraction of its width); `add` / `subtract` strokes where it fell short or leaked |
|
|
101
|
+
| A low-contrast or busy outline the edges don't follow | `select_polygon` without `snapToEdges`, along the contour (20–60 points) |
|
|
100
102
|
| Flat backdrop or solid colour (studio white, green screen, sky without clouds) | `magic_wand` on the backdrop (`tolerance` 20–40; `distance: "perceptual"` for gradients), then `invert_selection` |
|
|
101
103
|
| A colour spread across the image (all the reds, a dress) | `select_color_range` with `samples` (several picks) or a hue `preset`; `localized` to keep one area |
|
|
102
104
|
| Tones (shadows, highlights, a luminosity mask) | `select_color_range` with `preset` `shadows` / `midtones` / `highlights` |
|
|
@@ -155,6 +157,13 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
|
|
|
155
157
|
30–60), check `percent`, and grow with `mode: "add"`.
|
|
156
158
|
- **Box instead of outline:** `select_rect` around a subject masks its background too. Trace
|
|
157
159
|
the contour.
|
|
160
|
+
- **Quick Selection spills over a weak edge:** a stroke grows into neighbouring areas of a
|
|
161
|
+
similar colour. Paint smaller strokes further from the edge, then a `subtract` stroke on the
|
|
162
|
+
spill. Strokes near an edge also pull in the other side.
|
|
163
|
+
- **Magnetic outline jumps to the wrong edge:** `snapToEdges` follows the strongest edge near
|
|
164
|
+
each point, which can be a shadow or a texture. Put points within `width` of the edge you
|
|
165
|
+
want, add points where it turns or runs past another edge, raise `contrast` on a busy
|
|
166
|
+
background, and drop `snapToEdges` where the edge is too faint.
|
|
158
167
|
- **Over-feathering hard objects:** a 10 px feather on a product looks like a glow. Keep hard
|
|
159
168
|
edges at 0–2 px and refine soft ones instead.
|
|
160
169
|
- **Halo:** the old background shows as a light or dark fringe. `contract` 1–2 px or
|
|
@@ -183,7 +192,8 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
|
|
|
183
192
|
- `get_selection`: empty, bounds, area and percent after every step
|
|
184
193
|
- `select_all`, `deselect`, `invert_selection`: whole-image selections
|
|
185
194
|
- `select_rect`, `select_ellipse`: marquees
|
|
186
|
-
- `select_polygon`: the lasso, along a contour
|
|
195
|
+
- `select_polygon`: the lasso, along a contour; with `snapToEdges`, the Magnetic Lasso
|
|
196
|
+
- `quick_select`: brush strokes that grow out to the region's edges
|
|
187
197
|
- `select_line`: a single row or column
|
|
188
198
|
- `select_layer_transparency`: a layer's own pixels
|
|
189
199
|
- `grow_selection`, `select_similar`: add similar colour, connected or anywhere
|