@pixerate/editor-react 0.59.0 → 0.60.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/{chunk-SYTV33TW.js → chunk-OSOGA2OJ.js} +90 -18
- package/dist/chunk-OSOGA2OJ.js.map +1 -0
- package/dist/image-editor/index.cjs +77 -8
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +9 -3
- package/dist/image-editor/index.d.ts +9 -3
- package/dist/image-editor/index.js +1 -1
- package/dist/index.cjs +77 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +3 -3
- package/dist/chunk-SYTV33TW.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ImageEditorController, ImageEditorState, ImageEditorTool, CropBox, AspectRatio, ImageAdjustments, AdjustmentKind, AdjustmentLayerInit, AdjustmentLayerUpdate, ImageHistogram, DepthMaskOptions, CreateAnnotationPayload, Annotation, ImagePoint, ExportOptions, SerializedImageEditorState, ImageEditorOptions, InpaintHook, RemoveBackgroundHook, ImageEditorAIHooks, ControlSpec, CurvePoint, AdjustmentLayer, SelectionToolOptions, SelectionMask } from '@pixerate/editor/image-editor';
|
|
1
|
+
import { ImageEditorController, ImageEditorState, ImageEditorTool, CropBox, AspectRatio, ImageAdjustments, AdjustmentKind, AdjustmentLayerInit, AdjustmentLayerUpdate, ImageHistogram, DepthMaskOptions, CreateAnnotationPayload, Annotation, ImagePoint, ExportOptions, SerializedImageEditorState, AIResultOptions, ImageEditorOptions, InpaintHook, RemoveBackgroundHook, ImageEditorAIHooks, ControlSpec, CurvePoint, AdjustmentLayer, SelectionToolOptions, SelectionMask } from '@pixerate/editor/image-editor';
|
|
2
2
|
import React__default from 'react';
|
|
3
3
|
|
|
4
4
|
interface UseImageEditorReturn {
|
|
@@ -56,8 +56,10 @@ interface UseImageEditorReturn {
|
|
|
56
56
|
useCrop?: boolean;
|
|
57
57
|
}) => Promise<string>;
|
|
58
58
|
toSourceDataURL: (options?: Pick<ExportOptions, 'format' | 'quality'>) => Promise<string>;
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
/** In documents with several layers (or `target: 'new-layer'`) the result goes to a new layer. */
|
|
60
|
+
applyInpaintedImage: (newDataUrl: string, options?: AIResultOptions) => Promise<string | void>;
|
|
61
|
+
/** In documents with several layers (or `target: 'new-layer'`) the result's alpha masks the active layer. */
|
|
62
|
+
applyBackgroundRemovedImage: (newDataUrl: string, options?: AIResultOptions) => Promise<string | void>;
|
|
61
63
|
}
|
|
62
64
|
declare function useImageEditor(options?: ImageEditorOptions): UseImageEditorReturn;
|
|
63
65
|
|
|
@@ -160,6 +162,10 @@ interface LayersPanelProps {
|
|
|
160
162
|
controller: ImageEditorController;
|
|
161
163
|
/** Thumbnail size in px (default 32). */
|
|
162
164
|
thumbnailSize?: number;
|
|
165
|
+
/** Show Open PSD / Export PSD (default true). */
|
|
166
|
+
psd?: boolean;
|
|
167
|
+
/** Base name of exported PSD files (default `image`). */
|
|
168
|
+
psdFileName?: string;
|
|
163
169
|
className?: string;
|
|
164
170
|
}
|
|
165
171
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ImageEditorController, ImageEditorState, ImageEditorTool, CropBox, AspectRatio, ImageAdjustments, AdjustmentKind, AdjustmentLayerInit, AdjustmentLayerUpdate, ImageHistogram, DepthMaskOptions, CreateAnnotationPayload, Annotation, ImagePoint, ExportOptions, SerializedImageEditorState, ImageEditorOptions, InpaintHook, RemoveBackgroundHook, ImageEditorAIHooks, ControlSpec, CurvePoint, AdjustmentLayer, SelectionToolOptions, SelectionMask } from '@pixerate/editor/image-editor';
|
|
1
|
+
import { ImageEditorController, ImageEditorState, ImageEditorTool, CropBox, AspectRatio, ImageAdjustments, AdjustmentKind, AdjustmentLayerInit, AdjustmentLayerUpdate, ImageHistogram, DepthMaskOptions, CreateAnnotationPayload, Annotation, ImagePoint, ExportOptions, SerializedImageEditorState, AIResultOptions, ImageEditorOptions, InpaintHook, RemoveBackgroundHook, ImageEditorAIHooks, ControlSpec, CurvePoint, AdjustmentLayer, SelectionToolOptions, SelectionMask } from '@pixerate/editor/image-editor';
|
|
2
2
|
import React__default from 'react';
|
|
3
3
|
|
|
4
4
|
interface UseImageEditorReturn {
|
|
@@ -56,8 +56,10 @@ interface UseImageEditorReturn {
|
|
|
56
56
|
useCrop?: boolean;
|
|
57
57
|
}) => Promise<string>;
|
|
58
58
|
toSourceDataURL: (options?: Pick<ExportOptions, 'format' | 'quality'>) => Promise<string>;
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
/** In documents with several layers (or `target: 'new-layer'`) the result goes to a new layer. */
|
|
60
|
+
applyInpaintedImage: (newDataUrl: string, options?: AIResultOptions) => Promise<string | void>;
|
|
61
|
+
/** In documents with several layers (or `target: 'new-layer'`) the result's alpha masks the active layer. */
|
|
62
|
+
applyBackgroundRemovedImage: (newDataUrl: string, options?: AIResultOptions) => Promise<string | void>;
|
|
61
63
|
}
|
|
62
64
|
declare function useImageEditor(options?: ImageEditorOptions): UseImageEditorReturn;
|
|
63
65
|
|
|
@@ -160,6 +162,10 @@ interface LayersPanelProps {
|
|
|
160
162
|
controller: ImageEditorController;
|
|
161
163
|
/** Thumbnail size in px (default 32). */
|
|
162
164
|
thumbnailSize?: number;
|
|
165
|
+
/** Show Open PSD / Export PSD (default true). */
|
|
166
|
+
psd?: boolean;
|
|
167
|
+
/** Base name of exported PSD files (default `image`). */
|
|
168
|
+
psdFileName?: string;
|
|
163
169
|
className?: string;
|
|
164
170
|
}
|
|
165
171
|
/**
|
package/dist/index.cjs
CHANGED
|
@@ -3720,11 +3720,11 @@ function useImageEditor(options = {}) {
|
|
|
3720
3720
|
[controller]
|
|
3721
3721
|
);
|
|
3722
3722
|
const applyInpaintedImage = (0, import_react34.useCallback)(
|
|
3723
|
-
(newDataUrl) => controller.applyInpaintedImage(newDataUrl),
|
|
3723
|
+
(newDataUrl, options2) => controller.applyInpaintedImage(newDataUrl, options2),
|
|
3724
3724
|
[controller]
|
|
3725
3725
|
);
|
|
3726
3726
|
const applyBackgroundRemovedImage = (0, import_react34.useCallback)(
|
|
3727
|
-
(newDataUrl) => controller.applyBackgroundRemovedImage(newDataUrl),
|
|
3727
|
+
(newDataUrl, options2) => controller.applyBackgroundRemovedImage(newDataUrl, options2),
|
|
3728
3728
|
[controller]
|
|
3729
3729
|
);
|
|
3730
3730
|
return (0, import_react34.useMemo)(
|
|
@@ -4253,13 +4253,23 @@ var Thumbnail = ({
|
|
|
4253
4253
|
}
|
|
4254
4254
|
);
|
|
4255
4255
|
};
|
|
4256
|
-
var LayersPanel = ({ controller, thumbnailSize = 32, className }) => {
|
|
4256
|
+
var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "image", className }) => {
|
|
4257
4257
|
const [, setTick] = (0, import_react38.useState)(0);
|
|
4258
4258
|
(0, import_react38.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
4259
4259
|
const [error, setError] = (0, import_react38.useState)(null);
|
|
4260
4260
|
const [renaming, setRenaming] = (0, import_react38.useState)(null);
|
|
4261
4261
|
const [menu, setMenu] = (0, import_react38.useState)(null);
|
|
4262
4262
|
const [drag, setDrag] = (0, import_react38.useState)(null);
|
|
4263
|
+
const [psdNotes, setPsdNotes] = (0, import_react38.useState)([]);
|
|
4264
|
+
const fileInput = (0, import_react38.useRef)(null);
|
|
4265
|
+
const psdTask = async (fn) => {
|
|
4266
|
+
try {
|
|
4267
|
+
setError(null);
|
|
4268
|
+
setPsdNotes(await fn());
|
|
4269
|
+
} catch (err) {
|
|
4270
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4271
|
+
}
|
|
4272
|
+
};
|
|
4263
4273
|
const commitNext = (0, import_react38.useRef)(true);
|
|
4264
4274
|
const state = controller.getState();
|
|
4265
4275
|
const rows = (0, import_image_editor6.layerPanelRows)(state.layers, state.activeLayerId);
|
|
@@ -4319,7 +4329,31 @@ var LayersPanel = ({ controller, thumbnailSize = 32, className }) => {
|
|
|
4319
4329
|
},
|
|
4320
4330
|
children: "\u22EF"
|
|
4321
4331
|
}
|
|
4322
|
-
)
|
|
4332
|
+
),
|
|
4333
|
+
psd && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
4334
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, onClick: () => fileInput.current?.click(), children: "Open PSD\u2026" }),
|
|
4335
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, onClick: () => psdTask(async () => (await (0, import_image_editor6.downloadPsd)(controller, psdFileName)).warnings), children: "Export PSD" }),
|
|
4336
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4337
|
+
"input",
|
|
4338
|
+
{
|
|
4339
|
+
ref: fileInput,
|
|
4340
|
+
type: "file",
|
|
4341
|
+
accept: import_image_editor6.PSD_FILE_ACCEPT,
|
|
4342
|
+
className: "hidden",
|
|
4343
|
+
"data-testid": "psd-file-input",
|
|
4344
|
+
"aria-label": "Open a PSD file",
|
|
4345
|
+
onChange: (e) => {
|
|
4346
|
+
const file = e.currentTarget.files?.[0];
|
|
4347
|
+
e.currentTarget.value = "";
|
|
4348
|
+
if (file) psdTask(() => (0, import_image_editor6.openPsdFile)(controller, file));
|
|
4349
|
+
}
|
|
4350
|
+
}
|
|
4351
|
+
)
|
|
4352
|
+
] })
|
|
4353
|
+
] }),
|
|
4354
|
+
psdNotes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("ul", { className: "rounded bg-amber-900/30 text-amber-200 px-2 py-1 space-y-0.5", "data-testid": "psd-warnings", "aria-label": "PSD warnings", children: [
|
|
4355
|
+
psdNotes.map((n) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("li", { children: n }, n)),
|
|
4356
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: "underline", onClick: () => setPsdNotes([]), children: "Dismiss" }) })
|
|
4323
4357
|
] }),
|
|
4324
4358
|
active && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1 items-center", "data-testid": "layer-properties", children: [
|
|
4325
4359
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
|
|
@@ -4717,6 +4751,22 @@ var SelectionOptionsBar = ({
|
|
|
4717
4751
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
4718
4752
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
|
|
4719
4753
|
"Sample adjusted image"
|
|
4754
|
+
] }),
|
|
4755
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
4756
|
+
"Sample",
|
|
4757
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
4758
|
+
"select",
|
|
4759
|
+
{
|
|
4760
|
+
"aria-label": "Sample from",
|
|
4761
|
+
value: options.sample ?? "composite",
|
|
4762
|
+
onChange: (e) => set({ sample: e.target.value }),
|
|
4763
|
+
className: "bg-slate-800 border border-slate-700 rounded px-1 py-0.5",
|
|
4764
|
+
children: [
|
|
4765
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "composite", children: "All layers" }),
|
|
4766
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "active-layer", children: "Active layer" })
|
|
4767
|
+
]
|
|
4768
|
+
}
|
|
4769
|
+
)
|
|
4720
4770
|
] })
|
|
4721
4771
|
] }),
|
|
4722
4772
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
@@ -4947,6 +4997,8 @@ var ImageEditor = ({
|
|
|
4947
4997
|
const [isInpainting, setIsInpainting] = (0, import_react42.useState)(false);
|
|
4948
4998
|
const [aiError, setAiError] = (0, import_react42.useState)(null);
|
|
4949
4999
|
const [aiSuccess, setAiSuccess] = (0, import_react42.useState)(null);
|
|
5000
|
+
const [aiTarget, setAiTarget] = (0, import_react42.useState)("auto");
|
|
5001
|
+
const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
|
|
4950
5002
|
const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
|
|
4951
5003
|
const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
|
|
4952
5004
|
const handleRemoveBackground = async () => {
|
|
@@ -4958,10 +5010,10 @@ var ImageEditor = ({
|
|
|
4958
5010
|
setAiSuccess(null);
|
|
4959
5011
|
setIsRemovingBg(true);
|
|
4960
5012
|
try {
|
|
4961
|
-
const imageDataUrl = await
|
|
5013
|
+
const imageDataUrl = await controller.toAIInputDataURL(aiOptions);
|
|
4962
5014
|
const result = await effectiveOnRemoveBg({ imageDataUrl });
|
|
4963
5015
|
if (typeof result === "string") {
|
|
4964
|
-
await editor.applyBackgroundRemovedImage(result);
|
|
5016
|
+
await editor.applyBackgroundRemovedImage(result, aiOptions);
|
|
4965
5017
|
setAiSuccess("Background removed successfully!");
|
|
4966
5018
|
} else {
|
|
4967
5019
|
setAiSuccess("Background removal complete.");
|
|
@@ -4985,7 +5037,7 @@ var ImageEditor = ({
|
|
|
4985
5037
|
setAiSuccess(null);
|
|
4986
5038
|
setIsInpainting(true);
|
|
4987
5039
|
try {
|
|
4988
|
-
const imageDataUrl = await
|
|
5040
|
+
const imageDataUrl = await controller.toAIInputDataURL(aiOptions);
|
|
4989
5041
|
const maskDataUrl = await editor.toMaskDataURL({
|
|
4990
5042
|
useAnnotations: inpaintMaskMode === "annotations",
|
|
4991
5043
|
useCrop: inpaintMaskMode === "crop"
|
|
@@ -4997,7 +5049,7 @@ var ImageEditor = ({
|
|
|
4997
5049
|
cropBox: inpaintMaskMode === "crop" ? editor.state.crop : null
|
|
4998
5050
|
});
|
|
4999
5051
|
if (typeof result === "string") {
|
|
5000
|
-
await editor.applyInpaintedImage(result);
|
|
5052
|
+
await editor.applyInpaintedImage(result, aiOptions);
|
|
5001
5053
|
setAiSuccess("Inpainting applied successfully!");
|
|
5002
5054
|
} else {
|
|
5003
5055
|
setAiSuccess("Inpainting complete.");
|
|
@@ -6130,6 +6182,23 @@ var ImageEditor = ({
|
|
|
6130
6182
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
|
|
6131
6183
|
] }),
|
|
6132
6184
|
activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
6185
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
|
|
6186
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Results go to" }),
|
|
6187
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
6188
|
+
"select",
|
|
6189
|
+
{
|
|
6190
|
+
"aria-label": "AI result target",
|
|
6191
|
+
value: aiTarget,
|
|
6192
|
+
onChange: (e) => setAiTarget(e.target.value),
|
|
6193
|
+
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
6194
|
+
children: [
|
|
6195
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
|
|
6196
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
|
|
6197
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: "replace", children: "Replace image" })
|
|
6198
|
+
]
|
|
6199
|
+
}
|
|
6200
|
+
)
|
|
6201
|
+
] }),
|
|
6133
6202
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
6134
6203
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
6135
6204
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
|