@pixerate/editor-react 0.62.0 → 0.63.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.
@@ -181,9 +181,11 @@ interface BrushOptionsBarProps {
181
181
  className?: string;
182
182
  }
183
183
  /**
184
- * The paint tools: Move / Brush / Eraser, the brush's size, hardness, opacity, flow and smoothing,
185
- * pressure toggles, the foreground and background colours (D resets, X swaps) and Edit › Fill /
186
- * Clear on the active layer. Shortcuts are handled by `handlePaintShortcut` in the editor.
184
+ * The paint tools: Move / Brush / Mixer / Eraser, the brush's size, hardness, opacity, flow and
185
+ * smoothing, pressure toggles, the foreground and background colours (D resets, X swaps) and
186
+ * Edit › Fill / Clear on the active layer. With the Mixer Brush: its load (Load brush / Clean
187
+ * brush), Wet / Load / Mix, load and clean each stroke, and the RGB / Pigment mixing toggle.
188
+ * Shortcuts are handled by `handlePaintShortcut` in the editor.
187
189
  */
188
190
  declare const BrushOptionsBar: React__default.FC<BrushOptionsBarProps>;
189
191
 
@@ -181,9 +181,11 @@ interface BrushOptionsBarProps {
181
181
  className?: string;
182
182
  }
183
183
  /**
184
- * The paint tools: Move / Brush / Eraser, the brush's size, hardness, opacity, flow and smoothing,
185
- * pressure toggles, the foreground and background colours (D resets, X swaps) and Edit › Fill /
186
- * Clear on the active layer. Shortcuts are handled by `handlePaintShortcut` in the editor.
184
+ * The paint tools: Move / Brush / Mixer / Eraser, the brush's size, hardness, opacity, flow and
185
+ * smoothing, pressure toggles, the foreground and background colours (D resets, X swaps) and
186
+ * Edit › Fill / Clear on the active layer. With the Mixer Brush: its load (Load brush / Clean
187
+ * brush), Wet / Load / Mix, load and clean each stroke, and the RGB / Pigment mixing toggle.
188
+ * Shortcuts are handled by `handlePaintShortcut` in the editor.
187
189
  */
188
190
  declare const BrushOptionsBar: React__default.FC<BrushOptionsBarProps>;
189
191
 
@@ -10,7 +10,7 @@ import {
10
10
  SelectionOptionsBar,
11
11
  useImageEditor,
12
12
  useImageHistogram
13
- } from "../chunk-OSOGA2OJ.js";
13
+ } from "../chunk-QJSMW4CM.js";
14
14
  export {
15
15
  AdjustmentLayersPanel,
16
16
  BrushOptionsBar,
package/dist/index.cjs CHANGED
@@ -4600,7 +4600,7 @@ var BrushOptionsBar = ({ controller, className }) => {
4600
4600
  (0, import_react39.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
4601
4601
  const [error, setError] = (0, import_react39.useState)(null);
4602
4602
  const state = controller.getState();
4603
- const { brush, foreground, background } = state.paint;
4603
+ const { brush, foreground, background, mixer, mixerLoad } = state.paint;
4604
4604
  const attempt = (fn) => {
4605
4605
  try {
4606
4606
  setError(null);
@@ -4661,6 +4661,62 @@ var BrushOptionsBar = ({ controller, className }) => {
4661
4661
  },
4662
4662
  spec.id
4663
4663
  )),
4664
+ state.activeTool === "mixer" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Mixer Brush", "data-testid": "mixer-options", children: [
4665
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2", children: [
4666
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4667
+ "span",
4668
+ {
4669
+ "aria-label": "Brush load",
4670
+ title: mixerLoad.reservoir ? `Loaded ${(0, import_image_editor7.rgbUnitToHex)(mixerLoad.reservoir)}, ${Math.round(mixerLoad.amount * 100)}% left` : "Unloaded",
4671
+ className: "h-6 w-6 rounded border border-slate-700",
4672
+ style: { background: mixerLoad.reservoir ? (0, import_image_editor7.rgbUnitToHex)(mixerLoad.reservoir) : "transparent" }
4673
+ }
4674
+ ),
4675
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", title: "Fill the reservoir with the foreground colour", className: chip(false), onClick: () => controller.loadMixerBrush(), children: "Load brush" }),
4676
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", title: "Empty the picked-up colour", className: chip(false), onClick: () => controller.cleanMixerBrush(), children: "Clean brush" })
4677
+ ] }),
4678
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Mixing", children: import_image_editor7.MIXER_MIXING_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4679
+ "button",
4680
+ {
4681
+ type: "button",
4682
+ "aria-pressed": mixer.mixing === m.id,
4683
+ title: m.title,
4684
+ className: chip(mixer.mixing === m.id),
4685
+ onClick: () => controller.setPaintOptions({ mixer: { mixing: m.id } }),
4686
+ children: m.label
4687
+ },
4688
+ m.id
4689
+ )) }),
4690
+ import_image_editor7.MIXER_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ControlSlider, { spec, value: mixer[spec.id], onChange: (v) => controller.setPaintOptions({ mixer: { [spec.id]: v } }) }, spec.id)),
4691
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: [
4692
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4693
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4694
+ "input",
4695
+ {
4696
+ type: "checkbox",
4697
+ "aria-label": "Load the brush after each stroke",
4698
+ checked: mixer.loadEachStroke,
4699
+ onChange: (e) => controller.setPaintOptions({ mixer: { loadEachStroke: e.target.checked } }),
4700
+ className: "accent-indigo-500"
4701
+ }
4702
+ ),
4703
+ "Load each stroke"
4704
+ ] }),
4705
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4706
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4707
+ "input",
4708
+ {
4709
+ type: "checkbox",
4710
+ "aria-label": "Clean the brush after each stroke",
4711
+ checked: mixer.cleanEachStroke,
4712
+ onChange: (e) => controller.setPaintOptions({ mixer: { cleanEachStroke: e.target.checked } }),
4713
+ className: "accent-indigo-500"
4714
+ }
4715
+ ),
4716
+ "Clean each stroke"
4717
+ ] })
4718
+ ] })
4719
+ ] }),
4664
4720
  /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
4665
4721
  /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4666
4722
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(