@pixerate/editor 0.186.0 → 0.188.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.
@@ -7,7 +7,7 @@ var _chunkZ64NRDEHcjs = require('../chunk-Z64NRDEH.cjs');
7
7
 
8
8
 
9
9
 
10
- var _chunkX2KQQZBTcjs = require('../chunk-X2KQQZBT.cjs');
10
+ var _chunkJYV4R62Mcjs = require('../chunk-JYV4R62M.cjs');
11
11
  require('../chunk-A2IS7EHE.cjs');
12
12
 
13
13
 
@@ -1653,11 +1653,11 @@ function header(state, options) {
1653
1653
  return out;
1654
1654
  }
1655
1655
  function serializePaintDocument(state, options = {}) {
1656
- const { layers, assets } = _chunkX2KQQZBTcjs.serializeLayers.call(void 0, state.layers);
1656
+ const { layers, assets } = _chunkJYV4R62Mcjs.serializeLayers.call(void 0, state.layers);
1657
1657
  return { ...header(state, options), layers, assets };
1658
1658
  }
1659
1659
  async function serializePaintDocumentExternal(state, store, options = {}) {
1660
- const { layers, assets } = await _chunkX2KQQZBTcjs.serializeLayersExternal.call(void 0, state.layers, store);
1660
+ const { layers, assets } = await _chunkJYV4R62Mcjs.serializeLayersExternal.call(void 0, state.layers, store);
1661
1661
  return { ...header(state, options), layers, assets };
1662
1662
  }
1663
1663
  function paintLayersOnly(layers, problems) {
@@ -1694,7 +1694,7 @@ function deserializePaintDocument(raw) {
1694
1694
  const canvas = normalizeCanvas({ width: r.width, height: r.height, dpi: _nullishCoalesce(r.dpi, () => ( void 0)) });
1695
1695
  const paper = _chunkYQ5C5BVKcjs.normalizePaper.call(void 0, _nullishCoalesce(r.paper, () => ( {})));
1696
1696
  const assets = r.assets && typeof r.assets === "object" ? r.assets : {};
1697
- const layers = paintLayersOnly(_chunkX2KQQZBTcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
1697
+ const layers = paintLayersOnly(_chunkJYV4R62Mcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
1698
1698
  const wanted = typeof r.activeLayerId === "string" ? r.activeLayerId : null;
1699
1699
  const activeLayerId = wanted && _chunkHGTDMKNEcjs.findLayer.call(void 0, layers, wanted) ? wanted : _nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.flattenLayers.call(void 0, layers), 'access', _70 => _70.filter, 'call', _71 => _71((l) => l.type === "pixel"), 'access', _72 => _72.pop, 'call', _73 => _73(), 'optionalAccess', _74 => _74.id]), () => ( null));
1700
1700
  const wetEvents = Array.isArray(r.wetEvents) ? r.wetEvents.filter((e) => e && typeof e === "object" && Number.isInteger(e.clock) && typeof e.kind === "string") : [];
@@ -1710,7 +1710,7 @@ async function deserializePaintDocumentAsync(raw, store) {
1710
1710
  if (!raw || typeof raw !== "object") throw new Error("Not a paint document: expected a JSON object.");
1711
1711
  const r = raw;
1712
1712
  const problems = [];
1713
- const assets = await _chunkX2KQQZBTcjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
1713
+ const assets = await _chunkJYV4R62Mcjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
1714
1714
  const loaded = deserializePaintDocument({ ...r, assets });
1715
1715
  return { ...loaded, problems: [...problems, ...loaded.problems] };
1716
1716
  }
@@ -5409,7 +5409,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5409
5409
  return next.type === "group" ? { ...next, children: toStandard(next.children) } : next;
5410
5410
  });
5411
5411
  const layers = toStandard(dried);
5412
- const result = _chunkX2KQQZBTcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
5412
+ const result = _chunkJYV4R62Mcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
5413
5413
  for (const [mode, names] of changed) {
5414
5414
  const label = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _271 => _271.find, 'call', _272 => _272((m) => m.id === mode), 'optionalAccess', _273 => _273.label]), () => ( mode));
5415
5415
  const std = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _274 => _274.find, 'call', _275 => _275((m) => m.id === _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _276 => _276.label]), () => ( _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)));
@@ -7,7 +7,7 @@ import {
7
7
  resolveExternalAssets,
8
8
  serializeLayers,
9
9
  serializeLayersExternal
10
- } from "../chunk-FW7N64XK.js";
10
+ } from "../chunk-IGMNJM2H.js";
11
11
  import "../chunk-3CI7FRMK.js";
