@pixerate/editor-react 0.58.0 → 0.59.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-SYTV33TW.js} +810 -254
- package/dist/chunk-SYTV33TW.js.map +1 -0
- package/dist/image-editor/index.cjs +822 -275
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +26 -1
- package/dist/image-editor/index.d.ts +26 -1
- package/dist/image-editor/index.js +5 -1
- package/dist/index.cjs +1251 -704
- 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,
|
|
@@ -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,458 @@ 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, 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 commitNext = (0, import_react38.useRef)(true);
|
|
4264
|
+
const state = controller.getState();
|
|
4265
|
+
const rows = (0, import_image_editor6.layerPanelRows)(state.layers, state.activeLayerId);
|
|
4266
|
+
const active = controller.getActiveLayer();
|
|
4267
|
+
const attempt = (fn) => {
|
|
4268
|
+
try {
|
|
4269
|
+
setError(null);
|
|
4270
|
+
fn();
|
|
4271
|
+
} catch (err) {
|
|
4272
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4273
|
+
}
|
|
4274
|
+
};
|
|
4275
|
+
const run = async (action) => {
|
|
4276
|
+
setMenu(null);
|
|
4277
|
+
setError(await (0, import_image_editor6.runLayerMenuAction)(controller, action));
|
|
4278
|
+
};
|
|
4279
|
+
const prop = (key, value) => attempt(() => {
|
|
4280
|
+
controller.setLayerProperties(active.id, { [key]: value }, commitNext.current);
|
|
4281
|
+
commitNext.current = false;
|
|
4282
|
+
});
|
|
4283
|
+
const sliderEvents = {
|
|
4284
|
+
onPointerDown: () => commitNext.current = true,
|
|
4285
|
+
onPointerUp: () => commitNext.current = true,
|
|
4286
|
+
onKeyDown: () => commitNext.current = true
|
|
4287
|
+
};
|
|
4288
|
+
const onDrop = (e, row) => {
|
|
4289
|
+
e.preventDefault();
|
|
4290
|
+
const id = e.dataTransfer.getData("text/x-pixerate-layer") || drag;
|
|
4291
|
+
setDrag(null);
|
|
4292
|
+
if (!id) return;
|
|
4293
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
4294
|
+
const fraction = rect.height ? (e.clientY - rect.top) / rect.height : 0.5;
|
|
4295
|
+
const placement = (0, import_image_editor6.dropPlacement)(state.layers, id, row.layer.id, (0, import_image_editor6.dropZone)(fraction, row.layer.type === "group"));
|
|
4296
|
+
if (placement) attempt(() => controller.moveLayer(id, placement));
|
|
4297
|
+
};
|
|
4298
|
+
const thumb = (layer) => layer.type === "pixel" ? controller.getLayerThumbnail(layer.id, { maxSide: 64 }) : null;
|
|
4299
|
+
const maskThumb = (layer) => layer.mask && !layer.mask.source ? controller.getLayerThumbnail(layer.id, { maxSide: 64, mask: true }) : null;
|
|
4300
|
+
const locked = (layer) => Boolean(layer.locks?.all || layer.locks?.pixels || layer.locks?.position || layer.locks?.transparency);
|
|
4301
|
+
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: [
|
|
4302
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "toolbar", "aria-label": "Layer actions", children: [
|
|
4303
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, onClick: () => run("new-layer"), children: "New Layer" }),
|
|
4304
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, onClick: () => run("new-group"), children: "New Group" }),
|
|
4305
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("duplicate"), children: "Duplicate" }),
|
|
4306
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("add-mask"), children: "Add Mask" }),
|
|
4307
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("delete"), children: "Delete" }),
|
|
4308
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4309
|
+
"button",
|
|
4310
|
+
{
|
|
4311
|
+
type: "button",
|
|
4312
|
+
className: iconButton,
|
|
4313
|
+
"aria-label": "Layer menu",
|
|
4314
|
+
"aria-haspopup": "menu",
|
|
4315
|
+
onClick: (e) => {
|
|
4316
|
+
e.stopPropagation();
|
|
4317
|
+
const r = e.currentTarget.getBoundingClientRect();
|
|
4318
|
+
setMenu(menu ? null : { x: r.left, y: r.bottom });
|
|
4319
|
+
},
|
|
4320
|
+
children: "\u22EF"
|
|
4321
|
+
}
|
|
4322
|
+
)
|
|
4323
|
+
] }),
|
|
4324
|
+
active && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1 items-center", "data-testid": "layer-properties", children: [
|
|
4325
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
|
|
4326
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-slate-400", children: [
|
|
4327
|
+
"Opacity ",
|
|
4328
|
+
Math.round(active.opacity * 100),
|
|
4329
|
+
"%"
|
|
4330
|
+
] }),
|
|
4331
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4332
|
+
"input",
|
|
4333
|
+
{
|
|
4334
|
+
type: "range",
|
|
4335
|
+
min: 0,
|
|
4336
|
+
max: 100,
|
|
4337
|
+
"aria-label": "Layer opacity",
|
|
4338
|
+
value: Math.round(active.opacity * 100),
|
|
4339
|
+
...sliderEvents,
|
|
4340
|
+
onChange: (e) => prop("opacity", Number(e.target.value) / 100),
|
|
4341
|
+
className: "accent-indigo-500"
|
|
4342
|
+
}
|
|
4343
|
+
)
|
|
4344
|
+
] }),
|
|
4345
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
|
|
4346
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-slate-400", children: [
|
|
4347
|
+
"Fill ",
|
|
4348
|
+
Math.round(((active.type === "pixel" ? active.fillOpacity : void 0) ?? 1) * 100),
|
|
4349
|
+
"%"
|
|
4350
|
+
] }),
|
|
4351
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4352
|
+
"input",
|
|
4353
|
+
{
|
|
4354
|
+
type: "range",
|
|
4355
|
+
min: 0,
|
|
4356
|
+
max: 100,
|
|
4357
|
+
"aria-label": "Layer fill",
|
|
4358
|
+
disabled: active.type !== "pixel",
|
|
4359
|
+
value: Math.round(((active.type === "pixel" ? active.fillOpacity : void 0) ?? 1) * 100),
|
|
4360
|
+
...sliderEvents,
|
|
4361
|
+
onChange: (e) => prop("fillOpacity", Number(e.target.value) / 100),
|
|
4362
|
+
className: "accent-indigo-500 disabled:opacity-40"
|
|
4363
|
+
}
|
|
4364
|
+
)
|
|
4365
|
+
] }),
|
|
4366
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4367
|
+
"select",
|
|
4368
|
+
{
|
|
4369
|
+
"aria-label": "Layer blend mode",
|
|
4370
|
+
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
4371
|
+
value: active.blend,
|
|
4372
|
+
onChange: (e) => attempt(() => controller.setLayerProperties(active.id, { blend: e.target.value })),
|
|
4373
|
+
children: [
|
|
4374
|
+
active.type === "group" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: "pass-through", children: "Pass Through" }),
|
|
4375
|
+
import_image_editor6.BLEND_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: m.id, children: m.label }, m.id))
|
|
4376
|
+
]
|
|
4377
|
+
}
|
|
4378
|
+
),
|
|
4379
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
4380
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4381
|
+
"input",
|
|
4382
|
+
{
|
|
4383
|
+
type: "checkbox",
|
|
4384
|
+
"aria-label": "Clip to layer below",
|
|
4385
|
+
checked: Boolean(active.clipped),
|
|
4386
|
+
onChange: (e) => attempt(() => controller.setLayerProperties(active.id, { clipped: e.target.checked })),
|
|
4387
|
+
className: "accent-indigo-500"
|
|
4388
|
+
}
|
|
4389
|
+
),
|
|
4390
|
+
"Clip to below"
|
|
4391
|
+
] }),
|
|
4392
|
+
/* @__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: [
|
|
4393
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4394
|
+
"input",
|
|
4395
|
+
{
|
|
4396
|
+
type: "checkbox",
|
|
4397
|
+
"aria-label": `Lock ${k}`,
|
|
4398
|
+
checked: Boolean(active.locks?.[k]),
|
|
4399
|
+
onChange: (e) => attempt(() => controller.setLayerProperties(active.id, { locks: { ...active.locks, [k]: e.target.checked } })),
|
|
4400
|
+
className: "accent-indigo-500"
|
|
4401
|
+
}
|
|
4402
|
+
),
|
|
4403
|
+
k
|
|
4404
|
+
] }, k)) })
|
|
4405
|
+
] }),
|
|
4406
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("ul", { className: "flex flex-col gap-0.5", role: "tree", "aria-label": "Layers", children: rows.map((row) => {
|
|
4407
|
+
const { layer } = row;
|
|
4408
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4409
|
+
"li",
|
|
4410
|
+
{
|
|
4411
|
+
role: "treeitem",
|
|
4412
|
+
"aria-selected": row.active,
|
|
4413
|
+
"aria-level": row.depth + 1,
|
|
4414
|
+
"data-layer-id": layer.id,
|
|
4415
|
+
draggable: !layer.locks?.all,
|
|
4416
|
+
onDragStart: (e) => {
|
|
4417
|
+
e.dataTransfer.setData("text/x-pixerate-layer", layer.id);
|
|
4418
|
+
setDrag(layer.id);
|
|
4419
|
+
},
|
|
4420
|
+
onDragOver: (e) => e.preventDefault(),
|
|
4421
|
+
onDrop: (e) => onDrop(e, row),
|
|
4422
|
+
tabIndex: 0,
|
|
4423
|
+
onClick: () => attempt(() => controller.setActiveLayer(layer.id, "pixels")),
|
|
4424
|
+
onKeyDown: (e) => {
|
|
4425
|
+
if (e.target === e.currentTarget && (e.key === "Enter" || e.key === " ")) {
|
|
4426
|
+
e.preventDefault();
|
|
4427
|
+
attempt(() => controller.setActiveLayer(layer.id, "pixels"));
|
|
4428
|
+
}
|
|
4429
|
+
},
|
|
4430
|
+
onContextMenu: (e) => {
|
|
4431
|
+
e.preventDefault();
|
|
4432
|
+
controller.setActiveLayer(layer.id, state.activeLayerId === layer.id ? state.activeTarget : "pixels");
|
|
4433
|
+
setMenu({ x: e.clientX, y: e.clientY });
|
|
4434
|
+
},
|
|
4435
|
+
className: rowClass(row.active),
|
|
4436
|
+
style: { paddingLeft: 6 + row.depth * 14 },
|
|
4437
|
+
children: [
|
|
4438
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4439
|
+
"button",
|
|
4440
|
+
{
|
|
4441
|
+
type: "button",
|
|
4442
|
+
"aria-label": layer.visible ? `Hide ${row.label}` : `Show ${row.label}`,
|
|
4443
|
+
"aria-pressed": layer.visible,
|
|
4444
|
+
className: "w-4 text-center text-slate-300",
|
|
4445
|
+
onClick: (e) => {
|
|
4446
|
+
e.stopPropagation();
|
|
4447
|
+
attempt(() => controller.setLayerProperties(layer.id, { visible: !layer.visible }));
|
|
4448
|
+
},
|
|
4449
|
+
children: layer.visible ? "\u25CF" : "\u25CB"
|
|
4450
|
+
}
|
|
4451
|
+
),
|
|
4452
|
+
layer.type === "group" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4453
|
+
"button",
|
|
4454
|
+
{
|
|
4455
|
+
type: "button",
|
|
4456
|
+
"aria-label": layer.collapsed ? `Expand ${row.label}` : `Collapse ${row.label}`,
|
|
4457
|
+
className: "w-3 text-slate-400",
|
|
4458
|
+
onClick: (e) => {
|
|
4459
|
+
e.stopPropagation();
|
|
4460
|
+
attempt(() => controller.setLayerProperties(layer.id, { collapsed: !layer.collapsed }));
|
|
4461
|
+
},
|
|
4462
|
+
children: layer.collapsed ? "\u25B8" : "\u25BE"
|
|
4463
|
+
}
|
|
4464
|
+
),
|
|
4465
|
+
row.clipped && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-slate-500", "aria-label": "Clipped", children: "\u21B3" }),
|
|
4466
|
+
layer.type === "pixel" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4467
|
+
Thumbnail,
|
|
4468
|
+
{
|
|
4469
|
+
pixels: thumb(layer),
|
|
4470
|
+
size: thumbnailSize,
|
|
4471
|
+
label: `${row.label} pixels`,
|
|
4472
|
+
selected: row.active && state.activeTarget === "pixels" && Boolean(layer.mask)
|
|
4473
|
+
}
|
|
4474
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4475
|
+
"span",
|
|
4476
|
+
{
|
|
4477
|
+
className: "shrink-0 grid place-items-center rounded bg-slate-800 text-[9px] text-slate-400 ring-1 ring-slate-700",
|
|
4478
|
+
style: { width: thumbnailSize, height: thumbnailSize },
|
|
4479
|
+
children: (0, import_image_editor6.layerBadge)(layer)
|
|
4480
|
+
}
|
|
4481
|
+
),
|
|
4482
|
+
layer.mask && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4483
|
+
Thumbnail,
|
|
4484
|
+
{
|
|
4485
|
+
pixels: maskThumb(layer),
|
|
4486
|
+
size: thumbnailSize,
|
|
4487
|
+
label: `${row.label} mask${layer.mask.enabled === false ? " (disabled)" : ""}`,
|
|
4488
|
+
testId: "layer-mask-thumbnail",
|
|
4489
|
+
selected: row.active && state.activeTarget === "mask",
|
|
4490
|
+
onClick: (e) => {
|
|
4491
|
+
e.stopPropagation();
|
|
4492
|
+
if (e.shiftKey) attempt(() => controller.setLayerMaskProps(layer.id, { enabled: layer.mask.enabled === false }));
|
|
4493
|
+
else attempt(() => controller.setActiveLayer(layer.id, "mask"));
|
|
4494
|
+
}
|
|
4495
|
+
}
|
|
4496
|
+
),
|
|
4497
|
+
renaming === layer.id ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4498
|
+
"input",
|
|
4499
|
+
{
|
|
4500
|
+
autoFocus: true,
|
|
4501
|
+
"aria-label": "Layer name",
|
|
4502
|
+
defaultValue: layer.name || row.label,
|
|
4503
|
+
className: "flex-1 min-w-0 bg-slate-900 border border-slate-600 rounded px-1",
|
|
4504
|
+
onClick: (e) => e.stopPropagation(),
|
|
4505
|
+
onBlur: (e) => {
|
|
4506
|
+
setRenaming(null);
|
|
4507
|
+
if (e.target.value.trim() && e.target.value !== layer.name) attempt(() => controller.setLayerProperties(layer.id, { name: e.target.value }));
|
|
4508
|
+
},
|
|
4509
|
+
onKeyDown: (e) => {
|
|
4510
|
+
if (e.key === "Enter") e.target.blur();
|
|
4511
|
+
if (e.key === "Escape") setRenaming(null);
|
|
4512
|
+
}
|
|
4513
|
+
}
|
|
4514
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4515
|
+
"span",
|
|
4516
|
+
{
|
|
4517
|
+
className: `flex-1 min-w-0 truncate ${layer.visible ? "" : "text-slate-500"}`,
|
|
4518
|
+
onDoubleClick: (e) => {
|
|
4519
|
+
e.stopPropagation();
|
|
4520
|
+
setRenaming(layer.id);
|
|
4521
|
+
},
|
|
4522
|
+
children: row.label
|
|
4523
|
+
}
|
|
4524
|
+
),
|
|
4525
|
+
locked(layer) && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { "aria-label": "Locked", className: "text-slate-400", children: "\u{1F512}" }),
|
|
4526
|
+
layer.blend !== "normal" && layer.blend !== "pass-through" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[9px] text-slate-500", children: layer.blend })
|
|
4527
|
+
]
|
|
4528
|
+
},
|
|
4529
|
+
layer.id
|
|
4530
|
+
);
|
|
4531
|
+
}) }),
|
|
4532
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
|
|
4533
|
+
menu && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4534
|
+
"div",
|
|
4535
|
+
{
|
|
4536
|
+
role: "menu",
|
|
4537
|
+
"aria-label": "Layer menu",
|
|
4538
|
+
className: "fixed z-50 min-w-44 rounded border border-slate-700 bg-slate-900 py-1 shadow-xl",
|
|
4539
|
+
style: { left: menu.x, top: menu.y },
|
|
4540
|
+
onClick: (e) => e.stopPropagation(),
|
|
4541
|
+
onKeyDown: (e) => e.key === "Escape" && setMenu(null),
|
|
4542
|
+
children: (0, import_image_editor6.layerMenu)(controller).map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4543
|
+
"button",
|
|
4544
|
+
{
|
|
4545
|
+
type: "button",
|
|
4546
|
+
role: "menuitem",
|
|
4547
|
+
disabled: !item.enabled,
|
|
4548
|
+
className: "block w-full px-3 py-1 text-left hover:bg-slate-800 disabled:opacity-40",
|
|
4549
|
+
onClick: () => run(item.action),
|
|
4550
|
+
children: item.label
|
|
4551
|
+
},
|
|
4552
|
+
item.action
|
|
4553
|
+
))
|
|
4554
|
+
}
|
|
4555
|
+
)
|
|
4556
|
+
] });
|
|
4557
|
+
};
|
|
4558
|
+
|
|
4559
|
+
// src/image-editor/BrushOptionsBar.tsx
|
|
4560
|
+
var import_react39 = require("react");
|
|
4561
|
+
var import_image_editor7 = require("@pixerate/editor/image-editor");
|
|
4562
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
4563
|
+
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"}`;
|
|
4564
|
+
var BrushOptionsBar = ({ controller, className }) => {
|
|
4565
|
+
const [, setTick] = (0, import_react39.useState)(0);
|
|
4566
|
+
(0, import_react39.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
4567
|
+
const [error, setError] = (0, import_react39.useState)(null);
|
|
4568
|
+
const state = controller.getState();
|
|
4569
|
+
const { brush, foreground, background } = state.paint;
|
|
4570
|
+
const attempt = (fn) => {
|
|
4571
|
+
try {
|
|
4572
|
+
setError(null);
|
|
4573
|
+
fn();
|
|
4574
|
+
} catch (err) {
|
|
4575
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4576
|
+
}
|
|
4577
|
+
};
|
|
4578
|
+
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: [
|
|
4579
|
+
/* @__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)(
|
|
4580
|
+
"button",
|
|
4581
|
+
{
|
|
4582
|
+
type: "button",
|
|
4583
|
+
"aria-pressed": state.activeTool === t.id,
|
|
4584
|
+
title: `${t.label} (${t.shortcut})`,
|
|
4585
|
+
className: chip(state.activeTool === t.id),
|
|
4586
|
+
onClick: () => controller.setTool(t.id),
|
|
4587
|
+
children: t.label
|
|
4588
|
+
},
|
|
4589
|
+
t.id
|
|
4590
|
+
)) }),
|
|
4591
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2", role: "group", "aria-label": "Colours", children: [
|
|
4592
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
4593
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4594
|
+
"input",
|
|
4595
|
+
{
|
|
4596
|
+
type: "color",
|
|
4597
|
+
"aria-label": "Foreground colour",
|
|
4598
|
+
value: foreground,
|
|
4599
|
+
onChange: (e) => controller.setPaintOptions({ foreground: e.target.value }),
|
|
4600
|
+
className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
|
|
4601
|
+
}
|
|
4602
|
+
),
|
|
4603
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-slate-400", children: "FG" })
|
|
4604
|
+
] }),
|
|
4605
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
4606
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4607
|
+
"input",
|
|
4608
|
+
{
|
|
4609
|
+
type: "color",
|
|
4610
|
+
"aria-label": "Background colour",
|
|
4611
|
+
value: background,
|
|
4612
|
+
onChange: (e) => controller.setPaintOptions({ background: e.target.value }),
|
|
4613
|
+
className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
|
|
4614
|
+
}
|
|
4615
|
+
),
|
|
4616
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-slate-400", children: "BG" })
|
|
4617
|
+
] }),
|
|
4618
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", title: "Swap colours (X)", className: chip(false), onClick: () => controller.swapPaintColors(), children: "Swap" }),
|
|
4619
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", title: "Default colours (D)", className: chip(false), onClick: () => controller.resetPaintColors(), children: "Default" })
|
|
4620
|
+
] }),
|
|
4621
|
+
import_image_editor7.BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4622
|
+
ControlSlider,
|
|
4623
|
+
{
|
|
4624
|
+
spec,
|
|
4625
|
+
value: brush[spec.id],
|
|
4626
|
+
onChange: (v) => controller.setPaintOptions({ brush: { [spec.id]: v } })
|
|
4627
|
+
},
|
|
4628
|
+
spec.id
|
|
4629
|
+
)),
|
|
4630
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
|
|
4631
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1.5", children: [
|
|
4632
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4633
|
+
"input",
|
|
4634
|
+
{
|
|
4635
|
+
type: "checkbox",
|
|
4636
|
+
"aria-label": "Pressure controls size",
|
|
4637
|
+
checked: brush.pressureSize,
|
|
4638
|
+
onChange: (e) => controller.setPaintOptions({ brush: { pressureSize: e.target.checked } }),
|
|
4639
|
+
className: "accent-indigo-500"
|
|
4640
|
+
}
|
|
4641
|
+
),
|
|
4642
|
+
"Pressure size"
|
|
4643
|
+
] }),
|
|
4644
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1.5", children: [
|
|
4645
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4646
|
+
"input",
|
|
4647
|
+
{
|
|
4648
|
+
type: "checkbox",
|
|
4649
|
+
"aria-label": "Pressure controls opacity",
|
|
4650
|
+
checked: brush.pressureOpacity,
|
|
4651
|
+
onChange: (e) => controller.setPaintOptions({ brush: { pressureOpacity: e.target.checked } }),
|
|
4652
|
+
className: "accent-indigo-500"
|
|
4653
|
+
}
|
|
4654
|
+
),
|
|
4655
|
+
"Pressure opacity"
|
|
4656
|
+
] })
|
|
4657
|
+
] }),
|
|
4658
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex gap-1", children: [
|
|
4659
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.fillPixels()), children: "Fill" }),
|
|
4660
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.clearPixels()), children: "Clear" })
|
|
4661
|
+
] }),
|
|
4662
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
|
|
4663
|
+
] });
|
|
4664
|
+
};
|
|
4665
|
+
|
|
4666
|
+
// src/image-editor/SelectionOptionsBar.tsx
|
|
4667
|
+
var import_react40 = require("react");
|
|
4668
|
+
var import_image_editor8 = require("@pixerate/editor/image-editor");
|
|
4669
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
4220
4670
|
var MODIFY_OPS = [
|
|
4221
4671
|
{ op: "grow", label: "Grow" },
|
|
4222
4672
|
{ op: "shrink", label: "Shrink" },
|
|
@@ -4233,20 +4683,20 @@ var SelectionOptionsBar = ({
|
|
|
4233
4683
|
quickMask,
|
|
4234
4684
|
className = ""
|
|
4235
4685
|
}) => {
|
|
4236
|
-
const [radius, setRadius] = (0,
|
|
4686
|
+
const [radius, setRadius] = (0, import_react40.useState)(2);
|
|
4237
4687
|
const set = (patch) => onOptionsChange({ ...options, ...patch });
|
|
4238
4688
|
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
4239
4689
|
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,
|
|
4690
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
4691
|
+
/* @__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)) }),
|
|
4692
|
+
/* @__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)) }),
|
|
4693
|
+
options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
4694
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
4695
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
4696
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Tolerance" }),
|
|
4697
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "font-mono", children: options.tolerance })
|
|
4248
4698
|
] }),
|
|
4249
|
-
/* @__PURE__ */ (0,
|
|
4699
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4250
4700
|
"input",
|
|
4251
4701
|
{
|
|
4252
4702
|
type: "range",
|
|
@@ -4260,29 +4710,29 @@ var SelectionOptionsBar = ({
|
|
|
4260
4710
|
}
|
|
4261
4711
|
)
|
|
4262
4712
|
] }),
|
|
4263
|
-
/* @__PURE__ */ (0,
|
|
4264
|
-
/* @__PURE__ */ (0,
|
|
4713
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
4714
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
|
|
4265
4715
|
"Contiguous"
|
|
4266
4716
|
] }),
|
|
4267
|
-
/* @__PURE__ */ (0,
|
|
4268
|
-
/* @__PURE__ */ (0,
|
|
4717
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
4718
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
|
|
4269
4719
|
"Sample adjusted image"
|
|
4270
4720
|
] })
|
|
4271
4721
|
] }),
|
|
4272
|
-
/* @__PURE__ */ (0,
|
|
4273
|
-
/* @__PURE__ */ (0,
|
|
4722
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
4723
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
|
|
4274
4724
|
"Anti-alias"
|
|
4275
4725
|
] }),
|
|
4276
|
-
/* @__PURE__ */ (0,
|
|
4277
|
-
/* @__PURE__ */ (0,
|
|
4278
|
-
/* @__PURE__ */ (0,
|
|
4279
|
-
/* @__PURE__ */ (0,
|
|
4280
|
-
/* @__PURE__ */ (0,
|
|
4726
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
|
|
4727
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
|
|
4728
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
|
|
4729
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
|
|
4730
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
|
|
4281
4731
|
] }),
|
|
4282
|
-
/* @__PURE__ */ (0,
|
|
4283
|
-
/* @__PURE__ */ (0,
|
|
4732
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
4733
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
|
|
4284
4734
|
"Radius",
|
|
4285
|
-
/* @__PURE__ */ (0,
|
|
4735
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4286
4736
|
"input",
|
|
4287
4737
|
{
|
|
4288
4738
|
type: "number",
|
|
@@ -4296,24 +4746,24 @@ var SelectionOptionsBar = ({
|
|
|
4296
4746
|
}
|
|
4297
4747
|
)
|
|
4298
4748
|
] }),
|
|
4299
|
-
MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0,
|
|
4749
|
+
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
4750
|
] }),
|
|
4301
|
-
/* @__PURE__ */ (0,
|
|
4751
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor8.describeSelection)(sel) })
|
|
4302
4752
|
] });
|
|
4303
4753
|
};
|
|
4304
4754
|
|
|
4305
4755
|
// src/image-editor/RefineEdgePanel.tsx
|
|
4306
|
-
var
|
|
4307
|
-
var
|
|
4308
|
-
var
|
|
4756
|
+
var import_react41 = require("react");
|
|
4757
|
+
var import_image_editor9 = require("@pixerate/editor/image-editor");
|
|
4758
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
4309
4759
|
var DEFAULT_PARAMS = { radius: 8, smartRadius: false, smooth: 0, feather: 0, contrast: 0, shiftEdge: 0 };
|
|
4310
4760
|
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
4761
|
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,
|
|
4762
|
+
const [params, setParams] = (0, import_react41.useState)(DEFAULT_PARAMS);
|
|
4763
|
+
const [busy, setBusy] = (0, import_react41.useState)(false);
|
|
4764
|
+
const [error, setError] = (0, import_react41.useState)(null);
|
|
4765
|
+
const [layerId, setLayerId] = (0, import_react41.useState)("");
|
|
4766
|
+
const [newKind, setNewKind] = (0, import_react41.useState)("hueSaturation");
|
|
4317
4767
|
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
4318
4768
|
const list = layers ?? controller.getAdjustmentLayers();
|
|
4319
4769
|
const target = list.find((l) => l.id === layerId) ?? list[list.length - 1];
|
|
@@ -4328,17 +4778,17 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
4328
4778
|
setBusy(false);
|
|
4329
4779
|
}
|
|
4330
4780
|
};
|
|
4331
|
-
return /* @__PURE__ */ (0,
|
|
4332
|
-
/* @__PURE__ */ (0,
|
|
4333
|
-
|
|
4334
|
-
/* @__PURE__ */ (0,
|
|
4335
|
-
/* @__PURE__ */ (0,
|
|
4336
|
-
/* @__PURE__ */ (0,
|
|
4781
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
4782
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
|
|
4783
|
+
import_image_editor9.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
4784
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
4785
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: c.label }),
|
|
4786
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "font-mono", children: [
|
|
4337
4787
|
params[c.id],
|
|
4338
4788
|
c.unit
|
|
4339
4789
|
] })
|
|
4340
4790
|
] }),
|
|
4341
|
-
/* @__PURE__ */ (0,
|
|
4791
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4342
4792
|
"input",
|
|
4343
4793
|
{
|
|
4344
4794
|
type: "range",
|
|
@@ -4352,67 +4802,67 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
4352
4802
|
}
|
|
4353
4803
|
)
|
|
4354
4804
|
] }, c.id)),
|
|
4355
|
-
/* @__PURE__ */ (0,
|
|
4356
|
-
/* @__PURE__ */ (0,
|
|
4805
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
4806
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
|
|
4357
4807
|
"Smart Radius"
|
|
4358
4808
|
] }),
|
|
4359
|
-
/* @__PURE__ */ (0,
|
|
4360
|
-
/* @__PURE__ */ (0,
|
|
4361
|
-
/* @__PURE__ */ (0,
|
|
4809
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-1", children: [
|
|
4810
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
|
|
4811
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
|
|
4362
4812
|
] }),
|
|
4363
|
-
error && /* @__PURE__ */ (0,
|
|
4364
|
-
/* @__PURE__ */ (0,
|
|
4365
|
-
/* @__PURE__ */ (0,
|
|
4366
|
-
/* @__PURE__ */ (0,
|
|
4813
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
|
|
4814
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
|
|
4815
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-1 items-center", children: [
|
|
4816
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4367
4817
|
"select",
|
|
4368
4818
|
{
|
|
4369
4819
|
"aria-label": "New masked layer kind",
|
|
4370
4820
|
value: newKind,
|
|
4371
4821
|
onChange: (e) => setNewKind(e.target.value),
|
|
4372
4822
|
className: "flex-1 bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
|
|
4373
|
-
children:
|
|
4823
|
+
children: import_image_editor9.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: k.kind, children: k.label }, k.kind))
|
|
4374
4824
|
}
|
|
4375
4825
|
),
|
|
4376
|
-
/* @__PURE__ */ (0,
|
|
4826
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4377
4827
|
"button",
|
|
4378
4828
|
{
|
|
4379
4829
|
type: "button",
|
|
4380
4830
|
className: button,
|
|
4381
4831
|
disabled: !sel,
|
|
4382
|
-
onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0,
|
|
4832
|
+
onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor9.layerMaskFromSelection)(sel) })),
|
|
4383
4833
|
children: "New Masked Layer"
|
|
4384
4834
|
}
|
|
4385
4835
|
)
|
|
4386
4836
|
] }),
|
|
4387
|
-
list.length > 0 && target && /* @__PURE__ */ (0,
|
|
4388
|
-
/* @__PURE__ */ (0,
|
|
4837
|
+
list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
4838
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4389
4839
|
"select",
|
|
4390
4840
|
{
|
|
4391
4841
|
"aria-label": "Mask layer",
|
|
4392
4842
|
value: target.id,
|
|
4393
4843
|
onChange: (e) => setLayerId(e.target.value),
|
|
4394
4844
|
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,
|
|
4845
|
+
children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("option", { value: l.id, children: [
|
|
4846
|
+
l.name || (0, import_image_editor9.adjustmentKindLabel)(l.kind),
|
|
4397
4847
|
l.mask ? " (masked)" : ""
|
|
4398
4848
|
] }, l.id))
|
|
4399
4849
|
}
|
|
4400
4850
|
),
|
|
4401
|
-
/* @__PURE__ */ (0,
|
|
4402
|
-
/* @__PURE__ */ (0,
|
|
4403
|
-
/* @__PURE__ */ (0,
|
|
4404
|
-
/* @__PURE__ */ (0,
|
|
4851
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
|
|
4852
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
|
|
4853
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
|
|
4854
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
|
|
4405
4855
|
] }),
|
|
4406
|
-
target.mask && /* @__PURE__ */ (0,
|
|
4407
|
-
/* @__PURE__ */ (0,
|
|
4408
|
-
/* @__PURE__ */ (0,
|
|
4409
|
-
/* @__PURE__ */ (0,
|
|
4410
|
-
/* @__PURE__ */ (0,
|
|
4856
|
+
target.mask && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
4857
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
4858
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
4859
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Density" }),
|
|
4860
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "font-mono", children: [
|
|
4411
4861
|
Math.round((target.mask.density ?? 1) * 100),
|
|
4412
4862
|
"%"
|
|
4413
4863
|
] })
|
|
4414
4864
|
] }),
|
|
4415
|
-
/* @__PURE__ */ (0,
|
|
4865
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4416
4866
|
"input",
|
|
4417
4867
|
{
|
|
4418
4868
|
type: "range",
|
|
@@ -4426,15 +4876,15 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
4426
4876
|
}
|
|
4427
4877
|
)
|
|
4428
4878
|
] }),
|
|
4429
|
-
/* @__PURE__ */ (0,
|
|
4430
|
-
/* @__PURE__ */ (0,
|
|
4431
|
-
/* @__PURE__ */ (0,
|
|
4432
|
-
/* @__PURE__ */ (0,
|
|
4879
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
4880
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
4881
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Mask Feather" }),
|
|
4882
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "font-mono", children: [
|
|
4433
4883
|
target.mask.feather ?? 0,
|
|
4434
4884
|
"px"
|
|
4435
4885
|
] })
|
|
4436
4886
|
] }),
|
|
4437
|
-
/* @__PURE__ */ (0,
|
|
4887
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4438
4888
|
"input",
|
|
4439
4889
|
{
|
|
4440
4890
|
type: "range",
|
|
@@ -4454,7 +4904,7 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
4454
4904
|
};
|
|
4455
4905
|
|
|
4456
4906
|
// src/image-editor/ImageEditor.tsx
|
|
4457
|
-
var
|
|
4907
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
4458
4908
|
var ImageEditor = ({
|
|
4459
4909
|
editor: externalEditor,
|
|
4460
4910
|
src,
|
|
@@ -4469,26 +4919,34 @@ var ImageEditor = ({
|
|
|
4469
4919
|
const internalEditor = useImageEditor({ image: src });
|
|
4470
4920
|
const editor = externalEditor || internalEditor;
|
|
4471
4921
|
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,
|
|
4922
|
+
const legacyProcess = (0, import_image_editor10.normalizeProcessVersion)(state.adjustments.process) < import_image_editor10.LATEST_PROCESS_VERSION;
|
|
4923
|
+
const canvasRef = (0, import_react42.useRef)(null);
|
|
4924
|
+
const containerRef = (0, import_react42.useRef)(null);
|
|
4925
|
+
const [activeTab, setActiveTab] = (0, import_react42.useState)("crop");
|
|
4926
|
+
const [activeCropRatio, setActiveCropRatio] = (0, import_react42.useState)(null);
|
|
4927
|
+
const [selectionOptions, setSelectionOptions] = (0, import_react42.useState)(import_image_editor10.DEFAULT_SELECTION_TOOL_OPTIONS);
|
|
4928
|
+
const selectionOptionsRef = (0, import_react42.useRef)(selectionOptions);
|
|
4479
4929
|
selectionOptionsRef.current = selectionOptions;
|
|
4480
|
-
const selectionGestureRef = (0,
|
|
4930
|
+
const selectionGestureRef = (0, import_react42.useRef)(null);
|
|
4481
4931
|
if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
|
|
4482
|
-
selectionGestureRef.current = new
|
|
4932
|
+
selectionGestureRef.current = new import_image_editor10.SelectionGesture(controller, () => selectionOptionsRef.current);
|
|
4933
|
+
}
|
|
4934
|
+
const selectionDraftRef = (0, import_react42.useRef)(null);
|
|
4935
|
+
const [selectionError, setSelectionError] = (0, import_react42.useState)(null);
|
|
4936
|
+
const paintGestureRef = (0, import_react42.useRef)(null);
|
|
4937
|
+
const paintControllerRef = (0, import_react42.useRef)(controller);
|
|
4938
|
+
if (!paintGestureRef.current || paintControllerRef.current !== controller) {
|
|
4939
|
+
paintGestureRef.current = new import_image_editor10.PaintGesture(controller);
|
|
4940
|
+
paintControllerRef.current = controller;
|
|
4483
4941
|
}
|
|
4484
|
-
const
|
|
4485
|
-
const [
|
|
4486
|
-
const [inpaintPrompt, setInpaintPrompt] = (0,
|
|
4487
|
-
const [inpaintMaskMode, setInpaintMaskMode] = (0,
|
|
4488
|
-
const [isRemovingBg, setIsRemovingBg] = (0,
|
|
4489
|
-
const [isInpainting, setIsInpainting] = (0,
|
|
4490
|
-
const [aiError, setAiError] = (0,
|
|
4491
|
-
const [aiSuccess, setAiSuccess] = (0,
|
|
4942
|
+
const brushCursorRef = (0, import_react42.useRef)(null);
|
|
4943
|
+
const [paintError, setPaintError] = (0, import_react42.useState)(null);
|
|
4944
|
+
const [inpaintPrompt, setInpaintPrompt] = (0, import_react42.useState)("");
|
|
4945
|
+
const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react42.useState)("annotations");
|
|
4946
|
+
const [isRemovingBg, setIsRemovingBg] = (0, import_react42.useState)(false);
|
|
4947
|
+
const [isInpainting, setIsInpainting] = (0, import_react42.useState)(false);
|
|
4948
|
+
const [aiError, setAiError] = (0, import_react42.useState)(null);
|
|
4949
|
+
const [aiSuccess, setAiSuccess] = (0, import_react42.useState)(null);
|
|
4492
4950
|
const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
|
|
4493
4951
|
const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
|
|
4494
4952
|
const handleRemoveBackground = async () => {
|
|
@@ -4550,18 +5008,18 @@ var ImageEditor = ({
|
|
|
4550
5008
|
setIsInpainting(false);
|
|
4551
5009
|
}
|
|
4552
5010
|
};
|
|
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,
|
|
5011
|
+
const [activeColor, setActiveColor] = (0, import_react42.useState)("#ef4444");
|
|
5012
|
+
const [strokeWidth, setStrokeWidth] = (0, import_react42.useState)(3);
|
|
5013
|
+
const [fontSize, setFontSize] = (0, import_react42.useState)(24);
|
|
5014
|
+
const [textInput, setTextInput] = (0, import_react42.useState)("");
|
|
5015
|
+
const draftAnnotationRef = (0, import_react42.useRef)(null);
|
|
5016
|
+
const draftCropRef = (0, import_react42.useRef)(null);
|
|
5017
|
+
const cropDragInfoRef = (0, import_react42.useRef)(null);
|
|
5018
|
+
const annotationDragInfoRef = (0, import_react42.useRef)(null);
|
|
5019
|
+
const isDrawingRef = (0, import_react42.useRef)(false);
|
|
5020
|
+
const currentPathRef = (0, import_react42.useRef)([]);
|
|
5021
|
+
const dragStartPointRef = (0, import_react42.useRef)(null);
|
|
5022
|
+
const renderCanvas = (0, import_react42.useCallback)(
|
|
4565
5023
|
async (draftAnnotation, draftCrop) => {
|
|
4566
5024
|
const canvas = canvasRef.current;
|
|
4567
5025
|
const container = containerRef.current;
|
|
@@ -4576,12 +5034,13 @@ var ImageEditor = ({
|
|
|
4576
5034
|
interactive: true,
|
|
4577
5035
|
draftAnnotation: draftAnnotation !== void 0 ? draftAnnotation : draftAnnotationRef.current,
|
|
4578
5036
|
draftCrop: draftCrop !== void 0 ? draftCrop : draftCropRef.current,
|
|
4579
|
-
draftSelectionPath: selectionDraftRef.current
|
|
5037
|
+
draftSelectionPath: selectionDraftRef.current,
|
|
5038
|
+
brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null
|
|
4580
5039
|
});
|
|
4581
5040
|
},
|
|
4582
5041
|
[controller, activeTab]
|
|
4583
5042
|
);
|
|
4584
|
-
(0,
|
|
5043
|
+
(0, import_react42.useEffect)(() => {
|
|
4585
5044
|
const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
|
|
4586
5045
|
const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
|
|
4587
5046
|
const animId = raf(() => {
|
|
@@ -4589,12 +5048,12 @@ var ImageEditor = ({
|
|
|
4589
5048
|
});
|
|
4590
5049
|
return () => caf(animId);
|
|
4591
5050
|
}, [renderCanvas, state]);
|
|
4592
|
-
(0,
|
|
5051
|
+
(0, import_react42.useEffect)(() => {
|
|
4593
5052
|
if (activeTab === "crop" && editor.state.activeTool !== "crop") {
|
|
4594
5053
|
editor.setTool("crop");
|
|
4595
5054
|
}
|
|
4596
5055
|
}, [activeTab, editor]);
|
|
4597
|
-
(0,
|
|
5056
|
+
(0, import_react42.useEffect)(() => {
|
|
4598
5057
|
const container = containerRef.current;
|
|
4599
5058
|
if (!container) return;
|
|
4600
5059
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -4620,13 +5079,60 @@ var ImageEditor = ({
|
|
|
4620
5079
|
y: (e.clientY - rect.top) * scaleY
|
|
4621
5080
|
};
|
|
4622
5081
|
};
|
|
5082
|
+
const paintSamples = (e) => {
|
|
5083
|
+
const canvas = canvasRef.current;
|
|
5084
|
+
const native = e.nativeEvent;
|
|
5085
|
+
const events = typeof native.getCoalescedEvents === "function" ? native.getCoalescedEvents() : [];
|
|
5086
|
+
const list = events.length ? events : [native];
|
|
5087
|
+
const rect = canvas.getBoundingClientRect();
|
|
5088
|
+
const sx = rect.width > 0 ? canvas.width / rect.width : 1;
|
|
5089
|
+
const sy = rect.height > 0 ? canvas.height / rect.height : 1;
|
|
5090
|
+
const s = controller.getState();
|
|
5091
|
+
return list.map((ev) => ({
|
|
5092
|
+
...(0, import_image_editor10.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
|
|
5093
|
+
pressure: (0, import_image_editor10.pointerPressure)(ev)
|
|
5094
|
+
}));
|
|
5095
|
+
};
|
|
5096
|
+
const handlePaintPointerDown = (e) => {
|
|
5097
|
+
if (activeTab !== "paint" || e.button !== 0) return;
|
|
5098
|
+
e.preventDefault();
|
|
5099
|
+
try {
|
|
5100
|
+
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
5101
|
+
} catch {
|
|
5102
|
+
}
|
|
5103
|
+
const [first] = paintSamples(e);
|
|
5104
|
+
setPaintError(paintGestureRef.current.down(first));
|
|
5105
|
+
};
|
|
5106
|
+
const handlePaintPointerMove = (e) => {
|
|
5107
|
+
if (activeTab !== "paint") return;
|
|
5108
|
+
const samples = paintSamples(e);
|
|
5109
|
+
brushCursorRef.current = samples[samples.length - 1] ?? null;
|
|
5110
|
+
if (paintGestureRef.current.active) paintGestureRef.current.moveTo(samples);
|
|
5111
|
+
else void renderCanvas();
|
|
5112
|
+
};
|
|
5113
|
+
const handlePaintPointerUp = () => {
|
|
5114
|
+
if (activeTab !== "paint") return;
|
|
5115
|
+
const g = paintGestureRef.current;
|
|
5116
|
+
if (g.active) {
|
|
5117
|
+
g.up();
|
|
5118
|
+
if (g.error) setPaintError(g.error);
|
|
5119
|
+
}
|
|
5120
|
+
};
|
|
5121
|
+
(0, import_react42.useEffect)(() => {
|
|
5122
|
+
if (activeTab !== "paint" || typeof window === "undefined") return;
|
|
5123
|
+
const onKey = (e) => {
|
|
5124
|
+
if ((0, import_image_editor10.handlePaintShortcut)(controller, e)) e.preventDefault();
|
|
5125
|
+
};
|
|
5126
|
+
window.addEventListener("keydown", onKey);
|
|
5127
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
5128
|
+
}, [activeTab, controller]);
|
|
4623
5129
|
const handleMouseDown = (e) => {
|
|
4624
5130
|
const canvas = canvasRef.current;
|
|
4625
5131
|
if (!canvas) return;
|
|
4626
5132
|
const canvasPt = getCanvasEventPoint(e);
|
|
4627
5133
|
if (activeTab === "select") {
|
|
4628
5134
|
const gesture = selectionGestureRef.current;
|
|
4629
|
-
const imgPt = (0,
|
|
5135
|
+
const imgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
4630
5136
|
void gesture.begin(imgPt, e).then(() => setSelectionError(gesture.error));
|
|
4631
5137
|
return;
|
|
4632
5138
|
}
|
|
@@ -4637,8 +5143,8 @@ var ImageEditor = ({
|
|
|
4637
5143
|
width: state.imageDimensions.width,
|
|
4638
5144
|
height: state.imageDimensions.height
|
|
4639
5145
|
};
|
|
4640
|
-
const handle = (0,
|
|
4641
|
-
const startImgPt = (0,
|
|
5146
|
+
const handle = (0, import_image_editor10.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
|
|
5147
|
+
const startImgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
|
|
4642
5148
|
if (handle) {
|
|
4643
5149
|
cropDragInfoRef.current = {
|
|
4644
5150
|
handle,
|
|
@@ -4657,12 +5163,12 @@ var ImageEditor = ({
|
|
|
4657
5163
|
return;
|
|
4658
5164
|
}
|
|
4659
5165
|
if (activeTab === "annotate") {
|
|
4660
|
-
const imgPt = (0,
|
|
5166
|
+
const imgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
4661
5167
|
dragStartPointRef.current = imgPt;
|
|
4662
5168
|
if (state.activeTool === "select") {
|
|
4663
5169
|
for (let i = state.annotations.length - 1; i >= 0; i--) {
|
|
4664
5170
|
const ann = state.annotations[i];
|
|
4665
|
-
if ((0,
|
|
5171
|
+
if ((0, import_image_editor10.hitTestAnnotation)(imgPt, ann)) {
|
|
4666
5172
|
editor.selectAnnotation(ann.id);
|
|
4667
5173
|
annotationDragInfoRef.current = {
|
|
4668
5174
|
annId: ann.id,
|
|
@@ -4698,7 +5204,7 @@ var ImageEditor = ({
|
|
|
4698
5204
|
const canvasPt = getCanvasEventPoint(e);
|
|
4699
5205
|
if (activeTab === "select") {
|
|
4700
5206
|
const gesture = selectionGestureRef.current;
|
|
4701
|
-
if (gesture.active && gesture.move((0,
|
|
5207
|
+
if (gesture.active && gesture.move((0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
|
|
4702
5208
|
selectionDraftRef.current = gesture.draftPath;
|
|
4703
5209
|
renderCanvas();
|
|
4704
5210
|
}
|
|
@@ -4707,7 +5213,7 @@ var ImageEditor = ({
|
|
|
4707
5213
|
if (activeTab === "crop") {
|
|
4708
5214
|
const drag = cropDragInfoRef.current;
|
|
4709
5215
|
if (drag) {
|
|
4710
|
-
const currentImgPt = (0,
|
|
5216
|
+
const currentImgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
|
|
4711
5217
|
let newCrop;
|
|
4712
5218
|
if (drag.handle === "new") {
|
|
4713
5219
|
const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
|
|
@@ -4721,7 +5227,7 @@ var ImageEditor = ({
|
|
|
4721
5227
|
height: Math.round(Math.max(20, maxY - minY))
|
|
4722
5228
|
};
|
|
4723
5229
|
} else {
|
|
4724
|
-
newCrop = (0,
|
|
5230
|
+
newCrop = (0, import_image_editor10.calculateCropDrag)(
|
|
4725
5231
|
drag.startCrop,
|
|
4726
5232
|
drag.handle,
|
|
4727
5233
|
drag.startImgPt,
|
|
@@ -4741,15 +5247,15 @@ var ImageEditor = ({
|
|
|
4741
5247
|
width: state.imageDimensions.width,
|
|
4742
5248
|
height: state.imageDimensions.height
|
|
4743
5249
|
};
|
|
4744
|
-
const handle = (0,
|
|
4745
|
-
canvas.style.cursor = (0,
|
|
5250
|
+
const handle = (0, import_image_editor10.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
|
|
5251
|
+
canvas.style.cursor = (0, import_image_editor10.getCropCursor)(handle, state.transform);
|
|
4746
5252
|
}
|
|
4747
5253
|
return;
|
|
4748
5254
|
}
|
|
4749
5255
|
if (activeTab === "annotate") {
|
|
4750
5256
|
if (annotationDragInfoRef.current) {
|
|
4751
5257
|
const drag = annotationDragInfoRef.current;
|
|
4752
|
-
const currentImgPt2 = (0,
|
|
5258
|
+
const currentImgPt2 = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
4753
5259
|
const dx = currentImgPt2.x - drag.startImgPt.x;
|
|
4754
5260
|
const dy = currentImgPt2.y - drag.startImgPt.y;
|
|
4755
5261
|
editor.updateAnnotation(drag.annId, {
|
|
@@ -4761,10 +5267,10 @@ var ImageEditor = ({
|
|
|
4761
5267
|
const startPt = dragStartPointRef.current;
|
|
4762
5268
|
if (!startPt) {
|
|
4763
5269
|
if (state.activeTool === "select") {
|
|
4764
|
-
const imgPt = (0,
|
|
5270
|
+
const imgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
4765
5271
|
let hovered = false;
|
|
4766
5272
|
for (let i = state.annotations.length - 1; i >= 0; i--) {
|
|
4767
|
-
if ((0,
|
|
5273
|
+
if ((0, import_image_editor10.hitTestAnnotation)(imgPt, state.annotations[i])) {
|
|
4768
5274
|
hovered = true;
|
|
4769
5275
|
break;
|
|
4770
5276
|
}
|
|
@@ -4775,7 +5281,7 @@ var ImageEditor = ({
|
|
|
4775
5281
|
}
|
|
4776
5282
|
return;
|
|
4777
5283
|
}
|
|
4778
|
-
const currentImgPt = (0,
|
|
5284
|
+
const currentImgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
4779
5285
|
if (state.activeTool === "pen" && isDrawingRef.current) {
|
|
4780
5286
|
currentPathRef.current.push(currentImgPt);
|
|
4781
5287
|
const draft = {
|
|
@@ -4855,7 +5361,7 @@ var ImageEditor = ({
|
|
|
4855
5361
|
if (activeTab === "select") {
|
|
4856
5362
|
const gesture = selectionGestureRef.current;
|
|
4857
5363
|
if (gesture.active) {
|
|
4858
|
-
gesture.end((0,
|
|
5364
|
+
gesture.end((0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
|
|
4859
5365
|
selectionDraftRef.current = null;
|
|
4860
5366
|
renderCanvas();
|
|
4861
5367
|
}
|
|
@@ -4879,7 +5385,7 @@ var ImageEditor = ({
|
|
|
4879
5385
|
}
|
|
4880
5386
|
const startPt = dragStartPointRef.current;
|
|
4881
5387
|
if (startPt) {
|
|
4882
|
-
const currentImgPt = (0,
|
|
5388
|
+
const currentImgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
4883
5389
|
if (state.activeTool === "pen" && isDrawingRef.current) {
|
|
4884
5390
|
if (currentPathRef.current.length > 1) {
|
|
4885
5391
|
editor.addAnnotation({
|
|
@@ -4975,15 +5481,15 @@ var ImageEditor = ({
|
|
|
4975
5481
|
link.click();
|
|
4976
5482
|
}
|
|
4977
5483
|
};
|
|
4978
|
-
return /* @__PURE__ */ (0,
|
|
5484
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
4979
5485
|
"div",
|
|
4980
5486
|
{
|
|
4981
5487
|
className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
|
|
4982
5488
|
style,
|
|
4983
5489
|
children: [
|
|
4984
|
-
/* @__PURE__ */ (0,
|
|
4985
|
-
/* @__PURE__ */ (0,
|
|
4986
|
-
/* @__PURE__ */ (0,
|
|
5490
|
+
/* @__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: [
|
|
5491
|
+
/* @__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: [
|
|
5492
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4987
5493
|
"button",
|
|
4988
5494
|
{
|
|
4989
5495
|
type: "button",
|
|
@@ -4995,7 +5501,7 @@ var ImageEditor = ({
|
|
|
4995
5501
|
children: "Transform & Crop"
|
|
4996
5502
|
}
|
|
4997
5503
|
),
|
|
4998
|
-
/* @__PURE__ */ (0,
|
|
5504
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4999
5505
|
"button",
|
|
5000
5506
|
{
|
|
5001
5507
|
type: "button",
|
|
@@ -5007,7 +5513,31 @@ var ImageEditor = ({
|
|
|
5007
5513
|
children: "Adjustments"
|
|
5008
5514
|
}
|
|
5009
5515
|
),
|
|
5010
|
-
/* @__PURE__ */ (0,
|
|
5516
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5517
|
+
"button",
|
|
5518
|
+
{
|
|
5519
|
+
type: "button",
|
|
5520
|
+
onClick: () => {
|
|
5521
|
+
setActiveTab("layers");
|
|
5522
|
+
editor.setTool("select");
|
|
5523
|
+
},
|
|
5524
|
+
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"}`,
|
|
5525
|
+
children: "Layers"
|
|
5526
|
+
}
|
|
5527
|
+
),
|
|
5528
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5529
|
+
"button",
|
|
5530
|
+
{
|
|
5531
|
+
type: "button",
|
|
5532
|
+
onClick: () => {
|
|
5533
|
+
setActiveTab("paint");
|
|
5534
|
+
editor.setTool("brush");
|
|
5535
|
+
},
|
|
5536
|
+
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"}`,
|
|
5537
|
+
children: "Paint"
|
|
5538
|
+
}
|
|
5539
|
+
),
|
|
5540
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5011
5541
|
"button",
|
|
5012
5542
|
{
|
|
5013
5543
|
type: "button",
|
|
@@ -5019,7 +5549,7 @@ var ImageEditor = ({
|
|
|
5019
5549
|
children: "Select & Mask"
|
|
5020
5550
|
}
|
|
5021
5551
|
),
|
|
5022
|
-
/* @__PURE__ */ (0,
|
|
5552
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5023
5553
|
"button",
|
|
5024
5554
|
{
|
|
5025
5555
|
type: "button",
|
|
@@ -5031,7 +5561,7 @@ var ImageEditor = ({
|
|
|
5031
5561
|
children: "Annotations"
|
|
5032
5562
|
}
|
|
5033
5563
|
),
|
|
5034
|
-
/* @__PURE__ */ (0,
|
|
5564
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5035
5565
|
"button",
|
|
5036
5566
|
{
|
|
5037
5567
|
type: "button",
|
|
@@ -5043,7 +5573,7 @@ var ImageEditor = ({
|
|
|
5043
5573
|
children: "Depth Mask"
|
|
5044
5574
|
}
|
|
5045
5575
|
),
|
|
5046
|
-
/* @__PURE__ */ (0,
|
|
5576
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
5047
5577
|
"button",
|
|
5048
5578
|
{
|
|
5049
5579
|
type: "button",
|
|
@@ -5053,14 +5583,14 @@ var ImageEditor = ({
|
|
|
5053
5583
|
},
|
|
5054
5584
|
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
5585
|
children: [
|
|
5056
|
-
/* @__PURE__ */ (0,
|
|
5586
|
+
/* @__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
5587
|
"AI Tools"
|
|
5058
5588
|
]
|
|
5059
5589
|
}
|
|
5060
5590
|
)
|
|
5061
5591
|
] }),
|
|
5062
|
-
/* @__PURE__ */ (0,
|
|
5063
|
-
/* @__PURE__ */ (0,
|
|
5592
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
5593
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5064
5594
|
"button",
|
|
5065
5595
|
{
|
|
5066
5596
|
type: "button",
|
|
@@ -5071,7 +5601,7 @@ var ImageEditor = ({
|
|
|
5071
5601
|
children: "\u21A9"
|
|
5072
5602
|
}
|
|
5073
5603
|
),
|
|
5074
|
-
/* @__PURE__ */ (0,
|
|
5604
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5075
5605
|
"button",
|
|
5076
5606
|
{
|
|
5077
5607
|
type: "button",
|
|
@@ -5082,7 +5612,7 @@ var ImageEditor = ({
|
|
|
5082
5612
|
children: "\u21AA"
|
|
5083
5613
|
}
|
|
5084
5614
|
),
|
|
5085
|
-
/* @__PURE__ */ (0,
|
|
5615
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5086
5616
|
"button",
|
|
5087
5617
|
{
|
|
5088
5618
|
type: "button",
|
|
@@ -5091,8 +5621,8 @@ var ImageEditor = ({
|
|
|
5091
5621
|
children: "Reset"
|
|
5092
5622
|
}
|
|
5093
5623
|
),
|
|
5094
|
-
/* @__PURE__ */ (0,
|
|
5095
|
-
/* @__PURE__ */ (0,
|
|
5624
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
5625
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5096
5626
|
"button",
|
|
5097
5627
|
{
|
|
5098
5628
|
type: "button",
|
|
@@ -5102,11 +5632,11 @@ var ImageEditor = ({
|
|
|
5102
5632
|
children: "-"
|
|
5103
5633
|
}
|
|
5104
5634
|
),
|
|
5105
|
-
/* @__PURE__ */ (0,
|
|
5635
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
|
|
5106
5636
|
Math.round(state.zoom * 100),
|
|
5107
5637
|
"%"
|
|
5108
5638
|
] }),
|
|
5109
|
-
/* @__PURE__ */ (0,
|
|
5639
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5110
5640
|
"button",
|
|
5111
5641
|
{
|
|
5112
5642
|
type: "button",
|
|
@@ -5116,8 +5646,8 @@ var ImageEditor = ({
|
|
|
5116
5646
|
children: "+"
|
|
5117
5647
|
}
|
|
5118
5648
|
),
|
|
5119
|
-
/* @__PURE__ */ (0,
|
|
5120
|
-
/* @__PURE__ */ (0,
|
|
5649
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
5650
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5121
5651
|
"button",
|
|
5122
5652
|
{
|
|
5123
5653
|
type: "button",
|
|
@@ -5128,7 +5658,7 @@ var ImageEditor = ({
|
|
|
5128
5658
|
children: "Hold Compare"
|
|
5129
5659
|
}
|
|
5130
5660
|
),
|
|
5131
|
-
/* @__PURE__ */ (0,
|
|
5661
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5132
5662
|
"button",
|
|
5133
5663
|
{
|
|
5134
5664
|
type: "button",
|
|
@@ -5139,13 +5669,13 @@ var ImageEditor = ({
|
|
|
5139
5669
|
)
|
|
5140
5670
|
] })
|
|
5141
5671
|
] }),
|
|
5142
|
-
/* @__PURE__ */ (0,
|
|
5143
|
-
/* @__PURE__ */ (0,
|
|
5672
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
|
|
5673
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5144
5674
|
"div",
|
|
5145
5675
|
{
|
|
5146
5676
|
ref: containerRef,
|
|
5147
5677
|
className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
|
|
5148
|
-
children: /* @__PURE__ */ (0,
|
|
5678
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5149
5679
|
"canvas",
|
|
5150
5680
|
{
|
|
5151
5681
|
ref: canvasRef,
|
|
@@ -5153,16 +5683,21 @@ var ImageEditor = ({
|
|
|
5153
5683
|
onMouseMove: handleMouseMove,
|
|
5154
5684
|
onMouseUp: handleMouseUp,
|
|
5155
5685
|
onMouseLeave: handleMouseUp,
|
|
5156
|
-
|
|
5686
|
+
onPointerDown: handlePaintPointerDown,
|
|
5687
|
+
onPointerMove: handlePaintPointerMove,
|
|
5688
|
+
onPointerUp: handlePaintPointerUp,
|
|
5689
|
+
onPointerCancel: () => paintGestureRef.current?.cancel(),
|
|
5690
|
+
"data-testid": "image-editor-canvas",
|
|
5691
|
+
className: `absolute inset-0 w-full h-full block ${activeTab === "paint" ? "touch-none cursor-crosshair" : ""}`
|
|
5157
5692
|
}
|
|
5158
5693
|
)
|
|
5159
5694
|
}
|
|
5160
5695
|
),
|
|
5161
|
-
/* @__PURE__ */ (0,
|
|
5162
|
-
activeTab === "crop" && /* @__PURE__ */ (0,
|
|
5163
|
-
/* @__PURE__ */ (0,
|
|
5164
|
-
/* @__PURE__ */ (0,
|
|
5165
|
-
/* @__PURE__ */ (0,
|
|
5696
|
+
/* @__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: [
|
|
5697
|
+
activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
5698
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
|
|
5699
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
|
|
5700
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5166
5701
|
"button",
|
|
5167
5702
|
{
|
|
5168
5703
|
type: "button",
|
|
@@ -5174,7 +5709,7 @@ var ImageEditor = ({
|
|
|
5174
5709
|
children: "Freeform"
|
|
5175
5710
|
}
|
|
5176
5711
|
),
|
|
5177
|
-
/* @__PURE__ */ (0,
|
|
5712
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5178
5713
|
"button",
|
|
5179
5714
|
{
|
|
5180
5715
|
type: "button",
|
|
@@ -5186,7 +5721,7 @@ var ImageEditor = ({
|
|
|
5186
5721
|
children: "1:1 Square"
|
|
5187
5722
|
}
|
|
5188
5723
|
),
|
|
5189
|
-
/* @__PURE__ */ (0,
|
|
5724
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5190
5725
|
"button",
|
|
5191
5726
|
{
|
|
5192
5727
|
type: "button",
|
|
@@ -5198,7 +5733,7 @@ var ImageEditor = ({
|
|
|
5198
5733
|
children: "4:3 Standard"
|
|
5199
5734
|
}
|
|
5200
5735
|
),
|
|
5201
|
-
/* @__PURE__ */ (0,
|
|
5736
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5202
5737
|
"button",
|
|
5203
5738
|
{
|
|
5204
5739
|
type: "button",
|
|
@@ -5210,7 +5745,7 @@ var ImageEditor = ({
|
|
|
5210
5745
|
children: "16:9 Wide"
|
|
5211
5746
|
}
|
|
5212
5747
|
),
|
|
5213
|
-
/* @__PURE__ */ (0,
|
|
5748
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5214
5749
|
"button",
|
|
5215
5750
|
{
|
|
5216
5751
|
type: "button",
|
|
@@ -5222,7 +5757,7 @@ var ImageEditor = ({
|
|
|
5222
5757
|
children: "3:2 Photo"
|
|
5223
5758
|
}
|
|
5224
5759
|
),
|
|
5225
|
-
/* @__PURE__ */ (0,
|
|
5760
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5226
5761
|
"button",
|
|
5227
5762
|
{
|
|
5228
5763
|
type: "button",
|
|
@@ -5235,10 +5770,10 @@ var ImageEditor = ({
|
|
|
5235
5770
|
}
|
|
5236
5771
|
)
|
|
5237
5772
|
] }),
|
|
5238
|
-
/* @__PURE__ */ (0,
|
|
5239
|
-
/* @__PURE__ */ (0,
|
|
5240
|
-
/* @__PURE__ */ (0,
|
|
5241
|
-
/* @__PURE__ */ (0,
|
|
5773
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
5774
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
|
|
5775
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
5776
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5242
5777
|
"button",
|
|
5243
5778
|
{
|
|
5244
5779
|
type: "button",
|
|
@@ -5247,7 +5782,7 @@ var ImageEditor = ({
|
|
|
5247
5782
|
children: "Rotate -90\xB0"
|
|
5248
5783
|
}
|
|
5249
5784
|
),
|
|
5250
|
-
/* @__PURE__ */ (0,
|
|
5785
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5251
5786
|
"button",
|
|
5252
5787
|
{
|
|
5253
5788
|
type: "button",
|
|
@@ -5256,7 +5791,7 @@ var ImageEditor = ({
|
|
|
5256
5791
|
children: "Rotate +90\xB0"
|
|
5257
5792
|
}
|
|
5258
5793
|
),
|
|
5259
|
-
/* @__PURE__ */ (0,
|
|
5794
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5260
5795
|
"button",
|
|
5261
5796
|
{
|
|
5262
5797
|
type: "button",
|
|
@@ -5265,7 +5800,7 @@ var ImageEditor = ({
|
|
|
5265
5800
|
children: "Flip Horizontal"
|
|
5266
5801
|
}
|
|
5267
5802
|
),
|
|
5268
|
-
/* @__PURE__ */ (0,
|
|
5803
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5269
5804
|
"button",
|
|
5270
5805
|
{
|
|
5271
5806
|
type: "button",
|
|
@@ -5276,10 +5811,10 @@ var ImageEditor = ({
|
|
|
5276
5811
|
)
|
|
5277
5812
|
] })
|
|
5278
5813
|
] }),
|
|
5279
|
-
activeTab === "adjust" && /* @__PURE__ */ (0,
|
|
5280
|
-
/* @__PURE__ */ (0,
|
|
5281
|
-
/* @__PURE__ */ (0,
|
|
5282
|
-
/* @__PURE__ */ (0,
|
|
5814
|
+
activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
5815
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
5816
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
|
|
5817
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5283
5818
|
"button",
|
|
5284
5819
|
{
|
|
5285
5820
|
type: "button",
|
|
@@ -5289,25 +5824,25 @@ var ImageEditor = ({
|
|
|
5289
5824
|
}
|
|
5290
5825
|
)
|
|
5291
5826
|
] }),
|
|
5292
|
-
/* @__PURE__ */ (0,
|
|
5293
|
-
|
|
5294
|
-
/* @__PURE__ */ (0,
|
|
5827
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Histogram, { histogram: editor.histogram }),
|
|
5828
|
+
import_image_editor10.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react42.default.Fragment, { children: [
|
|
5829
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5295
5830
|
ControlSlider,
|
|
5296
5831
|
{
|
|
5297
5832
|
spec,
|
|
5298
|
-
value: (0,
|
|
5833
|
+
value: (0, import_image_editor10.readAdjustmentControls)(state.adjustments)[spec.id],
|
|
5299
5834
|
disabled: spec.requiresProcess !== void 0 && legacyProcess,
|
|
5300
5835
|
onChange: (v) => editor.setAdjustments({ [spec.id]: v })
|
|
5301
5836
|
}
|
|
5302
5837
|
),
|
|
5303
|
-
spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0,
|
|
5838
|
+
spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
5304
5839
|
"div",
|
|
5305
5840
|
{
|
|
5306
5841
|
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
5842
|
"data-testid": "image-editor-process-notice",
|
|
5308
5843
|
children: [
|
|
5309
|
-
/* @__PURE__ */ (0,
|
|
5310
|
-
/* @__PURE__ */ (0,
|
|
5844
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
|
|
5845
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5311
5846
|
"button",
|
|
5312
5847
|
{
|
|
5313
5848
|
type: "button",
|
|
@@ -5320,7 +5855,7 @@ var ImageEditor = ({
|
|
|
5320
5855
|
}
|
|
5321
5856
|
)
|
|
5322
5857
|
] }, spec.id)),
|
|
5323
|
-
/* @__PURE__ */ (0,
|
|
5858
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5324
5859
|
AdjustmentLayersPanel,
|
|
5325
5860
|
{
|
|
5326
5861
|
controller,
|
|
@@ -5329,9 +5864,19 @@ var ImageEditor = ({
|
|
|
5329
5864
|
}
|
|
5330
5865
|
) })
|
|
5331
5866
|
] }),
|
|
5332
|
-
activeTab === "
|
|
5333
|
-
/* @__PURE__ */ (0,
|
|
5334
|
-
/* @__PURE__ */ (0,
|
|
5867
|
+
activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
5868
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
|
|
5869
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LayersPanel, { controller })
|
|
5870
|
+
] }),
|
|
5871
|
+
activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
5872
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
|
|
5873
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(BrushOptionsBar, { controller }),
|
|
5874
|
+
paintError && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
|
|
5875
|
+
/* @__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 }) })
|
|
5876
|
+
] }),
|
|
5877
|
+
activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
5878
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
|
|
5879
|
+
/* @__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
5880
|
"button",
|
|
5336
5881
|
{
|
|
5337
5882
|
type: "button",
|
|
@@ -5341,9 +5886,9 @@ var ImageEditor = ({
|
|
|
5341
5886
|
},
|
|
5342
5887
|
t
|
|
5343
5888
|
)) }),
|
|
5344
|
-
/* @__PURE__ */ (0,
|
|
5345
|
-
/* @__PURE__ */ (0,
|
|
5346
|
-
/* @__PURE__ */ (0,
|
|
5889
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
5890
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("label", { className: "text-slate-400", children: "Color:" }),
|
|
5891
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5347
5892
|
"input",
|
|
5348
5893
|
{
|
|
5349
5894
|
type: "color",
|
|
@@ -5352,15 +5897,15 @@ var ImageEditor = ({
|
|
|
5352
5897
|
className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
|
|
5353
5898
|
}
|
|
5354
5899
|
),
|
|
5355
|
-
/* @__PURE__ */ (0,
|
|
5356
|
-
/* @__PURE__ */ (0,
|
|
5357
|
-
/* @__PURE__ */ (0,
|
|
5358
|
-
/* @__PURE__ */ (0,
|
|
5900
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex-1 ml-2", children: [
|
|
5901
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
|
|
5902
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Width:" }),
|
|
5903
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
|
|
5359
5904
|
strokeWidth,
|
|
5360
5905
|
"px"
|
|
5361
5906
|
] })
|
|
5362
5907
|
] }),
|
|
5363
|
-
/* @__PURE__ */ (0,
|
|
5908
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5364
5909
|
"input",
|
|
5365
5910
|
{
|
|
5366
5911
|
type: "range",
|
|
@@ -5373,10 +5918,10 @@ var ImageEditor = ({
|
|
|
5373
5918
|
)
|
|
5374
5919
|
] })
|
|
5375
5920
|
] }),
|
|
5376
|
-
/* @__PURE__ */ (0,
|
|
5377
|
-
/* @__PURE__ */ (0,
|
|
5378
|
-
/* @__PURE__ */ (0,
|
|
5379
|
-
/* @__PURE__ */ (0,
|
|
5921
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
5922
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
|
|
5923
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-2", children: [
|
|
5924
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5380
5925
|
"input",
|
|
5381
5926
|
{
|
|
5382
5927
|
type: "text",
|
|
@@ -5387,7 +5932,7 @@ var ImageEditor = ({
|
|
|
5387
5932
|
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
5933
|
}
|
|
5389
5934
|
),
|
|
5390
|
-
/* @__PURE__ */ (0,
|
|
5935
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5391
5936
|
"button",
|
|
5392
5937
|
{
|
|
5393
5938
|
type: "button",
|
|
@@ -5397,14 +5942,14 @@ var ImageEditor = ({
|
|
|
5397
5942
|
}
|
|
5398
5943
|
)
|
|
5399
5944
|
] }),
|
|
5400
|
-
/* @__PURE__ */ (0,
|
|
5401
|
-
/* @__PURE__ */ (0,
|
|
5402
|
-
/* @__PURE__ */ (0,
|
|
5945
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
|
|
5946
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Font Size:" }),
|
|
5947
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
|
|
5403
5948
|
fontSize,
|
|
5404
5949
|
"px"
|
|
5405
5950
|
] })
|
|
5406
5951
|
] }),
|
|
5407
|
-
/* @__PURE__ */ (0,
|
|
5952
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5408
5953
|
"input",
|
|
5409
5954
|
{
|
|
5410
5955
|
type: "range",
|
|
@@ -5415,14 +5960,14 @@ var ImageEditor = ({
|
|
|
5415
5960
|
className: "w-full accent-indigo-500"
|
|
5416
5961
|
}
|
|
5417
5962
|
),
|
|
5418
|
-
/* @__PURE__ */ (0,
|
|
5419
|
-
/* @__PURE__ */ (0,
|
|
5420
|
-
/* @__PURE__ */ (0,
|
|
5963
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
5964
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
5965
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "text-slate-400", children: [
|
|
5421
5966
|
"Layers (",
|
|
5422
5967
|
state.annotations.length,
|
|
5423
5968
|
")"
|
|
5424
5969
|
] }),
|
|
5425
|
-
state.selectedAnnotationId && /* @__PURE__ */ (0,
|
|
5970
|
+
state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5426
5971
|
"button",
|
|
5427
5972
|
{
|
|
5428
5973
|
type: "button",
|
|
@@ -5431,7 +5976,7 @@ var ImageEditor = ({
|
|
|
5431
5976
|
children: "Delete Selected"
|
|
5432
5977
|
}
|
|
5433
5978
|
),
|
|
5434
|
-
state.annotations.length > 0 && /* @__PURE__ */ (0,
|
|
5979
|
+
state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5435
5980
|
"button",
|
|
5436
5981
|
{
|
|
5437
5982
|
type: "button",
|
|
@@ -5442,10 +5987,10 @@ var ImageEditor = ({
|
|
|
5442
5987
|
)
|
|
5443
5988
|
] })
|
|
5444
5989
|
] }),
|
|
5445
|
-
activeTab === "depth" && /* @__PURE__ */ (0,
|
|
5446
|
-
/* @__PURE__ */ (0,
|
|
5447
|
-
/* @__PURE__ */ (0,
|
|
5448
|
-
/* @__PURE__ */ (0,
|
|
5990
|
+
activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
5991
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
5992
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
|
|
5993
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5449
5994
|
"button",
|
|
5450
5995
|
{
|
|
5451
5996
|
type: "button",
|
|
@@ -5455,8 +6000,8 @@ var ImageEditor = ({
|
|
|
5455
6000
|
}
|
|
5456
6001
|
)
|
|
5457
6002
|
] }),
|
|
5458
|
-
/* @__PURE__ */ (0,
|
|
5459
|
-
/* @__PURE__ */ (0,
|
|
6003
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
|
|
6004
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5460
6005
|
"input",
|
|
5461
6006
|
{
|
|
5462
6007
|
type: "checkbox",
|
|
@@ -5465,12 +6010,12 @@ var ImageEditor = ({
|
|
|
5465
6010
|
className: "rounded accent-indigo-500"
|
|
5466
6011
|
}
|
|
5467
6012
|
),
|
|
5468
|
-
/* @__PURE__ */ (0,
|
|
6013
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Enable Depth / Alpha Mask" })
|
|
5469
6014
|
] }),
|
|
5470
|
-
state.depthMask.enabled && /* @__PURE__ */ (0,
|
|
5471
|
-
/* @__PURE__ */ (0,
|
|
5472
|
-
/* @__PURE__ */ (0,
|
|
5473
|
-
/* @__PURE__ */ (0,
|
|
6015
|
+
state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
6016
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
|
|
6017
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
|
|
6018
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5474
6019
|
"input",
|
|
5475
6020
|
{
|
|
5476
6021
|
type: "text",
|
|
@@ -5481,8 +6026,8 @@ var ImageEditor = ({
|
|
|
5481
6026
|
}
|
|
5482
6027
|
)
|
|
5483
6028
|
] }),
|
|
5484
|
-
/* @__PURE__ */ (0,
|
|
5485
|
-
/* @__PURE__ */ (0,
|
|
6029
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-2", children: [
|
|
6030
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5486
6031
|
"button",
|
|
5487
6032
|
{
|
|
5488
6033
|
type: "button",
|
|
@@ -5491,7 +6036,7 @@ var ImageEditor = ({
|
|
|
5491
6036
|
children: "Threshold Mode"
|
|
5492
6037
|
}
|
|
5493
6038
|
),
|
|
5494
|
-
/* @__PURE__ */ (0,
|
|
6039
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5495
6040
|
"button",
|
|
5496
6041
|
{
|
|
5497
6042
|
type: "button",
|
|
@@ -5501,12 +6046,12 @@ var ImageEditor = ({
|
|
|
5501
6046
|
}
|
|
5502
6047
|
)
|
|
5503
6048
|
] }),
|
|
5504
|
-
/* @__PURE__ */ (0,
|
|
5505
|
-
/* @__PURE__ */ (0,
|
|
5506
|
-
/* @__PURE__ */ (0,
|
|
5507
|
-
/* @__PURE__ */ (0,
|
|
6049
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
|
|
6050
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
6051
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Depth Start (Lower):" }),
|
|
6052
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
|
|
5508
6053
|
] }),
|
|
5509
|
-
/* @__PURE__ */ (0,
|
|
6054
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5510
6055
|
"input",
|
|
5511
6056
|
{
|
|
5512
6057
|
type: "range",
|
|
@@ -5520,12 +6065,12 @@ var ImageEditor = ({
|
|
|
5520
6065
|
}
|
|
5521
6066
|
)
|
|
5522
6067
|
] }),
|
|
5523
|
-
/* @__PURE__ */ (0,
|
|
5524
|
-
/* @__PURE__ */ (0,
|
|
5525
|
-
/* @__PURE__ */ (0,
|
|
5526
|
-
/* @__PURE__ */ (0,
|
|
6068
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
|
|
6069
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
6070
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Depth Stop (Upper):" }),
|
|
6071
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
|
|
5527
6072
|
] }),
|
|
5528
|
-
/* @__PURE__ */ (0,
|
|
6073
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5529
6074
|
"input",
|
|
5530
6075
|
{
|
|
5531
6076
|
type: "range",
|
|
@@ -5539,12 +6084,12 @@ var ImageEditor = ({
|
|
|
5539
6084
|
}
|
|
5540
6085
|
)
|
|
5541
6086
|
] }),
|
|
5542
|
-
/* @__PURE__ */ (0,
|
|
5543
|
-
/* @__PURE__ */ (0,
|
|
5544
|
-
/* @__PURE__ */ (0,
|
|
5545
|
-
/* @__PURE__ */ (0,
|
|
6087
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
|
|
6088
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
6089
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Softness:" }),
|
|
6090
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
|
|
5546
6091
|
] }),
|
|
5547
|
-
/* @__PURE__ */ (0,
|
|
6092
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5548
6093
|
"input",
|
|
5549
6094
|
{
|
|
5550
6095
|
type: "range",
|
|
@@ -5556,8 +6101,8 @@ var ImageEditor = ({
|
|
|
5556
6101
|
}
|
|
5557
6102
|
)
|
|
5558
6103
|
] }),
|
|
5559
|
-
/* @__PURE__ */ (0,
|
|
5560
|
-
/* @__PURE__ */ (0,
|
|
6104
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
|
|
6105
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5561
6106
|
"input",
|
|
5562
6107
|
{
|
|
5563
6108
|
type: "checkbox",
|
|
@@ -5566,12 +6111,12 @@ var ImageEditor = ({
|
|
|
5566
6111
|
className: "rounded accent-indigo-500"
|
|
5567
6112
|
}
|
|
5568
6113
|
),
|
|
5569
|
-
/* @__PURE__ */ (0,
|
|
6114
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Invert Mask" })
|
|
5570
6115
|
] })
|
|
5571
6116
|
] })
|
|
5572
6117
|
] }),
|
|
5573
|
-
activeTab === "select" && /* @__PURE__ */ (0,
|
|
5574
|
-
/* @__PURE__ */ (0,
|
|
6118
|
+
activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
6119
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5575
6120
|
SelectionOptionsBar,
|
|
5576
6121
|
{
|
|
5577
6122
|
controller,
|
|
@@ -5581,51 +6126,51 @@ var ImageEditor = ({
|
|
|
5581
6126
|
quickMask: Boolean(state.quickMask)
|
|
5582
6127
|
}
|
|
5583
6128
|
),
|
|
5584
|
-
selectionError && /* @__PURE__ */ (0,
|
|
5585
|
-
/* @__PURE__ */ (0,
|
|
6129
|
+
selectionError && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
|
|
6130
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
|
|
5586
6131
|
] }),
|
|
5587
|
-
activeTab === "ai" && /* @__PURE__ */ (0,
|
|
5588
|
-
/* @__PURE__ */ (0,
|
|
5589
|
-
/* @__PURE__ */ (0,
|
|
5590
|
-
/* @__PURE__ */ (0,
|
|
5591
|
-
/* @__PURE__ */ (0,
|
|
6132
|
+
activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
6133
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
6134
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
6135
|
+
/* @__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: [
|
|
6136
|
+
/* @__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
6137
|
"Background Removal"
|
|
5593
6138
|
] }),
|
|
5594
|
-
isRemovingBg && /* @__PURE__ */ (0,
|
|
6139
|
+
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
6140
|
] }),
|
|
5596
|
-
/* @__PURE__ */ (0,
|
|
5597
|
-
/* @__PURE__ */ (0,
|
|
6141
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
|
|
6142
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5598
6143
|
"button",
|
|
5599
6144
|
{
|
|
5600
6145
|
type: "button",
|
|
5601
6146
|
onClick: handleRemoveBackground,
|
|
5602
6147
|
disabled: isRemovingBg || isInpainting,
|
|
5603
6148
|
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,
|
|
6149
|
+
children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
6150
|
+
/* @__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
6151
|
"Removing Background..."
|
|
5607
|
-
] }) : /* @__PURE__ */ (0,
|
|
5608
|
-
/* @__PURE__ */ (0,
|
|
6152
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
6153
|
+
/* @__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
6154
|
"Remove Background"
|
|
5610
6155
|
] })
|
|
5611
6156
|
}
|
|
5612
6157
|
)
|
|
5613
6158
|
] }),
|
|
5614
|
-
/* @__PURE__ */ (0,
|
|
5615
|
-
/* @__PURE__ */ (0,
|
|
5616
|
-
/* @__PURE__ */ (0,
|
|
5617
|
-
/* @__PURE__ */ (0,
|
|
5618
|
-
/* @__PURE__ */ (0,
|
|
5619
|
-
/* @__PURE__ */ (0,
|
|
6159
|
+
/* @__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: [
|
|
6160
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
6161
|
+
/* @__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: [
|
|
6162
|
+
/* @__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: [
|
|
6163
|
+
/* @__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" }),
|
|
6164
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "m14 7 3 3" })
|
|
5620
6165
|
] }),
|
|
5621
6166
|
"Generative Inpainting"
|
|
5622
6167
|
] }),
|
|
5623
|
-
isInpainting && /* @__PURE__ */ (0,
|
|
6168
|
+
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
6169
|
] }),
|
|
5625
|
-
/* @__PURE__ */ (0,
|
|
5626
|
-
/* @__PURE__ */ (0,
|
|
5627
|
-
/* @__PURE__ */ (0,
|
|
5628
|
-
/* @__PURE__ */ (0,
|
|
6170
|
+
/* @__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." }),
|
|
6171
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
6172
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
|
|
6173
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5629
6174
|
"textarea",
|
|
5630
6175
|
{
|
|
5631
6176
|
id: "ai-inpaint-prompt-react",
|
|
@@ -5637,10 +6182,10 @@ var ImageEditor = ({
|
|
|
5637
6182
|
}
|
|
5638
6183
|
)
|
|
5639
6184
|
] }),
|
|
5640
|
-
/* @__PURE__ */ (0,
|
|
5641
|
-
/* @__PURE__ */ (0,
|
|
5642
|
-
/* @__PURE__ */ (0,
|
|
5643
|
-
/* @__PURE__ */ (0,
|
|
6185
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
6186
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
|
|
6187
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
|
|
6188
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
5644
6189
|
"button",
|
|
5645
6190
|
{
|
|
5646
6191
|
type: "button",
|
|
@@ -5653,7 +6198,7 @@ var ImageEditor = ({
|
|
|
5653
6198
|
]
|
|
5654
6199
|
}
|
|
5655
6200
|
),
|
|
5656
|
-
/* @__PURE__ */ (0,
|
|
6201
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
5657
6202
|
"button",
|
|
5658
6203
|
{
|
|
5659
6204
|
type: "button",
|
|
@@ -5668,25 +6213,25 @@ var ImageEditor = ({
|
|
|
5668
6213
|
)
|
|
5669
6214
|
] })
|
|
5670
6215
|
] }),
|
|
5671
|
-
/* @__PURE__ */ (0,
|
|
6216
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5672
6217
|
"button",
|
|
5673
6218
|
{
|
|
5674
6219
|
type: "button",
|
|
5675
6220
|
onClick: handleInpaint,
|
|
5676
6221
|
disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
|
|
5677
6222
|
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,
|
|
6223
|
+
children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
6224
|
+
/* @__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
6225
|
"Generating Inpaint..."
|
|
5681
|
-
] }) : /* @__PURE__ */ (0,
|
|
5682
|
-
/* @__PURE__ */ (0,
|
|
6226
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
6227
|
+
/* @__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
6228
|
"Apply Inpainting"
|
|
5684
6229
|
] })
|
|
5685
6230
|
}
|
|
5686
6231
|
)
|
|
5687
6232
|
] }),
|
|
5688
|
-
aiError && /* @__PURE__ */ (0,
|
|
5689
|
-
aiSuccess && /* @__PURE__ */ (0,
|
|
6233
|
+
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 }),
|
|
6234
|
+
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
6235
|
] })
|
|
5691
6236
|
] })
|
|
5692
6237
|
] })
|
|
@@ -5696,7 +6241,7 @@ var ImageEditor = ({
|
|
|
5696
6241
|
};
|
|
5697
6242
|
|
|
5698
6243
|
// src/review/useReview.ts
|
|
5699
|
-
var
|
|
6244
|
+
var import_react43 = require("react");
|
|
5700
6245
|
var import_editor12 = require("@pixerate/editor");
|
|
5701
6246
|
var EMPTY_COMMENTS = Object.freeze({
|
|
5702
6247
|
threads: [],
|
|
@@ -5715,23 +6260,23 @@ function isCommentStore(value) {
|
|
|
5715
6260
|
}
|
|
5716
6261
|
function useComments(source) {
|
|
5717
6262
|
const store = isCommentStore(source) ? source : (0, import_editor12.getCommentStore)(source);
|
|
5718
|
-
const subscribe = (0,
|
|
6263
|
+
const subscribe = (0, import_react43.useCallback)(
|
|
5719
6264
|
(onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
|
|
5720
6265
|
[store]
|
|
5721
6266
|
);
|
|
5722
6267
|
const getSnapshot = () => store?.getSnapshot() ?? EMPTY_COMMENTS;
|
|
5723
|
-
const snapshot = (0,
|
|
5724
|
-
return (0,
|
|
6268
|
+
const snapshot = (0, import_react43.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
6269
|
+
return (0, import_react43.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
|
|
5725
6270
|
}
|
|
5726
6271
|
function useTrackChanges(editor) {
|
|
5727
6272
|
const store = (0, import_editor12.getTrackChangesStore)(editor ?? null);
|
|
5728
|
-
const subscribe = (0,
|
|
6273
|
+
const subscribe = (0, import_react43.useCallback)(
|
|
5729
6274
|
(onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
|
|
5730
6275
|
[store]
|
|
5731
6276
|
);
|
|
5732
6277
|
const getSnapshot = () => store?.getSnapshot() ?? EMPTY_TRACK_CHANGES;
|
|
5733
|
-
const snapshot = (0,
|
|
5734
|
-
return (0,
|
|
6278
|
+
const snapshot = (0, import_react43.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
6279
|
+
return (0, import_react43.useMemo)(() => {
|
|
5735
6280
|
const run = (fn) => () => {
|
|
5736
6281
|
if (editor && !editor.isDestroyed) fn(editor);
|
|
5737
6282
|
};
|
|
@@ -5754,9 +6299,9 @@ function useTrackChanges(editor) {
|
|
|
5754
6299
|
}
|
|
5755
6300
|
|
|
5756
6301
|
// src/review/CommentsPanel.tsx
|
|
5757
|
-
var
|
|
6302
|
+
var import_react44 = require("react");
|
|
5758
6303
|
var import_editor13 = require("@pixerate/editor");
|
|
5759
|
-
var
|
|
6304
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
5760
6305
|
var buttonClass2 = "rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50";
|
|
5761
6306
|
var primaryButtonClass = "rounded px-2 py-1 text-xs bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-50";
|
|
5762
6307
|
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 +6315,18 @@ var CommentsPanel = ({
|
|
|
5770
6315
|
emptyMessage = "No comments yet. Select text and add a comment."
|
|
5771
6316
|
}) => {
|
|
5772
6317
|
const { threads, activeThreadId, store } = useComments(storeProp ?? editor);
|
|
5773
|
-
const [showResolved, setShowResolved] = (0,
|
|
6318
|
+
const [showResolved, setShowResolved] = (0, import_react44.useState)(showResolvedInitial);
|
|
5774
6319
|
const author = authorProp ?? (0, import_editor13.getCommentAuthor)(editor) ?? { id: "anonymous", name: "Anonymous" };
|
|
5775
6320
|
const visible = threads.filter((t) => showResolved || !t.resolved);
|
|
5776
6321
|
const resolvedCount = threads.filter((t) => t.resolved).length;
|
|
5777
|
-
return /* @__PURE__ */ (0,
|
|
5778
|
-
/* @__PURE__ */ (0,
|
|
5779
|
-
/* @__PURE__ */ (0,
|
|
6322
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("aside", { className, "aria-label": "Comments", children: [
|
|
6323
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
|
|
6324
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "text-xs font-medium text-muted-foreground", children: [
|
|
5780
6325
|
threads.length - resolvedCount,
|
|
5781
6326
|
" open",
|
|
5782
6327
|
resolvedCount > 0 ? ` \xB7 ${resolvedCount} resolved` : ""
|
|
5783
6328
|
] }),
|
|
5784
|
-
resolvedCount > 0 && /* @__PURE__ */ (0,
|
|
6329
|
+
resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
5785
6330
|
"button",
|
|
5786
6331
|
{
|
|
5787
6332
|
type: "button",
|
|
@@ -5792,7 +6337,7 @@ var CommentsPanel = ({
|
|
|
5792
6337
|
}
|
|
5793
6338
|
)
|
|
5794
6339
|
] }),
|
|
5795
|
-
visible.length === 0 ? /* @__PURE__ */ (0,
|
|
6340
|
+
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
6341
|
CommentThreadCard,
|
|
5797
6342
|
{
|
|
5798
6343
|
thread,
|
|
@@ -5814,7 +6359,7 @@ var CommentThreadCard = ({
|
|
|
5814
6359
|
author,
|
|
5815
6360
|
formatTime
|
|
5816
6361
|
}) => {
|
|
5817
|
-
const [draft, setDraft] = (0,
|
|
6362
|
+
const [draft, setDraft] = (0, import_react44.useState)("");
|
|
5818
6363
|
const isDraft = thread.body === "";
|
|
5819
6364
|
const quote = thread.anchor?.quote ?? thread.lastQuote ?? "";
|
|
5820
6365
|
const live = editor && !editor.isDestroyed ? editor : null;
|
|
@@ -5840,7 +6385,7 @@ var CommentThreadCard = ({
|
|
|
5840
6385
|
setDraft("");
|
|
5841
6386
|
};
|
|
5842
6387
|
const stop = (e) => e.stopPropagation();
|
|
5843
|
-
return /* @__PURE__ */ (0,
|
|
6388
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
5844
6389
|
"li",
|
|
5845
6390
|
{
|
|
5846
6391
|
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 +6401,24 @@ var CommentThreadCard = ({
|
|
|
5856
6401
|
}
|
|
5857
6402
|
},
|
|
5858
6403
|
children: [
|
|
5859
|
-
/* @__PURE__ */ (0,
|
|
5860
|
-
/* @__PURE__ */ (0,
|
|
5861
|
-
/* @__PURE__ */ (0,
|
|
6404
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [
|
|
6405
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-medium", children: thread.author.name }),
|
|
6406
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
|
|
5862
6407
|
] }),
|
|
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,
|
|
6408
|
+
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 }),
|
|
6409
|
+
thread.orphaned && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
|
|
6410
|
+
thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
|
|
6411
|
+
!isDraft && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
|
|
6412
|
+
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: [
|
|
6413
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "text-xs", children: [
|
|
6414
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-medium", children: reply.author.name }),
|
|
5870
6415
|
" ",
|
|
5871
|
-
/* @__PURE__ */ (0,
|
|
6416
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
|
|
5872
6417
|
] }),
|
|
5873
|
-
/* @__PURE__ */ (0,
|
|
6418
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
|
|
5874
6419
|
] }, reply.id)) }),
|
|
5875
|
-
(active || isDraft) && !thread.resolved && /* @__PURE__ */ (0,
|
|
5876
|
-
/* @__PURE__ */ (0,
|
|
6420
|
+
(active || isDraft) && !thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-1", onClick: stop, children: [
|
|
6421
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
5877
6422
|
"textarea",
|
|
5878
6423
|
{
|
|
5879
6424
|
className: textareaClass,
|
|
@@ -5891,9 +6436,9 @@ var CommentThreadCard = ({
|
|
|
5891
6436
|
}
|
|
5892
6437
|
}
|
|
5893
6438
|
),
|
|
5894
|
-
/* @__PURE__ */ (0,
|
|
5895
|
-
isDraft && /* @__PURE__ */ (0,
|
|
5896
|
-
/* @__PURE__ */ (0,
|
|
6439
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex justify-end gap-1", children: [
|
|
6440
|
+
isDraft && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: buttonClass2, onClick: remove, children: "Cancel" }),
|
|
6441
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
5897
6442
|
"button",
|
|
5898
6443
|
{
|
|
5899
6444
|
type: "button",
|
|
@@ -5905,9 +6450,9 @@ var CommentThreadCard = ({
|
|
|
5905
6450
|
)
|
|
5906
6451
|
] })
|
|
5907
6452
|
] }),
|
|
5908
|
-
!isDraft && /* @__PURE__ */ (0,
|
|
5909
|
-
/* @__PURE__ */ (0,
|
|
5910
|
-
/* @__PURE__ */ (0,
|
|
6453
|
+
!isDraft && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex justify-end gap-1", onClick: stop, children: [
|
|
6454
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: buttonClass2, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
|
|
6455
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
5911
6456
|
"button",
|
|
5912
6457
|
{
|
|
5913
6458
|
type: "button",
|
|
@@ -5923,7 +6468,7 @@ var CommentThreadCard = ({
|
|
|
5923
6468
|
};
|
|
5924
6469
|
|
|
5925
6470
|
// src/review/ReviewToolbar.tsx
|
|
5926
|
-
var
|
|
6471
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
5927
6472
|
var defaultDescriptionClass = "max-w-[16rem] truncate px-1 text-xs text-muted-foreground";
|
|
5928
6473
|
var buttonClass3 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
|
|
5929
6474
|
var ReviewToolbar = ({
|
|
@@ -5936,8 +6481,8 @@ var ReviewToolbar = ({
|
|
|
5936
6481
|
const count = review.changes.length;
|
|
5937
6482
|
const current = review.currentChange;
|
|
5938
6483
|
const index = current ? review.changes.findIndex((c) => c.id === current.id) + 1 : 0;
|
|
5939
|
-
return /* @__PURE__ */ (0,
|
|
5940
|
-
/* @__PURE__ */ (0,
|
|
6484
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className, role: "toolbar", "aria-label": "Review", children: [
|
|
6485
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5941
6486
|
"button",
|
|
5942
6487
|
{
|
|
5943
6488
|
type: "button",
|
|
@@ -5948,8 +6493,8 @@ var ReviewToolbar = ({
|
|
|
5948
6493
|
children: review.enabled ? "Tracking on" : "Track changes"
|
|
5949
6494
|
}
|
|
5950
6495
|
),
|
|
5951
|
-
/* @__PURE__ */ (0,
|
|
5952
|
-
/* @__PURE__ */ (0,
|
|
6496
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
|
|
6497
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5953
6498
|
"button",
|
|
5954
6499
|
{
|
|
5955
6500
|
type: "button",
|
|
@@ -5960,8 +6505,8 @@ var ReviewToolbar = ({
|
|
|
5960
6505
|
children: "\u2039"
|
|
5961
6506
|
}
|
|
5962
6507
|
),
|
|
5963
|
-
/* @__PURE__ */ (0,
|
|
5964
|
-
/* @__PURE__ */ (0,
|
|
6508
|
+
/* @__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` }),
|
|
6509
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5965
6510
|
"button",
|
|
5966
6511
|
{
|
|
5967
6512
|
type: "button",
|
|
@@ -5972,7 +6517,7 @@ var ReviewToolbar = ({
|
|
|
5972
6517
|
children: "\u203A"
|
|
5973
6518
|
}
|
|
5974
6519
|
),
|
|
5975
|
-
showDescription && current && /* @__PURE__ */ (0,
|
|
6520
|
+
showDescription && current && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
5976
6521
|
"span",
|
|
5977
6522
|
{
|
|
5978
6523
|
className: descriptionClassName,
|
|
@@ -5984,8 +6529,8 @@ var ReviewToolbar = ({
|
|
|
5984
6529
|
]
|
|
5985
6530
|
}
|
|
5986
6531
|
),
|
|
5987
|
-
/* @__PURE__ */ (0,
|
|
5988
|
-
/* @__PURE__ */ (0,
|
|
6532
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
|
|
6533
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5989
6534
|
"button",
|
|
5990
6535
|
{
|
|
5991
6536
|
type: "button",
|
|
@@ -5995,7 +6540,7 @@ var ReviewToolbar = ({
|
|
|
5995
6540
|
children: "Accept"
|
|
5996
6541
|
}
|
|
5997
6542
|
),
|
|
5998
|
-
/* @__PURE__ */ (0,
|
|
6543
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5999
6544
|
"button",
|
|
6000
6545
|
{
|
|
6001
6546
|
type: "button",
|
|
@@ -6005,18 +6550,18 @@ var ReviewToolbar = ({
|
|
|
6005
6550
|
children: "Reject"
|
|
6006
6551
|
}
|
|
6007
6552
|
),
|
|
6008
|
-
/* @__PURE__ */ (0,
|
|
6009
|
-
/* @__PURE__ */ (0,
|
|
6553
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
|
|
6554
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
|
|
6010
6555
|
] });
|
|
6011
6556
|
};
|
|
6012
6557
|
|
|
6013
6558
|
// src/review/CommentButton.tsx
|
|
6014
|
-
var
|
|
6559
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
6015
6560
|
var CommentButton = ({
|
|
6016
6561
|
editor,
|
|
6017
6562
|
className = "rounded px-2 py-1 text-xs text-popover-foreground hover:bg-muted",
|
|
6018
6563
|
children = "Comment"
|
|
6019
|
-
}) => /* @__PURE__ */ (0,
|
|
6564
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
6020
6565
|
"button",
|
|
6021
6566
|
{
|
|
6022
6567
|
type: "button",
|
|
@@ -6028,13 +6573,13 @@ var CommentButton = ({
|
|
|
6028
6573
|
);
|
|
6029
6574
|
|
|
6030
6575
|
// src/review/useDocumentCompare.ts
|
|
6031
|
-
var
|
|
6576
|
+
var import_react45 = require("react");
|
|
6032
6577
|
var import_editor14 = require("@pixerate/editor");
|
|
6033
6578
|
function useDocumentCompare(editor, options) {
|
|
6034
|
-
const [summary, setSummary] = (0,
|
|
6035
|
-
const defaults = (0,
|
|
6579
|
+
const [summary, setSummary] = (0, import_react45.useState)(null);
|
|
6580
|
+
const defaults = (0, import_react45.useRef)(options);
|
|
6036
6581
|
defaults.current = options;
|
|
6037
|
-
const compare = (0,
|
|
6582
|
+
const compare = (0, import_react45.useCallback)(
|
|
6038
6583
|
(original, revised, overrides) => {
|
|
6039
6584
|
if (!editor || editor.isDestroyed) return null;
|
|
6040
6585
|
const result = (0, import_editor14.applyDocumentComparison)(editor, original, revised, {
|
|
@@ -6046,13 +6591,13 @@ function useDocumentCompare(editor, options) {
|
|
|
6046
6591
|
},
|
|
6047
6592
|
[editor]
|
|
6048
6593
|
);
|
|
6049
|
-
const clear = (0,
|
|
6050
|
-
return (0,
|
|
6594
|
+
const clear = (0, import_react45.useCallback)(() => setSummary(null), []);
|
|
6595
|
+
return (0, import_react45.useMemo)(() => ({ summary, compare, clear }), [summary, compare, clear]);
|
|
6051
6596
|
}
|
|
6052
6597
|
|
|
6053
6598
|
// src/review/TrackedChangesList.tsx
|
|
6054
6599
|
var import_editor15 = require("@pixerate/editor");
|
|
6055
|
-
var
|
|
6600
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
6056
6601
|
var buttonClass4 = "rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted disabled:opacity-40";
|
|
6057
6602
|
var TrackedChangesList = ({
|
|
6058
6603
|
editor,
|
|
@@ -6063,18 +6608,18 @@ var TrackedChangesList = ({
|
|
|
6063
6608
|
}) => {
|
|
6064
6609
|
const review = useTrackChanges(editor);
|
|
6065
6610
|
if (review.changes.length === 0) {
|
|
6066
|
-
return /* @__PURE__ */ (0,
|
|
6611
|
+
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
6612
|
}
|
|
6068
|
-
return /* @__PURE__ */ (0,
|
|
6613
|
+
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
6614
|
const active = change.id === review.currentChangeId;
|
|
6070
|
-
return /* @__PURE__ */ (0,
|
|
6615
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
6071
6616
|
"li",
|
|
6072
6617
|
{
|
|
6073
6618
|
className: active ? `${itemClassName} ${activeItemClassName}` : itemClassName,
|
|
6074
6619
|
"data-change-type": change.type,
|
|
6075
6620
|
"data-change-id": change.id,
|
|
6076
6621
|
children: [
|
|
6077
|
-
/* @__PURE__ */ (0,
|
|
6622
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
6078
6623
|
"button",
|
|
6079
6624
|
{
|
|
6080
6625
|
type: "button",
|
|
@@ -6082,14 +6627,14 @@ var TrackedChangesList = ({
|
|
|
6082
6627
|
title: `${change.author.name}: ${change.description}`,
|
|
6083
6628
|
onClick: () => review.select(change.id),
|
|
6084
6629
|
children: [
|
|
6085
|
-
/* @__PURE__ */ (0,
|
|
6630
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-medium", children: (0, import_editor15.trackedChangeLabel)(change) }),
|
|
6086
6631
|
change.author.name ? ` \xB7 ${change.author.name}` : "",
|
|
6087
|
-
/* @__PURE__ */ (0,
|
|
6632
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "block truncate text-muted-foreground", children: change.description })
|
|
6088
6633
|
]
|
|
6089
6634
|
}
|
|
6090
6635
|
),
|
|
6091
|
-
/* @__PURE__ */ (0,
|
|
6092
|
-
/* @__PURE__ */ (0,
|
|
6636
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.accept(change.id), children: "Accept" }),
|
|
6637
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.reject(change.id), children: "Reject" })
|
|
6093
6638
|
]
|
|
6094
6639
|
},
|
|
6095
6640
|
`${change.type}:${change.id}`
|
|
@@ -6098,12 +6643,12 @@ var TrackedChangesList = ({
|
|
|
6098
6643
|
};
|
|
6099
6644
|
|
|
6100
6645
|
// src/commands/useCommandPalette.ts
|
|
6101
|
-
var
|
|
6646
|
+
var import_react46 = require("react");
|
|
6102
6647
|
var import_commands2 = require("@pixerate/editor/commands");
|
|
6103
6648
|
function useCommandPalette(registry, options = {}) {
|
|
6104
|
-
const optionsRef = (0,
|
|
6649
|
+
const optionsRef = (0, import_react46.useRef)(options);
|
|
6105
6650
|
optionsRef.current = options;
|
|
6106
|
-
const controller = (0,
|
|
6651
|
+
const controller = (0, import_react46.useMemo)(
|
|
6107
6652
|
() => (0, import_commands2.createCommandPaletteController)(registry, {
|
|
6108
6653
|
context: () => {
|
|
6109
6654
|
const c = optionsRef.current.context;
|
|
@@ -6124,9 +6669,9 @@ function useCommandPalette(registry, options = {}) {
|
|
|
6124
6669
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
6125
6670
|
[registry]
|
|
6126
6671
|
);
|
|
6127
|
-
const state = (0,
|
|
6672
|
+
const state = (0, import_react46.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
|
|
6128
6673
|
const { hotkey, hotkeyTarget } = options;
|
|
6129
|
-
(0,
|
|
6674
|
+
(0, import_react46.useEffect)(() => {
|
|
6130
6675
|
if (!hotkey) return;
|
|
6131
6676
|
const target = hotkeyTarget ?? (typeof window !== "undefined" ? window : null);
|
|
6132
6677
|
if (!target) return;
|
|
@@ -6154,13 +6699,13 @@ function useCommandPalette(registry, options = {}) {
|
|
|
6154
6699
|
}
|
|
6155
6700
|
|
|
6156
6701
|
// src/commands/CommandPalette.tsx
|
|
6157
|
-
var
|
|
6158
|
-
var
|
|
6702
|
+
var import_react47 = __toESM(require("react"), 1);
|
|
6703
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
6159
6704
|
function HighlightedLabel({ item }) {
|
|
6160
|
-
if (item.labelIndices.length === 0) return /* @__PURE__ */ (0,
|
|
6705
|
+
if (item.labelIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, { children: item.label });
|
|
6161
6706
|
const marked = new Set(item.labelIndices);
|
|
6162
|
-
return /* @__PURE__ */ (0,
|
|
6163
|
-
(ch, i) => marked.has(i) ? /* @__PURE__ */ (0,
|
|
6707
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, { children: Array.from(item.label).map(
|
|
6708
|
+
(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
6709
|
) });
|
|
6165
6710
|
}
|
|
6166
6711
|
var CommandPalette = ({
|
|
@@ -6169,22 +6714,22 @@ var CommandPalette = ({
|
|
|
6169
6714
|
emptyMessage = "No matching commands",
|
|
6170
6715
|
className = ""
|
|
6171
6716
|
}) => {
|
|
6172
|
-
const inputRef = (0,
|
|
6173
|
-
const listRef = (0,
|
|
6174
|
-
const baseId = (0,
|
|
6717
|
+
const inputRef = (0, import_react47.useRef)(null);
|
|
6718
|
+
const listRef = (0, import_react47.useRef)(null);
|
|
6719
|
+
const baseId = (0, import_react47.useId)();
|
|
6175
6720
|
const listId = `${baseId}-list`;
|
|
6176
6721
|
const optionId = (index) => `${baseId}-option-${index}`;
|
|
6177
6722
|
const { open, query, items, activeIndex } = palette;
|
|
6178
|
-
(0,
|
|
6723
|
+
(0, import_react47.useEffect)(() => {
|
|
6179
6724
|
if (open) inputRef.current?.focus();
|
|
6180
6725
|
}, [open]);
|
|
6181
|
-
(0,
|
|
6726
|
+
(0, import_react47.useEffect)(() => {
|
|
6182
6727
|
if (!open) return;
|
|
6183
6728
|
const active = listRef.current?.querySelector('[aria-selected="true"]');
|
|
6184
6729
|
active?.scrollIntoView?.({ block: "nearest" });
|
|
6185
6730
|
}, [open, activeIndex]);
|
|
6186
6731
|
if (!open) return null;
|
|
6187
|
-
return /* @__PURE__ */ (0,
|
|
6732
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
6188
6733
|
"div",
|
|
6189
6734
|
{
|
|
6190
6735
|
className: "fixed inset-0 z-50 flex items-start justify-center bg-black/30 px-4 pt-[15vh]",
|
|
@@ -6192,7 +6737,7 @@ var CommandPalette = ({
|
|
|
6192
6737
|
onMouseDown: (e) => {
|
|
6193
6738
|
if (e.target === e.currentTarget) palette.setOpen(false);
|
|
6194
6739
|
},
|
|
6195
|
-
children: /* @__PURE__ */ (0,
|
|
6740
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
6196
6741
|
"div",
|
|
6197
6742
|
{
|
|
6198
6743
|
role: "dialog",
|
|
@@ -6201,7 +6746,7 @@ var CommandPalette = ({
|
|
|
6201
6746
|
className: `w-full max-w-lg overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-xl ${className}`,
|
|
6202
6747
|
style: { background: "var(--popover, var(--background, #fff))" },
|
|
6203
6748
|
children: [
|
|
6204
|
-
/* @__PURE__ */ (0,
|
|
6749
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
6205
6750
|
"input",
|
|
6206
6751
|
{
|
|
6207
6752
|
ref: inputRef,
|
|
@@ -6221,7 +6766,7 @@ var CommandPalette = ({
|
|
|
6221
6766
|
className: "w-full border-b border-border bg-transparent px-3 py-2 text-sm outline-none placeholder:text-muted-foreground"
|
|
6222
6767
|
}
|
|
6223
6768
|
),
|
|
6224
|
-
items.length === 0 ? /* @__PURE__ */ (0,
|
|
6769
|
+
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
6770
|
"li",
|
|
6226
6771
|
{
|
|
6227
6772
|
id: optionId(index),
|
|
@@ -6236,12 +6781,12 @@ var CommandPalette = ({
|
|
|
6236
6781
|
onClick: () => palette.run(item.id),
|
|
6237
6782
|
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
6783
|
children: [
|
|
6239
|
-
/* @__PURE__ */ (0,
|
|
6240
|
-
/* @__PURE__ */ (0,
|
|
6241
|
-
item.disabledReason && /* @__PURE__ */ (0,
|
|
6784
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
6785
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(HighlightedLabel, { item }),
|
|
6786
|
+
item.disabledReason && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "ml-2 text-xs text-muted-foreground", "data-disabled-reason": "", children: item.disabledReason })
|
|
6242
6787
|
] }),
|
|
6243
|
-
item.group && /* @__PURE__ */ (0,
|
|
6244
|
-
item.shortcut && /* @__PURE__ */ (0,
|
|
6788
|
+
item.group && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.group }),
|
|
6789
|
+
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
6790
|
]
|
|
6246
6791
|
},
|
|
6247
6792
|
item.id
|
|
@@ -6254,12 +6799,12 @@ var CommandPalette = ({
|
|
|
6254
6799
|
};
|
|
6255
6800
|
|
|
6256
6801
|
// src/commands/useCommandShortcuts.ts
|
|
6257
|
-
var
|
|
6802
|
+
var import_react48 = require("react");
|
|
6258
6803
|
function useCommandShortcuts(registry, options = {}) {
|
|
6259
|
-
const optionsRef = (0,
|
|
6804
|
+
const optionsRef = (0, import_react48.useRef)(options);
|
|
6260
6805
|
optionsRef.current = options;
|
|
6261
6806
|
const { enabled = true, target } = options;
|
|
6262
|
-
(0,
|
|
6807
|
+
(0, import_react48.useEffect)(() => {
|
|
6263
6808
|
if (!registry || !enabled) return;
|
|
6264
6809
|
const eventTarget = target ?? (typeof window !== "undefined" ? window : null);
|
|
6265
6810
|
if (!eventTarget) return;
|
|
@@ -6277,14 +6822,14 @@ function useCommandShortcuts(registry, options = {}) {
|
|
|
6277
6822
|
}, [registry, enabled, target]);
|
|
6278
6823
|
}
|
|
6279
6824
|
function useRegisterCommands(registry, specs) {
|
|
6280
|
-
(0,
|
|
6825
|
+
(0, import_react48.useEffect)(() => {
|
|
6281
6826
|
if (!registry || !specs || specs.length === 0) return;
|
|
6282
6827
|
return registry.register(specs);
|
|
6283
6828
|
}, [registry, specs]);
|
|
6284
6829
|
}
|
|
6285
6830
|
|
|
6286
6831
|
// src/persistence/useAutosave.ts
|
|
6287
|
-
var
|
|
6832
|
+
var import_react49 = require("react");
|
|
6288
6833
|
var import_persistence = require("@pixerate/editor/persistence");
|
|
6289
6834
|
var IDLE = {
|
|
6290
6835
|
status: "idle",
|
|
@@ -6295,18 +6840,18 @@ var IDLE = {
|
|
|
6295
6840
|
ready: false
|
|
6296
6841
|
};
|
|
6297
6842
|
function useAutosave(options) {
|
|
6298
|
-
const optionsRef = (0,
|
|
6843
|
+
const optionsRef = (0, import_react49.useRef)(options);
|
|
6299
6844
|
optionsRef.current = options;
|
|
6300
6845
|
const { storage, key, history, dirty } = options;
|
|
6301
6846
|
const recover = options.recover !== false;
|
|
6302
6847
|
const flushOnHide = options.flushOnHide !== false;
|
|
6303
6848
|
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,
|
|
6849
|
+
const [controller, setController] = (0, import_react49.useState)(null);
|
|
6850
|
+
const [status, setStatus] = (0, import_react49.useState)(IDLE);
|
|
6851
|
+
const [recovery, setRecovery] = (0, import_react49.useState)(null);
|
|
6852
|
+
const [pendingRecovery, setPendingRecovery] = (0, import_react49.useState)(recover);
|
|
6853
|
+
const revisionsRef = (0, import_react49.useRef)(null);
|
|
6854
|
+
(0, import_react49.useEffect)(() => {
|
|
6310
6855
|
const revisions = (0, import_persistence.createRevisionTracker)({ history, dirty });
|
|
6311
6856
|
const o = optionsRef.current;
|
|
6312
6857
|
const instance = (0, import_persistence.createAutosaveController)({
|
|
@@ -6349,10 +6894,10 @@ function useAutosave(options) {
|
|
|
6349
6894
|
if (revisionsRef.current === revisions) revisionsRef.current = null;
|
|
6350
6895
|
};
|
|
6351
6896
|
}, [storage, key, history, dirty, recover]);
|
|
6352
|
-
(0,
|
|
6897
|
+
(0, import_react49.useEffect)(() => {
|
|
6353
6898
|
if (controller && ready && !pendingRecovery) controller.ready();
|
|
6354
6899
|
}, [controller, ready, pendingRecovery]);
|
|
6355
|
-
(0,
|
|
6900
|
+
(0, import_react49.useEffect)(() => {
|
|
6356
6901
|
if (!controller || !flushOnHide || typeof window === "undefined") return;
|
|
6357
6902
|
const flush = () => void controller.flushNow();
|
|
6358
6903
|
const onVisibility = () => {
|
|
@@ -6365,31 +6910,31 @@ function useAutosave(options) {
|
|
|
6365
6910
|
document.removeEventListener("visibilitychange", onVisibility);
|
|
6366
6911
|
};
|
|
6367
6912
|
}, [controller, flushOnHide]);
|
|
6368
|
-
const restore = (0,
|
|
6913
|
+
const restore = (0, import_react49.useCallback)(() => {
|
|
6369
6914
|
const snapshot = recovery?.snapshot;
|
|
6370
6915
|
setRecovery(null);
|
|
6371
6916
|
setPendingRecovery(false);
|
|
6372
6917
|
return snapshot;
|
|
6373
6918
|
}, [recovery]);
|
|
6374
|
-
const discard = (0,
|
|
6919
|
+
const discard = (0, import_react49.useCallback)(async () => {
|
|
6375
6920
|
if (controller) await controller.discardRecovery();
|
|
6376
6921
|
setRecovery(null);
|
|
6377
6922
|
setPendingRecovery(false);
|
|
6378
6923
|
}, [controller]);
|
|
6379
|
-
const flushNow = (0,
|
|
6924
|
+
const flushNow = (0, import_react49.useCallback)(async () => {
|
|
6380
6925
|
await controller?.flushNow();
|
|
6381
6926
|
}, [controller]);
|
|
6382
|
-
const markClean = (0,
|
|
6927
|
+
const markClean = (0, import_react49.useCallback)(async () => {
|
|
6383
6928
|
revisionsRef.current?.markSaved();
|
|
6384
6929
|
await controller?.markClean();
|
|
6385
6930
|
}, [controller]);
|
|
6386
|
-
const notifyChange = (0,
|
|
6931
|
+
const notifyChange = (0, import_react49.useCallback)(() => revisionsRef.current?.bump(), []);
|
|
6387
6932
|
return { status, recovery, pendingRecovery, restore, discard, flushNow, markClean, notifyChange, controller };
|
|
6388
6933
|
}
|
|
6389
6934
|
|
|
6390
6935
|
// src/persistence/RecoveryPrompt.tsx
|
|
6391
6936
|
var import_persistence2 = require("@pixerate/editor/persistence");
|
|
6392
|
-
var
|
|
6937
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
6393
6938
|
var RecoveryPrompt = ({
|
|
6394
6939
|
recovery,
|
|
6395
6940
|
onRestore,
|
|
@@ -6401,7 +6946,7 @@ var RecoveryPrompt = ({
|
|
|
6401
6946
|
}) => {
|
|
6402
6947
|
if (!recovery) return null;
|
|
6403
6948
|
const { name } = recovery.meta;
|
|
6404
|
-
return /* @__PURE__ */ (0,
|
|
6949
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
6405
6950
|
"div",
|
|
6406
6951
|
{
|
|
6407
6952
|
role: "alertdialog",
|
|
@@ -6409,15 +6954,15 @@ var RecoveryPrompt = ({
|
|
|
6409
6954
|
"data-recovery-prompt": "",
|
|
6410
6955
|
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
6956
|
children: [
|
|
6412
|
-
/* @__PURE__ */ (0,
|
|
6957
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "min-w-0 flex-1", children: [
|
|
6413
6958
|
(0, import_persistence2.formatRecoveryMessage)(recovery.meta, formatTime),
|
|
6414
|
-
name ? /* @__PURE__ */ (0,
|
|
6959
|
+
name ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
|
|
6415
6960
|
"(",
|
|
6416
6961
|
name,
|
|
6417
6962
|
")"
|
|
6418
6963
|
] }) : null
|
|
6419
6964
|
] }),
|
|
6420
|
-
/* @__PURE__ */ (0,
|
|
6965
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6421
6966
|
"button",
|
|
6422
6967
|
{
|
|
6423
6968
|
type: "button",
|
|
@@ -6427,7 +6972,7 @@ var RecoveryPrompt = ({
|
|
|
6427
6972
|
children: restoreLabel
|
|
6428
6973
|
}
|
|
6429
6974
|
),
|
|
6430
|
-
/* @__PURE__ */ (0,
|
|
6975
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6431
6976
|
"button",
|
|
6432
6977
|
{
|
|
6433
6978
|
type: "button",
|
|
@@ -6443,17 +6988,17 @@ var RecoveryPrompt = ({
|
|
|
6443
6988
|
};
|
|
6444
6989
|
|
|
6445
6990
|
// src/generation/useGenerationPlan.ts
|
|
6446
|
-
var
|
|
6991
|
+
var import_react50 = require("react");
|
|
6447
6992
|
var import_generation = require("@pixerate/editor/generation");
|
|
6448
6993
|
function useGenerationPlan(request, capabilities, options = {}) {
|
|
6449
6994
|
const key = JSON.stringify([request, capabilities, options]);
|
|
6450
|
-
return (0,
|
|
6995
|
+
return (0, import_react50.useMemo)(() => (0, import_generation.planGenerationRequest)(request, capabilities, options), [key]);
|
|
6451
6996
|
}
|
|
6452
6997
|
function useJobProgress(options) {
|
|
6453
6998
|
const { startedAt, expectedMs, done, now, intervalMs = 1e3 } = options;
|
|
6454
|
-
const [tick, setTick] = (0,
|
|
6999
|
+
const [tick, setTick] = (0, import_react50.useState)(() => Date.now());
|
|
6455
7000
|
const ticking = !done && now === void 0;
|
|
6456
|
-
(0,
|
|
7001
|
+
(0, import_react50.useEffect)(() => {
|
|
6457
7002
|
if (!ticking) return;
|
|
6458
7003
|
setTick(Date.now());
|
|
6459
7004
|
const id = setInterval(() => setTick(Date.now()), Math.max(16, intervalMs));
|
|
@@ -6463,9 +7008,9 @@ function useJobProgress(options) {
|
|
|
6463
7008
|
}
|
|
6464
7009
|
|
|
6465
7010
|
// src/generation/GenerationSettings.tsx
|
|
6466
|
-
var
|
|
7011
|
+
var import_react51 = require("react");
|
|
6467
7012
|
var import_generation2 = require("@pixerate/editor/generation");
|
|
6468
|
-
var
|
|
7013
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
6469
7014
|
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
7015
|
function Control({
|
|
6471
7016
|
control,
|
|
@@ -6475,7 +7020,7 @@ function Control({
|
|
|
6475
7020
|
}) {
|
|
6476
7021
|
const shown = value ?? control.defaultValue;
|
|
6477
7022
|
if (control.kind === "checkbox") {
|
|
6478
|
-
return /* @__PURE__ */ (0,
|
|
7023
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6479
7024
|
"input",
|
|
6480
7025
|
{
|
|
6481
7026
|
id,
|
|
@@ -6487,7 +7032,7 @@ function Control({
|
|
|
6487
7032
|
);
|
|
6488
7033
|
}
|
|
6489
7034
|
if (control.kind === "select") {
|
|
6490
|
-
return /* @__PURE__ */ (0,
|
|
7035
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
6491
7036
|
"select",
|
|
6492
7037
|
{
|
|
6493
7038
|
id,
|
|
@@ -6496,14 +7041,14 @@ function Control({
|
|
|
6496
7041
|
value: shown === void 0 ? "" : String(shown),
|
|
6497
7042
|
onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value)),
|
|
6498
7043
|
children: [
|
|
6499
|
-
shown === void 0 && /* @__PURE__ */ (0,
|
|
6500
|
-
control.options.map((option) => /* @__PURE__ */ (0,
|
|
7044
|
+
shown === void 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: "", children: "Default" }),
|
|
7045
|
+
control.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: String(option.value), children: option.label }, String(option.value)))
|
|
6501
7046
|
]
|
|
6502
7047
|
}
|
|
6503
7048
|
);
|
|
6504
7049
|
}
|
|
6505
7050
|
if (control.kind === "textarea") {
|
|
6506
|
-
return /* @__PURE__ */ (0,
|
|
7051
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6507
7052
|
"textarea",
|
|
6508
7053
|
{
|
|
6509
7054
|
id,
|
|
@@ -6517,8 +7062,8 @@ function Control({
|
|
|
6517
7062
|
);
|
|
6518
7063
|
}
|
|
6519
7064
|
const numeric = typeof shown === "number" ? shown : void 0;
|
|
6520
|
-
return /* @__PURE__ */ (0,
|
|
6521
|
-
/* @__PURE__ */ (0,
|
|
7065
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
7066
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6522
7067
|
"input",
|
|
6523
7068
|
{
|
|
6524
7069
|
id,
|
|
@@ -6532,7 +7077,7 @@ function Control({
|
|
|
6532
7077
|
onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value))
|
|
6533
7078
|
}
|
|
6534
7079
|
),
|
|
6535
|
-
control.kind === "range" && /* @__PURE__ */ (0,
|
|
7080
|
+
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
7081
|
] });
|
|
6537
7082
|
}
|
|
6538
7083
|
var GenerationSettings = ({
|
|
@@ -6546,17 +7091,17 @@ var GenerationSettings = ({
|
|
|
6546
7091
|
renderReference,
|
|
6547
7092
|
className = ""
|
|
6548
7093
|
}) => {
|
|
6549
|
-
const baseId = (0,
|
|
6550
|
-
const controls = (0,
|
|
7094
|
+
const baseId = (0, import_react51.useId)();
|
|
7095
|
+
const controls = (0, import_react51.useMemo)(() => (0, import_generation2.getGenerationControls)(capabilities), [capabilities]);
|
|
6551
7096
|
const computed = useGenerationPlan(value, capabilities, { strategy });
|
|
6552
7097
|
const plan = planProp ?? computed;
|
|
6553
7098
|
const slots = (0, import_generation2.getReferenceSlots)(capabilities, value);
|
|
6554
|
-
return /* @__PURE__ */ (0,
|
|
7099
|
+
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
7100
|
controls.map((control) => {
|
|
6556
7101
|
const id = `${baseId}-${control.key}`;
|
|
6557
|
-
return /* @__PURE__ */ (0,
|
|
6558
|
-
/* @__PURE__ */ (0,
|
|
6559
|
-
/* @__PURE__ */ (0,
|
|
7102
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-1", "data-control": control.key, children: [
|
|
7103
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("label", { htmlFor: id, className: "text-xs font-medium text-muted-foreground", title: control.description, children: control.label }),
|
|
7104
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6560
7105
|
Control,
|
|
6561
7106
|
{
|
|
6562
7107
|
control,
|
|
@@ -6567,23 +7112,23 @@ var GenerationSettings = ({
|
|
|
6567
7112
|
)
|
|
6568
7113
|
] }, control.key);
|
|
6569
7114
|
}),
|
|
6570
|
-
slots.map((slot) => /* @__PURE__ */ (0,
|
|
6571
|
-
/* @__PURE__ */ (0,
|
|
7115
|
+
slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("fieldset", { className: "flex flex-col gap-1", "data-reference-role": slot.role, children: [
|
|
7116
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("legend", { className: "text-xs font-medium text-muted-foreground", title: slot.description, children: [
|
|
6572
7117
|
slot.label,
|
|
6573
7118
|
" ",
|
|
6574
|
-
/* @__PURE__ */ (0,
|
|
7119
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "tabular-nums", "data-reference-count": "", children: [
|
|
6575
7120
|
"(",
|
|
6576
7121
|
slot.references.length,
|
|
6577
7122
|
"/",
|
|
6578
7123
|
slot.max,
|
|
6579
7124
|
")"
|
|
6580
7125
|
] }),
|
|
6581
|
-
slot.min > 0 && /* @__PURE__ */ (0,
|
|
7126
|
+
slot.min > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-destructive", children: " *" })
|
|
6582
7127
|
] }),
|
|
6583
|
-
/* @__PURE__ */ (0,
|
|
6584
|
-
slot.references.map((ref) => /* @__PURE__ */ (0,
|
|
6585
|
-
renderReference ? renderReference(ref) : /* @__PURE__ */ (0,
|
|
6586
|
-
/* @__PURE__ */ (0,
|
|
7128
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("ul", { className: "flex flex-wrap gap-1", children: [
|
|
7129
|
+
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: [
|
|
7130
|
+
renderReference ? renderReference(ref) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "max-w-[10rem] truncate", children: ref.id }),
|
|
7131
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6587
7132
|
"button",
|
|
6588
7133
|
{
|
|
6589
7134
|
type: "button",
|
|
@@ -6594,7 +7139,7 @@ var GenerationSettings = ({
|
|
|
6594
7139
|
}
|
|
6595
7140
|
)
|
|
6596
7141
|
] }, ref.id)),
|
|
6597
|
-
onAddReference && slot.canAdd && /* @__PURE__ */ (0,
|
|
7142
|
+
onAddReference && slot.canAdd && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6598
7143
|
"button",
|
|
6599
7144
|
{
|
|
6600
7145
|
type: "button",
|
|
@@ -6605,21 +7150,21 @@ var GenerationSettings = ({
|
|
|
6605
7150
|
) })
|
|
6606
7151
|
] })
|
|
6607
7152
|
] }, slot.role)),
|
|
6608
|
-
showAdjustments && plan.adjustments.length > 0 && /* @__PURE__ */ (0,
|
|
6609
|
-
showAdjustments && plan.errors.length > 0 && /* @__PURE__ */ (0,
|
|
7153
|
+
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)) }),
|
|
7154
|
+
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
7155
|
] });
|
|
6611
7156
|
};
|
|
6612
7157
|
|
|
6613
7158
|
// src/generation/JobProgress.tsx
|
|
6614
|
-
var
|
|
7159
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
6615
7160
|
var JobProgress = ({ title, className = "", ...options }) => {
|
|
6616
7161
|
const progress = useJobProgress(options);
|
|
6617
|
-
return /* @__PURE__ */ (0,
|
|
6618
|
-
/* @__PURE__ */ (0,
|
|
6619
|
-
title && /* @__PURE__ */ (0,
|
|
6620
|
-
/* @__PURE__ */ (0,
|
|
7162
|
+
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: [
|
|
7163
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between gap-2 text-muted-foreground", children: [
|
|
7164
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "truncate text-foreground", children: title }),
|
|
7165
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { "data-job-progress-label": "", "aria-live": "polite", children: progress.label })
|
|
6621
7166
|
] }),
|
|
6622
|
-
/* @__PURE__ */ (0,
|
|
7167
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
6623
7168
|
"div",
|
|
6624
7169
|
{
|
|
6625
7170
|
role: "progressbar",
|
|
@@ -6629,7 +7174,7 @@ var JobProgress = ({ title, className = "", ...options }) => {
|
|
|
6629
7174
|
"aria-valuenow": progress.percent,
|
|
6630
7175
|
"aria-valuetext": `${progress.percent}%, ${progress.label}`,
|
|
6631
7176
|
className: "h-1.5 w-full overflow-hidden rounded-full bg-muted",
|
|
6632
|
-
children: /* @__PURE__ */ (0,
|
|
7177
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
6633
7178
|
"div",
|
|
6634
7179
|
{
|
|
6635
7180
|
className: "h-full rounded-full bg-primary transition-[width] duration-500",
|
|
@@ -6642,9 +7187,9 @@ var JobProgress = ({ title, className = "", ...options }) => {
|
|
|
6642
7187
|
};
|
|
6643
7188
|
|
|
6644
7189
|
// src/generation/AssetMentionChips.tsx
|
|
6645
|
-
var
|
|
7190
|
+
var import_react52 = require("react");
|
|
6646
7191
|
var import_generation3 = require("@pixerate/editor/generation");
|
|
6647
|
-
var
|
|
7192
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
6648
7193
|
var AssetMentionChips = ({
|
|
6649
7194
|
content,
|
|
6650
7195
|
onChange,
|
|
@@ -6654,14 +7199,14 @@ var AssetMentionChips = ({
|
|
|
6654
7199
|
renderAsset,
|
|
6655
7200
|
className = ""
|
|
6656
7201
|
}) => {
|
|
6657
|
-
const [open, setOpen] = (0,
|
|
6658
|
-
const rootRef = (0,
|
|
6659
|
-
const chips = (0,
|
|
7202
|
+
const [open, setOpen] = (0, import_react52.useState)(null);
|
|
7203
|
+
const rootRef = (0, import_react52.useRef)(null);
|
|
7204
|
+
const chips = (0, import_react52.useMemo)(
|
|
6660
7205
|
() => (0, import_generation3.describeAssetMentions)((0, import_generation3.findTextMentions)(content), assets, capabilities),
|
|
6661
7206
|
[content, assets, capabilities]
|
|
6662
7207
|
);
|
|
6663
7208
|
const options = roles ?? (capabilities ? (0, import_generation3.getAssetRoleOptions)(capabilities) : (0, import_generation3.defaultAssetRoleOptions)());
|
|
6664
|
-
(0,
|
|
7209
|
+
(0, import_react52.useEffect)(() => {
|
|
6665
7210
|
if (open === null) return;
|
|
6666
7211
|
const onPointer = (event) => {
|
|
6667
7212
|
if (!rootRef.current?.contains(event.target)) setOpen(null);
|
|
@@ -6669,19 +7214,19 @@ var AssetMentionChips = ({
|
|
|
6669
7214
|
document.addEventListener("mousedown", onPointer);
|
|
6670
7215
|
return () => document.removeEventListener("mousedown", onPointer);
|
|
6671
7216
|
}, [open]);
|
|
6672
|
-
const pick = (
|
|
7217
|
+
const pick = (chip2, role) => {
|
|
6673
7218
|
setOpen(null);
|
|
6674
|
-
if (
|
|
6675
|
-
onChange((0, import_generation3.setMentionRoleInText)(content,
|
|
7219
|
+
if (chip2.start === void 0) return;
|
|
7220
|
+
onChange((0, import_generation3.setMentionRoleInText)(content, chip2.start, role));
|
|
6676
7221
|
};
|
|
6677
7222
|
if (chips.length === 0) return null;
|
|
6678
|
-
return /* @__PURE__ */ (0,
|
|
6679
|
-
const error =
|
|
6680
|
-
const warning =
|
|
7223
|
+
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) => {
|
|
7224
|
+
const error = chip2.issues.find((issue) => issue.severity === "error");
|
|
7225
|
+
const warning = chip2.issues.find((issue) => issue.severity === "warning");
|
|
6681
7226
|
const problem = error ?? warning;
|
|
6682
|
-
const isOpen = open ===
|
|
6683
|
-
return /* @__PURE__ */ (0,
|
|
6684
|
-
/* @__PURE__ */ (0,
|
|
7227
|
+
const isOpen = open === chip2.index;
|
|
7228
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "relative inline-flex", "data-asset-chip": chip2.asset.id, children: [
|
|
7229
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
6685
7230
|
"button",
|
|
6686
7231
|
{
|
|
6687
7232
|
type: "button",
|
|
@@ -6689,82 +7234,82 @@ var AssetMentionChips = ({
|
|
|
6689
7234
|
"aria-expanded": isOpen,
|
|
6690
7235
|
title: problem?.message,
|
|
6691
7236
|
"data-issue": problem?.code,
|
|
6692
|
-
onClick: () => setOpen(isOpen ? null :
|
|
7237
|
+
onClick: () => setOpen(isOpen ? null : chip2.index),
|
|
6693
7238
|
onKeyDown: (e) => {
|
|
6694
7239
|
if (e.key === "Escape") setOpen(null);
|
|
6695
7240
|
},
|
|
6696
7241
|
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
7242
|
children: [
|
|
6698
|
-
/* @__PURE__ */ (0,
|
|
6699
|
-
/* @__PURE__ */ (0,
|
|
7243
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { children: renderAsset ? renderAsset(chip2) : `@${chip2.asset.label ?? chip2.handle}` }),
|
|
7244
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
6700
7245
|
"span",
|
|
6701
7246
|
{
|
|
6702
|
-
className: `rounded px-1 text-[10px] uppercase tracking-wide ${
|
|
6703
|
-
"data-role-badge":
|
|
6704
|
-
children:
|
|
7247
|
+
className: `rounded px-1 text-[10px] uppercase tracking-wide ${chip2.role ? "bg-primary/15" : "opacity-60"}`,
|
|
7248
|
+
"data-role-badge": chip2.role ?? "",
|
|
7249
|
+
children: chip2.roleLabel ?? "No role"
|
|
6705
7250
|
}
|
|
6706
7251
|
)
|
|
6707
7252
|
]
|
|
6708
7253
|
}
|
|
6709
7254
|
),
|
|
6710
|
-
isOpen && /* @__PURE__ */ (0,
|
|
7255
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
6711
7256
|
"div",
|
|
6712
7257
|
{
|
|
6713
7258
|
role: "listbox",
|
|
6714
|
-
"aria-label": `Role for ${
|
|
7259
|
+
"aria-label": `Role for ${chip2.asset.label ?? chip2.handle}`,
|
|
6715
7260
|
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
7261
|
"data-role-picker": "",
|
|
6717
7262
|
onKeyDown: (e) => {
|
|
6718
7263
|
if (e.key === "Escape") setOpen(null);
|
|
6719
7264
|
},
|
|
6720
7265
|
children: [
|
|
6721
|
-
options.map((option) => /* @__PURE__ */ (0,
|
|
7266
|
+
options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
6722
7267
|
"button",
|
|
6723
7268
|
{
|
|
6724
7269
|
type: "button",
|
|
6725
7270
|
role: "option",
|
|
6726
|
-
"aria-selected":
|
|
7271
|
+
"aria-selected": chip2.role === option.role,
|
|
6727
7272
|
"data-role-option": option.role,
|
|
6728
7273
|
title: option.description,
|
|
6729
|
-
onClick: () => pick(
|
|
7274
|
+
onClick: () => pick(chip2, option.role),
|
|
6730
7275
|
className: "flex items-center justify-between gap-2 rounded px-2 py-1 text-left hover:bg-muted",
|
|
6731
7276
|
children: [
|
|
6732
|
-
/* @__PURE__ */ (0,
|
|
6733
|
-
option.accepts?.length ? /* @__PURE__ */ (0,
|
|
7277
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { children: option.label }),
|
|
7278
|
+
option.accepts?.length ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-[10px] opacity-60", children: option.accepts.join(", ") }) : null
|
|
6734
7279
|
]
|
|
6735
7280
|
},
|
|
6736
7281
|
option.role
|
|
6737
7282
|
)),
|
|
6738
|
-
/* @__PURE__ */ (0,
|
|
7283
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
6739
7284
|
"button",
|
|
6740
7285
|
{
|
|
6741
7286
|
type: "button",
|
|
6742
7287
|
role: "option",
|
|
6743
|
-
"aria-selected": !
|
|
7288
|
+
"aria-selected": !chip2.role,
|
|
6744
7289
|
"data-role-option": "",
|
|
6745
|
-
onClick: () => pick(
|
|
7290
|
+
onClick: () => pick(chip2, null),
|
|
6746
7291
|
className: "rounded px-2 py-1 text-left opacity-70 hover:bg-muted",
|
|
6747
7292
|
children: "No role"
|
|
6748
7293
|
}
|
|
6749
7294
|
),
|
|
6750
|
-
|
|
7295
|
+
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
7296
|
]
|
|
6752
7297
|
}
|
|
6753
7298
|
)
|
|
6754
|
-
] }, `${
|
|
7299
|
+
] }, `${chip2.start}-${chip2.index}`);
|
|
6755
7300
|
}) });
|
|
6756
7301
|
};
|
|
6757
7302
|
|
|
6758
7303
|
// src/generation/GenerationHistory.tsx
|
|
6759
|
-
var
|
|
7304
|
+
var import_react53 = require("react");
|
|
6760
7305
|
var import_generation4 = require("@pixerate/editor/generation");
|
|
6761
|
-
var
|
|
7306
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
6762
7307
|
function useGenerationRecords(store, filter) {
|
|
6763
|
-
const [records, setRecords] = (0,
|
|
6764
|
-
const [loading, setLoading] = (0,
|
|
6765
|
-
const [error, setError] = (0,
|
|
7308
|
+
const [records, setRecords] = (0, import_react53.useState)([]);
|
|
7309
|
+
const [loading, setLoading] = (0, import_react53.useState)(!!store);
|
|
7310
|
+
const [error, setError] = (0, import_react53.useState)(null);
|
|
6766
7311
|
const filterKey = (0, import_generation4.stableStringify)(filter ?? {});
|
|
6767
|
-
const refresh = (0,
|
|
7312
|
+
const refresh = (0, import_react53.useCallback)(async () => {
|
|
6768
7313
|
if (!store) {
|
|
6769
7314
|
setRecords([]);
|
|
6770
7315
|
setLoading(false);
|
|
@@ -6781,7 +7326,7 @@ function useGenerationRecords(store, filter) {
|
|
|
6781
7326
|
setLoading(false);
|
|
6782
7327
|
}
|
|
6783
7328
|
}, [store, filterKey]);
|
|
6784
|
-
(0,
|
|
7329
|
+
(0, import_react53.useEffect)(() => {
|
|
6785
7330
|
void refresh();
|
|
6786
7331
|
if (!store) return;
|
|
6787
7332
|
return store.subscribe(() => void refresh());
|
|
@@ -6807,21 +7352,21 @@ var GenerationHistory = ({
|
|
|
6807
7352
|
emptyText = "No generations yet.",
|
|
6808
7353
|
className = ""
|
|
6809
7354
|
}) => {
|
|
6810
|
-
const [innerMode, setInnerMode] = (0,
|
|
7355
|
+
const [innerMode, setInnerMode] = (0, import_react53.useState)("exact");
|
|
6811
7356
|
const mode = modeProp ?? innerMode;
|
|
6812
7357
|
const setMode = (next) => {
|
|
6813
7358
|
if (modeProp === void 0) setInnerMode(next);
|
|
6814
7359
|
onModeChange?.(next);
|
|
6815
7360
|
};
|
|
6816
|
-
const options = (0,
|
|
6817
|
-
const results = (0,
|
|
6818
|
-
const models = (0,
|
|
7361
|
+
const options = (0, import_react53.useMemo)(() => ({ templates, capabilities, assets, mode }), [templates, capabilities, assets, mode]);
|
|
7362
|
+
const results = (0, import_react53.useMemo)(() => records.map((record) => (0, import_generation4.recreateRequest)(record, options)), [records, options]);
|
|
7363
|
+
const models = (0, import_react53.useMemo)(
|
|
6819
7364
|
() => capabilities ? Array.isArray(capabilities) ? capabilities : [capabilities] : [],
|
|
6820
7365
|
[capabilities]
|
|
6821
7366
|
);
|
|
6822
|
-
return /* @__PURE__ */ (0,
|
|
6823
|
-
/* @__PURE__ */ (0,
|
|
6824
|
-
/* @__PURE__ */ (0,
|
|
7367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: `flex flex-col gap-2 text-sm ${className}`, "data-generation-history": "", children: [
|
|
7368
|
+
/* @__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: [
|
|
7369
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
6825
7370
|
"input",
|
|
6826
7371
|
{
|
|
6827
7372
|
type: "radio",
|
|
@@ -6834,34 +7379,34 @@ var GenerationHistory = ({
|
|
|
6834
7379
|
),
|
|
6835
7380
|
value === "exact" ? "Exact (recorded versions)" : "Latest templates & settings"
|
|
6836
7381
|
] }, value)) }),
|
|
6837
|
-
records.length === 0 && /* @__PURE__ */ (0,
|
|
6838
|
-
/* @__PURE__ */ (0,
|
|
7382
|
+
records.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyText }),
|
|
7383
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ul", { className: "flex flex-col gap-2", children: records.map((record, i) => {
|
|
6839
7384
|
const result = results[i];
|
|
6840
7385
|
const model = models.find((m) => m.id === record.provenance.modelId);
|
|
6841
7386
|
const blocked = !result.ok;
|
|
6842
|
-
return /* @__PURE__ */ (0,
|
|
7387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
6843
7388
|
"li",
|
|
6844
7389
|
{
|
|
6845
7390
|
className: "rounded-md border border-border p-2",
|
|
6846
7391
|
"data-record": record.id,
|
|
6847
7392
|
"data-drift": result.drift.length,
|
|
6848
7393
|
children: [
|
|
6849
|
-
/* @__PURE__ */ (0,
|
|
6850
|
-
/* @__PURE__ */ (0,
|
|
6851
|
-
/* @__PURE__ */ (0,
|
|
6852
|
-
record.kind !== "generate" && /* @__PURE__ */ (0,
|
|
7394
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 text-xs", children: [
|
|
7395
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "font-medium", children: model?.name ?? record.provenance.modelId }),
|
|
7396
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
7397
|
+
record.kind !== "generate" && /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { "data-kind": "", children: [
|
|
6853
7398
|
record.kind,
|
|
6854
7399
|
" \xB7 "
|
|
6855
7400
|
] }),
|
|
6856
|
-
/* @__PURE__ */ (0,
|
|
6857
|
-
record.seed !== void 0 && /* @__PURE__ */ (0,
|
|
7401
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("time", { dateTime: record.createdAt, children: record.createdAt.replace("T", " ").slice(0, 16) }),
|
|
7402
|
+
record.seed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
|
|
6858
7403
|
" \xB7 seed ",
|
|
6859
7404
|
record.seed
|
|
6860
7405
|
] })
|
|
6861
7406
|
] })
|
|
6862
7407
|
] }),
|
|
6863
|
-
/* @__PURE__ */ (0,
|
|
6864
|
-
record.assets.length > 0 && /* @__PURE__ */ (0,
|
|
7408
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "mt-1 line-clamp-3 break-words text-xs", "data-record-prompt": "", children: record.provenance.resolvedPrompt }),
|
|
7409
|
+
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
7410
|
"span",
|
|
6866
7411
|
{
|
|
6867
7412
|
className: "rounded-full bg-muted px-2 py-0.5 text-[10px]",
|
|
@@ -6875,16 +7420,16 @@ var GenerationHistory = ({
|
|
|
6875
7420
|
`${asset.role}:${asset.id}`
|
|
6876
7421
|
)) }),
|
|
6877
7422
|
renderPreview?.(record),
|
|
6878
|
-
result.drift.length > 0 && /* @__PURE__ */ (0,
|
|
6879
|
-
/* @__PURE__ */ (0,
|
|
7423
|
+
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: [
|
|
7424
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("strong", { children: [
|
|
6880
7425
|
import_generation4.DRIFT_TYPE_LABELS[item.type],
|
|
6881
7426
|
":"
|
|
6882
7427
|
] }),
|
|
6883
7428
|
" ",
|
|
6884
7429
|
item.message
|
|
6885
7430
|
] }, j)) }),
|
|
6886
|
-
/* @__PURE__ */ (0,
|
|
6887
|
-
onRecreate && /* @__PURE__ */ (0,
|
|
7431
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "mt-2 flex gap-2", children: [
|
|
7432
|
+
onRecreate && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
6888
7433
|
"button",
|
|
6889
7434
|
{
|
|
6890
7435
|
type: "button",
|
|
@@ -6896,7 +7441,7 @@ var GenerationHistory = ({
|
|
|
6896
7441
|
children: "Recreate"
|
|
6897
7442
|
}
|
|
6898
7443
|
),
|
|
6899
|
-
onVariation && /* @__PURE__ */ (0,
|
|
7444
|
+
onVariation && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
6900
7445
|
"button",
|
|
6901
7446
|
{
|
|
6902
7447
|
type: "button",
|
|
@@ -6906,7 +7451,7 @@ var GenerationHistory = ({
|
|
|
6906
7451
|
children: "Variation"
|
|
6907
7452
|
}
|
|
6908
7453
|
),
|
|
6909
|
-
onRemove && /* @__PURE__ */ (0,
|
|
7454
|
+
onRemove && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
6910
7455
|
"button",
|
|
6911
7456
|
{
|
|
6912
7457
|
type: "button",
|
|
@@ -6926,19 +7471,19 @@ var GenerationHistory = ({
|
|
|
6926
7471
|
};
|
|
6927
7472
|
|
|
6928
7473
|
// src/find-replace/useFindReplace.ts
|
|
6929
|
-
var
|
|
7474
|
+
var import_react54 = require("react");
|
|
6930
7475
|
var import_editor16 = require("@pixerate/editor");
|
|
6931
7476
|
var noopUnsubscribe2 = () => {
|
|
6932
7477
|
};
|
|
6933
7478
|
function useFindReplace(editor) {
|
|
6934
7479
|
const store = (0, import_editor16.getFindReplaceStore)(editor ?? null);
|
|
6935
|
-
const subscribe = (0,
|
|
7480
|
+
const subscribe = (0, import_react54.useCallback)(
|
|
6936
7481
|
(onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe2,
|
|
6937
7482
|
[store]
|
|
6938
7483
|
);
|
|
6939
7484
|
const getSnapshot = () => store?.getSnapshot() ?? import_editor16.EMPTY_FIND_REPLACE_SNAPSHOT;
|
|
6940
|
-
const snapshot = (0,
|
|
6941
|
-
return (0,
|
|
7485
|
+
const snapshot = (0, import_react54.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
7486
|
+
return (0, import_react54.useMemo)(() => {
|
|
6942
7487
|
const run = (fn) => {
|
|
6943
7488
|
if (editor && !editor.isDestroyed && store) fn(editor);
|
|
6944
7489
|
};
|
|
@@ -6962,9 +7507,9 @@ function useFindReplace(editor) {
|
|
|
6962
7507
|
}
|
|
6963
7508
|
|
|
6964
7509
|
// src/find-replace/FindReplaceBar.tsx
|
|
6965
|
-
var
|
|
7510
|
+
var import_react55 = require("react");
|
|
6966
7511
|
var import_editor17 = require("@pixerate/editor");
|
|
6967
|
-
var
|
|
7512
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
6968
7513
|
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
7514
|
var buttonClass5 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
|
|
6970
7515
|
var toggleClass = (on) => `${buttonClass5} font-mono ${on ? "bg-primary/10 text-primary" : "text-muted-foreground"}`;
|
|
@@ -6977,10 +7522,10 @@ var FindReplaceBar = ({
|
|
|
6977
7522
|
onClose
|
|
6978
7523
|
}) => {
|
|
6979
7524
|
const find = useFindReplace(editor);
|
|
6980
|
-
const findInput = (0,
|
|
6981
|
-
const [moreOpen, setMoreOpen] = (0,
|
|
7525
|
+
const findInput = (0, import_react55.useRef)(null);
|
|
7526
|
+
const [moreOpen, setMoreOpen] = (0, import_react55.useState)(false);
|
|
6982
7527
|
const visible = find.available && (alwaysOpen || find.open);
|
|
6983
|
-
(0,
|
|
7528
|
+
(0, import_react55.useEffect)(() => {
|
|
6984
7529
|
if (!visible || find.focusRequest === 0) return;
|
|
6985
7530
|
findInput.current?.focus();
|
|
6986
7531
|
findInput.current?.select();
|
|
@@ -7018,9 +7563,9 @@ var FindReplaceBar = ({
|
|
|
7018
7563
|
if (isMod(e)) find.replaceAll();
|
|
7019
7564
|
else find.replace();
|
|
7020
7565
|
};
|
|
7021
|
-
return /* @__PURE__ */ (0,
|
|
7022
|
-
/* @__PURE__ */ (0,
|
|
7023
|
-
/* @__PURE__ */ (0,
|
|
7566
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
|
|
7567
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
7568
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7024
7569
|
"button",
|
|
7025
7570
|
{
|
|
7026
7571
|
type: "button",
|
|
@@ -7031,7 +7576,7 @@ var FindReplaceBar = ({
|
|
|
7031
7576
|
children: showReplace ? "\u25BE" : "\u25B8"
|
|
7032
7577
|
}
|
|
7033
7578
|
),
|
|
7034
|
-
/* @__PURE__ */ (0,
|
|
7579
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7035
7580
|
"input",
|
|
7036
7581
|
{
|
|
7037
7582
|
ref: findInput,
|
|
@@ -7045,7 +7590,7 @@ var FindReplaceBar = ({
|
|
|
7045
7590
|
onKeyDown: onFindKeyDown
|
|
7046
7591
|
}
|
|
7047
7592
|
),
|
|
7048
|
-
import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0,
|
|
7593
|
+
import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7049
7594
|
"button",
|
|
7050
7595
|
{
|
|
7051
7596
|
type: "button",
|
|
@@ -7058,7 +7603,7 @@ var FindReplaceBar = ({
|
|
|
7058
7603
|
},
|
|
7059
7604
|
t.key
|
|
7060
7605
|
)),
|
|
7061
|
-
/* @__PURE__ */ (0,
|
|
7606
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7062
7607
|
"span",
|
|
7063
7608
|
{
|
|
7064
7609
|
className: `min-w-[5rem] px-1 text-center text-xs ${find.error ? "text-destructive" : "text-muted-foreground"}`,
|
|
@@ -7068,9 +7613,9 @@ var FindReplaceBar = ({
|
|
|
7068
7613
|
children: status
|
|
7069
7614
|
}
|
|
7070
7615
|
),
|
|
7071
|
-
/* @__PURE__ */ (0,
|
|
7072
|
-
/* @__PURE__ */ (0,
|
|
7073
|
-
showMoreOptions && /* @__PURE__ */ (0,
|
|
7616
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
|
|
7617
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
|
|
7618
|
+
showMoreOptions && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7074
7619
|
"button",
|
|
7075
7620
|
{
|
|
7076
7621
|
type: "button",
|
|
@@ -7081,10 +7626,10 @@ var FindReplaceBar = ({
|
|
|
7081
7626
|
children: "\u2026"
|
|
7082
7627
|
}
|
|
7083
7628
|
),
|
|
7084
|
-
/* @__PURE__ */ (0,
|
|
7629
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Close find", onClick: close, children: "\xD7" })
|
|
7085
7630
|
] }),
|
|
7086
|
-
showReplace && /* @__PURE__ */ (0,
|
|
7087
|
-
/* @__PURE__ */ (0,
|
|
7631
|
+
showReplace && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-1 pl-7", children: [
|
|
7632
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7088
7633
|
"input",
|
|
7089
7634
|
{
|
|
7090
7635
|
type: "text",
|
|
@@ -7096,7 +7641,7 @@ var FindReplaceBar = ({
|
|
|
7096
7641
|
onKeyDown: onReplaceKeyDown
|
|
7097
7642
|
}
|
|
7098
7643
|
),
|
|
7099
|
-
/* @__PURE__ */ (0,
|
|
7644
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7100
7645
|
"button",
|
|
7101
7646
|
{
|
|
7102
7647
|
type: "button",
|
|
@@ -7106,11 +7651,11 @@ var FindReplaceBar = ({
|
|
|
7106
7651
|
children: "Replace"
|
|
7107
7652
|
}
|
|
7108
7653
|
),
|
|
7109
|
-
/* @__PURE__ */ (0,
|
|
7110
|
-
find.lastReplaceCount !== null && /* @__PURE__ */ (0,
|
|
7654
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass5, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
|
|
7655
|
+
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
7656
|
] }),
|
|
7112
|
-
showMoreOptions && moreOpen && /* @__PURE__ */ (0,
|
|
7113
|
-
/* @__PURE__ */ (0,
|
|
7657
|
+
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: [
|
|
7658
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7114
7659
|
"input",
|
|
7115
7660
|
{
|
|
7116
7661
|
type: "checkbox",
|
|
@@ -7124,12 +7669,12 @@ var FindReplaceBar = ({
|
|
|
7124
7669
|
};
|
|
7125
7670
|
|
|
7126
7671
|
// src/tables/useTableMenu.ts
|
|
7127
|
-
var
|
|
7672
|
+
var import_react56 = require("react");
|
|
7128
7673
|
var import_editor18 = require("@pixerate/editor");
|
|
7129
7674
|
function useTableMenu(editor) {
|
|
7130
|
-
const store = (0,
|
|
7131
|
-
const snapshot = (0,
|
|
7132
|
-
return (0,
|
|
7675
|
+
const store = (0, import_react56.useMemo)(() => (0, import_editor18.createTableStore)(editor), [editor]);
|
|
7676
|
+
const snapshot = (0, import_react56.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
7677
|
+
return (0, import_react56.useMemo)(
|
|
7133
7678
|
() => ({
|
|
7134
7679
|
...snapshot,
|
|
7135
7680
|
run: (action, params) => (0, import_editor18.runTableAction)(editor, action, params, { focus: true }),
|
|
@@ -7140,9 +7685,9 @@ function useTableMenu(editor) {
|
|
|
7140
7685
|
}
|
|
7141
7686
|
|
|
7142
7687
|
// src/tables/TableToolbar.tsx
|
|
7143
|
-
var
|
|
7688
|
+
var import_react57 = __toESM(require("react"), 1);
|
|
7144
7689
|
var import_editor19 = require("@pixerate/editor");
|
|
7145
|
-
var
|
|
7690
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
7146
7691
|
var keepSelection2 = (event) => event.preventDefault();
|
|
7147
7692
|
var TableToolbar = ({
|
|
7148
7693
|
editor,
|
|
@@ -7156,14 +7701,14 @@ var TableToolbar = ({
|
|
|
7156
7701
|
}) => {
|
|
7157
7702
|
const table = useTableMenu(editor);
|
|
7158
7703
|
if (!editor || !table.inTable && !showWhenOutside) return null;
|
|
7159
|
-
return /* @__PURE__ */ (0,
|
|
7704
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
|
|
7160
7705
|
const status = table.check(item.action, item.params);
|
|
7161
7706
|
const enabled = status === true;
|
|
7162
7707
|
const active = item.active?.(table);
|
|
7163
7708
|
const separator = index > 0 && items[index - 1].group !== item.group;
|
|
7164
|
-
return /* @__PURE__ */ (0,
|
|
7165
|
-
separator && /* @__PURE__ */ (0,
|
|
7166
|
-
/* @__PURE__ */ (0,
|
|
7709
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_react57.default.Fragment, { children: [
|
|
7710
|
+
separator && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: separatorClassName, "aria-hidden": "true" }),
|
|
7711
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
7167
7712
|
"button",
|
|
7168
7713
|
{
|
|
7169
7714
|
type: "button",
|
|
@@ -7185,8 +7730,8 @@ var TableToolbar = ({
|
|
|
7185
7730
|
};
|
|
7186
7731
|
|
|
7187
7732
|
// src/tables/InsertTableGrid.tsx
|
|
7188
|
-
var
|
|
7189
|
-
var
|
|
7733
|
+
var import_react58 = require("react");
|
|
7734
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
7190
7735
|
var keepSelection3 = (event) => event.preventDefault();
|
|
7191
7736
|
var InsertTableGrid = ({
|
|
7192
7737
|
editor,
|
|
@@ -7199,14 +7744,14 @@ var InsertTableGrid = ({
|
|
|
7199
7744
|
onInsert
|
|
7200
7745
|
}) => {
|
|
7201
7746
|
const table = useTableMenu(editor);
|
|
7202
|
-
const [hover, setHover] = (0,
|
|
7747
|
+
const [hover, setHover] = (0, import_react58.useState)(null);
|
|
7203
7748
|
const status = table.actions.insertTable;
|
|
7204
7749
|
const disabled = !editor || !status.enabled;
|
|
7205
7750
|
const insert = (size) => {
|
|
7206
7751
|
if (table.run("insertTable", { ...size, withHeaderRow })) onInsert?.(size);
|
|
7207
7752
|
setHover(null);
|
|
7208
7753
|
};
|
|
7209
|
-
return /* @__PURE__ */ (0,
|
|
7754
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
7210
7755
|
"div",
|
|
7211
7756
|
{
|
|
7212
7757
|
className,
|
|
@@ -7216,7 +7761,7 @@ var InsertTableGrid = ({
|
|
|
7216
7761
|
"data-insert-table-grid": "",
|
|
7217
7762
|
onMouseLeave: () => setHover(null),
|
|
7218
7763
|
children: [
|
|
7219
|
-
/* @__PURE__ */ (0,
|
|
7764
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
7220
7765
|
"div",
|
|
7221
7766
|
{
|
|
7222
7767
|
role: "grid",
|
|
@@ -7225,7 +7770,7 @@ var InsertTableGrid = ({
|
|
|
7225
7770
|
children: Array.from({ length: rows * cols }, (_, i) => {
|
|
7226
7771
|
const size = { rows: Math.floor(i / cols) + 1, cols: i % cols + 1 };
|
|
7227
7772
|
const active = !!hover && size.rows <= hover.rows && size.cols <= hover.cols;
|
|
7228
|
-
return /* @__PURE__ */ (0,
|
|
7773
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
7229
7774
|
"button",
|
|
7230
7775
|
{
|
|
7231
7776
|
type: "button",
|
|
@@ -7245,7 +7790,7 @@ var InsertTableGrid = ({
|
|
|
7245
7790
|
})
|
|
7246
7791
|
}
|
|
7247
7792
|
),
|
|
7248
|
-
/* @__PURE__ */ (0,
|
|
7793
|
+
/* @__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
7794
|
]
|
|
7250
7795
|
}
|
|
7251
7796
|
);
|
|
@@ -7253,31 +7798,31 @@ var InsertTableGrid = ({
|
|
|
7253
7798
|
|
|
7254
7799
|
// src/tables/TableBubbleMenu.tsx
|
|
7255
7800
|
var import_editor20 = require("@pixerate/editor");
|
|
7256
|
-
var
|
|
7801
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
7257
7802
|
var TableBubbleMenu = ({
|
|
7258
7803
|
editor,
|
|
7259
7804
|
children,
|
|
7260
7805
|
toolbarProps,
|
|
7261
7806
|
pluginKey = "tableBubbleMenu",
|
|
7262
7807
|
...rest
|
|
7263
|
-
}) => /* @__PURE__ */ (0,
|
|
7808
|
+
}) => /* @__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
7809
|
|
|
7265
7810
|
// src/chart-node/ChartNodeView.tsx
|
|
7266
7811
|
var import_client = require("react-dom/client");
|
|
7267
7812
|
|
|
7268
7813
|
// src/chart/ChartCanvas.tsx
|
|
7269
|
-
var
|
|
7814
|
+
var import_react60 = require("react");
|
|
7270
7815
|
var import_chart2 = require("@pixerate/editor/chart");
|
|
7271
7816
|
|
|
7272
7817
|
// src/chart/useChartEditor.ts
|
|
7273
|
-
var
|
|
7818
|
+
var import_react59 = require("react");
|
|
7274
7819
|
var import_chart = require("@pixerate/editor/chart");
|
|
7275
7820
|
function useChartState(controller) {
|
|
7276
|
-
return (0,
|
|
7821
|
+
return (0, import_react59.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
|
|
7277
7822
|
}
|
|
7278
7823
|
|
|
7279
7824
|
// src/chart/ChartCanvas.tsx
|
|
7280
|
-
var
|
|
7825
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
7281
7826
|
function renderChartMark(mark, fontFamily, interactive) {
|
|
7282
7827
|
const common = {
|
|
7283
7828
|
"data-role": mark.role,
|
|
@@ -7289,9 +7834,9 @@ function renderChartMark(mark, fontFamily, interactive) {
|
|
|
7289
7834
|
};
|
|
7290
7835
|
switch (mark.kind) {
|
|
7291
7836
|
case "rect":
|
|
7292
|
-
return /* @__PURE__ */ (0,
|
|
7837
|
+
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
7838
|
case "path":
|
|
7294
|
-
return /* @__PURE__ */ (0,
|
|
7839
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
7295
7840
|
"path",
|
|
7296
7841
|
{
|
|
7297
7842
|
...common,
|
|
@@ -7304,11 +7849,11 @@ function renderChartMark(mark, fontFamily, interactive) {
|
|
|
7304
7849
|
mark.key
|
|
7305
7850
|
);
|
|
7306
7851
|
case "circle":
|
|
7307
|
-
return /* @__PURE__ */ (0,
|
|
7852
|
+
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
7853
|
case "line":
|
|
7309
|
-
return /* @__PURE__ */ (0,
|
|
7854
|
+
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
7855
|
case "text":
|
|
7311
|
-
return /* @__PURE__ */ (0,
|
|
7856
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
7312
7857
|
"text",
|
|
7313
7858
|
{
|
|
7314
7859
|
...common,
|
|
@@ -7325,23 +7870,23 @@ function renderChartMark(mark, fontFamily, interactive) {
|
|
|
7325
7870
|
}
|
|
7326
7871
|
}
|
|
7327
7872
|
function ChartPresenceLayer({ presence }) {
|
|
7328
|
-
const { actors } = (0,
|
|
7329
|
-
return /* @__PURE__ */ (0,
|
|
7330
|
-
/* @__PURE__ */ (0,
|
|
7331
|
-
/* @__PURE__ */ (0,
|
|
7332
|
-
/* @__PURE__ */ (0,
|
|
7333
|
-
/* @__PURE__ */ (0,
|
|
7873
|
+
const { actors } = (0, import_react60.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
|
|
7874
|
+
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: [
|
|
7875
|
+
/* @__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 }),
|
|
7876
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("g", { transform: "translate(13 16)", children: [
|
|
7877
|
+
/* @__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 } }),
|
|
7878
|
+
/* @__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
7879
|
] })
|
|
7335
7880
|
] }, a.id)) });
|
|
7336
7881
|
}
|
|
7337
7882
|
function ChartCanvas({ controller, width = 640, height = 400, responsive = true, theme, editable = true, measureText, emptyMessage, className, presence, sceneRef }) {
|
|
7338
7883
|
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,
|
|
7884
|
+
const wrapper = (0, import_react60.useRef)(null);
|
|
7885
|
+
const svg = (0, import_react60.useRef)(null);
|
|
7886
|
+
const drag = (0, import_react60.useRef)(null);
|
|
7887
|
+
const [measured, setMeasured] = (0, import_react60.useState)(null);
|
|
7888
|
+
const [frozen, setFrozen] = (0, import_react60.useState)(null);
|
|
7889
|
+
(0, import_react60.useEffect)(() => {
|
|
7345
7890
|
const el = wrapper.current;
|
|
7346
7891
|
if (!responsive || !el || typeof ResizeObserver === "undefined") return;
|
|
7347
7892
|
const observer = new ResizeObserver(([entry]) => {
|
|
@@ -7352,8 +7897,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
|
|
|
7352
7897
|
return () => observer.disconnect();
|
|
7353
7898
|
}, [responsive]);
|
|
7354
7899
|
const sceneWidth = responsive && measured || width;
|
|
7355
|
-
const fullTheme = (0,
|
|
7356
|
-
const scene = (0,
|
|
7900
|
+
const fullTheme = (0, import_react60.useMemo)(() => ({ ...import_chart2.CSS_VARIABLE_CHART_THEME, ...theme }), [theme]);
|
|
7901
|
+
const scene = (0, import_react60.useMemo)(
|
|
7357
7902
|
() => (0, import_chart2.layoutChart)(state.spec, {
|
|
7358
7903
|
width: sceneWidth,
|
|
7359
7904
|
height,
|
|
@@ -7369,8 +7914,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
|
|
|
7369
7914
|
[state.spec, state.selection, sceneWidth, height, fullTheme, editable, measureText, emptyMessage, frozen]
|
|
7370
7915
|
);
|
|
7371
7916
|
if (sceneRef) sceneRef.current = scene;
|
|
7372
|
-
const byKey = (0,
|
|
7373
|
-
(0,
|
|
7917
|
+
const byKey = (0, import_react60.useMemo)(() => new Map(scene.marks.map((m) => [m.key, m])), [scene]);
|
|
7918
|
+
(0, import_react60.useEffect)(() => () => drag.current?.end(), []);
|
|
7374
7919
|
const scenePoint = (e) => (0, import_chart2.chartClientToScene)(scene, svg.current.getBoundingClientRect(), e.clientX, e.clientY);
|
|
7375
7920
|
const onPointerDown = (e) => {
|
|
7376
7921
|
if (!editable || e.button !== 0) return;
|
|
@@ -7403,7 +7948,7 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
|
|
|
7403
7948
|
if (editable && (0, import_chart2.handleChartKey)(controller, scene, e)) e.preventDefault();
|
|
7404
7949
|
};
|
|
7405
7950
|
const label = state.spec.title || "Chart";
|
|
7406
|
-
return /* @__PURE__ */ (0,
|
|
7951
|
+
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
7952
|
"svg",
|
|
7408
7953
|
{
|
|
7409
7954
|
ref: svg,
|
|
@@ -7421,14 +7966,14 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
|
|
|
7421
7966
|
onKeyDown,
|
|
7422
7967
|
children: [
|
|
7423
7968
|
scene.marks.map((m) => renderChartMark(m, scene.theme.fontFamily, editable)),
|
|
7424
|
-
presence && /* @__PURE__ */ (0,
|
|
7969
|
+
presence && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ChartPresenceLayer, { presence })
|
|
7425
7970
|
]
|
|
7426
7971
|
}
|
|
7427
7972
|
) });
|
|
7428
7973
|
}
|
|
7429
7974
|
|
|
7430
7975
|
// src/chart/ChartDataGrid.tsx
|
|
7431
|
-
var
|
|
7976
|
+
var import_react61 = require("react");
|
|
7432
7977
|
var import_chart3 = require("@pixerate/editor/chart");
|
|
7433
7978
|
|
|
7434
7979
|
// src/chart/styles.ts
|
|
@@ -7441,11 +7986,11 @@ var chartSectionClass = "space-y-2 border-b border-border pb-3 last:border-b-0";
|
|
|
7441
7986
|
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
7987
|
|
|
7443
7988
|
// src/chart/ChartDataGrid.tsx
|
|
7444
|
-
var
|
|
7989
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
7445
7990
|
function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
|
|
7446
|
-
const [draft, setDraft] = (0,
|
|
7447
|
-
const typing = (0,
|
|
7448
|
-
(0,
|
|
7991
|
+
const [draft, setDraft] = (0, import_react61.useState)(value);
|
|
7992
|
+
const typing = (0, import_react61.useRef)(false);
|
|
7993
|
+
(0, import_react61.useEffect)(() => {
|
|
7449
7994
|
if (!typing.current) setDraft(value);
|
|
7450
7995
|
}, [value]);
|
|
7451
7996
|
const commit = () => {
|
|
@@ -7454,7 +7999,7 @@ function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
|
|
|
7454
7999
|
if (draft === value) return;
|
|
7455
8000
|
if (onCommit(draft) === false) setDraft(value);
|
|
7456
8001
|
};
|
|
7457
|
-
return /* @__PURE__ */ (0,
|
|
8002
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
7458
8003
|
"input",
|
|
7459
8004
|
{
|
|
7460
8005
|
...rest,
|
|
@@ -7489,15 +8034,15 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
7489
8034
|
e.preventDefault();
|
|
7490
8035
|
controller.pasteCells(row, column, text);
|
|
7491
8036
|
};
|
|
7492
|
-
return /* @__PURE__ */ (0,
|
|
7493
|
-
/* @__PURE__ */ (0,
|
|
7494
|
-
/* @__PURE__ */ (0,
|
|
7495
|
-
/* @__PURE__ */ (0,
|
|
8037
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: `overflow-auto rounded-md border border-border ${className ?? ""}`, "data-chart-grid": "", children: [
|
|
8038
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("table", { className: "w-full border-collapse text-xs", children: [
|
|
8039
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("thead", { className: "bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("tr", { children: [
|
|
8040
|
+
/* @__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
8041
|
spec.series.map((s, si) => {
|
|
7497
8042
|
const color = (0, import_chart3.chartSeriesColor)(spec, si);
|
|
7498
8043
|
const selected = selection?.kind === "series" && selection.seriesId === s.id;
|
|
7499
|
-
return /* @__PURE__ */ (0,
|
|
7500
|
-
/* @__PURE__ */ (0,
|
|
8044
|
+
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: [
|
|
8045
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
7501
8046
|
"input",
|
|
7502
8047
|
{
|
|
7503
8048
|
type: "color",
|
|
@@ -7510,7 +8055,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
7510
8055
|
className: "h-5 w-5 shrink-0 cursor-pointer rounded border-0 bg-transparent p-0"
|
|
7511
8056
|
}
|
|
7512
8057
|
),
|
|
7513
|
-
/* @__PURE__ */ (0,
|
|
8058
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
7514
8059
|
ChartCommitInput,
|
|
7515
8060
|
{
|
|
7516
8061
|
value: s.name,
|
|
@@ -7520,8 +8065,8 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
7520
8065
|
className: `${chartInputClass} h-6 min-w-[5rem] border-transparent bg-transparent font-medium ${s.hidden ? "text-muted-foreground line-through" : ""}`
|
|
7521
8066
|
}
|
|
7522
8067
|
),
|
|
7523
|
-
!readOnly && /* @__PURE__ */ (0,
|
|
7524
|
-
/* @__PURE__ */ (0,
|
|
8068
|
+
!readOnly && /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_jsx_runtime41.Fragment, { children: [
|
|
8069
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
7525
8070
|
"button",
|
|
7526
8071
|
{
|
|
7527
8072
|
type: "button",
|
|
@@ -7534,16 +8079,16 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
7534
8079
|
children: s.hidden ? "\u25CB" : "\u25CF"
|
|
7535
8080
|
}
|
|
7536
8081
|
),
|
|
7537
|
-
/* @__PURE__ */ (0,
|
|
8082
|
+
/* @__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
8083
|
] })
|
|
7539
8084
|
] }) }, s.id);
|
|
7540
8085
|
}),
|
|
7541
|
-
!readOnly && /* @__PURE__ */ (0,
|
|
8086
|
+
!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
8087
|
] }) }),
|
|
7543
|
-
/* @__PURE__ */ (0,
|
|
8088
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("tbody", { children: spec.categories.map((category, i) => {
|
|
7544
8089
|
const rowSelected = selection?.kind === "category" && selection.index === i;
|
|
7545
|
-
return /* @__PURE__ */ (0,
|
|
7546
|
-
/* @__PURE__ */ (0,
|
|
8090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("tr", { "data-category-index": i, className: rowSelected ? "bg-primary/10" : void 0, children: [
|
|
8091
|
+
/* @__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
8092
|
ChartCommitInput,
|
|
7548
8093
|
{
|
|
7549
8094
|
value: category,
|
|
@@ -7557,7 +8102,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
7557
8102
|
spec.series.map((s) => {
|
|
7558
8103
|
const value = s.values[i];
|
|
7559
8104
|
const selected = selection?.kind === "point" && selection.seriesId === s.id && selection.index === i;
|
|
7560
|
-
return /* @__PURE__ */ (0,
|
|
8105
|
+
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
8106
|
ChartCommitInput,
|
|
7562
8107
|
{
|
|
7563
8108
|
value: value === null || value === void 0 ? "" : String(value),
|
|
@@ -7572,38 +8117,38 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
7572
8117
|
}
|
|
7573
8118
|
) }, s.id);
|
|
7574
8119
|
}),
|
|
7575
|
-
!readOnly && /* @__PURE__ */ (0,
|
|
8120
|
+
!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
8121
|
] }, i);
|
|
7577
8122
|
}) })
|
|
7578
8123
|
] }),
|
|
7579
|
-
!readOnly && /* @__PURE__ */ (0,
|
|
8124
|
+
!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
8125
|
] });
|
|
7581
8126
|
}
|
|
7582
8127
|
|
|
7583
8128
|
// src/chart/ChartInspector.tsx
|
|
7584
|
-
var
|
|
8129
|
+
var import_react62 = require("react");
|
|
7585
8130
|
var import_chart4 = require("@pixerate/editor/chart");
|
|
7586
|
-
var
|
|
8131
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
7587
8132
|
var cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
7588
8133
|
function Field({ label, htmlFor, children }) {
|
|
7589
|
-
return /* @__PURE__ */ (0,
|
|
7590
|
-
/* @__PURE__ */ (0,
|
|
7591
|
-
/* @__PURE__ */ (0,
|
|
8134
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
8135
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("label", { htmlFor, className: `${chartLabelClass} w-20 shrink-0`, children: label }),
|
|
8136
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "min-w-0 flex-1", children })
|
|
7592
8137
|
] });
|
|
7593
8138
|
}
|
|
7594
8139
|
function Toggle({ label, checked, onChange, name }) {
|
|
7595
|
-
return /* @__PURE__ */ (0,
|
|
7596
|
-
/* @__PURE__ */ (0,
|
|
8140
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("label", { className: "flex cursor-pointer items-center gap-2 text-xs text-foreground", children: [
|
|
8141
|
+
/* @__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
8142
|
label
|
|
7598
8143
|
] });
|
|
7599
8144
|
}
|
|
7600
8145
|
function Select({ id, value, options, onChange, name, labels }) {
|
|
7601
|
-
return /* @__PURE__ */ (0,
|
|
8146
|
+
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
8147
|
}
|
|
7603
8148
|
function AxisSection({ controller, axis, value, idBase, horizontal, numeric = false, scales = false }) {
|
|
7604
8149
|
const set = (patch) => controller.setAxis(axis, patch);
|
|
7605
8150
|
const setFormat = (patch) => set({ format: { ...value.format, ...patch } });
|
|
7606
|
-
const bound = (key2) => /* @__PURE__ */ (0,
|
|
8151
|
+
const bound = (key2) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7607
8152
|
ChartCommitInput,
|
|
7608
8153
|
{
|
|
7609
8154
|
id: `${idBase}-${axis}-${key2}`,
|
|
@@ -7618,26 +8163,26 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
|
|
|
7618
8163
|
const name = axis === "x" ? numeric ? "X axis" : "Category axis" : axis === "y" ? "Value axis" : "Secondary axis";
|
|
7619
8164
|
const valueAxis = axis !== "x" || numeric;
|
|
7620
8165
|
const key = axis === "y2" ? "yAxis2" : `${axis}Axis`;
|
|
7621
|
-
return /* @__PURE__ */ (0,
|
|
7622
|
-
/* @__PURE__ */ (0,
|
|
7623
|
-
/* @__PURE__ */ (0,
|
|
8166
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": `axis-${axis}`, children: [
|
|
8167
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
8168
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("h4", { className: "text-xs font-semibold text-foreground", children: [
|
|
7624
8169
|
name,
|
|
7625
|
-
/* @__PURE__ */ (0,
|
|
8170
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "ml-1 font-normal text-muted-foreground", children: [
|
|
7626
8171
|
"(",
|
|
7627
8172
|
axis === "x" ? horizontal ? "left" : "bottom" : axis === "y2" ? horizontal ? "top" : "right" : horizontal ? "bottom" : "left",
|
|
7628
8173
|
")"
|
|
7629
8174
|
] })
|
|
7630
8175
|
] }),
|
|
7631
|
-
/* @__PURE__ */ (0,
|
|
8176
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Show", name: `${axis}Axis.show`, checked: value.show, onChange: (show) => set({ show }) })
|
|
7632
8177
|
] }),
|
|
7633
|
-
/* @__PURE__ */ (0,
|
|
7634
|
-
/* @__PURE__ */ (0,
|
|
7635
|
-
/* @__PURE__ */ (0,
|
|
7636
|
-
axis === "x" && !numeric && /* @__PURE__ */ (0,
|
|
7637
|
-
scales && /* @__PURE__ */ (0,
|
|
7638
|
-
scales && valueAxis && /* @__PURE__ */ (0,
|
|
8178
|
+
/* @__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 }) }) }),
|
|
8179
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
|
|
8180
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Grid lines", name: `${key}.gridlines`, checked: value.gridlines, onChange: (gridlines) => set({ gridlines }) }),
|
|
8181
|
+
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 }) }),
|
|
8182
|
+
scales && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Reverse", name: `${key}.reverse`, checked: !!value.reverse, onChange: (reverse) => set({ reverse }) }),
|
|
8183
|
+
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
8184
|
] }),
|
|
7640
|
-
scales && valueAxis && value.scale === "log" && /* @__PURE__ */ (0,
|
|
8185
|
+
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
8186
|
ChartCommitInput,
|
|
7642
8187
|
{
|
|
7643
8188
|
id: `${idBase}-${axis}-log-base`,
|
|
@@ -7648,7 +8193,7 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
|
|
|
7648
8193
|
onCommit: (text) => set({ logBase: text.trim() === "" ? void 0 : Number(text) }).ok
|
|
7649
8194
|
}
|
|
7650
8195
|
) }),
|
|
7651
|
-
valueAxis && value.scale !== "log" && /* @__PURE__ */ (0,
|
|
8196
|
+
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
8197
|
ChartCommitInput,
|
|
7653
8198
|
{
|
|
7654
8199
|
id: `${idBase}-${axis}-step`,
|
|
@@ -7660,14 +8205,14 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
|
|
|
7660
8205
|
onCommit: (text) => set({ step: text.trim() === "" ? null : Number(text) }).ok
|
|
7661
8206
|
}
|
|
7662
8207
|
) }),
|
|
7663
|
-
valueAxis && /* @__PURE__ */ (0,
|
|
7664
|
-
/* @__PURE__ */ (0,
|
|
8208
|
+
valueAxis && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
|
|
8209
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Min / max", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex gap-1", children: [
|
|
7665
8210
|
bound("min"),
|
|
7666
8211
|
bound("max")
|
|
7667
8212
|
] }) }),
|
|
7668
|
-
/* @__PURE__ */ (0,
|
|
7669
|
-
/* @__PURE__ */ (0,
|
|
7670
|
-
/* @__PURE__ */ (0,
|
|
8213
|
+
/* @__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: [
|
|
8214
|
+
/* @__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 }) }),
|
|
8215
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7671
8216
|
ChartCommitInput,
|
|
7672
8217
|
{
|
|
7673
8218
|
value: value.format.decimals === void 0 ? "" : String(value.format.decimals),
|
|
@@ -7686,8 +8231,8 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
|
|
|
7686
8231
|
}
|
|
7687
8232
|
)
|
|
7688
8233
|
] }) }),
|
|
7689
|
-
value.format.style === "currency" && /* @__PURE__ */ (0,
|
|
7690
|
-
/* @__PURE__ */ (0,
|
|
8234
|
+
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() }) }) }),
|
|
8235
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Code", htmlFor: `${idBase}-${axis}-code`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7691
8236
|
ChartCommitInput,
|
|
7692
8237
|
{
|
|
7693
8238
|
id: `${idBase}-${axis}-code`,
|
|
@@ -7713,15 +8258,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
|
|
|
7713
8258
|
const values = which === "xErrorBars" ? series.x ?? [] : series.values;
|
|
7714
8259
|
const set = (next) => controller.updateSeries(series.id, { [which]: next });
|
|
7715
8260
|
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,
|
|
8261
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "space-y-1.5", "data-section": which === "errorBars" ? "error-bars" : "x-error-bars", children: [
|
|
8262
|
+
/* @__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: [
|
|
8263
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "None" }),
|
|
8264
|
+
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
8265
|
] }) }),
|
|
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,
|
|
8266
|
+
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 }) }),
|
|
8267
|
+
bars?.type === "custom" && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
|
|
8268
|
+
/* @__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 }) }),
|
|
8269
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Minus", htmlFor: `${id}-minus`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7725
8270
|
ChartCommitInput,
|
|
7726
8271
|
{
|
|
7727
8272
|
id: `${id}-minus`,
|
|
@@ -7738,15 +8283,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
|
|
|
7738
8283
|
}
|
|
7739
8284
|
) })
|
|
7740
8285
|
] }),
|
|
7741
|
-
bars && /* @__PURE__ */ (0,
|
|
7742
|
-
/* @__PURE__ */ (0,
|
|
7743
|
-
/* @__PURE__ */ (0,
|
|
8286
|
+
bars && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
8287
|
+
/* @__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)) }),
|
|
8288
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Caps", name: `${key}.cap`, checked: bars.cap !== false, onChange: (cap2) => patch({ cap: cap2 }) })
|
|
7744
8289
|
] })
|
|
7745
8290
|
] });
|
|
7746
8291
|
}
|
|
7747
8292
|
function ChartInspector({ controller, sections, className }) {
|
|
7748
8293
|
const { spec, selectedSeries } = useChartState(controller);
|
|
7749
|
-
const idBase = (0,
|
|
8294
|
+
const idBase = (0, import_react62.useId)();
|
|
7750
8295
|
const show = (section) => !sections || sections.includes(section);
|
|
7751
8296
|
const cartesian = (0, import_chart4.isCartesianChart)(spec.type);
|
|
7752
8297
|
const family = (0, import_chart4.chartFamily)(spec);
|
|
@@ -7758,29 +8303,29 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7758
8303
|
const hasLines = cartesian && types.some((t) => t === "line" || t === "area");
|
|
7759
8304
|
const seriesIndex = selectedSeries ? spec.series.findIndex((s) => s.id === selectedSeries.id) : -1;
|
|
7760
8305
|
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,
|
|
8306
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: `space-y-3 text-xs ${className ?? ""}`, "data-chart-inspector": "", children: [
|
|
8307
|
+
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)) }) }),
|
|
8308
|
+
show("style") && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "style", children: [
|
|
8309
|
+
/* @__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: [
|
|
8310
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Quick layout\u2026" }),
|
|
8311
|
+
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
8312
|
] }) }),
|
|
7768
|
-
/* @__PURE__ */ (0,
|
|
7769
|
-
/* @__PURE__ */ (0,
|
|
7770
|
-
import_chart4.CHART_COLOR_SCHEMES.map((c) => /* @__PURE__ */ (0,
|
|
8313
|
+
/* @__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: [
|
|
8314
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Custom" }),
|
|
8315
|
+
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
8316
|
] }) }),
|
|
7772
|
-
!colorCheck.ok && /* @__PURE__ */ (0,
|
|
7773
|
-
/* @__PURE__ */ (0,
|
|
8317
|
+
!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] }),
|
|
8318
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "transpose", onClick: () => controller.transpose(), children: "Switch rows and columns" })
|
|
7774
8319
|
] }),
|
|
7775
|
-
show("titles") && /* @__PURE__ */ (0,
|
|
7776
|
-
/* @__PURE__ */ (0,
|
|
7777
|
-
/* @__PURE__ */ (0,
|
|
8320
|
+
show("titles") && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "titles", children: [
|
|
8321
|
+
/* @__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) }) }),
|
|
8322
|
+
/* @__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
8323
|
] }),
|
|
7779
|
-
show("options") && /* @__PURE__ */ (0,
|
|
7780
|
-
cartesian && /* @__PURE__ */ (0,
|
|
7781
|
-
hasBars && /* @__PURE__ */ (0,
|
|
7782
|
-
hasLines && /* @__PURE__ */ (0,
|
|
7783
|
-
spec.type === "donut" && /* @__PURE__ */ (0,
|
|
8324
|
+
show("options") && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "options", children: [
|
|
8325
|
+
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 }) }) }),
|
|
8326
|
+
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)) }) }),
|
|
8327
|
+
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 }) }) }),
|
|
8328
|
+
spec.type === "donut" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Hole", htmlFor: `${idBase}-hole`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7784
8329
|
"input",
|
|
7785
8330
|
{
|
|
7786
8331
|
id: `${idBase}-hole`,
|
|
@@ -7796,7 +8341,7 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7796
8341
|
onChange: (e) => controller.update({ innerRadius: Number(e.currentTarget.value) })
|
|
7797
8342
|
}
|
|
7798
8343
|
) }),
|
|
7799
|
-
hasBars && /* @__PURE__ */ (0,
|
|
8344
|
+
hasBars && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Spacing", htmlFor: `${idBase}-gap`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7800
8345
|
"input",
|
|
7801
8346
|
{
|
|
7802
8347
|
id: `${idBase}-gap`,
|
|
@@ -7812,31 +8357,31 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7812
8357
|
onChange: (e) => controller.update({ gapWidth: Number(e.currentTarget.value) })
|
|
7813
8358
|
}
|
|
7814
8359
|
) }),
|
|
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,
|
|
8360
|
+
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 }) }) }),
|
|
8361
|
+
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 }) }),
|
|
8362
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
|
|
8363
|
+
spec.type === "waterfall" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Total bar", name: "showTotal", checked: spec.showTotal, onChange: (showTotal) => controller.update({ showTotal }) }),
|
|
8364
|
+
hasLines && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Points", name: "points", checked: spec.points, onChange: (points) => controller.update({ points }) }),
|
|
8365
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Data labels", name: "dataLabels", checked: spec.dataLabels, onChange: (dataLabels) => controller.update({ dataLabels }) })
|
|
7821
8366
|
] })
|
|
7822
8367
|
] }),
|
|
7823
|
-
show("legend") && /* @__PURE__ */ (0,
|
|
7824
|
-
/* @__PURE__ */ (0,
|
|
7825
|
-
/* @__PURE__ */ (0,
|
|
7826
|
-
/* @__PURE__ */ (0,
|
|
8368
|
+
show("legend") && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "legend", children: [
|
|
8369
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
8370
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Legend" }),
|
|
8371
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Show", name: "legend.show", checked: spec.legend.show, onChange: (v) => controller.setLegend({ show: v }) })
|
|
7827
8372
|
] }),
|
|
7828
|
-
spec.legend.show && /* @__PURE__ */ (0,
|
|
8373
|
+
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
8374
|
] }),
|
|
7830
|
-
show("axes") && hasAxes && /* @__PURE__ */ (0,
|
|
7831
|
-
family !== "box" && family !== "histogram" && /* @__PURE__ */ (0,
|
|
7832
|
-
/* @__PURE__ */ (0,
|
|
7833
|
-
usesSecondary && /* @__PURE__ */ (0,
|
|
8375
|
+
show("axes") && hasAxes && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
|
|
8376
|
+
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 }),
|
|
8377
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(AxisSection, { controller, axis: "y", value: spec.yAxis, idBase, horizontal: spec.orientation === "horizontal", scales }),
|
|
8378
|
+
usesSecondary && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(AxisSection, { controller, axis: "y2", value: spec.yAxis2, idBase, horizontal: spec.orientation === "horizontal", scales })
|
|
7834
8379
|
] }),
|
|
7835
|
-
show("series") && selectedSeries && /* @__PURE__ */ (0,
|
|
7836
|
-
/* @__PURE__ */ (0,
|
|
7837
|
-
/* @__PURE__ */ (0,
|
|
7838
|
-
/* @__PURE__ */ (0,
|
|
7839
|
-
/* @__PURE__ */ (0,
|
|
8380
|
+
show("series") && selectedSeries && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "series", "data-series-id": selectedSeries.id, children: [
|
|
8381
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Series" }),
|
|
8382
|
+
/* @__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 }) }) }),
|
|
8383
|
+
/* @__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: [
|
|
8384
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7840
8385
|
"input",
|
|
7841
8386
|
{
|
|
7842
8387
|
id: `${idBase}-series-color`,
|
|
@@ -7849,9 +8394,9 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7849
8394
|
onChange: (e) => controller.updateSeries(selectedSeries.id, { color: e.currentTarget.value })
|
|
7850
8395
|
}
|
|
7851
8396
|
),
|
|
7852
|
-
selectedSeries.color && /* @__PURE__ */ (0,
|
|
8397
|
+
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
8398
|
] }) }),
|
|
7854
|
-
cartesian && /* @__PURE__ */ (0,
|
|
8399
|
+
cartesian && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Draw as", htmlFor: `${idBase}-series-type`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
7855
8400
|
"select",
|
|
7856
8401
|
{
|
|
7857
8402
|
id: `${idBase}-series-type`,
|
|
@@ -7860,12 +8405,12 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7860
8405
|
"data-option": "series.type",
|
|
7861
8406
|
onChange: (e) => controller.updateSeries(selectedSeries.id, { type: e.currentTarget.value || null }),
|
|
7862
8407
|
children: [
|
|
7863
|
-
/* @__PURE__ */ (0,
|
|
7864
|
-
import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0,
|
|
8408
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Chart type" }),
|
|
8409
|
+
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
8410
|
]
|
|
7866
8411
|
}
|
|
7867
8412
|
) }),
|
|
7868
|
-
(cartesian || family === "xy") && ["line", "area", "scatter"].includes((0, import_chart4.chartSeriesType)(spec, selectedSeries)) && /* @__PURE__ */ (0,
|
|
8413
|
+
(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
8414
|
"select",
|
|
7870
8415
|
{
|
|
7871
8416
|
id: `${idBase}-series-marker`,
|
|
@@ -7874,20 +8419,20 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7874
8419
|
"data-option": "series.marker",
|
|
7875
8420
|
onChange: (e) => controller.updateSeries(selectedSeries.id, { marker: e.currentTarget.value || null }),
|
|
7876
8421
|
children: [
|
|
7877
|
-
/* @__PURE__ */ (0,
|
|
7878
|
-
import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0,
|
|
8422
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Default" }),
|
|
8423
|
+
import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: m, children: cap(m) }, m))
|
|
7879
8424
|
]
|
|
7880
8425
|
}
|
|
7881
8426
|
) }),
|
|
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,
|
|
8427
|
+
scales && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "errorBars", idBase }),
|
|
8428
|
+
family === "xy" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "xErrorBars", idBase }),
|
|
8429
|
+
(0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "space-y-1", "data-section": "trendlines", children: [
|
|
8430
|
+
(selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-1", "data-trendline": i, children: [
|
|
8431
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "flex-1 truncate text-muted-foreground", children: (0, import_chart4.chartTrendlineName)(t, selectedSeries.name) }),
|
|
8432
|
+
/* @__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 }) }),
|
|
8433
|
+
/* @__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
8434
|
] }, i)),
|
|
7890
|
-
/* @__PURE__ */ (0,
|
|
8435
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
7891
8436
|
"select",
|
|
7892
8437
|
{
|
|
7893
8438
|
className: chartInputClass,
|
|
@@ -7896,32 +8441,32 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
7896
8441
|
"data-option": "trendline.add",
|
|
7897
8442
|
onChange: (e) => e.currentTarget.value && controller.addTrendline(selectedSeries.id, { type: e.currentTarget.value }),
|
|
7898
8443
|
children: [
|
|
7899
|
-
/* @__PURE__ */ (0,
|
|
7900
|
-
import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0,
|
|
8444
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Add trendline\u2026" }),
|
|
8445
|
+
import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: t, children: cap(t.replace("-", " ")) }, t))
|
|
7901
8446
|
]
|
|
7902
8447
|
}
|
|
7903
8448
|
)
|
|
7904
8449
|
] }),
|
|
7905
|
-
/* @__PURE__ */ (0,
|
|
7906
|
-
/* @__PURE__ */ (0,
|
|
7907
|
-
family === "cartesian" && /* @__PURE__ */ (0,
|
|
7908
|
-
/* @__PURE__ */ (0,
|
|
7909
|
-
/* @__PURE__ */ (0,
|
|
7910
|
-
/* @__PURE__ */ (0,
|
|
7911
|
-
/* @__PURE__ */ (0,
|
|
8450
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
8451
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Hidden", name: "series.hidden", checked: !!selectedSeries.hidden, onChange: (hidden) => controller.updateSeries(selectedSeries.id, { hidden }) }),
|
|
8452
|
+
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 }) }),
|
|
8453
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "flex-1" }),
|
|
8454
|
+
/* @__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" }),
|
|
8455
|
+
/* @__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" }),
|
|
8456
|
+
/* @__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
8457
|
] })
|
|
7913
8458
|
] })
|
|
7914
8459
|
] });
|
|
7915
8460
|
}
|
|
7916
8461
|
|
|
7917
8462
|
// src/chart-node/ChartNodeView.tsx
|
|
7918
|
-
var
|
|
8463
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
7919
8464
|
function ChartNodeView({ state, theme, showDataGrid = true }) {
|
|
7920
8465
|
const { controller, editing, editable, selected, width, height, setEditing } = state;
|
|
7921
8466
|
const open = () => {
|
|
7922
8467
|
if (editable && !editing) setEditing(true);
|
|
7923
8468
|
};
|
|
7924
|
-
return /* @__PURE__ */ (0,
|
|
8469
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
7925
8470
|
"div",
|
|
7926
8471
|
{
|
|
7927
8472
|
className: `not-prose my-2 rounded-md border bg-background p-1 ${selected ? "border-primary ring-1 ring-primary" : "border-border"}`,
|
|
@@ -7934,24 +8479,24 @@ function ChartNodeView({ state, theme, showDataGrid = true }) {
|
|
|
7934
8479
|
}
|
|
7935
8480
|
},
|
|
7936
8481
|
children: [
|
|
7937
|
-
editing && /* @__PURE__ */ (0,
|
|
7938
|
-
/* @__PURE__ */ (0,
|
|
7939
|
-
/* @__PURE__ */ (0,
|
|
8482
|
+
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: [
|
|
8483
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-xs text-muted-foreground", children: "Editing chart" }),
|
|
8484
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "done", onClick: () => setEditing(false), children: "Done" })
|
|
7940
8485
|
] }),
|
|
7941
|
-
/* @__PURE__ */ (0,
|
|
8486
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
7942
8487
|
"div",
|
|
7943
8488
|
{
|
|
7944
8489
|
className: editable && !editing ? "cursor-pointer" : void 0,
|
|
7945
8490
|
onClick: open,
|
|
7946
8491
|
title: editable && !editing ? "Click to edit the chart" : void 0,
|
|
7947
8492
|
"data-chart-node-canvas": "",
|
|
7948
|
-
children: /* @__PURE__ */ (0,
|
|
8493
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ChartCanvas, { controller, width: width ?? 640, height, responsive: width === null, editable: editing, theme })
|
|
7949
8494
|
}
|
|
7950
8495
|
),
|
|
7951
8496
|
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,
|
|
8497
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "mt-2 flex flex-wrap items-start gap-2", "data-chart-node-panel": "", children: [
|
|
8498
|
+
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 }) }),
|
|
8499
|
+
/* @__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
8500
|
] })
|
|
7956
8501
|
]
|
|
7957
8502
|
}
|
|
@@ -7969,7 +8514,7 @@ function createReactChartNodeView(options = {}) {
|
|
|
7969
8514
|
scheduled = true;
|
|
7970
8515
|
queueMicrotask(() => {
|
|
7971
8516
|
scheduled = false;
|
|
7972
|
-
if (!destroyed) root.render(/* @__PURE__ */ (0,
|
|
8517
|
+
if (!destroyed) root.render(/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Component, { ...props, state: latest }));
|
|
7973
8518
|
});
|
|
7974
8519
|
};
|
|
7975
8520
|
schedule();
|
|
@@ -7989,6 +8534,7 @@ function createReactChartNodeView(options = {}) {
|
|
|
7989
8534
|
0 && (module.exports = {
|
|
7990
8535
|
AdjustmentLayersPanel,
|
|
7991
8536
|
AssetMentionChips,
|
|
8537
|
+
BrushOptionsBar,
|
|
7992
8538
|
BubbleMenu,
|
|
7993
8539
|
ChartNodeView,
|
|
7994
8540
|
CommandPalette,
|
|
@@ -8009,6 +8555,7 @@ function createReactChartNodeView(options = {}) {
|
|
|
8009
8555
|
ImageEditor,
|
|
8010
8556
|
InsertTableGrid,
|
|
8011
8557
|
JobProgress,
|
|
8558
|
+
LayersPanel,
|
|
8012
8559
|
MergePreview,
|
|
8013
8560
|
NameManager,
|
|
8014
8561
|
OutlinePanel,
|