@pixerate/editor-react 0.58.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-ZU54BMDC.js → chunk-OSOGA2OJ.js} +888 -260
- package/dist/chunk-OSOGA2OJ.js.map +1 -0
- package/dist/image-editor/index.cjs +897 -281
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +35 -4
- package/dist/image-editor/index.d.ts +35 -4
- package/dist/image-editor/index.js +5 -1
- package/dist/index.cjs +1326 -710
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-ZU54BMDC.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -32,6 +32,7 @@ var src_exports = {};
|
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
AdjustmentLayersPanel: () => AdjustmentLayersPanel,
|
|
34
34
|
AssetMentionChips: () => AssetMentionChips,
|
|
35
|
+
BrushOptionsBar: () => BrushOptionsBar,
|
|
35
36
|
BubbleMenu: () => BubbleMenu,
|
|
36
37
|
ChartNodeView: () => ChartNodeView,
|
|
37
38
|
CommandPalette: () => CommandPalette,
|
|
@@ -52,6 +53,7 @@ __export(src_exports, {
|
|
|
52
53
|
ImageEditor: () => ImageEditor,
|
|
53
54
|
InsertTableGrid: () => InsertTableGrid,
|
|
54
55
|
JobProgress: () => JobProgress,
|
|
56
|
+
LayersPanel: () => LayersPanel,
|
|
55
57
|
MergePreview: () => MergePreview,
|
|
56
58
|
NameManager: () => NameManager,
|
|
57
59
|
OutlinePanel: () => OutlinePanel,
|
|
@@ -3718,11 +3720,11 @@ function useImageEditor(options = {}) {
|
|
|
3718
3720
|
[controller]
|
|
3719
3721
|
);
|
|
3720
3722
|
const applyInpaintedImage = (0, import_react34.useCallback)(
|
|
3721
|
-
(newDataUrl) => controller.applyInpaintedImage(newDataUrl),
|
|
3723
|
+
(newDataUrl, options2) => controller.applyInpaintedImage(newDataUrl, options2),
|
|
3722
3724
|
[controller]
|
|
3723
3725
|
);
|
|
3724
3726
|
const applyBackgroundRemovedImage = (0, import_react34.useCallback)(
|
|
3725
|
-
(newDataUrl) => controller.applyBackgroundRemovedImage(newDataUrl),
|
|
3727
|
+
(newDataUrl, options2) => controller.applyBackgroundRemovedImage(newDataUrl, options2),
|
|
3726
3728
|
[controller]
|
|
3727
3729
|
);
|
|
3728
3730
|
return (0, import_react34.useMemo)(
|
|
@@ -3781,8 +3783,8 @@ function useImageEditor(options = {}) {
|
|
|
3781
3783
|
}
|
|
3782
3784
|
|
|
3783
3785
|
// src/image-editor/ImageEditor.tsx
|
|
3784
|
-
var
|
|
3785
|
-
var
|
|
3786
|
+
var import_react42 = __toESM(require("react"), 1);
|
|
3787
|
+
var import_image_editor10 = require("@pixerate/editor/image-editor");
|
|
3786
3788
|
|
|
3787
3789
|
// src/image-editor/ControlSlider.tsx
|
|
3788
3790
|
var import_image_editor2 = require("@pixerate/editor/image-editor");
|
|
@@ -4213,10 +4215,492 @@ var AdjustmentLayersPanel = ({ controller, layers: layersProp, histogram }) => {
|
|
|
4213
4215
|
] });
|
|
4214
4216
|
};
|
|
4215
4217
|
|
|
4216
|
-
// src/image-editor/
|
|
4218
|
+
// src/image-editor/LayersPanel.tsx
|
|
4217
4219
|
var import_react38 = require("react");
|
|
4218
4220
|
var import_image_editor6 = require("@pixerate/editor/image-editor");
|
|
4219
4221
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
4222
|
+
var iconButton = "px-1.5 py-0.5 rounded text-[10px] bg-slate-800 text-slate-300 hover:text-white disabled:opacity-40";
|
|
4223
|
+
var rowClass = (active) => `flex items-center gap-1.5 px-1.5 py-1 rounded cursor-pointer select-none ${active ? "bg-indigo-600/30 ring-1 ring-indigo-500" : "hover:bg-slate-800"}`;
|
|
4224
|
+
var Thumbnail = ({
|
|
4225
|
+
pixels,
|
|
4226
|
+
size,
|
|
4227
|
+
label,
|
|
4228
|
+
onClick,
|
|
4229
|
+
selected,
|
|
4230
|
+
testId
|
|
4231
|
+
}) => {
|
|
4232
|
+
const ref = (0, import_react38.useRef)(null);
|
|
4233
|
+
(0, import_react38.useEffect)(() => {
|
|
4234
|
+
const canvas = ref.current;
|
|
4235
|
+
const ctx = canvas?.getContext("2d");
|
|
4236
|
+
if (!canvas || !ctx || !pixels || typeof ctx.createImageData !== "function") return;
|
|
4237
|
+
canvas.width = pixels.width;
|
|
4238
|
+
canvas.height = pixels.height;
|
|
4239
|
+
const img = ctx.createImageData(pixels.width, pixels.height);
|
|
4240
|
+
img.data.set(pixels.data);
|
|
4241
|
+
ctx.putImageData(img, 0, 0);
|
|
4242
|
+
}, [pixels]);
|
|
4243
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4244
|
+
"canvas",
|
|
4245
|
+
{
|
|
4246
|
+
ref,
|
|
4247
|
+
role: onClick ? "button" : "img",
|
|
4248
|
+
"aria-label": label,
|
|
4249
|
+
"data-testid": testId,
|
|
4250
|
+
onClick,
|
|
4251
|
+
style: { width: size, height: size },
|
|
4252
|
+
className: `shrink-0 rounded bg-[repeating-conic-gradient(#334155_0%_25%,#1e293b_0%_50%)] [background-size:8px_8px] object-contain ${selected ? "ring-2 ring-white" : "ring-1 ring-slate-700"}`
|
|
4253
|
+
}
|
|
4254
|
+
);
|
|
4255
|
+
};
|
|
4256
|
+
var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "image", className }) => {
|
|
4257
|
+
const [, setTick] = (0, import_react38.useState)(0);
|
|
4258
|
+
(0, import_react38.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
4259
|
+
const [error, setError] = (0, import_react38.useState)(null);
|
|
4260
|
+
const [renaming, setRenaming] = (0, import_react38.useState)(null);
|
|
4261
|
+
const [menu, setMenu] = (0, import_react38.useState)(null);
|
|
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
|
+
};
|
|
4273
|
+
const commitNext = (0, import_react38.useRef)(true);
|
|
4274
|
+
const state = controller.getState();
|
|
4275
|
+
const rows = (0, import_image_editor6.layerPanelRows)(state.layers, state.activeLayerId);
|
|
4276
|
+
const active = controller.getActiveLayer();
|
|
4277
|
+
const attempt = (fn) => {
|
|
4278
|
+
try {
|
|
4279
|
+
setError(null);
|
|
4280
|
+
fn();
|
|
4281
|
+
} catch (err) {
|
|
4282
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4283
|
+
}
|
|
4284
|
+
};
|
|
4285
|
+
const run = async (action) => {
|
|
4286
|
+
setMenu(null);
|
|
4287
|
+
setError(await (0, import_image_editor6.runLayerMenuAction)(controller, action));
|
|
4288
|
+
};
|
|
4289
|
+
const prop = (key, value) => attempt(() => {
|
|
4290
|
+
controller.setLayerProperties(active.id, { [key]: value }, commitNext.current);
|
|
4291
|
+
commitNext.current = false;
|
|
4292
|
+
});
|
|
4293
|
+
const sliderEvents = {
|
|
4294
|
+
onPointerDown: () => commitNext.current = true,
|
|
4295
|
+
onPointerUp: () => commitNext.current = true,
|
|
4296
|
+
onKeyDown: () => commitNext.current = true
|
|
4297
|
+
};
|
|
4298
|
+
const onDrop = (e, row) => {
|
|
4299
|
+
e.preventDefault();
|
|
4300
|
+
const id = e.dataTransfer.getData("text/x-pixerate-layer") || drag;
|
|
4301
|
+
setDrag(null);
|
|
4302
|
+
if (!id) return;
|
|
4303
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
4304
|
+
const fraction = rect.height ? (e.clientY - rect.top) / rect.height : 0.5;
|
|
4305
|
+
const placement = (0, import_image_editor6.dropPlacement)(state.layers, id, row.layer.id, (0, import_image_editor6.dropZone)(fraction, row.layer.type === "group"));
|
|
4306
|
+
if (placement) attempt(() => controller.moveLayer(id, placement));
|
|
4307
|
+
};
|
|
4308
|
+
const thumb = (layer) => layer.type === "pixel" ? controller.getLayerThumbnail(layer.id, { maxSide: 64 }) : null;
|
|
4309
|
+
const maskThumb = (layer) => layer.mask && !layer.mask.source ? controller.getLayerThumbnail(layer.id, { maxSide: 64, mask: true }) : null;
|
|
4310
|
+
const locked = (layer) => Boolean(layer.locks?.all || layer.locks?.pixels || layer.locks?.position || layer.locks?.transparency);
|
|
4311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "layers-panel", onClick: () => menu && setMenu(null), children: [
|
|
4312
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "toolbar", "aria-label": "Layer actions", children: [
|
|
4313
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, onClick: () => run("new-layer"), children: "New Layer" }),
|
|
4314
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, onClick: () => run("new-group"), children: "New Group" }),
|
|
4315
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("duplicate"), children: "Duplicate" }),
|
|
4316
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("add-mask"), children: "Add Mask" }),
|
|
4317
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("delete"), children: "Delete" }),
|
|
4318
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4319
|
+
"button",
|
|
4320
|
+
{
|
|
4321
|
+
type: "button",
|
|
4322
|
+
className: iconButton,
|
|
4323
|
+
"aria-label": "Layer menu",
|
|
4324
|
+
"aria-haspopup": "menu",
|
|
4325
|
+
onClick: (e) => {
|
|
4326
|
+
e.stopPropagation();
|
|
4327
|
+
const r = e.currentTarget.getBoundingClientRect();
|
|
4328
|
+
setMenu(menu ? null : { x: r.left, y: r.bottom });
|
|
4329
|
+
},
|
|
4330
|
+
children: "\u22EF"
|
|
4331
|
+
}
|
|
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" }) })
|
|
4357
|
+
] }),
|
|
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: [
|
|
4359
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
|
|
4360
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-slate-400", children: [
|
|
4361
|
+
"Opacity ",
|
|
4362
|
+
Math.round(active.opacity * 100),
|
|
4363
|
+
"%"
|
|
4364
|
+
] }),
|
|
4365
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4366
|
+
"input",
|
|
4367
|
+
{
|
|
4368
|
+
type: "range",
|
|
4369
|
+
min: 0,
|
|
4370
|
+
max: 100,
|
|
4371
|
+
"aria-label": "Layer opacity",
|
|
4372
|
+
value: Math.round(active.opacity * 100),
|
|
4373
|
+
...sliderEvents,
|
|
4374
|
+
onChange: (e) => prop("opacity", Number(e.target.value) / 100),
|
|
4375
|
+
className: "accent-indigo-500"
|
|
4376
|
+
}
|
|
4377
|
+
)
|
|
4378
|
+
] }),
|
|
4379
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
|
|
4380
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-slate-400", children: [
|
|
4381
|
+
"Fill ",
|
|
4382
|
+
Math.round(((active.type === "pixel" ? active.fillOpacity : void 0) ?? 1) * 100),
|
|
4383
|
+
"%"
|
|
4384
|
+
] }),
|
|
4385
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4386
|
+
"input",
|
|
4387
|
+
{
|
|
4388
|
+
type: "range",
|
|
4389
|
+
min: 0,
|
|
4390
|
+
max: 100,
|
|
4391
|
+
"aria-label": "Layer fill",
|
|
4392
|
+
disabled: active.type !== "pixel",
|
|
4393
|
+
value: Math.round(((active.type === "pixel" ? active.fillOpacity : void 0) ?? 1) * 100),
|
|
4394
|
+
...sliderEvents,
|
|
4395
|
+
onChange: (e) => prop("fillOpacity", Number(e.target.value) / 100),
|
|
4396
|
+
className: "accent-indigo-500 disabled:opacity-40"
|
|
4397
|
+
}
|
|
4398
|
+
)
|
|
4399
|
+
] }),
|
|
4400
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4401
|
+
"select",
|
|
4402
|
+
{
|
|
4403
|
+
"aria-label": "Layer blend mode",
|
|
4404
|
+
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
4405
|
+
value: active.blend,
|
|
4406
|
+
onChange: (e) => attempt(() => controller.setLayerProperties(active.id, { blend: e.target.value })),
|
|
4407
|
+
children: [
|
|
4408
|
+
active.type === "group" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: "pass-through", children: "Pass Through" }),
|
|
4409
|
+
import_image_editor6.BLEND_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: m.id, children: m.label }, m.id))
|
|
4410
|
+
]
|
|
4411
|
+
}
|
|
4412
|
+
),
|
|
4413
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
4414
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4415
|
+
"input",
|
|
4416
|
+
{
|
|
4417
|
+
type: "checkbox",
|
|
4418
|
+
"aria-label": "Clip to layer below",
|
|
4419
|
+
checked: Boolean(active.clipped),
|
|
4420
|
+
onChange: (e) => attempt(() => controller.setLayerProperties(active.id, { clipped: e.target.checked })),
|
|
4421
|
+
className: "accent-indigo-500"
|
|
4422
|
+
}
|
|
4423
|
+
),
|
|
4424
|
+
"Clip to below"
|
|
4425
|
+
] }),
|
|
4426
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "col-span-2 flex flex-wrap gap-2 text-slate-400", role: "group", "aria-label": "Layer locks", children: ["pixels", "transparency", "position", "all"].map((k) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
4427
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4428
|
+
"input",
|
|
4429
|
+
{
|
|
4430
|
+
type: "checkbox",
|
|
4431
|
+
"aria-label": `Lock ${k}`,
|
|
4432
|
+
checked: Boolean(active.locks?.[k]),
|
|
4433
|
+
onChange: (e) => attempt(() => controller.setLayerProperties(active.id, { locks: { ...active.locks, [k]: e.target.checked } })),
|
|
4434
|
+
className: "accent-indigo-500"
|
|
4435
|
+
}
|
|
4436
|
+
),
|
|
4437
|
+
k
|
|
4438
|
+
] }, k)) })
|
|
4439
|
+
] }),
|
|
4440
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("ul", { className: "flex flex-col gap-0.5", role: "tree", "aria-label": "Layers", children: rows.map((row) => {
|
|
4441
|
+
const { layer } = row;
|
|
4442
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4443
|
+
"li",
|
|
4444
|
+
{
|
|
4445
|
+
role: "treeitem",
|
|
4446
|
+
"aria-selected": row.active,
|
|
4447
|
+
"aria-level": row.depth + 1,
|
|
4448
|
+
"data-layer-id": layer.id,
|
|
4449
|
+
draggable: !layer.locks?.all,
|
|
4450
|
+
onDragStart: (e) => {
|
|
4451
|
+
e.dataTransfer.setData("text/x-pixerate-layer", layer.id);
|
|
4452
|
+
setDrag(layer.id);
|
|
4453
|
+
},
|
|
4454
|
+
onDragOver: (e) => e.preventDefault(),
|
|
4455
|
+
onDrop: (e) => onDrop(e, row),
|
|
4456
|
+
tabIndex: 0,
|
|
4457
|
+
onClick: () => attempt(() => controller.setActiveLayer(layer.id, "pixels")),
|
|
4458
|
+
onKeyDown: (e) => {
|
|
4459
|
+
if (e.target === e.currentTarget && (e.key === "Enter" || e.key === " ")) {
|
|
4460
|
+
e.preventDefault();
|
|
4461
|
+
attempt(() => controller.setActiveLayer(layer.id, "pixels"));
|
|
4462
|
+
}
|
|
4463
|
+
},
|
|
4464
|
+
onContextMenu: (e) => {
|
|
4465
|
+
e.preventDefault();
|
|
4466
|
+
controller.setActiveLayer(layer.id, state.activeLayerId === layer.id ? state.activeTarget : "pixels");
|
|
4467
|
+
setMenu({ x: e.clientX, y: e.clientY });
|
|
4468
|
+
},
|
|
4469
|
+
className: rowClass(row.active),
|
|
4470
|
+
style: { paddingLeft: 6 + row.depth * 14 },
|
|
4471
|
+
children: [
|
|
4472
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4473
|
+
"button",
|
|
4474
|
+
{
|
|
4475
|
+
type: "button",
|
|
4476
|
+
"aria-label": layer.visible ? `Hide ${row.label}` : `Show ${row.label}`,
|
|
4477
|
+
"aria-pressed": layer.visible,
|
|
4478
|
+
className: "w-4 text-center text-slate-300",
|
|
4479
|
+
onClick: (e) => {
|
|
4480
|
+
e.stopPropagation();
|
|
4481
|
+
attempt(() => controller.setLayerProperties(layer.id, { visible: !layer.visible }));
|
|
4482
|
+
},
|
|
4483
|
+
children: layer.visible ? "\u25CF" : "\u25CB"
|
|
4484
|
+
}
|
|
4485
|
+
),
|
|
4486
|
+
layer.type === "group" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4487
|
+
"button",
|
|
4488
|
+
{
|
|
4489
|
+
type: "button",
|
|
4490
|
+
"aria-label": layer.collapsed ? `Expand ${row.label}` : `Collapse ${row.label}`,
|
|
4491
|
+
className: "w-3 text-slate-400",
|
|
4492
|
+
onClick: (e) => {
|
|
4493
|
+
e.stopPropagation();
|
|
4494
|
+
attempt(() => controller.setLayerProperties(layer.id, { collapsed: !layer.collapsed }));
|
|
4495
|
+
},
|
|
4496
|
+
children: layer.collapsed ? "\u25B8" : "\u25BE"
|
|
4497
|
+
}
|
|
4498
|
+
),
|
|
4499
|
+
row.clipped && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-slate-500", "aria-label": "Clipped", children: "\u21B3" }),
|
|
4500
|
+
layer.type === "pixel" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4501
|
+
Thumbnail,
|
|
4502
|
+
{
|
|
4503
|
+
pixels: thumb(layer),
|
|
4504
|
+
size: thumbnailSize,
|
|
4505
|
+
label: `${row.label} pixels`,
|
|
4506
|
+
selected: row.active && state.activeTarget === "pixels" && Boolean(layer.mask)
|
|
4507
|
+
}
|
|
4508
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4509
|
+
"span",
|
|
4510
|
+
{
|
|
4511
|
+
className: "shrink-0 grid place-items-center rounded bg-slate-800 text-[9px] text-slate-400 ring-1 ring-slate-700",
|
|
4512
|
+
style: { width: thumbnailSize, height: thumbnailSize },
|
|
4513
|
+
children: (0, import_image_editor6.layerBadge)(layer)
|
|
4514
|
+
}
|
|
4515
|
+
),
|
|
4516
|
+
layer.mask && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4517
|
+
Thumbnail,
|
|
4518
|
+
{
|
|
4519
|
+
pixels: maskThumb(layer),
|
|
4520
|
+
size: thumbnailSize,
|
|
4521
|
+
label: `${row.label} mask${layer.mask.enabled === false ? " (disabled)" : ""}`,
|
|
4522
|
+
testId: "layer-mask-thumbnail",
|
|
4523
|
+
selected: row.active && state.activeTarget === "mask",
|
|
4524
|
+
onClick: (e) => {
|
|
4525
|
+
e.stopPropagation();
|
|
4526
|
+
if (e.shiftKey) attempt(() => controller.setLayerMaskProps(layer.id, { enabled: layer.mask.enabled === false }));
|
|
4527
|
+
else attempt(() => controller.setActiveLayer(layer.id, "mask"));
|
|
4528
|
+
}
|
|
4529
|
+
}
|
|
4530
|
+
),
|
|
4531
|
+
renaming === layer.id ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4532
|
+
"input",
|
|
4533
|
+
{
|
|
4534
|
+
autoFocus: true,
|
|
4535
|
+
"aria-label": "Layer name",
|
|
4536
|
+
defaultValue: layer.name || row.label,
|
|
4537
|
+
className: "flex-1 min-w-0 bg-slate-900 border border-slate-600 rounded px-1",
|
|
4538
|
+
onClick: (e) => e.stopPropagation(),
|
|
4539
|
+
onBlur: (e) => {
|
|
4540
|
+
setRenaming(null);
|
|
4541
|
+
if (e.target.value.trim() && e.target.value !== layer.name) attempt(() => controller.setLayerProperties(layer.id, { name: e.target.value }));
|
|
4542
|
+
},
|
|
4543
|
+
onKeyDown: (e) => {
|
|
4544
|
+
if (e.key === "Enter") e.target.blur();
|
|
4545
|
+
if (e.key === "Escape") setRenaming(null);
|
|
4546
|
+
}
|
|
4547
|
+
}
|
|
4548
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4549
|
+
"span",
|
|
4550
|
+
{
|
|
4551
|
+
className: `flex-1 min-w-0 truncate ${layer.visible ? "" : "text-slate-500"}`,
|
|
4552
|
+
onDoubleClick: (e) => {
|
|
4553
|
+
e.stopPropagation();
|
|
4554
|
+
setRenaming(layer.id);
|
|
4555
|
+
},
|
|
4556
|
+
children: row.label
|
|
4557
|
+
}
|
|
4558
|
+
),
|
|
4559
|
+
locked(layer) && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { "aria-label": "Locked", className: "text-slate-400", children: "\u{1F512}" }),
|
|
4560
|
+
layer.blend !== "normal" && layer.blend !== "pass-through" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[9px] text-slate-500", children: layer.blend })
|
|
4561
|
+
]
|
|
4562
|
+
},
|
|
4563
|
+
layer.id
|
|
4564
|
+
);
|
|
4565
|
+
}) }),
|
|
4566
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
|
|
4567
|
+
menu && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4568
|
+
"div",
|
|
4569
|
+
{
|
|
4570
|
+
role: "menu",
|
|
4571
|
+
"aria-label": "Layer menu",
|
|
4572
|
+
className: "fixed z-50 min-w-44 rounded border border-slate-700 bg-slate-900 py-1 shadow-xl",
|
|
4573
|
+
style: { left: menu.x, top: menu.y },
|
|
4574
|
+
onClick: (e) => e.stopPropagation(),
|
|
4575
|
+
onKeyDown: (e) => e.key === "Escape" && setMenu(null),
|
|
4576
|
+
children: (0, import_image_editor6.layerMenu)(controller).map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4577
|
+
"button",
|
|
4578
|
+
{
|
|
4579
|
+
type: "button",
|
|
4580
|
+
role: "menuitem",
|
|
4581
|
+
disabled: !item.enabled,
|
|
4582
|
+
className: "block w-full px-3 py-1 text-left hover:bg-slate-800 disabled:opacity-40",
|
|
4583
|
+
onClick: () => run(item.action),
|
|
4584
|
+
children: item.label
|
|
4585
|
+
},
|
|
4586
|
+
item.action
|
|
4587
|
+
))
|
|
4588
|
+
}
|
|
4589
|
+
)
|
|
4590
|
+
] });
|
|
4591
|
+
};
|
|
4592
|
+
|
|
4593
|
+
// src/image-editor/BrushOptionsBar.tsx
|
|
4594
|
+
var import_react39 = require("react");
|
|
4595
|
+
var import_image_editor7 = require("@pixerate/editor/image-editor");
|
|
4596
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
4597
|
+
var chip = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
|
|
4598
|
+
var BrushOptionsBar = ({ controller, className }) => {
|
|
4599
|
+
const [, setTick] = (0, import_react39.useState)(0);
|
|
4600
|
+
(0, import_react39.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
4601
|
+
const [error, setError] = (0, import_react39.useState)(null);
|
|
4602
|
+
const state = controller.getState();
|
|
4603
|
+
const { brush, foreground, background } = state.paint;
|
|
4604
|
+
const attempt = (fn) => {
|
|
4605
|
+
try {
|
|
4606
|
+
setError(null);
|
|
4607
|
+
fn();
|
|
4608
|
+
} catch (err) {
|
|
4609
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4610
|
+
}
|
|
4611
|
+
};
|
|
4612
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "brush-options", children: [
|
|
4613
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Paint tools", children: import_image_editor7.PAINT_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4614
|
+
"button",
|
|
4615
|
+
{
|
|
4616
|
+
type: "button",
|
|
4617
|
+
"aria-pressed": state.activeTool === t.id,
|
|
4618
|
+
title: `${t.label} (${t.shortcut})`,
|
|
4619
|
+
className: chip(state.activeTool === t.id),
|
|
4620
|
+
onClick: () => controller.setTool(t.id),
|
|
4621
|
+
children: t.label
|
|
4622
|
+
},
|
|
4623
|
+
t.id
|
|
4624
|
+
)) }),
|
|
4625
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2", role: "group", "aria-label": "Colours", children: [
|
|
4626
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
4627
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4628
|
+
"input",
|
|
4629
|
+
{
|
|
4630
|
+
type: "color",
|
|
4631
|
+
"aria-label": "Foreground colour",
|
|
4632
|
+
value: foreground,
|
|
4633
|
+
onChange: (e) => controller.setPaintOptions({ foreground: e.target.value }),
|
|
4634
|
+
className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
|
|
4635
|
+
}
|
|
4636
|
+
),
|
|
4637
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-slate-400", children: "FG" })
|
|
4638
|
+
] }),
|
|
4639
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
4640
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4641
|
+
"input",
|
|
4642
|
+
{
|
|
4643
|
+
type: "color",
|
|
4644
|
+
"aria-label": "Background colour",
|
|
4645
|
+
value: background,
|
|
4646
|
+
onChange: (e) => controller.setPaintOptions({ background: e.target.value }),
|
|
4647
|
+
className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
|
|
4648
|
+
}
|
|
4649
|
+
),
|
|
4650
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-slate-400", children: "BG" })
|
|
4651
|
+
] }),
|
|
4652
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", title: "Swap colours (X)", className: chip(false), onClick: () => controller.swapPaintColors(), children: "Swap" }),
|
|
4653
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", title: "Default colours (D)", className: chip(false), onClick: () => controller.resetPaintColors(), children: "Default" })
|
|
4654
|
+
] }),
|
|
4655
|
+
import_image_editor7.BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4656
|
+
ControlSlider,
|
|
4657
|
+
{
|
|
4658
|
+
spec,
|
|
4659
|
+
value: brush[spec.id],
|
|
4660
|
+
onChange: (v) => controller.setPaintOptions({ brush: { [spec.id]: v } })
|
|
4661
|
+
},
|
|
4662
|
+
spec.id
|
|
4663
|
+
)),
|
|
4664
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
|
|
4665
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1.5", children: [
|
|
4666
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4667
|
+
"input",
|
|
4668
|
+
{
|
|
4669
|
+
type: "checkbox",
|
|
4670
|
+
"aria-label": "Pressure controls size",
|
|
4671
|
+
checked: brush.pressureSize,
|
|
4672
|
+
onChange: (e) => controller.setPaintOptions({ brush: { pressureSize: e.target.checked } }),
|
|
4673
|
+
className: "accent-indigo-500"
|
|
4674
|
+
}
|
|
4675
|
+
),
|
|
4676
|
+
"Pressure size"
|
|
4677
|
+
] }),
|
|
4678
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1.5", children: [
|
|
4679
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4680
|
+
"input",
|
|
4681
|
+
{
|
|
4682
|
+
type: "checkbox",
|
|
4683
|
+
"aria-label": "Pressure controls opacity",
|
|
4684
|
+
checked: brush.pressureOpacity,
|
|
4685
|
+
onChange: (e) => controller.setPaintOptions({ brush: { pressureOpacity: e.target.checked } }),
|
|
4686
|
+
className: "accent-indigo-500"
|
|
4687
|
+
}
|
|
4688
|
+
),
|
|
4689
|
+
"Pressure opacity"
|
|
4690
|
+
] })
|
|
4691
|
+
] }),
|
|
4692
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex gap-1", children: [
|
|
4693
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.fillPixels()), children: "Fill" }),
|
|
4694
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.clearPixels()), children: "Clear" })
|
|
4695
|
+
] }),
|
|
4696
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
|
|
4697
|
+
] });
|
|
4698
|
+
};
|
|
4699
|
+
|
|
4700
|
+
// src/image-editor/SelectionOptionsBar.tsx
|
|
4701
|
+
var import_react40 = require("react");
|
|
4702
|
+
var import_image_editor8 = require("@pixerate/editor/image-editor");
|
|
4703
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
4220
4704
|
var MODIFY_OPS = [
|
|
4221
4705
|
{ op: "grow", label: "Grow" },
|
|
4222
4706
|
{ op: "shrink", label: "Shrink" },
|
|
@@ -4233,20 +4717,20 @@ var SelectionOptionsBar = ({
|
|
|
4233
4717
|
quickMask,
|
|
4234
4718
|
className = ""
|
|
4235
4719
|
}) => {
|
|
4236
|
-
const [radius, setRadius] = (0,
|
|
4720
|
+
const [radius, setRadius] = (0, import_react40.useState)(2);
|
|
4237
4721
|
const set = (patch) => onOptionsChange({ ...options, ...patch });
|
|
4238
4722
|
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
4239
4723
|
const qm = quickMask ?? Boolean(controller.getState().quickMask);
|
|
4240
|
-
return /* @__PURE__ */ (0,
|
|
4241
|
-
/* @__PURE__ */ (0,
|
|
4242
|
-
/* @__PURE__ */ (0,
|
|
4243
|
-
options.tool === "wand" && /* @__PURE__ */ (0,
|
|
4244
|
-
/* @__PURE__ */ (0,
|
|
4245
|
-
/* @__PURE__ */ (0,
|
|
4246
|
-
/* @__PURE__ */ (0,
|
|
4247
|
-
/* @__PURE__ */ (0,
|
|
4724
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
4725
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { role: "group", "aria-label": "Selection tool", className: "flex flex-wrap gap-1", children: import_image_editor8.SELECTION_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", "aria-pressed": options.tool === t.id, className: btn(options.tool === t.id), onClick: () => set({ tool: t.id }), children: t.label }, t.id)) }),
|
|
4726
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { role: "group", "aria-label": "Selection mode", className: "flex flex-wrap gap-1", children: import_image_editor8.SELECTION_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", "aria-pressed": options.mode === m, className: btn(options.mode === m), onClick: () => set({ mode: m }), children: import_image_editor8.SELECTION_MODE_LABELS[m] }, m)) }),
|
|
4727
|
+
options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
4728
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
4729
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
4730
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Tolerance" }),
|
|
4731
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "font-mono", children: options.tolerance })
|
|
4248
4732
|
] }),
|
|
4249
|
-
/* @__PURE__ */ (0,
|
|
4733
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4250
4734
|
"input",
|
|
4251
4735
|
{
|
|
4252
4736
|
type: "range",
|
|
@@ -4260,29 +4744,45 @@ var SelectionOptionsBar = ({
|
|
|
4260
4744
|
}
|
|
4261
4745
|
)
|
|
4262
4746
|
] }),
|
|
4263
|
-
/* @__PURE__ */ (0,
|
|
4264
|
-
/* @__PURE__ */ (0,
|
|
4747
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
4748
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
|
|
4265
4749
|
"Contiguous"
|
|
4266
4750
|
] }),
|
|
4267
|
-
/* @__PURE__ */ (0,
|
|
4268
|
-
/* @__PURE__ */ (0,
|
|
4751
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
4752
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
|
|
4269
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
|
+
)
|
|
4270
4770
|
] })
|
|
4271
4771
|
] }),
|
|
4272
|
-
/* @__PURE__ */ (0,
|
|
4273
|
-
/* @__PURE__ */ (0,
|
|
4772
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
4773
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
|
|
4274
4774
|
"Anti-alias"
|
|
4275
4775
|
] }),
|
|
4276
|
-
/* @__PURE__ */ (0,
|
|
4277
|
-
/* @__PURE__ */ (0,
|
|
4278
|
-
/* @__PURE__ */ (0,
|
|
4279
|
-
/* @__PURE__ */ (0,
|
|
4280
|
-
/* @__PURE__ */ (0,
|
|
4776
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
|
|
4777
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
|
|
4778
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
|
|
4779
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
|
|
4780
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
|
|
4281
4781
|
] }),
|
|
4282
|
-
/* @__PURE__ */ (0,
|
|
4283
|
-
/* @__PURE__ */ (0,
|
|
4782
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
4783
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
|
|
4284
4784
|
"Radius",
|
|
4285
|
-
/* @__PURE__ */ (0,
|
|
4785
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4286
4786
|
"input",
|
|
4287
4787
|
{
|
|
4288
4788
|
type: "number",
|
|
@@ -4296,24 +4796,24 @@ var SelectionOptionsBar = ({
|
|
|
4296
4796
|
}
|
|
4297
4797
|
)
|
|
4298
4798
|
] }),
|
|
4299
|
-
MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0,
|
|
4799
|
+
MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.modifySelection(op, radius), children: label }, op))
|
|
4300
4800
|
] }),
|
|
4301
|
-
/* @__PURE__ */ (0,
|
|
4801
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor8.describeSelection)(sel) })
|
|
4302
4802
|
] });
|
|
4303
4803
|
};
|
|
4304
4804
|
|
|
4305
4805
|
// src/image-editor/RefineEdgePanel.tsx
|
|
4306
|
-
var
|
|
4307
|
-
var
|
|
4308
|
-
var
|
|
4806
|
+
var import_react41 = require("react");
|
|
4807
|
+
var import_image_editor9 = require("@pixerate/editor/image-editor");
|
|
4808
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
4309
4809
|
var DEFAULT_PARAMS = { radius: 8, smartRadius: false, smooth: 0, feather: 0, contrast: 0, shiftEdge: 0 };
|
|
4310
4810
|
var button = "px-2 py-1 rounded-md border border-slate-800 bg-slate-950 text-[11px] text-slate-200 hover:text-white disabled:opacity-40";
|
|
4311
4811
|
var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
4312
|
-
const [params, setParams] = (0,
|
|
4313
|
-
const [busy, setBusy] = (0,
|
|
4314
|
-
const [error, setError] = (0,
|
|
4315
|
-
const [layerId, setLayerId] = (0,
|
|
4316
|
-
const [newKind, setNewKind] = (0,
|
|
4812
|
+
const [params, setParams] = (0, import_react41.useState)(DEFAULT_PARAMS);
|
|
4813
|
+
const [busy, setBusy] = (0, import_react41.useState)(false);
|
|
4814
|
+
const [error, setError] = (0, import_react41.useState)(null);
|
|
4815
|
+
const [layerId, setLayerId] = (0, import_react41.useState)("");
|
|
4816
|
+
const [newKind, setNewKind] = (0, import_react41.useState)("hueSaturation");
|
|
4317
4817
|
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
4318
4818
|
const list = layers ?? controller.getAdjustmentLayers();
|
|
4319
4819
|
const target = list.find((l) => l.id === layerId) ?? list[list.length - 1];
|
|
@@ -4328,17 +4828,17 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
4328
4828
|
setBusy(false);
|
|
4329
4829
|
}
|
|
4330
4830
|
};
|
|
4331
|
-
return /* @__PURE__ */ (0,
|
|
4332
|
-
/* @__PURE__ */ (0,
|
|
4333
|
-
|
|
4334
|
-
/* @__PURE__ */ (0,
|
|
4335
|
-
/* @__PURE__ */ (0,
|
|
4336
|
-
/* @__PURE__ */ (0,
|
|
4831
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
4832
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
|
|
4833
|
+
import_image_editor9.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
4834
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
4835
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: c.label }),
|
|
4836
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "font-mono", children: [
|
|
4337
4837
|
params[c.id],
|
|
4338
4838
|
c.unit
|
|
4339
4839
|
] })
|
|
4340
4840
|
] }),
|
|
4341
|
-
/* @__PURE__ */ (0,
|
|
4841
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4342
4842
|
"input",
|
|
4343
4843
|
{
|
|
4344
4844
|
type: "range",
|
|
@@ -4352,67 +4852,67 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
4352
4852
|
}
|
|
4353
4853
|
)
|
|
4354
4854
|
] }, c.id)),
|
|
4355
|
-
/* @__PURE__ */ (0,
|
|
4356
|
-
/* @__PURE__ */ (0,
|
|
4855
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
4856
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
|
|
4357
4857
|
"Smart Radius"
|
|
4358
4858
|
] }),
|
|
4359
|
-
/* @__PURE__ */ (0,
|
|
4360
|
-
/* @__PURE__ */ (0,
|
|
4361
|
-
/* @__PURE__ */ (0,
|
|
4859
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-1", children: [
|
|
4860
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
|
|
4861
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
|
|
4362
4862
|
] }),
|
|
4363
|
-
error && /* @__PURE__ */ (0,
|
|
4364
|
-
/* @__PURE__ */ (0,
|
|
4365
|
-
/* @__PURE__ */ (0,
|
|
4366
|
-
/* @__PURE__ */ (0,
|
|
4863
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
|
|
4864
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
|
|
4865
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-1 items-center", children: [
|
|
4866
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4367
4867
|
"select",
|
|
4368
4868
|
{
|
|
4369
4869
|
"aria-label": "New masked layer kind",
|
|
4370
4870
|
value: newKind,
|
|
4371
4871
|
onChange: (e) => setNewKind(e.target.value),
|
|
4372
4872
|
className: "flex-1 bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
|
|
4373
|
-
children:
|
|
4873
|
+
children: import_image_editor9.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: k.kind, children: k.label }, k.kind))
|
|
4374
4874
|
}
|
|
4375
4875
|
),
|
|
4376
|
-
/* @__PURE__ */ (0,
|
|
4876
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4377
4877
|
"button",
|
|
4378
4878
|
{
|
|
4379
4879
|
type: "button",
|
|
4380
4880
|
className: button,
|
|
4381
4881
|
disabled: !sel,
|
|
4382
|
-
onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0,
|
|
4882
|
+
onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor9.layerMaskFromSelection)(sel) })),
|
|
4383
4883
|
children: "New Masked Layer"
|
|
4384
4884
|
}
|
|
4385
4885
|
)
|
|
4386
4886
|
] }),
|
|
4387
|
-
list.length > 0 && target && /* @__PURE__ */ (0,
|
|
4388
|
-
/* @__PURE__ */ (0,
|
|
4887
|
+
list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
4888
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4389
4889
|
"select",
|
|
4390
4890
|
{
|
|
4391
4891
|
"aria-label": "Mask layer",
|
|
4392
4892
|
value: target.id,
|
|
4393
4893
|
onChange: (e) => setLayerId(e.target.value),
|
|
4394
4894
|
className: "bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
|
|
4395
|
-
children: list.map((l) => /* @__PURE__ */ (0,
|
|
4396
|
-
l.name || (0,
|
|
4895
|
+
children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("option", { value: l.id, children: [
|
|
4896
|
+
l.name || (0, import_image_editor9.adjustmentKindLabel)(l.kind),
|
|
4397
4897
|
l.mask ? " (masked)" : ""
|
|
4398
4898
|
] }, l.id))
|
|
4399
4899
|
}
|
|
4400
4900
|
),
|
|
4401
|
-
/* @__PURE__ */ (0,
|
|
4402
|
-
/* @__PURE__ */ (0,
|
|
4403
|
-
/* @__PURE__ */ (0,
|
|
4404
|
-
/* @__PURE__ */ (0,
|
|
4901
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
|
|
4902
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
|
|
4903
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
|
|
4904
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
|
|
4405
4905
|
] }),
|
|
4406
|
-
target.mask && /* @__PURE__ */ (0,
|
|
4407
|
-
/* @__PURE__ */ (0,
|
|
4408
|
-
/* @__PURE__ */ (0,
|
|
4409
|
-
/* @__PURE__ */ (0,
|
|
4410
|
-
/* @__PURE__ */ (0,
|
|
4906
|
+
target.mask && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
4907
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
4908
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
4909
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Density" }),
|
|
4910
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "font-mono", children: [
|
|
4411
4911
|
Math.round((target.mask.density ?? 1) * 100),
|
|
4412
4912
|
"%"
|
|
4413
4913
|
] })
|
|
4414
4914
|
] }),
|
|
4415
|
-
/* @__PURE__ */ (0,
|
|
4915
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4416
4916
|
"input",
|
|
4417
4917
|
{
|
|
4418
4918
|
type: "range",
|
|
@@ -4426,15 +4926,15 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
4426
4926
|
}
|
|
4427
4927
|
)
|
|
4428
4928
|
] }),
|
|
4429
|
-
/* @__PURE__ */ (0,
|
|
4430
|
-
/* @__PURE__ */ (0,
|
|
4431
|
-
/* @__PURE__ */ (0,
|
|
4432
|
-
/* @__PURE__ */ (0,
|
|
4929
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
4930
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
4931
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Mask Feather" }),
|
|
4932
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "font-mono", children: [
|
|
4433
4933
|
target.mask.feather ?? 0,
|
|
4434
4934
|
"px"
|
|
4435
4935
|
] })
|
|
4436
4936
|
] }),
|
|
4437
|
-
/* @__PURE__ */ (0,
|
|
4937
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4438
4938
|
"input",
|
|
4439
4939
|
{
|
|
4440
4940
|
type: "range",
|
|
@@ -4454,7 +4954,7 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
4454
4954
|
};
|
|
4455
4955
|
|
|
4456
4956
|
// src/image-editor/ImageEditor.tsx
|
|
4457
|
-
var
|
|
4957
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
4458
4958
|
var ImageEditor = ({
|
|
4459
4959
|
editor: externalEditor,
|
|
4460
4960
|
src,
|
|
@@ -4469,26 +4969,36 @@ var ImageEditor = ({
|
|
|
4469
4969
|
const internalEditor = useImageEditor({ image: src });
|
|
4470
4970
|
const editor = externalEditor || internalEditor;
|
|
4471
4971
|
const { state, controller } = editor;
|
|
4472
|
-
const legacyProcess = (0,
|
|
4473
|
-
const canvasRef = (0,
|
|
4474
|
-
const containerRef = (0,
|
|
4475
|
-
const [activeTab, setActiveTab] = (0,
|
|
4476
|
-
const [activeCropRatio, setActiveCropRatio] = (0,
|
|
4477
|
-
const [selectionOptions, setSelectionOptions] = (0,
|
|
4478
|
-
const selectionOptionsRef = (0,
|
|
4972
|
+
const legacyProcess = (0, import_image_editor10.normalizeProcessVersion)(state.adjustments.process) < import_image_editor10.LATEST_PROCESS_VERSION;
|
|
4973
|
+
const canvasRef = (0, import_react42.useRef)(null);
|
|
4974
|
+
const containerRef = (0, import_react42.useRef)(null);
|
|
4975
|
+
const [activeTab, setActiveTab] = (0, import_react42.useState)("crop");
|
|
4976
|
+
const [activeCropRatio, setActiveCropRatio] = (0, import_react42.useState)(null);
|
|
4977
|
+
const [selectionOptions, setSelectionOptions] = (0, import_react42.useState)(import_image_editor10.DEFAULT_SELECTION_TOOL_OPTIONS);
|
|
4978
|
+
const selectionOptionsRef = (0, import_react42.useRef)(selectionOptions);
|
|
4479
4979
|
selectionOptionsRef.current = selectionOptions;
|
|
4480
|
-
const selectionGestureRef = (0,
|
|
4980
|
+
const selectionGestureRef = (0, import_react42.useRef)(null);
|
|
4481
4981
|
if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
|
|
4482
|
-
selectionGestureRef.current = new
|
|
4982
|
+
selectionGestureRef.current = new import_image_editor10.SelectionGesture(controller, () => selectionOptionsRef.current);
|
|
4483
4983
|
}
|
|
4484
|
-
const selectionDraftRef = (0,
|
|
4485
|
-
const [selectionError, setSelectionError] = (0,
|
|
4486
|
-
const
|
|
4487
|
-
const
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4984
|
+
const selectionDraftRef = (0, import_react42.useRef)(null);
|
|
4985
|
+
const [selectionError, setSelectionError] = (0, import_react42.useState)(null);
|
|
4986
|
+
const paintGestureRef = (0, import_react42.useRef)(null);
|
|
4987
|
+
const paintControllerRef = (0, import_react42.useRef)(controller);
|
|
4988
|
+
if (!paintGestureRef.current || paintControllerRef.current !== controller) {
|
|
4989
|
+
paintGestureRef.current = new import_image_editor10.PaintGesture(controller);
|
|
4990
|
+
paintControllerRef.current = controller;
|
|
4991
|
+
}
|
|
4992
|
+
const brushCursorRef = (0, import_react42.useRef)(null);
|
|
4993
|
+
const [paintError, setPaintError] = (0, import_react42.useState)(null);
|
|
4994
|
+
const [inpaintPrompt, setInpaintPrompt] = (0, import_react42.useState)("");
|
|
4995
|
+
const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react42.useState)("annotations");
|
|
4996
|
+
const [isRemovingBg, setIsRemovingBg] = (0, import_react42.useState)(false);
|
|
4997
|
+
const [isInpainting, setIsInpainting] = (0, import_react42.useState)(false);
|
|
4998
|
+
const [aiError, setAiError] = (0, import_react42.useState)(null);
|
|
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 };
|
|
4492
5002
|
const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
|
|
4493
5003
|
const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
|
|
4494
5004
|
const handleRemoveBackground = async () => {
|
|
@@ -4500,10 +5010,10 @@ var ImageEditor = ({
|
|
|
4500
5010
|
setAiSuccess(null);
|
|
4501
5011
|
setIsRemovingBg(true);
|
|
4502
5012
|
try {
|
|
4503
|
-
const imageDataUrl = await
|
|
5013
|
+
const imageDataUrl = await controller.toAIInputDataURL(aiOptions);
|
|
4504
5014
|
const result = await effectiveOnRemoveBg({ imageDataUrl });
|
|
4505
5015
|
if (typeof result === "string") {
|
|
4506
|
-
await editor.applyBackgroundRemovedImage(result);
|
|
5016
|
+
await editor.applyBackgroundRemovedImage(result, aiOptions);
|
|
4507
5017
|
setAiSuccess("Background removed successfully!");
|
|
4508
5018
|
} else {
|
|
4509
5019
|
setAiSuccess("Background removal complete.");
|
|
@@ -4527,7 +5037,7 @@ var ImageEditor = ({
|
|
|
4527
5037
|
setAiSuccess(null);
|
|
4528
5038
|
setIsInpainting(true);
|
|
4529
5039
|
try {
|
|
4530
|
-
const imageDataUrl = await
|
|
5040
|
+
const imageDataUrl = await controller.toAIInputDataURL(aiOptions);
|
|
4531
5041
|
const maskDataUrl = await editor.toMaskDataURL({
|
|
4532
5042
|
useAnnotations: inpaintMaskMode === "annotations",
|
|
4533
5043
|
useCrop: inpaintMaskMode === "crop"
|
|
@@ -4539,7 +5049,7 @@ var ImageEditor = ({
|
|
|
4539
5049
|
cropBox: inpaintMaskMode === "crop" ? editor.state.crop : null
|
|
4540
5050
|
});
|
|
4541
5051
|
if (typeof result === "string") {
|
|
4542
|
-
await editor.applyInpaintedImage(result);
|
|
5052
|
+
await editor.applyInpaintedImage(result, aiOptions);
|
|
4543
5053
|
setAiSuccess("Inpainting applied successfully!");
|
|
4544
5054
|
} else {
|
|
4545
5055
|
setAiSuccess("Inpainting complete.");
|
|
@@ -4550,18 +5060,18 @@ var ImageEditor = ({
|
|
|
4550
5060
|
setIsInpainting(false);
|
|
4551
5061
|
}
|
|
4552
5062
|
};
|
|
4553
|
-
const [activeColor, setActiveColor] = (0,
|
|
4554
|
-
const [strokeWidth, setStrokeWidth] = (0,
|
|
4555
|
-
const [fontSize, setFontSize] = (0,
|
|
4556
|
-
const [textInput, setTextInput] = (0,
|
|
4557
|
-
const draftAnnotationRef = (0,
|
|
4558
|
-
const draftCropRef = (0,
|
|
4559
|
-
const cropDragInfoRef = (0,
|
|
4560
|
-
const annotationDragInfoRef = (0,
|
|
4561
|
-
const isDrawingRef = (0,
|
|
4562
|
-
const currentPathRef = (0,
|
|
4563
|
-
const dragStartPointRef = (0,
|
|
4564
|
-
const renderCanvas = (0,
|
|
5063
|
+
const [activeColor, setActiveColor] = (0, import_react42.useState)("#ef4444");
|
|
5064
|
+
const [strokeWidth, setStrokeWidth] = (0, import_react42.useState)(3);
|
|
5065
|
+
const [fontSize, setFontSize] = (0, import_react42.useState)(24);
|
|
5066
|
+
const [textInput, setTextInput] = (0, import_react42.useState)("");
|
|
5067
|
+
const draftAnnotationRef = (0, import_react42.useRef)(null);
|
|
5068
|
+
const draftCropRef = (0, import_react42.useRef)(null);
|
|
5069
|
+
const cropDragInfoRef = (0, import_react42.useRef)(null);
|
|
5070
|
+
const annotationDragInfoRef = (0, import_react42.useRef)(null);
|
|
5071
|
+
const isDrawingRef = (0, import_react42.useRef)(false);
|
|
5072
|
+
const currentPathRef = (0, import_react42.useRef)([]);
|
|
5073
|
+
const dragStartPointRef = (0, import_react42.useRef)(null);
|
|
5074
|
+
const renderCanvas = (0, import_react42.useCallback)(
|
|
4565
5075
|
async (draftAnnotation, draftCrop) => {
|
|
4566
5076
|
const canvas = canvasRef.current;
|
|
4567
5077
|
const container = containerRef.current;
|
|
@@ -4576,12 +5086,13 @@ var ImageEditor = ({
|
|
|
4576
5086
|
interactive: true,
|
|
4577
5087
|
draftAnnotation: draftAnnotation !== void 0 ? draftAnnotation : draftAnnotationRef.current,
|
|
4578
5088
|
draftCrop: draftCrop !== void 0 ? draftCrop : draftCropRef.current,
|
|
4579
|
-
draftSelectionPath: selectionDraftRef.current
|
|
5089
|
+
draftSelectionPath: selectionDraftRef.current,
|
|
5090
|
+
brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null
|
|
4580
5091
|
});
|
|
4581
5092
|
},
|
|
4582
5093
|
[controller, activeTab]
|
|
4583
5094
|
);
|
|
4584
|
-
(0,
|
|
5095
|
+
(0, import_react42.useEffect)(() => {
|
|
4585
5096
|
const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
|
|
4586
5097
|
const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
|
|
4587
5098
|
const animId = raf(() => {
|
|
@@ -4589,12 +5100,12 @@ var ImageEditor = ({
|
|
|
4589
5100
|
});
|
|
4590
5101
|
return () => caf(animId);
|
|
4591
5102
|
}, [renderCanvas, state]);
|
|
4592
|
-
(0,
|
|
5103
|
+
(0, import_react42.useEffect)(() => {
|
|
4593
5104
|
if (activeTab === "crop" && editor.state.activeTool !== "crop") {
|
|
4594
5105
|
editor.setTool("crop");
|
|
4595
5106
|
}
|
|
4596
5107
|
}, [activeTab, editor]);
|
|
4597
|
-
(0,
|
|
5108
|
+
(0, import_react42.useEffect)(() => {
|
|
4598
5109
|
const container = containerRef.current;
|
|
4599
5110
|
if (!container) return;
|
|
4600
5111
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -4620,13 +5131,60 @@ var ImageEditor = ({
|
|
|
4620
5131
|
y: (e.clientY - rect.top) * scaleY
|
|
4621
5132
|
};
|
|
4622
5133
|
};
|
|
5134
|
+
const paintSamples = (e) => {
|
|
5135
|
+
const canvas = canvasRef.current;
|
|
5136
|
+
const native = e.nativeEvent;
|
|
5137
|
+
const events = typeof native.getCoalescedEvents === "function" ? native.getCoalescedEvents() : [];
|
|
5138
|
+
const list = events.length ? events : [native];
|
|
5139
|
+
const rect = canvas.getBoundingClientRect();
|
|
5140
|
+
const sx = rect.width > 0 ? canvas.width / rect.width : 1;
|
|
5141
|
+
const sy = rect.height > 0 ? canvas.height / rect.height : 1;
|
|
5142
|
+
const s = controller.getState();
|
|
5143
|
+
return list.map((ev) => ({
|
|
5144
|
+
...(0, import_image_editor10.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
|
|
5145
|
+
pressure: (0, import_image_editor10.pointerPressure)(ev)
|
|
5146
|
+
}));
|
|
5147
|
+
};
|
|
5148
|
+
const handlePaintPointerDown = (e) => {
|
|
5149
|
+
if (activeTab !== "paint" || e.button !== 0) return;
|
|
5150
|
+
e.preventDefault();
|
|
5151
|
+
try {
|
|
5152
|
+
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
5153
|
+
} catch {
|
|
5154
|
+
}
|
|
5155
|
+
const [first] = paintSamples(e);
|
|
5156
|
+
setPaintError(paintGestureRef.current.down(first));
|
|
5157
|
+
};
|
|
5158
|
+
const handlePaintPointerMove = (e) => {
|
|
5159
|
+
if (activeTab !== "paint") return;
|
|
5160
|
+
const samples = paintSamples(e);
|
|
5161
|
+
brushCursorRef.current = samples[samples.length - 1] ?? null;
|
|
5162
|
+
if (paintGestureRef.current.active) paintGestureRef.current.moveTo(samples);
|
|
5163
|
+
else void renderCanvas();
|
|
5164
|
+
};
|
|
5165
|
+
const handlePaintPointerUp = () => {
|
|
5166
|
+
if (activeTab !== "paint") return;
|
|
5167
|
+
const g = paintGestureRef.current;
|
|
5168
|
+
if (g.active) {
|
|
5169
|
+
g.up();
|
|
5170
|
+
if (g.error) setPaintError(g.error);
|
|
5171
|
+
}
|
|
5172
|
+
};
|
|
5173
|
+
(0, import_react42.useEffect)(() => {
|
|
5174
|
+
if (activeTab !== "paint" || typeof window === "undefined") return;
|
|
5175
|
+
const onKey = (e) => {
|
|
5176
|
+
if ((0, import_image_editor10.handlePaintShortcut)(controller, e)) e.preventDefault();
|
|
5177
|
+
};
|
|
5178
|
+
window.addEventListener("keydown", onKey);
|
|
5179
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
5180
|
+
}, [activeTab, controller]);
|
|
4623
5181
|
const handleMouseDown = (e) => {
|
|
4624
5182
|
const canvas = canvasRef.current;
|
|
4625
5183
|
if (!canvas) return;
|
|
4626
5184
|
const canvasPt = getCanvasEventPoint(e);
|
|
4627
5185
|
if (activeTab === "select") {
|
|
4628
5186
|
const gesture = selectionGestureRef.current;
|
|
4629
|
-
const imgPt = (0,
|
|
5187
|
+
const imgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
4630
5188
|
void gesture.begin(imgPt, e).then(() => setSelectionError(gesture.error));
|
|
4631
5189
|
return;
|
|
4632
5190
|
}
|
|
@@ -4637,8 +5195,8 @@ var ImageEditor = ({
|
|
|
4637
5195
|
width: state.imageDimensions.width,
|
|
4638
5196
|
height: state.imageDimensions.height
|
|
4639
5197
|
};
|
|
4640
|
-
const handle = (0,
|
|
4641
|
-
const startImgPt = (0,
|
|
5198
|
+
const handle = (0, import_image_editor10.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
|
|
5199
|
+
const startImgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
|
|
4642
5200
|
if (handle) {
|
|
4643
5201
|
cropDragInfoRef.current = {
|
|
4644
5202
|
handle,
|
|
@@ -4657,12 +5215,12 @@ var ImageEditor = ({
|
|
|
4657
5215
|
return;
|
|
4658
5216
|
}
|
|
4659
5217
|
if (activeTab === "annotate") {
|
|
4660
|
-
const imgPt = (0,
|
|
5218
|
+
const imgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
4661
5219
|
dragStartPointRef.current = imgPt;
|
|
4662
5220
|
if (state.activeTool === "select") {
|
|
4663
5221
|
for (let i = state.annotations.length - 1; i >= 0; i--) {
|
|
4664
5222
|
const ann = state.annotations[i];
|
|
4665
|
-
if ((0,
|
|
5223
|
+
if ((0, import_image_editor10.hitTestAnnotation)(imgPt, ann)) {
|
|
4666
5224
|
editor.selectAnnotation(ann.id);
|
|
4667
5225
|
annotationDragInfoRef.current = {
|
|
4668
5226
|
annId: ann.id,
|
|
@@ -4698,7 +5256,7 @@ var ImageEditor = ({
|
|
|
4698
5256
|
const canvasPt = getCanvasEventPoint(e);
|
|
4699
5257
|
if (activeTab === "select") {
|
|
4700
5258
|
const gesture = selectionGestureRef.current;
|
|
4701
|
-
if (gesture.active && gesture.move((0,
|
|
5259
|
+
if (gesture.active && gesture.move((0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
|
|
4702
5260
|
selectionDraftRef.current = gesture.draftPath;
|
|
4703
5261
|
renderCanvas();
|
|
4704
5262
|
}
|
|
@@ -4707,7 +5265,7 @@ var ImageEditor = ({
|
|
|
4707
5265
|
if (activeTab === "crop") {
|
|
4708
5266
|
const drag = cropDragInfoRef.current;
|
|
4709
5267
|
if (drag) {
|
|
4710
|
-
const currentImgPt = (0,
|
|
5268
|
+
const currentImgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
|
|
4711
5269
|
let newCrop;
|
|
4712
5270
|
if (drag.handle === "new") {
|
|
4713
5271
|
const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
|
|
@@ -4721,7 +5279,7 @@ var ImageEditor = ({
|
|
|
4721
5279
|
height: Math.round(Math.max(20, maxY - minY))
|
|
4722
5280
|
};
|
|
4723
5281
|
} else {
|
|
4724
|
-
newCrop = (0,
|
|
5282
|
+
newCrop = (0, import_image_editor10.calculateCropDrag)(
|
|
4725
5283
|
drag.startCrop,
|
|
4726
5284
|
drag.handle,
|
|
4727
5285
|
drag.startImgPt,
|
|
@@ -4741,15 +5299,15 @@ var ImageEditor = ({
|
|
|
4741
5299
|
width: state.imageDimensions.width,
|
|
4742
5300
|
height: state.imageDimensions.height
|
|
4743
5301
|
};
|
|
4744
|
-
const handle = (0,
|
|
4745
|
-
canvas.style.cursor = (0,
|
|
5302
|
+
const handle = (0, import_image_editor10.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
|
|
5303
|
+
canvas.style.cursor = (0, import_image_editor10.getCropCursor)(handle, state.transform);
|
|
4746
5304
|
}
|
|
4747
5305
|
return;
|
|
4748
5306
|
}
|
|
4749
5307
|
if (activeTab === "annotate") {
|
|
4750
5308
|
if (annotationDragInfoRef.current) {
|
|
4751
5309
|
const drag = annotationDragInfoRef.current;
|
|
4752
|
-
const currentImgPt2 = (0,
|
|
5310
|
+
const currentImgPt2 = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
4753
5311
|
const dx = currentImgPt2.x - drag.startImgPt.x;
|
|
4754
5312
|
const dy = currentImgPt2.y - drag.startImgPt.y;
|
|
4755
5313
|
editor.updateAnnotation(drag.annId, {
|
|
@@ -4761,10 +5319,10 @@ var ImageEditor = ({
|
|
|
4761
5319
|
const startPt = dragStartPointRef.current;
|
|
4762
5320
|
if (!startPt) {
|
|
4763
5321
|
if (state.activeTool === "select") {
|
|
4764
|
-
const imgPt = (0,
|
|
5322
|
+
const imgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
4765
5323
|
let hovered = false;
|
|
4766
5324
|
for (let i = state.annotations.length - 1; i >= 0; i--) {
|
|
4767
|
-
if ((0,
|
|
5325
|
+
if ((0, import_image_editor10.hitTestAnnotation)(imgPt, state.annotations[i])) {
|
|
4768
5326
|
hovered = true;
|
|
4769
5327
|
break;
|
|
4770
5328
|
}
|
|
@@ -4775,7 +5333,7 @@ var ImageEditor = ({
|
|
|
4775
5333
|
}
|
|
4776
5334
|
return;
|
|
4777
5335
|
}
|
|
4778
|
-
const currentImgPt = (0,
|
|
5336
|
+
const currentImgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
4779
5337
|
if (state.activeTool === "pen" && isDrawingRef.current) {
|
|
4780
5338
|
currentPathRef.current.push(currentImgPt);
|
|
4781
5339
|
const draft = {
|
|
@@ -4855,7 +5413,7 @@ var ImageEditor = ({
|
|
|
4855
5413
|
if (activeTab === "select") {
|
|
4856
5414
|
const gesture = selectionGestureRef.current;
|
|
4857
5415
|
if (gesture.active) {
|
|
4858
|
-
gesture.end((0,
|
|
5416
|
+
gesture.end((0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
|
|
4859
5417
|
selectionDraftRef.current = null;
|
|
4860
5418
|
renderCanvas();
|
|
4861
5419
|
}
|
|
@@ -4879,7 +5437,7 @@ var ImageEditor = ({
|
|
|
4879
5437
|
}
|
|
4880
5438
|
const startPt = dragStartPointRef.current;
|
|
4881
5439
|
if (startPt) {
|
|
4882
|
-
const currentImgPt = (0,
|
|
5440
|
+
const currentImgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
4883
5441
|
if (state.activeTool === "pen" && isDrawingRef.current) {
|
|
4884
5442
|
if (currentPathRef.current.length > 1) {
|
|
4885
5443
|
editor.addAnnotation({
|
|
@@ -4975,15 +5533,15 @@ var ImageEditor = ({
|
|
|
4975
5533
|
link.click();
|
|
4976
5534
|
}
|
|
4977
5535
|
};
|
|
4978
|
-
return /* @__PURE__ */ (0,
|
|
5536
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
4979
5537
|
"div",
|
|
4980
5538
|
{
|
|
4981
5539
|
className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
|
|
4982
5540
|
style,
|
|
4983
5541
|
children: [
|
|
4984
|
-
/* @__PURE__ */ (0,
|
|
4985
|
-
/* @__PURE__ */ (0,
|
|
4986
|
-
/* @__PURE__ */ (0,
|
|
5542
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap items-center justify-between px-4 py-3 bg-slate-950/80 border-b border-slate-800 gap-3", children: [
|
|
5543
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
|
|
5544
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4987
5545
|
"button",
|
|
4988
5546
|
{
|
|
4989
5547
|
type: "button",
|
|
@@ -4995,7 +5553,7 @@ var ImageEditor = ({
|
|
|
4995
5553
|
children: "Transform & Crop"
|
|
4996
5554
|
}
|
|
4997
5555
|
),
|
|
4998
|
-
/* @__PURE__ */ (0,
|
|
5556
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4999
5557
|
"button",
|
|
5000
5558
|
{
|
|
5001
5559
|
type: "button",
|
|
@@ -5007,7 +5565,31 @@ var ImageEditor = ({
|
|
|
5007
5565
|
children: "Adjustments"
|
|
5008
5566
|
}
|
|
5009
5567
|
),
|
|
5010
|
-
/* @__PURE__ */ (0,
|
|
5568
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5569
|
+
"button",
|
|
5570
|
+
{
|
|
5571
|
+
type: "button",
|
|
5572
|
+
onClick: () => {
|
|
5573
|
+
setActiveTab("layers");
|
|
5574
|
+
editor.setTool("select");
|
|
5575
|
+
},
|
|
5576
|
+
className: `px-3 py-1.5 rounded-md font-medium transition-colors ${activeTab === "layers" ? "bg-indigo-600 text-white shadow" : "text-slate-400 hover:text-slate-200"}`,
|
|
5577
|
+
children: "Layers"
|
|
5578
|
+
}
|
|
5579
|
+
),
|
|
5580
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5581
|
+
"button",
|
|
5582
|
+
{
|
|
5583
|
+
type: "button",
|
|
5584
|
+
onClick: () => {
|
|
5585
|
+
setActiveTab("paint");
|
|
5586
|
+
editor.setTool("brush");
|
|
5587
|
+
},
|
|
5588
|
+
className: `px-3 py-1.5 rounded-md font-medium transition-colors ${activeTab === "paint" ? "bg-indigo-600 text-white shadow" : "text-slate-400 hover:text-slate-200"}`,
|
|
5589
|
+
children: "Paint"
|
|
5590
|
+
}
|
|
5591
|
+
),
|
|
5592
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5011
5593
|
"button",
|
|
5012
5594
|
{
|
|
5013
5595
|
type: "button",
|
|
@@ -5019,7 +5601,7 @@ var ImageEditor = ({
|
|
|
5019
5601
|
children: "Select & Mask"
|
|
5020
5602
|
}
|
|
5021
5603
|
),
|
|
5022
|
-
/* @__PURE__ */ (0,
|
|
5604
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5023
5605
|
"button",
|
|
5024
5606
|
{
|
|
5025
5607
|
type: "button",
|
|
@@ -5031,7 +5613,7 @@ var ImageEditor = ({
|
|
|
5031
5613
|
children: "Annotations"
|
|
5032
5614
|
}
|
|
5033
5615
|
),
|
|
5034
|
-
/* @__PURE__ */ (0,
|
|
5616
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5035
5617
|
"button",
|
|
5036
5618
|
{
|
|
5037
5619
|
type: "button",
|
|
@@ -5043,7 +5625,7 @@ var ImageEditor = ({
|
|
|
5043
5625
|
children: "Depth Mask"
|
|
5044
5626
|
}
|
|
5045
5627
|
),
|
|
5046
|
-
/* @__PURE__ */ (0,
|
|
5628
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
5047
5629
|
"button",
|
|
5048
5630
|
{
|
|
5049
5631
|
type: "button",
|
|
@@ -5053,14 +5635,14 @@ var ImageEditor = ({
|
|
|
5053
5635
|
},
|
|
5054
5636
|
className: `px-3 py-1.5 rounded-md font-medium transition-colors flex items-center gap-1.5 ${activeTab === "ai" ? "bg-indigo-600 text-white shadow" : "text-slate-400 hover:text-slate-200"}`,
|
|
5055
5637
|
children: [
|
|
5056
|
-
/* @__PURE__ */ (0,
|
|
5638
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
|
|
5057
5639
|
"AI Tools"
|
|
5058
5640
|
]
|
|
5059
5641
|
}
|
|
5060
5642
|
)
|
|
5061
5643
|
] }),
|
|
5062
|
-
/* @__PURE__ */ (0,
|
|
5063
|
-
/* @__PURE__ */ (0,
|
|
5644
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
5645
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5064
5646
|
"button",
|
|
5065
5647
|
{
|
|
5066
5648
|
type: "button",
|
|
@@ -5071,7 +5653,7 @@ var ImageEditor = ({
|
|
|
5071
5653
|
children: "\u21A9"
|
|
5072
5654
|
}
|
|
5073
5655
|
),
|
|
5074
|
-
/* @__PURE__ */ (0,
|
|
5656
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5075
5657
|
"button",
|
|
5076
5658
|
{
|
|
5077
5659
|
type: "button",
|
|
@@ -5082,7 +5664,7 @@ var ImageEditor = ({
|
|
|
5082
5664
|
children: "\u21AA"
|
|
5083
5665
|
}
|
|
5084
5666
|
),
|
|
5085
|
-
/* @__PURE__ */ (0,
|
|
5667
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5086
5668
|
"button",
|
|
5087
5669
|
{
|
|
5088
5670
|
type: "button",
|
|
@@ -5091,8 +5673,8 @@ var ImageEditor = ({
|
|
|
5091
5673
|
children: "Reset"
|
|
5092
5674
|
}
|
|
5093
5675
|
),
|
|
5094
|
-
/* @__PURE__ */ (0,
|
|
5095
|
-
/* @__PURE__ */ (0,
|
|
5676
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
5677
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5096
5678
|
"button",
|
|
5097
5679
|
{
|
|
5098
5680
|
type: "button",
|
|
@@ -5102,11 +5684,11 @@ var ImageEditor = ({
|
|
|
5102
5684
|
children: "-"
|
|
5103
5685
|
}
|
|
5104
5686
|
),
|
|
5105
|
-
/* @__PURE__ */ (0,
|
|
5687
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
|
|
5106
5688
|
Math.round(state.zoom * 100),
|
|
5107
5689
|
"%"
|
|
5108
5690
|
] }),
|
|
5109
|
-
/* @__PURE__ */ (0,
|
|
5691
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5110
5692
|
"button",
|
|
5111
5693
|
{
|
|
5112
5694
|
type: "button",
|
|
@@ -5116,8 +5698,8 @@ var ImageEditor = ({
|
|
|
5116
5698
|
children: "+"
|
|
5117
5699
|
}
|
|
5118
5700
|
),
|
|
5119
|
-
/* @__PURE__ */ (0,
|
|
5120
|
-
/* @__PURE__ */ (0,
|
|
5701
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
5702
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5121
5703
|
"button",
|
|
5122
5704
|
{
|
|
5123
5705
|
type: "button",
|
|
@@ -5128,7 +5710,7 @@ var ImageEditor = ({
|
|
|
5128
5710
|
children: "Hold Compare"
|
|
5129
5711
|
}
|
|
5130
5712
|
),
|
|
5131
|
-
/* @__PURE__ */ (0,
|
|
5713
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5132
5714
|
"button",
|
|
5133
5715
|
{
|
|
5134
5716
|
type: "button",
|
|
@@ -5139,13 +5721,13 @@ var ImageEditor = ({
|
|
|
5139
5721
|
)
|
|
5140
5722
|
] })
|
|
5141
5723
|
] }),
|
|
5142
|
-
/* @__PURE__ */ (0,
|
|
5143
|
-
/* @__PURE__ */ (0,
|
|
5724
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
|
|
5725
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5144
5726
|
"div",
|
|
5145
5727
|
{
|
|
5146
5728
|
ref: containerRef,
|
|
5147
5729
|
className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
|
|
5148
|
-
children: /* @__PURE__ */ (0,
|
|
5730
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5149
5731
|
"canvas",
|
|
5150
5732
|
{
|
|
5151
5733
|
ref: canvasRef,
|
|
@@ -5153,16 +5735,21 @@ var ImageEditor = ({
|
|
|
5153
5735
|
onMouseMove: handleMouseMove,
|
|
5154
5736
|
onMouseUp: handleMouseUp,
|
|
5155
5737
|
onMouseLeave: handleMouseUp,
|
|
5156
|
-
|
|
5738
|
+
onPointerDown: handlePaintPointerDown,
|
|
5739
|
+
onPointerMove: handlePaintPointerMove,
|
|
5740
|
+
onPointerUp: handlePaintPointerUp,
|
|
5741
|
+
onPointerCancel: () => paintGestureRef.current?.cancel(),
|
|
5742
|
+
"data-testid": "image-editor-canvas",
|
|
5743
|
+
className: `absolute inset-0 w-full h-full block ${activeTab === "paint" ? "touch-none cursor-crosshair" : ""}`
|
|
5157
5744
|
}
|
|
5158
5745
|
)
|
|
5159
5746
|
}
|
|
5160
5747
|
),
|
|
5161
|
-
/* @__PURE__ */ (0,
|
|
5162
|
-
activeTab === "crop" && /* @__PURE__ */ (0,
|
|
5163
|
-
/* @__PURE__ */ (0,
|
|
5164
|
-
/* @__PURE__ */ (0,
|
|
5165
|
-
/* @__PURE__ */ (0,
|
|
5748
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "w-full md:w-80 bg-slate-900/90 border-t md:border-t-0 md:border-l border-slate-800 p-4 overflow-y-auto h-auto md:h-full md:max-h-[560px]", children: [
|
|
5749
|
+
activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
5750
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
|
|
5751
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
|
|
5752
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5166
5753
|
"button",
|
|
5167
5754
|
{
|
|
5168
5755
|
type: "button",
|
|
@@ -5174,7 +5761,7 @@ var ImageEditor = ({
|
|
|
5174
5761
|
children: "Freeform"
|
|
5175
5762
|
}
|
|
5176
5763
|
),
|
|
5177
|
-
/* @__PURE__ */ (0,
|
|
5764
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5178
5765
|
"button",
|
|
5179
5766
|
{
|
|
5180
5767
|
type: "button",
|
|
@@ -5186,7 +5773,7 @@ var ImageEditor = ({
|
|
|
5186
5773
|
children: "1:1 Square"
|
|
5187
5774
|
}
|
|
5188
5775
|
),
|
|
5189
|
-
/* @__PURE__ */ (0,
|
|
5776
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5190
5777
|
"button",
|
|
5191
5778
|
{
|
|
5192
5779
|
type: "button",
|
|
@@ -5198,7 +5785,7 @@ var ImageEditor = ({
|
|
|
5198
5785
|
children: "4:3 Standard"
|
|
5199
5786
|
}
|
|
5200
5787
|
),
|
|
5201
|
-
/* @__PURE__ */ (0,
|
|
5788
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5202
5789
|
"button",
|
|
5203
5790
|
{
|
|
5204
5791
|
type: "button",
|
|
@@ -5210,7 +5797,7 @@ var ImageEditor = ({
|
|
|
5210
5797
|
children: "16:9 Wide"
|
|
5211
5798
|
}
|
|
5212
5799
|
),
|
|
5213
|
-
/* @__PURE__ */ (0,
|
|
5800
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5214
5801
|
"button",
|
|
5215
5802
|
{
|
|
5216
5803
|
type: "button",
|
|
@@ -5222,7 +5809,7 @@ var ImageEditor = ({
|
|
|
5222
5809
|
children: "3:2 Photo"
|
|
5223
5810
|
}
|
|
5224
5811
|
),
|
|
5225
|
-
/* @__PURE__ */ (0,
|
|
5812
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5226
5813
|
"button",
|
|
5227
5814
|
{
|
|
5228
5815
|
type: "button",
|
|
@@ -5235,10 +5822,10 @@ var ImageEditor = ({
|
|
|
5235
5822
|
}
|
|
5236
5823
|
)
|
|
5237
5824
|
] }),
|
|
5238
|
-
/* @__PURE__ */ (0,
|
|
5239
|
-
/* @__PURE__ */ (0,
|
|
5240
|
-
/* @__PURE__ */ (0,
|
|
5241
|
-
/* @__PURE__ */ (0,
|
|
5825
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
5826
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
|
|
5827
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
5828
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5242
5829
|
"button",
|
|
5243
5830
|
{
|
|
5244
5831
|
type: "button",
|
|
@@ -5247,7 +5834,7 @@ var ImageEditor = ({
|
|
|
5247
5834
|
children: "Rotate -90\xB0"
|
|
5248
5835
|
}
|
|
5249
5836
|
),
|
|
5250
|
-
/* @__PURE__ */ (0,
|
|
5837
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5251
5838
|
"button",
|
|
5252
5839
|
{
|
|
5253
5840
|
type: "button",
|
|
@@ -5256,7 +5843,7 @@ var ImageEditor = ({
|
|
|
5256
5843
|
children: "Rotate +90\xB0"
|
|
5257
5844
|
}
|
|
5258
5845
|
),
|
|
5259
|
-
/* @__PURE__ */ (0,
|
|
5846
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5260
5847
|
"button",
|
|
5261
5848
|
{
|
|
5262
5849
|
type: "button",
|
|
@@ -5265,7 +5852,7 @@ var ImageEditor = ({
|
|
|
5265
5852
|
children: "Flip Horizontal"
|
|
5266
5853
|
}
|
|
5267
5854
|
),
|
|
5268
|
-
/* @__PURE__ */ (0,
|
|
5855
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5269
5856
|
"button",
|
|
5270
5857
|
{
|
|
5271
5858
|
type: "button",
|
|
@@ -5276,10 +5863,10 @@ var ImageEditor = ({
|
|
|
5276
5863
|
)
|
|
5277
5864
|
] })
|
|
5278
5865
|
] }),
|
|
5279
|
-
activeTab === "adjust" && /* @__PURE__ */ (0,
|
|
5280
|
-
/* @__PURE__ */ (0,
|
|
5281
|
-
/* @__PURE__ */ (0,
|
|
5282
|
-
/* @__PURE__ */ (0,
|
|
5866
|
+
activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
5867
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
5868
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
|
|
5869
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5283
5870
|
"button",
|
|
5284
5871
|
{
|
|
5285
5872
|
type: "button",
|
|
@@ -5289,25 +5876,25 @@ var ImageEditor = ({
|
|
|
5289
5876
|
}
|
|
5290
5877
|
)
|
|
5291
5878
|
] }),
|
|
5292
|
-
/* @__PURE__ */ (0,
|
|
5293
|
-
|
|
5294
|
-
/* @__PURE__ */ (0,
|
|
5879
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Histogram, { histogram: editor.histogram }),
|
|
5880
|
+
import_image_editor10.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react42.default.Fragment, { children: [
|
|
5881
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5295
5882
|
ControlSlider,
|
|
5296
5883
|
{
|
|
5297
5884
|
spec,
|
|
5298
|
-
value: (0,
|
|
5885
|
+
value: (0, import_image_editor10.readAdjustmentControls)(state.adjustments)[spec.id],
|
|
5299
5886
|
disabled: spec.requiresProcess !== void 0 && legacyProcess,
|
|
5300
5887
|
onChange: (v) => editor.setAdjustments({ [spec.id]: v })
|
|
5301
5888
|
}
|
|
5302
5889
|
),
|
|
5303
|
-
spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0,
|
|
5890
|
+
spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
5304
5891
|
"div",
|
|
5305
5892
|
{
|
|
5306
5893
|
className: "flex items-center justify-between gap-2 rounded border border-amber-500/30 bg-amber-500/10 px-2 py-1.5 text-[10px] text-amber-200",
|
|
5307
5894
|
"data-testid": "image-editor-process-notice",
|
|
5308
5895
|
children: [
|
|
5309
|
-
/* @__PURE__ */ (0,
|
|
5310
|
-
/* @__PURE__ */ (0,
|
|
5896
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
|
|
5897
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5311
5898
|
"button",
|
|
5312
5899
|
{
|
|
5313
5900
|
type: "button",
|
|
@@ -5320,7 +5907,7 @@ var ImageEditor = ({
|
|
|
5320
5907
|
}
|
|
5321
5908
|
)
|
|
5322
5909
|
] }, spec.id)),
|
|
5323
|
-
/* @__PURE__ */ (0,
|
|
5910
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5324
5911
|
AdjustmentLayersPanel,
|
|
5325
5912
|
{
|
|
5326
5913
|
controller,
|
|
@@ -5329,9 +5916,19 @@ var ImageEditor = ({
|
|
|
5329
5916
|
}
|
|
5330
5917
|
) })
|
|
5331
5918
|
] }),
|
|
5332
|
-
activeTab === "
|
|
5333
|
-
/* @__PURE__ */ (0,
|
|
5334
|
-
/* @__PURE__ */ (0,
|
|
5919
|
+
activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
5920
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
|
|
5921
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LayersPanel, { controller })
|
|
5922
|
+
] }),
|
|
5923
|
+
activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
5924
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
|
|
5925
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(BrushOptionsBar, { controller }),
|
|
5926
|
+
paintError && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
|
|
5927
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LayersPanel, { controller }) })
|
|
5928
|
+
] }),
|
|
5929
|
+
activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
5930
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
|
|
5931
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5335
5932
|
"button",
|
|
5336
5933
|
{
|
|
5337
5934
|
type: "button",
|
|
@@ -5341,9 +5938,9 @@ var ImageEditor = ({
|
|
|
5341
5938
|
},
|
|
5342
5939
|
t
|
|
5343
5940
|
)) }),
|
|
5344
|
-
/* @__PURE__ */ (0,
|
|
5345
|
-
/* @__PURE__ */ (0,
|
|
5346
|
-
/* @__PURE__ */ (0,
|
|
5941
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
5942
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("label", { className: "text-slate-400", children: "Color:" }),
|
|
5943
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5347
5944
|
"input",
|
|
5348
5945
|
{
|
|
5349
5946
|
type: "color",
|
|
@@ -5352,15 +5949,15 @@ var ImageEditor = ({
|
|
|
5352
5949
|
className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
|
|
5353
5950
|
}
|
|
5354
5951
|
),
|
|
5355
|
-
/* @__PURE__ */ (0,
|
|
5356
|
-
/* @__PURE__ */ (0,
|
|
5357
|
-
/* @__PURE__ */ (0,
|
|
5358
|
-
/* @__PURE__ */ (0,
|
|
5952
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex-1 ml-2", children: [
|
|
5953
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
|
|
5954
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Width:" }),
|
|
5955
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
|
|
5359
5956
|
strokeWidth,
|
|
5360
5957
|
"px"
|
|
5361
5958
|
] })
|
|
5362
5959
|
] }),
|
|
5363
|
-
/* @__PURE__ */ (0,
|
|
5960
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5364
5961
|
"input",
|
|
5365
5962
|
{
|
|
5366
5963
|
type: "range",
|
|
@@ -5373,10 +5970,10 @@ var ImageEditor = ({
|
|
|
5373
5970
|
)
|
|
5374
5971
|
] })
|
|
5375
5972
|
] }),
|
|
5376
|
-
/* @__PURE__ */ (0,
|
|
5377
|
-
/* @__PURE__ */ (0,
|
|
5378
|
-
/* @__PURE__ */ (0,
|
|
5379
|
-
/* @__PURE__ */ (0,
|
|
5973
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
5974
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
|
|
5975
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-2", children: [
|
|
5976
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5380
5977
|
"input",
|
|
5381
5978
|
{
|
|
5382
5979
|
type: "text",
|
|
@@ -5387,7 +5984,7 @@ var ImageEditor = ({
|
|
|
5387
5984
|
className: "flex-1 bg-slate-950 border border-slate-700 rounded-lg px-2.5 py-1.5 text-xs text-slate-100 placeholder-slate-500 focus:outline-none focus:border-indigo-500"
|
|
5388
5985
|
}
|
|
5389
5986
|
),
|
|
5390
|
-
/* @__PURE__ */ (0,
|
|
5987
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5391
5988
|
"button",
|
|
5392
5989
|
{
|
|
5393
5990
|
type: "button",
|
|
@@ -5397,14 +5994,14 @@ var ImageEditor = ({
|
|
|
5397
5994
|
}
|
|
5398
5995
|
)
|
|
5399
5996
|
] }),
|
|
5400
|
-
/* @__PURE__ */ (0,
|
|
5401
|
-
/* @__PURE__ */ (0,
|
|
5402
|
-
/* @__PURE__ */ (0,
|
|
5997
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
|
|
5998
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Font Size:" }),
|
|
5999
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
|
|
5403
6000
|
fontSize,
|
|
5404
6001
|
"px"
|
|
5405
6002
|
] })
|
|
5406
6003
|
] }),
|
|
5407
|
-
/* @__PURE__ */ (0,
|
|
6004
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5408
6005
|
"input",
|
|
5409
6006
|
{
|
|
5410
6007
|
type: "range",
|
|
@@ -5415,14 +6012,14 @@ var ImageEditor = ({
|
|
|
5415
6012
|
className: "w-full accent-indigo-500"
|
|
5416
6013
|
}
|
|
5417
6014
|
),
|
|
5418
|
-
/* @__PURE__ */ (0,
|
|
5419
|
-
/* @__PURE__ */ (0,
|
|
5420
|
-
/* @__PURE__ */ (0,
|
|
6015
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
6016
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
6017
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "text-slate-400", children: [
|
|
5421
6018
|
"Layers (",
|
|
5422
6019
|
state.annotations.length,
|
|
5423
6020
|
")"
|
|
5424
6021
|
] }),
|
|
5425
|
-
state.selectedAnnotationId && /* @__PURE__ */ (0,
|
|
6022
|
+
state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5426
6023
|
"button",
|
|
5427
6024
|
{
|
|
5428
6025
|
type: "button",
|
|
@@ -5431,7 +6028,7 @@ var ImageEditor = ({
|
|
|
5431
6028
|
children: "Delete Selected"
|
|
5432
6029
|
}
|
|
5433
6030
|
),
|
|
5434
|
-
state.annotations.length > 0 && /* @__PURE__ */ (0,
|
|
6031
|
+
state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5435
6032
|
"button",
|
|
5436
6033
|
{
|
|
5437
6034
|
type: "button",
|
|
@@ -5442,10 +6039,10 @@ var ImageEditor = ({
|
|
|
5442
6039
|
)
|
|
5443
6040
|
] })
|
|
5444
6041
|
] }),
|
|
5445
|
-
activeTab === "depth" && /* @__PURE__ */ (0,
|
|
5446
|
-
/* @__PURE__ */ (0,
|
|
5447
|
-
/* @__PURE__ */ (0,
|
|
5448
|
-
/* @__PURE__ */ (0,
|
|
6042
|
+
activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
6043
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
6044
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
|
|
6045
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5449
6046
|
"button",
|
|
5450
6047
|
{
|
|
5451
6048
|
type: "button",
|
|
@@ -5455,8 +6052,8 @@ var ImageEditor = ({
|
|
|
5455
6052
|
}
|
|
5456
6053
|
)
|
|
5457
6054
|
] }),
|
|
5458
|
-
/* @__PURE__ */ (0,
|
|
5459
|
-
/* @__PURE__ */ (0,
|
|
6055
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
|
|
6056
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5460
6057
|
"input",
|
|
5461
6058
|
{
|
|
5462
6059
|
type: "checkbox",
|
|
@@ -5465,12 +6062,12 @@ var ImageEditor = ({
|
|
|
5465
6062
|
className: "rounded accent-indigo-500"
|
|
5466
6063
|
}
|
|
5467
6064
|
),
|
|
5468
|
-
/* @__PURE__ */ (0,
|
|
6065
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Enable Depth / Alpha Mask" })
|
|
5469
6066
|
] }),
|
|
5470
|
-
state.depthMask.enabled && /* @__PURE__ */ (0,
|
|
5471
|
-
/* @__PURE__ */ (0,
|
|
5472
|
-
/* @__PURE__ */ (0,
|
|
5473
|
-
/* @__PURE__ */ (0,
|
|
6067
|
+
state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
6068
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
|
|
6069
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
|
|
6070
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5474
6071
|
"input",
|
|
5475
6072
|
{
|
|
5476
6073
|
type: "text",
|
|
@@ -5481,8 +6078,8 @@ var ImageEditor = ({
|
|
|
5481
6078
|
}
|
|
5482
6079
|
)
|
|
5483
6080
|
] }),
|
|
5484
|
-
/* @__PURE__ */ (0,
|
|
5485
|
-
/* @__PURE__ */ (0,
|
|
6081
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-2", children: [
|
|
6082
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5486
6083
|
"button",
|
|
5487
6084
|
{
|
|
5488
6085
|
type: "button",
|
|
@@ -5491,7 +6088,7 @@ var ImageEditor = ({
|
|
|
5491
6088
|
children: "Threshold Mode"
|
|
5492
6089
|
}
|
|
5493
6090
|
),
|
|
5494
|
-
/* @__PURE__ */ (0,
|
|
6091
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5495
6092
|
"button",
|
|
5496
6093
|
{
|
|
5497
6094
|
type: "button",
|
|
@@ -5501,12 +6098,12 @@ var ImageEditor = ({
|
|
|
5501
6098
|
}
|
|
5502
6099
|
)
|
|
5503
6100
|
] }),
|
|
5504
|
-
/* @__PURE__ */ (0,
|
|
5505
|
-
/* @__PURE__ */ (0,
|
|
5506
|
-
/* @__PURE__ */ (0,
|
|
5507
|
-
/* @__PURE__ */ (0,
|
|
6101
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
|
|
6102
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
6103
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Depth Start (Lower):" }),
|
|
6104
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
|
|
5508
6105
|
] }),
|
|
5509
|
-
/* @__PURE__ */ (0,
|
|
6106
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5510
6107
|
"input",
|
|
5511
6108
|
{
|
|
5512
6109
|
type: "range",
|
|
@@ -5520,12 +6117,12 @@ var ImageEditor = ({
|
|
|
5520
6117
|
}
|
|
5521
6118
|
)
|
|
5522
6119
|
] }),
|
|
5523
|
-
/* @__PURE__ */ (0,
|
|
5524
|
-
/* @__PURE__ */ (0,
|
|
5525
|
-
/* @__PURE__ */ (0,
|
|
5526
|
-
/* @__PURE__ */ (0,
|
|
6120
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
|
|
6121
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
6122
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Depth Stop (Upper):" }),
|
|
6123
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
|
|
5527
6124
|
] }),
|
|
5528
|
-
/* @__PURE__ */ (0,
|
|
6125
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5529
6126
|
"input",
|
|
5530
6127
|
{
|
|
5531
6128
|
type: "range",
|
|
@@ -5539,12 +6136,12 @@ var ImageEditor = ({
|
|
|
5539
6136
|
}
|
|
5540
6137
|
)
|
|
5541
6138
|
] }),
|
|
5542
|
-
/* @__PURE__ */ (0,
|
|
5543
|
-
/* @__PURE__ */ (0,
|
|
5544
|
-
/* @__PURE__ */ (0,
|
|
5545
|
-
/* @__PURE__ */ (0,
|
|
6139
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
|
|
6140
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
6141
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Softness:" }),
|
|
6142
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
|
|
5546
6143
|
] }),
|
|
5547
|
-
/* @__PURE__ */ (0,
|
|
6144
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5548
6145
|
"input",
|
|
5549
6146
|
{
|
|
5550
6147
|
type: "range",
|
|
@@ -5556,8 +6153,8 @@ var ImageEditor = ({
|
|
|
5556
6153
|
}
|
|
5557
6154
|
)
|
|
5558
6155
|
] }),
|
|
5559
|
-
/* @__PURE__ */ (0,
|
|
5560
|
-
/* @__PURE__ */ (0,
|
|
6156
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
|
|
6157
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5561
6158
|
"input",
|
|
5562
6159
|
{
|
|
5563
6160
|
type: "checkbox",
|
|
@@ -5566,12 +6163,12 @@ var ImageEditor = ({
|
|
|
5566
6163
|
className: "rounded accent-indigo-500"
|
|
5567
6164
|
}
|
|
5568
6165
|
),
|
|
5569
|
-
/* @__PURE__ */ (0,
|
|
6166
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Invert Mask" })
|
|
5570
6167
|
] })
|
|
5571
6168
|
] })
|
|
5572
6169
|
] }),
|
|
5573
|
-
activeTab === "select" && /* @__PURE__ */ (0,
|
|
5574
|
-
/* @__PURE__ */ (0,
|
|
6170
|
+
activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
6171
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5575
6172
|
SelectionOptionsBar,
|
|
5576
6173
|
{
|
|
5577
6174
|
controller,
|
|
@@ -5581,51 +6178,68 @@ var ImageEditor = ({
|
|
|
5581
6178
|
quickMask: Boolean(state.quickMask)
|
|
5582
6179
|
}
|
|
5583
6180
|
),
|
|
5584
|
-
selectionError && /* @__PURE__ */ (0,
|
|
5585
|
-
/* @__PURE__ */ (0,
|
|
6181
|
+
selectionError && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
|
|
6182
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
|
|
5586
6183
|
] }),
|
|
5587
|
-
activeTab === "ai" && /* @__PURE__ */ (0,
|
|
5588
|
-
/* @__PURE__ */ (0,
|
|
5589
|
-
/* @__PURE__ */ (0,
|
|
5590
|
-
|
|
5591
|
-
|
|
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
|
+
] }),
|
|
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: [
|
|
6203
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
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: [
|
|
6205
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("svg", { className: "w-3.5 h-3.5 text-indigo-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "M6 3v12M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" }) }),
|
|
5592
6206
|
"Background Removal"
|
|
5593
6207
|
] }),
|
|
5594
|
-
isRemovingBg && /* @__PURE__ */ (0,
|
|
6208
|
+
isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-indigo-900/60 text-indigo-300 animate-pulse", children: "Removing..." })
|
|
5595
6209
|
] }),
|
|
5596
|
-
/* @__PURE__ */ (0,
|
|
5597
|
-
/* @__PURE__ */ (0,
|
|
6210
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
|
|
6211
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5598
6212
|
"button",
|
|
5599
6213
|
{
|
|
5600
6214
|
type: "button",
|
|
5601
6215
|
onClick: handleRemoveBackground,
|
|
5602
6216
|
disabled: isRemovingBg || isInpainting,
|
|
5603
6217
|
className: "mt-1 px-3 py-2 rounded-lg bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white font-medium shadow transition-colors flex items-center justify-center gap-2",
|
|
5604
|
-
children: isRemovingBg ? /* @__PURE__ */ (0,
|
|
5605
|
-
/* @__PURE__ */ (0,
|
|
6218
|
+
children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
6219
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
5606
6220
|
"Removing Background..."
|
|
5607
|
-
] }) : /* @__PURE__ */ (0,
|
|
5608
|
-
/* @__PURE__ */ (0,
|
|
6221
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
6222
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
|
|
5609
6223
|
"Remove Background"
|
|
5610
6224
|
] })
|
|
5611
6225
|
}
|
|
5612
6226
|
)
|
|
5613
6227
|
] }),
|
|
5614
|
-
/* @__PURE__ */ (0,
|
|
5615
|
-
/* @__PURE__ */ (0,
|
|
5616
|
-
/* @__PURE__ */ (0,
|
|
5617
|
-
/* @__PURE__ */ (0,
|
|
5618
|
-
/* @__PURE__ */ (0,
|
|
5619
|
-
/* @__PURE__ */ (0,
|
|
6228
|
+
/* @__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: [
|
|
6229
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
6230
|
+
/* @__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: [
|
|
6231
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
6232
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "m21.64 3.64-1.28-1.28a1.2 1.2 0 0 0-1.7 0l-9.72 9.72-1.94 4.86 4.86-1.94 9.72-9.72a1.2 1.2 0 0 0 .06-1.64z" }),
|
|
6233
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "m14 7 3 3" })
|
|
5620
6234
|
] }),
|
|
5621
6235
|
"Generative Inpainting"
|
|
5622
6236
|
] }),
|
|
5623
|
-
isInpainting && /* @__PURE__ */ (0,
|
|
6237
|
+
isInpainting && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-purple-900/60 text-purple-300 animate-pulse", children: "Inpainting..." })
|
|
5624
6238
|
] }),
|
|
5625
|
-
/* @__PURE__ */ (0,
|
|
5626
|
-
/* @__PURE__ */ (0,
|
|
5627
|
-
/* @__PURE__ */ (0,
|
|
5628
|
-
/* @__PURE__ */ (0,
|
|
6239
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
|
|
6240
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
6241
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
|
|
6242
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5629
6243
|
"textarea",
|
|
5630
6244
|
{
|
|
5631
6245
|
id: "ai-inpaint-prompt-react",
|
|
@@ -5637,10 +6251,10 @@ var ImageEditor = ({
|
|
|
5637
6251
|
}
|
|
5638
6252
|
)
|
|
5639
6253
|
] }),
|
|
5640
|
-
/* @__PURE__ */ (0,
|
|
5641
|
-
/* @__PURE__ */ (0,
|
|
5642
|
-
/* @__PURE__ */ (0,
|
|
5643
|
-
/* @__PURE__ */ (0,
|
|
6254
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
6255
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
|
|
6256
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
|
|
6257
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
5644
6258
|
"button",
|
|
5645
6259
|
{
|
|
5646
6260
|
type: "button",
|
|
@@ -5653,7 +6267,7 @@ var ImageEditor = ({
|
|
|
5653
6267
|
]
|
|
5654
6268
|
}
|
|
5655
6269
|
),
|
|
5656
|
-
/* @__PURE__ */ (0,
|
|
6270
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
5657
6271
|
"button",
|
|
5658
6272
|
{
|
|
5659
6273
|
type: "button",
|
|
@@ -5668,25 +6282,25 @@ var ImageEditor = ({
|
|
|
5668
6282
|
)
|
|
5669
6283
|
] })
|
|
5670
6284
|
] }),
|
|
5671
|
-
/* @__PURE__ */ (0,
|
|
6285
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5672
6286
|
"button",
|
|
5673
6287
|
{
|
|
5674
6288
|
type: "button",
|
|
5675
6289
|
onClick: handleInpaint,
|
|
5676
6290
|
disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
|
|
5677
6291
|
className: "mt-1 px-3 py-2 rounded-lg bg-purple-600 hover:bg-purple-500 disabled:opacity-50 text-white font-medium shadow transition-colors flex items-center justify-center gap-2",
|
|
5678
|
-
children: isInpainting ? /* @__PURE__ */ (0,
|
|
5679
|
-
/* @__PURE__ */ (0,
|
|
6292
|
+
children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
6293
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
5680
6294
|
"Generating Inpaint..."
|
|
5681
|
-
] }) : /* @__PURE__ */ (0,
|
|
5682
|
-
/* @__PURE__ */ (0,
|
|
6295
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
6296
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
|
|
5683
6297
|
"Apply Inpainting"
|
|
5684
6298
|
] })
|
|
5685
6299
|
}
|
|
5686
6300
|
)
|
|
5687
6301
|
] }),
|
|
5688
|
-
aiError && /* @__PURE__ */ (0,
|
|
5689
|
-
aiSuccess && /* @__PURE__ */ (0,
|
|
6302
|
+
aiError && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
|
|
6303
|
+
aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
|
|
5690
6304
|
] })
|
|
5691
6305
|
] })
|
|
5692
6306
|
] })
|
|
@@ -5696,7 +6310,7 @@ var ImageEditor = ({
|
|
|
5696
6310
|
};
|
|
5697
6311
|
|
|
5698
6312
|
// src/review/useReview.ts
|
|
5699
|
-
var
|
|
6313
|
+
var import_react43 = require("react");
|
|
5700
6314
|
var import_editor12 = require("@pixerate/editor");
|
|
5701
6315
|
var EMPTY_COMMENTS = Object.freeze({
|
|
5702
6316
|
threads: [],
|
|
@@ -5715,23 +6329,23 @@ function isCommentStore(value) {
|
|
|
5715
6329
|
}
|
|
5716
6330
|
function useComments(source) {
|
|
5717
6331
|
const store = isCommentStore(source) ? source : (0, import_editor12.getCommentStore)(source);
|
|
5718
|
-
const subscribe = (0,
|
|
6332
|
+
const subscribe = (0, import_react43.useCallback)(
|
|
5719
6333
|
(onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
|
|
5720
6334
|
[store]
|
|
5721
6335
|
);
|
|
5722
6336
|
const getSnapshot = () => store?.getSnapshot() ?? EMPTY_COMMENTS;
|
|
5723
|
-
const snapshot = (0,
|
|
5724
|
-
return (0,
|
|
6337
|
+
const snapshot = (0, import_react43.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
6338
|
+
return (0, import_react43.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
|
|
5725
6339
|
}
|
|
5726
6340
|
function useTrackChanges(editor) {
|
|
5727
6341
|
const store = (0, import_editor12.getTrackChangesStore)(editor ?? null);
|
|
5728
|
-
const subscribe = (0,
|
|
6342
|
+
const subscribe = (0, import_react43.useCallback)(
|
|
5729
6343
|
(onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
|
|
5730
6344
|
[store]
|
|
5731
6345
|
);
|
|
5732
6346
|
const getSnapshot = () => store?.getSnapshot() ?? EMPTY_TRACK_CHANGES;
|
|
5733
|
-
const snapshot = (0,
|
|
5734
|
-
return (0,
|
|
6347
|
+
const snapshot = (0, import_react43.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
6348
|
+
return (0, import_react43.useMemo)(() => {
|
|
5735
6349
|
const run = (fn) => () => {
|
|
5736
6350
|
if (editor && !editor.isDestroyed) fn(editor);
|
|
5737
6351
|
};
|
|
@@ -5754,9 +6368,9 @@ function useTrackChanges(editor) {
|
|
|
5754
6368
|
}
|
|
5755
6369
|
|
|
5756
6370
|
// src/review/CommentsPanel.tsx
|
|
5757
|
-
var
|
|
6371
|
+
var import_react44 = require("react");
|
|
5758
6372
|
var import_editor13 = require("@pixerate/editor");
|
|
5759
|
-
var
|
|
6373
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
5760
6374
|
var buttonClass2 = "rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50";
|
|
5761
6375
|
var primaryButtonClass = "rounded px-2 py-1 text-xs bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-50";
|
|
5762
6376
|
var textareaClass = "w-full resize-y rounded-md border border-input bg-background p-2 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary";
|
|
@@ -5770,18 +6384,18 @@ var CommentsPanel = ({
|
|
|
5770
6384
|
emptyMessage = "No comments yet. Select text and add a comment."
|
|
5771
6385
|
}) => {
|
|
5772
6386
|
const { threads, activeThreadId, store } = useComments(storeProp ?? editor);
|
|
5773
|
-
const [showResolved, setShowResolved] = (0,
|
|
6387
|
+
const [showResolved, setShowResolved] = (0, import_react44.useState)(showResolvedInitial);
|
|
5774
6388
|
const author = authorProp ?? (0, import_editor13.getCommentAuthor)(editor) ?? { id: "anonymous", name: "Anonymous" };
|
|
5775
6389
|
const visible = threads.filter((t) => showResolved || !t.resolved);
|
|
5776
6390
|
const resolvedCount = threads.filter((t) => t.resolved).length;
|
|
5777
|
-
return /* @__PURE__ */ (0,
|
|
5778
|
-
/* @__PURE__ */ (0,
|
|
5779
|
-
/* @__PURE__ */ (0,
|
|
6391
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("aside", { className, "aria-label": "Comments", children: [
|
|
6392
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
|
|
6393
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "text-xs font-medium text-muted-foreground", children: [
|
|
5780
6394
|
threads.length - resolvedCount,
|
|
5781
6395
|
" open",
|
|
5782
6396
|
resolvedCount > 0 ? ` \xB7 ${resolvedCount} resolved` : ""
|
|
5783
6397
|
] }),
|
|
5784
|
-
resolvedCount > 0 && /* @__PURE__ */ (0,
|
|
6398
|
+
resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
5785
6399
|
"button",
|
|
5786
6400
|
{
|
|
5787
6401
|
type: "button",
|
|
@@ -5792,7 +6406,7 @@ var CommentsPanel = ({
|
|
|
5792
6406
|
}
|
|
5793
6407
|
)
|
|
5794
6408
|
] }),
|
|
5795
|
-
visible.length === 0 ? /* @__PURE__ */ (0,
|
|
6409
|
+
visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("ul", { className: "flex flex-col gap-2", role: "list", children: visible.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
5796
6410
|
CommentThreadCard,
|
|
5797
6411
|
{
|
|
5798
6412
|
thread,
|
|
@@ -5814,7 +6428,7 @@ var CommentThreadCard = ({
|
|
|
5814
6428
|
author,
|
|
5815
6429
|
formatTime
|
|
5816
6430
|
}) => {
|
|
5817
|
-
const [draft, setDraft] = (0,
|
|
6431
|
+
const [draft, setDraft] = (0, import_react44.useState)("");
|
|
5818
6432
|
const isDraft = thread.body === "";
|
|
5819
6433
|
const quote = thread.anchor?.quote ?? thread.lastQuote ?? "";
|
|
5820
6434
|
const live = editor && !editor.isDestroyed ? editor : null;
|
|
@@ -5840,7 +6454,7 @@ var CommentThreadCard = ({
|
|
|
5840
6454
|
setDraft("");
|
|
5841
6455
|
};
|
|
5842
6456
|
const stop = (e) => e.stopPropagation();
|
|
5843
|
-
return /* @__PURE__ */ (0,
|
|
6457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
5844
6458
|
"li",
|
|
5845
6459
|
{
|
|
5846
6460
|
className: `flex flex-col gap-2 rounded-md border bg-background p-3 cursor-pointer ${active ? "border-primary ring-1 ring-primary" : "border-border"} ${thread.resolved ? "opacity-70" : ""}`,
|
|
@@ -5856,24 +6470,24 @@ var CommentThreadCard = ({
|
|
|
5856
6470
|
}
|
|
5857
6471
|
},
|
|
5858
6472
|
children: [
|
|
5859
|
-
/* @__PURE__ */ (0,
|
|
5860
|
-
/* @__PURE__ */ (0,
|
|
5861
|
-
/* @__PURE__ */ (0,
|
|
6473
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [
|
|
6474
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-medium", children: thread.author.name }),
|
|
6475
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
|
|
5862
6476
|
] }),
|
|
5863
|
-
quote && /* @__PURE__ */ (0,
|
|
5864
|
-
thread.orphaned && /* @__PURE__ */ (0,
|
|
5865
|
-
thread.resolved && /* @__PURE__ */ (0,
|
|
5866
|
-
!isDraft && /* @__PURE__ */ (0,
|
|
5867
|
-
thread.replies.length > 0 && /* @__PURE__ */ (0,
|
|
5868
|
-
/* @__PURE__ */ (0,
|
|
5869
|
-
/* @__PURE__ */ (0,
|
|
6477
|
+
quote && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("blockquote", { className: "border-l-2 border-border pl-2 text-xs text-muted-foreground line-clamp-2", children: quote }),
|
|
6478
|
+
thread.orphaned && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
|
|
6479
|
+
thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
|
|
6480
|
+
!isDraft && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
|
|
6481
|
+
thread.replies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("ul", { className: "flex flex-col gap-2 border-l border-border pl-3", role: "list", children: thread.replies.map((reply) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("li", { className: "flex flex-col gap-0.5", "data-reply-id": reply.id, children: [
|
|
6482
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "text-xs", children: [
|
|
6483
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-medium", children: reply.author.name }),
|
|
5870
6484
|
" ",
|
|
5871
|
-
/* @__PURE__ */ (0,
|
|
6485
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
|
|
5872
6486
|
] }),
|
|
5873
|
-
/* @__PURE__ */ (0,
|
|
6487
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
|
|
5874
6488
|
] }, reply.id)) }),
|
|
5875
|
-
(active || isDraft) && !thread.resolved && /* @__PURE__ */ (0,
|
|
5876
|
-
/* @__PURE__ */ (0,
|
|
6489
|
+
(active || isDraft) && !thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-1", onClick: stop, children: [
|
|
6490
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
5877
6491
|
"textarea",
|
|
5878
6492
|
{
|
|
5879
6493
|
className: textareaClass,
|
|
@@ -5891,9 +6505,9 @@ var CommentThreadCard = ({
|
|
|
5891
6505
|
}
|
|
5892
6506
|
}
|
|
5893
6507
|
),
|
|
5894
|
-
/* @__PURE__ */ (0,
|
|
5895
|
-
isDraft && /* @__PURE__ */ (0,
|
|
5896
|
-
/* @__PURE__ */ (0,
|
|
6508
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex justify-end gap-1", children: [
|
|
6509
|
+
isDraft && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: buttonClass2, onClick: remove, children: "Cancel" }),
|
|
6510
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
5897
6511
|
"button",
|
|
5898
6512
|
{
|
|
5899
6513
|
type: "button",
|
|
@@ -5905,9 +6519,9 @@ var CommentThreadCard = ({
|
|
|
5905
6519
|
)
|
|
5906
6520
|
] })
|
|
5907
6521
|
] }),
|
|
5908
|
-
!isDraft && /* @__PURE__ */ (0,
|
|
5909
|
-
/* @__PURE__ */ (0,
|
|
5910
|
-
/* @__PURE__ */ (0,
|
|
6522
|
+
!isDraft && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex justify-end gap-1", onClick: stop, children: [
|
|
6523
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: buttonClass2, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
|
|
6524
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
5911
6525
|
"button",
|
|
5912
6526
|
{
|
|
5913
6527
|
type: "button",
|
|
@@ -5923,7 +6537,7 @@ var CommentThreadCard = ({
|
|
|
5923
6537
|
};
|
|
5924
6538
|
|
|
5925
6539
|
// src/review/ReviewToolbar.tsx
|
|
5926
|
-
var
|
|
6540
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
5927
6541
|
var defaultDescriptionClass = "max-w-[16rem] truncate px-1 text-xs text-muted-foreground";
|
|
5928
6542
|
var buttonClass3 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
|
|
5929
6543
|
var ReviewToolbar = ({
|
|
@@ -5936,8 +6550,8 @@ var ReviewToolbar = ({
|
|
|
5936
6550
|
const count = review.changes.length;
|
|
5937
6551
|
const current = review.currentChange;
|
|
5938
6552
|
const index = current ? review.changes.findIndex((c) => c.id === current.id) + 1 : 0;
|
|
5939
|
-
return /* @__PURE__ */ (0,
|
|
5940
|
-
/* @__PURE__ */ (0,
|
|
6553
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className, role: "toolbar", "aria-label": "Review", children: [
|
|
6554
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5941
6555
|
"button",
|
|
5942
6556
|
{
|
|
5943
6557
|
type: "button",
|
|
@@ -5948,8 +6562,8 @@ var ReviewToolbar = ({
|
|
|
5948
6562
|
children: review.enabled ? "Tracking on" : "Track changes"
|
|
5949
6563
|
}
|
|
5950
6564
|
),
|
|
5951
|
-
/* @__PURE__ */ (0,
|
|
5952
|
-
/* @__PURE__ */ (0,
|
|
6565
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
|
|
6566
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5953
6567
|
"button",
|
|
5954
6568
|
{
|
|
5955
6569
|
type: "button",
|
|
@@ -5960,8 +6574,8 @@ var ReviewToolbar = ({
|
|
|
5960
6574
|
children: "\u2039"
|
|
5961
6575
|
}
|
|
5962
6576
|
),
|
|
5963
|
-
/* @__PURE__ */ (0,
|
|
5964
|
-
/* @__PURE__ */ (0,
|
|
6577
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "min-w-[4rem] text-center text-xs text-muted-foreground", "aria-live": "polite", children: count === 0 ? "No changes" : current ? `${index} of ${count}` : `${count} changes` }),
|
|
6578
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5965
6579
|
"button",
|
|
5966
6580
|
{
|
|
5967
6581
|
type: "button",
|
|
@@ -5972,7 +6586,7 @@ var ReviewToolbar = ({
|
|
|
5972
6586
|
children: "\u203A"
|
|
5973
6587
|
}
|
|
5974
6588
|
),
|
|
5975
|
-
showDescription && current && /* @__PURE__ */ (0,
|
|
6589
|
+
showDescription && current && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
5976
6590
|
"span",
|
|
5977
6591
|
{
|
|
5978
6592
|
className: descriptionClassName,
|
|
@@ -5984,8 +6598,8 @@ var ReviewToolbar = ({
|
|
|
5984
6598
|
]
|
|
5985
6599
|
}
|
|
5986
6600
|
),
|
|
5987
|
-
/* @__PURE__ */ (0,
|
|
5988
|
-
/* @__PURE__ */ (0,
|
|
6601
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
|
|
6602
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5989
6603
|
"button",
|
|
5990
6604
|
{
|
|
5991
6605
|
type: "button",
|
|
@@ -5995,7 +6609,7 @@ var ReviewToolbar = ({
|
|
|
5995
6609
|
children: "Accept"
|
|
5996
6610
|
}
|
|
5997
6611
|
),
|
|
5998
|
-
/* @__PURE__ */ (0,
|
|
6612
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5999
6613
|
"button",
|
|
6000
6614
|
{
|
|
6001
6615
|
type: "button",
|
|
@@ -6005,18 +6619,18 @@ var ReviewToolbar = ({
|
|
|
6005
6619
|
children: "Reject"
|
|
6006
6620
|
}
|
|
6007
6621
|
),
|
|
6008
|
-
/* @__PURE__ */ (0,
|
|
6009
|
-
/* @__PURE__ */ (0,
|
|
6622
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
|
|
6623
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
|
|
6010
6624
|
] });
|
|
6011
6625
|
};
|
|
6012
6626
|
|
|
6013
6627
|
// src/review/CommentButton.tsx
|
|
6014
|
-
var
|
|
6628
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
6015
6629
|
var CommentButton = ({
|
|
6016
6630
|
editor,
|
|
6017
6631
|
className = "rounded px-2 py-1 text-xs text-popover-foreground hover:bg-muted",
|
|
6018
6632
|
children = "Comment"
|
|
6019
|
-
}) => /* @__PURE__ */ (0,
|
|
6633
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
6020
6634
|
"button",
|
|
6021
6635
|
{
|
|
6022
6636
|
type: "button",
|
|
@@ -6028,13 +6642,13 @@ var CommentButton = ({
|
|
|
6028
6642
|
);
|
|
6029
6643
|
|
|
6030
6644
|
// src/review/useDocumentCompare.ts
|
|
6031
|
-
var
|
|
6645
|
+
var import_react45 = require("react");
|
|
6032
6646
|
var import_editor14 = require("@pixerate/editor");
|
|
6033
6647
|
function useDocumentCompare(editor, options) {
|
|
6034
|
-
const [summary, setSummary] = (0,
|
|
6035
|
-
const defaults = (0,
|
|
6648
|
+
const [summary, setSummary] = (0, import_react45.useState)(null);
|
|
6649
|
+
const defaults = (0, import_react45.useRef)(options);
|
|
6036
6650
|
defaults.current = options;
|
|
6037
|
-
const compare = (0,
|
|
6651
|
+
const compare = (0, import_react45.useCallback)(
|
|
6038
6652
|
(original, revised, overrides) => {
|
|
6039
6653
|
if (!editor || editor.isDestroyed) return null;
|
|
6040
6654
|
const result = (0, import_editor14.applyDocumentComparison)(editor, original, revised, {
|
|
@@ -6046,13 +6660,13 @@ function useDocumentCompare(editor, options) {
|
|
|
6046
6660
|
},
|
|
6047
6661
|
[editor]
|
|
6048
6662
|
);
|
|
6049
|
-
const clear = (0,
|
|
6050
|
-
return (0,
|
|
6663
|
+
const clear = (0, import_react45.useCallback)(() => setSummary(null), []);
|
|
6664
|
+
return (0, import_react45.useMemo)(() => ({ summary, compare, clear }), [summary, compare, clear]);
|
|
6051
6665
|
}
|
|
6052
6666
|
|
|
6053
6667
|
// src/review/TrackedChangesList.tsx
|
|
6054
6668
|
var import_editor15 = require("@pixerate/editor");
|
|
6055
|
-
var
|
|
6669
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
6056
6670
|
var buttonClass4 = "rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted disabled:opacity-40";
|
|
6057
6671
|
var TrackedChangesList = ({
|
|
6058
6672
|
editor,
|
|
@@ -6063,18 +6677,18 @@ var TrackedChangesList = ({
|
|
|
6063
6677
|
}) => {
|
|
6064
6678
|
const review = useTrackChanges(editor);
|
|
6065
6679
|
if (review.changes.length === 0) {
|
|
6066
|
-
return /* @__PURE__ */ (0,
|
|
6680
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className, "data-tracked-changes-list": "", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "pixerate-changes-empty text-xs text-muted-foreground", children: emptyState }) });
|
|
6067
6681
|
}
|
|
6068
|
-
return /* @__PURE__ */ (0,
|
|
6682
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("ul", { className, role: "list", "aria-label": "Tracked changes", "data-tracked-changes-list": "", children: review.changes.map((change) => {
|
|
6069
6683
|
const active = change.id === review.currentChangeId;
|
|
6070
|
-
return /* @__PURE__ */ (0,
|
|
6684
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
6071
6685
|
"li",
|
|
6072
6686
|
{
|
|
6073
6687
|
className: active ? `${itemClassName} ${activeItemClassName}` : itemClassName,
|
|
6074
6688
|
"data-change-type": change.type,
|
|
6075
6689
|
"data-change-id": change.id,
|
|
6076
6690
|
children: [
|
|
6077
|
-
/* @__PURE__ */ (0,
|
|
6691
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
6078
6692
|
"button",
|
|
6079
6693
|
{
|
|
6080
6694
|
type: "button",
|
|
@@ -6082,14 +6696,14 @@ var TrackedChangesList = ({
|
|
|
6082
6696
|
title: `${change.author.name}: ${change.description}`,
|
|
6083
6697
|
onClick: () => review.select(change.id),
|
|
6084
6698
|
children: [
|
|
6085
|
-
/* @__PURE__ */ (0,
|
|
6699
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-medium", children: (0, import_editor15.trackedChangeLabel)(change) }),
|
|
6086
6700
|
change.author.name ? ` \xB7 ${change.author.name}` : "",
|
|
6087
|
-
/* @__PURE__ */ (0,
|
|
6701
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "block truncate text-muted-foreground", children: change.description })
|
|
6088
6702
|
]
|
|
6089
6703
|
}
|
|
6090
6704
|
),
|
|
6091
|
-
/* @__PURE__ */ (0,
|
|
6092
|
-
/* @__PURE__ */ (0,
|
|
6705
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.accept(change.id), children: "Accept" }),
|
|
6706
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.reject(change.id), children: "Reject" })
|
|
6093
6707
|
]
|
|
6094
6708
|
},
|
|
6095
6709
|
`${change.type}:${change.id}`
|
|
@@ -6098,12 +6712,12 @@ var TrackedChangesList = ({
|
|
|
6098
6712
|
};
|
|
6099
6713
|
|
|
6100
6714
|
// src/commands/useCommandPalette.ts
|
|
6101
|
-
var
|
|
6715
|
+
var import_react46 = require("react");
|
|
6102
6716
|
var import_commands2 = require("@pixerate/editor/commands");
|
|
6103
6717
|
function useCommandPalette(registry, options = {}) {
|
|
6104
|
-
const optionsRef = (0,
|
|
6718
|
+
const optionsRef = (0, import_react46.useRef)(options);
|
|
6105
6719
|
optionsRef.current = options;
|
|
6106
|
-
const controller = (0,
|
|
6720
|
+
const controller = (0, import_react46.useMemo)(
|
|
6107
6721
|
() => (0, import_commands2.createCommandPaletteController)(registry, {
|
|
6108
6722
|
context: () => {
|
|
6109
6723
|
const c = optionsRef.current.context;
|
|
@@ -6124,9 +6738,9 @@ function useCommandPalette(registry, options = {}) {
|
|
|
6124
6738
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
6125
6739
|
[registry]
|
|
6126
6740
|
);
|
|
6127
|
-
const state = (0,
|
|
6741
|
+
const state = (0, import_react46.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
|
|
6128
6742
|
const { hotkey, hotkeyTarget } = options;
|
|
6129
|
-
(0,
|
|
6743
|
+
(0, import_react46.useEffect)(() => {
|
|
6130
6744
|
if (!hotkey) return;
|
|
6131
6745
|
const target = hotkeyTarget ?? (typeof window !== "undefined" ? window : null);
|
|
6132
6746
|
if (!target) return;
|
|
@@ -6154,13 +6768,13 @@ function useCommandPalette(registry, options = {}) {
|
|
|
6154
6768
|
}
|
|
6155
6769
|
|
|
6156
6770
|
// src/commands/CommandPalette.tsx
|
|
6157
|
-
var
|
|
6158
|
-
var
|
|
6771
|
+
var import_react47 = __toESM(require("react"), 1);
|
|
6772
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
6159
6773
|
function HighlightedLabel({ item }) {
|
|
6160
|
-
if (item.labelIndices.length === 0) return /* @__PURE__ */ (0,
|
|
6774
|
+
if (item.labelIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, { children: item.label });
|
|
6161
6775
|
const marked = new Set(item.labelIndices);
|
|
6162
|
-
return /* @__PURE__ */ (0,
|
|
6163
|
-
(ch, i) => marked.has(i) ? /* @__PURE__ */ (0,
|
|
6776
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, { children: Array.from(item.label).map(
|
|
6777
|
+
(ch, i) => marked.has(i) ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-foreground", "data-match": "", children: ch }, i) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react47.default.Fragment, { children: ch }, i)
|
|
6164
6778
|
) });
|
|
6165
6779
|
}
|
|
6166
6780
|
var CommandPalette = ({
|
|
@@ -6169,22 +6783,22 @@ var CommandPalette = ({
|
|
|
6169
6783
|
emptyMessage = "No matching commands",
|
|
6170
6784
|
className = ""
|
|
6171
6785
|
}) => {
|
|
6172
|
-
const inputRef = (0,
|
|
6173
|
-
const listRef = (0,
|
|
6174
|
-
const baseId = (0,
|
|
6786
|
+
const inputRef = (0, import_react47.useRef)(null);
|
|
6787
|
+
const listRef = (0, import_react47.useRef)(null);
|
|
6788
|
+
const baseId = (0, import_react47.useId)();
|
|
6175
6789
|
const listId = `${baseId}-list`;
|
|
6176
6790
|
const optionId = (index) => `${baseId}-option-${index}`;
|
|
6177
6791
|
const { open, query, items, activeIndex } = palette;
|
|
6178
|
-
(0,
|
|
6792
|
+
(0, import_react47.useEffect)(() => {
|
|
6179
6793
|
if (open) inputRef.current?.focus();
|
|
6180
6794
|
}, [open]);
|
|
6181
|
-
(0,
|
|
6795
|
+
(0, import_react47.useEffect)(() => {
|
|
6182
6796
|
if (!open) return;
|
|
6183
6797
|
const active = listRef.current?.querySelector('[aria-selected="true"]');
|
|
6184
6798
|
active?.scrollIntoView?.({ block: "nearest" });
|
|
6185
6799
|
}, [open, activeIndex]);
|
|
6186
6800
|
if (!open) return null;
|
|
6187
|
-
return /* @__PURE__ */ (0,
|
|
6801
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
6188
6802
|
"div",
|
|
6189
6803
|
{
|
|
6190
6804
|
className: "fixed inset-0 z-50 flex items-start justify-center bg-black/30 px-4 pt-[15vh]",
|
|
@@ -6192,7 +6806,7 @@ var CommandPalette = ({
|
|
|
6192
6806
|
onMouseDown: (e) => {
|
|
6193
6807
|
if (e.target === e.currentTarget) palette.setOpen(false);
|
|
6194
6808
|
},
|
|
6195
|
-
children: /* @__PURE__ */ (0,
|
|
6809
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
6196
6810
|
"div",
|
|
6197
6811
|
{
|
|
6198
6812
|
role: "dialog",
|
|
@@ -6201,7 +6815,7 @@ var CommandPalette = ({
|
|
|
6201
6815
|
className: `w-full max-w-lg overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-xl ${className}`,
|
|
6202
6816
|
style: { background: "var(--popover, var(--background, #fff))" },
|
|
6203
6817
|
children: [
|
|
6204
|
-
/* @__PURE__ */ (0,
|
|
6818
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
6205
6819
|
"input",
|
|
6206
6820
|
{
|
|
6207
6821
|
ref: inputRef,
|
|
@@ -6221,7 +6835,7 @@ var CommandPalette = ({
|
|
|
6221
6835
|
className: "w-full border-b border-border bg-transparent px-3 py-2 text-sm outline-none placeholder:text-muted-foreground"
|
|
6222
6836
|
}
|
|
6223
6837
|
),
|
|
6224
|
-
items.length === 0 ? /* @__PURE__ */ (0,
|
|
6838
|
+
items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("ul", { ref: listRef, id: listId, role: "listbox", "aria-label": "Commands", className: "max-h-80 overflow-y-auto py-1", children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
6225
6839
|
"li",
|
|
6226
6840
|
{
|
|
6227
6841
|
id: optionId(index),
|
|
@@ -6236,12 +6850,12 @@ var CommandPalette = ({
|
|
|
6236
6850
|
onClick: () => palette.run(item.id),
|
|
6237
6851
|
className: `flex cursor-pointer items-center gap-2 px-3 py-1.5 text-sm ${index === activeIndex ? "bg-muted" : ""} ${item.enabled ? "" : "cursor-default opacity-50"}`,
|
|
6238
6852
|
children: [
|
|
6239
|
-
/* @__PURE__ */ (0,
|
|
6240
|
-
/* @__PURE__ */ (0,
|
|
6241
|
-
item.disabledReason && /* @__PURE__ */ (0,
|
|
6853
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
6854
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(HighlightedLabel, { item }),
|
|
6855
|
+
item.disabledReason && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "ml-2 text-xs text-muted-foreground", "data-disabled-reason": "", children: item.disabledReason })
|
|
6242
6856
|
] }),
|
|
6243
|
-
item.group && /* @__PURE__ */ (0,
|
|
6244
|
-
item.shortcut && /* @__PURE__ */ (0,
|
|
6857
|
+
item.group && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.group }),
|
|
6858
|
+
item.shortcut && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("kbd", { className: "shrink-0 rounded border border-border px-1.5 font-mono text-[10px] text-muted-foreground", children: item.shortcut })
|
|
6245
6859
|
]
|
|
6246
6860
|
},
|
|
6247
6861
|
item.id
|
|
@@ -6254,12 +6868,12 @@ var CommandPalette = ({
|
|
|
6254
6868
|
};
|
|
6255
6869
|
|
|
6256
6870
|
// src/commands/useCommandShortcuts.ts
|
|
6257
|
-
var
|
|
6871
|
+
var import_react48 = require("react");
|
|
6258
6872
|
function useCommandShortcuts(registry, options = {}) {
|
|
6259
|
-
const optionsRef = (0,
|
|
6873
|
+
const optionsRef = (0, import_react48.useRef)(options);
|
|
6260
6874
|
optionsRef.current = options;
|
|
6261
6875
|
const { enabled = true, target } = options;
|
|
6262
|
-
(0,
|
|
6876
|
+
(0, import_react48.useEffect)(() => {
|
|
6263
6877
|
if (!registry || !enabled) return;
|
|
6264
6878
|
const eventTarget = target ?? (typeof window !== "undefined" ? window : null);
|
|
6265
6879
|
if (!eventTarget) return;
|
|
@@ -6277,14 +6891,14 @@ function useCommandShortcuts(registry, options = {}) {
|
|
|
6277
6891
|
}, [registry, enabled, target]);
|
|
6278
6892
|
}
|
|
6279
6893
|
function useRegisterCommands(registry, specs) {
|
|
6280
|
-
(0,
|
|
6894
|
+
(0, import_react48.useEffect)(() => {
|
|
6281
6895
|
if (!registry || !specs || specs.length === 0) return;
|
|
6282
6896
|
return registry.register(specs);
|
|
6283
6897
|
}, [registry, specs]);
|
|
6284
6898
|
}
|
|
6285
6899
|
|
|
6286
6900
|
// src/persistence/useAutosave.ts
|
|
6287
|
-
var
|
|
6901
|
+
var import_react49 = require("react");
|
|
6288
6902
|
var import_persistence = require("@pixerate/editor/persistence");
|
|
6289
6903
|
var IDLE = {
|
|
6290
6904
|
status: "idle",
|
|
@@ -6295,18 +6909,18 @@ var IDLE = {
|
|
|
6295
6909
|
ready: false
|
|
6296
6910
|
};
|
|
6297
6911
|
function useAutosave(options) {
|
|
6298
|
-
const optionsRef = (0,
|
|
6912
|
+
const optionsRef = (0, import_react49.useRef)(options);
|
|
6299
6913
|
optionsRef.current = options;
|
|
6300
6914
|
const { storage, key, history, dirty } = options;
|
|
6301
6915
|
const recover = options.recover !== false;
|
|
6302
6916
|
const flushOnHide = options.flushOnHide !== false;
|
|
6303
6917
|
const ready = options.ready !== false;
|
|
6304
|
-
const [controller, setController] = (0,
|
|
6305
|
-
const [status, setStatus] = (0,
|
|
6306
|
-
const [recovery, setRecovery] = (0,
|
|
6307
|
-
const [pendingRecovery, setPendingRecovery] = (0,
|
|
6308
|
-
const revisionsRef = (0,
|
|
6309
|
-
(0,
|
|
6918
|
+
const [controller, setController] = (0, import_react49.useState)(null);
|
|
6919
|
+
const [status, setStatus] = (0, import_react49.useState)(IDLE);
|
|
6920
|
+
const [recovery, setRecovery] = (0, import_react49.useState)(null);
|
|
6921
|
+
const [pendingRecovery, setPendingRecovery] = (0, import_react49.useState)(recover);
|
|
6922
|
+
const revisionsRef = (0, import_react49.useRef)(null);
|
|
6923
|
+
(0, import_react49.useEffect)(() => {
|
|
6310
6924
|
const revisions = (0, import_persistence.createRevisionTracker)({ history, dirty });
|
|
6311
6925
|
const o = optionsRef.current;
|
|
6312
6926
|
const instance = (0, import_persistence.createAutosaveController)({
|
|
@@ -6349,10 +6963,10 @@ function useAutosave(options) {
|
|
|
6349
6963
|
if (revisionsRef.current === revisions) revisionsRef.current = null;
|
|
6350
6964
|
};
|
|
6351
6965
|
}, [storage, key, history, dirty, recover]);
|
|
6352
|
-
(0,
|
|
6966
|
+
(0, import_react49.useEffect)(() => {
|
|
6353
6967
|
if (controller && ready && !pendingRecovery) controller.ready();
|
|
6354
6968
|
}, [controller, ready, pendingRecovery]);
|
|
6355
|
-
(0,
|
|
6969
|
+
(0, import_react49.useEffect)(() => {
|
|
6356
6970
|
if (!controller || !flushOnHide || typeof window === "undefined") return;
|
|
6357
6971
|
const flush = () => void controller.flushNow();
|
|
6358
6972
|
const onVisibility = () => {
|
|
@@ -6365,31 +6979,31 @@ function useAutosave(options) {
|
|
|
6365
6979
|
document.removeEventListener("visibilitychange", onVisibility);
|
|
6366
6980
|
};
|
|
6367
6981
|
}, [controller, flushOnHide]);
|
|
6368
|
-
const restore = (0,
|
|
6982
|
+
const restore = (0, import_react49.useCallback)(() => {
|
|
6369
6983
|
const snapshot = recovery?.snapshot;
|
|
6370
6984
|
setRecovery(null);
|
|
6371
6985
|
setPendingRecovery(false);
|
|
6372
6986
|
return snapshot;
|
|
6373
6987
|
}, [recovery]);
|
|
6374
|
-
const discard = (0,
|
|
6988
|
+
const discard = (0, import_react49.useCallback)(async () => {
|
|
6375
6989
|
if (controller) await controller.discardRecovery();
|
|
6376
6990
|
setRecovery(null);
|
|
6377
6991
|
setPendingRecovery(false);
|
|
6378
6992
|
}, [controller]);
|
|
6379
|
-
const flushNow = (0,
|
|
6993
|
+
const flushNow = (0, import_react49.useCallback)(async () => {
|
|
6380
6994
|
await controller?.flushNow();
|
|
6381
6995
|
}, [controller]);
|
|
6382
|
-
const markClean = (0,
|
|
6996
|
+
const markClean = (0, import_react49.useCallback)(async () => {
|
|
6383
6997
|
revisionsRef.current?.markSaved();
|
|
6384
6998
|
await controller?.markClean();
|
|
6385
6999
|
}, [controller]);
|
|
6386
|
-
const notifyChange = (0,
|
|
7000
|
+
const notifyChange = (0, import_react49.useCallback)(() => revisionsRef.current?.bump(), []);
|
|
6387
7001
|
return { status, recovery, pendingRecovery, restore, discard, flushNow, markClean, notifyChange, controller };
|
|
6388
7002
|
}
|
|
6389
7003
|
|
|
6390
7004
|
// src/persistence/RecoveryPrompt.tsx
|
|
6391
7005
|
var import_persistence2 = require("@pixerate/editor/persistence");
|
|
6392
|
-
var
|
|
7006
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
6393
7007
|
var RecoveryPrompt = ({
|
|
6394
7008
|
recovery,
|
|
6395
7009
|
onRestore,
|
|
@@ -6401,7 +7015,7 @@ var RecoveryPrompt = ({
|
|
|
6401
7015
|
}) => {
|
|
6402
7016
|
if (!recovery) return null;
|
|
6403
7017
|
const { name } = recovery.meta;
|
|
6404
|
-
return /* @__PURE__ */ (0,
|
|
7018
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
6405
7019
|
"div",
|
|
6406
7020
|
{
|
|
6407
7021
|
role: "alertdialog",
|
|
@@ -6409,15 +7023,15 @@ var RecoveryPrompt = ({
|
|
|
6409
7023
|
"data-recovery-prompt": "",
|
|
6410
7024
|
className: `flex flex-wrap items-center gap-3 rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground shadow-sm ${className}`,
|
|
6411
7025
|
children: [
|
|
6412
|
-
/* @__PURE__ */ (0,
|
|
7026
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "min-w-0 flex-1", children: [
|
|
6413
7027
|
(0, import_persistence2.formatRecoveryMessage)(recovery.meta, formatTime),
|
|
6414
|
-
name ? /* @__PURE__ */ (0,
|
|
7028
|
+
name ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
|
|
6415
7029
|
"(",
|
|
6416
7030
|
name,
|
|
6417
7031
|
")"
|
|
6418
7032
|
] }) : null
|
|
6419
7033
|
] }),
|
|
6420
|
-
/* @__PURE__ */ (0,
|
|
7034
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6421
7035
|
"button",
|
|
6422
7036
|
{
|
|
6423
7037
|
type: "button",
|
|
@@ -6427,7 +7041,7 @@ var RecoveryPrompt = ({
|
|
|
6427
7041
|
children: restoreLabel
|
|
6428
7042
|
}
|
|
6429
7043
|
),
|
|
6430
|
-
/* @__PURE__ */ (0,
|
|
7044
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6431
7045
|
"button",
|
|
6432
7046
|
{
|
|
6433
7047
|
type: "button",
|
|
@@ -6443,17 +7057,17 @@ var RecoveryPrompt = ({
|
|
|
6443
7057
|
};
|
|
6444
7058
|
|
|
6445
7059
|
// src/generation/useGenerationPlan.ts
|
|
6446
|
-
var
|
|
7060
|
+
var import_react50 = require("react");
|
|
6447
7061
|
var import_generation = require("@pixerate/editor/generation");
|
|
6448
7062
|
function useGenerationPlan(request, capabilities, options = {}) {
|
|
6449
7063
|
const key = JSON.stringify([request, capabilities, options]);
|
|
6450
|
-
return (0,
|
|
7064
|
+
return (0, import_react50.useMemo)(() => (0, import_generation.planGenerationRequest)(request, capabilities, options), [key]);
|
|
6451
7065
|
}
|
|
6452
7066
|
function useJobProgress(options) {
|
|
6453
7067
|
const { startedAt, expectedMs, done, now, intervalMs = 1e3 } = options;
|
|
6454
|
-
const [tick, setTick] = (0,
|
|
7068
|
+
const [tick, setTick] = (0, import_react50.useState)(() => Date.now());
|
|
6455
7069
|
const ticking = !done && now === void 0;
|
|
6456
|
-
(0,
|
|
7070
|
+
(0, import_react50.useEffect)(() => {
|
|
6457
7071
|
if (!ticking) return;
|
|
6458
7072
|
setTick(Date.now());
|
|
6459
7073
|
const id = setInterval(() => setTick(Date.now()), Math.max(16, intervalMs));
|
|
@@ -6463,9 +7077,9 @@ function useJobProgress(options) {
|
|
|
6463
7077
|
}
|
|
6464
7078
|
|
|
6465
7079
|
// src/generation/GenerationSettings.tsx
|
|
6466
|
-
var
|
|
7080
|
+
var import_react51 = require("react");
|
|
6467
7081
|
var import_generation2 = require("@pixerate/editor/generation");
|
|
6468
|
-
var
|
|
7082
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
6469
7083
|
var inputClass2 = "w-full rounded-md border border-border bg-background px-2 py-1 text-sm outline-none focus:ring-1 focus:ring-ring";
|
|
6470
7084
|
function Control({
|
|
6471
7085
|
control,
|
|
@@ -6475,7 +7089,7 @@ function Control({
|
|
|
6475
7089
|
}) {
|
|
6476
7090
|
const shown = value ?? control.defaultValue;
|
|
6477
7091
|
if (control.kind === "checkbox") {
|
|
6478
|
-
return /* @__PURE__ */ (0,
|
|
7092
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6479
7093
|
"input",
|
|
6480
7094
|
{
|
|
6481
7095
|
id,
|
|
@@ -6487,7 +7101,7 @@ function Control({
|
|
|
6487
7101
|
);
|
|
6488
7102
|
}
|
|
6489
7103
|
if (control.kind === "select") {
|
|
6490
|
-
return /* @__PURE__ */ (0,
|
|
7104
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
6491
7105
|
"select",
|
|
6492
7106
|
{
|
|
6493
7107
|
id,
|
|
@@ -6496,14 +7110,14 @@ function Control({
|
|
|
6496
7110
|
value: shown === void 0 ? "" : String(shown),
|
|
6497
7111
|
onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value)),
|
|
6498
7112
|
children: [
|
|
6499
|
-
shown === void 0 && /* @__PURE__ */ (0,
|
|
6500
|
-
control.options.map((option) => /* @__PURE__ */ (0,
|
|
7113
|
+
shown === void 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: "", children: "Default" }),
|
|
7114
|
+
control.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: String(option.value), children: option.label }, String(option.value)))
|
|
6501
7115
|
]
|
|
6502
7116
|
}
|
|
6503
7117
|
);
|
|
6504
7118
|
}
|
|
6505
7119
|
if (control.kind === "textarea") {
|
|
6506
|
-
return /* @__PURE__ */ (0,
|
|
7120
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6507
7121
|
"textarea",
|
|
6508
7122
|
{
|
|
6509
7123
|
id,
|
|
@@ -6517,8 +7131,8 @@ function Control({
|
|
|
6517
7131
|
);
|
|
6518
7132
|
}
|
|
6519
7133
|
const numeric = typeof shown === "number" ? shown : void 0;
|
|
6520
|
-
return /* @__PURE__ */ (0,
|
|
6521
|
-
/* @__PURE__ */ (0,
|
|
7134
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
7135
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6522
7136
|
"input",
|
|
6523
7137
|
{
|
|
6524
7138
|
id,
|
|
@@ -6532,7 +7146,7 @@ function Control({
|
|
|
6532
7146
|
onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value))
|
|
6533
7147
|
}
|
|
6534
7148
|
),
|
|
6535
|
-
control.kind === "range" && /* @__PURE__ */ (0,
|
|
7149
|
+
control.kind === "range" && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "w-10 text-right tabular-nums text-muted-foreground", "data-field-value": "", children: numeric ?? "\u2013" })
|
|
6536
7150
|
] });
|
|
6537
7151
|
}
|
|
6538
7152
|
var GenerationSettings = ({
|
|
@@ -6546,17 +7160,17 @@ var GenerationSettings = ({
|
|
|
6546
7160
|
renderReference,
|
|
6547
7161
|
className = ""
|
|
6548
7162
|
}) => {
|
|
6549
|
-
const baseId = (0,
|
|
6550
|
-
const controls = (0,
|
|
7163
|
+
const baseId = (0, import_react51.useId)();
|
|
7164
|
+
const controls = (0, import_react51.useMemo)(() => (0, import_generation2.getGenerationControls)(capabilities), [capabilities]);
|
|
6551
7165
|
const computed = useGenerationPlan(value, capabilities, { strategy });
|
|
6552
7166
|
const plan = planProp ?? computed;
|
|
6553
7167
|
const slots = (0, import_generation2.getReferenceSlots)(capabilities, value);
|
|
6554
|
-
return /* @__PURE__ */ (0,
|
|
7168
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: `flex flex-col gap-3 text-sm ${className}`, "data-generation-settings": "", "data-model": capabilities.id, children: [
|
|
6555
7169
|
controls.map((control) => {
|
|
6556
7170
|
const id = `${baseId}-${control.key}`;
|
|
6557
|
-
return /* @__PURE__ */ (0,
|
|
6558
|
-
/* @__PURE__ */ (0,
|
|
6559
|
-
/* @__PURE__ */ (0,
|
|
7171
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-1", "data-control": control.key, children: [
|
|
7172
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("label", { htmlFor: id, className: "text-xs font-medium text-muted-foreground", title: control.description, children: control.label }),
|
|
7173
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6560
7174
|
Control,
|
|
6561
7175
|
{
|
|
6562
7176
|
control,
|
|
@@ -6567,23 +7181,23 @@ var GenerationSettings = ({
|
|
|
6567
7181
|
)
|
|
6568
7182
|
] }, control.key);
|
|
6569
7183
|
}),
|
|
6570
|
-
slots.map((slot) => /* @__PURE__ */ (0,
|
|
6571
|
-
/* @__PURE__ */ (0,
|
|
7184
|
+
slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("fieldset", { className: "flex flex-col gap-1", "data-reference-role": slot.role, children: [
|
|
7185
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("legend", { className: "text-xs font-medium text-muted-foreground", title: slot.description, children: [
|
|
6572
7186
|
slot.label,
|
|
6573
7187
|
" ",
|
|
6574
|
-
/* @__PURE__ */ (0,
|
|
7188
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "tabular-nums", "data-reference-count": "", children: [
|
|
6575
7189
|
"(",
|
|
6576
7190
|
slot.references.length,
|
|
6577
7191
|
"/",
|
|
6578
7192
|
slot.max,
|
|
6579
7193
|
")"
|
|
6580
7194
|
] }),
|
|
6581
|
-
slot.min > 0 && /* @__PURE__ */ (0,
|
|
7195
|
+
slot.min > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-destructive", children: " *" })
|
|
6582
7196
|
] }),
|
|
6583
|
-
/* @__PURE__ */ (0,
|
|
6584
|
-
slot.references.map((ref) => /* @__PURE__ */ (0,
|
|
6585
|
-
renderReference ? renderReference(ref) : /* @__PURE__ */ (0,
|
|
6586
|
-
/* @__PURE__ */ (0,
|
|
7197
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("ul", { className: "flex flex-wrap gap-1", children: [
|
|
7198
|
+
slot.references.map((ref) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("li", { className: "flex items-center gap-1 rounded border border-border px-1.5 py-0.5", "data-reference-id": ref.id, children: [
|
|
7199
|
+
renderReference ? renderReference(ref) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "max-w-[10rem] truncate", children: ref.id }),
|
|
7200
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6587
7201
|
"button",
|
|
6588
7202
|
{
|
|
6589
7203
|
type: "button",
|
|
@@ -6594,7 +7208,7 @@ var GenerationSettings = ({
|
|
|
6594
7208
|
}
|
|
6595
7209
|
)
|
|
6596
7210
|
] }, ref.id)),
|
|
6597
|
-
onAddReference && slot.canAdd && /* @__PURE__ */ (0,
|
|
7211
|
+
onAddReference && slot.canAdd && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6598
7212
|
"button",
|
|
6599
7213
|
{
|
|
6600
7214
|
type: "button",
|
|
@@ -6605,21 +7219,21 @@ var GenerationSettings = ({
|
|
|
6605
7219
|
) })
|
|
6606
7220
|
] })
|
|
6607
7221
|
] }, slot.role)),
|
|
6608
|
-
showAdjustments && plan.adjustments.length > 0 && /* @__PURE__ */ (0,
|
|
6609
|
-
showAdjustments && plan.errors.length > 0 && /* @__PURE__ */ (0,
|
|
7222
|
+
showAdjustments && plan.adjustments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("ul", { role: "status", className: "flex flex-col gap-0.5 text-xs text-muted-foreground", "data-generation-adjustments": "", children: plan.adjustments.map((adjustment, index) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("li", { "data-adjustment-field": adjustment.field, "data-adjustment-kind": adjustment.kind, children: adjustment.reason }, index)) }),
|
|
7223
|
+
showAdjustments && plan.errors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("ul", { role: "alert", className: "flex flex-col gap-0.5 text-xs text-destructive", "data-generation-errors": "", children: plan.errors.map((error, index) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("li", { "data-error-field": error.field, children: error.message }, index)) })
|
|
6610
7224
|
] });
|
|
6611
7225
|
};
|
|
6612
7226
|
|
|
6613
7227
|
// src/generation/JobProgress.tsx
|
|
6614
|
-
var
|
|
7228
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
6615
7229
|
var JobProgress = ({ title, className = "", ...options }) => {
|
|
6616
7230
|
const progress = useJobProgress(options);
|
|
6617
|
-
return /* @__PURE__ */ (0,
|
|
6618
|
-
/* @__PURE__ */ (0,
|
|
6619
|
-
title && /* @__PURE__ */ (0,
|
|
6620
|
-
/* @__PURE__ */ (0,
|
|
7231
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: `flex flex-col gap-1 text-sm ${className}`, "data-job-progress": "", "data-done": options.done ? "" : void 0, children: [
|
|
7232
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between gap-2 text-muted-foreground", children: [
|
|
7233
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "truncate text-foreground", children: title }),
|
|
7234
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { "data-job-progress-label": "", "aria-live": "polite", children: progress.label })
|
|
6621
7235
|
] }),
|
|
6622
|
-
/* @__PURE__ */ (0,
|
|
7236
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
6623
7237
|
"div",
|
|
6624
7238
|
{
|
|
6625
7239
|
role: "progressbar",
|
|
@@ -6629,7 +7243,7 @@ var JobProgress = ({ title, className = "", ...options }) => {
|
|
|
6629
7243
|
"aria-valuenow": progress.percent,
|
|
6630
7244
|
"aria-valuetext": `${progress.percent}%, ${progress.label}`,
|
|
6631
7245
|
className: "h-1.5 w-full overflow-hidden rounded-full bg-muted",
|
|
6632
|
-
children: /* @__PURE__ */ (0,
|
|
7246
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
6633
7247
|
"div",
|
|
6634
7248
|
{
|
|
6635
7249
|
className: "h-full rounded-full bg-primary transition-[width] duration-500",
|
|
@@ -6642,9 +7256,9 @@ var JobProgress = ({ title, className = "", ...options }) => {
|
|
|
6642
7256
|
};
|
|
6643
7257
|
|
|
6644
7258
|
// src/generation/AssetMentionChips.tsx
|
|
6645
|
-
var
|
|
7259
|
+
var import_react52 = require("react");
|
|
6646
7260
|
var import_generation3 = require("@pixerate/editor/generation");
|
|
6647
|
-
var
|
|
7261
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
6648
7262
|
var AssetMentionChips = ({
|
|
6649
7263
|
content,
|
|
6650
7264
|
onChange,
|
|
@@ -6654,14 +7268,14 @@ var AssetMentionChips = ({
|
|
|
6654
7268
|
renderAsset,
|
|
6655
7269
|
className = ""
|
|
6656
7270
|
}) => {
|
|
6657
|
-
const [open, setOpen] = (0,
|
|
6658
|
-
const rootRef = (0,
|
|
6659
|
-
const chips = (0,
|
|
7271
|
+
const [open, setOpen] = (0, import_react52.useState)(null);
|
|
7272
|
+
const rootRef = (0, import_react52.useRef)(null);
|
|
7273
|
+
const chips = (0, import_react52.useMemo)(
|
|
6660
7274
|
() => (0, import_generation3.describeAssetMentions)((0, import_generation3.findTextMentions)(content), assets, capabilities),
|
|
6661
7275
|
[content, assets, capabilities]
|
|
6662
7276
|
);
|
|
6663
7277
|
const options = roles ?? (capabilities ? (0, import_generation3.getAssetRoleOptions)(capabilities) : (0, import_generation3.defaultAssetRoleOptions)());
|
|
6664
|
-
(0,
|
|
7278
|
+
(0, import_react52.useEffect)(() => {
|
|
6665
7279
|
if (open === null) return;
|
|
6666
7280
|
const onPointer = (event) => {
|
|
6667
7281
|
if (!rootRef.current?.contains(event.target)) setOpen(null);
|
|
@@ -6669,19 +7283,19 @@ var AssetMentionChips = ({
|
|
|
6669
7283
|
document.addEventListener("mousedown", onPointer);
|
|
6670
7284
|
return () => document.removeEventListener("mousedown", onPointer);
|
|
6671
7285
|
}, [open]);
|
|
6672
|
-
const pick = (
|
|
7286
|
+
const pick = (chip2, role) => {
|
|
6673
7287
|
setOpen(null);
|
|
6674
|
-
if (
|
|
6675
|
-
onChange((0, import_generation3.setMentionRoleInText)(content,
|
|
7288
|
+
if (chip2.start === void 0) return;
|
|
7289
|
+
onChange((0, import_generation3.setMentionRoleInText)(content, chip2.start, role));
|
|
6676
7290
|
};
|
|
6677
7291
|
if (chips.length === 0) return null;
|
|
6678
|
-
return /* @__PURE__ */ (0,
|
|
6679
|
-
const error =
|
|
6680
|
-
const warning =
|
|
7292
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { ref: rootRef, className: `flex flex-wrap gap-1.5 ${className}`, "data-asset-mention-chips": "", children: chips.map((chip2) => {
|
|
7293
|
+
const error = chip2.issues.find((issue) => issue.severity === "error");
|
|
7294
|
+
const warning = chip2.issues.find((issue) => issue.severity === "warning");
|
|
6681
7295
|
const problem = error ?? warning;
|
|
6682
|
-
const isOpen = open ===
|
|
6683
|
-
return /* @__PURE__ */ (0,
|
|
6684
|
-
/* @__PURE__ */ (0,
|
|
7296
|
+
const isOpen = open === chip2.index;
|
|
7297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "relative inline-flex", "data-asset-chip": chip2.asset.id, children: [
|
|
7298
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
6685
7299
|
"button",
|
|
6686
7300
|
{
|
|
6687
7301
|
type: "button",
|
|
@@ -6689,82 +7303,82 @@ var AssetMentionChips = ({
|
|
|
6689
7303
|
"aria-expanded": isOpen,
|
|
6690
7304
|
title: problem?.message,
|
|
6691
7305
|
"data-issue": problem?.code,
|
|
6692
|
-
onClick: () => setOpen(isOpen ? null :
|
|
7306
|
+
onClick: () => setOpen(isOpen ? null : chip2.index),
|
|
6693
7307
|
onKeyDown: (e) => {
|
|
6694
7308
|
if (e.key === "Escape") setOpen(null);
|
|
6695
7309
|
},
|
|
6696
7310
|
className: `inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs ${error ? "border-red-500/60" : warning ? "border-amber-500/60" : "border-border"} bg-muted/40 hover:bg-muted`,
|
|
6697
7311
|
children: [
|
|
6698
|
-
/* @__PURE__ */ (0,
|
|
6699
|
-
/* @__PURE__ */ (0,
|
|
7312
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { children: renderAsset ? renderAsset(chip2) : `@${chip2.asset.label ?? chip2.handle}` }),
|
|
7313
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
6700
7314
|
"span",
|
|
6701
7315
|
{
|
|
6702
|
-
className: `rounded px-1 text-[10px] uppercase tracking-wide ${
|
|
6703
|
-
"data-role-badge":
|
|
6704
|
-
children:
|
|
7316
|
+
className: `rounded px-1 text-[10px] uppercase tracking-wide ${chip2.role ? "bg-primary/15" : "opacity-60"}`,
|
|
7317
|
+
"data-role-badge": chip2.role ?? "",
|
|
7318
|
+
children: chip2.roleLabel ?? "No role"
|
|
6705
7319
|
}
|
|
6706
7320
|
)
|
|
6707
7321
|
]
|
|
6708
7322
|
}
|
|
6709
7323
|
),
|
|
6710
|
-
isOpen && /* @__PURE__ */ (0,
|
|
7324
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
6711
7325
|
"div",
|
|
6712
7326
|
{
|
|
6713
7327
|
role: "listbox",
|
|
6714
|
-
"aria-label": `Role for ${
|
|
7328
|
+
"aria-label": `Role for ${chip2.asset.label ?? chip2.handle}`,
|
|
6715
7329
|
className: "absolute left-0 top-full z-50 mt-1 flex min-w-[12rem] flex-col rounded-md border border-border bg-background p-1 text-xs shadow-lg",
|
|
6716
7330
|
"data-role-picker": "",
|
|
6717
7331
|
onKeyDown: (e) => {
|
|
6718
7332
|
if (e.key === "Escape") setOpen(null);
|
|
6719
7333
|
},
|
|
6720
7334
|
children: [
|
|
6721
|
-
options.map((option) => /* @__PURE__ */ (0,
|
|
7335
|
+
options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
6722
7336
|
"button",
|
|
6723
7337
|
{
|
|
6724
7338
|
type: "button",
|
|
6725
7339
|
role: "option",
|
|
6726
|
-
"aria-selected":
|
|
7340
|
+
"aria-selected": chip2.role === option.role,
|
|
6727
7341
|
"data-role-option": option.role,
|
|
6728
7342
|
title: option.description,
|
|
6729
|
-
onClick: () => pick(
|
|
7343
|
+
onClick: () => pick(chip2, option.role),
|
|
6730
7344
|
className: "flex items-center justify-between gap-2 rounded px-2 py-1 text-left hover:bg-muted",
|
|
6731
7345
|
children: [
|
|
6732
|
-
/* @__PURE__ */ (0,
|
|
6733
|
-
option.accepts?.length ? /* @__PURE__ */ (0,
|
|
7346
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { children: option.label }),
|
|
7347
|
+
option.accepts?.length ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-[10px] opacity-60", children: option.accepts.join(", ") }) : null
|
|
6734
7348
|
]
|
|
6735
7349
|
},
|
|
6736
7350
|
option.role
|
|
6737
7351
|
)),
|
|
6738
|
-
/* @__PURE__ */ (0,
|
|
7352
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
6739
7353
|
"button",
|
|
6740
7354
|
{
|
|
6741
7355
|
type: "button",
|
|
6742
7356
|
role: "option",
|
|
6743
|
-
"aria-selected": !
|
|
7357
|
+
"aria-selected": !chip2.role,
|
|
6744
7358
|
"data-role-option": "",
|
|
6745
|
-
onClick: () => pick(
|
|
7359
|
+
onClick: () => pick(chip2, null),
|
|
6746
7360
|
className: "rounded px-2 py-1 text-left opacity-70 hover:bg-muted",
|
|
6747
7361
|
children: "No role"
|
|
6748
7362
|
}
|
|
6749
7363
|
),
|
|
6750
|
-
|
|
7364
|
+
chip2.issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("ul", { className: "mt-1 border-t border-border px-2 pt-1 text-[10px]", "data-chip-issues": "", children: chip2.issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("li", { className: issue.severity === "error" ? "text-red-500" : "text-amber-500", children: issue.message }, i)) })
|
|
6751
7365
|
]
|
|
6752
7366
|
}
|
|
6753
7367
|
)
|
|
6754
|
-
] }, `${
|
|
7368
|
+
] }, `${chip2.start}-${chip2.index}`);
|
|
6755
7369
|
}) });
|
|
6756
7370
|
};
|
|
6757
7371
|
|
|
6758
7372
|
// src/generation/GenerationHistory.tsx
|
|
6759
|
-
var
|
|
7373
|
+
var import_react53 = require("react");
|
|
6760
7374
|
var import_generation4 = require("@pixerate/editor/generation");
|
|
6761
|
-
var
|
|
7375
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
6762
7376
|
function useGenerationRecords(store, filter) {
|
|
6763
|
-
const [records, setRecords] = (0,
|
|
6764
|
-
const [loading, setLoading] = (0,
|
|
6765
|
-
const [error, setError] = (0,
|
|
7377
|
+
const [records, setRecords] = (0, import_react53.useState)([]);
|
|
7378
|
+
const [loading, setLoading] = (0, import_react53.useState)(!!store);
|
|
7379
|
+
const [error, setError] = (0, import_react53.useState)(null);
|
|
6766
7380
|
const filterKey = (0, import_generation4.stableStringify)(filter ?? {});
|
|
6767
|
-
const refresh = (0,
|
|
7381
|
+
const refresh = (0, import_react53.useCallback)(async () => {
|
|
6768
7382
|
if (!store) {
|
|
6769
7383
|
setRecords([]);
|
|
6770
7384
|
setLoading(false);
|
|
@@ -6781,7 +7395,7 @@ function useGenerationRecords(store, filter) {
|
|
|
6781
7395
|
setLoading(false);
|
|
6782
7396
|
}
|
|
6783
7397
|
}, [store, filterKey]);
|
|
6784
|
-
(0,
|
|
7398
|
+
(0, import_react53.useEffect)(() => {
|
|
6785
7399
|
void refresh();
|
|
6786
7400
|
if (!store) return;
|
|
6787
7401
|
return store.subscribe(() => void refresh());
|
|
@@ -6807,21 +7421,21 @@ var GenerationHistory = ({
|
|
|
6807
7421
|
emptyText = "No generations yet.",
|
|
6808
7422
|
className = ""
|
|
6809
7423
|
}) => {
|
|
6810
|
-
const [innerMode, setInnerMode] = (0,
|
|
7424
|
+
const [innerMode, setInnerMode] = (0, import_react53.useState)("exact");
|
|
6811
7425
|
const mode = modeProp ?? innerMode;
|
|
6812
7426
|
const setMode = (next) => {
|
|
6813
7427
|
if (modeProp === void 0) setInnerMode(next);
|
|
6814
7428
|
onModeChange?.(next);
|
|
6815
7429
|
};
|
|
6816
|
-
const options = (0,
|
|
6817
|
-
const results = (0,
|
|
6818
|
-
const models = (0,
|
|
7430
|
+
const options = (0, import_react53.useMemo)(() => ({ templates, capabilities, assets, mode }), [templates, capabilities, assets, mode]);
|
|
7431
|
+
const results = (0, import_react53.useMemo)(() => records.map((record) => (0, import_generation4.recreateRequest)(record, options)), [records, options]);
|
|
7432
|
+
const models = (0, import_react53.useMemo)(
|
|
6819
7433
|
() => capabilities ? Array.isArray(capabilities) ? capabilities : [capabilities] : [],
|
|
6820
7434
|
[capabilities]
|
|
6821
7435
|
);
|
|
6822
|
-
return /* @__PURE__ */ (0,
|
|
6823
|
-
/* @__PURE__ */ (0,
|
|
6824
|
-
/* @__PURE__ */ (0,
|
|
7436
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: `flex flex-col gap-2 text-sm ${className}`, "data-generation-history": "", children: [
|
|
7437
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "flex items-center gap-2 text-xs", role: "radiogroup", "aria-label": "Recreate mode", children: ["exact", "latest"].map((value) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("label", { className: "inline-flex items-center gap-1", children: [
|
|
7438
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
6825
7439
|
"input",
|
|
6826
7440
|
{
|
|
6827
7441
|
type: "radio",
|
|
@@ -6834,34 +7448,34 @@ var GenerationHistory = ({
|
|
|
6834
7448
|
),
|
|
6835
7449
|
value === "exact" ? "Exact (recorded versions)" : "Latest templates & settings"
|
|
6836
7450
|
] }, value)) }),
|
|
6837
|
-
records.length === 0 && /* @__PURE__ */ (0,
|
|
6838
|
-
/* @__PURE__ */ (0,
|
|
7451
|
+
records.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyText }),
|
|
7452
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ul", { className: "flex flex-col gap-2", children: records.map((record, i) => {
|
|
6839
7453
|
const result = results[i];
|
|
6840
7454
|
const model = models.find((m) => m.id === record.provenance.modelId);
|
|
6841
7455
|
const blocked = !result.ok;
|
|
6842
|
-
return /* @__PURE__ */ (0,
|
|
7456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
6843
7457
|
"li",
|
|
6844
7458
|
{
|
|
6845
7459
|
className: "rounded-md border border-border p-2",
|
|
6846
7460
|
"data-record": record.id,
|
|
6847
7461
|
"data-drift": result.drift.length,
|
|
6848
7462
|
children: [
|
|
6849
|
-
/* @__PURE__ */ (0,
|
|
6850
|
-
/* @__PURE__ */ (0,
|
|
6851
|
-
/* @__PURE__ */ (0,
|
|
6852
|
-
record.kind !== "generate" && /* @__PURE__ */ (0,
|
|
7463
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 text-xs", children: [
|
|
7464
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "font-medium", children: model?.name ?? record.provenance.modelId }),
|
|
7465
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
7466
|
+
record.kind !== "generate" && /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { "data-kind": "", children: [
|
|
6853
7467
|
record.kind,
|
|
6854
7468
|
" \xB7 "
|
|
6855
7469
|
] }),
|
|
6856
|
-
/* @__PURE__ */ (0,
|
|
6857
|
-
record.seed !== void 0 && /* @__PURE__ */ (0,
|
|
7470
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("time", { dateTime: record.createdAt, children: record.createdAt.replace("T", " ").slice(0, 16) }),
|
|
7471
|
+
record.seed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
|
|
6858
7472
|
" \xB7 seed ",
|
|
6859
7473
|
record.seed
|
|
6860
7474
|
] })
|
|
6861
7475
|
] })
|
|
6862
7476
|
] }),
|
|
6863
|
-
/* @__PURE__ */ (0,
|
|
6864
|
-
record.assets.length > 0 && /* @__PURE__ */ (0,
|
|
7477
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "mt-1 line-clamp-3 break-words text-xs", "data-record-prompt": "", children: record.provenance.resolvedPrompt }),
|
|
7478
|
+
record.assets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "mt-1 flex flex-wrap gap-1", children: record.assets.map((asset) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
6865
7479
|
"span",
|
|
6866
7480
|
{
|
|
6867
7481
|
className: "rounded-full bg-muted px-2 py-0.5 text-[10px]",
|
|
@@ -6875,16 +7489,16 @@ var GenerationHistory = ({
|
|
|
6875
7489
|
`${asset.role}:${asset.id}`
|
|
6876
7490
|
)) }),
|
|
6877
7491
|
renderPreview?.(record),
|
|
6878
|
-
result.drift.length > 0 && /* @__PURE__ */ (0,
|
|
6879
|
-
/* @__PURE__ */ (0,
|
|
7492
|
+
result.drift.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ul", { className: "mt-1 flex flex-col gap-0.5 text-[11px]", "data-drift-report": "", children: result.drift.map((item, j) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("li", { className: severityClass[item.severity], "data-drift-type": item.type, children: [
|
|
7493
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("strong", { children: [
|
|
6880
7494
|
import_generation4.DRIFT_TYPE_LABELS[item.type],
|
|
6881
7495
|
":"
|
|
6882
7496
|
] }),
|
|
6883
7497
|
" ",
|
|
6884
7498
|
item.message
|
|
6885
7499
|
] }, j)) }),
|
|
6886
|
-
/* @__PURE__ */ (0,
|
|
6887
|
-
onRecreate && /* @__PURE__ */ (0,
|
|
7500
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "mt-2 flex gap-2", children: [
|
|
7501
|
+
onRecreate && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
6888
7502
|
"button",
|
|
6889
7503
|
{
|
|
6890
7504
|
type: "button",
|
|
@@ -6896,7 +7510,7 @@ var GenerationHistory = ({
|
|
|
6896
7510
|
children: "Recreate"
|
|
6897
7511
|
}
|
|
6898
7512
|
),
|
|
6899
|
-
onVariation && /* @__PURE__ */ (0,
|
|
7513
|
+
onVariation && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
6900
7514
|
"button",
|
|
6901
7515
|
{
|
|
6902
7516
|
type: "button",
|
|
@@ -6906,7 +7520,7 @@ var GenerationHistory = ({
|
|
|
6906
7520
|
children: "Variation"
|
|
6907
7521
|
}
|
|
6908
7522
|
),
|
|
6909
|
-
onRemove && /* @__PURE__ */ (0,
|
|
7523
|
+
onRemove && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
6910
7524
|
"button",
|
|
6911
7525
|
{
|
|
6912
7526
|
type: "button",
|
|
@@ -6926,19 +7540,19 @@ var GenerationHistory = ({
|
|
|
6926
7540
|
};
|
|
6927
7541
|
|
|
6928
7542
|
// src/find-replace/useFindReplace.ts
|
|
6929
|
-
var
|
|
7543
|
+
var import_react54 = require("react");
|
|
6930
7544
|
var import_editor16 = require("@pixerate/editor");
|
|
6931
7545
|
var noopUnsubscribe2 = () => {
|
|
6932
7546
|
};
|
|
6933
7547
|
function useFindReplace(editor) {
|
|
6934
7548
|
const store = (0, import_editor16.getFindReplaceStore)(editor ?? null);
|
|
6935
|
-
const subscribe = (0,
|
|
7549
|
+
const subscribe = (0, import_react54.useCallback)(
|
|
6936
7550
|
(onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe2,
|
|
6937
7551
|
[store]
|
|
6938
7552
|
);
|
|
6939
7553
|
const getSnapshot = () => store?.getSnapshot() ?? import_editor16.EMPTY_FIND_REPLACE_SNAPSHOT;
|
|
6940
|
-
const snapshot = (0,
|
|
6941
|
-
return (0,
|
|
7554
|
+
const snapshot = (0, import_react54.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
7555
|
+
return (0, import_react54.useMemo)(() => {
|
|
6942
7556
|
const run = (fn) => {
|
|
6943
7557
|
if (editor && !editor.isDestroyed && store) fn(editor);
|
|
6944
7558
|
};
|
|
@@ -6962,9 +7576,9 @@ function useFindReplace(editor) {
|
|
|
6962
7576
|
}
|
|
6963
7577
|
|
|
6964
7578
|
// src/find-replace/FindReplaceBar.tsx
|
|
6965
|
-
var
|
|
7579
|
+
var import_react55 = require("react");
|
|
6966
7580
|
var import_editor17 = require("@pixerate/editor");
|
|
6967
|
-
var
|
|
7581
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
6968
7582
|
var inputClass3 = "min-w-0 flex-1 rounded border border-input bg-background px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-ring";
|
|
6969
7583
|
var buttonClass5 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
|
|
6970
7584
|
var toggleClass = (on) => `${buttonClass5} font-mono ${on ? "bg-primary/10 text-primary" : "text-muted-foreground"}`;
|
|
@@ -6977,10 +7591,10 @@ var FindReplaceBar = ({
|
|
|
6977
7591
|
onClose
|
|
6978
7592
|
}) => {
|
|
6979
7593
|
const find = useFindReplace(editor);
|
|
6980
|
-
const findInput = (0,
|
|
6981
|
-
const [moreOpen, setMoreOpen] = (0,
|
|
7594
|
+
const findInput = (0, import_react55.useRef)(null);
|
|
7595
|
+
const [moreOpen, setMoreOpen] = (0, import_react55.useState)(false);
|
|
6982
7596
|
const visible = find.available && (alwaysOpen || find.open);
|
|
6983
|
-
(0,
|
|
7597
|
+
(0, import_react55.useEffect)(() => {
|
|
6984
7598
|
if (!visible || find.focusRequest === 0) return;
|
|
6985
7599
|
findInput.current?.focus();
|
|
6986
7600
|
findInput.current?.select();
|
|
@@ -7018,9 +7632,9 @@ var FindReplaceBar = ({
|
|
|
7018
7632
|
if (isMod(e)) find.replaceAll();
|
|
7019
7633
|
else find.replace();
|
|
7020
7634
|
};
|
|
7021
|
-
return /* @__PURE__ */ (0,
|
|
7022
|
-
/* @__PURE__ */ (0,
|
|
7023
|
-
/* @__PURE__ */ (0,
|
|
7635
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
|
|
7636
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
7637
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7024
7638
|
"button",
|
|
7025
7639
|
{
|
|
7026
7640
|
type: "button",
|
|
@@ -7031,7 +7645,7 @@ var FindReplaceBar = ({
|
|
|
7031
7645
|
children: showReplace ? "\u25BE" : "\u25B8"
|
|
7032
7646
|
}
|
|
7033
7647
|
),
|
|
7034
|
-
/* @__PURE__ */ (0,
|
|
7648
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7035
7649
|
"input",
|
|
7036
7650
|
{
|
|
7037
7651
|
ref: findInput,
|
|
@@ -7045,7 +7659,7 @@ var FindReplaceBar = ({
|
|
|
7045
7659
|
onKeyDown: onFindKeyDown
|
|
7046
7660
|
}
|
|
7047
7661
|
),
|
|
7048
|
-
import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0,
|
|
7662
|
+
import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7049
7663
|
"button",
|
|
7050
7664
|
{
|
|
7051
7665
|
type: "button",
|
|
@@ -7058,7 +7672,7 @@ var FindReplaceBar = ({
|
|
|
7058
7672
|
},
|
|
7059
7673
|
t.key
|
|
7060
7674
|
)),
|
|
7061
|
-
/* @__PURE__ */ (0,
|
|
7675
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7062
7676
|
"span",
|
|
7063
7677
|
{
|
|
7064
7678
|
className: `min-w-[5rem] px-1 text-center text-xs ${find.error ? "text-destructive" : "text-muted-foreground"}`,
|
|
@@ -7068,9 +7682,9 @@ var FindReplaceBar = ({
|
|
|
7068
7682
|
children: status
|
|
7069
7683
|
}
|
|
7070
7684
|
),
|
|
7071
|
-
/* @__PURE__ */ (0,
|
|
7072
|
-
/* @__PURE__ */ (0,
|
|
7073
|
-
showMoreOptions && /* @__PURE__ */ (0,
|
|
7685
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
|
|
7686
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
|
|
7687
|
+
showMoreOptions && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7074
7688
|
"button",
|
|
7075
7689
|
{
|
|
7076
7690
|
type: "button",
|
|
@@ -7081,10 +7695,10 @@ var FindReplaceBar = ({
|
|
|
7081
7695
|
children: "\u2026"
|
|
7082
7696
|
}
|
|
7083
7697
|
),
|
|
7084
|
-
/* @__PURE__ */ (0,
|
|
7698
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Close find", onClick: close, children: "\xD7" })
|
|
7085
7699
|
] }),
|
|
7086
|
-
showReplace && /* @__PURE__ */ (0,
|
|
7087
|
-
/* @__PURE__ */ (0,
|
|
7700
|
+
showReplace && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-1 pl-7", children: [
|
|
7701
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7088
7702
|
"input",
|
|
7089
7703
|
{
|
|
7090
7704
|
type: "text",
|
|
@@ -7096,7 +7710,7 @@ var FindReplaceBar = ({
|
|
|
7096
7710
|
onKeyDown: onReplaceKeyDown
|
|
7097
7711
|
}
|
|
7098
7712
|
),
|
|
7099
|
-
/* @__PURE__ */ (0,
|
|
7713
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7100
7714
|
"button",
|
|
7101
7715
|
{
|
|
7102
7716
|
type: "button",
|
|
@@ -7106,11 +7720,11 @@ var FindReplaceBar = ({
|
|
|
7106
7720
|
children: "Replace"
|
|
7107
7721
|
}
|
|
7108
7722
|
),
|
|
7109
|
-
/* @__PURE__ */ (0,
|
|
7110
|
-
find.lastReplaceCount !== null && /* @__PURE__ */ (0,
|
|
7723
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass5, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
|
|
7724
|
+
find.lastReplaceCount !== null && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "px-1 text-xs text-muted-foreground", "aria-live": "polite", children: find.lastReplaceCount === 1 ? "1 replaced" : `${find.lastReplaceCount} replaced` })
|
|
7111
7725
|
] }),
|
|
7112
|
-
showMoreOptions && moreOpen && /* @__PURE__ */ (0,
|
|
7113
|
-
/* @__PURE__ */ (0,
|
|
7726
|
+
showMoreOptions && moreOpen && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 pl-7 text-xs text-muted-foreground", children: import_editor17.FIND_OPTION_TOGGLES.filter((t) => t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
7727
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7114
7728
|
"input",
|
|
7115
7729
|
{
|
|
7116
7730
|
type: "checkbox",
|
|
@@ -7124,12 +7738,12 @@ var FindReplaceBar = ({
|
|
|
7124
7738
|
};
|
|
7125
7739
|
|
|
7126
7740
|
// src/tables/useTableMenu.ts
|
|
7127
|
-
var
|
|
7741
|
+
var import_react56 = require("react");
|
|
7128
7742
|
var import_editor18 = require("@pixerate/editor");
|
|
7129
7743
|
function useTableMenu(editor) {
|
|
7130
|
-
const store = (0,
|
|
7131
|
-
const snapshot = (0,
|
|
7132
|
-
return (0,
|
|
7744
|
+
const store = (0, import_react56.useMemo)(() => (0, import_editor18.createTableStore)(editor), [editor]);
|
|
7745
|
+
const snapshot = (0, import_react56.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
7746
|
+
return (0, import_react56.useMemo)(
|
|
7133
7747
|
() => ({
|
|
7134
7748
|
...snapshot,
|
|
7135
7749
|
run: (action, params) => (0, import_editor18.runTableAction)(editor, action, params, { focus: true }),
|
|
@@ -7140,9 +7754,9 @@ function useTableMenu(editor) {
|
|
|
7140
7754
|
}
|
|
7141
7755
|
|
|
7142
7756
|
// src/tables/TableToolbar.tsx
|
|
7143
|
-
var
|
|
7757
|
+
var import_react57 = __toESM(require("react"), 1);
|
|
7144
7758
|
var import_editor19 = require("@pixerate/editor");
|
|
7145
|
-
var
|
|
7759
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
7146
7760
|
var keepSelection2 = (event) => event.preventDefault();
|
|
7147
7761
|
var TableToolbar = ({
|
|
7148
7762
|
editor,
|
|
@@ -7156,14 +7770,14 @@ var TableToolbar = ({
|
|
|
7156
7770
|
}) => {
|
|
7157
7771
|
const table = useTableMenu(editor);
|
|
7158
7772
|
if (!editor || !table.inTable && !showWhenOutside) return null;
|
|
7159
|
-
return /* @__PURE__ */ (0,
|
|
7773
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
|
|
7160
7774
|
const status = table.check(item.action, item.params);
|
|
7161
7775
|
const enabled = status === true;
|
|
7162
7776
|
const active = item.active?.(table);
|
|
7163
7777
|
const separator = index > 0 && items[index - 1].group !== item.group;
|
|
7164
|
-
return /* @__PURE__ */ (0,
|
|
7165
|
-
separator && /* @__PURE__ */ (0,
|
|
7166
|
-
/* @__PURE__ */ (0,
|
|
7778
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_react57.default.Fragment, { children: [
|
|
7779
|
+
separator && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: separatorClassName, "aria-hidden": "true" }),
|
|
7780
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
7167
7781
|
"button",
|
|
7168
7782
|
{
|
|
7169
7783
|
type: "button",
|
|
@@ -7185,8 +7799,8 @@ var TableToolbar = ({
|
|
|
7185
7799
|
};
|
|
7186
7800
|
|
|
7187
7801
|
// src/tables/InsertTableGrid.tsx
|
|
7188
|
-
var
|
|
7189
|
-
var
|
|
7802
|
+
var import_react58 = require("react");
|
|
7803
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
7190
7804
|
var keepSelection3 = (event) => event.preventDefault();
|
|
7191
7805
|
var InsertTableGrid = ({
|
|
7192
7806
|
editor,
|
|
@@ -7199,14 +7813,14 @@ var InsertTableGrid = ({
|
|
|
7199
7813
|
onInsert
|
|
7200
7814
|
}) => {
|
|
7201
7815
|
const table = useTableMenu(editor);
|
|
7202
|
-
const [hover, setHover] = (0,
|
|
7816
|
+
const [hover, setHover] = (0, import_react58.useState)(null);
|
|
7203
7817
|
const status = table.actions.insertTable;
|
|
7204
7818
|
const disabled = !editor || !status.enabled;
|
|
7205
7819
|
const insert = (size) => {
|
|
7206
7820
|
if (table.run("insertTable", { ...size, withHeaderRow })) onInsert?.(size);
|
|
7207
7821
|
setHover(null);
|
|
7208
7822
|
};
|
|
7209
|
-
return /* @__PURE__ */ (0,
|
|
7823
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
7210
7824
|
"div",
|
|
7211
7825
|
{
|
|
7212
7826
|
className,
|
|
@@ -7216,7 +7830,7 @@ var InsertTableGrid = ({
|
|
|
7216
7830
|
"data-insert-table-grid": "",
|
|
7217
7831
|
onMouseLeave: () => setHover(null),
|
|
7218
7832
|
children: [
|
|
7219
|
-
/* @__PURE__ */ (0,
|
|
7833
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
7220
7834
|
"div",
|
|
7221
7835
|
{
|
|
7222
7836
|
role: "grid",
|
|
@@ -7225,7 +7839,7 @@ var InsertTableGrid = ({
|
|
|
7225
7839
|
children: Array.from({ length: rows * cols }, (_, i) => {
|
|
7226
7840
|
const size = { rows: Math.floor(i / cols) + 1, cols: i % cols + 1 };
|
|
7227
7841
|
const active = !!hover && size.rows <= hover.rows && size.cols <= hover.cols;
|
|
7228
|
-
return /* @__PURE__ */ (0,
|
|
7842
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
7229
7843
|
"button",
|
|
7230
7844
|
{
|
|
7231
7845
|
type: "button",
|
|
@@ -7245,7 +7859,7 @@ var InsertTableGrid = ({
|
|
|
7245
7859
|
})
|
|
7246
7860
|
}
|
|
7247
7861
|
),
|
|
7248
|
-
/* @__PURE__ */ (0,
|
|
7862
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { "aria-live": "polite", "data-testid": "insert-table-size", children: disabled ? status.reason : hover ? `${hover.rows} \xD7 ${hover.cols}` : "Insert table" })
|
|
7249
7863
|
]
|
|
7250
7864
|
}
|
|
7251
7865
|
);
|
|
@@ -7253,31 +7867,31 @@ var InsertTableGrid = ({
|
|
|
7253
7867
|
|
|
7254
7868
|
// src/tables/TableBubbleMenu.tsx
|
|
7255
7869
|
var import_editor20 = require("@pixerate/editor");
|
|
7256
|
-
var
|
|
7870
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
7257
7871
|
var TableBubbleMenu = ({
|
|
7258
7872
|
editor,
|
|
7259
7873
|
children,
|
|
7260
7874
|
toolbarProps,
|
|
7261
7875
|
pluginKey = "tableBubbleMenu",
|
|
7262
7876
|
...rest
|
|
7263
|
-
}) => /* @__PURE__ */ (0,
|
|
7877
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(BubbleMenu, { editor, pluginKey, shouldShow: import_editor20.shouldShowTableBubbleMenu, ...rest, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(TableToolbar, { editor, ...toolbarProps }) });
|
|
7264
7878
|
|
|
7265
7879
|
// src/chart-node/ChartNodeView.tsx
|
|
7266
7880
|
var import_client = require("react-dom/client");
|
|
7267
7881
|
|
|
7268
7882
|
// src/chart/ChartCanvas.tsx
|
|
7269
|
-
var
|
|
7883
|
+
var import_react60 = require("react");
|
|
7270
7884
|
var import_chart2 = require("@pixerate/editor/chart");
|
|
7271
7885
|
|
|
7272
7886
|
// src/chart/useChartEditor.ts
|
|
7273
|
-
var
|
|
7887
|
+
var import_react59 = require("react");
|
|
7274
7888
|
var import_chart = require("@pixerate/editor/chart");
|
|
7275
7889
|
function useChartState(controller) {
|
|
7276
|
-
return (0,
|
|
7890
|
+
return (0, import_react59.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
|
|
7277
7891
|
}
|
|
7278
7892
|
|
|
7279
7893
|
// src/chart/ChartCanvas.tsx
|
|
7280
|
-
var
|
|
7894
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
7281
7895
|
function renderChartMark(mark, fontFamily, interactive) {
|
|
7282
7896
|
const common = {
|
|
7283
7897
|
"data-role": mark.role,
|
|
@@ -7289,9 +7903,9 @@ function renderChartMark(mark, fontFamily, interactive) {
|
|
|
7289
7903
|
};
|
|
7290
7904
|
switch (mark.kind) {
|
|
7291
7905
|
case "rect":
|
|
7292
|
-
return /* @__PURE__ */ (0,
|
|
7906
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("rect", { ...common, x: mark.x, y: mark.y, width: mark.width, height: mark.height, rx: mark.radius, style: { fill: mark.fill, stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
|
|
7293
7907
|
case "path":
|
|
7294
|
-
return /* @__PURE__ */ (0,
|
|
7908
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
7295
7909
|
"path",
|
|
7296
7910
|
{
|
|
7297
7911
|
...common,
|
|
@@ -7304,11 +7918,11 @@ function renderChartMark(mark, fontFamily, interactive) {
|
|
|
7304
7918
|
mark.key
|
|
7305
7919
|
);
|
|
7306
7920
|
case "circle":
|
|
7307
|
-
return /* @__PURE__ */ (0,
|
|
7921
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("circle", { ...common, cx: mark.cx, cy: mark.cy, r: mark.r, style: { fill: mark.fill, stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
|
|
7308
7922
|
case "line":
|
|
7309
|
-
return /* @__PURE__ */ (0,
|
|
7923
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("line", { ...common, x1: mark.x1, y1: mark.y1, x2: mark.x2, y2: mark.y2, strokeDasharray: mark.dash, style: { stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
|
|
7310
7924
|
case "text":
|
|
7311
|
-
return /* @__PURE__ */ (0,
|
|
7925
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
7312
7926
|
"text",
|
|
7313
7927
|
{
|
|
7314
7928
|
...common,
|
|
@@ -7325,23 +7939,23 @@ function renderChartMark(mark, fontFamily, interactive) {
|
|
|
7325
7939
|
}
|
|
7326
7940
|
}
|
|
7327
7941
|
function ChartPresenceLayer({ presence }) {
|
|
7328
|
-
const { actors } = (0,
|
|
7329
|
-
return /* @__PURE__ */ (0,
|
|
7330
|
-
/* @__PURE__ */ (0,
|
|
7331
|
-
/* @__PURE__ */ (0,
|
|
7332
|
-
/* @__PURE__ */ (0,
|
|
7333
|
-
/* @__PURE__ */ (0,
|
|
7942
|
+
const { actors } = (0, import_react60.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
|
|
7943
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("g", { "data-chart-presence": "", pointerEvents: "none", children: actors.map((a) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("g", { transform: `translate(${a.x} ${a.y})`, "data-actor": a.id, children: [
|
|
7944
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("path", { d: "M0,0 L0,14 L4,10.5 L7,17 L9.5,16 L6.5,9.5 L11.5,9.5 Z", style: { fill: a.color, stroke: "#ffffff", strokeWidth: 1 }, transform: a.pressed ? "scale(0.9)" : void 0 }),
|
|
7945
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("g", { transform: "translate(13 16)", children: [
|
|
7946
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("rect", { x: 0, y: 0, rx: 4, height: 18, width: Math.max(28, (a.message ?? a.name).length * 6.4 + 12), style: { fill: a.color } }),
|
|
7947
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("text", { x: 6, y: 9, dominantBaseline: "central", style: { fill: "#ffffff", fontSize: 11, fontWeight: 600, fontFamily: "inherit" }, children: a.message ?? a.name })
|
|
7334
7948
|
] })
|
|
7335
7949
|
] }, a.id)) });
|
|
7336
7950
|
}
|
|
7337
7951
|
function ChartCanvas({ controller, width = 640, height = 400, responsive = true, theme, editable = true, measureText, emptyMessage, className, presence, sceneRef }) {
|
|
7338
7952
|
const state = useChartState(controller);
|
|
7339
|
-
const wrapper = (0,
|
|
7340
|
-
const svg = (0,
|
|
7341
|
-
const drag = (0,
|
|
7342
|
-
const [measured, setMeasured] = (0,
|
|
7343
|
-
const [frozen, setFrozen] = (0,
|
|
7344
|
-
(0,
|
|
7953
|
+
const wrapper = (0, import_react60.useRef)(null);
|
|
7954
|
+
const svg = (0, import_react60.useRef)(null);
|
|
7955
|
+
const drag = (0, import_react60.useRef)(null);
|
|
7956
|
+
const [measured, setMeasured] = (0, import_react60.useState)(null);
|
|
7957
|
+
const [frozen, setFrozen] = (0, import_react60.useState)(null);
|
|
7958
|
+
(0, import_react60.useEffect)(() => {
|
|
7345
7959
|
const el = wrapper.current;
|
|
7346
7960
|
if (!responsive || !el || typeof ResizeObserver === "undefined") return;
|
|
7347
7961
|
const observer = new ResizeObserver(([entry]) => {
|
|
@@ -7352,8 +7966,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
|
|
|
7352
7966
|
return () => observer.disconnect();
|
|
7353
7967
|
}, [responsive]);
|
|
7354
7968
|
const sceneWidth = responsive && measured || width;
|
|
7355
|
-
const fullTheme = (0,
|
|
7356
|
-
const scene = (0,
|
|
7969
|
+
const fullTheme = (0, import_react60.useMemo)(() => ({ ...import_chart2.CSS_VARIABLE_CHART_THEME, ...theme }), [theme]);
|
|
7970
|
+
const scene = (0, import_react60.useMemo)(
|
|
7357
7971
|
() => (0, import_chart2.layoutChart)(state.spec, {
|
|
7358
7972
|
width: sceneWidth,
|
|
7359
7973
|
height,
|
|
@@ -7369,8 +7983,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
|
|
|
7369
7983
|
[state.spec, state.selection, sceneWidth, height, fullTheme, editable, measureText, emptyMessage, frozen]
|
|
7370
7984
|
);
|
|
7371
7985
|
if (sceneRef) sceneRef.current = scene;
|
|
7372
|
-
const byKey = (0,
|
|
7373
|
-
(0,
|
|
7986
|
+
const byKey = (0, import_react60.useMemo)(() => new Map(scene.marks.map((m) => [m.key, m])), [scene]);
|
|
7987
|
+
(0, import_react60.useEffect)(() => () => drag.current?.end(), []);
|
|
7374
7988
|
const scenePoint = (e) => (0, import_chart2.chartClientToScene)(scene, svg.current.getBoundingClientRect(), e.clientX, e.clientY);
|
|
7375
7989
|
const onPointerDown = (e) => {
|
|
7376
7990
|
if (!editable || e.button !== 0) return;
|
|
@@ -7403,7 +8017,7 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
|
|
|
7403
8017
|
if (editable && (0, import_chart2.handleChartKey)(controller, scene, e)) e.preventDefault();
|
|
7404
8018
|
};
|
|
7405
8019
|
const label = state.spec.title || "Chart";
|
|
7406
|
-
return /* @__PURE__ */ (0,
|
|
8020
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { ref: wrapper, className: `w-full ${className ?? ""}`, "data-chart-canvas": "", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
7407
8021
|
"svg",
|
|
7408
8022
|
{
|
|
7409
8023
|
ref: svg,
|
|
@@ -7421,14 +8035,14 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
|
|
|
7421
8035
|
onKeyDown,
|
|
7422
8036
|
children: [
|
|
7423
8037
|
scene.marks.map((m) => renderChartMark(m, scene.theme.fontFamily, editable)),
|
|
7424
|
-
presence && /* @__PURE__ */ (0,
|
|
8038
|
+
presence && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ChartPresenceLayer, { presence })
|
|
7425
8039
|
]
|
|
7426
8040
|
}
|
|
7427
8041
|
) });
|
|
7428
8042
|
}
|
|
7429
8043
|
|
|
7430
8044
|
// src/chart/ChartDataGrid.tsx
|
|
7431
|
-
var
|
|
8045
|
+
var import_react61 = require("react");
|
|
7432
8046
|
var import_chart3 = require("@pixerate/editor/chart");
|
|
7433
8047
|
|
|
7434
8048
|
// src/chart/styles.ts
|
|
@@ -7441,11 +8055,11 @@ var chartSectionClass = "space-y-2 border-b border-border pb-3 last:border-b-0";
|
|
|
7441
8055
|
var chartCellClass = "h-7 w-full min-w-[4.5rem] bg-transparent px-2 text-right text-xs tabular-nums text-foreground focus-visible:bg-background focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-primary";
|
|
7442
8056
|
|
|
7443
8057
|
// src/chart/ChartDataGrid.tsx
|
|
7444
|
-
var
|
|
8058
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
7445
8059
|
function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
|
|
7446
|
-
const [draft, setDraft] = (0,
|
|
7447
|
-
const typing = (0,
|
|
7448
|
-
(0,
|
|
8060
|
+
const [draft, setDraft] = (0, import_react61.useState)(value);
|
|
8061
|
+
const typing = (0, import_react61.useRef)(false);
|
|
8062
|
+
(0, import_react61.useEffect)(() => {
|
|
7449
8063
|
if (!typing.current) setDraft(value);
|
|
7450
8064
|
}, [value]);
|
|
7451
8065
|
const commit = () => {
|
|
@@ -7454,7 +8068,7 @@ function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
|
|
|
7454
8068
|
if (draft === value) return;
|
|
7455
8069
|
if (onCommit(draft) === false) setDraft(value);
|
|
7456
8070
|
};
|
|
7457
|
-
return /* @__PURE__ */ (0,
|
|
8071
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
7458
8072
|
"input",
|
|
7459
8073
|
{
|
|
7460
8074
|
...rest,
|
|
@@ -7489,15 +8103,15 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
7489
8103
|
e.preventDefault();
|
|
7490
8104
|
controller.pasteCells(row, column, text);
|
|
7491
8105
|
};
|
|
7492
|
-
return /* @__PURE__ */ (0,
|
|
7493
|
-
/* @__PURE__ */ (0,
|
|
7494
|
-
/* @__PURE__ */ (0,
|
|
7495
|
-
/* @__PURE__ */ (0,
|
|
8106
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: `overflow-auto rounded-md border border-border ${className ?? ""}`, "data-chart-grid": "", children: [
|
|
8107
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("table", { className: "w-full border-collapse text-xs", children: [
|
|
8108
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("thead", { className: "bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("tr", { children: [
|
|
8109
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("th", { className: "border-b border-r border-border px-2 py-1 text-left font-medium text-muted-foreground", children: categoryHeader }),
|
|
7496
8110
|
spec.series.map((s, si) => {
|
|
7497
8111
|
const color = (0, import_chart3.chartSeriesColor)(spec, si);
|
|
7498
8112
|
const selected = selection?.kind === "series" && selection.seriesId === s.id;
|
|
7499
|
-
return /* @__PURE__ */ (0,
|
|
7500
|
-
/* @__PURE__ */ (0,
|
|
8113
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("th", { "data-series-id": s.id, className: `border-b border-r border-border px-1 py-1 font-medium ${selected ? "bg-primary/10" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
8114
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
7501
8115
|
"input",
|
|
7502
8116
|
{
|
|
7503
8117
|
type: "color",
|
|
@@ -7510,7 +8124,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
7510
8124
|
className: "h-5 w-5 shrink-0 cursor-pointer rounded border-0 bg-transparent p-0"
|
|
7511
8125
|
}
|
|
7512
8126
|
),
|
|
7513
|
-
/* @__PURE__ */ (0,
|
|
8127
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
7514
8128
|
ChartCommitInput,
|
|
7515
8129
|
{
|
|
7516
8130
|
value: s.name,
|
|
@@ -7520,8 +8134,8 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
7520
8134
|
className: `${chartInputClass} h-6 min-w-[5rem] border-transparent bg-transparent font-medium ${s.hidden ? "text-muted-foreground line-through" : ""}`
|
|
7521
8135
|
}
|
|
7522
8136
|
),
|
|
7523
|
-
!readOnly && /* @__PURE__ */ (0,
|
|
7524
|
-
/* @__PURE__ */ (0,
|
|
8137
|
+
!readOnly && /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_jsx_runtime41.Fragment, { children: [
|
|
8138
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
7525
8139
|
"button",
|
|
7526
8140
|
{
|
|
7527
8141
|
type: "button",
|
|
@@ -7534,16 +8148,16 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
7534
8148
|
children: s.hidden ? "\u25CB" : "\u25CF"
|
|
7535
8149
|
}
|
|
7536
8150
|
),
|
|
7537
|
-
/* @__PURE__ */ (0,
|
|
8151
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Delete series", "aria-label": `Delete ${s.name}`, "data-action": "remove-series", onClick: () => controller.removeSeries(s.id), children: "\xD7" })
|
|
7538
8152
|
] })
|
|
7539
8153
|
] }) }, s.id);
|
|
7540
8154
|
}),
|
|
7541
|
-
!readOnly && /* @__PURE__ */ (0,
|
|
8155
|
+
!readOnly && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("th", { className: "w-8 border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Add series", "aria-label": "Add series", "data-action": "add-series", onClick: () => controller.addSeries(), children: "+" }) })
|
|
7542
8156
|
] }) }),
|
|
7543
|
-
/* @__PURE__ */ (0,
|
|
8157
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("tbody", { children: spec.categories.map((category, i) => {
|
|
7544
8158
|
const rowSelected = selection?.kind === "category" && selection.index === i;
|
|
7545
|
-
return /* @__PURE__ */ (0,
|
|
7546
|
-
/* @__PURE__ */ (0,
|
|
8159
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("tr", { "data-category-index": i, className: rowSelected ? "bg-primary/10" : void 0, children: [
|
|
8160
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("th", { className: "border-b border-r border-border p-0 text-left font-normal", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
7547
8161
|
ChartCommitInput,
|
|
7548
8162
|
{
|
|
7549
8163
|
value: category,
|
|
@@ -7557,7 +8171,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
7557
8171
|
spec.series.map((s) => {
|
|
7558
8172
|
const value = s.values[i];
|
|
7559
8173
|
const selected = selection?.kind === "point" && selection.seriesId === s.id && selection.index === i;
|
|
7560
|
-
return /* @__PURE__ */ (0,
|
|
8174
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("td", { className: `border-b border-r border-border p-0 ${selected ? "bg-primary/10" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
7561
8175
|
ChartCommitInput,
|
|
7562
8176
|
{
|
|
7563
8177
|
value: value === null || value === void 0 ? "" : String(value),
|
|
@@ -7572,38 +8186,38 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
7572
8186
|
}
|
|
7573
8187
|
) }, s.id);
|
|
7574
8188
|
}),
|
|
7575
|
-
!readOnly && /* @__PURE__ */ (0,
|
|
8189
|
+
!readOnly && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("td", { className: "border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Delete category", "aria-label": `Delete ${category}`, "data-action": "remove-category", onClick: () => controller.removeCategory(i), children: "\xD7" }) })
|
|
7576
8190
|
] }, i);
|
|
7577
8191
|
}) })
|
|
7578
8192
|
] }),
|
|
7579
|
-
!readOnly && /* @__PURE__ */ (0,
|
|
8193
|
+
!readOnly && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "p-1", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: `${chartButtonClass} h-6 border-dashed`, "data-action": "add-category", onClick: () => controller.addCategory(), children: "+ Add category" }) })
|
|
7580
8194
|
] });
|
|
7581
8195
|
}
|
|
7582
8196
|
|
|
7583
8197
|
// src/chart/ChartInspector.tsx
|
|
7584
|
-
var
|
|
8198
|
+
var import_react62 = require("react");
|
|
7585
8199
|
var import_chart4 = require("@pixerate/editor/chart");
|
|
7586
|
-
var
|
|
8200
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
7587
8201
|
var cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
7588
8202
|
function Field({ label, htmlFor, children }) {
|
|
7589
|
-
return /* @__PURE__ */ (0,
|
|
7590
|
-
/* @__PURE__ */ (0,
|
|
7591
|
-
/* @__PURE__ */ (0,
|
|
8203
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
8204
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("label", { htmlFor, className: `${chartLabelClass} w-20 shrink-0`, children: label }),
|
|
8205
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "min-w-0 flex-1", children })
|
|
7592
8206
|
] });
|
|
7593
8207
|
}
|
|
7594
8208
|
function Toggle({ label, checked, onChange, name }) {
|
|
7595
|
-
return /* @__PURE__ */ (0,
|
|
7596
|
-
/* @__PURE__ */ (0,
|
|
8209
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("label", { className: "flex cursor-pointer items-center gap-2 text-xs text-foreground", children: [
|
|
8210
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("input", { type: "checkbox", className: "h-3.5 w-3.5 accent-primary", checked, "data-option": name, onChange: (e) => onChange(e.currentTarget.checked) }),
|
|
7597
8211
|
label
|
|
7598
8212
|
] });
|
|
7599
8213
|
}
|
|
7600
8214
|
function Select({ id, value, options, onChange, name, labels }) {
|
|
7601
|
-
return /* @__PURE__ */ (0,
|
|
8215
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("select", { id, className: chartInputClass, value, "data-option": name, onChange: (e) => onChange(e.currentTarget.value), children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: o, children: labels?.[o] ?? cap(o) }, o)) });
|
|
7602
8216
|
}
|
|
7603
8217
|
function AxisSection({ controller, axis, value, idBase, horizontal, numeric = false, scales = false }) {
|
|
7604
8218
|
const set = (patch) => controller.setAxis(axis, patch);
|
|
7605
8219
|
const setFormat = (patch) => set({ format: { ...value.format, ...patch } });
|
|
7606
|
-
const bound = (key2) => /* @__PURE__ */ (0,
|
|
8220
|
+
const bound = (key2) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7607
8221
|
ChartCommitInput,
|
|
7608
8222
|
{
|
|
7609
8223
|
id: `${idBase}-${axis}-${key2}`,
|
|
@@ -7618,26 +8232,26 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
|
|
|
7618
8232
|
const name = axis === "x" ? numeric ? "X axis" : "Category axis" : axis === "y" ? "Value axis" : "Secondary axis";
|
|
7619
8233
|
const valueAxis = axis !== "x" || numeric;
|
|
7620
8234
|
const key = axis === "y2" ? "yAxis2" : `${axis}Axis`;
|
|
7621
|
-
return /* @__PURE__ */ (0,
|
|
7622
|
-
/* @__PURE__ */ (0,
|
|
7623
|
-
/* @__PURE__ */ (0,
|
|
8235
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": `axis-${axis}`, children: [
|
|
8236
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
8237
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("h4", { className: "text-xs font-semibold text-foreground", children: [
|
|
7624
8238
|
name,
|
|
7625
|
-
/* @__PURE__ */ (0,
|
|
8239
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "ml-1 font-normal text-muted-foreground", children: [
|
|
7626
8240
|
"(",
|
|
7627
8241
|
axis === "x" ? horizontal ? "left" : "bottom" : axis === "y2" ? horizontal ? "top" : "right" : horizontal ? "bottom" : "left",
|
|
7628
8242
|
")"
|
|
7629
8243
|
] })
|
|
7630
8244
|
] }),
|
|
7631
|
-
/* @__PURE__ */ (0,
|
|
8245
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Show", name: `${axis}Axis.show`, checked: value.show, onChange: (show) => set({ show }) })
|
|
7632
8246
|
] }),
|
|
7633
|
-
/* @__PURE__ */ (0,
|
|
7634
|
-
/* @__PURE__ */ (0,
|
|
7635
|
-
/* @__PURE__ */ (0,
|
|
7636
|
-
axis === "x" && !numeric && /* @__PURE__ */ (0,
|
|
7637
|
-
scales && /* @__PURE__ */ (0,
|
|
7638
|
-
scales && valueAxis && /* @__PURE__ */ (0,
|
|
8247
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Title", htmlFor: `${idBase}-${axis}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartCommitInput, { id: `${idBase}-${axis}-title`, value: value.title, "data-option": `${axis}Axis.title`, className: chartInputClass, onCommit: (title) => void set({ title }) }) }),
|
|
8248
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
|
|
8249
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Grid lines", name: `${key}.gridlines`, checked: value.gridlines, onChange: (gridlines) => set({ gridlines }) }),
|
|
8250
|
+
axis === "x" && !numeric && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Dates", name: "xAxis.kind", checked: value.kind === "date", onChange: (dates) => set({ kind: dates ? "date" : void 0 }) }),
|
|
8251
|
+
scales && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Reverse", name: `${key}.reverse`, checked: !!value.reverse, onChange: (reverse) => set({ reverse }) }),
|
|
8252
|
+
scales && valueAxis && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Log scale", name: `${key}.scale`, checked: value.scale === "log", onChange: (log) => set({ scale: log ? "log" : "linear" }) })
|
|
7639
8253
|
] }),
|
|
7640
|
-
scales && valueAxis && value.scale === "log" && /* @__PURE__ */ (0,
|
|
8254
|
+
scales && valueAxis && value.scale === "log" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Log base", htmlFor: `${idBase}-${axis}-log-base`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7641
8255
|
ChartCommitInput,
|
|
7642
8256
|
{
|
|
7643
8257
|
id: `${idBase}-${axis}-log-base`,
|
|
@@ -7648,7 +8262,7 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
|
|
|
7648
8262
|
onCommit: (text) => set({ logBase: text.trim() === "" ? void 0 : Number(text) }).ok
|
|
7649
8263
|
}
|
|
7650
8264
|
) }),
|
|
7651
|
-
valueAxis && value.scale !== "log" && /* @__PURE__ */ (0,
|
|
8265
|
+
valueAxis && value.scale !== "log" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Step", htmlFor: `${idBase}-${axis}-step`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7652
8266
|
ChartCommitInput,
|
|
7653
8267
|
{
|
|
7654
8268
|
id: `${idBase}-${axis}-step`,
|
|
@@ -7660,14 +8274,14 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
|
|
|
7660
8274
|
onCommit: (text) => set({ step: text.trim() === "" ? null : Number(text) }).ok
|
|
7661
8275
|
}
|
|
7662
8276
|
) }),
|
|
7663
|
-
valueAxis && /* @__PURE__ */ (0,
|
|
7664
|
-
/* @__PURE__ */ (0,
|
|
8277
|
+
valueAxis && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
|
|
8278
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Min / max", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex gap-1", children: [
|
|
7665
8279
|
bound("min"),
|
|
7666
8280
|
bound("max")
|
|
7667
8281
|
] }) }),
|
|
7668
|
-
/* @__PURE__ */ (0,
|
|
7669
|
-
/* @__PURE__ */ (0,
|
|
7670
|
-
/* @__PURE__ */ (0,
|
|
8282
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Format", htmlFor: `${idBase}-${axis}-format`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex gap-1", children: [
|
|
8283
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Select, { id: `${idBase}-${axis}-format`, name: `${key}.format.style`, value: value.format.style ?? "number", options: import_chart4.CHART_NUMBER_STYLES, onChange: (style) => setFormat({ style }) }),
|
|
8284
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7671
8285
|
ChartCommitInput,
|
|
7672
8286
|
{
|
|
7673
8287
|
value: value.format.decimals === void 0 ? "" : String(value.format.decimals),
|
|
@@ -7686,8 +8300,8 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
|
|
|
7686
8300
|
}
|
|
7687
8301
|
)
|
|
7688
8302
|
] }) }),
|
|
7689
|
-
value.format.style === "currency" && /* @__PURE__ */ (0,
|
|
7690
|
-
/* @__PURE__ */ (0,
|
|
8303
|
+
value.format.style === "currency" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Currency", htmlFor: `${idBase}-${axis}-currency`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartCommitInput, { id: `${idBase}-${axis}-currency`, value: value.format.currency ?? "USD", "data-option": `${key}.format.currency`, className: chartInputClass, onCommit: (currency) => void setFormat({ currency: currency.toUpperCase() }) }) }),
|
|
8304
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Code", htmlFor: `${idBase}-${axis}-code`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7691
8305
|
ChartCommitInput,
|
|
7692
8306
|
{
|
|
7693
8307
|
id: `${idBase}-${axis}-code`,
|
|
@@ -7713,15 +8327,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
|
|
|
7713
8327
|
const values = which === "xErrorBars" ? series.x ?? [] : series.values;
|
|
7714
8328
|
const set = (next) => controller.updateSeries(series.id, { [which]: next });
|
|
7715
8329
|
const patch = (p) => bars && set({ ...bars, ...p });
|
|
7716
|
-
return /* @__PURE__ */ (0,
|
|
7717
|
-
/* @__PURE__ */ (0,
|
|
7718
|
-
/* @__PURE__ */ (0,
|
|
7719
|
-
import_chart4.CHART_ERROR_BAR_TYPES.map((t) => /* @__PURE__ */ (0,
|
|
8330
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "space-y-1.5", "data-section": which === "errorBars" ? "error-bars" : "x-error-bars", children: [
|
|
8331
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: which === "errorBars" ? "Error bars" : "X error bars", htmlFor: `${id}-type`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("select", { id: `${id}-type`, className: chartInputClass, value: bars?.type ?? "", "data-option": `${key}.type`, onChange: (e) => set((0, import_chart4.chartErrorBarsOfType)(e.currentTarget.value, bars, values)), children: [
|
|
8332
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "None" }),
|
|
8333
|
+
import_chart4.CHART_ERROR_BAR_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: t, children: import_chart4.CHART_ERROR_BAR_LABELS[t] }, t))
|
|
7720
8334
|
] }) }),
|
|
7721
|
-
bars && (bars.type === "fixed" || bars.type === "percent" || bars.type === "stddev") && /* @__PURE__ */ (0,
|
|
7722
|
-
bars?.type === "custom" && /* @__PURE__ */ (0,
|
|
7723
|
-
/* @__PURE__ */ (0,
|
|
7724
|
-
/* @__PURE__ */ (0,
|
|
8335
|
+
bars && (bars.type === "fixed" || bars.type === "percent" || bars.type === "stddev") && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: bars.type === "percent" ? "Percent" : bars.type === "stddev" ? "Deviations" : "Amount", htmlFor: `${id}-value`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartCommitInput, { id: `${id}-value`, value: String(bars.value ?? (0, import_chart4.defaultChartErrorBarValue)(bars.type)), inputMode: "decimal", "data-option": `${key}.value`, className: chartInputClass, onCommit: (text) => !!patch({ value: text.trim() === "" ? void 0 : Number(text) })?.ok }) }),
|
|
8336
|
+
bars?.type === "custom" && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
|
|
8337
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Plus", htmlFor: `${id}-plus`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartCommitInput, { id: `${id}-plus`, value: (0, import_chart4.formatChartAmountList)(bars.plus), placeholder: "1, 2, -, 0.5", "data-option": `${key}.plus`, className: chartInputClass, onCommit: (text) => !!patch({ plus: (0, import_chart4.parseChartAmountList)(text) })?.ok }) }),
|
|
8338
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Minus", htmlFor: `${id}-minus`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7725
8339
|
ChartCommitInput,
|
|
7726
8340
|
{
|
|
7727
8341
|
id: `${id}-minus`,
|
|
@@ -7738,15 +8352,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
|
|
|
7738
8352
|
}
|
|
7739
8353
|
) })
|
|
7740
8354
|
] }),
|
|
7741
|
-
bars && /* @__PURE__ */ (0,
|
|
7742
|
-
/* @__PURE__ */ (0,
|
|
7743
|
-
/* @__PURE__ */ (0,
|
|
8355
|
+
bars && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
8356
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("select", { className: `${chartInputClass} flex-1`, "aria-label": "Error bar direction", value: bars.direction ?? "both", "data-option": `${key}.direction`, onChange: (e) => patch({ direction: e.currentTarget.value }), children: import_chart4.CHART_ERROR_BAR_DIRECTIONS.map((d) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: d, children: d === "both" ? "Both ways" : d === "plus" ? "Plus only" : "Minus only" }, d)) }),
|
|
8357
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Caps", name: `${key}.cap`, checked: bars.cap !== false, onChange: (cap2) => patch({ cap: cap2 }) })
|
|
7744
8358
|
] })
|
|
7745
8359
|
] });
|
|
7746
8360
|
}
|
|
7747
8361
|
function ChartInspector({ controller, sections, className }) {
|
|
7748
8362
|
const { spec, selectedSeries } = useChartState(controller);
|
|
7749
|
-
const idBase = (0,
|
|
8363
|
+
const idBase = (0, import_react62.useId)();
|
|
7750
8364
|
const show = (section) => !sections || sections.includes(section);
|
|
7751
8365
|
const cartesian = (0, import_chart4.isCartesianChart)(spec.type);
|
|
7752
8366
|
const family = (0, import_chart4.chartFamily)(spec);
|
|
@@ -7758,29 +8372,29 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7758
8372
|
const hasLines = cartesian && types.some((t) => t === "line" || t === "area");
|
|
7759
8373
|
const seriesIndex = selectedSeries ? spec.series.findIndex((s) => s.id === selectedSeries.id) : -1;
|
|
7760
8374
|
const scales = family === "cartesian" || family === "xy";
|
|
7761
|
-
return /* @__PURE__ */ (0,
|
|
7762
|
-
show("type") && /* @__PURE__ */ (0,
|
|
7763
|
-
show("style") && /* @__PURE__ */ (0,
|
|
7764
|
-
/* @__PURE__ */ (0,
|
|
7765
|
-
/* @__PURE__ */ (0,
|
|
7766
|
-
import_chart4.CHART_LAYOUT_PRESETS.map((p) => /* @__PURE__ */ (0,
|
|
8375
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: `space-y-3 text-xs ${className ?? ""}`, "data-chart-inspector": "", children: [
|
|
8376
|
+
show("type") && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: chartSectionClass, "data-section": "type", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "grid grid-cols-3 gap-0.5 rounded-md bg-muted p-0.5", role: "radiogroup", "aria-label": "Chart type", children: import_chart4.CHART_TYPES.map((type) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", role: "radio", "aria-checked": spec.type === type, "data-chart-type": type, className: chartSegmentClass(spec.type === type), onClick: () => controller.setType(type), children: import_chart4.CHART_TYPE_LABELS[type] }, type)) }) }),
|
|
8377
|
+
show("style") && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "style", children: [
|
|
8378
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Layout", htmlFor: `${idBase}-layout`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("select", { id: `${idBase}-layout`, className: chartInputClass, value: "", "data-option": "preset.layout", onChange: (e) => e.currentTarget.value && controller.applyPreset({ layout: e.currentTarget.value }), children: [
|
|
8379
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Quick layout\u2026" }),
|
|
8380
|
+
import_chart4.CHART_LAYOUT_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: p.id, title: p.description, children: p.label }, p.id))
|
|
7767
8381
|
] }) }),
|
|
7768
|
-
/* @__PURE__ */ (0,
|
|
7769
|
-
/* @__PURE__ */ (0,
|
|
7770
|
-
import_chart4.CHART_COLOR_SCHEMES.map((c) => /* @__PURE__ */ (0,
|
|
8382
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Colours", htmlFor: `${idBase}-colors`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("select", { id: `${idBase}-colors`, className: chartInputClass, value: import_chart4.CHART_COLOR_SCHEMES.find((c) => c.palette.join() === spec.palette.join())?.id ?? "", "data-option": "preset.colors", onChange: (e) => e.currentTarget.value && controller.applyPreset({ colors: e.currentTarget.value }), children: [
|
|
8383
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Custom" }),
|
|
8384
|
+
import_chart4.CHART_COLOR_SCHEMES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: c.id, title: c.description, children: c.label }, c.id))
|
|
7771
8385
|
] }) }),
|
|
7772
|
-
!colorCheck.ok && /* @__PURE__ */ (0,
|
|
7773
|
-
/* @__PURE__ */ (0,
|
|
8386
|
+
!colorCheck.ok && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-[11px] leading-snug text-amber-600 dark:text-amber-400", "data-chart-color-warning": "", children: colorCheck.issues[0] }),
|
|
8387
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "transpose", onClick: () => controller.transpose(), children: "Switch rows and columns" })
|
|
7774
8388
|
] }),
|
|
7775
|
-
show("titles") && /* @__PURE__ */ (0,
|
|
7776
|
-
/* @__PURE__ */ (0,
|
|
7777
|
-
/* @__PURE__ */ (0,
|
|
8389
|
+
show("titles") && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "titles", children: [
|
|
8390
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Title", htmlFor: `${idBase}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartCommitInput, { id: `${idBase}-title`, value: spec.title, "data-option": "title", className: chartInputClass, onCommit: (title) => void controller.setTitle(title) }) }),
|
|
8391
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Subtitle", htmlFor: `${idBase}-subtitle`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartCommitInput, { id: `${idBase}-subtitle`, value: spec.subtitle, "data-option": "subtitle", className: chartInputClass, onCommit: (subtitle) => void controller.setSubtitle(subtitle) }) })
|
|
7778
8392
|
] }),
|
|
7779
|
-
show("options") && /* @__PURE__ */ (0,
|
|
7780
|
-
cartesian && /* @__PURE__ */ (0,
|
|
7781
|
-
hasBars && /* @__PURE__ */ (0,
|
|
7782
|
-
hasLines && /* @__PURE__ */ (0,
|
|
7783
|
-
spec.type === "donut" && /* @__PURE__ */ (0,
|
|
8393
|
+
show("options") && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "options", children: [
|
|
8394
|
+
cartesian && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Stacking", htmlFor: `${idBase}-stacking`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Select, { id: `${idBase}-stacking`, name: "stacking", value: spec.stacking, options: import_chart4.CHART_STACKINGS, labels: { none: "None", stacked: "Stacked", percent: "100%" }, onChange: (stacking) => controller.update({ stacking }) }) }),
|
|
8395
|
+
hasBars && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Bars", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex gap-0.5 rounded-md bg-muted p-0.5", children: ["vertical", "horizontal"].map((o) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", "aria-pressed": spec.orientation === o, "data-option": `orientation.${o}`, className: chartSegmentClass(spec.orientation === o), onClick: () => controller.update({ orientation: o }), children: cap(o) }, o)) }) }),
|
|
8396
|
+
hasLines && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Lines", htmlFor: `${idBase}-curve`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Select, { id: `${idBase}-curve`, name: "curve", value: spec.curve, options: import_chart4.CHART_CURVES, onChange: (curve) => controller.update({ curve }) }) }),
|
|
8397
|
+
spec.type === "donut" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Hole", htmlFor: `${idBase}-hole`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7784
8398
|
"input",
|
|
7785
8399
|
{
|
|
7786
8400
|
id: `${idBase}-hole`,
|
|
@@ -7796,7 +8410,7 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7796
8410
|
onChange: (e) => controller.update({ innerRadius: Number(e.currentTarget.value) })
|
|
7797
8411
|
}
|
|
7798
8412
|
) }),
|
|
7799
|
-
hasBars && /* @__PURE__ */ (0,
|
|
8413
|
+
hasBars && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Spacing", htmlFor: `${idBase}-gap`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7800
8414
|
"input",
|
|
7801
8415
|
{
|
|
7802
8416
|
id: `${idBase}-gap`,
|
|
@@ -7812,31 +8426,31 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7812
8426
|
onChange: (e) => controller.update({ gapWidth: Number(e.currentTarget.value) })
|
|
7813
8427
|
}
|
|
7814
8428
|
) }),
|
|
7815
|
-
spec.dataLabels && hasBars && /* @__PURE__ */ (0,
|
|
7816
|
-
spec.type === "histogram" && /* @__PURE__ */ (0,
|
|
7817
|
-
/* @__PURE__ */ (0,
|
|
7818
|
-
spec.type === "waterfall" && /* @__PURE__ */ (0,
|
|
7819
|
-
hasLines && /* @__PURE__ */ (0,
|
|
7820
|
-
/* @__PURE__ */ (0,
|
|
8429
|
+
spec.dataLabels && hasBars && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Labels", htmlFor: `${idBase}-label-position`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Select, { id: `${idBase}-label-position`, name: "labelPosition", value: spec.labelPosition, options: import_chart4.CHART_LABEL_POSITIONS, onChange: (labelPosition) => controller.update({ labelPosition }) }) }),
|
|
8430
|
+
spec.type === "histogram" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Bins", htmlFor: `${idBase}-bins`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartCommitInput, { id: `${idBase}-bins`, value: spec.bins === null ? "" : String(spec.bins), placeholder: "Auto", inputMode: "numeric", "data-option": "bins", className: chartInputClass, onCommit: (text) => controller.update({ bins: text.trim() === "" ? null : Number(text) }).ok }) }),
|
|
8431
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
|
|
8432
|
+
spec.type === "waterfall" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Total bar", name: "showTotal", checked: spec.showTotal, onChange: (showTotal) => controller.update({ showTotal }) }),
|
|
8433
|
+
hasLines && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Points", name: "points", checked: spec.points, onChange: (points) => controller.update({ points }) }),
|
|
8434
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Data labels", name: "dataLabels", checked: spec.dataLabels, onChange: (dataLabels) => controller.update({ dataLabels }) })
|
|
7821
8435
|
] })
|
|
7822
8436
|
] }),
|
|
7823
|
-
show("legend") && /* @__PURE__ */ (0,
|
|
7824
|
-
/* @__PURE__ */ (0,
|
|
7825
|
-
/* @__PURE__ */ (0,
|
|
7826
|
-
/* @__PURE__ */ (0,
|
|
8437
|
+
show("legend") && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "legend", children: [
|
|
8438
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
8439
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Legend" }),
|
|
8440
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Show", name: "legend.show", checked: spec.legend.show, onChange: (v) => controller.setLegend({ show: v }) })
|
|
7827
8441
|
] }),
|
|
7828
|
-
spec.legend.show && /* @__PURE__ */ (0,
|
|
8442
|
+
spec.legend.show && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex gap-0.5 rounded-md bg-muted p-0.5", children: import_chart4.CHART_LEGEND_POSITIONS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", "aria-pressed": spec.legend.position === p, "data-option": `legend.${p}`, className: chartSegmentClass(spec.legend.position === p), onClick: () => controller.setLegend({ position: p }), children: cap(p) }, p)) })
|
|
7829
8443
|
] }),
|
|
7830
|
-
show("axes") && hasAxes && /* @__PURE__ */ (0,
|
|
7831
|
-
family !== "box" && family !== "histogram" && /* @__PURE__ */ (0,
|
|
7832
|
-
/* @__PURE__ */ (0,
|
|
7833
|
-
usesSecondary && /* @__PURE__ */ (0,
|
|
8444
|
+
show("axes") && hasAxes && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
|
|
8445
|
+
family !== "box" && family !== "histogram" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(AxisSection, { controller, axis: "x", value: spec.xAxis, idBase, horizontal: spec.orientation === "horizontal", numeric: family === "xy", scales }),
|
|
8446
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(AxisSection, { controller, axis: "y", value: spec.yAxis, idBase, horizontal: spec.orientation === "horizontal", scales }),
|
|
8447
|
+
usesSecondary && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(AxisSection, { controller, axis: "y2", value: spec.yAxis2, idBase, horizontal: spec.orientation === "horizontal", scales })
|
|
7834
8448
|
] }),
|
|
7835
|
-
show("series") && selectedSeries && /* @__PURE__ */ (0,
|
|
7836
|
-
/* @__PURE__ */ (0,
|
|
7837
|
-
/* @__PURE__ */ (0,
|
|
7838
|
-
/* @__PURE__ */ (0,
|
|
7839
|
-
/* @__PURE__ */ (0,
|
|
8449
|
+
show("series") && selectedSeries && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "series", "data-series-id": selectedSeries.id, children: [
|
|
8450
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Series" }),
|
|
8451
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Name", htmlFor: `${idBase}-series-name`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartCommitInput, { id: `${idBase}-series-name`, value: selectedSeries.name, "data-option": "series.name", className: chartInputClass, onCommit: (name) => void controller.updateSeries(selectedSeries.id, { name }) }) }),
|
|
8452
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Colour", htmlFor: `${idBase}-series-color`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
8453
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7840
8454
|
"input",
|
|
7841
8455
|
{
|
|
7842
8456
|
id: `${idBase}-series-color`,
|
|
@@ -7849,9 +8463,9 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7849
8463
|
onChange: (e) => controller.updateSeries(selectedSeries.id, { color: e.currentTarget.value })
|
|
7850
8464
|
}
|
|
7851
8465
|
),
|
|
7852
|
-
selectedSeries.color && /* @__PURE__ */ (0,
|
|
8466
|
+
selectedSeries.color && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "reset-color", onClick: () => controller.updateSeries(selectedSeries.id, { color: null }), children: "Palette" })
|
|
7853
8467
|
] }) }),
|
|
7854
|
-
cartesian && /* @__PURE__ */ (0,
|
|
8468
|
+
cartesian && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Draw as", htmlFor: `${idBase}-series-type`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
7855
8469
|
"select",
|
|
7856
8470
|
{
|
|
7857
8471
|
id: `${idBase}-series-type`,
|
|
@@ -7860,12 +8474,12 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7860
8474
|
"data-option": "series.type",
|
|
7861
8475
|
onChange: (e) => controller.updateSeries(selectedSeries.id, { type: e.currentTarget.value || null }),
|
|
7862
8476
|
children: [
|
|
7863
|
-
/* @__PURE__ */ (0,
|
|
7864
|
-
import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0,
|
|
8477
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Chart type" }),
|
|
8478
|
+
import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: t, children: import_chart4.CHART_TYPE_LABELS[t] }, t))
|
|
7865
8479
|
]
|
|
7866
8480
|
}
|
|
7867
8481
|
) }),
|
|
7868
|
-
(cartesian || family === "xy") && ["line", "area", "scatter"].includes((0, import_chart4.chartSeriesType)(spec, selectedSeries)) && /* @__PURE__ */ (0,
|
|
8482
|
+
(cartesian || family === "xy") && ["line", "area", "scatter"].includes((0, import_chart4.chartSeriesType)(spec, selectedSeries)) && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Marker", htmlFor: `${idBase}-series-marker`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
7869
8483
|
"select",
|
|
7870
8484
|
{
|
|
7871
8485
|
id: `${idBase}-series-marker`,
|
|
@@ -7874,20 +8488,20 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7874
8488
|
"data-option": "series.marker",
|
|
7875
8489
|
onChange: (e) => controller.updateSeries(selectedSeries.id, { marker: e.currentTarget.value || null }),
|
|
7876
8490
|
children: [
|
|
7877
|
-
/* @__PURE__ */ (0,
|
|
7878
|
-
import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0,
|
|
8491
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Default" }),
|
|
8492
|
+
import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: m, children: cap(m) }, m))
|
|
7879
8493
|
]
|
|
7880
8494
|
}
|
|
7881
8495
|
) }),
|
|
7882
|
-
scales && /* @__PURE__ */ (0,
|
|
7883
|
-
family === "xy" && /* @__PURE__ */ (0,
|
|
7884
|
-
(0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0,
|
|
7885
|
-
(selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0,
|
|
7886
|
-
/* @__PURE__ */ (0,
|
|
7887
|
-
/* @__PURE__ */ (0,
|
|
7888
|
-
/* @__PURE__ */ (0,
|
|
8496
|
+
scales && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "errorBars", idBase }),
|
|
8497
|
+
family === "xy" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "xErrorBars", idBase }),
|
|
8498
|
+
(0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "space-y-1", "data-section": "trendlines", children: [
|
|
8499
|
+
(selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-1", "data-trendline": i, children: [
|
|
8500
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "flex-1 truncate text-muted-foreground", children: (0, import_chart4.chartTrendlineName)(t, selectedSeries.name) }),
|
|
8501
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "R\xB2", name: `trendline.${i}.showR2`, checked: !!t.showR2, onChange: (showR2) => controller.updateTrendline(selectedSeries.id, i, { showR2 }) }),
|
|
8502
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: chartButtonClass, "aria-label": "Delete trendline", "data-action": "trendline-delete", onClick: () => controller.removeTrendline(selectedSeries.id, i), children: "\xD7" })
|
|
7889
8503
|
] }, i)),
|
|
7890
|
-
/* @__PURE__ */ (0,
|
|
8504
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
7891
8505
|
"select",
|
|
7892
8506
|
{
|
|
7893
8507
|
className: chartInputClass,
|
|
@@ -7896,32 +8510,32 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7896
8510
|
"data-option": "trendline.add",
|
|
7897
8511
|
onChange: (e) => e.currentTarget.value && controller.addTrendline(selectedSeries.id, { type: e.currentTarget.value }),
|
|
7898
8512
|
children: [
|
|
7899
|
-
/* @__PURE__ */ (0,
|
|
7900
|
-
import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0,
|
|
8513
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Add trendline\u2026" }),
|
|
8514
|
+
import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: t, children: cap(t.replace("-", " ")) }, t))
|
|
7901
8515
|
]
|
|
7902
8516
|
}
|
|
7903
8517
|
)
|
|
7904
8518
|
] }),
|
|
7905
|
-
/* @__PURE__ */ (0,
|
|
7906
|
-
/* @__PURE__ */ (0,
|
|
7907
|
-
family === "cartesian" && /* @__PURE__ */ (0,
|
|
7908
|
-
/* @__PURE__ */ (0,
|
|
7909
|
-
/* @__PURE__ */ (0,
|
|
7910
|
-
/* @__PURE__ */ (0,
|
|
7911
|
-
/* @__PURE__ */ (0,
|
|
8519
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
8520
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Hidden", name: "series.hidden", checked: !!selectedSeries.hidden, onChange: (hidden) => controller.updateSeries(selectedSeries.id, { hidden }) }),
|
|
8521
|
+
family === "cartesian" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Secondary axis", name: "series.axis", checked: selectedSeries.axis === "secondary", onChange: (secondary) => controller.updateSeries(selectedSeries.id, { axis: secondary ? "secondary" : null }) }),
|
|
8522
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "flex-1" }),
|
|
8523
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: chartButtonClass, disabled: seriesIndex <= 0, "aria-label": "Move series earlier", "data-action": "series-up", onClick: () => controller.moveSeries(selectedSeries.id, seriesIndex - 1), children: "\u2191" }),
|
|
8524
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: chartButtonClass, disabled: seriesIndex >= spec.series.length - 1, "aria-label": "Move series later", "data-action": "series-down", onClick: () => controller.moveSeries(selectedSeries.id, seriesIndex + 1), children: "\u2193" }),
|
|
8525
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: `${chartButtonClass} text-destructive`, "data-action": "series-delete", onClick: () => controller.removeSeries(selectedSeries.id), children: "Delete" })
|
|
7912
8526
|
] })
|
|
7913
8527
|
] })
|
|
7914
8528
|
] });
|
|
7915
8529
|
}
|
|
7916
8530
|
|
|
7917
8531
|
// src/chart-node/ChartNodeView.tsx
|
|
7918
|
-
var
|
|
8532
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
7919
8533
|
function ChartNodeView({ state, theme, showDataGrid = true }) {
|
|
7920
8534
|
const { controller, editing, editable, selected, width, height, setEditing } = state;
|
|
7921
8535
|
const open = () => {
|
|
7922
8536
|
if (editable && !editing) setEditing(true);
|
|
7923
8537
|
};
|
|
7924
|
-
return /* @__PURE__ */ (0,
|
|
8538
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
7925
8539
|
"div",
|
|
7926
8540
|
{
|
|
7927
8541
|
className: `not-prose my-2 rounded-md border bg-background p-1 ${selected ? "border-primary ring-1 ring-primary" : "border-border"}`,
|
|
@@ -7934,24 +8548,24 @@ function ChartNodeView({ state, theme, showDataGrid = true }) {
|
|
|
7934
8548
|
}
|
|
7935
8549
|
},
|
|
7936
8550
|
children: [
|
|
7937
|
-
editing && /* @__PURE__ */ (0,
|
|
7938
|
-
/* @__PURE__ */ (0,
|
|
7939
|
-
/* @__PURE__ */ (0,
|
|
8551
|
+
editing && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "mb-1 flex items-center justify-between gap-2 px-1", "data-chart-node-toolbar": "", children: [
|
|
8552
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-xs text-muted-foreground", children: "Editing chart" }),
|
|
8553
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "done", onClick: () => setEditing(false), children: "Done" })
|
|
7940
8554
|
] }),
|
|
7941
|
-
/* @__PURE__ */ (0,
|
|
8555
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
7942
8556
|
"div",
|
|
7943
8557
|
{
|
|
7944
8558
|
className: editable && !editing ? "cursor-pointer" : void 0,
|
|
7945
8559
|
onClick: open,
|
|
7946
8560
|
title: editable && !editing ? "Click to edit the chart" : void 0,
|
|
7947
8561
|
"data-chart-node-canvas": "",
|
|
7948
|
-
children: /* @__PURE__ */ (0,
|
|
8562
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ChartCanvas, { controller, width: width ?? 640, height, responsive: width === null, editable: editing, theme })
|
|
7949
8563
|
}
|
|
7950
8564
|
),
|
|
7951
8565
|
editing && // Wraps by the document's width, not the viewport's: side by side when there is room.
|
|
7952
|
-
/* @__PURE__ */ (0,
|
|
7953
|
-
showDataGrid && /* @__PURE__ */ (0,
|
|
7954
|
-
/* @__PURE__ */ (0,
|
|
8566
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "mt-2 flex flex-wrap items-start gap-2", "data-chart-node-panel": "", children: [
|
|
8567
|
+
showDataGrid && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "min-w-0 flex-[1_1_20rem] overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ChartDataGrid, { controller }) }),
|
|
8568
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ChartInspector, { controller, className: "max-h-96 min-w-0 flex-[1_1_16rem] overflow-y-auto rounded-md border border-border p-3" })
|
|
7955
8569
|
] })
|
|
7956
8570
|
]
|
|
7957
8571
|
}
|
|
@@ -7969,7 +8583,7 @@ function createReactChartNodeView(options = {}) {
|
|
|
7969
8583
|
scheduled = true;
|
|
7970
8584
|
queueMicrotask(() => {
|
|
7971
8585
|
scheduled = false;
|
|
7972
|
-
if (!destroyed) root.render(/* @__PURE__ */ (0,
|
|
8586
|
+
if (!destroyed) root.render(/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Component, { ...props, state: latest }));
|
|
7973
8587
|
});
|
|
7974
8588
|
};
|
|
7975
8589
|
schedule();
|
|
@@ -7989,6 +8603,7 @@ function createReactChartNodeView(options = {}) {
|
|
|
7989
8603
|
0 && (module.exports = {
|
|
7990
8604
|
AdjustmentLayersPanel,
|
|
7991
8605
|
AssetMentionChips,
|
|
8606
|
+
BrushOptionsBar,
|
|
7992
8607
|
BubbleMenu,
|
|
7993
8608
|
ChartNodeView,
|
|
7994
8609
|
CommandPalette,
|
|
@@ -8009,6 +8624,7 @@ function createReactChartNodeView(options = {}) {
|
|
|
8009
8624
|
ImageEditor,
|
|
8010
8625
|
InsertTableGrid,
|
|
8011
8626
|
JobProgress,
|
|
8627
|
+
LayersPanel,
|
|
8012
8628
|
MergePreview,
|
|
8013
8629
|
NameManager,
|
|
8014
8630
|
OutlinePanel,
|