@pixerate/editor-react 0.86.0 → 0.88.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/vector/index.cjs +163 -49
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +25 -4
- package/dist/vector/index.d.ts +25 -4
- package/dist/vector/index.js +122 -7
- package/dist/vector/index.js.map +1 -1
- package/package.json +3 -3
package/dist/vector/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { VectorEditorController, VectorEditorState, VectorTool, VectorCommandOptions, VectorEditorOptions, VectorEffectsToolProviderOptions, VectorRenderFilter, VectorRenderGradientAnnotator, VectorPaintDef, VectorRenderMask, VectorRenderNode, VectorRenderText, VectorWidthPointEdit } from '@pixerate/editor/vector';
|
|
1
|
+
import { VectorEditorController, VectorEditorState, VectorTool, VectorCommandOptions, VectorEditorOptions, VectorEffectsToolProviderOptions, VectorGenerationToolProviderOptions, VectorRenderFilter, VectorRenderGradientAnnotator, VectorPaintDef, VectorRenderMask, VectorRenderNode, VectorRenderText, VectorWidthPointEdit, VectorArtModel, VectorArtGenerator } from '@pixerate/editor/vector';
|
|
2
2
|
import { ToolRegistry } from '@pixerate/editor/tools';
|
|
3
3
|
import React__default from 'react';
|
|
4
4
|
import { EffectProvider } from '@pixerate/editor/effects';
|
|
@@ -35,6 +35,12 @@ declare function useVectorCommands(registry: VectorCommandTarget | null | undefi
|
|
|
35
35
|
* `registry` while mounted. They work once an effects provider is registered (see `useEffects`).
|
|
36
36
|
*/
|
|
37
37
|
declare function useVectorEffectsTools(registry: ToolRegistry | null | undefined, controller: VectorEditorController, options?: VectorEffectsToolProviderOptions): void;
|
|
38
|
+
/**
|
|
39
|
+
* Registers the vector editor's generative-prompt tools (`list_vector_art_models`,
|
|
40
|
+
* `generate_vector_art`, `regenerate_vector_art`) for the lifetime of the component. `models` and
|
|
41
|
+
* `generate` are read fresh on every call, so they may change between renders.
|
|
42
|
+
*/
|
|
43
|
+
declare function useVectorGenerationTools(registry: ToolRegistry | null | undefined, controller: VectorEditorController, options: VectorGenerationToolProviderOptions): void;
|
|
38
44
|
|
|
39
45
|
interface VectorCanvasProps {
|
|
40
46
|
controller: VectorEditorController;
|
|
@@ -311,8 +317,9 @@ interface VectorTracePanelProps {
|
|
|
311
317
|
className?: string;
|
|
312
318
|
}
|
|
313
319
|
/**
|
|
314
|
-
* Image Trace: pick an image file and trace it into paths, in one colour (dark areas)
|
|
315
|
-
* path per colour
|
|
320
|
+
* Image Trace and stylise: pick an image file and trace it into paths, in one colour (dark areas)
|
|
321
|
+
* or a stacked path per colour, or stylise it as mosaic tiles, halftone dots, low-poly triangles
|
|
322
|
+
* or engraving lines. The group goes on the artboard at its width. One undo step.
|
|
316
323
|
*/
|
|
317
324
|
declare function VectorTracePanel({ controller, className }: VectorTracePanelProps): React__default.JSX.Element;
|
|
318
325
|
|
|
@@ -360,4 +367,18 @@ interface VectorProviderEffectsPanelProps {
|
|
|
360
367
|
*/
|
|
361
368
|
declare function VectorProviderEffectsPanel({ controller, className }: VectorProviderEffectsPanelProps): React__default.JSX.Element;
|
|
362
369
|
|
|
363
|
-
|
|
370
|
+
interface VectorGeneratePanelProps {
|
|
371
|
+
controller: VectorEditorController;
|
|
372
|
+
/** The host's models (image models are traced or stylised; text models write SVG). */
|
|
373
|
+
models: readonly VectorArtModel[];
|
|
374
|
+
/** The host's generator (sends a planned request to its model). */
|
|
375
|
+
generate: VectorArtGenerator;
|
|
376
|
+
className?: string;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Generative prompts: describe art, pick a model (and, for image models, how the picture becomes
|
|
380
|
+
* vectors) and generate it into the artboard as one editable group. One undo step.
|
|
381
|
+
*/
|
|
382
|
+
declare function VectorGeneratePanel({ controller, models, generate, className }: VectorGeneratePanelProps): React__default.JSX.Element | null;
|
|
383
|
+
|
|
384
|
+
export { type UseVectorEditorResult, VectorAppearancePanel, type VectorAppearancePanelProps, VectorCanvas, type VectorCanvasProps, type VectorCommandTarget, VectorConnectorPanel, type VectorConnectorPanelProps, VectorConstraintsPanel, type VectorConstraintsPanelProps, VectorEditor, type VectorEditorProps, VectorEffectsPanel, type VectorEffectsPanelProps, VectorEnvelopePanel, type VectorEnvelopePanelProps, VectorFilterDefs, VectorFramePanel, type VectorFramePanelProps, VectorGeneratePanel, type VectorGeneratePanelProps, VectorGradientAnnotator, VectorGradientDefs, VectorGradientEditor, type VectorGradientEditorProps, VectorLensPanel, type VectorLensPanelProps, VectorMaskPanel, type VectorMaskPanelProps, VectorMaskedNodes, VectorPagesPanel, type VectorPagesPanelProps, VectorPerspectivePanel, type VectorPerspectivePanelProps, VectorProviderEffectsPanel, type VectorProviderEffectsPanelProps, VectorSceneNodes, VectorShadingPanel, type VectorShadingPanelProps, VectorStylePanel, type VectorStylePanelProps, VectorSymbolsPanel, type VectorSymbolsPanelProps, VectorSymmetryPanel, type VectorSymmetryPanelProps, VectorTextElement, VectorTextPanel, type VectorTextPanelProps, VectorToolbar, type VectorToolbarProps, VectorTracePanel, type VectorTracePanelProps, VectorWidthPointEditor, type VectorWidthPointEditorProps, useVectorCommands, useVectorEditor, useVectorEditorController, useVectorEditorState, useVectorEffectsTools, useVectorGenerationTools };
|
package/dist/vector/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { VectorEditorController, VectorEditorState, VectorTool, VectorCommandOptions, VectorEditorOptions, VectorEffectsToolProviderOptions, VectorRenderFilter, VectorRenderGradientAnnotator, VectorPaintDef, VectorRenderMask, VectorRenderNode, VectorRenderText, VectorWidthPointEdit } from '@pixerate/editor/vector';
|
|
1
|
+
import { VectorEditorController, VectorEditorState, VectorTool, VectorCommandOptions, VectorEditorOptions, VectorEffectsToolProviderOptions, VectorGenerationToolProviderOptions, VectorRenderFilter, VectorRenderGradientAnnotator, VectorPaintDef, VectorRenderMask, VectorRenderNode, VectorRenderText, VectorWidthPointEdit, VectorArtModel, VectorArtGenerator } from '@pixerate/editor/vector';
|
|
2
2
|
import { ToolRegistry } from '@pixerate/editor/tools';
|
|
3
3
|
import React__default from 'react';
|
|
4
4
|
import { EffectProvider } from '@pixerate/editor/effects';
|
|
@@ -35,6 +35,12 @@ declare function useVectorCommands(registry: VectorCommandTarget | null | undefi
|
|
|
35
35
|
* `registry` while mounted. They work once an effects provider is registered (see `useEffects`).
|
|
36
36
|
*/
|
|
37
37
|
declare function useVectorEffectsTools(registry: ToolRegistry | null | undefined, controller: VectorEditorController, options?: VectorEffectsToolProviderOptions): void;
|
|
38
|
+
/**
|
|
39
|
+
* Registers the vector editor's generative-prompt tools (`list_vector_art_models`,
|
|
40
|
+
* `generate_vector_art`, `regenerate_vector_art`) for the lifetime of the component. `models` and
|
|
41
|
+
* `generate` are read fresh on every call, so they may change between renders.
|
|
42
|
+
*/
|
|
43
|
+
declare function useVectorGenerationTools(registry: ToolRegistry | null | undefined, controller: VectorEditorController, options: VectorGenerationToolProviderOptions): void;
|
|
38
44
|
|
|
39
45
|
interface VectorCanvasProps {
|
|
40
46
|
controller: VectorEditorController;
|
|
@@ -311,8 +317,9 @@ interface VectorTracePanelProps {
|
|
|
311
317
|
className?: string;
|
|
312
318
|
}
|
|
313
319
|
/**
|
|
314
|
-
* Image Trace: pick an image file and trace it into paths, in one colour (dark areas)
|
|
315
|
-
* path per colour
|
|
320
|
+
* Image Trace and stylise: pick an image file and trace it into paths, in one colour (dark areas)
|
|
321
|
+
* or a stacked path per colour, or stylise it as mosaic tiles, halftone dots, low-poly triangles
|
|
322
|
+
* or engraving lines. The group goes on the artboard at its width. One undo step.
|
|
316
323
|
*/
|
|
317
324
|
declare function VectorTracePanel({ controller, className }: VectorTracePanelProps): React__default.JSX.Element;
|
|
318
325
|
|
|
@@ -360,4 +367,18 @@ interface VectorProviderEffectsPanelProps {
|
|
|
360
367
|
*/
|
|
361
368
|
declare function VectorProviderEffectsPanel({ controller, className }: VectorProviderEffectsPanelProps): React__default.JSX.Element;
|
|
362
369
|
|
|
363
|
-
|
|
370
|
+
interface VectorGeneratePanelProps {
|
|
371
|
+
controller: VectorEditorController;
|
|
372
|
+
/** The host's models (image models are traced or stylised; text models write SVG). */
|
|
373
|
+
models: readonly VectorArtModel[];
|
|
374
|
+
/** The host's generator (sends a planned request to its model). */
|
|
375
|
+
generate: VectorArtGenerator;
|
|
376
|
+
className?: string;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Generative prompts: describe art, pick a model (and, for image models, how the picture becomes
|
|
380
|
+
* vectors) and generate it into the artboard as one editable group. One undo step.
|
|
381
|
+
*/
|
|
382
|
+
declare function VectorGeneratePanel({ controller, models, generate, className }: VectorGeneratePanelProps): React__default.JSX.Element | null;
|
|
383
|
+
|
|
384
|
+
export { type UseVectorEditorResult, VectorAppearancePanel, type VectorAppearancePanelProps, VectorCanvas, type VectorCanvasProps, type VectorCommandTarget, VectorConnectorPanel, type VectorConnectorPanelProps, VectorConstraintsPanel, type VectorConstraintsPanelProps, VectorEditor, type VectorEditorProps, VectorEffectsPanel, type VectorEffectsPanelProps, VectorEnvelopePanel, type VectorEnvelopePanelProps, VectorFilterDefs, VectorFramePanel, type VectorFramePanelProps, VectorGeneratePanel, type VectorGeneratePanelProps, VectorGradientAnnotator, VectorGradientDefs, VectorGradientEditor, type VectorGradientEditorProps, VectorLensPanel, type VectorLensPanelProps, VectorMaskPanel, type VectorMaskPanelProps, VectorMaskedNodes, VectorPagesPanel, type VectorPagesPanelProps, VectorPerspectivePanel, type VectorPerspectivePanelProps, VectorProviderEffectsPanel, type VectorProviderEffectsPanelProps, VectorSceneNodes, VectorShadingPanel, type VectorShadingPanelProps, VectorStylePanel, type VectorStylePanelProps, VectorSymbolsPanel, type VectorSymbolsPanelProps, VectorSymmetryPanel, type VectorSymmetryPanelProps, VectorTextElement, VectorTextPanel, type VectorTextPanelProps, VectorToolbar, type VectorToolbarProps, VectorTracePanel, type VectorTracePanelProps, VectorWidthPointEditor, type VectorWidthPointEditorProps, useVectorCommands, useVectorEditor, useVectorEditorController, useVectorEditorState, useVectorEffectsTools, useVectorGenerationTools };
|
package/dist/vector/index.js
CHANGED
|
@@ -11,7 +11,8 @@ import { useEffect, useMemo, useRef, useSyncExternalStore } from "react";
|
|
|
11
11
|
import {
|
|
12
12
|
VectorEditorController,
|
|
13
13
|
createVectorCommands,
|
|
14
|
-
createVectorEffectsToolProvider
|
|
14
|
+
createVectorEffectsToolProvider,
|
|
15
|
+
createVectorGenerationToolProvider
|
|
15
16
|
} from "@pixerate/editor/vector";
|
|
16
17
|
function useVectorEditorController(options = {}) {
|
|
17
18
|
const ref = useRef(null);
|
|
@@ -58,6 +59,30 @@ function useVectorEffectsTools(registry, controller, options = {}) {
|
|
|
58
59
|
return registry.register(createVectorEffectsToolProvider(controller, { id, namespace, readOnly }));
|
|
59
60
|
}, [registry, controller, id, namespace, readOnly]);
|
|
60
61
|
}
|
|
62
|
+
function useVectorGenerationTools(registry, controller, options) {
|
|
63
|
+
const latest = useRef(options);
|
|
64
|
+
latest.current = options;
|
|
65
|
+
const { id, namespace } = options;
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (!registry) return;
|
|
68
|
+
const models = () => {
|
|
69
|
+
const m = latest.current.models;
|
|
70
|
+
return typeof m === "function" ? m() : m;
|
|
71
|
+
};
|
|
72
|
+
return registry.register(
|
|
73
|
+
createVectorGenerationToolProvider(controller, {
|
|
74
|
+
id,
|
|
75
|
+
namespace,
|
|
76
|
+
models,
|
|
77
|
+
generate: (request, context) => latest.current.generate(request, context),
|
|
78
|
+
readOnly: () => {
|
|
79
|
+
const r = latest.current.readOnly;
|
|
80
|
+
return (typeof r === "function" ? r() : r) ?? false;
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
);
|
|
84
|
+
}, [registry, controller, id, namespace]);
|
|
85
|
+
}
|
|
61
86
|
|
|
62
87
|
// src/vector/VectorCanvas.tsx
|
|
63
88
|
import React2, { useEffect as useEffect2, useId, useRef as useRef3, useState as useState2 } from "react";
|
|
@@ -252,7 +277,12 @@ var VectorSceneNode = React2.memo(function VectorSceneNode2({ node }) {
|
|
|
252
277
|
if (node.layers)
|
|
253
278
|
return (
|
|
254
279
|
// Fill and stroke stacks: each layer in order, bottom to top.
|
|
255
|
-
/* @__PURE__ */ jsx2("g", { "data-vector-id": node.id, transform: node.transform, opacity: node.opacity < 1 ? node.opacity : void 0, filter: node.filter, style: blendStyle(node.blendMode), children: node.layers.map(
|
|
280
|
+
/* @__PURE__ */ jsx2("g", { "data-vector-id": node.id, transform: node.transform, opacity: node.opacity < 1 ? node.opacity : void 0, filter: node.filter, style: blendStyle(node.blendMode), children: node.layers.map(
|
|
281
|
+
(layer) => layer.kind === "brushstroke" ? (
|
|
282
|
+
// A brushstroke: its rendered brush images over their boxes.
|
|
283
|
+
/* @__PURE__ */ jsx2("g", { "data-vector-layer": `brushstroke-${layer.index}`, opacity: layer.opacity < 1 ? layer.opacity : void 0, style: blendStyle(layer.blendMode), children: (layer.images ?? []).map((im, i) => /* @__PURE__ */ jsx2("image", { href: im.href, x: im.x, y: im.y, width: im.width, height: im.height, preserveAspectRatio: "none" }, i)) }, `${layer.kind}-${layer.index}`)
|
|
284
|
+
) : /* @__PURE__ */ jsx2(VectorPaintPath, { paint: layer, d: node.d, fillRule: node.fillRule, layer: `${layer.kind}-${layer.index}` }, `${layer.kind}-${layer.index}`)
|
|
285
|
+
) })
|
|
256
286
|
);
|
|
257
287
|
return /* @__PURE__ */ jsx2(VectorPaintPath, { paint: node, d: node.d, fillRule: node.fillRule, id: node.id, transform: node.transform, filter: node.filter, blendMode: node.blendMode });
|
|
258
288
|
});
|
|
@@ -611,6 +641,7 @@ function VectorCanvas({
|
|
|
611
641
|
overlay.builder.lines.map((d, i) => /* @__PURE__ */ jsx2("path", { "data-vector-builder-line": "", d, fill: "none", stroke: THEME2.builderErase, strokeWidth: 3, strokeLinecap: "round" }, `l${i}`)),
|
|
612
642
|
overlay.builder.trail && /* @__PURE__ */ jsx2("path", { "data-vector-builder-trail": "", d: overlay.builder.trail, fill: "none", stroke: overlay.builder.mode === "erase" ? THEME2.builderErase : accentColor, strokeWidth: 1 })
|
|
613
643
|
] }),
|
|
644
|
+
overlay.brush && /* @__PURE__ */ jsx2("circle", { "data-vector-brush": "", cx: overlay.brush.x, cy: overlay.brush.y, r: overlay.brush.r, fill: "none", stroke: accentColor, strokeWidth: 1, strokeDasharray: "4 3", pointerEvents: "none" }),
|
|
614
645
|
overlay.toolStroke && /* @__PURE__ */ jsx2(
|
|
615
646
|
"path",
|
|
616
647
|
{
|
|
@@ -793,6 +824,7 @@ function VectorCanvas({
|
|
|
793
824
|
import React10 from "react";
|
|
794
825
|
import {
|
|
795
826
|
VECTOR_TOOLS,
|
|
827
|
+
VECTOR_DISTORT_BRUSH_MODES,
|
|
796
828
|
VECTOR_TOOL_GLYPHS,
|
|
797
829
|
VECTOR_TOOL_SHORTCUTS,
|
|
798
830
|
VECTOR_EDIT_TOGGLES,
|
|
@@ -977,7 +1009,8 @@ import {
|
|
|
977
1009
|
VECTOR_BLEND_MODE_MENU,
|
|
978
1010
|
VECTOR_FILTER_MENU,
|
|
979
1011
|
VECTOR_STROKE_ALIGN_LABELS,
|
|
980
|
-
getVectorAppearancePanel
|
|
1012
|
+
getVectorAppearancePanel,
|
|
1013
|
+
vectorBrushstrokeBrushes
|
|
981
1014
|
} from "@pixerate/editor/vector";
|
|
982
1015
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
983
1016
|
var buttonClass2 = "inline-flex h-7 min-w-7 items-center justify-center rounded-md border border-border bg-background px-1.5 text-xs font-medium text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:opacity-40";
|
|
@@ -994,6 +1027,30 @@ function VectorAppearancePanel({ controller, className }) {
|
|
|
994
1027
|
const update = (l, patch, merge = false) => controller.updatePaintLayer(l.kind, l.index, patch, { ids, merge });
|
|
995
1028
|
const layerRow = (l, count) => {
|
|
996
1029
|
const name = `${l.kind === "fill" ? "Fill" : "Stroke"} ${l.index + 1}`;
|
|
1030
|
+
if (l.brushstroke)
|
|
1031
|
+
return /* @__PURE__ */ jsx4("div", { className: "space-y-1 rounded border border-border p-1", "data-vector-layer": `${l.kind}-${l.index}`, "data-vector-brushstroke": "", children: /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1", children: [
|
|
1032
|
+
/* @__PURE__ */ jsx4("input", { type: "checkbox", "aria-label": `${name} visible`, title: "Show", checked: l.visible, onChange: (e) => update(l, { visible: e.target.checked }) }),
|
|
1033
|
+
/* @__PURE__ */ jsx4("input", { type: "color", "aria-label": `${name} colour`, className: "h-7 w-10 cursor-pointer rounded border border-border bg-background", value: l.color ?? "#000000", onChange: (e) => controller.setBrushstroke(l.index, { color: e.target.value }, { ids, merge: true }), onBlur: end }),
|
|
1034
|
+
/* @__PURE__ */ jsx4("select", { "aria-label": `${name} brush`, className: selectClass2, value: l.brushstroke.brushId, onChange: (e) => controller.setBrushstroke(l.index, { brushId: e.target.value }, { ids }), children: vectorBrushstrokeBrushes().map((b) => /* @__PURE__ */ jsx4("option", { value: b.id, children: b.name }, b.id)) }),
|
|
1035
|
+
/* @__PURE__ */ jsx4(
|
|
1036
|
+
"input",
|
|
1037
|
+
{
|
|
1038
|
+
type: "number",
|
|
1039
|
+
min: 0.5,
|
|
1040
|
+
step: 0.5,
|
|
1041
|
+
"aria-label": `${name} brush size`,
|
|
1042
|
+
title: "Brush size",
|
|
1043
|
+
className: numberClass2,
|
|
1044
|
+
value: l.brushstroke.size,
|
|
1045
|
+
onChange: (e) => {
|
|
1046
|
+
const n = parseFloat(e.target.value);
|
|
1047
|
+
if (Number.isFinite(n) && n > 0) controller.setBrushstroke(l.index, { size: Math.min(500, n) }, { ids, merge: true });
|
|
1048
|
+
},
|
|
1049
|
+
onBlur: end
|
|
1050
|
+
}
|
|
1051
|
+
),
|
|
1052
|
+
/* @__PURE__ */ jsx4("button", { type: "button", className: buttonClass2, title: "Remove", "aria-label": `Remove ${name}`, onClick: () => controller.removePaintLayer("stroke", l.index, { ids }), children: "\xD7" })
|
|
1053
|
+
] }) }, `${l.kind}-${l.index}`);
|
|
997
1054
|
if (l.unknownKind)
|
|
998
1055
|
return /* @__PURE__ */ jsxs4("div", { className: "text-[11px] text-muted-foreground", "data-vector-layer": `${l.kind}-${l.index}`, children: [
|
|
999
1056
|
name,
|
|
@@ -1089,7 +1146,8 @@ function VectorAppearancePanel({ controller, className }) {
|
|
|
1089
1146
|
onClick: () => controller.addPaintLayer(kind, {}, { ids }),
|
|
1090
1147
|
children: "+"
|
|
1091
1148
|
}
|
|
1092
|
-
)
|
|
1149
|
+
),
|
|
1150
|
+
kind === "stroke" && /* @__PURE__ */ jsx4("button", { type: "button", className: buttonClass2, title: "Add a brushstroke (a natural-media brush along the path)", "aria-label": "Add brushstroke", "data-vector-add-brushstroke": "", disabled: !ids.length, onClick: () => controller.addBrushstroke({ brushId: vectorBrushstrokeBrushes()[0].id }, { ids }), children: "\u270E+" })
|
|
1093
1151
|
] }),
|
|
1094
1152
|
[...layers].reverse().map((l) => layerRow(l, layers.length))
|
|
1095
1153
|
] });
|
|
@@ -2028,6 +2086,7 @@ function VectorShadingPanel({ controller, className }) {
|
|
|
2028
2086
|
|
|
2029
2087
|
// src/vector/VectorTracePanel.tsx
|
|
2030
2088
|
import { useRef as useRef4, useState as useState6 } from "react";
|
|
2089
|
+
import { VECTOR_STYLIZE_LABELS, VECTOR_STYLIZE_STYLES } from "@pixerate/editor/vector";
|
|
2031
2090
|
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2032
2091
|
var buttonClass12 = "inline-flex h-7 min-w-7 items-center justify-center rounded-md border border-border bg-background px-1.5 text-xs font-medium text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:opacity-40";
|
|
2033
2092
|
var selectClass9 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
@@ -2054,7 +2113,8 @@ function VectorTracePanel({ controller, className }) {
|
|
|
2054
2113
|
const pixels = await filePixels(file);
|
|
2055
2114
|
const doc = controller.getState().document;
|
|
2056
2115
|
const width = Math.min(doc.width, pixels.width);
|
|
2057
|
-
const
|
|
2116
|
+
const name = file.name.replace(/\.[^.]+$/, "") || void 0;
|
|
2117
|
+
const r = mode === "threshold" || mode === "color" ? controller.traceImage(pixels, { mode, colors, width, name: name ?? "Image Trace" }) : controller.stylizeImage(pixels, mode, { width, ...name ? { name } : {} });
|
|
2058
2118
|
setMessage(r.ok ? null : r.message);
|
|
2059
2119
|
} catch {
|
|
2060
2120
|
setMessage("That file could not be read as an image.");
|
|
@@ -2065,7 +2125,8 @@ function VectorTracePanel({ controller, className }) {
|
|
|
2065
2125
|
/* @__PURE__ */ jsx14("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Trace" }),
|
|
2066
2126
|
/* @__PURE__ */ jsxs14("select", { "aria-label": "Trace mode", className: selectClass9, value: mode, onChange: (e) => setMode(e.target.value), children: [
|
|
2067
2127
|
/* @__PURE__ */ jsx14("option", { value: "threshold", children: "Black & white" }),
|
|
2068
|
-
/* @__PURE__ */ jsx14("option", { value: "color", children: "Colours" })
|
|
2128
|
+
/* @__PURE__ */ jsx14("option", { value: "color", children: "Colours" }),
|
|
2129
|
+
VECTOR_STYLIZE_STYLES.map((s) => /* @__PURE__ */ jsx14("option", { value: s, children: VECTOR_STYLIZE_LABELS[s] }, s))
|
|
2069
2130
|
] }),
|
|
2070
2131
|
mode === "color" && /* @__PURE__ */ jsx14("input", { type: "number", min: 2, max: 32, "aria-label": "Trace colours", title: "Colours", className: numberClass7, value: colors, onChange: (e) => setColors(Math.max(2, Math.min(32, parseInt(e.target.value, 10) || 2))) }),
|
|
2071
2132
|
/* @__PURE__ */ jsx14("button", { type: "button", className: buttonClass12, "data-vector-trace-action": "", title: "Image Trace: pick an image to turn into paths", onClick: () => input.current?.click(), children: "Image\u2026" }),
|
|
@@ -2543,6 +2604,20 @@ function VectorToolbar({
|
|
|
2543
2604
|
}
|
|
2544
2605
|
)
|
|
2545
2606
|
] }),
|
|
2607
|
+
state.tool === "distort" && /* @__PURE__ */ jsxs19("span", { className: "flex flex-wrap items-center gap-1", "data-vector-distort-options": "", children: [
|
|
2608
|
+
/* @__PURE__ */ jsx19("select", { "aria-label": "Distort brush", title: "What the brush does to the outlines it passes over", className: "h-7 rounded border border-border bg-background px-1 text-xs", value: editing.distortMode, onChange: (e) => controller.setEditing({ distortMode: e.target.value }), children: VECTOR_DISTORT_BRUSH_MODES.map((m) => /* @__PURE__ */ jsx19("option", { value: m, children: m[0].toUpperCase() + m.slice(1) }, m)) }),
|
|
2609
|
+
/* @__PURE__ */ jsxs19("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
2610
|
+
"Size",
|
|
2611
|
+
/* @__PURE__ */ jsx19("input", { type: "number", min: 1, step: 1, "aria-label": "Distort brush size", className: "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs", value: editing.distortSize, onChange: (e) => {
|
|
2612
|
+
const n = parseFloat(e.target.value);
|
|
2613
|
+
if (Number.isFinite(n) && n > 0) controller.setEditing({ distortSize: n });
|
|
2614
|
+
} })
|
|
2615
|
+
] }),
|
|
2616
|
+
/* @__PURE__ */ jsxs19("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
2617
|
+
"Strength",
|
|
2618
|
+
/* @__PURE__ */ jsx19("input", { type: "range", min: 0, max: 1, step: 0.05, "aria-label": "Distort brush strength", className: "h-4 w-20 accent-primary", value: editing.distortStrength, onChange: (e) => controller.setEditing({ distortStrength: parseFloat(e.target.value) }) })
|
|
2619
|
+
] })
|
|
2620
|
+
] }),
|
|
2546
2621
|
state.tool === "paintBucket" && /* @__PURE__ */ jsx19(
|
|
2547
2622
|
"button",
|
|
2548
2623
|
{
|
|
@@ -2997,6 +3072,44 @@ function VectorEditor({ controller, tools, showStylePanel = true, height = 520,
|
|
|
2997
3072
|
] })
|
|
2998
3073
|
] });
|
|
2999
3074
|
}
|
|
3075
|
+
|
|
3076
|
+
// src/vector/VectorGeneratePanel.tsx
|
|
3077
|
+
import { useState as useState8 } from "react";
|
|
3078
|
+
import { VECTOR_GENERATED_IMAGE_AS, generateVectorArt, vectorArtModels } from "@pixerate/editor/vector";
|
|
3079
|
+
import { jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
3080
|
+
var buttonClass17 = "inline-flex h-7 min-w-7 items-center justify-center rounded-md border border-border bg-background px-1.5 text-xs font-medium text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:opacity-40";
|
|
3081
|
+
var selectClass15 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
3082
|
+
var AS_LABELS = { color: "Traced in colour", threshold: "Traced in one colour", mosaic: "Mosaic", halftone: "Halftone", lowPoly: "Low poly", hatch: "Engraving" };
|
|
3083
|
+
function VectorGeneratePanel({ controller, models, generate, className }) {
|
|
3084
|
+
const usable = vectorArtModels(models);
|
|
3085
|
+
const [prompt, setPrompt] = useState8("");
|
|
3086
|
+
const [model, setModel] = useState8("");
|
|
3087
|
+
const [as, setAs] = useState8("color");
|
|
3088
|
+
const [busy, setBusy] = useState8(false);
|
|
3089
|
+
const [message, setMessage] = useState8(null);
|
|
3090
|
+
const chosen = usable.find((m) => m.id === model) ?? usable[0];
|
|
3091
|
+
if (!usable.length) return null;
|
|
3092
|
+
const run = async () => {
|
|
3093
|
+
setBusy(true);
|
|
3094
|
+
setMessage(null);
|
|
3095
|
+
const r = await generateVectorArt(controller, { prompt, model: chosen.id, as, idempotencyKey: `${Date.now()}-${Math.random().toString(36).slice(2)}` }, { models, generate });
|
|
3096
|
+
setBusy(false);
|
|
3097
|
+
setMessage(r.ok ? null : r.message ?? "Generation failed.");
|
|
3098
|
+
};
|
|
3099
|
+
return /* @__PURE__ */ jsxs22("div", { className: `space-y-1 ${className ?? ""}`, "data-vector-generate-panel": "", "aria-label": "Generate", children: [
|
|
3100
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-1", children: [
|
|
3101
|
+
/* @__PURE__ */ jsx22("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Generate" }),
|
|
3102
|
+
/* @__PURE__ */ jsx22("select", { "aria-label": "Generation model", className: selectClass15, value: chosen.id, onChange: (e) => setModel(e.target.value), children: usable.map((m) => /* @__PURE__ */ jsx22("option", { value: m.id, children: m.name ?? m.id }, m.id)) }),
|
|
3103
|
+
chosen.media === "image" && /* @__PURE__ */ jsx22("select", { "aria-label": "Image to vectors", className: selectClass15, value: as, onChange: (e) => setAs(e.target.value), children: VECTOR_GENERATED_IMAGE_AS.map((a) => /* @__PURE__ */ jsx22("option", { value: a, children: AS_LABELS[a] }, a)) })
|
|
3104
|
+
] }),
|
|
3105
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-1", children: [
|
|
3106
|
+
/* @__PURE__ */ jsx22("span", { className: "w-16" }),
|
|
3107
|
+
/* @__PURE__ */ jsx22("input", { type: "text", "aria-label": "Prompt", placeholder: "Describe the art\u2026", className: "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1.5 text-xs", value: prompt, onChange: (e) => setPrompt(e.target.value), onKeyDown: (e) => e.key === "Enter" && prompt.trim() && !busy && void run() }),
|
|
3108
|
+
/* @__PURE__ */ jsx22("button", { type: "button", className: buttonClass17, "data-vector-generate-action": "", disabled: !prompt.trim() || busy, onClick: () => void run(), children: busy ? "Generating\u2026" : "Generate" })
|
|
3109
|
+
] }),
|
|
3110
|
+
message && /* @__PURE__ */ jsx22("p", { className: "text-[11px] text-red-600", children: message })
|
|
3111
|
+
] });
|
|
3112
|
+
}
|
|
3000
3113
|
export {
|
|
3001
3114
|
VectorAppearancePanel,
|
|
3002
3115
|
VectorCanvas,
|
|
@@ -3007,6 +3120,7 @@ export {
|
|
|
3007
3120
|
VectorEnvelopePanel,
|
|
3008
3121
|
VectorFilterDefs,
|
|
3009
3122
|
VectorFramePanel,
|
|
3123
|
+
VectorGeneratePanel,
|
|
3010
3124
|
VectorGradientAnnotator,
|
|
3011
3125
|
VectorGradientDefs,
|
|
3012
3126
|
VectorGradientEditor,
|
|
@@ -3030,6 +3144,7 @@ export {
|
|
|
3030
3144
|
useVectorEditor,
|
|
3031
3145
|
useVectorEditorController,
|
|
3032
3146
|
useVectorEditorState,
|
|
3033
|
-
useVectorEffectsTools
|
|
3147
|
+
useVectorEffectsTools,
|
|
3148
|
+
useVectorGenerationTools
|
|
3034
3149
|
};
|
|
3035
3150
|
//# sourceMappingURL=index.js.map
|