12
12
  import {
13
13
  EffectRendererPool
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor",
3
- "version": "0.186.0",
3
+ "version": "0.188.0",
4
4
  "description": "UI-agnostic rich text and media editing core library",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -126,30 +126,9 @@ drawing or editing either.
126
126
  overall strength and `flow` for gradual build-up within the stroke.
127
127
  4. **Limit paint with a selection**, or lock transparency (`set_layer_properties`
128
128
  `locks.transparency`) to paint only where the layer already has pixels.
129
- 5. **Mix paint colours with `mix_colors`** when the user names paints and amounts ("two parts
130
- ultramarine to one part yellow", "a tint of red"). It mixes like pigment, so blue and yellow
131
- make green and white makes a tint, where averaging RGB gives grey or a dull pastel. Pass its
132
- `mixed` hex as the `color` of `paint_stroke` or `fill_pixels`. Give a strong dark paint a
133
- `strength` above 1 when a little of it should tint a lot of white.
134
- 6. **Blend and smear with the Mixer Brush** (`paint_stroke` with `tool: "mixer"`) when the
135
- user wants paint to pick up and drag the colours already on the layer (wet blending, softening
136
- an edge, pulling one colour into another). `mixer.wet` is how much it picks up (0 paints only
137
- the loaded colour), `mixer.mix` how far each dab leans from the loaded colour to the picked-up
138
- one, and `mixer.load` below 1 makes long strokes run dry. Use `mixing: "pigment"` for
139
- painterly results (blue dragged through yellow goes green); keep `rgb` for retouching, where
140
- colours should stay between the two you started with. A brush with `blend: "pigment"` mixes
141
- its one colour into the layer; only the mixer carries picked-up colour along the stroke. A `brush.flow` around 0.3..0.6 keeps
142
- some of the canvas under each dab and blends more naturally than 1. The stroke samples the
143
- target layer only, so paint on the layer that holds the colours to blend.
144
- 7. **Keep the mixer stateless unless you need a carried load.** By default each mixer stroke
145
- loads `color` (or the foreground) and is cleaned afterwards, so every call is independent and
146
- replays the same. To carry dirty paint from stroke to stroke, pass `mixer.loadEachStroke:
147
- false` and `cleanEachStroke: false`, start with `load_mixer_brush`, read the brush with
148
- `get_mixer_brush` when unsure, and reset it with `clean_mixer_brush`.
149
- 8. **Gradient paint** (colour that changes as the stroke goes): `set_paint` with `{ type:
150
- "gradient", stops, map }`, or `paint_stroke` `paint` for one stroke (brush only). `map.by`
151
- `distance` (default 300 px, mirrored) for drag-it-out colour, `pressure`, `direction`,
152
- `across-tip`, `random`; stops may be `"paint"` / `"secondary"` (foreground / background).
129
+ 5. **Mixing paint, the Mixer Brush and gradient paint**: `mix_colors` mixes named paints like
130
+ pigment; `paint_stroke` `tool: "mixer"` picks up and smears the layer's colours; gradient paint
131
+ changes colour along a stroke. Read [references/painting.md](references/painting.md) first.
153
132
 
154
133
  ### Colour management
155
134
 
@@ -401,6 +380,8 @@ in the source frame at the document's bit depth, colour mode and profile. Read
401
380
  | `set_channel_properties` | Rename a channel or change its overlay `color`, `opacity`, `indicates` (`masked` / `selected`) and `visible`. Returns the `channel`. |
402
381
  | `duplicate_channel` | Copy a channel (`name`, default "<name> copy"). Returns the copy. |
403
382
  | `delete_channel` | Delete a channel (undoable). Returns the remaining channels. |
383
+ | `export_mask_image` | Read-only. The selection, a channel (`channelId`) or a layer's painted mask (`layerId`) as a greyscale PNG (white = selected), `invert`, `maxSide` (default 1024). Returns the image and its size. |
384
+ | `load_channel_from_image` | Store a mask image (`image` data URL / URL; `channel`, `threshold`, `invert`, `name`) in a new channel without changing the selection. Returns the `channel`. |
404
385
  | `set_quick_mask` | Quick Mask mode (`enabled`): paint, fill and retouch tools without `layerId` edit the selection (white selects, black deselects); turn it off before painting layers. Returns the mode. |
405
386
 
406
387
  ### Save and open
@@ -0,0 +1,29 @@
1
+ # Painting: mixing paint, the Mixer Brush and gradient paint
2
+
3
+ Read this before `mix_colors`, a `paint_stroke` with `tool: "mixer"`, or gradient paint
4
+ (`set_paint` / `paint_stroke` `paint`).
5
+
6
+ 1. **Mix paint colours with `mix_colors`** when the user names paints and amounts ("two parts
7
+ ultramarine to one part yellow", "a tint of red"). It mixes like pigment, so blue and yellow
8
+ make green and white makes a tint, where averaging RGB gives grey or a dull pastel. Pass its
9
+ `mixed` hex as the `color` of `paint_stroke` or `fill_pixels`. Give a strong dark paint a
10
+ `strength` above 1 when a little of it should tint a lot of white.
11
+ 2. **Blend and smear with the Mixer Brush** (`paint_stroke` with `tool: "mixer"`) when the
12
+ user wants paint to pick up and drag the colours already on the layer (wet blending, softening
13
+ an edge, pulling one colour into another). `mixer.wet` is how much it picks up (0 paints only
14
+ the loaded colour), `mixer.mix` how far each dab leans from the loaded colour to the picked-up
15
+ one, and `mixer.load` below 1 makes long strokes run dry. Use `mixing: "pigment"` for
16
+ painterly results (blue dragged through yellow goes green); keep `rgb` for retouching, where
17
+ colours should stay between the two you started with. A brush with `blend: "pigment"` mixes
18
+ its one colour into the layer; only the mixer carries picked-up colour along the stroke. A `brush.flow` around 0.3..0.6 keeps
19
+ some of the canvas under each dab and blends more naturally than 1. The stroke samples the
20
+ target layer only, so paint on the layer that holds the colours to blend.
21
+ 3. **Keep the mixer stateless unless you need a carried load.** By default each mixer stroke
22
+ loads `color` (or the foreground) and is cleaned afterwards, so every call is independent and
23
+ replays the same. To carry dirty paint from stroke to stroke, pass `mixer.loadEachStroke:
24
+ false` and `cleanEachStroke: false`, start with `load_mixer_brush`, read the brush with
25
+ `get_mixer_brush` when unsure, and reset it with `clean_mixer_brush`.
26
+ 4. **Gradient paint** (colour that changes as the stroke goes): `set_paint` with `{ type:
27
+ "gradient", stops, map }`, or `paint_stroke` `paint` for one stroke (brush only). `map.by`
28
+ `distance` (default 300 px, mirrored) for drag-it-out colour, `pressure`, `direction`,
29
+ `across-tip`, `random`; stops may be `"paint"` / `"secondary"` (foreground / background).
@@ -76,6 +76,10 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
76
76
  6. **Store.** `save_selection` with a clear name before you change a selection that took
77
77
  work, and whenever it will be needed again (a second adjustment, a later refinement). Load
78
78
  it with `load_selection_from_channel`; channels are saved with the document and in PSDs.
79
+ To hand a mask to another tool or service, or to look at it alone, `export_mask_image`
80
+ writes the selection, a channel or a layer mask as a greyscale PNG; a matte that comes
81
+ back goes into a channel with `load_channel_from_image` (or straight to the selection with
82
+ `load_selection_from_image`).
79
83
  7. **Verify.** `render_preview` at 1024 px or more, and `capture_view` on the edge at 2–8×.
80
84
  **Check:** no fringe of the old background colour, no stair-steps, no visible line where an
81
85
  adjustment ends. Fix by loading the mask back (`load_selection_from_mask`), refining, and
@@ -91,7 +95,7 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
91
95
  | 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 |
92
96
  | Tones (shadows, highlights, a luminosity mask) | `select_color_range` with `preset` `shadows` / `midtones` / `highlights` |
93
97
  | Skin for retouching | `select_color_range` `preset: "skinTones"`, then `intersect` with a box around the face |
94
- | An AI matte or saved mask from the host | `load_selection_from_image` (soft: no `threshold`), then `refine_selection` |
98
+ | An AI matte or saved mask from the host | `load_selection_from_image` (soft: no `threshold`), then `refine_selection`; `load_channel_from_image` to keep it for later |
95
99
  | An existing layer mask | `load_selection_from_mask` |
96
100
  | A cutout, shape or text already on its own layer | `select_layer_transparency` (exact, soft where the layer is) |
97
101
  | A dead pixel row or column | `select_line`, then fill or heal it |
@@ -178,6 +182,8 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
178
182
  - `reselect`: undo a deselect
179
183
  - `save_selection`, `load_selection_from_channel`, `list_channels`: keep selections as alpha channels
180
184
  - `set_channel_properties`, `duplicate_channel`, `delete_channel`: manage channels
185
+ - `export_mask_image`: a selection, channel or layer mask as a greyscale PNG
186
+ - `load_channel_from_image`: a mask image into a new channel
181
187
  - `set_quick_mask`: paint the selection
182
188
  - `fill_pixels`, `blur_stroke`: fill or soften the selection in Quick Mask mode
183
189
  - `magic_wand`: similar colour from a seed