@pixerate/editor-react 0.71.0 → 0.72.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.
@@ -201,6 +201,9 @@ interface BrushOptionsBarProps {
201
201
  * smoothing, pressure toggles, the foreground and background colours (D resets, X swaps) and
202
202
  * Edit › Fill / Clear on the active layer. With the Mixer Brush: its load (Load brush / Clean
203
203
  * brush), Wet / Load / Mix, load and clean each stroke, and the RGB / Pigment mixing toggle.
204
+ * With a retouching tool: the clone source (Alt-click the canvas to set it), Sample, the Spot
205
+ * Healing type, the tone Range, Exposure / Strength and the Aligned / Protect tones / Vibrance
206
+ * toggles that tool uses.
204
207
  * Shortcuts are handled by `handlePaintShortcut` in the editor.
205
208
  */
206
209
  declare const BrushOptionsBar: React__default.FC<BrushOptionsBarProps>;
@@ -201,6 +201,9 @@ interface BrushOptionsBarProps {
201
201
  * smoothing, pressure toggles, the foreground and background colours (D resets, X swaps) and
202
202
  * Edit › Fill / Clear on the active layer. With the Mixer Brush: its load (Load brush / Clean
203
203
  * brush), Wet / Load / Mix, load and clean each stroke, and the RGB / Pigment mixing toggle.
204
+ * With a retouching tool: the clone source (Alt-click the canvas to set it), Sample, the Spot
205
+ * Healing type, the tone Range, Exposure / Strength and the Aligned / Protect tones / Vibrance
206
+ * toggles that tool uses.
204
207
  * Shortcuts are handled by `handlePaintShortcut` in the editor.
205
208
  */
206
209
  declare const BrushOptionsBar: React__default.FC<BrushOptionsBarProps>;
@@ -14,7 +14,7 @@ import {
14
14
  TypeOptionsBar,
15
15
  useImageEditor,
16
16
  useImageHistogram
17
- } from "../chunk-63FQB5BT.js";
17
+ } from "../chunk-YAFNCBDA.js";
18
18
  export {
19
19
  AdjustmentLayersPanel,
20
20
  BrushOptionsBar,
package/dist/index.cjs CHANGED
@@ -4836,7 +4836,8 @@ var BrushOptionsBar = ({ controller, className }) => {
4836
4836
  (0, import_react40.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
4837
4837
  const [error, setError] = (0, import_react40.useState)(null);
4838
4838
  const state = controller.getState();
4839
- const { brush, foreground, background, mixer, mixerLoad } = state.paint;
4839
+ const { brush, foreground, background, mixer, mixerLoad, retouch, cloneSource } = state.paint;
4840
+ const tool = state.activeTool;
4840
4841
  const attempt = (fn) => {
4841
4842
  try {
4842
4843
  setError(null);
@@ -4846,12 +4847,12 @@ var BrushOptionsBar = ({ controller, className }) => {
4846
4847
  }
4847
4848
  };
4848
4849
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "brush-options", children: [
4849
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Paint tools", children: import_image_editor8.PAINT_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4850
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Paint tools", children: import_image_editor8.PAINT_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4850
4851
  "button",
4851
4852
  {
4852
4853
  type: "button",
4853
4854
  "aria-pressed": state.activeTool === t.id,
4854
- title: `${t.label} (${t.shortcut})`,
4855
+ title: t.shortcut ? `${t.label} (${t.shortcut})` : t.label,
4855
4856
  className: chip(state.activeTool === t.id),
4856
4857
  onClick: () => controller.setTool(t.id),
4857
4858
  children: t.label
@@ -4953,6 +4954,41 @@ var BrushOptionsBar = ({ controller, className }) => {
4953
4954
  ] })
4954
4955
  ] })
4955
4956
  ] }),
4957
+ (0, import_image_editor8.isRetouchPaintTool)(tool) && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Retouch options", "data-testid": "retouch-options", children: [
4958
+ (tool === "clone" || tool === "heal") && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2", children: [
4959
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-slate-400", "data-testid": "clone-source", children: (0, import_image_editor8.cloneSourceLabel)(controller) }),
4960
+ cloneSource && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Forget the source point", className: chip(false), onClick: () => controller.setCloneSource(null), children: "Clear source" })
4961
+ ] }),
4962
+ import_image_editor8.RETOUCH_CHOICES.filter((c) => c.tools.includes(tool)).map((choice) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": choice.label, children: [
4963
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-slate-400", children: choice.label }),
4964
+ choice.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4965
+ "button",
4966
+ {
4967
+ type: "button",
4968
+ "aria-pressed": retouch[choice.id] === o.id,
4969
+ title: o.title,
4970
+ className: chip(retouch[choice.id] === o.id),
4971
+ onClick: () => (0, import_image_editor8.setRetouchChoice)(controller, choice.id, o.id),
4972
+ children: o.label
4973
+ },
4974
+ o.id
4975
+ ))
4976
+ ] }, choice.id)),
4977
+ import_image_editor8.RETOUCH_OPTION_CONTROLS.filter((c) => c.tools.includes(tool)).map((spec) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ControlSlider, { spec, value: retouch[spec.id], onChange: (v) => controller.setPaintOptions({ retouch: { [spec.id]: v } }) }, spec.id)),
4978
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: import_image_editor8.RETOUCH_TOGGLES.filter((t) => t.tools.includes(tool)).map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4979
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4980
+ "input",
4981
+ {
4982
+ type: "checkbox",
4983
+ "aria-label": t.label,
4984
+ checked: retouch[t.id],
4985
+ onChange: (e) => controller.setPaintOptions({ retouch: { [t.id]: e.target.checked } }),
4986
+ className: "accent-indigo-500"
4987
+ }
4988
+ ),
4989
+ t.label
4990
+ ] }, t.id)) })
4991
+ ] }),
4956
4992
  /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
4957
4993
  /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4958
4994
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
@@ -5911,7 +5947,7 @@ var ImageEditor = ({
5911
5947
  } catch {
5912
5948
  }
5913
5949
  const [first] = paintSamples(e);
5914
- setPaintError(paintGestureRef.current.down(first));
5950
+ setPaintError(paintGestureRef.current.down({ ...first, altKey: e.altKey }));
5915
5951
  };
5916
5952
  const handlePaintPointerMove = (e) => {
5917
5953
  if (handleTransformPointerMove(e)) return;