@pixerate/editor-react 0.63.0 → 0.65.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-QJSMW4CM.js → chunk-OSBDCFF4.js} +799 -382
- package/dist/chunk-OSBDCFF4.js.map +1 -0
- package/dist/image-editor/index.cjs +833 -417
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +31 -3
- package/dist/image-editor/index.d.ts +31 -3
- package/dist/image-editor/index.js +5 -1
- package/dist/index.cjs +1267 -851
- 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-QJSMW4CM.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -46,6 +46,7 @@ __export(src_exports, {
|
|
|
46
46
|
ExportDocxButton: () => ExportDocxButton,
|
|
47
47
|
FindReplaceBar: () => FindReplaceBar,
|
|
48
48
|
FormulaHints: () => FormulaHints,
|
|
49
|
+
FreeTransformOptionsBar: () => FreeTransformOptionsBar,
|
|
49
50
|
GenerationHistory: () => GenerationHistory,
|
|
50
51
|
GenerationSettings: () => GenerationSettings,
|
|
51
52
|
Histogram: () => Histogram,
|
|
@@ -53,6 +54,7 @@ __export(src_exports, {
|
|
|
53
54
|
ImageEditor: () => ImageEditor,
|
|
54
55
|
InsertTableGrid: () => InsertTableGrid,
|
|
55
56
|
JobProgress: () => JobProgress,
|
|
57
|
+
LayerEffectsPanel: () => LayerEffectsPanel,
|
|
56
58
|
LayersPanel: () => LayersPanel,
|
|
57
59
|
MergePreview: () => MergePreview,
|
|
58
60
|
NameManager: () => NameManager,
|
|
@@ -2003,17 +2005,17 @@ var SpreadsheetValidationDialog = ({ prompt, onResolve }) => {
|
|
|
2003
2005
|
style === "warning" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "mt-2", children: "Continue?" })
|
|
2004
2006
|
] })
|
|
2005
2007
|
] }),
|
|
2006
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-4 flex justify-end gap-2", children: buttons.map((
|
|
2008
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-4 flex justify-end gap-2", children: buttons.map((button3, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2007
2009
|
"button",
|
|
2008
2010
|
{
|
|
2009
2011
|
ref: i === 0 ? firstButton : void 0,
|
|
2010
2012
|
type: "button",
|
|
2011
|
-
"data-action":
|
|
2013
|
+
"data-action": button3.action,
|
|
2012
2014
|
className: `rounded border border-border px-3 py-1 ${i === 0 ? "bg-primary text-primary-foreground" : "hover:bg-muted"}`,
|
|
2013
|
-
onClick: () => onResolve(
|
|
2014
|
-
children:
|
|
2015
|
+
onClick: () => onResolve(button3.action),
|
|
2016
|
+
children: button3.label
|
|
2015
2017
|
},
|
|
2016
|
-
|
|
2018
|
+
button3.action
|
|
2017
2019
|
)) })
|
|
2018
2020
|
]
|
|
2019
2021
|
}
|
|
@@ -3783,8 +3785,8 @@ function useImageEditor(options = {}) {
|
|
|
3783
3785
|
}
|
|
3784
3786
|
|
|
3785
3787
|
// src/image-editor/ImageEditor.tsx
|
|
3786
|
-
var
|
|
3787
|
-
var
|
|
3788
|
+
var import_react44 = __toESM(require("react"), 1);
|
|
3789
|
+
var import_image_editor12 = require("@pixerate/editor/image-editor");
|
|
3788
3790
|
|
|
3789
3791
|
// src/image-editor/ControlSlider.tsx
|
|
3790
3792
|
var import_image_editor2 = require("@pixerate/editor/image-editor");
|
|
@@ -4216,9 +4218,198 @@ var AdjustmentLayersPanel = ({ controller, layers: layersProp, histogram }) => {
|
|
|
4216
4218
|
};
|
|
4217
4219
|
|
|
4218
4220
|
// src/image-editor/LayersPanel.tsx
|
|
4221
|
+
var import_react39 = require("react");
|
|
4222
|
+
|
|
4223
|
+
// src/image-editor/LayerEffectsPanel.tsx
|
|
4219
4224
|
var import_react38 = require("react");
|
|
4220
4225
|
var import_image_editor6 = require("@pixerate/editor/image-editor");
|
|
4221
4226
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
4227
|
+
var button = "px-1.5 py-0.5 rounded text-[10px] bg-slate-800 text-slate-300 hover:text-white disabled:opacity-40";
|
|
4228
|
+
var LayerEffectsPanel = ({ controller, layerId, className }) => {
|
|
4229
|
+
const [, setTick] = (0, import_react38.useState)(0);
|
|
4230
|
+
(0, import_react38.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
4231
|
+
const [open, setOpen] = (0, import_react38.useState)(null);
|
|
4232
|
+
const [error, setError] = (0, import_react38.useState)(null);
|
|
4233
|
+
const commitNext = (0, import_react38.useRef)(true);
|
|
4234
|
+
const layer = layerId ? controller.getLayer(layerId) : controller.getActiveLayer();
|
|
4235
|
+
const model = (0, import_image_editor6.layerEffectsPanel)(layer);
|
|
4236
|
+
const id = layer?.id;
|
|
4237
|
+
const attempt = (fn) => {
|
|
4238
|
+
try {
|
|
4239
|
+
setError(null);
|
|
4240
|
+
fn();
|
|
4241
|
+
} catch (err) {
|
|
4242
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4243
|
+
}
|
|
4244
|
+
};
|
|
4245
|
+
const sliderEvents = {
|
|
4246
|
+
onPointerDown: () => commitNext.current = true,
|
|
4247
|
+
onPointerUp: () => commitNext.current = true,
|
|
4248
|
+
onKeyDown: () => commitNext.current = true
|
|
4249
|
+
};
|
|
4250
|
+
if (!model.available || !id) {
|
|
4251
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: `text-xs text-slate-500 ${className ?? ""}`, "data-testid": "layer-effects", children: model.reason });
|
|
4252
|
+
}
|
|
4253
|
+
const effects = controller.getLayerEffects(id);
|
|
4254
|
+
const patterns = controller.getDocumentPatterns();
|
|
4255
|
+
const change = (effectId, control, value, drag = false) => attempt(() => {
|
|
4256
|
+
const effect = controller.getLayerEffects(id).items.find((e) => e.id === effectId);
|
|
4257
|
+
controller.updateLayerEffect(id, effectId, (0, import_image_editor6.effectControlChange)(effect, control.key, value, patterns), drag ? commitNext.current : true);
|
|
4258
|
+
if (drag) commitNext.current = false;
|
|
4259
|
+
});
|
|
4260
|
+
const renderControl = (effectId, c) => {
|
|
4261
|
+
const label = `${c.label}`;
|
|
4262
|
+
switch (c.type) {
|
|
4263
|
+
case "range": {
|
|
4264
|
+
const k = c.percent ? 100 : 1;
|
|
4265
|
+
const shown = Math.round(c.value * k * 100) / 100;
|
|
4266
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
|
|
4267
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-slate-400", children: [
|
|
4268
|
+
label,
|
|
4269
|
+
" ",
|
|
4270
|
+
shown,
|
|
4271
|
+
c.unit
|
|
4272
|
+
] }),
|
|
4273
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4274
|
+
"input",
|
|
4275
|
+
{
|
|
4276
|
+
type: "range",
|
|
4277
|
+
"aria-label": label,
|
|
4278
|
+
min: c.min * k,
|
|
4279
|
+
max: c.max * k,
|
|
4280
|
+
step: c.step * k,
|
|
4281
|
+
value: shown,
|
|
4282
|
+
disabled: model.readOnly,
|
|
4283
|
+
...sliderEvents,
|
|
4284
|
+
onChange: (e) => change(effectId, c, Number(e.target.value) / k, true),
|
|
4285
|
+
className: "accent-indigo-500"
|
|
4286
|
+
}
|
|
4287
|
+
)
|
|
4288
|
+
] }, c.key);
|
|
4289
|
+
}
|
|
4290
|
+
case "color":
|
|
4291
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
4292
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("input", { type: "color", "aria-label": label, value: c.value, disabled: model.readOnly, onChange: (e) => change(effectId, c, e.target.value) }),
|
|
4293
|
+
label
|
|
4294
|
+
] }, c.key);
|
|
4295
|
+
case "checkbox":
|
|
4296
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
4297
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("input", { type: "checkbox", "aria-label": label, checked: c.value, disabled: model.readOnly, onChange: (e) => change(effectId, c, e.target.checked), className: "accent-indigo-500" }),
|
|
4298
|
+
label
|
|
4299
|
+
] }, c.key);
|
|
4300
|
+
case "select":
|
|
4301
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
|
|
4302
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-slate-400", children: label }),
|
|
4303
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4304
|
+
"select",
|
|
4305
|
+
{
|
|
4306
|
+
"aria-label": label,
|
|
4307
|
+
value: c.value,
|
|
4308
|
+
disabled: model.readOnly,
|
|
4309
|
+
onChange: (e) => change(effectId, c, e.target.value),
|
|
4310
|
+
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
4311
|
+
children: c.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: o.value, children: o.label }, o.value))
|
|
4312
|
+
}
|
|
4313
|
+
)
|
|
4314
|
+
] }, c.key);
|
|
4315
|
+
}
|
|
4316
|
+
};
|
|
4317
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `flex flex-col gap-1.5 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "layer-effects", "aria-label": "Layer effects", role: "group", children: [
|
|
4318
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
4319
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "font-semibold text-slate-300", children: "fx Effects" }),
|
|
4320
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-1 text-slate-300", children: [
|
|
4321
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4322
|
+
"input",
|
|
4323
|
+
{
|
|
4324
|
+
type: "checkbox",
|
|
4325
|
+
"aria-label": "Effects on",
|
|
4326
|
+
checked: model.enabled,
|
|
4327
|
+
disabled: model.readOnly,
|
|
4328
|
+
onChange: (e) => attempt(() => controller.setLayerEffectsEnabled(id, e.target.checked)),
|
|
4329
|
+
className: "accent-indigo-500"
|
|
4330
|
+
}
|
|
4331
|
+
),
|
|
4332
|
+
"On"
|
|
4333
|
+
] }),
|
|
4334
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
|
|
4335
|
+
"Scale",
|
|
4336
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4337
|
+
"input",
|
|
4338
|
+
{
|
|
4339
|
+
type: "number",
|
|
4340
|
+
"aria-label": "Scale effects",
|
|
4341
|
+
min: 1,
|
|
4342
|
+
max: 1e3,
|
|
4343
|
+
step: 1,
|
|
4344
|
+
value: Math.round(model.scale * 100),
|
|
4345
|
+
disabled: model.readOnly,
|
|
4346
|
+
onChange: (e) => {
|
|
4347
|
+
const v = Number(e.target.value);
|
|
4348
|
+
if (v >= 1 && v <= 1e3) attempt(() => controller.setLayerEffectsEnabled(id, model.enabled, v / 100));
|
|
4349
|
+
},
|
|
4350
|
+
className: "w-14 bg-slate-800 border border-slate-700 rounded px-1"
|
|
4351
|
+
}
|
|
4352
|
+
),
|
|
4353
|
+
"%"
|
|
4354
|
+
] }),
|
|
4355
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4356
|
+
"select",
|
|
4357
|
+
{
|
|
4358
|
+
"aria-label": "Add effect",
|
|
4359
|
+
value: "",
|
|
4360
|
+
disabled: model.readOnly,
|
|
4361
|
+
onChange: (e) => {
|
|
4362
|
+
const kind = e.target.value;
|
|
4363
|
+
if (!kind) return;
|
|
4364
|
+
attempt(() => setOpen(controller.addLayerEffect(id, kind).effect.id));
|
|
4365
|
+
},
|
|
4366
|
+
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
4367
|
+
children: [
|
|
4368
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: "", children: "Add effect\u2026" }),
|
|
4369
|
+
import_image_editor6.LAYER_EFFECT_MENU.map((m) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: m.kind, children: m.label }, m.kind))
|
|
4370
|
+
]
|
|
4371
|
+
}
|
|
4372
|
+
)
|
|
4373
|
+
] }),
|
|
4374
|
+
model.readOnly && model.reason && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-slate-500", children: model.reason }),
|
|
4375
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("ul", { className: "flex flex-col gap-1", "aria-label": "Effects", children: model.rows.map((row) => {
|
|
4376
|
+
const effect = effects.items.find((e) => e.id === row.id);
|
|
4377
|
+
const expanded = open === row.id;
|
|
4378
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("li", { "data-effect-id": row.id, className: "rounded bg-slate-900/60 ring-1 ring-slate-800", children: [
|
|
4379
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5 px-1.5 py-1", children: [
|
|
4380
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4381
|
+
"input",
|
|
4382
|
+
{
|
|
4383
|
+
type: "checkbox",
|
|
4384
|
+
"aria-label": `${row.label} on`,
|
|
4385
|
+
checked: row.enabled,
|
|
4386
|
+
disabled: model.readOnly,
|
|
4387
|
+
onChange: (e) => attempt(() => controller.updateLayerEffect(id, row.id, { enabled: e.target.checked })),
|
|
4388
|
+
className: "accent-indigo-500"
|
|
4389
|
+
}
|
|
4390
|
+
),
|
|
4391
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4392
|
+
"button",
|
|
4393
|
+
{
|
|
4394
|
+
type: "button",
|
|
4395
|
+
"aria-expanded": expanded,
|
|
4396
|
+
className: `flex-1 text-left ${row.enabled && model.enabled ? "" : "text-slate-500"}`,
|
|
4397
|
+
onClick: () => setOpen(expanded ? null : row.id),
|
|
4398
|
+
children: row.label
|
|
4399
|
+
}
|
|
4400
|
+
),
|
|
4401
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: button, "aria-label": `Remove ${row.label}`, disabled: model.readOnly, onClick: () => attempt(() => controller.removeLayerEffect(id, row.id)), children: "\u2715" })
|
|
4402
|
+
] }),
|
|
4403
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1 px-1.5 pb-1.5", "data-testid": "effect-settings", children: (0, import_image_editor6.layerEffectControls)(effect, patterns).map((c) => renderControl(row.id, c)) })
|
|
4404
|
+
] }, row.id);
|
|
4405
|
+
}) }),
|
|
4406
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
|
|
4407
|
+
] });
|
|
4408
|
+
};
|
|
4409
|
+
|
|
4410
|
+
// src/image-editor/LayersPanel.tsx
|
|
4411
|
+
var import_image_editor7 = require("@pixerate/editor/image-editor");
|
|
4412
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
4222
4413
|
var iconButton = "px-1.5 py-0.5 rounded text-[10px] bg-slate-800 text-slate-300 hover:text-white disabled:opacity-40";
|
|
4223
4414
|
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
4415
|
var Thumbnail = ({
|
|
@@ -4229,8 +4420,8 @@ var Thumbnail = ({
|
|
|
4229
4420
|
selected,
|
|
4230
4421
|
testId
|
|
4231
4422
|
}) => {
|
|
4232
|
-
const ref = (0,
|
|
4233
|
-
(0,
|
|
4423
|
+
const ref = (0, import_react39.useRef)(null);
|
|
4424
|
+
(0, import_react39.useEffect)(() => {
|
|
4234
4425
|
const canvas = ref.current;
|
|
4235
4426
|
const ctx = canvas?.getContext("2d");
|
|
4236
4427
|
if (!canvas || !ctx || !pixels || typeof ctx.createImageData !== "function") return;
|
|
@@ -4240,7 +4431,7 @@ var Thumbnail = ({
|
|
|
4240
4431
|
img.data.set(pixels.data);
|
|
4241
4432
|
ctx.putImageData(img, 0, 0);
|
|
4242
4433
|
}, [pixels]);
|
|
4243
|
-
return /* @__PURE__ */ (0,
|
|
4434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4244
4435
|
"canvas",
|
|
4245
4436
|
{
|
|
4246
4437
|
ref,
|
|
@@ -4253,15 +4444,15 @@ var Thumbnail = ({
|
|
|
4253
4444
|
}
|
|
4254
4445
|
);
|
|
4255
4446
|
};
|
|
4256
|
-
var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "image", className }) => {
|
|
4257
|
-
const [, setTick] = (0,
|
|
4258
|
-
(0,
|
|
4259
|
-
const [error, setError] = (0,
|
|
4260
|
-
const [renaming, setRenaming] = (0,
|
|
4261
|
-
const [menu, setMenu] = (0,
|
|
4262
|
-
const [drag, setDrag] = (0,
|
|
4263
|
-
const [psdNotes, setPsdNotes] = (0,
|
|
4264
|
-
const fileInput = (0,
|
|
4447
|
+
var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "image", effects = true, className }) => {
|
|
4448
|
+
const [, setTick] = (0, import_react39.useState)(0);
|
|
4449
|
+
(0, import_react39.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
4450
|
+
const [error, setError] = (0, import_react39.useState)(null);
|
|
4451
|
+
const [renaming, setRenaming] = (0, import_react39.useState)(null);
|
|
4452
|
+
const [menu, setMenu] = (0, import_react39.useState)(null);
|
|
4453
|
+
const [drag, setDrag] = (0, import_react39.useState)(null);
|
|
4454
|
+
const [psdNotes, setPsdNotes] = (0, import_react39.useState)([]);
|
|
4455
|
+
const fileInput = (0, import_react39.useRef)(null);
|
|
4265
4456
|
const psdTask = async (fn) => {
|
|
4266
4457
|
try {
|
|
4267
4458
|
setError(null);
|
|
@@ -4270,9 +4461,9 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4270
4461
|
setError(err instanceof Error ? err.message : String(err));
|
|
4271
4462
|
}
|
|
4272
4463
|
};
|
|
4273
|
-
const commitNext = (0,
|
|
4464
|
+
const commitNext = (0, import_react39.useRef)(true);
|
|
4274
4465
|
const state = controller.getState();
|
|
4275
|
-
const rows = (0,
|
|
4466
|
+
const rows = (0, import_image_editor7.layerPanelRows)(state.layers, state.activeLayerId);
|
|
4276
4467
|
const active = controller.getActiveLayer();
|
|
4277
4468
|
const attempt = (fn) => {
|
|
4278
4469
|
try {
|
|
@@ -4284,7 +4475,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4284
4475
|
};
|
|
4285
4476
|
const run = async (action) => {
|
|
4286
4477
|
setMenu(null);
|
|
4287
|
-
setError(await (0,
|
|
4478
|
+
setError(await (0, import_image_editor7.runLayerMenuAction)(controller, action));
|
|
4288
4479
|
};
|
|
4289
4480
|
const prop = (key, value) => attempt(() => {
|
|
4290
4481
|
controller.setLayerProperties(active.id, { [key]: value }, commitNext.current);
|
|
@@ -4302,20 +4493,20 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4302
4493
|
if (!id) return;
|
|
4303
4494
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
4304
4495
|
const fraction = rect.height ? (e.clientY - rect.top) / rect.height : 0.5;
|
|
4305
|
-
const placement = (0,
|
|
4496
|
+
const placement = (0, import_image_editor7.dropPlacement)(state.layers, id, row.layer.id, (0, import_image_editor7.dropZone)(fraction, row.layer.type === "group"));
|
|
4306
4497
|
if (placement) attempt(() => controller.moveLayer(id, placement));
|
|
4307
4498
|
};
|
|
4308
4499
|
const thumb = (layer) => layer.type === "pixel" ? controller.getLayerThumbnail(layer.id, { maxSide: 64 }) : null;
|
|
4309
4500
|
const maskThumb = (layer) => layer.mask && !layer.mask.source ? controller.getLayerThumbnail(layer.id, { maxSide: 64, mask: true }) : null;
|
|
4310
4501
|
const locked = (layer) => Boolean(layer.locks?.all || layer.locks?.pixels || layer.locks?.position || layer.locks?.transparency);
|
|
4311
|
-
return /* @__PURE__ */ (0,
|
|
4312
|
-
/* @__PURE__ */ (0,
|
|
4313
|
-
/* @__PURE__ */ (0,
|
|
4314
|
-
/* @__PURE__ */ (0,
|
|
4315
|
-
/* @__PURE__ */ (0,
|
|
4316
|
-
/* @__PURE__ */ (0,
|
|
4317
|
-
/* @__PURE__ */ (0,
|
|
4318
|
-
/* @__PURE__ */ (0,
|
|
4502
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "layers-panel", onClick: () => menu && setMenu(null), children: [
|
|
4503
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "toolbar", "aria-label": "Layer actions", children: [
|
|
4504
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, onClick: () => run("new-layer"), children: "New Layer" }),
|
|
4505
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, onClick: () => run("new-group"), children: "New Group" }),
|
|
4506
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("duplicate"), children: "Duplicate" }),
|
|
4507
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("add-mask"), children: "Add Mask" }),
|
|
4508
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("delete"), children: "Delete" }),
|
|
4509
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4319
4510
|
"button",
|
|
4320
4511
|
{
|
|
4321
4512
|
type: "button",
|
|
@@ -4330,39 +4521,39 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4330
4521
|
children: "\u22EF"
|
|
4331
4522
|
}
|
|
4332
4523
|
),
|
|
4333
|
-
psd && /* @__PURE__ */ (0,
|
|
4334
|
-
/* @__PURE__ */ (0,
|
|
4335
|
-
/* @__PURE__ */ (0,
|
|
4336
|
-
/* @__PURE__ */ (0,
|
|
4524
|
+
psd && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
4525
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, onClick: () => fileInput.current?.click(), children: "Open PSD\u2026" }),
|
|
4526
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, onClick: () => psdTask(async () => (await (0, import_image_editor7.downloadPsd)(controller, psdFileName)).warnings), children: "Export PSD" }),
|
|
4527
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4337
4528
|
"input",
|
|
4338
4529
|
{
|
|
4339
4530
|
ref: fileInput,
|
|
4340
4531
|
type: "file",
|
|
4341
|
-
accept:
|
|
4532
|
+
accept: import_image_editor7.PSD_FILE_ACCEPT,
|
|
4342
4533
|
className: "hidden",
|
|
4343
4534
|
"data-testid": "psd-file-input",
|
|
4344
4535
|
"aria-label": "Open a PSD file",
|
|
4345
4536
|
onChange: (e) => {
|
|
4346
4537
|
const file = e.currentTarget.files?.[0];
|
|
4347
4538
|
e.currentTarget.value = "";
|
|
4348
|
-
if (file) psdTask(() => (0,
|
|
4539
|
+
if (file) psdTask(() => (0, import_image_editor7.openPsdFile)(controller, file));
|
|
4349
4540
|
}
|
|
4350
4541
|
}
|
|
4351
4542
|
)
|
|
4352
4543
|
] })
|
|
4353
4544
|
] }),
|
|
4354
|
-
psdNotes.length > 0 && /* @__PURE__ */ (0,
|
|
4355
|
-
psdNotes.map((n) => /* @__PURE__ */ (0,
|
|
4356
|
-
/* @__PURE__ */ (0,
|
|
4545
|
+
psdNotes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("ul", { className: "rounded bg-amber-900/30 text-amber-200 px-2 py-1 space-y-0.5", "data-testid": "psd-warnings", "aria-label": "PSD warnings", children: [
|
|
4546
|
+
psdNotes.map((n) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("li", { children: n }, n)),
|
|
4547
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: "underline", onClick: () => setPsdNotes([]), children: "Dismiss" }) })
|
|
4357
4548
|
] }),
|
|
4358
|
-
active && /* @__PURE__ */ (0,
|
|
4359
|
-
/* @__PURE__ */ (0,
|
|
4360
|
-
/* @__PURE__ */ (0,
|
|
4549
|
+
active && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1 items-center", "data-testid": "layer-properties", children: [
|
|
4550
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
|
|
4551
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "text-slate-400", children: [
|
|
4361
4552
|
"Opacity ",
|
|
4362
4553
|
Math.round(active.opacity * 100),
|
|
4363
4554
|
"%"
|
|
4364
4555
|
] }),
|
|
4365
|
-
/* @__PURE__ */ (0,
|
|
4556
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4366
4557
|
"input",
|
|
4367
4558
|
{
|
|
4368
4559
|
type: "range",
|
|
@@ -4376,13 +4567,13 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4376
4567
|
}
|
|
4377
4568
|
)
|
|
4378
4569
|
] }),
|
|
4379
|
-
/* @__PURE__ */ (0,
|
|
4380
|
-
/* @__PURE__ */ (0,
|
|
4570
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
|
|
4571
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "text-slate-400", children: [
|
|
4381
4572
|
"Fill ",
|
|
4382
4573
|
Math.round(((active.type === "pixel" ? active.fillOpacity : void 0) ?? 1) * 100),
|
|
4383
4574
|
"%"
|
|
4384
4575
|
] }),
|
|
4385
|
-
/* @__PURE__ */ (0,
|
|
4576
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4386
4577
|
"input",
|
|
4387
4578
|
{
|
|
4388
4579
|
type: "range",
|
|
@@ -4397,7 +4588,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4397
4588
|
}
|
|
4398
4589
|
)
|
|
4399
4590
|
] }),
|
|
4400
|
-
/* @__PURE__ */ (0,
|
|
4591
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
4401
4592
|
"select",
|
|
4402
4593
|
{
|
|
4403
4594
|
"aria-label": "Layer blend mode",
|
|
@@ -4405,13 +4596,13 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4405
4596
|
value: active.blend,
|
|
4406
4597
|
onChange: (e) => attempt(() => controller.setLayerProperties(active.id, { blend: e.target.value })),
|
|
4407
4598
|
children: [
|
|
4408
|
-
active.type === "group" && /* @__PURE__ */ (0,
|
|
4409
|
-
|
|
4599
|
+
active.type === "group" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("option", { value: "pass-through", children: "Pass Through" }),
|
|
4600
|
+
import_image_editor7.BLEND_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("option", { value: m.id, children: m.label }, m.id))
|
|
4410
4601
|
]
|
|
4411
4602
|
}
|
|
4412
4603
|
),
|
|
4413
|
-
/* @__PURE__ */ (0,
|
|
4414
|
-
/* @__PURE__ */ (0,
|
|
4604
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
4605
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4415
4606
|
"input",
|
|
4416
4607
|
{
|
|
4417
4608
|
type: "checkbox",
|
|
@@ -4423,8 +4614,8 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4423
4614
|
),
|
|
4424
4615
|
"Clip to below"
|
|
4425
4616
|
] }),
|
|
4426
|
-
/* @__PURE__ */ (0,
|
|
4427
|
-
/* @__PURE__ */ (0,
|
|
4617
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.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_runtime22.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
4618
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4428
4619
|
"input",
|
|
4429
4620
|
{
|
|
4430
4621
|
type: "checkbox",
|
|
@@ -4437,9 +4628,10 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4437
4628
|
k
|
|
4438
4629
|
] }, k)) })
|
|
4439
4630
|
] }),
|
|
4440
|
-
/* @__PURE__ */ (0,
|
|
4631
|
+
effects && active && active.type !== "adjustment" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(LayerEffectsPanel, { controller, className: "border-t border-slate-800 pt-1.5" }),
|
|
4632
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("ul", { className: "flex flex-col gap-0.5", role: "tree", "aria-label": "Layers", children: rows.map((row) => {
|
|
4441
4633
|
const { layer } = row;
|
|
4442
|
-
return /* @__PURE__ */ (0,
|
|
4634
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
4443
4635
|
"li",
|
|
4444
4636
|
{
|
|
4445
4637
|
role: "treeitem",
|
|
@@ -4469,7 +4661,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4469
4661
|
className: rowClass(row.active),
|
|
4470
4662
|
style: { paddingLeft: 6 + row.depth * 14 },
|
|
4471
4663
|
children: [
|
|
4472
|
-
/* @__PURE__ */ (0,
|
|
4664
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4473
4665
|
"button",
|
|
4474
4666
|
{
|
|
4475
4667
|
type: "button",
|
|
@@ -4483,7 +4675,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4483
4675
|
children: layer.visible ? "\u25CF" : "\u25CB"
|
|
4484
4676
|
}
|
|
4485
4677
|
),
|
|
4486
|
-
layer.type === "group" && /* @__PURE__ */ (0,
|
|
4678
|
+
layer.type === "group" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4487
4679
|
"button",
|
|
4488
4680
|
{
|
|
4489
4681
|
type: "button",
|
|
@@ -4496,8 +4688,8 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4496
4688
|
children: layer.collapsed ? "\u25B8" : "\u25BE"
|
|
4497
4689
|
}
|
|
4498
4690
|
),
|
|
4499
|
-
row.clipped && /* @__PURE__ */ (0,
|
|
4500
|
-
layer.type === "pixel" ? /* @__PURE__ */ (0,
|
|
4691
|
+
row.clipped && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-slate-500", "aria-label": "Clipped", children: "\u21B3" }),
|
|
4692
|
+
layer.type === "pixel" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4501
4693
|
Thumbnail,
|
|
4502
4694
|
{
|
|
4503
4695
|
pixels: thumb(layer),
|
|
@@ -4505,15 +4697,31 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4505
4697
|
label: `${row.label} pixels`,
|
|
4506
4698
|
selected: row.active && state.activeTarget === "pixels" && Boolean(layer.mask)
|
|
4507
4699
|
}
|
|
4508
|
-
) : /* @__PURE__ */ (0,
|
|
4700
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4509
4701
|
"span",
|
|
4510
4702
|
{
|
|
4511
4703
|
className: "shrink-0 grid place-items-center rounded bg-slate-800 text-[9px] text-slate-400 ring-1 ring-slate-700",
|
|
4512
4704
|
style: { width: thumbnailSize, height: thumbnailSize },
|
|
4513
|
-
children: (0,
|
|
4705
|
+
children: (0, import_image_editor7.layerBadge)(layer)
|
|
4514
4706
|
}
|
|
4515
4707
|
),
|
|
4516
|
-
layer.mask && /* @__PURE__ */ (0,
|
|
4708
|
+
layer.mask && !layer.mask.source && layer.type === "pixel" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4709
|
+
"button",
|
|
4710
|
+
{
|
|
4711
|
+
type: "button",
|
|
4712
|
+
"aria-label": `${layer.mask.linked === false ? "Link" : "Unlink"} ${row.label} mask`,
|
|
4713
|
+
"aria-pressed": layer.mask.linked !== false,
|
|
4714
|
+
title: layer.mask.linked === false ? "Mask unlinked: it stays put when the layer moves or transforms. Click to link." : "Mask linked: it moves with the layer. Click to unlink.",
|
|
4715
|
+
"data-testid": "layer-mask-link",
|
|
4716
|
+
className: `shrink-0 text-[10px] leading-none ${layer.mask.linked === false ? "text-slate-600" : "text-slate-300"}`,
|
|
4717
|
+
onClick: (e) => {
|
|
4718
|
+
e.stopPropagation();
|
|
4719
|
+
attempt(() => controller.setLayerMaskProps(layer.id, { linked: layer.mask.linked === false }));
|
|
4720
|
+
},
|
|
4721
|
+
children: layer.mask.linked === false ? "\u26D3\uFE0E\u0338" : "\u26D3\uFE0E"
|
|
4722
|
+
}
|
|
4723
|
+
),
|
|
4724
|
+
layer.mask && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4517
4725
|
Thumbnail,
|
|
4518
4726
|
{
|
|
4519
4727
|
pixels: maskThumb(layer),
|
|
@@ -4528,7 +4736,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4528
4736
|
}
|
|
4529
4737
|
}
|
|
4530
4738
|
),
|
|
4531
|
-
renaming === layer.id ? /* @__PURE__ */ (0,
|
|
4739
|
+
renaming === layer.id ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4532
4740
|
"input",
|
|
4533
4741
|
{
|
|
4534
4742
|
autoFocus: true,
|
|
@@ -4545,7 +4753,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4545
4753
|
if (e.key === "Escape") setRenaming(null);
|
|
4546
4754
|
}
|
|
4547
4755
|
}
|
|
4548
|
-
) : /* @__PURE__ */ (0,
|
|
4756
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4549
4757
|
"span",
|
|
4550
4758
|
{
|
|
4551
4759
|
className: `flex-1 min-w-0 truncate ${layer.visible ? "" : "text-slate-500"}`,
|
|
@@ -4556,15 +4764,30 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4556
4764
|
children: row.label
|
|
4557
4765
|
}
|
|
4558
4766
|
),
|
|
4559
|
-
|
|
4560
|
-
|
|
4767
|
+
(0, import_image_editor7.layerEffectsBadge)(layer) && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4768
|
+
"button",
|
|
4769
|
+
{
|
|
4770
|
+
type: "button",
|
|
4771
|
+
"data-testid": "layer-fx-badge",
|
|
4772
|
+
"aria-label": (0, import_image_editor7.layerEffectsBadge)(layer) === "on" ? `Turn effects off for ${row.label}` : `Turn effects on for ${row.label}`,
|
|
4773
|
+
"aria-pressed": (0, import_image_editor7.layerEffectsBadge)(layer) === "on",
|
|
4774
|
+
className: `text-[9px] italic font-semibold ${(0, import_image_editor7.layerEffectsBadge)(layer) === "on" ? "text-indigo-300" : "text-slate-600 line-through"}`,
|
|
4775
|
+
onClick: (e) => {
|
|
4776
|
+
e.stopPropagation();
|
|
4777
|
+
attempt(() => controller.setLayerEffectsEnabled(layer.id, (0, import_image_editor7.layerEffectsBadge)(layer) !== "on"));
|
|
4778
|
+
},
|
|
4779
|
+
children: "fx"
|
|
4780
|
+
}
|
|
4781
|
+
),
|
|
4782
|
+
locked(layer) && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { "aria-label": "Locked", className: "text-slate-400", children: "\u{1F512}" }),
|
|
4783
|
+
layer.blend !== "normal" && layer.blend !== "pass-through" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-[9px] text-slate-500", children: layer.blend })
|
|
4561
4784
|
]
|
|
4562
4785
|
},
|
|
4563
4786
|
layer.id
|
|
4564
4787
|
);
|
|
4565
4788
|
}) }),
|
|
4566
|
-
error && /* @__PURE__ */ (0,
|
|
4567
|
-
menu && /* @__PURE__ */ (0,
|
|
4789
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
|
|
4790
|
+
menu && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4568
4791
|
"div",
|
|
4569
4792
|
{
|
|
4570
4793
|
role: "menu",
|
|
@@ -4573,7 +4796,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4573
4796
|
style: { left: menu.x, top: menu.y },
|
|
4574
4797
|
onClick: (e) => e.stopPropagation(),
|
|
4575
4798
|
onKeyDown: (e) => e.key === "Escape" && setMenu(null),
|
|
4576
|
-
children: (0,
|
|
4799
|
+
children: (0, import_image_editor7.layerMenu)(controller).map((item) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4577
4800
|
"button",
|
|
4578
4801
|
{
|
|
4579
4802
|
type: "button",
|
|
@@ -4591,14 +4814,14 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
4591
4814
|
};
|
|
4592
4815
|
|
|
4593
4816
|
// src/image-editor/BrushOptionsBar.tsx
|
|
4594
|
-
var
|
|
4595
|
-
var
|
|
4596
|
-
var
|
|
4817
|
+
var import_react40 = require("react");
|
|
4818
|
+
var import_image_editor8 = require("@pixerate/editor/image-editor");
|
|
4819
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
4597
4820
|
var chip = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
|
|
4598
4821
|
var BrushOptionsBar = ({ controller, className }) => {
|
|
4599
|
-
const [, setTick] = (0,
|
|
4600
|
-
(0,
|
|
4601
|
-
const [error, setError] = (0,
|
|
4822
|
+
const [, setTick] = (0, import_react40.useState)(0);
|
|
4823
|
+
(0, import_react40.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
4824
|
+
const [error, setError] = (0, import_react40.useState)(null);
|
|
4602
4825
|
const state = controller.getState();
|
|
4603
4826
|
const { brush, foreground, background, mixer, mixerLoad } = state.paint;
|
|
4604
4827
|
const attempt = (fn) => {
|
|
@@ -4609,8 +4832,8 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
4609
4832
|
setError(err instanceof Error ? err.message : String(err));
|
|
4610
4833
|
}
|
|
4611
4834
|
};
|
|
4612
|
-
return /* @__PURE__ */ (0,
|
|
4613
|
-
/* @__PURE__ */ (0,
|
|
4835
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "brush-options", children: [
|
|
4836
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Paint tools", children: import_image_editor8.PAINT_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4614
4837
|
"button",
|
|
4615
4838
|
{
|
|
4616
4839
|
type: "button",
|
|
@@ -4622,9 +4845,9 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
4622
4845
|
},
|
|
4623
4846
|
t.id
|
|
4624
4847
|
)) }),
|
|
4625
|
-
/* @__PURE__ */ (0,
|
|
4626
|
-
/* @__PURE__ */ (0,
|
|
4627
|
-
/* @__PURE__ */ (0,
|
|
4848
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2", role: "group", "aria-label": "Colours", children: [
|
|
4849
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
4850
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4628
4851
|
"input",
|
|
4629
4852
|
{
|
|
4630
4853
|
type: "color",
|
|
@@ -4634,10 +4857,10 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
4634
4857
|
className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
|
|
4635
4858
|
}
|
|
4636
4859
|
),
|
|
4637
|
-
/* @__PURE__ */ (0,
|
|
4860
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-slate-400", children: "FG" })
|
|
4638
4861
|
] }),
|
|
4639
|
-
/* @__PURE__ */ (0,
|
|
4640
|
-
/* @__PURE__ */ (0,
|
|
4862
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
4863
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4641
4864
|
"input",
|
|
4642
4865
|
{
|
|
4643
4866
|
type: "color",
|
|
@@ -4647,12 +4870,12 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
4647
4870
|
className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
|
|
4648
4871
|
}
|
|
4649
4872
|
),
|
|
4650
|
-
/* @__PURE__ */ (0,
|
|
4873
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-slate-400", children: "BG" })
|
|
4651
4874
|
] }),
|
|
4652
|
-
/* @__PURE__ */ (0,
|
|
4653
|
-
/* @__PURE__ */ (0,
|
|
4875
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Swap colours (X)", className: chip(false), onClick: () => controller.swapPaintColors(), children: "Swap" }),
|
|
4876
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Default colours (D)", className: chip(false), onClick: () => controller.resetPaintColors(), children: "Default" })
|
|
4654
4877
|
] }),
|
|
4655
|
-
|
|
4878
|
+
import_image_editor8.BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4656
4879
|
ControlSlider,
|
|
4657
4880
|
{
|
|
4658
4881
|
spec,
|
|
@@ -4661,21 +4884,21 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
4661
4884
|
},
|
|
4662
4885
|
spec.id
|
|
4663
4886
|
)),
|
|
4664
|
-
state.activeTool === "mixer" && /* @__PURE__ */ (0,
|
|
4665
|
-
/* @__PURE__ */ (0,
|
|
4666
|
-
/* @__PURE__ */ (0,
|
|
4887
|
+
state.activeTool === "mixer" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Mixer Brush", "data-testid": "mixer-options", children: [
|
|
4888
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
4889
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4667
4890
|
"span",
|
|
4668
4891
|
{
|
|
4669
4892
|
"aria-label": "Brush load",
|
|
4670
|
-
title: mixerLoad.reservoir ? `Loaded ${(0,
|
|
4893
|
+
title: mixerLoad.reservoir ? `Loaded ${(0, import_image_editor8.rgbUnitToHex)(mixerLoad.reservoir)}, ${Math.round(mixerLoad.amount * 100)}% left` : "Unloaded",
|
|
4671
4894
|
className: "h-6 w-6 rounded border border-slate-700",
|
|
4672
|
-
style: { background: mixerLoad.reservoir ? (0,
|
|
4895
|
+
style: { background: mixerLoad.reservoir ? (0, import_image_editor8.rgbUnitToHex)(mixerLoad.reservoir) : "transparent" }
|
|
4673
4896
|
}
|
|
4674
4897
|
),
|
|
4675
|
-
/* @__PURE__ */ (0,
|
|
4676
|
-
/* @__PURE__ */ (0,
|
|
4898
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Fill the reservoir with the foreground colour", className: chip(false), onClick: () => controller.loadMixerBrush(), children: "Load brush" }),
|
|
4899
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Empty the picked-up colour", className: chip(false), onClick: () => controller.cleanMixerBrush(), children: "Clean brush" })
|
|
4677
4900
|
] }),
|
|
4678
|
-
/* @__PURE__ */ (0,
|
|
4901
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Mixing", children: import_image_editor8.MIXER_MIXING_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4679
4902
|
"button",
|
|
4680
4903
|
{
|
|
4681
4904
|
type: "button",
|
|
@@ -4687,10 +4910,10 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
4687
4910
|
},
|
|
4688
4911
|
m.id
|
|
4689
4912
|
)) }),
|
|
4690
|
-
|
|
4691
|
-
/* @__PURE__ */ (0,
|
|
4692
|
-
/* @__PURE__ */ (0,
|
|
4693
|
-
/* @__PURE__ */ (0,
|
|
4913
|
+
import_image_editor8.MIXER_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ControlSlider, { spec, value: mixer[spec.id], onChange: (v) => controller.setPaintOptions({ mixer: { [spec.id]: v } }) }, spec.id)),
|
|
4914
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: [
|
|
4915
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
|
|
4916
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4694
4917
|
"input",
|
|
4695
4918
|
{
|
|
4696
4919
|
type: "checkbox",
|
|
@@ -4702,8 +4925,8 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
4702
4925
|
),
|
|
4703
4926
|
"Load each stroke"
|
|
4704
4927
|
] }),
|
|
4705
|
-
/* @__PURE__ */ (0,
|
|
4706
|
-
/* @__PURE__ */ (0,
|
|
4928
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
|
|
4929
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4707
4930
|
"input",
|
|
4708
4931
|
{
|
|
4709
4932
|
type: "checkbox",
|
|
@@ -4717,9 +4940,9 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
4717
4940
|
] })
|
|
4718
4941
|
] })
|
|
4719
4942
|
] }),
|
|
4720
|
-
/* @__PURE__ */ (0,
|
|
4721
|
-
/* @__PURE__ */ (0,
|
|
4722
|
-
/* @__PURE__ */ (0,
|
|
4943
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
|
|
4944
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
|
|
4945
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4723
4946
|
"input",
|
|
4724
4947
|
{
|
|
4725
4948
|
type: "checkbox",
|
|
@@ -4731,8 +4954,8 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
4731
4954
|
),
|
|
4732
4955
|
"Pressure size"
|
|
4733
4956
|
] }),
|
|
4734
|
-
/* @__PURE__ */ (0,
|
|
4735
|
-
/* @__PURE__ */ (0,
|
|
4957
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
|
|
4958
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4736
4959
|
"input",
|
|
4737
4960
|
{
|
|
4738
4961
|
type: "checkbox",
|
|
@@ -4745,18 +4968,18 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
4745
4968
|
"Pressure opacity"
|
|
4746
4969
|
] })
|
|
4747
4970
|
] }),
|
|
4748
|
-
/* @__PURE__ */ (0,
|
|
4749
|
-
/* @__PURE__ */ (0,
|
|
4750
|
-
/* @__PURE__ */ (0,
|
|
4971
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex gap-1", children: [
|
|
4972
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.fillPixels()), children: "Fill" }),
|
|
4973
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.clearPixels()), children: "Clear" })
|
|
4751
4974
|
] }),
|
|
4752
|
-
error && /* @__PURE__ */ (0,
|
|
4975
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
|
|
4753
4976
|
] });
|
|
4754
4977
|
};
|
|
4755
4978
|
|
|
4756
4979
|
// src/image-editor/SelectionOptionsBar.tsx
|
|
4757
|
-
var
|
|
4758
|
-
var
|
|
4759
|
-
var
|
|
4980
|
+
var import_react41 = require("react");
|
|
4981
|
+
var import_image_editor9 = require("@pixerate/editor/image-editor");
|
|
4982
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
4760
4983
|
var MODIFY_OPS = [
|
|
4761
4984
|
{ op: "grow", label: "Grow" },
|
|
4762
4985
|
{ op: "shrink", label: "Shrink" },
|
|
@@ -4773,20 +4996,20 @@ var SelectionOptionsBar = ({
|
|
|
4773
4996
|
quickMask,
|
|
4774
4997
|
className = ""
|
|
4775
4998
|
}) => {
|
|
4776
|
-
const [radius, setRadius] = (0,
|
|
4999
|
+
const [radius, setRadius] = (0, import_react41.useState)(2);
|
|
4777
5000
|
const set = (patch) => onOptionsChange({ ...options, ...patch });
|
|
4778
5001
|
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
4779
5002
|
const qm = quickMask ?? Boolean(controller.getState().quickMask);
|
|
4780
|
-
return /* @__PURE__ */ (0,
|
|
4781
|
-
/* @__PURE__ */ (0,
|
|
4782
|
-
/* @__PURE__ */ (0,
|
|
4783
|
-
options.tool === "wand" && /* @__PURE__ */ (0,
|
|
4784
|
-
/* @__PURE__ */ (0,
|
|
4785
|
-
/* @__PURE__ */ (0,
|
|
4786
|
-
/* @__PURE__ */ (0,
|
|
4787
|
-
/* @__PURE__ */ (0,
|
|
5003
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
5004
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { role: "group", "aria-label": "Selection tool", className: "flex flex-wrap gap-1", children: import_image_editor9.SELECTION_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime24.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)) }),
|
|
5005
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { role: "group", "aria-label": "Selection mode", className: "flex flex-wrap gap-1", children: import_image_editor9.SELECTION_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", "aria-pressed": options.mode === m, className: btn(options.mode === m), onClick: () => set({ mode: m }), children: import_image_editor9.SELECTION_MODE_LABELS[m] }, m)) }),
|
|
5006
|
+
options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
5007
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
5008
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
5009
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Tolerance" }),
|
|
5010
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "font-mono", children: options.tolerance })
|
|
4788
5011
|
] }),
|
|
4789
|
-
/* @__PURE__ */ (0,
|
|
5012
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4790
5013
|
"input",
|
|
4791
5014
|
{
|
|
4792
5015
|
type: "range",
|
|
@@ -4800,17 +5023,17 @@ var SelectionOptionsBar = ({
|
|
|
4800
5023
|
}
|
|
4801
5024
|
)
|
|
4802
5025
|
] }),
|
|
4803
|
-
/* @__PURE__ */ (0,
|
|
4804
|
-
/* @__PURE__ */ (0,
|
|
5026
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
5027
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
|
|
4805
5028
|
"Contiguous"
|
|
4806
5029
|
] }),
|
|
4807
|
-
/* @__PURE__ */ (0,
|
|
4808
|
-
/* @__PURE__ */ (0,
|
|
5030
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
5031
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
|
|
4809
5032
|
"Sample adjusted image"
|
|
4810
5033
|
] }),
|
|
4811
|
-
/* @__PURE__ */ (0,
|
|
5034
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
4812
5035
|
"Sample",
|
|
4813
|
-
/* @__PURE__ */ (0,
|
|
5036
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
4814
5037
|
"select",
|
|
4815
5038
|
{
|
|
4816
5039
|
"aria-label": "Sample from",
|
|
@@ -4818,27 +5041,27 @@ var SelectionOptionsBar = ({
|
|
|
4818
5041
|
onChange: (e) => set({ sample: e.target.value }),
|
|
4819
5042
|
className: "bg-slate-800 border border-slate-700 rounded px-1 py-0.5",
|
|
4820
5043
|
children: [
|
|
4821
|
-
/* @__PURE__ */ (0,
|
|
4822
|
-
/* @__PURE__ */ (0,
|
|
5044
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: "composite", children: "All layers" }),
|
|
5045
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: "active-layer", children: "Active layer" })
|
|
4823
5046
|
]
|
|
4824
5047
|
}
|
|
4825
5048
|
)
|
|
4826
5049
|
] })
|
|
4827
5050
|
] }),
|
|
4828
|
-
/* @__PURE__ */ (0,
|
|
4829
|
-
/* @__PURE__ */ (0,
|
|
5051
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
5052
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
|
|
4830
5053
|
"Anti-alias"
|
|
4831
5054
|
] }),
|
|
4832
|
-
/* @__PURE__ */ (0,
|
|
4833
|
-
/* @__PURE__ */ (0,
|
|
4834
|
-
/* @__PURE__ */ (0,
|
|
4835
|
-
/* @__PURE__ */ (0,
|
|
4836
|
-
/* @__PURE__ */ (0,
|
|
5055
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
|
|
5056
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
|
|
5057
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
|
|
5058
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
|
|
5059
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
|
|
4837
5060
|
] }),
|
|
4838
|
-
/* @__PURE__ */ (0,
|
|
4839
|
-
/* @__PURE__ */ (0,
|
|
5061
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
5062
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
|
|
4840
5063
|
"Radius",
|
|
4841
|
-
/* @__PURE__ */ (0,
|
|
5064
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4842
5065
|
"input",
|
|
4843
5066
|
{
|
|
4844
5067
|
type: "number",
|
|
@@ -4852,24 +5075,24 @@ var SelectionOptionsBar = ({
|
|
|
4852
5075
|
}
|
|
4853
5076
|
)
|
|
4854
5077
|
] }),
|
|
4855
|
-
MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0,
|
|
5078
|
+
MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.modifySelection(op, radius), children: label }, op))
|
|
4856
5079
|
] }),
|
|
4857
|
-
/* @__PURE__ */ (0,
|
|
5080
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor9.describeSelection)(sel) })
|
|
4858
5081
|
] });
|
|
4859
5082
|
};
|
|
4860
5083
|
|
|
4861
5084
|
// src/image-editor/RefineEdgePanel.tsx
|
|
4862
|
-
var
|
|
4863
|
-
var
|
|
4864
|
-
var
|
|
5085
|
+
var import_react42 = require("react");
|
|
5086
|
+
var import_image_editor10 = require("@pixerate/editor/image-editor");
|
|
5087
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
4865
5088
|
var DEFAULT_PARAMS = { radius: 8, smartRadius: false, smooth: 0, feather: 0, contrast: 0, shiftEdge: 0 };
|
|
4866
|
-
var
|
|
5089
|
+
var button2 = "px-2 py-1 rounded-md border border-slate-800 bg-slate-950 text-[11px] text-slate-200 hover:text-white disabled:opacity-40";
|
|
4867
5090
|
var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
4868
|
-
const [params, setParams] = (0,
|
|
4869
|
-
const [busy, setBusy] = (0,
|
|
4870
|
-
const [error, setError] = (0,
|
|
4871
|
-
const [layerId, setLayerId] = (0,
|
|
4872
|
-
const [newKind, setNewKind] = (0,
|
|
5091
|
+
const [params, setParams] = (0, import_react42.useState)(DEFAULT_PARAMS);
|
|
5092
|
+
const [busy, setBusy] = (0, import_react42.useState)(false);
|
|
5093
|
+
const [error, setError] = (0, import_react42.useState)(null);
|
|
5094
|
+
const [layerId, setLayerId] = (0, import_react42.useState)("");
|
|
5095
|
+
const [newKind, setNewKind] = (0, import_react42.useState)("hueSaturation");
|
|
4873
5096
|
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
4874
5097
|
const list = layers ?? controller.getAdjustmentLayers();
|
|
4875
5098
|
const target = list.find((l) => l.id === layerId) ?? list[list.length - 1];
|
|
@@ -4884,17 +5107,17 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
4884
5107
|
setBusy(false);
|
|
4885
5108
|
}
|
|
4886
5109
|
};
|
|
4887
|
-
return /* @__PURE__ */ (0,
|
|
4888
|
-
/* @__PURE__ */ (0,
|
|
4889
|
-
|
|
4890
|
-
/* @__PURE__ */ (0,
|
|
4891
|
-
/* @__PURE__ */ (0,
|
|
4892
|
-
/* @__PURE__ */ (0,
|
|
5110
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
5111
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
|
|
5112
|
+
import_image_editor10.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
5113
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
5114
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: c.label }),
|
|
5115
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
|
|
4893
5116
|
params[c.id],
|
|
4894
5117
|
c.unit
|
|
4895
5118
|
] })
|
|
4896
5119
|
] }),
|
|
4897
|
-
/* @__PURE__ */ (0,
|
|
5120
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4898
5121
|
"input",
|
|
4899
5122
|
{
|
|
4900
5123
|
type: "range",
|
|
@@ -4908,67 +5131,67 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
4908
5131
|
}
|
|
4909
5132
|
)
|
|
4910
5133
|
] }, c.id)),
|
|
4911
|
-
/* @__PURE__ */ (0,
|
|
4912
|
-
/* @__PURE__ */ (0,
|
|
5134
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
5135
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
|
|
4913
5136
|
"Smart Radius"
|
|
4914
5137
|
] }),
|
|
4915
|
-
/* @__PURE__ */ (0,
|
|
4916
|
-
/* @__PURE__ */ (0,
|
|
4917
|
-
/* @__PURE__ */ (0,
|
|
5138
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-1", children: [
|
|
5139
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
|
|
5140
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
|
|
4918
5141
|
] }),
|
|
4919
|
-
error && /* @__PURE__ */ (0,
|
|
4920
|
-
/* @__PURE__ */ (0,
|
|
4921
|
-
/* @__PURE__ */ (0,
|
|
4922
|
-
/* @__PURE__ */ (0,
|
|
5142
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
|
|
5143
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
|
|
5144
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-1 items-center", children: [
|
|
5145
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4923
5146
|
"select",
|
|
4924
5147
|
{
|
|
4925
5148
|
"aria-label": "New masked layer kind",
|
|
4926
5149
|
value: newKind,
|
|
4927
5150
|
onChange: (e) => setNewKind(e.target.value),
|
|
4928
5151
|
className: "flex-1 bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
|
|
4929
|
-
children:
|
|
5152
|
+
children: import_image_editor10.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: k.kind, children: k.label }, k.kind))
|
|
4930
5153
|
}
|
|
4931
5154
|
),
|
|
4932
|
-
/* @__PURE__ */ (0,
|
|
5155
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4933
5156
|
"button",
|
|
4934
5157
|
{
|
|
4935
5158
|
type: "button",
|
|
4936
|
-
className:
|
|
5159
|
+
className: button2,
|
|
4937
5160
|
disabled: !sel,
|
|
4938
|
-
onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0,
|
|
5161
|
+
onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor10.layerMaskFromSelection)(sel) })),
|
|
4939
5162
|
children: "New Masked Layer"
|
|
4940
5163
|
}
|
|
4941
5164
|
)
|
|
4942
5165
|
] }),
|
|
4943
|
-
list.length > 0 && target && /* @__PURE__ */ (0,
|
|
4944
|
-
/* @__PURE__ */ (0,
|
|
5166
|
+
list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
5167
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4945
5168
|
"select",
|
|
4946
5169
|
{
|
|
4947
5170
|
"aria-label": "Mask layer",
|
|
4948
5171
|
value: target.id,
|
|
4949
5172
|
onChange: (e) => setLayerId(e.target.value),
|
|
4950
5173
|
className: "bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
|
|
4951
|
-
children: list.map((l) => /* @__PURE__ */ (0,
|
|
4952
|
-
l.name || (0,
|
|
5174
|
+
children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("option", { value: l.id, children: [
|
|
5175
|
+
l.name || (0, import_image_editor10.adjustmentKindLabel)(l.kind),
|
|
4953
5176
|
l.mask ? " (masked)" : ""
|
|
4954
5177
|
] }, l.id))
|
|
4955
5178
|
}
|
|
4956
5179
|
),
|
|
4957
|
-
/* @__PURE__ */ (0,
|
|
4958
|
-
/* @__PURE__ */ (0,
|
|
4959
|
-
/* @__PURE__ */ (0,
|
|
4960
|
-
/* @__PURE__ */ (0,
|
|
5180
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
|
|
5181
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
|
|
5182
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
|
|
5183
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
|
|
4961
5184
|
] }),
|
|
4962
|
-
target.mask && /* @__PURE__ */ (0,
|
|
4963
|
-
/* @__PURE__ */ (0,
|
|
4964
|
-
/* @__PURE__ */ (0,
|
|
4965
|
-
/* @__PURE__ */ (0,
|
|
4966
|
-
/* @__PURE__ */ (0,
|
|
5185
|
+
target.mask && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
5186
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
5187
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
5188
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Density" }),
|
|
5189
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
|
|
4967
5190
|
Math.round((target.mask.density ?? 1) * 100),
|
|
4968
5191
|
"%"
|
|
4969
5192
|
] })
|
|
4970
5193
|
] }),
|
|
4971
|
-
/* @__PURE__ */ (0,
|
|
5194
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4972
5195
|
"input",
|
|
4973
5196
|
{
|
|
4974
5197
|
type: "range",
|
|
@@ -4982,15 +5205,15 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
4982
5205
|
}
|
|
4983
5206
|
)
|
|
4984
5207
|
] }),
|
|
4985
|
-
/* @__PURE__ */ (0,
|
|
4986
|
-
/* @__PURE__ */ (0,
|
|
4987
|
-
/* @__PURE__ */ (0,
|
|
4988
|
-
/* @__PURE__ */ (0,
|
|
5208
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
5209
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
5210
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Mask Feather" }),
|
|
5211
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
|
|
4989
5212
|
target.mask.feather ?? 0,
|
|
4990
5213
|
"px"
|
|
4991
5214
|
] })
|
|
4992
5215
|
] }),
|
|
4993
|
-
/* @__PURE__ */ (0,
|
|
5216
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4994
5217
|
"input",
|
|
4995
5218
|
{
|
|
4996
5219
|
type: "range",
|
|
@@ -5009,8 +5232,83 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
5009
5232
|
] });
|
|
5010
5233
|
};
|
|
5011
5234
|
|
|
5235
|
+
// src/image-editor/FreeTransformOptionsBar.tsx
|
|
5236
|
+
var import_react43 = require("react");
|
|
5237
|
+
var import_image_editor11 = require("@pixerate/editor/image-editor");
|
|
5238
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
5239
|
+
var chip2 = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
|
|
5240
|
+
var round = (v, unit) => unit === "px" ? Math.round(v * 10) / 10 : Math.round(v * 100) / 100;
|
|
5241
|
+
var FreeTransformOptionsBar = ({ tool, className }) => {
|
|
5242
|
+
const [, setTick] = (0, import_react43.useState)(0);
|
|
5243
|
+
(0, import_react43.useEffect)(() => tool.subscribe(() => setTick((n) => n + 1)), [tool]);
|
|
5244
|
+
const bar = tool.bar();
|
|
5245
|
+
if (!tool.active || !bar) return null;
|
|
5246
|
+
const apply = (field, raw) => {
|
|
5247
|
+
const v = Number(raw);
|
|
5248
|
+
if (raw.trim() !== "" && Number.isFinite(v) && Math.abs(v - bar[field]) > 1e-9) tool.setField(field, v);
|
|
5249
|
+
};
|
|
5250
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: `flex flex-wrap items-center gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "free-transform-options", role: "toolbar", "aria-label": "Free Transform options", children: [
|
|
5251
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Transform mode", children: import_image_editor11.FREE_TRANSFORM_MODE_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", title: m.title, "aria-pressed": tool.mode === m.id, className: chip2(tool.mode === m.id), onClick: () => tool.setMode(m.id), children: m.label }, m.id)) }),
|
|
5252
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "grid grid-cols-3 gap-px", role: "group", "aria-label": "Reference point", children: import_image_editor11.TRANSFORM_ANCHORS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", "aria-label": `Reference point ${a}`, title: `Reference point: ${a}`, className: "h-2.5 w-2.5 rounded-sm bg-slate-700 hover:bg-indigo-500", onClick: () => tool.setReference(a) }, a)) }),
|
|
5253
|
+
import_image_editor11.FREE_TRANSFORM_FIELDS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", title: f.title, children: [
|
|
5254
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: f.label }),
|
|
5255
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
5256
|
+
"input",
|
|
5257
|
+
{
|
|
5258
|
+
type: "number",
|
|
5259
|
+
"aria-label": f.title,
|
|
5260
|
+
defaultValue: round(bar[f.id], f.unit),
|
|
5261
|
+
disabled: !bar.affine,
|
|
5262
|
+
step: f.unit === "px" ? 1 : 0.1,
|
|
5263
|
+
className: "w-16 rounded border border-slate-700 bg-slate-900 px-1 py-0.5 text-right disabled:opacity-40",
|
|
5264
|
+
onBlur: (e) => apply(f.id, e.currentTarget.value),
|
|
5265
|
+
onKeyDown: (e) => {
|
|
5266
|
+
if (e.key === "Enter") {
|
|
5267
|
+
e.preventDefault();
|
|
5268
|
+
e.stopPropagation();
|
|
5269
|
+
apply(f.id, e.currentTarget.value);
|
|
5270
|
+
}
|
|
5271
|
+
}
|
|
5272
|
+
},
|
|
5273
|
+
`${f.id}:${round(bar[f.id], f.unit)}`
|
|
5274
|
+
),
|
|
5275
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-500", children: f.unit }),
|
|
5276
|
+
f.id === "scaleX" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
5277
|
+
"button",
|
|
5278
|
+
{
|
|
5279
|
+
type: "button",
|
|
5280
|
+
"aria-label": "Keep width and height proportional",
|
|
5281
|
+
"aria-pressed": tool.proportional,
|
|
5282
|
+
className: chip2(tool.proportional),
|
|
5283
|
+
onClick: () => {
|
|
5284
|
+
tool.proportional = !tool.proportional;
|
|
5285
|
+
setTick((n) => n + 1);
|
|
5286
|
+
},
|
|
5287
|
+
children: "\u26D3\uFE0E"
|
|
5288
|
+
}
|
|
5289
|
+
)
|
|
5290
|
+
] }, f.id)),
|
|
5291
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
5292
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: "Interpolation" }),
|
|
5293
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
5294
|
+
"select",
|
|
5295
|
+
{
|
|
5296
|
+
"aria-label": "Interpolation",
|
|
5297
|
+
value: tool.interpolation,
|
|
5298
|
+
onChange: (e) => tool.setInterpolation(e.target.value),
|
|
5299
|
+
className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
|
|
5300
|
+
children: import_image_editor11.INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: i, children: i[0].toUpperCase() + i.slice(1) }, i))
|
|
5301
|
+
}
|
|
5302
|
+
)
|
|
5303
|
+
] }),
|
|
5304
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", title: "Commit (Enter)", className: "px-2 py-1 rounded bg-emerald-600 text-white hover:bg-emerald-500", onClick: () => tool.commit(), children: "Commit" }),
|
|
5305
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", title: "Cancel (Esc)", className: chip2(false), onClick: () => tool.cancel(), children: "Cancel" }),
|
|
5306
|
+
tool.error && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { role: "alert", className: "text-rose-400", children: tool.error })
|
|
5307
|
+
] });
|
|
5308
|
+
};
|
|
5309
|
+
|
|
5012
5310
|
// src/image-editor/ImageEditor.tsx
|
|
5013
|
-
var
|
|
5311
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
5014
5312
|
var ImageEditor = ({
|
|
5015
5313
|
editor: externalEditor,
|
|
5016
5314
|
src,
|
|
@@ -5025,35 +5323,47 @@ var ImageEditor = ({
|
|
|
5025
5323
|
const internalEditor = useImageEditor({ image: src });
|
|
5026
5324
|
const editor = externalEditor || internalEditor;
|
|
5027
5325
|
const { state, controller } = editor;
|
|
5028
|
-
const legacyProcess = (0,
|
|
5029
|
-
const canvasRef = (0,
|
|
5030
|
-
const containerRef = (0,
|
|
5031
|
-
const [activeTab, setActiveTab] = (0,
|
|
5032
|
-
const [activeCropRatio, setActiveCropRatio] = (0,
|
|
5033
|
-
const [selectionOptions, setSelectionOptions] = (0,
|
|
5034
|
-
const selectionOptionsRef = (0,
|
|
5326
|
+
const legacyProcess = (0, import_image_editor12.normalizeProcessVersion)(state.adjustments.process) < import_image_editor12.LATEST_PROCESS_VERSION;
|
|
5327
|
+
const canvasRef = (0, import_react44.useRef)(null);
|
|
5328
|
+
const containerRef = (0, import_react44.useRef)(null);
|
|
5329
|
+
const [activeTab, setActiveTab] = (0, import_react44.useState)("crop");
|
|
5330
|
+
const [activeCropRatio, setActiveCropRatio] = (0, import_react44.useState)(null);
|
|
5331
|
+
const [selectionOptions, setSelectionOptions] = (0, import_react44.useState)(import_image_editor12.DEFAULT_SELECTION_TOOL_OPTIONS);
|
|
5332
|
+
const selectionOptionsRef = (0, import_react44.useRef)(selectionOptions);
|
|
5035
5333
|
selectionOptionsRef.current = selectionOptions;
|
|
5036
|
-
const selectionGestureRef = (0,
|
|
5334
|
+
const selectionGestureRef = (0, import_react44.useRef)(null);
|
|
5037
5335
|
if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
|
|
5038
|
-
selectionGestureRef.current = new
|
|
5336
|
+
selectionGestureRef.current = new import_image_editor12.SelectionGesture(controller, () => selectionOptionsRef.current);
|
|
5039
5337
|
}
|
|
5040
|
-
const selectionDraftRef = (0,
|
|
5041
|
-
const [selectionError, setSelectionError] = (0,
|
|
5042
|
-
const paintGestureRef = (0,
|
|
5043
|
-
const paintControllerRef = (0,
|
|
5338
|
+
const selectionDraftRef = (0, import_react44.useRef)(null);
|
|
5339
|
+
const [selectionError, setSelectionError] = (0, import_react44.useState)(null);
|
|
5340
|
+
const paintGestureRef = (0, import_react44.useRef)(null);
|
|
5341
|
+
const paintControllerRef = (0, import_react44.useRef)(controller);
|
|
5044
5342
|
if (!paintGestureRef.current || paintControllerRef.current !== controller) {
|
|
5045
|
-
paintGestureRef.current = new
|
|
5343
|
+
paintGestureRef.current = new import_image_editor12.PaintGesture(controller);
|
|
5046
5344
|
paintControllerRef.current = controller;
|
|
5047
5345
|
}
|
|
5048
|
-
const brushCursorRef = (0,
|
|
5049
|
-
const [paintError, setPaintError] = (0,
|
|
5050
|
-
const
|
|
5051
|
-
const
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5346
|
+
const brushCursorRef = (0, import_react44.useRef)(null);
|
|
5347
|
+
const [paintError, setPaintError] = (0, import_react44.useState)(null);
|
|
5348
|
+
const transformToolRef = (0, import_react44.useRef)(null);
|
|
5349
|
+
const transformControllerRef = (0, import_react44.useRef)(controller);
|
|
5350
|
+
if (!transformToolRef.current || transformControllerRef.current !== controller) {
|
|
5351
|
+
transformToolRef.current?.cancel();
|
|
5352
|
+
transformToolRef.current = new import_image_editor12.FreeTransformTool(controller, {
|
|
5353
|
+
schedule: (run) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(run) : run()
|
|
5354
|
+
});
|
|
5355
|
+
transformControllerRef.current = controller;
|
|
5356
|
+
}
|
|
5357
|
+
const transformTool = transformToolRef.current;
|
|
5358
|
+
const [, setTransformTick] = (0, import_react44.useState)(0);
|
|
5359
|
+
const [transformCursor, setTransformCursor] = (0, import_react44.useState)("default");
|
|
5360
|
+
const [inpaintPrompt, setInpaintPrompt] = (0, import_react44.useState)("");
|
|
5361
|
+
const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react44.useState)("annotations");
|
|
5362
|
+
const [isRemovingBg, setIsRemovingBg] = (0, import_react44.useState)(false);
|
|
5363
|
+
const [isInpainting, setIsInpainting] = (0, import_react44.useState)(false);
|
|
5364
|
+
const [aiError, setAiError] = (0, import_react44.useState)(null);
|
|
5365
|
+
const [aiSuccess, setAiSuccess] = (0, import_react44.useState)(null);
|
|
5366
|
+
const [aiTarget, setAiTarget] = (0, import_react44.useState)("auto");
|
|
5057
5367
|
const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
|
|
5058
5368
|
const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
|
|
5059
5369
|
const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
|
|
@@ -5116,18 +5426,18 @@ var ImageEditor = ({
|
|
|
5116
5426
|
setIsInpainting(false);
|
|
5117
5427
|
}
|
|
5118
5428
|
};
|
|
5119
|
-
const [activeColor, setActiveColor] = (0,
|
|
5120
|
-
const [strokeWidth, setStrokeWidth] = (0,
|
|
5121
|
-
const [fontSize, setFontSize] = (0,
|
|
5122
|
-
const [textInput, setTextInput] = (0,
|
|
5123
|
-
const draftAnnotationRef = (0,
|
|
5124
|
-
const draftCropRef = (0,
|
|
5125
|
-
const cropDragInfoRef = (0,
|
|
5126
|
-
const annotationDragInfoRef = (0,
|
|
5127
|
-
const isDrawingRef = (0,
|
|
5128
|
-
const currentPathRef = (0,
|
|
5129
|
-
const dragStartPointRef = (0,
|
|
5130
|
-
const renderCanvas = (0,
|
|
5429
|
+
const [activeColor, setActiveColor] = (0, import_react44.useState)("#ef4444");
|
|
5430
|
+
const [strokeWidth, setStrokeWidth] = (0, import_react44.useState)(3);
|
|
5431
|
+
const [fontSize, setFontSize] = (0, import_react44.useState)(24);
|
|
5432
|
+
const [textInput, setTextInput] = (0, import_react44.useState)("");
|
|
5433
|
+
const draftAnnotationRef = (0, import_react44.useRef)(null);
|
|
5434
|
+
const draftCropRef = (0, import_react44.useRef)(null);
|
|
5435
|
+
const cropDragInfoRef = (0, import_react44.useRef)(null);
|
|
5436
|
+
const annotationDragInfoRef = (0, import_react44.useRef)(null);
|
|
5437
|
+
const isDrawingRef = (0, import_react44.useRef)(false);
|
|
5438
|
+
const currentPathRef = (0, import_react44.useRef)([]);
|
|
5439
|
+
const dragStartPointRef = (0, import_react44.useRef)(null);
|
|
5440
|
+
const renderCanvas = (0, import_react44.useCallback)(
|
|
5131
5441
|
async (draftAnnotation, draftCrop) => {
|
|
5132
5442
|
const canvas = canvasRef.current;
|
|
5133
5443
|
const container = containerRef.current;
|
|
@@ -5143,12 +5453,64 @@ var ImageEditor = ({
|
|
|
5143
5453
|
draftAnnotation: draftAnnotation !== void 0 ? draftAnnotation : draftAnnotationRef.current,
|
|
5144
5454
|
draftCrop: draftCrop !== void 0 ? draftCrop : draftCropRef.current,
|
|
5145
5455
|
draftSelectionPath: selectionDraftRef.current,
|
|
5146
|
-
brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null
|
|
5456
|
+
brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" && !transformTool.active ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null,
|
|
5457
|
+
freeTransform: transformTool.overlay()
|
|
5147
5458
|
});
|
|
5148
5459
|
},
|
|
5149
|
-
[controller, activeTab]
|
|
5460
|
+
[controller, activeTab, transformTool]
|
|
5150
5461
|
);
|
|
5151
|
-
(0,
|
|
5462
|
+
(0, import_react44.useEffect)(() => transformTool.subscribe(() => {
|
|
5463
|
+
setTransformTick((n) => n + 1);
|
|
5464
|
+
void renderCanvas();
|
|
5465
|
+
}), [transformTool, renderCanvas]);
|
|
5466
|
+
const transformPoint = (e) => {
|
|
5467
|
+
const canvas = canvasRef.current;
|
|
5468
|
+
const rect = canvas.getBoundingClientRect();
|
|
5469
|
+
const sx = rect.width > 0 ? canvas.width / rect.width : 1;
|
|
5470
|
+
const sy = rect.height > 0 ? canvas.height / rect.height : 1;
|
|
5471
|
+
const s = controller.getState();
|
|
5472
|
+
const cropping = activeTab === "crop";
|
|
5473
|
+
const projection = (0, import_image_editor12.getViewportProjection)(s, canvas.width, canvas.height, cropping);
|
|
5474
|
+
const pt = (0, import_image_editor12.canvasToImagePoint)({ x: (e.clientX - rect.left) * sx, y: (e.clientY - rect.top) * sy }, s, canvas.width, canvas.height, cropping);
|
|
5475
|
+
transformTool.setView(projection.scale);
|
|
5476
|
+
return { pt, tolerance: 6 / (projection.scale || 1) };
|
|
5477
|
+
};
|
|
5478
|
+
const handleTransformPointerDown = (e) => {
|
|
5479
|
+
if (!transformTool.active) return false;
|
|
5480
|
+
if (e.button !== 0) return true;
|
|
5481
|
+
e.preventDefault();
|
|
5482
|
+
try {
|
|
5483
|
+
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
5484
|
+
} catch {
|
|
5485
|
+
}
|
|
5486
|
+
const { pt, tolerance } = transformPoint(e);
|
|
5487
|
+
transformTool.down(pt, tolerance);
|
|
5488
|
+
return true;
|
|
5489
|
+
};
|
|
5490
|
+
const handleTransformPointerMove = (e) => {
|
|
5491
|
+
if (!transformTool.active) return false;
|
|
5492
|
+
const { pt, tolerance } = transformPoint(e);
|
|
5493
|
+
if (e.buttons & 1) transformTool.move(pt, e);
|
|
5494
|
+
else {
|
|
5495
|
+
const over = transformTool.hit(pt, tolerance);
|
|
5496
|
+
setTransformCursor(transformTool.cursor(over));
|
|
5497
|
+
}
|
|
5498
|
+
return true;
|
|
5499
|
+
};
|
|
5500
|
+
const handleTransformPointerUp = () => {
|
|
5501
|
+
if (!transformTool.active) return false;
|
|
5502
|
+
transformTool.up();
|
|
5503
|
+
return true;
|
|
5504
|
+
};
|
|
5505
|
+
(0, import_react44.useEffect)(() => {
|
|
5506
|
+
if (typeof window === "undefined") return;
|
|
5507
|
+
const onKey = (e) => {
|
|
5508
|
+
if (transformTool.key(e)) e.preventDefault();
|
|
5509
|
+
};
|
|
5510
|
+
window.addEventListener("keydown", onKey);
|
|
5511
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
5512
|
+
}, [transformTool]);
|
|
5513
|
+
(0, import_react44.useEffect)(() => {
|
|
5152
5514
|
const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
|
|
5153
5515
|
const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
|
|
5154
5516
|
const animId = raf(() => {
|
|
@@ -5156,12 +5518,12 @@ var ImageEditor = ({
|
|
|
5156
5518
|
});
|
|
5157
5519
|
return () => caf(animId);
|
|
5158
5520
|
}, [renderCanvas, state]);
|
|
5159
|
-
(0,
|
|
5521
|
+
(0, import_react44.useEffect)(() => {
|
|
5160
5522
|
if (activeTab === "crop" && editor.state.activeTool !== "crop") {
|
|
5161
5523
|
editor.setTool("crop");
|
|
5162
5524
|
}
|
|
5163
5525
|
}, [activeTab, editor]);
|
|
5164
|
-
(0,
|
|
5526
|
+
(0, import_react44.useEffect)(() => {
|
|
5165
5527
|
const container = containerRef.current;
|
|
5166
5528
|
if (!container) return;
|
|
5167
5529
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -5197,11 +5559,12 @@ var ImageEditor = ({
|
|
|
5197
5559
|
const sy = rect.height > 0 ? canvas.height / rect.height : 1;
|
|
5198
5560
|
const s = controller.getState();
|
|
5199
5561
|
return list.map((ev) => ({
|
|
5200
|
-
...(0,
|
|
5201
|
-
pressure: (0,
|
|
5562
|
+
...(0, import_image_editor12.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
|
|
5563
|
+
pressure: (0, import_image_editor12.pointerPressure)(ev)
|
|
5202
5564
|
}));
|
|
5203
5565
|
};
|
|
5204
5566
|
const handlePaintPointerDown = (e) => {
|
|
5567
|
+
if (handleTransformPointerDown(e)) return;
|
|
5205
5568
|
if (activeTab !== "paint" || e.button !== 0) return;
|
|
5206
5569
|
e.preventDefault();
|
|
5207
5570
|
try {
|
|
@@ -5212,6 +5575,7 @@ var ImageEditor = ({
|
|
|
5212
5575
|
setPaintError(paintGestureRef.current.down(first));
|
|
5213
5576
|
};
|
|
5214
5577
|
const handlePaintPointerMove = (e) => {
|
|
5578
|
+
if (handleTransformPointerMove(e)) return;
|
|
5215
5579
|
if (activeTab !== "paint") return;
|
|
5216
5580
|
const samples = paintSamples(e);
|
|
5217
5581
|
brushCursorRef.current = samples[samples.length - 1] ?? null;
|
|
@@ -5219,6 +5583,7 @@ var ImageEditor = ({
|
|
|
5219
5583
|
else void renderCanvas();
|
|
5220
5584
|
};
|
|
5221
5585
|
const handlePaintPointerUp = () => {
|
|
5586
|
+
if (handleTransformPointerUp()) return;
|
|
5222
5587
|
if (activeTab !== "paint") return;
|
|
5223
5588
|
const g = paintGestureRef.current;
|
|
5224
5589
|
if (g.active) {
|
|
@@ -5226,21 +5591,21 @@ var ImageEditor = ({
|
|
|
5226
5591
|
if (g.error) setPaintError(g.error);
|
|
5227
5592
|
}
|
|
5228
5593
|
};
|
|
5229
|
-
(0,
|
|
5594
|
+
(0, import_react44.useEffect)(() => {
|
|
5230
5595
|
if (activeTab !== "paint" || typeof window === "undefined") return;
|
|
5231
5596
|
const onKey = (e) => {
|
|
5232
|
-
if ((0,
|
|
5597
|
+
if ((0, import_image_editor12.handlePaintShortcut)(controller, e)) e.preventDefault();
|
|
5233
5598
|
};
|
|
5234
5599
|
window.addEventListener("keydown", onKey);
|
|
5235
5600
|
return () => window.removeEventListener("keydown", onKey);
|
|
5236
5601
|
}, [activeTab, controller]);
|
|
5237
5602
|
const handleMouseDown = (e) => {
|
|
5238
5603
|
const canvas = canvasRef.current;
|
|
5239
|
-
if (!canvas) return;
|
|
5604
|
+
if (!canvas || transformTool.active) return;
|
|
5240
5605
|
const canvasPt = getCanvasEventPoint(e);
|
|
5241
5606
|
if (activeTab === "select") {
|
|
5242
5607
|
const gesture = selectionGestureRef.current;
|
|
5243
|
-
const imgPt = (0,
|
|
5608
|
+
const imgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
5244
5609
|
void gesture.begin(imgPt, e).then(() => setSelectionError(gesture.error));
|
|
5245
5610
|
return;
|
|
5246
5611
|
}
|
|
@@ -5251,8 +5616,8 @@ var ImageEditor = ({
|
|
|
5251
5616
|
width: state.imageDimensions.width,
|
|
5252
5617
|
height: state.imageDimensions.height
|
|
5253
5618
|
};
|
|
5254
|
-
const handle = (0,
|
|
5255
|
-
const startImgPt = (0,
|
|
5619
|
+
const handle = (0, import_image_editor12.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
|
|
5620
|
+
const startImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
|
|
5256
5621
|
if (handle) {
|
|
5257
5622
|
cropDragInfoRef.current = {
|
|
5258
5623
|
handle,
|
|
@@ -5271,12 +5636,12 @@ var ImageEditor = ({
|
|
|
5271
5636
|
return;
|
|
5272
5637
|
}
|
|
5273
5638
|
if (activeTab === "annotate") {
|
|
5274
|
-
const imgPt = (0,
|
|
5639
|
+
const imgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
5275
5640
|
dragStartPointRef.current = imgPt;
|
|
5276
5641
|
if (state.activeTool === "select") {
|
|
5277
5642
|
for (let i = state.annotations.length - 1; i >= 0; i--) {
|
|
5278
5643
|
const ann = state.annotations[i];
|
|
5279
|
-
if ((0,
|
|
5644
|
+
if ((0, import_image_editor12.hitTestAnnotation)(imgPt, ann)) {
|
|
5280
5645
|
editor.selectAnnotation(ann.id);
|
|
5281
5646
|
annotationDragInfoRef.current = {
|
|
5282
5647
|
annId: ann.id,
|
|
@@ -5308,11 +5673,11 @@ var ImageEditor = ({
|
|
|
5308
5673
|
};
|
|
5309
5674
|
const handleMouseMove = (e) => {
|
|
5310
5675
|
const canvas = canvasRef.current;
|
|
5311
|
-
if (!canvas) return;
|
|
5676
|
+
if (!canvas || transformTool.active) return;
|
|
5312
5677
|
const canvasPt = getCanvasEventPoint(e);
|
|
5313
5678
|
if (activeTab === "select") {
|
|
5314
5679
|
const gesture = selectionGestureRef.current;
|
|
5315
|
-
if (gesture.active && gesture.move((0,
|
|
5680
|
+
if (gesture.active && gesture.move((0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
|
|
5316
5681
|
selectionDraftRef.current = gesture.draftPath;
|
|
5317
5682
|
renderCanvas();
|
|
5318
5683
|
}
|
|
@@ -5321,7 +5686,7 @@ var ImageEditor = ({
|
|
|
5321
5686
|
if (activeTab === "crop") {
|
|
5322
5687
|
const drag = cropDragInfoRef.current;
|
|
5323
5688
|
if (drag) {
|
|
5324
|
-
const currentImgPt = (0,
|
|
5689
|
+
const currentImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
|
|
5325
5690
|
let newCrop;
|
|
5326
5691
|
if (drag.handle === "new") {
|
|
5327
5692
|
const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
|
|
@@ -5335,7 +5700,7 @@ var ImageEditor = ({
|
|
|
5335
5700
|
height: Math.round(Math.max(20, maxY - minY))
|
|
5336
5701
|
};
|
|
5337
5702
|
} else {
|
|
5338
|
-
newCrop = (0,
|
|
5703
|
+
newCrop = (0, import_image_editor12.calculateCropDrag)(
|
|
5339
5704
|
drag.startCrop,
|
|
5340
5705
|
drag.handle,
|
|
5341
5706
|
drag.startImgPt,
|
|
@@ -5355,15 +5720,15 @@ var ImageEditor = ({
|
|
|
5355
5720
|
width: state.imageDimensions.width,
|
|
5356
5721
|
height: state.imageDimensions.height
|
|
5357
5722
|
};
|
|
5358
|
-
const handle = (0,
|
|
5359
|
-
canvas.style.cursor = (0,
|
|
5723
|
+
const handle = (0, import_image_editor12.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
|
|
5724
|
+
canvas.style.cursor = (0, import_image_editor12.getCropCursor)(handle, state.transform);
|
|
5360
5725
|
}
|
|
5361
5726
|
return;
|
|
5362
5727
|
}
|
|
5363
5728
|
if (activeTab === "annotate") {
|
|
5364
5729
|
if (annotationDragInfoRef.current) {
|
|
5365
5730
|
const drag = annotationDragInfoRef.current;
|
|
5366
|
-
const currentImgPt2 = (0,
|
|
5731
|
+
const currentImgPt2 = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
5367
5732
|
const dx = currentImgPt2.x - drag.startImgPt.x;
|
|
5368
5733
|
const dy = currentImgPt2.y - drag.startImgPt.y;
|
|
5369
5734
|
editor.updateAnnotation(drag.annId, {
|
|
@@ -5375,10 +5740,10 @@ var ImageEditor = ({
|
|
|
5375
5740
|
const startPt = dragStartPointRef.current;
|
|
5376
5741
|
if (!startPt) {
|
|
5377
5742
|
if (state.activeTool === "select") {
|
|
5378
|
-
const imgPt = (0,
|
|
5743
|
+
const imgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
5379
5744
|
let hovered = false;
|
|
5380
5745
|
for (let i = state.annotations.length - 1; i >= 0; i--) {
|
|
5381
|
-
if ((0,
|
|
5746
|
+
if ((0, import_image_editor12.hitTestAnnotation)(imgPt, state.annotations[i])) {
|
|
5382
5747
|
hovered = true;
|
|
5383
5748
|
break;
|
|
5384
5749
|
}
|
|
@@ -5389,7 +5754,7 @@ var ImageEditor = ({
|
|
|
5389
5754
|
}
|
|
5390
5755
|
return;
|
|
5391
5756
|
}
|
|
5392
|
-
const currentImgPt = (0,
|
|
5757
|
+
const currentImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
5393
5758
|
if (state.activeTool === "pen" && isDrawingRef.current) {
|
|
5394
5759
|
currentPathRef.current.push(currentImgPt);
|
|
5395
5760
|
const draft = {
|
|
@@ -5464,12 +5829,12 @@ var ImageEditor = ({
|
|
|
5464
5829
|
};
|
|
5465
5830
|
const handleMouseUp = (e) => {
|
|
5466
5831
|
const canvas = canvasRef.current;
|
|
5467
|
-
if (!canvas) return;
|
|
5832
|
+
if (!canvas || transformTool.active) return;
|
|
5468
5833
|
const canvasPt = getCanvasEventPoint(e);
|
|
5469
5834
|
if (activeTab === "select") {
|
|
5470
5835
|
const gesture = selectionGestureRef.current;
|
|
5471
5836
|
if (gesture.active) {
|
|
5472
|
-
gesture.end((0,
|
|
5837
|
+
gesture.end((0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
|
|
5473
5838
|
selectionDraftRef.current = null;
|
|
5474
5839
|
renderCanvas();
|
|
5475
5840
|
}
|
|
@@ -5493,7 +5858,7 @@ var ImageEditor = ({
|
|
|
5493
5858
|
}
|
|
5494
5859
|
const startPt = dragStartPointRef.current;
|
|
5495
5860
|
if (startPt) {
|
|
5496
|
-
const currentImgPt = (0,
|
|
5861
|
+
const currentImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
5497
5862
|
if (state.activeTool === "pen" && isDrawingRef.current) {
|
|
5498
5863
|
if (currentPathRef.current.length > 1) {
|
|
5499
5864
|
editor.addAnnotation({
|
|
@@ -5589,15 +5954,15 @@ var ImageEditor = ({
|
|
|
5589
5954
|
link.click();
|
|
5590
5955
|
}
|
|
5591
5956
|
};
|
|
5592
|
-
return /* @__PURE__ */ (0,
|
|
5957
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
5593
5958
|
"div",
|
|
5594
5959
|
{
|
|
5595
5960
|
className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
|
|
5596
5961
|
style,
|
|
5597
5962
|
children: [
|
|
5598
|
-
/* @__PURE__ */ (0,
|
|
5599
|
-
/* @__PURE__ */ (0,
|
|
5600
|
-
/* @__PURE__ */ (0,
|
|
5963
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.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: [
|
|
5964
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
|
|
5965
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5601
5966
|
"button",
|
|
5602
5967
|
{
|
|
5603
5968
|
type: "button",
|
|
@@ -5609,7 +5974,7 @@ var ImageEditor = ({
|
|
|
5609
5974
|
children: "Transform & Crop"
|
|
5610
5975
|
}
|
|
5611
5976
|
),
|
|
5612
|
-
/* @__PURE__ */ (0,
|
|
5977
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5613
5978
|
"button",
|
|
5614
5979
|
{
|
|
5615
5980
|
type: "button",
|
|
@@ -5621,7 +5986,7 @@ var ImageEditor = ({
|
|
|
5621
5986
|
children: "Adjustments"
|
|
5622
5987
|
}
|
|
5623
5988
|
),
|
|
5624
|
-
/* @__PURE__ */ (0,
|
|
5989
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5625
5990
|
"button",
|
|
5626
5991
|
{
|
|
5627
5992
|
type: "button",
|
|
@@ -5633,7 +5998,7 @@ var ImageEditor = ({
|
|
|
5633
5998
|
children: "Layers"
|
|
5634
5999
|
}
|
|
5635
6000
|
),
|
|
5636
|
-
/* @__PURE__ */ (0,
|
|
6001
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5637
6002
|
"button",
|
|
5638
6003
|
{
|
|
5639
6004
|
type: "button",
|
|
@@ -5645,7 +6010,7 @@ var ImageEditor = ({
|
|
|
5645
6010
|
children: "Paint"
|
|
5646
6011
|
}
|
|
5647
6012
|
),
|
|
5648
|
-
/* @__PURE__ */ (0,
|
|
6013
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5649
6014
|
"button",
|
|
5650
6015
|
{
|
|
5651
6016
|
type: "button",
|
|
@@ -5657,7 +6022,7 @@ var ImageEditor = ({
|
|
|
5657
6022
|
children: "Select & Mask"
|
|
5658
6023
|
}
|
|
5659
6024
|
),
|
|
5660
|
-
/* @__PURE__ */ (0,
|
|
6025
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5661
6026
|
"button",
|
|
5662
6027
|
{
|
|
5663
6028
|
type: "button",
|
|
@@ -5669,7 +6034,7 @@ var ImageEditor = ({
|
|
|
5669
6034
|
children: "Annotations"
|
|
5670
6035
|
}
|
|
5671
6036
|
),
|
|
5672
|
-
/* @__PURE__ */ (0,
|
|
6037
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5673
6038
|
"button",
|
|
5674
6039
|
{
|
|
5675
6040
|
type: "button",
|
|
@@ -5681,7 +6046,7 @@ var ImageEditor = ({
|
|
|
5681
6046
|
children: "Depth Mask"
|
|
5682
6047
|
}
|
|
5683
6048
|
),
|
|
5684
|
-
/* @__PURE__ */ (0,
|
|
6049
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
5685
6050
|
"button",
|
|
5686
6051
|
{
|
|
5687
6052
|
type: "button",
|
|
@@ -5691,14 +6056,14 @@ var ImageEditor = ({
|
|
|
5691
6056
|
},
|
|
5692
6057
|
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"}`,
|
|
5693
6058
|
children: [
|
|
5694
|
-
/* @__PURE__ */ (0,
|
|
6059
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.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_runtime27.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" }) }),
|
|
5695
6060
|
"AI Tools"
|
|
5696
6061
|
]
|
|
5697
6062
|
}
|
|
5698
6063
|
)
|
|
5699
6064
|
] }),
|
|
5700
|
-
/* @__PURE__ */ (0,
|
|
5701
|
-
/* @__PURE__ */ (0,
|
|
6065
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
6066
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5702
6067
|
"button",
|
|
5703
6068
|
{
|
|
5704
6069
|
type: "button",
|
|
@@ -5709,7 +6074,7 @@ var ImageEditor = ({
|
|
|
5709
6074
|
children: "\u21A9"
|
|
5710
6075
|
}
|
|
5711
6076
|
),
|
|
5712
|
-
/* @__PURE__ */ (0,
|
|
6077
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5713
6078
|
"button",
|
|
5714
6079
|
{
|
|
5715
6080
|
type: "button",
|
|
@@ -5720,7 +6085,7 @@ var ImageEditor = ({
|
|
|
5720
6085
|
children: "\u21AA"
|
|
5721
6086
|
}
|
|
5722
6087
|
),
|
|
5723
|
-
/* @__PURE__ */ (0,
|
|
6088
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5724
6089
|
"button",
|
|
5725
6090
|
{
|
|
5726
6091
|
type: "button",
|
|
@@ -5729,8 +6094,8 @@ var ImageEditor = ({
|
|
|
5729
6094
|
children: "Reset"
|
|
5730
6095
|
}
|
|
5731
6096
|
),
|
|
5732
|
-
/* @__PURE__ */ (0,
|
|
5733
|
-
/* @__PURE__ */ (0,
|
|
6097
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
6098
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5734
6099
|
"button",
|
|
5735
6100
|
{
|
|
5736
6101
|
type: "button",
|
|
@@ -5740,11 +6105,11 @@ var ImageEditor = ({
|
|
|
5740
6105
|
children: "-"
|
|
5741
6106
|
}
|
|
5742
6107
|
),
|
|
5743
|
-
/* @__PURE__ */ (0,
|
|
6108
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
|
|
5744
6109
|
Math.round(state.zoom * 100),
|
|
5745
6110
|
"%"
|
|
5746
6111
|
] }),
|
|
5747
|
-
/* @__PURE__ */ (0,
|
|
6112
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5748
6113
|
"button",
|
|
5749
6114
|
{
|
|
5750
6115
|
type: "button",
|
|
@@ -5754,8 +6119,8 @@ var ImageEditor = ({
|
|
|
5754
6119
|
children: "+"
|
|
5755
6120
|
}
|
|
5756
6121
|
),
|
|
5757
|
-
/* @__PURE__ */ (0,
|
|
5758
|
-
/* @__PURE__ */ (0,
|
|
6122
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
6123
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5759
6124
|
"button",
|
|
5760
6125
|
{
|
|
5761
6126
|
type: "button",
|
|
@@ -5766,7 +6131,7 @@ var ImageEditor = ({
|
|
|
5766
6131
|
children: "Hold Compare"
|
|
5767
6132
|
}
|
|
5768
6133
|
),
|
|
5769
|
-
/* @__PURE__ */ (0,
|
|
6134
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5770
6135
|
"button",
|
|
5771
6136
|
{
|
|
5772
6137
|
type: "button",
|
|
@@ -5777,13 +6142,15 @@ var ImageEditor = ({
|
|
|
5777
6142
|
)
|
|
5778
6143
|
] })
|
|
5779
6144
|
] }),
|
|
5780
|
-
/* @__PURE__ */ (0,
|
|
5781
|
-
|
|
6145
|
+
transformTool.active && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
|
|
6146
|
+
!transformTool.active && transformTool.error && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { role: "alert", className: "border-b border-rose-900 bg-rose-950/80 px-4 py-1.5 text-xs text-rose-200", children: transformTool.error }),
|
|
6147
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
|
|
6148
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5782
6149
|
"div",
|
|
5783
6150
|
{
|
|
5784
6151
|
ref: containerRef,
|
|
5785
6152
|
className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
|
|
5786
|
-
children: /* @__PURE__ */ (0,
|
|
6153
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5787
6154
|
"canvas",
|
|
5788
6155
|
{
|
|
5789
6156
|
ref: canvasRef,
|
|
@@ -5796,16 +6163,17 @@ var ImageEditor = ({
|
|
|
5796
6163
|
onPointerUp: handlePaintPointerUp,
|
|
5797
6164
|
onPointerCancel: () => paintGestureRef.current?.cancel(),
|
|
5798
6165
|
"data-testid": "image-editor-canvas",
|
|
5799
|
-
|
|
6166
|
+
style: transformTool.active ? { cursor: transformCursor } : void 0,
|
|
6167
|
+
className: `absolute inset-0 w-full h-full block ${transformTool.active ? "touch-none" : activeTab === "paint" ? "touch-none cursor-crosshair" : ""}`
|
|
5800
6168
|
}
|
|
5801
6169
|
)
|
|
5802
6170
|
}
|
|
5803
6171
|
),
|
|
5804
|
-
/* @__PURE__ */ (0,
|
|
5805
|
-
activeTab === "crop" && /* @__PURE__ */ (0,
|
|
5806
|
-
/* @__PURE__ */ (0,
|
|
5807
|
-
/* @__PURE__ */ (0,
|
|
5808
|
-
/* @__PURE__ */ (0,
|
|
6172
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.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: [
|
|
6173
|
+
activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
6174
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
|
|
6175
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
|
|
6176
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5809
6177
|
"button",
|
|
5810
6178
|
{
|
|
5811
6179
|
type: "button",
|
|
@@ -5817,7 +6185,7 @@ var ImageEditor = ({
|
|
|
5817
6185
|
children: "Freeform"
|
|
5818
6186
|
}
|
|
5819
6187
|
),
|
|
5820
|
-
/* @__PURE__ */ (0,
|
|
6188
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5821
6189
|
"button",
|
|
5822
6190
|
{
|
|
5823
6191
|
type: "button",
|
|
@@ -5829,7 +6197,7 @@ var ImageEditor = ({
|
|
|
5829
6197
|
children: "1:1 Square"
|
|
5830
6198
|
}
|
|
5831
6199
|
),
|
|
5832
|
-
/* @__PURE__ */ (0,
|
|
6200
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5833
6201
|
"button",
|
|
5834
6202
|
{
|
|
5835
6203
|
type: "button",
|
|
@@ -5841,7 +6209,7 @@ var ImageEditor = ({
|
|
|
5841
6209
|
children: "4:3 Standard"
|
|
5842
6210
|
}
|
|
5843
6211
|
),
|
|
5844
|
-
/* @__PURE__ */ (0,
|
|
6212
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5845
6213
|
"button",
|
|
5846
6214
|
{
|
|
5847
6215
|
type: "button",
|
|
@@ -5853,7 +6221,7 @@ var ImageEditor = ({
|
|
|
5853
6221
|
children: "16:9 Wide"
|
|
5854
6222
|
}
|
|
5855
6223
|
),
|
|
5856
|
-
/* @__PURE__ */ (0,
|
|
6224
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5857
6225
|
"button",
|
|
5858
6226
|
{
|
|
5859
6227
|
type: "button",
|
|
@@ -5865,7 +6233,7 @@ var ImageEditor = ({
|
|
|
5865
6233
|
children: "3:2 Photo"
|
|
5866
6234
|
}
|
|
5867
6235
|
),
|
|
5868
|
-
/* @__PURE__ */ (0,
|
|
6236
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5869
6237
|
"button",
|
|
5870
6238
|
{
|
|
5871
6239
|
type: "button",
|
|
@@ -5878,10 +6246,10 @@ var ImageEditor = ({
|
|
|
5878
6246
|
}
|
|
5879
6247
|
)
|
|
5880
6248
|
] }),
|
|
5881
|
-
/* @__PURE__ */ (0,
|
|
5882
|
-
/* @__PURE__ */ (0,
|
|
5883
|
-
/* @__PURE__ */ (0,
|
|
5884
|
-
/* @__PURE__ */ (0,
|
|
6249
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
6250
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
|
|
6251
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
6252
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5885
6253
|
"button",
|
|
5886
6254
|
{
|
|
5887
6255
|
type: "button",
|
|
@@ -5890,7 +6258,7 @@ var ImageEditor = ({
|
|
|
5890
6258
|
children: "Rotate -90\xB0"
|
|
5891
6259
|
}
|
|
5892
6260
|
),
|
|
5893
|
-
/* @__PURE__ */ (0,
|
|
6261
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5894
6262
|
"button",
|
|
5895
6263
|
{
|
|
5896
6264
|
type: "button",
|
|
@@ -5899,7 +6267,7 @@ var ImageEditor = ({
|
|
|
5899
6267
|
children: "Rotate +90\xB0"
|
|
5900
6268
|
}
|
|
5901
6269
|
),
|
|
5902
|
-
/* @__PURE__ */ (0,
|
|
6270
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5903
6271
|
"button",
|
|
5904
6272
|
{
|
|
5905
6273
|
type: "button",
|
|
@@ -5908,7 +6276,7 @@ var ImageEditor = ({
|
|
|
5908
6276
|
children: "Flip Horizontal"
|
|
5909
6277
|
}
|
|
5910
6278
|
),
|
|
5911
|
-
/* @__PURE__ */ (0,
|
|
6279
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5912
6280
|
"button",
|
|
5913
6281
|
{
|
|
5914
6282
|
type: "button",
|
|
@@ -5919,10 +6287,10 @@ var ImageEditor = ({
|
|
|
5919
6287
|
)
|
|
5920
6288
|
] })
|
|
5921
6289
|
] }),
|
|
5922
|
-
activeTab === "adjust" && /* @__PURE__ */ (0,
|
|
5923
|
-
/* @__PURE__ */ (0,
|
|
5924
|
-
/* @__PURE__ */ (0,
|
|
5925
|
-
/* @__PURE__ */ (0,
|
|
6290
|
+
activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
6291
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
6292
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
|
|
6293
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5926
6294
|
"button",
|
|
5927
6295
|
{
|
|
5928
6296
|
type: "button",
|
|
@@ -5932,25 +6300,25 @@ var ImageEditor = ({
|
|
|
5932
6300
|
}
|
|
5933
6301
|
)
|
|
5934
6302
|
] }),
|
|
5935
|
-
/* @__PURE__ */ (0,
|
|
5936
|
-
|
|
5937
|
-
/* @__PURE__ */ (0,
|
|
6303
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Histogram, { histogram: editor.histogram }),
|
|
6304
|
+
import_image_editor12.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react44.default.Fragment, { children: [
|
|
6305
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5938
6306
|
ControlSlider,
|
|
5939
6307
|
{
|
|
5940
6308
|
spec,
|
|
5941
|
-
value: (0,
|
|
6309
|
+
value: (0, import_image_editor12.readAdjustmentControls)(state.adjustments)[spec.id],
|
|
5942
6310
|
disabled: spec.requiresProcess !== void 0 && legacyProcess,
|
|
5943
6311
|
onChange: (v) => editor.setAdjustments({ [spec.id]: v })
|
|
5944
6312
|
}
|
|
5945
6313
|
),
|
|
5946
|
-
spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0,
|
|
6314
|
+
spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
5947
6315
|
"div",
|
|
5948
6316
|
{
|
|
5949
6317
|
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",
|
|
5950
6318
|
"data-testid": "image-editor-process-notice",
|
|
5951
6319
|
children: [
|
|
5952
|
-
/* @__PURE__ */ (0,
|
|
5953
|
-
/* @__PURE__ */ (0,
|
|
6320
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
|
|
6321
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5954
6322
|
"button",
|
|
5955
6323
|
{
|
|
5956
6324
|
type: "button",
|
|
@@ -5963,7 +6331,7 @@ var ImageEditor = ({
|
|
|
5963
6331
|
}
|
|
5964
6332
|
)
|
|
5965
6333
|
] }, spec.id)),
|
|
5966
|
-
/* @__PURE__ */ (0,
|
|
6334
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5967
6335
|
AdjustmentLayersPanel,
|
|
5968
6336
|
{
|
|
5969
6337
|
controller,
|
|
@@ -5972,19 +6340,41 @@ var ImageEditor = ({
|
|
|
5972
6340
|
}
|
|
5973
6341
|
) })
|
|
5974
6342
|
] }),
|
|
5975
|
-
activeTab === "layers" && /* @__PURE__ */ (0,
|
|
5976
|
-
/* @__PURE__ */ (0,
|
|
5977
|
-
/* @__PURE__ */ (0,
|
|
6343
|
+
activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
6344
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
|
|
6345
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6346
|
+
"button",
|
|
6347
|
+
{
|
|
6348
|
+
type: "button",
|
|
6349
|
+
title: "Edit \u203A Free Transform (Ctrl/Cmd+T): the selected pixels, or the whole active layer",
|
|
6350
|
+
className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
|
|
6351
|
+
disabled: transformTool.active,
|
|
6352
|
+
onClick: () => transformTool.begin(),
|
|
6353
|
+
children: "Free Transform"
|
|
6354
|
+
}
|
|
6355
|
+
),
|
|
6356
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(LayersPanel, { controller })
|
|
5978
6357
|
] }),
|
|
5979
|
-
activeTab === "paint" && /* @__PURE__ */ (0,
|
|
5980
|
-
/* @__PURE__ */ (0,
|
|
5981
|
-
/* @__PURE__ */ (0,
|
|
5982
|
-
|
|
5983
|
-
|
|
6358
|
+
activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
6359
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
|
|
6360
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(BrushOptionsBar, { controller }),
|
|
6361
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6362
|
+
"button",
|
|
6363
|
+
{
|
|
6364
|
+
type: "button",
|
|
6365
|
+
title: "Edit \u203A Free Transform (Ctrl/Cmd+T): the selected pixels, or the whole active layer",
|
|
6366
|
+
className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start",
|
|
6367
|
+
disabled: transformTool.active,
|
|
6368
|
+
onClick: () => transformTool.begin(),
|
|
6369
|
+
children: "Free Transform"
|
|
6370
|
+
}
|
|
6371
|
+
),
|
|
6372
|
+
paintError && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
|
|
6373
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(LayersPanel, { controller }) })
|
|
5984
6374
|
] }),
|
|
5985
|
-
activeTab === "annotate" && /* @__PURE__ */ (0,
|
|
5986
|
-
/* @__PURE__ */ (0,
|
|
5987
|
-
/* @__PURE__ */ (0,
|
|
6375
|
+
activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
6376
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
|
|
6377
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5988
6378
|
"button",
|
|
5989
6379
|
{
|
|
5990
6380
|
type: "button",
|
|
@@ -5994,9 +6384,9 @@ var ImageEditor = ({
|
|
|
5994
6384
|
},
|
|
5995
6385
|
t
|
|
5996
6386
|
)) }),
|
|
5997
|
-
/* @__PURE__ */ (0,
|
|
5998
|
-
/* @__PURE__ */ (0,
|
|
5999
|
-
/* @__PURE__ */ (0,
|
|
6387
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
6388
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("label", { className: "text-slate-400", children: "Color:" }),
|
|
6389
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6000
6390
|
"input",
|
|
6001
6391
|
{
|
|
6002
6392
|
type: "color",
|
|
@@ -6005,15 +6395,15 @@ var ImageEditor = ({
|
|
|
6005
6395
|
className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
|
|
6006
6396
|
}
|
|
6007
6397
|
),
|
|
6008
|
-
/* @__PURE__ */ (0,
|
|
6009
|
-
/* @__PURE__ */ (0,
|
|
6010
|
-
/* @__PURE__ */ (0,
|
|
6011
|
-
/* @__PURE__ */ (0,
|
|
6398
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex-1 ml-2", children: [
|
|
6399
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
|
|
6400
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Width:" }),
|
|
6401
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "font-mono", children: [
|
|
6012
6402
|
strokeWidth,
|
|
6013
6403
|
"px"
|
|
6014
6404
|
] })
|
|
6015
6405
|
] }),
|
|
6016
|
-
/* @__PURE__ */ (0,
|
|
6406
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6017
6407
|
"input",
|
|
6018
6408
|
{
|
|
6019
6409
|
type: "range",
|
|
@@ -6026,10 +6416,10 @@ var ImageEditor = ({
|
|
|
6026
6416
|
)
|
|
6027
6417
|
] })
|
|
6028
6418
|
] }),
|
|
6029
|
-
/* @__PURE__ */ (0,
|
|
6030
|
-
/* @__PURE__ */ (0,
|
|
6031
|
-
/* @__PURE__ */ (0,
|
|
6032
|
-
/* @__PURE__ */ (0,
|
|
6419
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
6420
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
|
|
6421
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex gap-2", children: [
|
|
6422
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6033
6423
|
"input",
|
|
6034
6424
|
{
|
|
6035
6425
|
type: "text",
|
|
@@ -6040,7 +6430,7 @@ var ImageEditor = ({
|
|
|
6040
6430
|
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"
|
|
6041
6431
|
}
|
|
6042
6432
|
),
|
|
6043
|
-
/* @__PURE__ */ (0,
|
|
6433
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6044
6434
|
"button",
|
|
6045
6435
|
{
|
|
6046
6436
|
type: "button",
|
|
@@ -6050,14 +6440,14 @@ var ImageEditor = ({
|
|
|
6050
6440
|
}
|
|
6051
6441
|
)
|
|
6052
6442
|
] }),
|
|
6053
|
-
/* @__PURE__ */ (0,
|
|
6054
|
-
/* @__PURE__ */ (0,
|
|
6055
|
-
/* @__PURE__ */ (0,
|
|
6443
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
|
|
6444
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Font Size:" }),
|
|
6445
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "font-mono", children: [
|
|
6056
6446
|
fontSize,
|
|
6057
6447
|
"px"
|
|
6058
6448
|
] })
|
|
6059
6449
|
] }),
|
|
6060
|
-
/* @__PURE__ */ (0,
|
|
6450
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6061
6451
|
"input",
|
|
6062
6452
|
{
|
|
6063
6453
|
type: "range",
|
|
@@ -6068,14 +6458,14 @@ var ImageEditor = ({
|
|
|
6068
6458
|
className: "w-full accent-indigo-500"
|
|
6069
6459
|
}
|
|
6070
6460
|
),
|
|
6071
|
-
/* @__PURE__ */ (0,
|
|
6072
|
-
/* @__PURE__ */ (0,
|
|
6073
|
-
/* @__PURE__ */ (0,
|
|
6461
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
6462
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
6463
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "text-slate-400", children: [
|
|
6074
6464
|
"Layers (",
|
|
6075
6465
|
state.annotations.length,
|
|
6076
6466
|
")"
|
|
6077
6467
|
] }),
|
|
6078
|
-
state.selectedAnnotationId && /* @__PURE__ */ (0,
|
|
6468
|
+
state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6079
6469
|
"button",
|
|
6080
6470
|
{
|
|
6081
6471
|
type: "button",
|
|
@@ -6084,7 +6474,7 @@ var ImageEditor = ({
|
|
|
6084
6474
|
children: "Delete Selected"
|
|
6085
6475
|
}
|
|
6086
6476
|
),
|
|
6087
|
-
state.annotations.length > 0 && /* @__PURE__ */ (0,
|
|
6477
|
+
state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6088
6478
|
"button",
|
|
6089
6479
|
{
|
|
6090
6480
|
type: "button",
|
|
@@ -6095,10 +6485,10 @@ var ImageEditor = ({
|
|
|
6095
6485
|
)
|
|
6096
6486
|
] })
|
|
6097
6487
|
] }),
|
|
6098
|
-
activeTab === "depth" && /* @__PURE__ */ (0,
|
|
6099
|
-
/* @__PURE__ */ (0,
|
|
6100
|
-
/* @__PURE__ */ (0,
|
|
6101
|
-
/* @__PURE__ */ (0,
|
|
6488
|
+
activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
6489
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
6490
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
|
|
6491
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6102
6492
|
"button",
|
|
6103
6493
|
{
|
|
6104
6494
|
type: "button",
|
|
@@ -6108,8 +6498,8 @@ var ImageEditor = ({
|
|
|
6108
6498
|
}
|
|
6109
6499
|
)
|
|
6110
6500
|
] }),
|
|
6111
|
-
/* @__PURE__ */ (0,
|
|
6112
|
-
/* @__PURE__ */ (0,
|
|
6501
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
|
|
6502
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6113
6503
|
"input",
|
|
6114
6504
|
{
|
|
6115
6505
|
type: "checkbox",
|
|
@@ -6118,12 +6508,12 @@ var ImageEditor = ({
|
|
|
6118
6508
|
className: "rounded accent-indigo-500"
|
|
6119
6509
|
}
|
|
6120
6510
|
),
|
|
6121
|
-
/* @__PURE__ */ (0,
|
|
6511
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Enable Depth / Alpha Mask" })
|
|
6122
6512
|
] }),
|
|
6123
|
-
state.depthMask.enabled && /* @__PURE__ */ (0,
|
|
6124
|
-
/* @__PURE__ */ (0,
|
|
6125
|
-
/* @__PURE__ */ (0,
|
|
6126
|
-
/* @__PURE__ */ (0,
|
|
6513
|
+
state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
6514
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { children: [
|
|
6515
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
|
|
6516
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6127
6517
|
"input",
|
|
6128
6518
|
{
|
|
6129
6519
|
type: "text",
|
|
@@ -6134,8 +6524,8 @@ var ImageEditor = ({
|
|
|
6134
6524
|
}
|
|
6135
6525
|
)
|
|
6136
6526
|
] }),
|
|
6137
|
-
/* @__PURE__ */ (0,
|
|
6138
|
-
/* @__PURE__ */ (0,
|
|
6527
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex gap-2", children: [
|
|
6528
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6139
6529
|
"button",
|
|
6140
6530
|
{
|
|
6141
6531
|
type: "button",
|
|
@@ -6144,7 +6534,7 @@ var ImageEditor = ({
|
|
|
6144
6534
|
children: "Threshold Mode"
|
|
6145
6535
|
}
|
|
6146
6536
|
),
|
|
6147
|
-
/* @__PURE__ */ (0,
|
|
6537
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6148
6538
|
"button",
|
|
6149
6539
|
{
|
|
6150
6540
|
type: "button",
|
|
@@ -6154,12 +6544,12 @@ var ImageEditor = ({
|
|
|
6154
6544
|
}
|
|
6155
6545
|
)
|
|
6156
6546
|
] }),
|
|
6157
|
-
/* @__PURE__ */ (0,
|
|
6158
|
-
/* @__PURE__ */ (0,
|
|
6159
|
-
/* @__PURE__ */ (0,
|
|
6160
|
-
/* @__PURE__ */ (0,
|
|
6547
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { children: [
|
|
6548
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
6549
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Depth Start (Lower):" }),
|
|
6550
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
|
|
6161
6551
|
] }),
|
|
6162
|
-
/* @__PURE__ */ (0,
|
|
6552
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6163
6553
|
"input",
|
|
6164
6554
|
{
|
|
6165
6555
|
type: "range",
|
|
@@ -6173,12 +6563,12 @@ var ImageEditor = ({
|
|
|
6173
6563
|
}
|
|
6174
6564
|
)
|
|
6175
6565
|
] }),
|
|
6176
|
-
/* @__PURE__ */ (0,
|
|
6177
|
-
/* @__PURE__ */ (0,
|
|
6178
|
-
/* @__PURE__ */ (0,
|
|
6179
|
-
/* @__PURE__ */ (0,
|
|
6566
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { children: [
|
|
6567
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
6568
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Depth Stop (Upper):" }),
|
|
6569
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
|
|
6180
6570
|
] }),
|
|
6181
|
-
/* @__PURE__ */ (0,
|
|
6571
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6182
6572
|
"input",
|
|
6183
6573
|
{
|
|
6184
6574
|
type: "range",
|
|
@@ -6192,12 +6582,12 @@ var ImageEditor = ({
|
|
|
6192
6582
|
}
|
|
6193
6583
|
)
|
|
6194
6584
|
] }),
|
|
6195
|
-
/* @__PURE__ */ (0,
|
|
6196
|
-
/* @__PURE__ */ (0,
|
|
6197
|
-
/* @__PURE__ */ (0,
|
|
6198
|
-
/* @__PURE__ */ (0,
|
|
6585
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { children: [
|
|
6586
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
6587
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Softness:" }),
|
|
6588
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
|
|
6199
6589
|
] }),
|
|
6200
|
-
/* @__PURE__ */ (0,
|
|
6590
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6201
6591
|
"input",
|
|
6202
6592
|
{
|
|
6203
6593
|
type: "range",
|
|
@@ -6209,8 +6599,8 @@ var ImageEditor = ({
|
|
|
6209
6599
|
}
|
|
6210
6600
|
)
|
|
6211
6601
|
] }),
|
|
6212
|
-
/* @__PURE__ */ (0,
|
|
6213
|
-
/* @__PURE__ */ (0,
|
|
6602
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
|
|
6603
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6214
6604
|
"input",
|
|
6215
6605
|
{
|
|
6216
6606
|
type: "checkbox",
|
|
@@ -6219,12 +6609,12 @@ var ImageEditor = ({
|
|
|
6219
6609
|
className: "rounded accent-indigo-500"
|
|
6220
6610
|
}
|
|
6221
6611
|
),
|
|
6222
|
-
/* @__PURE__ */ (0,
|
|
6612
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Invert Mask" })
|
|
6223
6613
|
] })
|
|
6224
6614
|
] })
|
|
6225
6615
|
] }),
|
|
6226
|
-
activeTab === "select" && /* @__PURE__ */ (0,
|
|
6227
|
-
/* @__PURE__ */ (0,
|
|
6616
|
+
activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
6617
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6228
6618
|
SelectionOptionsBar,
|
|
6229
6619
|
{
|
|
6230
6620
|
controller,
|
|
@@ -6234,13 +6624,37 @@ var ImageEditor = ({
|
|
|
6234
6624
|
quickMask: Boolean(state.quickMask)
|
|
6235
6625
|
}
|
|
6236
6626
|
),
|
|
6237
|
-
selectionError && /* @__PURE__ */ (0,
|
|
6238
|
-
/* @__PURE__ */ (0,
|
|
6627
|
+
selectionError && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
|
|
6628
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex gap-1", children: [
|
|
6629
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6630
|
+
"button",
|
|
6631
|
+
{
|
|
6632
|
+
type: "button",
|
|
6633
|
+
title: "Select \u203A Transform Selection: the outline only",
|
|
6634
|
+
className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
|
|
6635
|
+
disabled: transformTool.active,
|
|
6636
|
+
onClick: () => transformTool.begin({ content: "selection-outline" }),
|
|
6637
|
+
children: "Transform Selection"
|
|
6638
|
+
}
|
|
6639
|
+
),
|
|
6640
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6641
|
+
"button",
|
|
6642
|
+
{
|
|
6643
|
+
type: "button",
|
|
6644
|
+
title: "Edit \u203A Free Transform: the selected pixels of the active layer",
|
|
6645
|
+
className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
|
|
6646
|
+
disabled: transformTool.active,
|
|
6647
|
+
onClick: () => transformTool.begin({ content: "selection" }),
|
|
6648
|
+
children: "Free Transform Pixels"
|
|
6649
|
+
}
|
|
6650
|
+
)
|
|
6651
|
+
] }),
|
|
6652
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
|
|
6239
6653
|
] }),
|
|
6240
|
-
activeTab === "ai" && /* @__PURE__ */ (0,
|
|
6241
|
-
/* @__PURE__ */ (0,
|
|
6242
|
-
/* @__PURE__ */ (0,
|
|
6243
|
-
/* @__PURE__ */ (0,
|
|
6654
|
+
activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
6655
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
|
|
6656
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Results go to" }),
|
|
6657
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
6244
6658
|
"select",
|
|
6245
6659
|
{
|
|
6246
6660
|
"aria-label": "AI result target",
|
|
@@ -6248,54 +6662,54 @@ var ImageEditor = ({
|
|
|
6248
6662
|
onChange: (e) => setAiTarget(e.target.value),
|
|
6249
6663
|
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
6250
6664
|
children: [
|
|
6251
|
-
/* @__PURE__ */ (0,
|
|
6252
|
-
/* @__PURE__ */ (0,
|
|
6253
|
-
/* @__PURE__ */ (0,
|
|
6665
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
|
|
6666
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
|
|
6667
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: "replace", children: "Replace image" })
|
|
6254
6668
|
]
|
|
6255
6669
|
}
|
|
6256
6670
|
)
|
|
6257
6671
|
] }),
|
|
6258
|
-
/* @__PURE__ */ (0,
|
|
6259
|
-
/* @__PURE__ */ (0,
|
|
6260
|
-
/* @__PURE__ */ (0,
|
|
6261
|
-
/* @__PURE__ */ (0,
|
|
6672
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
6673
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
6674
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
|
|
6675
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.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_runtime27.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" }) }),
|
|
6262
6676
|
"Background Removal"
|
|
6263
6677
|
] }),
|
|
6264
|
-
isRemovingBg && /* @__PURE__ */ (0,
|
|
6678
|
+
isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime27.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..." })
|
|
6265
6679
|
] }),
|
|
6266
|
-
/* @__PURE__ */ (0,
|
|
6267
|
-
/* @__PURE__ */ (0,
|
|
6680
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
|
|
6681
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6268
6682
|
"button",
|
|
6269
6683
|
{
|
|
6270
6684
|
type: "button",
|
|
6271
6685
|
onClick: handleRemoveBackground,
|
|
6272
6686
|
disabled: isRemovingBg || isInpainting,
|
|
6273
6687
|
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",
|
|
6274
|
-
children: isRemovingBg ? /* @__PURE__ */ (0,
|
|
6275
|
-
/* @__PURE__ */ (0,
|
|
6688
|
+
children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
6689
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
6276
6690
|
"Removing Background..."
|
|
6277
|
-
] }) : /* @__PURE__ */ (0,
|
|
6278
|
-
/* @__PURE__ */ (0,
|
|
6691
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
6692
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.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_runtime27.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" }) }),
|
|
6279
6693
|
"Remove Background"
|
|
6280
6694
|
] })
|
|
6281
6695
|
}
|
|
6282
6696
|
)
|
|
6283
6697
|
] }),
|
|
6284
|
-
/* @__PURE__ */ (0,
|
|
6285
|
-
/* @__PURE__ */ (0,
|
|
6286
|
-
/* @__PURE__ */ (0,
|
|
6287
|
-
/* @__PURE__ */ (0,
|
|
6288
|
-
/* @__PURE__ */ (0,
|
|
6289
|
-
/* @__PURE__ */ (0,
|
|
6698
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
6699
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
6700
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
|
|
6701
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
6702
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.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" }),
|
|
6703
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("path", { d: "m14 7 3 3" })
|
|
6290
6704
|
] }),
|
|
6291
6705
|
"Generative Inpainting"
|
|
6292
6706
|
] }),
|
|
6293
|
-
isInpainting && /* @__PURE__ */ (0,
|
|
6707
|
+
isInpainting && /* @__PURE__ */ (0, import_jsx_runtime27.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..." })
|
|
6294
6708
|
] }),
|
|
6295
|
-
/* @__PURE__ */ (0,
|
|
6296
|
-
/* @__PURE__ */ (0,
|
|
6297
|
-
/* @__PURE__ */ (0,
|
|
6298
|
-
/* @__PURE__ */ (0,
|
|
6709
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
|
|
6710
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
6711
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
|
|
6712
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6299
6713
|
"textarea",
|
|
6300
6714
|
{
|
|
6301
6715
|
id: "ai-inpaint-prompt-react",
|
|
@@ -6307,10 +6721,10 @@ var ImageEditor = ({
|
|
|
6307
6721
|
}
|
|
6308
6722
|
)
|
|
6309
6723
|
] }),
|
|
6310
|
-
/* @__PURE__ */ (0,
|
|
6311
|
-
/* @__PURE__ */ (0,
|
|
6312
|
-
/* @__PURE__ */ (0,
|
|
6313
|
-
/* @__PURE__ */ (0,
|
|
6724
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
6725
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
|
|
6726
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
|
|
6727
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
6314
6728
|
"button",
|
|
6315
6729
|
{
|
|
6316
6730
|
type: "button",
|
|
@@ -6323,7 +6737,7 @@ var ImageEditor = ({
|
|
|
6323
6737
|
]
|
|
6324
6738
|
}
|
|
6325
6739
|
),
|
|
6326
|
-
/* @__PURE__ */ (0,
|
|
6740
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
6327
6741
|
"button",
|
|
6328
6742
|
{
|
|
6329
6743
|
type: "button",
|
|
@@ -6338,25 +6752,25 @@ var ImageEditor = ({
|
|
|
6338
6752
|
)
|
|
6339
6753
|
] })
|
|
6340
6754
|
] }),
|
|
6341
|
-
/* @__PURE__ */ (0,
|
|
6755
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6342
6756
|
"button",
|
|
6343
6757
|
{
|
|
6344
6758
|
type: "button",
|
|
6345
6759
|
onClick: handleInpaint,
|
|
6346
6760
|
disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
|
|
6347
6761
|
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",
|
|
6348
|
-
children: isInpainting ? /* @__PURE__ */ (0,
|
|
6349
|
-
/* @__PURE__ */ (0,
|
|
6762
|
+
children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
6763
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
6350
6764
|
"Generating Inpaint..."
|
|
6351
|
-
] }) : /* @__PURE__ */ (0,
|
|
6352
|
-
/* @__PURE__ */ (0,
|
|
6765
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
6766
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.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_runtime27.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" }) }),
|
|
6353
6767
|
"Apply Inpainting"
|
|
6354
6768
|
] })
|
|
6355
6769
|
}
|
|
6356
6770
|
)
|
|
6357
6771
|
] }),
|
|
6358
|
-
aiError && /* @__PURE__ */ (0,
|
|
6359
|
-
aiSuccess && /* @__PURE__ */ (0,
|
|
6772
|
+
aiError && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
|
|
6773
|
+
aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
|
|
6360
6774
|
] })
|
|
6361
6775
|
] })
|
|
6362
6776
|
] })
|
|
@@ -6366,7 +6780,7 @@ var ImageEditor = ({
|
|
|
6366
6780
|
};
|
|
6367
6781
|
|
|
6368
6782
|
// src/review/useReview.ts
|
|
6369
|
-
var
|
|
6783
|
+
var import_react45 = require("react");
|
|
6370
6784
|
var import_editor12 = require("@pixerate/editor");
|
|
6371
6785
|
var EMPTY_COMMENTS = Object.freeze({
|
|
6372
6786
|
threads: [],
|
|
@@ -6385,23 +6799,23 @@ function isCommentStore(value) {
|
|
|
6385
6799
|
}
|
|
6386
6800
|
function useComments(source) {
|
|
6387
6801
|
const store = isCommentStore(source) ? source : (0, import_editor12.getCommentStore)(source);
|
|
6388
|
-
const subscribe = (0,
|
|
6802
|
+
const subscribe = (0, import_react45.useCallback)(
|
|
6389
6803
|
(onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
|
|
6390
6804
|
[store]
|
|
6391
6805
|
);
|
|
6392
6806
|
const getSnapshot = () => store?.getSnapshot() ?? EMPTY_COMMENTS;
|
|
6393
|
-
const snapshot = (0,
|
|
6394
|
-
return (0,
|
|
6807
|
+
const snapshot = (0, import_react45.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
6808
|
+
return (0, import_react45.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
|
|
6395
6809
|
}
|
|
6396
6810
|
function useTrackChanges(editor) {
|
|
6397
6811
|
const store = (0, import_editor12.getTrackChangesStore)(editor ?? null);
|
|
6398
|
-
const subscribe = (0,
|
|
6812
|
+
const subscribe = (0, import_react45.useCallback)(
|
|
6399
6813
|
(onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
|
|
6400
6814
|
[store]
|
|
6401
6815
|
);
|
|
6402
6816
|
const getSnapshot = () => store?.getSnapshot() ?? EMPTY_TRACK_CHANGES;
|
|
6403
|
-
const snapshot = (0,
|
|
6404
|
-
return (0,
|
|
6817
|
+
const snapshot = (0, import_react45.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
6818
|
+
return (0, import_react45.useMemo)(() => {
|
|
6405
6819
|
const run = (fn) => () => {
|
|
6406
6820
|
if (editor && !editor.isDestroyed) fn(editor);
|
|
6407
6821
|
};
|
|
@@ -6424,9 +6838,9 @@ function useTrackChanges(editor) {
|
|
|
6424
6838
|
}
|
|
6425
6839
|
|
|
6426
6840
|
// src/review/CommentsPanel.tsx
|
|
6427
|
-
var
|
|
6841
|
+
var import_react46 = require("react");
|
|
6428
6842
|
var import_editor13 = require("@pixerate/editor");
|
|
6429
|
-
var
|
|
6843
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
6430
6844
|
var buttonClass2 = "rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50";
|
|
6431
6845
|
var primaryButtonClass = "rounded px-2 py-1 text-xs bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-50";
|
|
6432
6846
|
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";
|
|
@@ -6440,18 +6854,18 @@ var CommentsPanel = ({
|
|
|
6440
6854
|
emptyMessage = "No comments yet. Select text and add a comment."
|
|
6441
6855
|
}) => {
|
|
6442
6856
|
const { threads, activeThreadId, store } = useComments(storeProp ?? editor);
|
|
6443
|
-
const [showResolved, setShowResolved] = (0,
|
|
6857
|
+
const [showResolved, setShowResolved] = (0, import_react46.useState)(showResolvedInitial);
|
|
6444
6858
|
const author = authorProp ?? (0, import_editor13.getCommentAuthor)(editor) ?? { id: "anonymous", name: "Anonymous" };
|
|
6445
6859
|
const visible = threads.filter((t) => showResolved || !t.resolved);
|
|
6446
6860
|
const resolvedCount = threads.filter((t) => t.resolved).length;
|
|
6447
|
-
return /* @__PURE__ */ (0,
|
|
6448
|
-
/* @__PURE__ */ (0,
|
|
6449
|
-
/* @__PURE__ */ (0,
|
|
6861
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("aside", { className, "aria-label": "Comments", children: [
|
|
6862
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
|
|
6863
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "text-xs font-medium text-muted-foreground", children: [
|
|
6450
6864
|
threads.length - resolvedCount,
|
|
6451
6865
|
" open",
|
|
6452
6866
|
resolvedCount > 0 ? ` \xB7 ${resolvedCount} resolved` : ""
|
|
6453
6867
|
] }),
|
|
6454
|
-
resolvedCount > 0 && /* @__PURE__ */ (0,
|
|
6868
|
+
resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
6455
6869
|
"button",
|
|
6456
6870
|
{
|
|
6457
6871
|
type: "button",
|
|
@@ -6462,7 +6876,7 @@ var CommentsPanel = ({
|
|
|
6462
6876
|
}
|
|
6463
6877
|
)
|
|
6464
6878
|
] }),
|
|
6465
|
-
visible.length === 0 ? /* @__PURE__ */ (0,
|
|
6879
|
+
visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("ul", { className: "flex flex-col gap-2", role: "list", children: visible.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
6466
6880
|
CommentThreadCard,
|
|
6467
6881
|
{
|
|
6468
6882
|
thread,
|
|
@@ -6484,7 +6898,7 @@ var CommentThreadCard = ({
|
|
|
6484
6898
|
author,
|
|
6485
6899
|
formatTime
|
|
6486
6900
|
}) => {
|
|
6487
|
-
const [draft, setDraft] = (0,
|
|
6901
|
+
const [draft, setDraft] = (0, import_react46.useState)("");
|
|
6488
6902
|
const isDraft = thread.body === "";
|
|
6489
6903
|
const quote = thread.anchor?.quote ?? thread.lastQuote ?? "";
|
|
6490
6904
|
const live = editor && !editor.isDestroyed ? editor : null;
|
|
@@ -6510,7 +6924,7 @@ var CommentThreadCard = ({
|
|
|
6510
6924
|
setDraft("");
|
|
6511
6925
|
};
|
|
6512
6926
|
const stop = (e) => e.stopPropagation();
|
|
6513
|
-
return /* @__PURE__ */ (0,
|
|
6927
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
6514
6928
|
"li",
|
|
6515
6929
|
{
|
|
6516
6930
|
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" : ""}`,
|
|
@@ -6526,24 +6940,24 @@ var CommentThreadCard = ({
|
|
|
6526
6940
|
}
|
|
6527
6941
|
},
|
|
6528
6942
|
children: [
|
|
6529
|
-
/* @__PURE__ */ (0,
|
|
6530
|
-
/* @__PURE__ */ (0,
|
|
6531
|
-
/* @__PURE__ */ (0,
|
|
6943
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [
|
|
6944
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "font-medium", children: thread.author.name }),
|
|
6945
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
|
|
6532
6946
|
] }),
|
|
6533
|
-
quote && /* @__PURE__ */ (0,
|
|
6534
|
-
thread.orphaned && /* @__PURE__ */ (0,
|
|
6535
|
-
thread.resolved && /* @__PURE__ */ (0,
|
|
6536
|
-
!isDraft && /* @__PURE__ */ (0,
|
|
6537
|
-
thread.replies.length > 0 && /* @__PURE__ */ (0,
|
|
6538
|
-
/* @__PURE__ */ (0,
|
|
6539
|
-
/* @__PURE__ */ (0,
|
|
6947
|
+
quote && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("blockquote", { className: "border-l-2 border-border pl-2 text-xs text-muted-foreground line-clamp-2", children: quote }),
|
|
6948
|
+
thread.orphaned && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
|
|
6949
|
+
thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
|
|
6950
|
+
!isDraft && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
|
|
6951
|
+
thread.replies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.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_runtime28.jsxs)("li", { className: "flex flex-col gap-0.5", "data-reply-id": reply.id, children: [
|
|
6952
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "text-xs", children: [
|
|
6953
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "font-medium", children: reply.author.name }),
|
|
6540
6954
|
" ",
|
|
6541
|
-
/* @__PURE__ */ (0,
|
|
6955
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
|
|
6542
6956
|
] }),
|
|
6543
|
-
/* @__PURE__ */ (0,
|
|
6957
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
|
|
6544
6958
|
] }, reply.id)) }),
|
|
6545
|
-
(active || isDraft) && !thread.resolved && /* @__PURE__ */ (0,
|
|
6546
|
-
/* @__PURE__ */ (0,
|
|
6959
|
+
(active || isDraft) && !thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col gap-1", onClick: stop, children: [
|
|
6960
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
6547
6961
|
"textarea",
|
|
6548
6962
|
{
|
|
6549
6963
|
className: textareaClass,
|
|
@@ -6561,9 +6975,9 @@ var CommentThreadCard = ({
|
|
|
6561
6975
|
}
|
|
6562
6976
|
}
|
|
6563
6977
|
),
|
|
6564
|
-
/* @__PURE__ */ (0,
|
|
6565
|
-
isDraft && /* @__PURE__ */ (0,
|
|
6566
|
-
/* @__PURE__ */ (0,
|
|
6978
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex justify-end gap-1", children: [
|
|
6979
|
+
isDraft && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", className: buttonClass2, onClick: remove, children: "Cancel" }),
|
|
6980
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
6567
6981
|
"button",
|
|
6568
6982
|
{
|
|
6569
6983
|
type: "button",
|
|
@@ -6575,9 +6989,9 @@ var CommentThreadCard = ({
|
|
|
6575
6989
|
)
|
|
6576
6990
|
] })
|
|
6577
6991
|
] }),
|
|
6578
|
-
!isDraft && /* @__PURE__ */ (0,
|
|
6579
|
-
/* @__PURE__ */ (0,
|
|
6580
|
-
/* @__PURE__ */ (0,
|
|
6992
|
+
!isDraft && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex justify-end gap-1", onClick: stop, children: [
|
|
6993
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", className: buttonClass2, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
|
|
6994
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
6581
6995
|
"button",
|
|
6582
6996
|
{
|
|
6583
6997
|
type: "button",
|
|
@@ -6593,7 +7007,7 @@ var CommentThreadCard = ({
|
|
|
6593
7007
|
};
|
|
6594
7008
|
|
|
6595
7009
|
// src/review/ReviewToolbar.tsx
|
|
6596
|
-
var
|
|
7010
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
6597
7011
|
var defaultDescriptionClass = "max-w-[16rem] truncate px-1 text-xs text-muted-foreground";
|
|
6598
7012
|
var buttonClass3 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
|
|
6599
7013
|
var ReviewToolbar = ({
|
|
@@ -6606,8 +7020,8 @@ var ReviewToolbar = ({
|
|
|
6606
7020
|
const count = review.changes.length;
|
|
6607
7021
|
const current = review.currentChange;
|
|
6608
7022
|
const index = current ? review.changes.findIndex((c) => c.id === current.id) + 1 : 0;
|
|
6609
|
-
return /* @__PURE__ */ (0,
|
|
6610
|
-
/* @__PURE__ */ (0,
|
|
7023
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className, role: "toolbar", "aria-label": "Review", children: [
|
|
7024
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6611
7025
|
"button",
|
|
6612
7026
|
{
|
|
6613
7027
|
type: "button",
|
|
@@ -6618,8 +7032,8 @@ var ReviewToolbar = ({
|
|
|
6618
7032
|
children: review.enabled ? "Tracking on" : "Track changes"
|
|
6619
7033
|
}
|
|
6620
7034
|
),
|
|
6621
|
-
/* @__PURE__ */ (0,
|
|
6622
|
-
/* @__PURE__ */ (0,
|
|
7035
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
|
|
7036
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6623
7037
|
"button",
|
|
6624
7038
|
{
|
|
6625
7039
|
type: "button",
|
|
@@ -6630,8 +7044,8 @@ var ReviewToolbar = ({
|
|
|
6630
7044
|
children: "\u2039"
|
|
6631
7045
|
}
|
|
6632
7046
|
),
|
|
6633
|
-
/* @__PURE__ */ (0,
|
|
6634
|
-
/* @__PURE__ */ (0,
|
|
7047
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.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` }),
|
|
7048
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6635
7049
|
"button",
|
|
6636
7050
|
{
|
|
6637
7051
|
type: "button",
|
|
@@ -6642,7 +7056,7 @@ var ReviewToolbar = ({
|
|
|
6642
7056
|
children: "\u203A"
|
|
6643
7057
|
}
|
|
6644
7058
|
),
|
|
6645
|
-
showDescription && current && /* @__PURE__ */ (0,
|
|
7059
|
+
showDescription && current && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
6646
7060
|
"span",
|
|
6647
7061
|
{
|
|
6648
7062
|
className: descriptionClassName,
|
|
@@ -6654,8 +7068,8 @@ var ReviewToolbar = ({
|
|
|
6654
7068
|
]
|
|
6655
7069
|
}
|
|
6656
7070
|
),
|
|
6657
|
-
/* @__PURE__ */ (0,
|
|
6658
|
-
/* @__PURE__ */ (0,
|
|
7071
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
|
|
7072
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6659
7073
|
"button",
|
|
6660
7074
|
{
|
|
6661
7075
|
type: "button",
|
|
@@ -6665,7 +7079,7 @@ var ReviewToolbar = ({
|
|
|
6665
7079
|
children: "Accept"
|
|
6666
7080
|
}
|
|
6667
7081
|
),
|
|
6668
|
-
/* @__PURE__ */ (0,
|
|
7082
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
6669
7083
|
"button",
|
|
6670
7084
|
{
|
|
6671
7085
|
type: "button",
|
|
@@ -6675,18 +7089,18 @@ var ReviewToolbar = ({
|
|
|
6675
7089
|
children: "Reject"
|
|
6676
7090
|
}
|
|
6677
7091
|
),
|
|
6678
|
-
/* @__PURE__ */ (0,
|
|
6679
|
-
/* @__PURE__ */ (0,
|
|
7092
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
|
|
7093
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
|
|
6680
7094
|
] });
|
|
6681
7095
|
};
|
|
6682
7096
|
|
|
6683
7097
|
// src/review/CommentButton.tsx
|
|
6684
|
-
var
|
|
7098
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
6685
7099
|
var CommentButton = ({
|
|
6686
7100
|
editor,
|
|
6687
7101
|
className = "rounded px-2 py-1 text-xs text-popover-foreground hover:bg-muted",
|
|
6688
7102
|
children = "Comment"
|
|
6689
|
-
}) => /* @__PURE__ */ (0,
|
|
7103
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
6690
7104
|
"button",
|
|
6691
7105
|
{
|
|
6692
7106
|
type: "button",
|
|
@@ -6698,13 +7112,13 @@ var CommentButton = ({
|
|
|
6698
7112
|
);
|
|
6699
7113
|
|
|
6700
7114
|
// src/review/useDocumentCompare.ts
|
|
6701
|
-
var
|
|
7115
|
+
var import_react47 = require("react");
|
|
6702
7116
|
var import_editor14 = require("@pixerate/editor");
|
|
6703
7117
|
function useDocumentCompare(editor, options) {
|
|
6704
|
-
const [summary, setSummary] = (0,
|
|
6705
|
-
const defaults = (0,
|
|
7118
|
+
const [summary, setSummary] = (0, import_react47.useState)(null);
|
|
7119
|
+
const defaults = (0, import_react47.useRef)(options);
|
|
6706
7120
|
defaults.current = options;
|
|
6707
|
-
const compare = (0,
|
|
7121
|
+
const compare = (0, import_react47.useCallback)(
|
|
6708
7122
|
(original, revised, overrides) => {
|
|
6709
7123
|
if (!editor || editor.isDestroyed) return null;
|
|
6710
7124
|
const result = (0, import_editor14.applyDocumentComparison)(editor, original, revised, {
|
|
@@ -6716,13 +7130,13 @@ function useDocumentCompare(editor, options) {
|
|
|
6716
7130
|
},
|
|
6717
7131
|
[editor]
|
|
6718
7132
|
);
|
|
6719
|
-
const clear = (0,
|
|
6720
|
-
return (0,
|
|
7133
|
+
const clear = (0, import_react47.useCallback)(() => setSummary(null), []);
|
|
7134
|
+
return (0, import_react47.useMemo)(() => ({ summary, compare, clear }), [summary, compare, clear]);
|
|
6721
7135
|
}
|
|
6722
7136
|
|
|
6723
7137
|
// src/review/TrackedChangesList.tsx
|
|
6724
7138
|
var import_editor15 = require("@pixerate/editor");
|
|
6725
|
-
var
|
|
7139
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
6726
7140
|
var buttonClass4 = "rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted disabled:opacity-40";
|
|
6727
7141
|
var TrackedChangesList = ({
|
|
6728
7142
|
editor,
|
|
@@ -6733,18 +7147,18 @@ var TrackedChangesList = ({
|
|
|
6733
7147
|
}) => {
|
|
6734
7148
|
const review = useTrackChanges(editor);
|
|
6735
7149
|
if (review.changes.length === 0) {
|
|
6736
|
-
return /* @__PURE__ */ (0,
|
|
7150
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className, "data-tracked-changes-list": "", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "pixerate-changes-empty text-xs text-muted-foreground", children: emptyState }) });
|
|
6737
7151
|
}
|
|
6738
|
-
return /* @__PURE__ */ (0,
|
|
7152
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("ul", { className, role: "list", "aria-label": "Tracked changes", "data-tracked-changes-list": "", children: review.changes.map((change) => {
|
|
6739
7153
|
const active = change.id === review.currentChangeId;
|
|
6740
|
-
return /* @__PURE__ */ (0,
|
|
7154
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
6741
7155
|
"li",
|
|
6742
7156
|
{
|
|
6743
7157
|
className: active ? `${itemClassName} ${activeItemClassName}` : itemClassName,
|
|
6744
7158
|
"data-change-type": change.type,
|
|
6745
7159
|
"data-change-id": change.id,
|
|
6746
7160
|
children: [
|
|
6747
|
-
/* @__PURE__ */ (0,
|
|
7161
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
6748
7162
|
"button",
|
|
6749
7163
|
{
|
|
6750
7164
|
type: "button",
|
|
@@ -6752,14 +7166,14 @@ var TrackedChangesList = ({
|
|
|
6752
7166
|
title: `${change.author.name}: ${change.description}`,
|
|
6753
7167
|
onClick: () => review.select(change.id),
|
|
6754
7168
|
children: [
|
|
6755
|
-
/* @__PURE__ */ (0,
|
|
7169
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "font-medium", children: (0, import_editor15.trackedChangeLabel)(change) }),
|
|
6756
7170
|
change.author.name ? ` \xB7 ${change.author.name}` : "",
|
|
6757
|
-
/* @__PURE__ */ (0,
|
|
7171
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "block truncate text-muted-foreground", children: change.description })
|
|
6758
7172
|
]
|
|
6759
7173
|
}
|
|
6760
7174
|
),
|
|
6761
|
-
/* @__PURE__ */ (0,
|
|
6762
|
-
/* @__PURE__ */ (0,
|
|
7175
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.accept(change.id), children: "Accept" }),
|
|
7176
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.reject(change.id), children: "Reject" })
|
|
6763
7177
|
]
|
|
6764
7178
|
},
|
|
6765
7179
|
`${change.type}:${change.id}`
|
|
@@ -6768,12 +7182,12 @@ var TrackedChangesList = ({
|
|
|
6768
7182
|
};
|
|
6769
7183
|
|
|
6770
7184
|
// src/commands/useCommandPalette.ts
|
|
6771
|
-
var
|
|
7185
|
+
var import_react48 = require("react");
|
|
6772
7186
|
var import_commands2 = require("@pixerate/editor/commands");
|
|
6773
7187
|
function useCommandPalette(registry, options = {}) {
|
|
6774
|
-
const optionsRef = (0,
|
|
7188
|
+
const optionsRef = (0, import_react48.useRef)(options);
|
|
6775
7189
|
optionsRef.current = options;
|
|
6776
|
-
const controller = (0,
|
|
7190
|
+
const controller = (0, import_react48.useMemo)(
|
|
6777
7191
|
() => (0, import_commands2.createCommandPaletteController)(registry, {
|
|
6778
7192
|
context: () => {
|
|
6779
7193
|
const c = optionsRef.current.context;
|
|
@@ -6794,9 +7208,9 @@ function useCommandPalette(registry, options = {}) {
|
|
|
6794
7208
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
6795
7209
|
[registry]
|
|
6796
7210
|
);
|
|
6797
|
-
const state = (0,
|
|
7211
|
+
const state = (0, import_react48.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
|
|
6798
7212
|
const { hotkey, hotkeyTarget } = options;
|
|
6799
|
-
(0,
|
|
7213
|
+
(0, import_react48.useEffect)(() => {
|
|
6800
7214
|
if (!hotkey) return;
|
|
6801
7215
|
const target = hotkeyTarget ?? (typeof window !== "undefined" ? window : null);
|
|
6802
7216
|
if (!target) return;
|
|
@@ -6824,13 +7238,13 @@ function useCommandPalette(registry, options = {}) {
|
|
|
6824
7238
|
}
|
|
6825
7239
|
|
|
6826
7240
|
// src/commands/CommandPalette.tsx
|
|
6827
|
-
var
|
|
6828
|
-
var
|
|
7241
|
+
var import_react49 = __toESM(require("react"), 1);
|
|
7242
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
6829
7243
|
function HighlightedLabel({ item }) {
|
|
6830
|
-
if (item.labelIndices.length === 0) return /* @__PURE__ */ (0,
|
|
7244
|
+
if (item.labelIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_jsx_runtime32.Fragment, { children: item.label });
|
|
6831
7245
|
const marked = new Set(item.labelIndices);
|
|
6832
|
-
return /* @__PURE__ */ (0,
|
|
6833
|
-
(ch, i) => marked.has(i) ? /* @__PURE__ */ (0,
|
|
7246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_jsx_runtime32.Fragment, { children: Array.from(item.label).map(
|
|
7247
|
+
(ch, i) => marked.has(i) ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-semibold text-foreground", "data-match": "", children: ch }, i) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react49.default.Fragment, { children: ch }, i)
|
|
6834
7248
|
) });
|
|
6835
7249
|
}
|
|
6836
7250
|
var CommandPalette = ({
|
|
@@ -6839,22 +7253,22 @@ var CommandPalette = ({
|
|
|
6839
7253
|
emptyMessage = "No matching commands",
|
|
6840
7254
|
className = ""
|
|
6841
7255
|
}) => {
|
|
6842
|
-
const inputRef = (0,
|
|
6843
|
-
const listRef = (0,
|
|
6844
|
-
const baseId = (0,
|
|
7256
|
+
const inputRef = (0, import_react49.useRef)(null);
|
|
7257
|
+
const listRef = (0, import_react49.useRef)(null);
|
|
7258
|
+
const baseId = (0, import_react49.useId)();
|
|
6845
7259
|
const listId = `${baseId}-list`;
|
|
6846
7260
|
const optionId = (index) => `${baseId}-option-${index}`;
|
|
6847
7261
|
const { open, query, items, activeIndex } = palette;
|
|
6848
|
-
(0,
|
|
7262
|
+
(0, import_react49.useEffect)(() => {
|
|
6849
7263
|
if (open) inputRef.current?.focus();
|
|
6850
7264
|
}, [open]);
|
|
6851
|
-
(0,
|
|
7265
|
+
(0, import_react49.useEffect)(() => {
|
|
6852
7266
|
if (!open) return;
|
|
6853
7267
|
const active = listRef.current?.querySelector('[aria-selected="true"]');
|
|
6854
7268
|
active?.scrollIntoView?.({ block: "nearest" });
|
|
6855
7269
|
}, [open, activeIndex]);
|
|
6856
7270
|
if (!open) return null;
|
|
6857
|
-
return /* @__PURE__ */ (0,
|
|
7271
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6858
7272
|
"div",
|
|
6859
7273
|
{
|
|
6860
7274
|
className: "fixed inset-0 z-50 flex items-start justify-center bg-black/30 px-4 pt-[15vh]",
|
|
@@ -6862,7 +7276,7 @@ var CommandPalette = ({
|
|
|
6862
7276
|
onMouseDown: (e) => {
|
|
6863
7277
|
if (e.target === e.currentTarget) palette.setOpen(false);
|
|
6864
7278
|
},
|
|
6865
|
-
children: /* @__PURE__ */ (0,
|
|
7279
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
6866
7280
|
"div",
|
|
6867
7281
|
{
|
|
6868
7282
|
role: "dialog",
|
|
@@ -6871,7 +7285,7 @@ var CommandPalette = ({
|
|
|
6871
7285
|
className: `w-full max-w-lg overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-xl ${className}`,
|
|
6872
7286
|
style: { background: "var(--popover, var(--background, #fff))" },
|
|
6873
7287
|
children: [
|
|
6874
|
-
/* @__PURE__ */ (0,
|
|
7288
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6875
7289
|
"input",
|
|
6876
7290
|
{
|
|
6877
7291
|
ref: inputRef,
|
|
@@ -6891,7 +7305,7 @@ var CommandPalette = ({
|
|
|
6891
7305
|
className: "w-full border-b border-border bg-transparent px-3 py-2 text-sm outline-none placeholder:text-muted-foreground"
|
|
6892
7306
|
}
|
|
6893
7307
|
),
|
|
6894
|
-
items.length === 0 ? /* @__PURE__ */ (0,
|
|
7308
|
+
items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime32.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_runtime32.jsxs)(
|
|
6895
7309
|
"li",
|
|
6896
7310
|
{
|
|
6897
7311
|
id: optionId(index),
|
|
@@ -6906,12 +7320,12 @@ var CommandPalette = ({
|
|
|
6906
7320
|
onClick: () => palette.run(item.id),
|
|
6907
7321
|
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"}`,
|
|
6908
7322
|
children: [
|
|
6909
|
-
/* @__PURE__ */ (0,
|
|
6910
|
-
/* @__PURE__ */ (0,
|
|
6911
|
-
item.disabledReason && /* @__PURE__ */ (0,
|
|
7323
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
7324
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(HighlightedLabel, { item }),
|
|
7325
|
+
item.disabledReason && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "ml-2 text-xs text-muted-foreground", "data-disabled-reason": "", children: item.disabledReason })
|
|
6912
7326
|
] }),
|
|
6913
|
-
item.group && /* @__PURE__ */ (0,
|
|
6914
|
-
item.shortcut && /* @__PURE__ */ (0,
|
|
7327
|
+
item.group && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.group }),
|
|
7328
|
+
item.shortcut && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("kbd", { className: "shrink-0 rounded border border-border px-1.5 font-mono text-[10px] text-muted-foreground", children: item.shortcut })
|
|
6915
7329
|
]
|
|
6916
7330
|
},
|
|
6917
7331
|
item.id
|
|
@@ -6924,12 +7338,12 @@ var CommandPalette = ({
|
|
|
6924
7338
|
};
|
|
6925
7339
|
|
|
6926
7340
|
// src/commands/useCommandShortcuts.ts
|
|
6927
|
-
var
|
|
7341
|
+
var import_react50 = require("react");
|
|
6928
7342
|
function useCommandShortcuts(registry, options = {}) {
|
|
6929
|
-
const optionsRef = (0,
|
|
7343
|
+
const optionsRef = (0, import_react50.useRef)(options);
|
|
6930
7344
|
optionsRef.current = options;
|
|
6931
7345
|
const { enabled = true, target } = options;
|
|
6932
|
-
(0,
|
|
7346
|
+
(0, import_react50.useEffect)(() => {
|
|
6933
7347
|
if (!registry || !enabled) return;
|
|
6934
7348
|
const eventTarget = target ?? (typeof window !== "undefined" ? window : null);
|
|
6935
7349
|
if (!eventTarget) return;
|
|
@@ -6947,14 +7361,14 @@ function useCommandShortcuts(registry, options = {}) {
|
|
|
6947
7361
|
}, [registry, enabled, target]);
|
|
6948
7362
|
}
|
|
6949
7363
|
function useRegisterCommands(registry, specs) {
|
|
6950
|
-
(0,
|
|
7364
|
+
(0, import_react50.useEffect)(() => {
|
|
6951
7365
|
if (!registry || !specs || specs.length === 0) return;
|
|
6952
7366
|
return registry.register(specs);
|
|
6953
7367
|
}, [registry, specs]);
|
|
6954
7368
|
}
|
|
6955
7369
|
|
|
6956
7370
|
// src/persistence/useAutosave.ts
|
|
6957
|
-
var
|
|
7371
|
+
var import_react51 = require("react");
|
|
6958
7372
|
var import_persistence = require("@pixerate/editor/persistence");
|
|
6959
7373
|
var IDLE = {
|
|
6960
7374
|
status: "idle",
|
|
@@ -6965,18 +7379,18 @@ var IDLE = {
|
|
|
6965
7379
|
ready: false
|
|
6966
7380
|
};
|
|
6967
7381
|
function useAutosave(options) {
|
|
6968
|
-
const optionsRef = (0,
|
|
7382
|
+
const optionsRef = (0, import_react51.useRef)(options);
|
|
6969
7383
|
optionsRef.current = options;
|
|
6970
7384
|
const { storage, key, history, dirty } = options;
|
|
6971
7385
|
const recover = options.recover !== false;
|
|
6972
7386
|
const flushOnHide = options.flushOnHide !== false;
|
|
6973
7387
|
const ready = options.ready !== false;
|
|
6974
|
-
const [controller, setController] = (0,
|
|
6975
|
-
const [status, setStatus] = (0,
|
|
6976
|
-
const [recovery, setRecovery] = (0,
|
|
6977
|
-
const [pendingRecovery, setPendingRecovery] = (0,
|
|
6978
|
-
const revisionsRef = (0,
|
|
6979
|
-
(0,
|
|
7388
|
+
const [controller, setController] = (0, import_react51.useState)(null);
|
|
7389
|
+
const [status, setStatus] = (0, import_react51.useState)(IDLE);
|
|
7390
|
+
const [recovery, setRecovery] = (0, import_react51.useState)(null);
|
|
7391
|
+
const [pendingRecovery, setPendingRecovery] = (0, import_react51.useState)(recover);
|
|
7392
|
+
const revisionsRef = (0, import_react51.useRef)(null);
|
|
7393
|
+
(0, import_react51.useEffect)(() => {
|
|
6980
7394
|
const revisions = (0, import_persistence.createRevisionTracker)({ history, dirty });
|
|
6981
7395
|
const o = optionsRef.current;
|
|
6982
7396
|
const instance = (0, import_persistence.createAutosaveController)({
|
|
@@ -7019,10 +7433,10 @@ function useAutosave(options) {
|
|
|
7019
7433
|
if (revisionsRef.current === revisions) revisionsRef.current = null;
|
|
7020
7434
|
};
|
|
7021
7435
|
}, [storage, key, history, dirty, recover]);
|
|
7022
|
-
(0,
|
|
7436
|
+
(0, import_react51.useEffect)(() => {
|
|
7023
7437
|
if (controller && ready && !pendingRecovery) controller.ready();
|
|
7024
7438
|
}, [controller, ready, pendingRecovery]);
|
|
7025
|
-
(0,
|
|
7439
|
+
(0, import_react51.useEffect)(() => {
|
|
7026
7440
|
if (!controller || !flushOnHide || typeof window === "undefined") return;
|
|
7027
7441
|
const flush = () => void controller.flushNow();
|
|
7028
7442
|
const onVisibility = () => {
|
|
@@ -7035,31 +7449,31 @@ function useAutosave(options) {
|
|
|
7035
7449
|
document.removeEventListener("visibilitychange", onVisibility);
|
|
7036
7450
|
};
|
|
7037
7451
|
}, [controller, flushOnHide]);
|
|
7038
|
-
const restore = (0,
|
|
7452
|
+
const restore = (0, import_react51.useCallback)(() => {
|
|
7039
7453
|
const snapshot = recovery?.snapshot;
|
|
7040
7454
|
setRecovery(null);
|
|
7041
7455
|
setPendingRecovery(false);
|
|
7042
7456
|
return snapshot;
|
|
7043
7457
|
}, [recovery]);
|
|
7044
|
-
const discard = (0,
|
|
7458
|
+
const discard = (0, import_react51.useCallback)(async () => {
|
|
7045
7459
|
if (controller) await controller.discardRecovery();
|
|
7046
7460
|
setRecovery(null);
|
|
7047
7461
|
setPendingRecovery(false);
|
|
7048
7462
|
}, [controller]);
|
|
7049
|
-
const flushNow = (0,
|
|
7463
|
+
const flushNow = (0, import_react51.useCallback)(async () => {
|
|
7050
7464
|
await controller?.flushNow();
|
|
7051
7465
|
}, [controller]);
|
|
7052
|
-
const markClean = (0,
|
|
7466
|
+
const markClean = (0, import_react51.useCallback)(async () => {
|
|
7053
7467
|
revisionsRef.current?.markSaved();
|
|
7054
7468
|
await controller?.markClean();
|
|
7055
7469
|
}, [controller]);
|
|
7056
|
-
const notifyChange = (0,
|
|
7470
|
+
const notifyChange = (0, import_react51.useCallback)(() => revisionsRef.current?.bump(), []);
|
|
7057
7471
|
return { status, recovery, pendingRecovery, restore, discard, flushNow, markClean, notifyChange, controller };
|
|
7058
7472
|
}
|
|
7059
7473
|
|
|
7060
7474
|
// src/persistence/RecoveryPrompt.tsx
|
|
7061
7475
|
var import_persistence2 = require("@pixerate/editor/persistence");
|
|
7062
|
-
var
|
|
7476
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
7063
7477
|
var RecoveryPrompt = ({
|
|
7064
7478
|
recovery,
|
|
7065
7479
|
onRestore,
|
|
@@ -7071,7 +7485,7 @@ var RecoveryPrompt = ({
|
|
|
7071
7485
|
}) => {
|
|
7072
7486
|
if (!recovery) return null;
|
|
7073
7487
|
const { name } = recovery.meta;
|
|
7074
|
-
return /* @__PURE__ */ (0,
|
|
7488
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
7075
7489
|
"div",
|
|
7076
7490
|
{
|
|
7077
7491
|
role: "alertdialog",
|
|
@@ -7079,15 +7493,15 @@ var RecoveryPrompt = ({
|
|
|
7079
7493
|
"data-recovery-prompt": "",
|
|
7080
7494
|
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}`,
|
|
7081
7495
|
children: [
|
|
7082
|
-
/* @__PURE__ */ (0,
|
|
7496
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "min-w-0 flex-1", children: [
|
|
7083
7497
|
(0, import_persistence2.formatRecoveryMessage)(recovery.meta, formatTime),
|
|
7084
|
-
name ? /* @__PURE__ */ (0,
|
|
7498
|
+
name ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
|
|
7085
7499
|
"(",
|
|
7086
7500
|
name,
|
|
7087
7501
|
")"
|
|
7088
7502
|
] }) : null
|
|
7089
7503
|
] }),
|
|
7090
|
-
/* @__PURE__ */ (0,
|
|
7504
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
7091
7505
|
"button",
|
|
7092
7506
|
{
|
|
7093
7507
|
type: "button",
|
|
@@ -7097,7 +7511,7 @@ var RecoveryPrompt = ({
|
|
|
7097
7511
|
children: restoreLabel
|
|
7098
7512
|
}
|
|
7099
7513
|
),
|
|
7100
|
-
/* @__PURE__ */ (0,
|
|
7514
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
7101
7515
|
"button",
|
|
7102
7516
|
{
|
|
7103
7517
|
type: "button",
|
|
@@ -7113,17 +7527,17 @@ var RecoveryPrompt = ({
|
|
|
7113
7527
|
};
|
|
7114
7528
|
|
|
7115
7529
|
// src/generation/useGenerationPlan.ts
|
|
7116
|
-
var
|
|
7530
|
+
var import_react52 = require("react");
|
|
7117
7531
|
var import_generation = require("@pixerate/editor/generation");
|
|
7118
7532
|
function useGenerationPlan(request, capabilities, options = {}) {
|
|
7119
7533
|
const key = JSON.stringify([request, capabilities, options]);
|
|
7120
|
-
return (0,
|
|
7534
|
+
return (0, import_react52.useMemo)(() => (0, import_generation.planGenerationRequest)(request, capabilities, options), [key]);
|
|
7121
7535
|
}
|
|
7122
7536
|
function useJobProgress(options) {
|
|
7123
7537
|
const { startedAt, expectedMs, done, now, intervalMs = 1e3 } = options;
|
|
7124
|
-
const [tick, setTick] = (0,
|
|
7538
|
+
const [tick, setTick] = (0, import_react52.useState)(() => Date.now());
|
|
7125
7539
|
const ticking = !done && now === void 0;
|
|
7126
|
-
(0,
|
|
7540
|
+
(0, import_react52.useEffect)(() => {
|
|
7127
7541
|
if (!ticking) return;
|
|
7128
7542
|
setTick(Date.now());
|
|
7129
7543
|
const id = setInterval(() => setTick(Date.now()), Math.max(16, intervalMs));
|
|
@@ -7133,9 +7547,9 @@ function useJobProgress(options) {
|
|
|
7133
7547
|
}
|
|
7134
7548
|
|
|
7135
7549
|
// src/generation/GenerationSettings.tsx
|
|
7136
|
-
var
|
|
7550
|
+
var import_react53 = require("react");
|
|
7137
7551
|
var import_generation2 = require("@pixerate/editor/generation");
|
|
7138
|
-
var
|
|
7552
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
7139
7553
|
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";
|
|
7140
7554
|
function Control({
|
|
7141
7555
|
control,
|
|
@@ -7145,7 +7559,7 @@ function Control({
|
|
|
7145
7559
|
}) {
|
|
7146
7560
|
const shown = value ?? control.defaultValue;
|
|
7147
7561
|
if (control.kind === "checkbox") {
|
|
7148
|
-
return /* @__PURE__ */ (0,
|
|
7562
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
7149
7563
|
"input",
|
|
7150
7564
|
{
|
|
7151
7565
|
id,
|
|
@@ -7157,7 +7571,7 @@ function Control({
|
|
|
7157
7571
|
);
|
|
7158
7572
|
}
|
|
7159
7573
|
if (control.kind === "select") {
|
|
7160
|
-
return /* @__PURE__ */ (0,
|
|
7574
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
7161
7575
|
"select",
|
|
7162
7576
|
{
|
|
7163
7577
|
id,
|
|
@@ -7166,14 +7580,14 @@ function Control({
|
|
|
7166
7580
|
value: shown === void 0 ? "" : String(shown),
|
|
7167
7581
|
onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value)),
|
|
7168
7582
|
children: [
|
|
7169
|
-
shown === void 0 && /* @__PURE__ */ (0,
|
|
7170
|
-
control.options.map((option) => /* @__PURE__ */ (0,
|
|
7583
|
+
shown === void 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("option", { value: "", children: "Default" }),
|
|
7584
|
+
control.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("option", { value: String(option.value), children: option.label }, String(option.value)))
|
|
7171
7585
|
]
|
|
7172
7586
|
}
|
|
7173
7587
|
);
|
|
7174
7588
|
}
|
|
7175
7589
|
if (control.kind === "textarea") {
|
|
7176
|
-
return /* @__PURE__ */ (0,
|
|
7590
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
7177
7591
|
"textarea",
|
|
7178
7592
|
{
|
|
7179
7593
|
id,
|
|
@@ -7187,8 +7601,8 @@ function Control({
|
|
|
7187
7601
|
);
|
|
7188
7602
|
}
|
|
7189
7603
|
const numeric = typeof shown === "number" ? shown : void 0;
|
|
7190
|
-
return /* @__PURE__ */ (0,
|
|
7191
|
-
/* @__PURE__ */ (0,
|
|
7604
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
7605
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
7192
7606
|
"input",
|
|
7193
7607
|
{
|
|
7194
7608
|
id,
|
|
@@ -7202,7 +7616,7 @@ function Control({
|
|
|
7202
7616
|
onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value))
|
|
7203
7617
|
}
|
|
7204
7618
|
),
|
|
7205
|
-
control.kind === "range" && /* @__PURE__ */ (0,
|
|
7619
|
+
control.kind === "range" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "w-10 text-right tabular-nums text-muted-foreground", "data-field-value": "", children: numeric ?? "\u2013" })
|
|
7206
7620
|
] });
|
|
7207
7621
|
}
|
|
7208
7622
|
var GenerationSettings = ({
|
|
@@ -7216,17 +7630,17 @@ var GenerationSettings = ({
|
|
|
7216
7630
|
renderReference,
|
|
7217
7631
|
className = ""
|
|
7218
7632
|
}) => {
|
|
7219
|
-
const baseId = (0,
|
|
7220
|
-
const controls = (0,
|
|
7633
|
+
const baseId = (0, import_react53.useId)();
|
|
7634
|
+
const controls = (0, import_react53.useMemo)(() => (0, import_generation2.getGenerationControls)(capabilities), [capabilities]);
|
|
7221
7635
|
const computed = useGenerationPlan(value, capabilities, { strategy });
|
|
7222
7636
|
const plan = planProp ?? computed;
|
|
7223
7637
|
const slots = (0, import_generation2.getReferenceSlots)(capabilities, value);
|
|
7224
|
-
return /* @__PURE__ */ (0,
|
|
7638
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: `flex flex-col gap-3 text-sm ${className}`, "data-generation-settings": "", "data-model": capabilities.id, children: [
|
|
7225
7639
|
controls.map((control) => {
|
|
7226
7640
|
const id = `${baseId}-${control.key}`;
|
|
7227
|
-
return /* @__PURE__ */ (0,
|
|
7228
|
-
/* @__PURE__ */ (0,
|
|
7229
|
-
/* @__PURE__ */ (0,
|
|
7641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex flex-col gap-1", "data-control": control.key, children: [
|
|
7642
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("label", { htmlFor: id, className: "text-xs font-medium text-muted-foreground", title: control.description, children: control.label }),
|
|
7643
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
7230
7644
|
Control,
|
|
7231
7645
|
{
|
|
7232
7646
|
control,
|
|
@@ -7237,23 +7651,23 @@ var GenerationSettings = ({
|
|
|
7237
7651
|
)
|
|
7238
7652
|
] }, control.key);
|
|
7239
7653
|
}),
|
|
7240
|
-
slots.map((slot) => /* @__PURE__ */ (0,
|
|
7241
|
-
/* @__PURE__ */ (0,
|
|
7654
|
+
slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("fieldset", { className: "flex flex-col gap-1", "data-reference-role": slot.role, children: [
|
|
7655
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("legend", { className: "text-xs font-medium text-muted-foreground", title: slot.description, children: [
|
|
7242
7656
|
slot.label,
|
|
7243
7657
|
" ",
|
|
7244
|
-
/* @__PURE__ */ (0,
|
|
7658
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "tabular-nums", "data-reference-count": "", children: [
|
|
7245
7659
|
"(",
|
|
7246
7660
|
slot.references.length,
|
|
7247
7661
|
"/",
|
|
7248
7662
|
slot.max,
|
|
7249
7663
|
")"
|
|
7250
7664
|
] }),
|
|
7251
|
-
slot.min > 0 && /* @__PURE__ */ (0,
|
|
7665
|
+
slot.min > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-destructive", children: " *" })
|
|
7252
7666
|
] }),
|
|
7253
|
-
/* @__PURE__ */ (0,
|
|
7254
|
-
slot.references.map((ref) => /* @__PURE__ */ (0,
|
|
7255
|
-
renderReference ? renderReference(ref) : /* @__PURE__ */ (0,
|
|
7256
|
-
/* @__PURE__ */ (0,
|
|
7667
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("ul", { className: "flex flex-wrap gap-1", children: [
|
|
7668
|
+
slot.references.map((ref) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("li", { className: "flex items-center gap-1 rounded border border-border px-1.5 py-0.5", "data-reference-id": ref.id, children: [
|
|
7669
|
+
renderReference ? renderReference(ref) : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "max-w-[10rem] truncate", children: ref.id }),
|
|
7670
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
7257
7671
|
"button",
|
|
7258
7672
|
{
|
|
7259
7673
|
type: "button",
|
|
@@ -7264,7 +7678,7 @@ var GenerationSettings = ({
|
|
|
7264
7678
|
}
|
|
7265
7679
|
)
|
|
7266
7680
|
] }, ref.id)),
|
|
7267
|
-
onAddReference && slot.canAdd && /* @__PURE__ */ (0,
|
|
7681
|
+
onAddReference && slot.canAdd && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
7268
7682
|
"button",
|
|
7269
7683
|
{
|
|
7270
7684
|
type: "button",
|
|
@@ -7275,21 +7689,21 @@ var GenerationSettings = ({
|
|
|
7275
7689
|
) })
|
|
7276
7690
|
] })
|
|
7277
7691
|
] }, slot.role)),
|
|
7278
|
-
showAdjustments && plan.adjustments.length > 0 && /* @__PURE__ */ (0,
|
|
7279
|
-
showAdjustments && plan.errors.length > 0 && /* @__PURE__ */ (0,
|
|
7692
|
+
showAdjustments && plan.adjustments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.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_runtime34.jsx)("li", { "data-adjustment-field": adjustment.field, "data-adjustment-kind": adjustment.kind, children: adjustment.reason }, index)) }),
|
|
7693
|
+
showAdjustments && plan.errors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.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_runtime34.jsx)("li", { "data-error-field": error.field, children: error.message }, index)) })
|
|
7280
7694
|
] });
|
|
7281
7695
|
};
|
|
7282
7696
|
|
|
7283
7697
|
// src/generation/JobProgress.tsx
|
|
7284
|
-
var
|
|
7698
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
7285
7699
|
var JobProgress = ({ title, className = "", ...options }) => {
|
|
7286
7700
|
const progress = useJobProgress(options);
|
|
7287
|
-
return /* @__PURE__ */ (0,
|
|
7288
|
-
/* @__PURE__ */ (0,
|
|
7289
|
-
title && /* @__PURE__ */ (0,
|
|
7290
|
-
/* @__PURE__ */ (0,
|
|
7701
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: `flex flex-col gap-1 text-sm ${className}`, "data-job-progress": "", "data-done": options.done ? "" : void 0, children: [
|
|
7702
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex items-center justify-between gap-2 text-muted-foreground", children: [
|
|
7703
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "truncate text-foreground", children: title }),
|
|
7704
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { "data-job-progress-label": "", "aria-live": "polite", children: progress.label })
|
|
7291
7705
|
] }),
|
|
7292
|
-
/* @__PURE__ */ (0,
|
|
7706
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
7293
7707
|
"div",
|
|
7294
7708
|
{
|
|
7295
7709
|
role: "progressbar",
|
|
@@ -7299,7 +7713,7 @@ var JobProgress = ({ title, className = "", ...options }) => {
|
|
|
7299
7713
|
"aria-valuenow": progress.percent,
|
|
7300
7714
|
"aria-valuetext": `${progress.percent}%, ${progress.label}`,
|
|
7301
7715
|
className: "h-1.5 w-full overflow-hidden rounded-full bg-muted",
|
|
7302
|
-
children: /* @__PURE__ */ (0,
|
|
7716
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
7303
7717
|
"div",
|
|
7304
7718
|
{
|
|
7305
7719
|
className: "h-full rounded-full bg-primary transition-[width] duration-500",
|
|
@@ -7312,9 +7726,9 @@ var JobProgress = ({ title, className = "", ...options }) => {
|
|
|
7312
7726
|
};
|
|
7313
7727
|
|
|
7314
7728
|
// src/generation/AssetMentionChips.tsx
|
|
7315
|
-
var
|
|
7729
|
+
var import_react54 = require("react");
|
|
7316
7730
|
var import_generation3 = require("@pixerate/editor/generation");
|
|
7317
|
-
var
|
|
7731
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
7318
7732
|
var AssetMentionChips = ({
|
|
7319
7733
|
content,
|
|
7320
7734
|
onChange,
|
|
@@ -7324,14 +7738,14 @@ var AssetMentionChips = ({
|
|
|
7324
7738
|
renderAsset,
|
|
7325
7739
|
className = ""
|
|
7326
7740
|
}) => {
|
|
7327
|
-
const [open, setOpen] = (0,
|
|
7328
|
-
const rootRef = (0,
|
|
7329
|
-
const chips = (0,
|
|
7741
|
+
const [open, setOpen] = (0, import_react54.useState)(null);
|
|
7742
|
+
const rootRef = (0, import_react54.useRef)(null);
|
|
7743
|
+
const chips = (0, import_react54.useMemo)(
|
|
7330
7744
|
() => (0, import_generation3.describeAssetMentions)((0, import_generation3.findTextMentions)(content), assets, capabilities),
|
|
7331
7745
|
[content, assets, capabilities]
|
|
7332
7746
|
);
|
|
7333
7747
|
const options = roles ?? (capabilities ? (0, import_generation3.getAssetRoleOptions)(capabilities) : (0, import_generation3.defaultAssetRoleOptions)());
|
|
7334
|
-
(0,
|
|
7748
|
+
(0, import_react54.useEffect)(() => {
|
|
7335
7749
|
if (open === null) return;
|
|
7336
7750
|
const onPointer = (event) => {
|
|
7337
7751
|
if (!rootRef.current?.contains(event.target)) setOpen(null);
|
|
@@ -7339,19 +7753,19 @@ var AssetMentionChips = ({
|
|
|
7339
7753
|
document.addEventListener("mousedown", onPointer);
|
|
7340
7754
|
return () => document.removeEventListener("mousedown", onPointer);
|
|
7341
7755
|
}, [open]);
|
|
7342
|
-
const pick = (
|
|
7756
|
+
const pick = (chip3, role) => {
|
|
7343
7757
|
setOpen(null);
|
|
7344
|
-
if (
|
|
7345
|
-
onChange((0, import_generation3.setMentionRoleInText)(content,
|
|
7758
|
+
if (chip3.start === void 0) return;
|
|
7759
|
+
onChange((0, import_generation3.setMentionRoleInText)(content, chip3.start, role));
|
|
7346
7760
|
};
|
|
7347
7761
|
if (chips.length === 0) return null;
|
|
7348
|
-
return /* @__PURE__ */ (0,
|
|
7349
|
-
const error =
|
|
7350
|
-
const warning =
|
|
7762
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { ref: rootRef, className: `flex flex-wrap gap-1.5 ${className}`, "data-asset-mention-chips": "", children: chips.map((chip3) => {
|
|
7763
|
+
const error = chip3.issues.find((issue) => issue.severity === "error");
|
|
7764
|
+
const warning = chip3.issues.find((issue) => issue.severity === "warning");
|
|
7351
7765
|
const problem = error ?? warning;
|
|
7352
|
-
const isOpen = open ===
|
|
7353
|
-
return /* @__PURE__ */ (0,
|
|
7354
|
-
/* @__PURE__ */ (0,
|
|
7766
|
+
const isOpen = open === chip3.index;
|
|
7767
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "relative inline-flex", "data-asset-chip": chip3.asset.id, children: [
|
|
7768
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
7355
7769
|
"button",
|
|
7356
7770
|
{
|
|
7357
7771
|
type: "button",
|
|
@@ -7359,82 +7773,82 @@ var AssetMentionChips = ({
|
|
|
7359
7773
|
"aria-expanded": isOpen,
|
|
7360
7774
|
title: problem?.message,
|
|
7361
7775
|
"data-issue": problem?.code,
|
|
7362
|
-
onClick: () => setOpen(isOpen ? null :
|
|
7776
|
+
onClick: () => setOpen(isOpen ? null : chip3.index),
|
|
7363
7777
|
onKeyDown: (e) => {
|
|
7364
7778
|
if (e.key === "Escape") setOpen(null);
|
|
7365
7779
|
},
|
|
7366
7780
|
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`,
|
|
7367
7781
|
children: [
|
|
7368
|
-
/* @__PURE__ */ (0,
|
|
7369
|
-
/* @__PURE__ */ (0,
|
|
7782
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { children: renderAsset ? renderAsset(chip3) : `@${chip3.asset.label ?? chip3.handle}` }),
|
|
7783
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7370
7784
|
"span",
|
|
7371
7785
|
{
|
|
7372
|
-
className: `rounded px-1 text-[10px] uppercase tracking-wide ${
|
|
7373
|
-
"data-role-badge":
|
|
7374
|
-
children:
|
|
7786
|
+
className: `rounded px-1 text-[10px] uppercase tracking-wide ${chip3.role ? "bg-primary/15" : "opacity-60"}`,
|
|
7787
|
+
"data-role-badge": chip3.role ?? "",
|
|
7788
|
+
children: chip3.roleLabel ?? "No role"
|
|
7375
7789
|
}
|
|
7376
7790
|
)
|
|
7377
7791
|
]
|
|
7378
7792
|
}
|
|
7379
7793
|
),
|
|
7380
|
-
isOpen && /* @__PURE__ */ (0,
|
|
7794
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
7381
7795
|
"div",
|
|
7382
7796
|
{
|
|
7383
7797
|
role: "listbox",
|
|
7384
|
-
"aria-label": `Role for ${
|
|
7798
|
+
"aria-label": `Role for ${chip3.asset.label ?? chip3.handle}`,
|
|
7385
7799
|
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",
|
|
7386
7800
|
"data-role-picker": "",
|
|
7387
7801
|
onKeyDown: (e) => {
|
|
7388
7802
|
if (e.key === "Escape") setOpen(null);
|
|
7389
7803
|
},
|
|
7390
7804
|
children: [
|
|
7391
|
-
options.map((option) => /* @__PURE__ */ (0,
|
|
7805
|
+
options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
7392
7806
|
"button",
|
|
7393
7807
|
{
|
|
7394
7808
|
type: "button",
|
|
7395
7809
|
role: "option",
|
|
7396
|
-
"aria-selected":
|
|
7810
|
+
"aria-selected": chip3.role === option.role,
|
|
7397
7811
|
"data-role-option": option.role,
|
|
7398
7812
|
title: option.description,
|
|
7399
|
-
onClick: () => pick(
|
|
7813
|
+
onClick: () => pick(chip3, option.role),
|
|
7400
7814
|
className: "flex items-center justify-between gap-2 rounded px-2 py-1 text-left hover:bg-muted",
|
|
7401
7815
|
children: [
|
|
7402
|
-
/* @__PURE__ */ (0,
|
|
7403
|
-
option.accepts?.length ? /* @__PURE__ */ (0,
|
|
7816
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { children: option.label }),
|
|
7817
|
+
option.accepts?.length ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-[10px] opacity-60", children: option.accepts.join(", ") }) : null
|
|
7404
7818
|
]
|
|
7405
7819
|
},
|
|
7406
7820
|
option.role
|
|
7407
7821
|
)),
|
|
7408
|
-
/* @__PURE__ */ (0,
|
|
7822
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
7409
7823
|
"button",
|
|
7410
7824
|
{
|
|
7411
7825
|
type: "button",
|
|
7412
7826
|
role: "option",
|
|
7413
|
-
"aria-selected": !
|
|
7827
|
+
"aria-selected": !chip3.role,
|
|
7414
7828
|
"data-role-option": "",
|
|
7415
|
-
onClick: () => pick(
|
|
7829
|
+
onClick: () => pick(chip3, null),
|
|
7416
7830
|
className: "rounded px-2 py-1 text-left opacity-70 hover:bg-muted",
|
|
7417
7831
|
children: "No role"
|
|
7418
7832
|
}
|
|
7419
7833
|
),
|
|
7420
|
-
|
|
7834
|
+
chip3.issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("ul", { className: "mt-1 border-t border-border px-2 pt-1 text-[10px]", "data-chip-issues": "", children: chip3.issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("li", { className: issue.severity === "error" ? "text-red-500" : "text-amber-500", children: issue.message }, i)) })
|
|
7421
7835
|
]
|
|
7422
7836
|
}
|
|
7423
7837
|
)
|
|
7424
|
-
] }, `${
|
|
7838
|
+
] }, `${chip3.start}-${chip3.index}`);
|
|
7425
7839
|
}) });
|
|
7426
7840
|
};
|
|
7427
7841
|
|
|
7428
7842
|
// src/generation/GenerationHistory.tsx
|
|
7429
|
-
var
|
|
7843
|
+
var import_react55 = require("react");
|
|
7430
7844
|
var import_generation4 = require("@pixerate/editor/generation");
|
|
7431
|
-
var
|
|
7845
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
7432
7846
|
function useGenerationRecords(store, filter) {
|
|
7433
|
-
const [records, setRecords] = (0,
|
|
7434
|
-
const [loading, setLoading] = (0,
|
|
7435
|
-
const [error, setError] = (0,
|
|
7847
|
+
const [records, setRecords] = (0, import_react55.useState)([]);
|
|
7848
|
+
const [loading, setLoading] = (0, import_react55.useState)(!!store);
|
|
7849
|
+
const [error, setError] = (0, import_react55.useState)(null);
|
|
7436
7850
|
const filterKey = (0, import_generation4.stableStringify)(filter ?? {});
|
|
7437
|
-
const refresh = (0,
|
|
7851
|
+
const refresh = (0, import_react55.useCallback)(async () => {
|
|
7438
7852
|
if (!store) {
|
|
7439
7853
|
setRecords([]);
|
|
7440
7854
|
setLoading(false);
|
|
@@ -7451,7 +7865,7 @@ function useGenerationRecords(store, filter) {
|
|
|
7451
7865
|
setLoading(false);
|
|
7452
7866
|
}
|
|
7453
7867
|
}, [store, filterKey]);
|
|
7454
|
-
(0,
|
|
7868
|
+
(0, import_react55.useEffect)(() => {
|
|
7455
7869
|
void refresh();
|
|
7456
7870
|
if (!store) return;
|
|
7457
7871
|
return store.subscribe(() => void refresh());
|
|
@@ -7477,21 +7891,21 @@ var GenerationHistory = ({
|
|
|
7477
7891
|
emptyText = "No generations yet.",
|
|
7478
7892
|
className = ""
|
|
7479
7893
|
}) => {
|
|
7480
|
-
const [innerMode, setInnerMode] = (0,
|
|
7894
|
+
const [innerMode, setInnerMode] = (0, import_react55.useState)("exact");
|
|
7481
7895
|
const mode = modeProp ?? innerMode;
|
|
7482
7896
|
const setMode = (next) => {
|
|
7483
7897
|
if (modeProp === void 0) setInnerMode(next);
|
|
7484
7898
|
onModeChange?.(next);
|
|
7485
7899
|
};
|
|
7486
|
-
const options = (0,
|
|
7487
|
-
const results = (0,
|
|
7488
|
-
const models = (0,
|
|
7900
|
+
const options = (0, import_react55.useMemo)(() => ({ templates, capabilities, assets, mode }), [templates, capabilities, assets, mode]);
|
|
7901
|
+
const results = (0, import_react55.useMemo)(() => records.map((record) => (0, import_generation4.recreateRequest)(record, options)), [records, options]);
|
|
7902
|
+
const models = (0, import_react55.useMemo)(
|
|
7489
7903
|
() => capabilities ? Array.isArray(capabilities) ? capabilities : [capabilities] : [],
|
|
7490
7904
|
[capabilities]
|
|
7491
7905
|
);
|
|
7492
|
-
return /* @__PURE__ */ (0,
|
|
7493
|
-
/* @__PURE__ */ (0,
|
|
7494
|
-
/* @__PURE__ */ (0,
|
|
7906
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: `flex flex-col gap-2 text-sm ${className}`, "data-generation-history": "", children: [
|
|
7907
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.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_runtime37.jsxs)("label", { className: "inline-flex items-center gap-1", children: [
|
|
7908
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
7495
7909
|
"input",
|
|
7496
7910
|
{
|
|
7497
7911
|
type: "radio",
|
|
@@ -7504,34 +7918,34 @@ var GenerationHistory = ({
|
|
|
7504
7918
|
),
|
|
7505
7919
|
value === "exact" ? "Exact (recorded versions)" : "Latest templates & settings"
|
|
7506
7920
|
] }, value)) }),
|
|
7507
|
-
records.length === 0 && /* @__PURE__ */ (0,
|
|
7508
|
-
/* @__PURE__ */ (0,
|
|
7921
|
+
records.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyText }),
|
|
7922
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("ul", { className: "flex flex-col gap-2", children: records.map((record, i) => {
|
|
7509
7923
|
const result = results[i];
|
|
7510
7924
|
const model = models.find((m) => m.id === record.provenance.modelId);
|
|
7511
7925
|
const blocked = !result.ok;
|
|
7512
|
-
return /* @__PURE__ */ (0,
|
|
7926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
7513
7927
|
"li",
|
|
7514
7928
|
{
|
|
7515
7929
|
className: "rounded-md border border-border p-2",
|
|
7516
7930
|
"data-record": record.id,
|
|
7517
7931
|
"data-drift": result.drift.length,
|
|
7518
7932
|
children: [
|
|
7519
|
-
/* @__PURE__ */ (0,
|
|
7520
|
-
/* @__PURE__ */ (0,
|
|
7521
|
-
/* @__PURE__ */ (0,
|
|
7522
|
-
record.kind !== "generate" && /* @__PURE__ */ (0,
|
|
7933
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 text-xs", children: [
|
|
7934
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "font-medium", children: model?.name ?? record.provenance.modelId }),
|
|
7935
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
7936
|
+
record.kind !== "generate" && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { "data-kind": "", children: [
|
|
7523
7937
|
record.kind,
|
|
7524
7938
|
" \xB7 "
|
|
7525
7939
|
] }),
|
|
7526
|
-
/* @__PURE__ */ (0,
|
|
7527
|
-
record.seed !== void 0 && /* @__PURE__ */ (0,
|
|
7940
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("time", { dateTime: record.createdAt, children: record.createdAt.replace("T", " ").slice(0, 16) }),
|
|
7941
|
+
record.seed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
|
|
7528
7942
|
" \xB7 seed ",
|
|
7529
7943
|
record.seed
|
|
7530
7944
|
] })
|
|
7531
7945
|
] })
|
|
7532
7946
|
] }),
|
|
7533
|
-
/* @__PURE__ */ (0,
|
|
7534
|
-
record.assets.length > 0 && /* @__PURE__ */ (0,
|
|
7947
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "mt-1 line-clamp-3 break-words text-xs", "data-record-prompt": "", children: record.provenance.resolvedPrompt }),
|
|
7948
|
+
record.assets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "mt-1 flex flex-wrap gap-1", children: record.assets.map((asset) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
7535
7949
|
"span",
|
|
7536
7950
|
{
|
|
7537
7951
|
className: "rounded-full bg-muted px-2 py-0.5 text-[10px]",
|
|
@@ -7545,16 +7959,16 @@ var GenerationHistory = ({
|
|
|
7545
7959
|
`${asset.role}:${asset.id}`
|
|
7546
7960
|
)) }),
|
|
7547
7961
|
renderPreview?.(record),
|
|
7548
|
-
result.drift.length > 0 && /* @__PURE__ */ (0,
|
|
7549
|
-
/* @__PURE__ */ (0,
|
|
7962
|
+
result.drift.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.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_runtime37.jsxs)("li", { className: severityClass[item.severity], "data-drift-type": item.type, children: [
|
|
7963
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("strong", { children: [
|
|
7550
7964
|
import_generation4.DRIFT_TYPE_LABELS[item.type],
|
|
7551
7965
|
":"
|
|
7552
7966
|
] }),
|
|
7553
7967
|
" ",
|
|
7554
7968
|
item.message
|
|
7555
7969
|
] }, j)) }),
|
|
7556
|
-
/* @__PURE__ */ (0,
|
|
7557
|
-
onRecreate && /* @__PURE__ */ (0,
|
|
7970
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "mt-2 flex gap-2", children: [
|
|
7971
|
+
onRecreate && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
7558
7972
|
"button",
|
|
7559
7973
|
{
|
|
7560
7974
|
type: "button",
|
|
@@ -7566,7 +7980,7 @@ var GenerationHistory = ({
|
|
|
7566
7980
|
children: "Recreate"
|
|
7567
7981
|
}
|
|
7568
7982
|
),
|
|
7569
|
-
onVariation && /* @__PURE__ */ (0,
|
|
7983
|
+
onVariation && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
7570
7984
|
"button",
|
|
7571
7985
|
{
|
|
7572
7986
|
type: "button",
|
|
@@ -7576,7 +7990,7 @@ var GenerationHistory = ({
|
|
|
7576
7990
|
children: "Variation"
|
|
7577
7991
|
}
|
|
7578
7992
|
),
|
|
7579
|
-
onRemove && /* @__PURE__ */ (0,
|
|
7993
|
+
onRemove && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
7580
7994
|
"button",
|
|
7581
7995
|
{
|
|
7582
7996
|
type: "button",
|
|
@@ -7596,19 +8010,19 @@ var GenerationHistory = ({
|
|
|
7596
8010
|
};
|
|
7597
8011
|
|
|
7598
8012
|
// src/find-replace/useFindReplace.ts
|
|
7599
|
-
var
|
|
8013
|
+
var import_react56 = require("react");
|
|
7600
8014
|
var import_editor16 = require("@pixerate/editor");
|
|
7601
8015
|
var noopUnsubscribe2 = () => {
|
|
7602
8016
|
};
|
|
7603
8017
|
function useFindReplace(editor) {
|
|
7604
8018
|
const store = (0, import_editor16.getFindReplaceStore)(editor ?? null);
|
|
7605
|
-
const subscribe = (0,
|
|
8019
|
+
const subscribe = (0, import_react56.useCallback)(
|
|
7606
8020
|
(onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe2,
|
|
7607
8021
|
[store]
|
|
7608
8022
|
);
|
|
7609
8023
|
const getSnapshot = () => store?.getSnapshot() ?? import_editor16.EMPTY_FIND_REPLACE_SNAPSHOT;
|
|
7610
|
-
const snapshot = (0,
|
|
7611
|
-
return (0,
|
|
8024
|
+
const snapshot = (0, import_react56.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
8025
|
+
return (0, import_react56.useMemo)(() => {
|
|
7612
8026
|
const run = (fn) => {
|
|
7613
8027
|
if (editor && !editor.isDestroyed && store) fn(editor);
|
|
7614
8028
|
};
|
|
@@ -7632,9 +8046,9 @@ function useFindReplace(editor) {
|
|
|
7632
8046
|
}
|
|
7633
8047
|
|
|
7634
8048
|
// src/find-replace/FindReplaceBar.tsx
|
|
7635
|
-
var
|
|
8049
|
+
var import_react57 = require("react");
|
|
7636
8050
|
var import_editor17 = require("@pixerate/editor");
|
|
7637
|
-
var
|
|
8051
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
7638
8052
|
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";
|
|
7639
8053
|
var buttonClass5 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
|
|
7640
8054
|
var toggleClass = (on) => `${buttonClass5} font-mono ${on ? "bg-primary/10 text-primary" : "text-muted-foreground"}`;
|
|
@@ -7647,10 +8061,10 @@ var FindReplaceBar = ({
|
|
|
7647
8061
|
onClose
|
|
7648
8062
|
}) => {
|
|
7649
8063
|
const find = useFindReplace(editor);
|
|
7650
|
-
const findInput = (0,
|
|
7651
|
-
const [moreOpen, setMoreOpen] = (0,
|
|
8064
|
+
const findInput = (0, import_react57.useRef)(null);
|
|
8065
|
+
const [moreOpen, setMoreOpen] = (0, import_react57.useState)(false);
|
|
7652
8066
|
const visible = find.available && (alwaysOpen || find.open);
|
|
7653
|
-
(0,
|
|
8067
|
+
(0, import_react57.useEffect)(() => {
|
|
7654
8068
|
if (!visible || find.focusRequest === 0) return;
|
|
7655
8069
|
findInput.current?.focus();
|
|
7656
8070
|
findInput.current?.select();
|
|
@@ -7688,9 +8102,9 @@ var FindReplaceBar = ({
|
|
|
7688
8102
|
if (isMod(e)) find.replaceAll();
|
|
7689
8103
|
else find.replace();
|
|
7690
8104
|
};
|
|
7691
|
-
return /* @__PURE__ */ (0,
|
|
7692
|
-
/* @__PURE__ */ (0,
|
|
7693
|
-
/* @__PURE__ */ (0,
|
|
8105
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
|
|
8106
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
8107
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
7694
8108
|
"button",
|
|
7695
8109
|
{
|
|
7696
8110
|
type: "button",
|
|
@@ -7701,7 +8115,7 @@ var FindReplaceBar = ({
|
|
|
7701
8115
|
children: showReplace ? "\u25BE" : "\u25B8"
|
|
7702
8116
|
}
|
|
7703
8117
|
),
|
|
7704
|
-
/* @__PURE__ */ (0,
|
|
8118
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
7705
8119
|
"input",
|
|
7706
8120
|
{
|
|
7707
8121
|
ref: findInput,
|
|
@@ -7715,7 +8129,7 @@ var FindReplaceBar = ({
|
|
|
7715
8129
|
onKeyDown: onFindKeyDown
|
|
7716
8130
|
}
|
|
7717
8131
|
),
|
|
7718
|
-
import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0,
|
|
8132
|
+
import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
7719
8133
|
"button",
|
|
7720
8134
|
{
|
|
7721
8135
|
type: "button",
|
|
@@ -7728,7 +8142,7 @@ var FindReplaceBar = ({
|
|
|
7728
8142
|
},
|
|
7729
8143
|
t.key
|
|
7730
8144
|
)),
|
|
7731
|
-
/* @__PURE__ */ (0,
|
|
8145
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
7732
8146
|
"span",
|
|
7733
8147
|
{
|
|
7734
8148
|
className: `min-w-[5rem] px-1 text-center text-xs ${find.error ? "text-destructive" : "text-muted-foreground"}`,
|
|
@@ -7738,9 +8152,9 @@ var FindReplaceBar = ({
|
|
|
7738
8152
|
children: status
|
|
7739
8153
|
}
|
|
7740
8154
|
),
|
|
7741
|
-
/* @__PURE__ */ (0,
|
|
7742
|
-
/* @__PURE__ */ (0,
|
|
7743
|
-
showMoreOptions && /* @__PURE__ */ (0,
|
|
8155
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
|
|
8156
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
|
|
8157
|
+
showMoreOptions && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
7744
8158
|
"button",
|
|
7745
8159
|
{
|
|
7746
8160
|
type: "button",
|
|
@@ -7751,10 +8165,10 @@ var FindReplaceBar = ({
|
|
|
7751
8165
|
children: "\u2026"
|
|
7752
8166
|
}
|
|
7753
8167
|
),
|
|
7754
|
-
/* @__PURE__ */ (0,
|
|
8168
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Close find", onClick: close, children: "\xD7" })
|
|
7755
8169
|
] }),
|
|
7756
|
-
showReplace && /* @__PURE__ */ (0,
|
|
7757
|
-
/* @__PURE__ */ (0,
|
|
8170
|
+
showReplace && /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-1 pl-7", children: [
|
|
8171
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
7758
8172
|
"input",
|
|
7759
8173
|
{
|
|
7760
8174
|
type: "text",
|
|
@@ -7766,7 +8180,7 @@ var FindReplaceBar = ({
|
|
|
7766
8180
|
onKeyDown: onReplaceKeyDown
|
|
7767
8181
|
}
|
|
7768
8182
|
),
|
|
7769
|
-
/* @__PURE__ */ (0,
|
|
8183
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
7770
8184
|
"button",
|
|
7771
8185
|
{
|
|
7772
8186
|
type: "button",
|
|
@@ -7776,11 +8190,11 @@ var FindReplaceBar = ({
|
|
|
7776
8190
|
children: "Replace"
|
|
7777
8191
|
}
|
|
7778
8192
|
),
|
|
7779
|
-
/* @__PURE__ */ (0,
|
|
7780
|
-
find.lastReplaceCount !== null && /* @__PURE__ */ (0,
|
|
8193
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("button", { type: "button", className: buttonClass5, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
|
|
8194
|
+
find.lastReplaceCount !== null && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "px-1 text-xs text-muted-foreground", "aria-live": "polite", children: find.lastReplaceCount === 1 ? "1 replaced" : `${find.lastReplaceCount} replaced` })
|
|
7781
8195
|
] }),
|
|
7782
|
-
showMoreOptions && moreOpen && /* @__PURE__ */ (0,
|
|
7783
|
-
/* @__PURE__ */ (0,
|
|
8196
|
+
showMoreOptions && moreOpen && /* @__PURE__ */ (0, import_jsx_runtime38.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_runtime38.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
8197
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
7784
8198
|
"input",
|
|
7785
8199
|
{
|
|
7786
8200
|
type: "checkbox",
|
|
@@ -7794,12 +8208,12 @@ var FindReplaceBar = ({
|
|
|
7794
8208
|
};
|
|
7795
8209
|
|
|
7796
8210
|
// src/tables/useTableMenu.ts
|
|
7797
|
-
var
|
|
8211
|
+
var import_react58 = require("react");
|
|
7798
8212
|
var import_editor18 = require("@pixerate/editor");
|
|
7799
8213
|
function useTableMenu(editor) {
|
|
7800
|
-
const store = (0,
|
|
7801
|
-
const snapshot = (0,
|
|
7802
|
-
return (0,
|
|
8214
|
+
const store = (0, import_react58.useMemo)(() => (0, import_editor18.createTableStore)(editor), [editor]);
|
|
8215
|
+
const snapshot = (0, import_react58.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
8216
|
+
return (0, import_react58.useMemo)(
|
|
7803
8217
|
() => ({
|
|
7804
8218
|
...snapshot,
|
|
7805
8219
|
run: (action, params) => (0, import_editor18.runTableAction)(editor, action, params, { focus: true }),
|
|
@@ -7810,9 +8224,9 @@ function useTableMenu(editor) {
|
|
|
7810
8224
|
}
|
|
7811
8225
|
|
|
7812
8226
|
// src/tables/TableToolbar.tsx
|
|
7813
|
-
var
|
|
8227
|
+
var import_react59 = __toESM(require("react"), 1);
|
|
7814
8228
|
var import_editor19 = require("@pixerate/editor");
|
|
7815
|
-
var
|
|
8229
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
7816
8230
|
var keepSelection2 = (event) => event.preventDefault();
|
|
7817
8231
|
var TableToolbar = ({
|
|
7818
8232
|
editor,
|
|
@@ -7826,14 +8240,14 @@ var TableToolbar = ({
|
|
|
7826
8240
|
}) => {
|
|
7827
8241
|
const table = useTableMenu(editor);
|
|
7828
8242
|
if (!editor || !table.inTable && !showWhenOutside) return null;
|
|
7829
|
-
return /* @__PURE__ */ (0,
|
|
8243
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
|
|
7830
8244
|
const status = table.check(item.action, item.params);
|
|
7831
8245
|
const enabled = status === true;
|
|
7832
8246
|
const active = item.active?.(table);
|
|
7833
8247
|
const separator = index > 0 && items[index - 1].group !== item.group;
|
|
7834
|
-
return /* @__PURE__ */ (0,
|
|
7835
|
-
separator && /* @__PURE__ */ (0,
|
|
7836
|
-
/* @__PURE__ */ (0,
|
|
8248
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_react59.default.Fragment, { children: [
|
|
8249
|
+
separator && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: separatorClassName, "aria-hidden": "true" }),
|
|
8250
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
7837
8251
|
"button",
|
|
7838
8252
|
{
|
|
7839
8253
|
type: "button",
|
|
@@ -7855,8 +8269,8 @@ var TableToolbar = ({
|
|
|
7855
8269
|
};
|
|
7856
8270
|
|
|
7857
8271
|
// src/tables/InsertTableGrid.tsx
|
|
7858
|
-
var
|
|
7859
|
-
var
|
|
8272
|
+
var import_react60 = require("react");
|
|
8273
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
7860
8274
|
var keepSelection3 = (event) => event.preventDefault();
|
|
7861
8275
|
var InsertTableGrid = ({
|
|
7862
8276
|
editor,
|
|
@@ -7869,14 +8283,14 @@ var InsertTableGrid = ({
|
|
|
7869
8283
|
onInsert
|
|
7870
8284
|
}) => {
|
|
7871
8285
|
const table = useTableMenu(editor);
|
|
7872
|
-
const [hover, setHover] = (0,
|
|
8286
|
+
const [hover, setHover] = (0, import_react60.useState)(null);
|
|
7873
8287
|
const status = table.actions.insertTable;
|
|
7874
8288
|
const disabled = !editor || !status.enabled;
|
|
7875
8289
|
const insert = (size) => {
|
|
7876
8290
|
if (table.run("insertTable", { ...size, withHeaderRow })) onInsert?.(size);
|
|
7877
8291
|
setHover(null);
|
|
7878
8292
|
};
|
|
7879
|
-
return /* @__PURE__ */ (0,
|
|
8293
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
7880
8294
|
"div",
|
|
7881
8295
|
{
|
|
7882
8296
|
className,
|
|
@@ -7886,7 +8300,7 @@ var InsertTableGrid = ({
|
|
|
7886
8300
|
"data-insert-table-grid": "",
|
|
7887
8301
|
onMouseLeave: () => setHover(null),
|
|
7888
8302
|
children: [
|
|
7889
|
-
/* @__PURE__ */ (0,
|
|
8303
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
7890
8304
|
"div",
|
|
7891
8305
|
{
|
|
7892
8306
|
role: "grid",
|
|
@@ -7895,7 +8309,7 @@ var InsertTableGrid = ({
|
|
|
7895
8309
|
children: Array.from({ length: rows * cols }, (_, i) => {
|
|
7896
8310
|
const size = { rows: Math.floor(i / cols) + 1, cols: i % cols + 1 };
|
|
7897
8311
|
const active = !!hover && size.rows <= hover.rows && size.cols <= hover.cols;
|
|
7898
|
-
return /* @__PURE__ */ (0,
|
|
8312
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
7899
8313
|
"button",
|
|
7900
8314
|
{
|
|
7901
8315
|
type: "button",
|
|
@@ -7915,7 +8329,7 @@ var InsertTableGrid = ({
|
|
|
7915
8329
|
})
|
|
7916
8330
|
}
|
|
7917
8331
|
),
|
|
7918
|
-
/* @__PURE__ */ (0,
|
|
8332
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { "aria-live": "polite", "data-testid": "insert-table-size", children: disabled ? status.reason : hover ? `${hover.rows} \xD7 ${hover.cols}` : "Insert table" })
|
|
7919
8333
|
]
|
|
7920
8334
|
}
|
|
7921
8335
|
);
|
|
@@ -7923,31 +8337,31 @@ var InsertTableGrid = ({
|
|
|
7923
8337
|
|
|
7924
8338
|
// src/tables/TableBubbleMenu.tsx
|
|
7925
8339
|
var import_editor20 = require("@pixerate/editor");
|
|
7926
|
-
var
|
|
8340
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
7927
8341
|
var TableBubbleMenu = ({
|
|
7928
8342
|
editor,
|
|
7929
8343
|
children,
|
|
7930
8344
|
toolbarProps,
|
|
7931
8345
|
pluginKey = "tableBubbleMenu",
|
|
7932
8346
|
...rest
|
|
7933
|
-
}) => /* @__PURE__ */ (0,
|
|
8347
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(BubbleMenu, { editor, pluginKey, shouldShow: import_editor20.shouldShowTableBubbleMenu, ...rest, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(TableToolbar, { editor, ...toolbarProps }) });
|
|
7934
8348
|
|
|
7935
8349
|
// src/chart-node/ChartNodeView.tsx
|
|
7936
8350
|
var import_client = require("react-dom/client");
|
|
7937
8351
|
|
|
7938
8352
|
// src/chart/ChartCanvas.tsx
|
|
7939
|
-
var
|
|
8353
|
+
var import_react62 = require("react");
|
|
7940
8354
|
var import_chart2 = require("@pixerate/editor/chart");
|
|
7941
8355
|
|
|
7942
8356
|
// src/chart/useChartEditor.ts
|
|
7943
|
-
var
|
|
8357
|
+
var import_react61 = require("react");
|
|
7944
8358
|
var import_chart = require("@pixerate/editor/chart");
|
|
7945
8359
|
function useChartState(controller) {
|
|
7946
|
-
return (0,
|
|
8360
|
+
return (0, import_react61.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
|
|
7947
8361
|
}
|
|
7948
8362
|
|
|
7949
8363
|
// src/chart/ChartCanvas.tsx
|
|
7950
|
-
var
|
|
8364
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
7951
8365
|
function renderChartMark(mark, fontFamily, interactive) {
|
|
7952
8366
|
const common = {
|
|
7953
8367
|
"data-role": mark.role,
|
|
@@ -7959,9 +8373,9 @@ function renderChartMark(mark, fontFamily, interactive) {
|
|
|
7959
8373
|
};
|
|
7960
8374
|
switch (mark.kind) {
|
|
7961
8375
|
case "rect":
|
|
7962
|
-
return /* @__PURE__ */ (0,
|
|
8376
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.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);
|
|
7963
8377
|
case "path":
|
|
7964
|
-
return /* @__PURE__ */ (0,
|
|
8378
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7965
8379
|
"path",
|
|
7966
8380
|
{
|
|
7967
8381
|
...common,
|
|
@@ -7974,11 +8388,11 @@ function renderChartMark(mark, fontFamily, interactive) {
|
|
|
7974
8388
|
mark.key
|
|
7975
8389
|
);
|
|
7976
8390
|
case "circle":
|
|
7977
|
-
return /* @__PURE__ */ (0,
|
|
8391
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("circle", { ...common, cx: mark.cx, cy: mark.cy, r: mark.r, style: { fill: mark.fill, stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
|
|
7978
8392
|
case "line":
|
|
7979
|
-
return /* @__PURE__ */ (0,
|
|
8393
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.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);
|
|
7980
8394
|
case "text":
|
|
7981
|
-
return /* @__PURE__ */ (0,
|
|
8395
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
7982
8396
|
"text",
|
|
7983
8397
|
{
|
|
7984
8398
|
...common,
|
|
@@ -7995,23 +8409,23 @@ function renderChartMark(mark, fontFamily, interactive) {
|
|
|
7995
8409
|
}
|
|
7996
8410
|
}
|
|
7997
8411
|
function ChartPresenceLayer({ presence }) {
|
|
7998
|
-
const { actors } = (0,
|
|
7999
|
-
return /* @__PURE__ */ (0,
|
|
8000
|
-
/* @__PURE__ */ (0,
|
|
8001
|
-
/* @__PURE__ */ (0,
|
|
8002
|
-
/* @__PURE__ */ (0,
|
|
8003
|
-
/* @__PURE__ */ (0,
|
|
8412
|
+
const { actors } = (0, import_react62.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
|
|
8413
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("g", { "data-chart-presence": "", pointerEvents: "none", children: actors.map((a) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("g", { transform: `translate(${a.x} ${a.y})`, "data-actor": a.id, children: [
|
|
8414
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.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 }),
|
|
8415
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("g", { transform: "translate(13 16)", children: [
|
|
8416
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.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 } }),
|
|
8417
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("text", { x: 6, y: 9, dominantBaseline: "central", style: { fill: "#ffffff", fontSize: 11, fontWeight: 600, fontFamily: "inherit" }, children: a.message ?? a.name })
|
|
8004
8418
|
] })
|
|
8005
8419
|
] }, a.id)) });
|
|
8006
8420
|
}
|
|
8007
8421
|
function ChartCanvas({ controller, width = 640, height = 400, responsive = true, theme, editable = true, measureText, emptyMessage, className, presence, sceneRef }) {
|
|
8008
8422
|
const state = useChartState(controller);
|
|
8009
|
-
const wrapper = (0,
|
|
8010
|
-
const svg = (0,
|
|
8011
|
-
const drag = (0,
|
|
8012
|
-
const [measured, setMeasured] = (0,
|
|
8013
|
-
const [frozen, setFrozen] = (0,
|
|
8014
|
-
(0,
|
|
8423
|
+
const wrapper = (0, import_react62.useRef)(null);
|
|
8424
|
+
const svg = (0, import_react62.useRef)(null);
|
|
8425
|
+
const drag = (0, import_react62.useRef)(null);
|
|
8426
|
+
const [measured, setMeasured] = (0, import_react62.useState)(null);
|
|
8427
|
+
const [frozen, setFrozen] = (0, import_react62.useState)(null);
|
|
8428
|
+
(0, import_react62.useEffect)(() => {
|
|
8015
8429
|
const el = wrapper.current;
|
|
8016
8430
|
if (!responsive || !el || typeof ResizeObserver === "undefined") return;
|
|
8017
8431
|
const observer = new ResizeObserver(([entry]) => {
|
|
@@ -8022,8 +8436,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
|
|
|
8022
8436
|
return () => observer.disconnect();
|
|
8023
8437
|
}, [responsive]);
|
|
8024
8438
|
const sceneWidth = responsive && measured || width;
|
|
8025
|
-
const fullTheme = (0,
|
|
8026
|
-
const scene = (0,
|
|
8439
|
+
const fullTheme = (0, import_react62.useMemo)(() => ({ ...import_chart2.CSS_VARIABLE_CHART_THEME, ...theme }), [theme]);
|
|
8440
|
+
const scene = (0, import_react62.useMemo)(
|
|
8027
8441
|
() => (0, import_chart2.layoutChart)(state.spec, {
|
|
8028
8442
|
width: sceneWidth,
|
|
8029
8443
|
height,
|
|
@@ -8039,8 +8453,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
|
|
|
8039
8453
|
[state.spec, state.selection, sceneWidth, height, fullTheme, editable, measureText, emptyMessage, frozen]
|
|
8040
8454
|
);
|
|
8041
8455
|
if (sceneRef) sceneRef.current = scene;
|
|
8042
|
-
const byKey = (0,
|
|
8043
|
-
(0,
|
|
8456
|
+
const byKey = (0, import_react62.useMemo)(() => new Map(scene.marks.map((m) => [m.key, m])), [scene]);
|
|
8457
|
+
(0, import_react62.useEffect)(() => () => drag.current?.end(), []);
|
|
8044
8458
|
const scenePoint = (e) => (0, import_chart2.chartClientToScene)(scene, svg.current.getBoundingClientRect(), e.clientX, e.clientY);
|
|
8045
8459
|
const onPointerDown = (e) => {
|
|
8046
8460
|
if (!editable || e.button !== 0) return;
|
|
@@ -8073,7 +8487,7 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
|
|
|
8073
8487
|
if (editable && (0, import_chart2.handleChartKey)(controller, scene, e)) e.preventDefault();
|
|
8074
8488
|
};
|
|
8075
8489
|
const label = state.spec.title || "Chart";
|
|
8076
|
-
return /* @__PURE__ */ (0,
|
|
8490
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { ref: wrapper, className: `w-full ${className ?? ""}`, "data-chart-canvas": "", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
8077
8491
|
"svg",
|
|
8078
8492
|
{
|
|
8079
8493
|
ref: svg,
|
|
@@ -8091,14 +8505,14 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
|
|
|
8091
8505
|
onKeyDown,
|
|
8092
8506
|
children: [
|
|
8093
8507
|
scene.marks.map((m) => renderChartMark(m, scene.theme.fontFamily, editable)),
|
|
8094
|
-
presence && /* @__PURE__ */ (0,
|
|
8508
|
+
presence && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartPresenceLayer, { presence })
|
|
8095
8509
|
]
|
|
8096
8510
|
}
|
|
8097
8511
|
) });
|
|
8098
8512
|
}
|
|
8099
8513
|
|
|
8100
8514
|
// src/chart/ChartDataGrid.tsx
|
|
8101
|
-
var
|
|
8515
|
+
var import_react63 = require("react");
|
|
8102
8516
|
var import_chart3 = require("@pixerate/editor/chart");
|
|
8103
8517
|
|
|
8104
8518
|
// src/chart/styles.ts
|
|
@@ -8111,11 +8525,11 @@ var chartSectionClass = "space-y-2 border-b border-border pb-3 last:border-b-0";
|
|
|
8111
8525
|
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";
|
|
8112
8526
|
|
|
8113
8527
|
// src/chart/ChartDataGrid.tsx
|
|
8114
|
-
var
|
|
8528
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
8115
8529
|
function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
|
|
8116
|
-
const [draft, setDraft] = (0,
|
|
8117
|
-
const typing = (0,
|
|
8118
|
-
(0,
|
|
8530
|
+
const [draft, setDraft] = (0, import_react63.useState)(value);
|
|
8531
|
+
const typing = (0, import_react63.useRef)(false);
|
|
8532
|
+
(0, import_react63.useEffect)(() => {
|
|
8119
8533
|
if (!typing.current) setDraft(value);
|
|
8120
8534
|
}, [value]);
|
|
8121
8535
|
const commit = () => {
|
|
@@ -8124,7 +8538,7 @@ function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
|
|
|
8124
8538
|
if (draft === value) return;
|
|
8125
8539
|
if (onCommit(draft) === false) setDraft(value);
|
|
8126
8540
|
};
|
|
8127
|
-
return /* @__PURE__ */ (0,
|
|
8541
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
8128
8542
|
"input",
|
|
8129
8543
|
{
|
|
8130
8544
|
...rest,
|
|
@@ -8159,15 +8573,15 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
8159
8573
|
e.preventDefault();
|
|
8160
8574
|
controller.pasteCells(row, column, text);
|
|
8161
8575
|
};
|
|
8162
|
-
return /* @__PURE__ */ (0,
|
|
8163
|
-
/* @__PURE__ */ (0,
|
|
8164
|
-
/* @__PURE__ */ (0,
|
|
8165
|
-
/* @__PURE__ */ (0,
|
|
8576
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: `overflow-auto rounded-md border border-border ${className ?? ""}`, "data-chart-grid": "", children: [
|
|
8577
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("table", { className: "w-full border-collapse text-xs", children: [
|
|
8578
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("thead", { className: "bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("tr", { children: [
|
|
8579
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("th", { className: "border-b border-r border-border px-2 py-1 text-left font-medium text-muted-foreground", children: categoryHeader }),
|
|
8166
8580
|
spec.series.map((s, si) => {
|
|
8167
8581
|
const color = (0, import_chart3.chartSeriesColor)(spec, si);
|
|
8168
8582
|
const selected = selection?.kind === "series" && selection.seriesId === s.id;
|
|
8169
|
-
return /* @__PURE__ */ (0,
|
|
8170
|
-
/* @__PURE__ */ (0,
|
|
8583
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.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_runtime43.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
8584
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
8171
8585
|
"input",
|
|
8172
8586
|
{
|
|
8173
8587
|
type: "color",
|
|
@@ -8180,7 +8594,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
8180
8594
|
className: "h-5 w-5 shrink-0 cursor-pointer rounded border-0 bg-transparent p-0"
|
|
8181
8595
|
}
|
|
8182
8596
|
),
|
|
8183
|
-
/* @__PURE__ */ (0,
|
|
8597
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
8184
8598
|
ChartCommitInput,
|
|
8185
8599
|
{
|
|
8186
8600
|
value: s.name,
|
|
@@ -8190,8 +8604,8 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
8190
8604
|
className: `${chartInputClass} h-6 min-w-[5rem] border-transparent bg-transparent font-medium ${s.hidden ? "text-muted-foreground line-through" : ""}`
|
|
8191
8605
|
}
|
|
8192
8606
|
),
|
|
8193
|
-
!readOnly && /* @__PURE__ */ (0,
|
|
8194
|
-
/* @__PURE__ */ (0,
|
|
8607
|
+
!readOnly && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
|
|
8608
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
8195
8609
|
"button",
|
|
8196
8610
|
{
|
|
8197
8611
|
type: "button",
|
|
@@ -8204,16 +8618,16 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
8204
8618
|
children: s.hidden ? "\u25CB" : "\u25CF"
|
|
8205
8619
|
}
|
|
8206
8620
|
),
|
|
8207
|
-
/* @__PURE__ */ (0,
|
|
8621
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.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" })
|
|
8208
8622
|
] })
|
|
8209
8623
|
] }) }, s.id);
|
|
8210
8624
|
}),
|
|
8211
|
-
!readOnly && /* @__PURE__ */ (0,
|
|
8625
|
+
!readOnly && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("th", { className: "w-8 border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Add series", "aria-label": "Add series", "data-action": "add-series", onClick: () => controller.addSeries(), children: "+" }) })
|
|
8212
8626
|
] }) }),
|
|
8213
|
-
/* @__PURE__ */ (0,
|
|
8627
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("tbody", { children: spec.categories.map((category, i) => {
|
|
8214
8628
|
const rowSelected = selection?.kind === "category" && selection.index === i;
|
|
8215
|
-
return /* @__PURE__ */ (0,
|
|
8216
|
-
/* @__PURE__ */ (0,
|
|
8629
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("tr", { "data-category-index": i, className: rowSelected ? "bg-primary/10" : void 0, children: [
|
|
8630
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("th", { className: "border-b border-r border-border p-0 text-left font-normal", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
8217
8631
|
ChartCommitInput,
|
|
8218
8632
|
{
|
|
8219
8633
|
value: category,
|
|
@@ -8227,7 +8641,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
8227
8641
|
spec.series.map((s) => {
|
|
8228
8642
|
const value = s.values[i];
|
|
8229
8643
|
const selected = selection?.kind === "point" && selection.seriesId === s.id && selection.index === i;
|
|
8230
|
-
return /* @__PURE__ */ (0,
|
|
8644
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("td", { className: `border-b border-r border-border p-0 ${selected ? "bg-primary/10" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
8231
8645
|
ChartCommitInput,
|
|
8232
8646
|
{
|
|
8233
8647
|
value: value === null || value === void 0 ? "" : String(value),
|
|
@@ -8242,38 +8656,38 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
|
|
|
8242
8656
|
}
|
|
8243
8657
|
) }, s.id);
|
|
8244
8658
|
}),
|
|
8245
|
-
!readOnly && /* @__PURE__ */ (0,
|
|
8659
|
+
!readOnly && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("td", { className: "border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Delete category", "aria-label": `Delete ${category}`, "data-action": "remove-category", onClick: () => controller.removeCategory(i), children: "\xD7" }) })
|
|
8246
8660
|
] }, i);
|
|
8247
8661
|
}) })
|
|
8248
8662
|
] }),
|
|
8249
|
-
!readOnly && /* @__PURE__ */ (0,
|
|
8663
|
+
!readOnly && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "p-1", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: `${chartButtonClass} h-6 border-dashed`, "data-action": "add-category", onClick: () => controller.addCategory(), children: "+ Add category" }) })
|
|
8250
8664
|
] });
|
|
8251
8665
|
}
|
|
8252
8666
|
|
|
8253
8667
|
// src/chart/ChartInspector.tsx
|
|
8254
|
-
var
|
|
8668
|
+
var import_react64 = require("react");
|
|
8255
8669
|
var import_chart4 = require("@pixerate/editor/chart");
|
|
8256
|
-
var
|
|
8670
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
8257
8671
|
var cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
8258
8672
|
function Field({ label, htmlFor, children }) {
|
|
8259
|
-
return /* @__PURE__ */ (0,
|
|
8260
|
-
/* @__PURE__ */ (0,
|
|
8261
|
-
/* @__PURE__ */ (0,
|
|
8673
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
8674
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("label", { htmlFor, className: `${chartLabelClass} w-20 shrink-0`, children: label }),
|
|
8675
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "min-w-0 flex-1", children })
|
|
8262
8676
|
] });
|
|
8263
8677
|
}
|
|
8264
8678
|
function Toggle({ label, checked, onChange, name }) {
|
|
8265
|
-
return /* @__PURE__ */ (0,
|
|
8266
|
-
/* @__PURE__ */ (0,
|
|
8679
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { className: "flex cursor-pointer items-center gap-2 text-xs text-foreground", children: [
|
|
8680
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { type: "checkbox", className: "h-3.5 w-3.5 accent-primary", checked, "data-option": name, onChange: (e) => onChange(e.currentTarget.checked) }),
|
|
8267
8681
|
label
|
|
8268
8682
|
] });
|
|
8269
8683
|
}
|
|
8270
8684
|
function Select({ id, value, options, onChange, name, labels }) {
|
|
8271
|
-
return /* @__PURE__ */ (0,
|
|
8685
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("select", { id, className: chartInputClass, value, "data-option": name, onChange: (e) => onChange(e.currentTarget.value), children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: o, children: labels?.[o] ?? cap(o) }, o)) });
|
|
8272
8686
|
}
|
|
8273
8687
|
function AxisSection({ controller, axis, value, idBase, horizontal, numeric = false, scales = false }) {
|
|
8274
8688
|
const set = (patch) => controller.setAxis(axis, patch);
|
|
8275
8689
|
const setFormat = (patch) => set({ format: { ...value.format, ...patch } });
|
|
8276
|
-
const bound = (key2) => /* @__PURE__ */ (0,
|
|
8690
|
+
const bound = (key2) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
8277
8691
|
ChartCommitInput,
|
|
8278
8692
|
{
|
|
8279
8693
|
id: `${idBase}-${axis}-${key2}`,
|
|
@@ -8288,26 +8702,26 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
|
|
|
8288
8702
|
const name = axis === "x" ? numeric ? "X axis" : "Category axis" : axis === "y" ? "Value axis" : "Secondary axis";
|
|
8289
8703
|
const valueAxis = axis !== "x" || numeric;
|
|
8290
8704
|
const key = axis === "y2" ? "yAxis2" : `${axis}Axis`;
|
|
8291
|
-
return /* @__PURE__ */ (0,
|
|
8292
|
-
/* @__PURE__ */ (0,
|
|
8293
|
-
/* @__PURE__ */ (0,
|
|
8705
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: chartSectionClass, "data-section": `axis-${axis}`, children: [
|
|
8706
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
8707
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("h4", { className: "text-xs font-semibold text-foreground", children: [
|
|
8294
8708
|
name,
|
|
8295
|
-
/* @__PURE__ */ (0,
|
|
8709
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "ml-1 font-normal text-muted-foreground", children: [
|
|
8296
8710
|
"(",
|
|
8297
8711
|
axis === "x" ? horizontal ? "left" : "bottom" : axis === "y2" ? horizontal ? "top" : "right" : horizontal ? "bottom" : "left",
|
|
8298
8712
|
")"
|
|
8299
8713
|
] })
|
|
8300
8714
|
] }),
|
|
8301
|
-
/* @__PURE__ */ (0,
|
|
8715
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Show", name: `${axis}Axis.show`, checked: value.show, onChange: (show) => set({ show }) })
|
|
8302
8716
|
] }),
|
|
8303
|
-
/* @__PURE__ */ (0,
|
|
8304
|
-
/* @__PURE__ */ (0,
|
|
8305
|
-
/* @__PURE__ */ (0,
|
|
8306
|
-
axis === "x" && !numeric && /* @__PURE__ */ (0,
|
|
8307
|
-
scales && /* @__PURE__ */ (0,
|
|
8308
|
-
scales && valueAxis && /* @__PURE__ */ (0,
|
|
8717
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Title", htmlFor: `${idBase}-${axis}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartCommitInput, { id: `${idBase}-${axis}-title`, value: value.title, "data-option": `${axis}Axis.title`, className: chartInputClass, onCommit: (title) => void set({ title }) }) }),
|
|
8718
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
|
|
8719
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Grid lines", name: `${key}.gridlines`, checked: value.gridlines, onChange: (gridlines) => set({ gridlines }) }),
|
|
8720
|
+
axis === "x" && !numeric && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Dates", name: "xAxis.kind", checked: value.kind === "date", onChange: (dates) => set({ kind: dates ? "date" : void 0 }) }),
|
|
8721
|
+
scales && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Reverse", name: `${key}.reverse`, checked: !!value.reverse, onChange: (reverse) => set({ reverse }) }),
|
|
8722
|
+
scales && valueAxis && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Log scale", name: `${key}.scale`, checked: value.scale === "log", onChange: (log) => set({ scale: log ? "log" : "linear" }) })
|
|
8309
8723
|
] }),
|
|
8310
|
-
scales && valueAxis && value.scale === "log" && /* @__PURE__ */ (0,
|
|
8724
|
+
scales && valueAxis && value.scale === "log" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Log base", htmlFor: `${idBase}-${axis}-log-base`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
8311
8725
|
ChartCommitInput,
|
|
8312
8726
|
{
|
|
8313
8727
|
id: `${idBase}-${axis}-log-base`,
|
|
@@ -8318,7 +8732,7 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
|
|
|
8318
8732
|
onCommit: (text) => set({ logBase: text.trim() === "" ? void 0 : Number(text) }).ok
|
|
8319
8733
|
}
|
|
8320
8734
|
) }),
|
|
8321
|
-
valueAxis && value.scale !== "log" && /* @__PURE__ */ (0,
|
|
8735
|
+
valueAxis && value.scale !== "log" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Step", htmlFor: `${idBase}-${axis}-step`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
8322
8736
|
ChartCommitInput,
|
|
8323
8737
|
{
|
|
8324
8738
|
id: `${idBase}-${axis}-step`,
|
|
@@ -8330,14 +8744,14 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
|
|
|
8330
8744
|
onCommit: (text) => set({ step: text.trim() === "" ? null : Number(text) }).ok
|
|
8331
8745
|
}
|
|
8332
8746
|
) }),
|
|
8333
|
-
valueAxis && /* @__PURE__ */ (0,
|
|
8334
|
-
/* @__PURE__ */ (0,
|
|
8747
|
+
valueAxis && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
|
|
8748
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Min / max", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex gap-1", children: [
|
|
8335
8749
|
bound("min"),
|
|
8336
8750
|
bound("max")
|
|
8337
8751
|
] }) }),
|
|
8338
|
-
/* @__PURE__ */ (0,
|
|
8339
|
-
/* @__PURE__ */ (0,
|
|
8340
|
-
/* @__PURE__ */ (0,
|
|
8752
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Format", htmlFor: `${idBase}-${axis}-format`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex gap-1", children: [
|
|
8753
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.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 }) }),
|
|
8754
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
8341
8755
|
ChartCommitInput,
|
|
8342
8756
|
{
|
|
8343
8757
|
value: value.format.decimals === void 0 ? "" : String(value.format.decimals),
|
|
@@ -8356,8 +8770,8 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
|
|
|
8356
8770
|
}
|
|
8357
8771
|
)
|
|
8358
8772
|
] }) }),
|
|
8359
|
-
value.format.style === "currency" && /* @__PURE__ */ (0,
|
|
8360
|
-
/* @__PURE__ */ (0,
|
|
8773
|
+
value.format.style === "currency" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Currency", htmlFor: `${idBase}-${axis}-currency`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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() }) }) }),
|
|
8774
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Code", htmlFor: `${idBase}-${axis}-code`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
8361
8775
|
ChartCommitInput,
|
|
8362
8776
|
{
|
|
8363
8777
|
id: `${idBase}-${axis}-code`,
|
|
@@ -8383,15 +8797,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
|
|
|
8383
8797
|
const values = which === "xErrorBars" ? series.x ?? [] : series.values;
|
|
8384
8798
|
const set = (next) => controller.updateSeries(series.id, { [which]: next });
|
|
8385
8799
|
const patch = (p) => bars && set({ ...bars, ...p });
|
|
8386
|
-
return /* @__PURE__ */ (0,
|
|
8387
|
-
/* @__PURE__ */ (0,
|
|
8388
|
-
/* @__PURE__ */ (0,
|
|
8389
|
-
import_chart4.CHART_ERROR_BAR_TYPES.map((t) => /* @__PURE__ */ (0,
|
|
8800
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "space-y-1.5", "data-section": which === "errorBars" ? "error-bars" : "x-error-bars", children: [
|
|
8801
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: which === "errorBars" ? "Error bars" : "X error bars", htmlFor: `${id}-type`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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: [
|
|
8802
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: "", children: "None" }),
|
|
8803
|
+
import_chart4.CHART_ERROR_BAR_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: t, children: import_chart4.CHART_ERROR_BAR_LABELS[t] }, t))
|
|
8390
8804
|
] }) }),
|
|
8391
|
-
bars && (bars.type === "fixed" || bars.type === "percent" || bars.type === "stddev") && /* @__PURE__ */ (0,
|
|
8392
|
-
bars?.type === "custom" && /* @__PURE__ */ (0,
|
|
8393
|
-
/* @__PURE__ */ (0,
|
|
8394
|
-
/* @__PURE__ */ (0,
|
|
8805
|
+
bars && (bars.type === "fixed" || bars.type === "percent" || bars.type === "stddev") && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: bars.type === "percent" ? "Percent" : bars.type === "stddev" ? "Deviations" : "Amount", htmlFor: `${id}-value`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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 }) }),
|
|
8806
|
+
bars?.type === "custom" && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
|
|
8807
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Plus", htmlFor: `${id}-plus`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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 }) }),
|
|
8808
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Minus", htmlFor: `${id}-minus`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
8395
8809
|
ChartCommitInput,
|
|
8396
8810
|
{
|
|
8397
8811
|
id: `${id}-minus`,
|
|
@@ -8408,15 +8822,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
|
|
|
8408
8822
|
}
|
|
8409
8823
|
) })
|
|
8410
8824
|
] }),
|
|
8411
|
-
bars && /* @__PURE__ */ (0,
|
|
8412
|
-
/* @__PURE__ */ (0,
|
|
8413
|
-
/* @__PURE__ */ (0,
|
|
8825
|
+
bars && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
8826
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.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_runtime44.jsx)("option", { value: d, children: d === "both" ? "Both ways" : d === "plus" ? "Plus only" : "Minus only" }, d)) }),
|
|
8827
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Caps", name: `${key}.cap`, checked: bars.cap !== false, onChange: (cap2) => patch({ cap: cap2 }) })
|
|
8414
8828
|
] })
|
|
8415
8829
|
] });
|
|
8416
8830
|
}
|
|
8417
8831
|
function ChartInspector({ controller, sections, className }) {
|
|
8418
8832
|
const { spec, selectedSeries } = useChartState(controller);
|
|
8419
|
-
const idBase = (0,
|
|
8833
|
+
const idBase = (0, import_react64.useId)();
|
|
8420
8834
|
const show = (section) => !sections || sections.includes(section);
|
|
8421
8835
|
const cartesian = (0, import_chart4.isCartesianChart)(spec.type);
|
|
8422
8836
|
const family = (0, import_chart4.chartFamily)(spec);
|
|
@@ -8428,29 +8842,29 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
8428
8842
|
const hasLines = cartesian && types.some((t) => t === "line" || t === "area");
|
|
8429
8843
|
const seriesIndex = selectedSeries ? spec.series.findIndex((s) => s.id === selectedSeries.id) : -1;
|
|
8430
8844
|
const scales = family === "cartesian" || family === "xy";
|
|
8431
|
-
return /* @__PURE__ */ (0,
|
|
8432
|
-
show("type") && /* @__PURE__ */ (0,
|
|
8433
|
-
show("style") && /* @__PURE__ */ (0,
|
|
8434
|
-
/* @__PURE__ */ (0,
|
|
8435
|
-
/* @__PURE__ */ (0,
|
|
8436
|
-
import_chart4.CHART_LAYOUT_PRESETS.map((p) => /* @__PURE__ */ (0,
|
|
8845
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: `space-y-3 text-xs ${className ?? ""}`, "data-chart-inspector": "", children: [
|
|
8846
|
+
show("type") && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: chartSectionClass, "data-section": "type", children: /* @__PURE__ */ (0, import_jsx_runtime44.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_runtime44.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)) }) }),
|
|
8847
|
+
show("style") && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: chartSectionClass, "data-section": "style", children: [
|
|
8848
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Layout", htmlFor: `${idBase}-layout`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("select", { id: `${idBase}-layout`, className: chartInputClass, value: "", "data-option": "preset.layout", onChange: (e) => e.currentTarget.value && controller.applyPreset({ layout: e.currentTarget.value }), children: [
|
|
8849
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: "", children: "Quick layout\u2026" }),
|
|
8850
|
+
import_chart4.CHART_LAYOUT_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: p.id, title: p.description, children: p.label }, p.id))
|
|
8437
8851
|
] }) }),
|
|
8438
|
-
/* @__PURE__ */ (0,
|
|
8439
|
-
/* @__PURE__ */ (0,
|
|
8440
|
-
import_chart4.CHART_COLOR_SCHEMES.map((c) => /* @__PURE__ */ (0,
|
|
8852
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Colours", htmlFor: `${idBase}-colors`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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: [
|
|
8853
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: "", children: "Custom" }),
|
|
8854
|
+
import_chart4.CHART_COLOR_SCHEMES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: c.id, title: c.description, children: c.label }, c.id))
|
|
8441
8855
|
] }) }),
|
|
8442
|
-
!colorCheck.ok && /* @__PURE__ */ (0,
|
|
8443
|
-
/* @__PURE__ */ (0,
|
|
8856
|
+
!colorCheck.ok && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "text-[11px] leading-snug text-amber-600 dark:text-amber-400", "data-chart-color-warning": "", children: colorCheck.issues[0] }),
|
|
8857
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "transpose", onClick: () => controller.transpose(), children: "Switch rows and columns" })
|
|
8444
8858
|
] }),
|
|
8445
|
-
show("titles") && /* @__PURE__ */ (0,
|
|
8446
|
-
/* @__PURE__ */ (0,
|
|
8447
|
-
/* @__PURE__ */ (0,
|
|
8859
|
+
show("titles") && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: chartSectionClass, "data-section": "titles", children: [
|
|
8860
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Title", htmlFor: `${idBase}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartCommitInput, { id: `${idBase}-title`, value: spec.title, "data-option": "title", className: chartInputClass, onCommit: (title) => void controller.setTitle(title) }) }),
|
|
8861
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Subtitle", htmlFor: `${idBase}-subtitle`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartCommitInput, { id: `${idBase}-subtitle`, value: spec.subtitle, "data-option": "subtitle", className: chartInputClass, onCommit: (subtitle) => void controller.setSubtitle(subtitle) }) })
|
|
8448
8862
|
] }),
|
|
8449
|
-
show("options") && /* @__PURE__ */ (0,
|
|
8450
|
-
cartesian && /* @__PURE__ */ (0,
|
|
8451
|
-
hasBars && /* @__PURE__ */ (0,
|
|
8452
|
-
hasLines && /* @__PURE__ */ (0,
|
|
8453
|
-
spec.type === "donut" && /* @__PURE__ */ (0,
|
|
8863
|
+
show("options") && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: chartSectionClass, "data-section": "options", children: [
|
|
8864
|
+
cartesian && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Stacking", htmlFor: `${idBase}-stacking`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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 }) }) }),
|
|
8865
|
+
hasBars && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Bars", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "flex gap-0.5 rounded-md bg-muted p-0.5", children: ["vertical", "horizontal"].map((o) => /* @__PURE__ */ (0, import_jsx_runtime44.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)) }) }),
|
|
8866
|
+
hasLines && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Lines", htmlFor: `${idBase}-curve`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Select, { id: `${idBase}-curve`, name: "curve", value: spec.curve, options: import_chart4.CHART_CURVES, onChange: (curve) => controller.update({ curve }) }) }),
|
|
8867
|
+
spec.type === "donut" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Hole", htmlFor: `${idBase}-hole`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
8454
8868
|
"input",
|
|
8455
8869
|
{
|
|
8456
8870
|
id: `${idBase}-hole`,
|
|
@@ -8466,7 +8880,7 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
8466
8880
|
onChange: (e) => controller.update({ innerRadius: Number(e.currentTarget.value) })
|
|
8467
8881
|
}
|
|
8468
8882
|
) }),
|
|
8469
|
-
hasBars && /* @__PURE__ */ (0,
|
|
8883
|
+
hasBars && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Spacing", htmlFor: `${idBase}-gap`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
8470
8884
|
"input",
|
|
8471
8885
|
{
|
|
8472
8886
|
id: `${idBase}-gap`,
|
|
@@ -8482,31 +8896,31 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
8482
8896
|
onChange: (e) => controller.update({ gapWidth: Number(e.currentTarget.value) })
|
|
8483
8897
|
}
|
|
8484
8898
|
) }),
|
|
8485
|
-
spec.dataLabels && hasBars && /* @__PURE__ */ (0,
|
|
8486
|
-
spec.type === "histogram" && /* @__PURE__ */ (0,
|
|
8487
|
-
/* @__PURE__ */ (0,
|
|
8488
|
-
spec.type === "waterfall" && /* @__PURE__ */ (0,
|
|
8489
|
-
hasLines && /* @__PURE__ */ (0,
|
|
8490
|
-
/* @__PURE__ */ (0,
|
|
8899
|
+
spec.dataLabels && hasBars && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Labels", htmlFor: `${idBase}-label-position`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Select, { id: `${idBase}-label-position`, name: "labelPosition", value: spec.labelPosition, options: import_chart4.CHART_LABEL_POSITIONS, onChange: (labelPosition) => controller.update({ labelPosition }) }) }),
|
|
8900
|
+
spec.type === "histogram" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Bins", htmlFor: `${idBase}-bins`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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 }) }),
|
|
8901
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
|
|
8902
|
+
spec.type === "waterfall" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Total bar", name: "showTotal", checked: spec.showTotal, onChange: (showTotal) => controller.update({ showTotal }) }),
|
|
8903
|
+
hasLines && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Points", name: "points", checked: spec.points, onChange: (points) => controller.update({ points }) }),
|
|
8904
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Data labels", name: "dataLabels", checked: spec.dataLabels, onChange: (dataLabels) => controller.update({ dataLabels }) })
|
|
8491
8905
|
] })
|
|
8492
8906
|
] }),
|
|
8493
|
-
show("legend") && /* @__PURE__ */ (0,
|
|
8494
|
-
/* @__PURE__ */ (0,
|
|
8495
|
-
/* @__PURE__ */ (0,
|
|
8496
|
-
/* @__PURE__ */ (0,
|
|
8907
|
+
show("legend") && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: chartSectionClass, "data-section": "legend", children: [
|
|
8908
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
8909
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Legend" }),
|
|
8910
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Show", name: "legend.show", checked: spec.legend.show, onChange: (v) => controller.setLegend({ show: v }) })
|
|
8497
8911
|
] }),
|
|
8498
|
-
spec.legend.show && /* @__PURE__ */ (0,
|
|
8912
|
+
spec.legend.show && /* @__PURE__ */ (0, import_jsx_runtime44.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_runtime44.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)) })
|
|
8499
8913
|
] }),
|
|
8500
|
-
show("axes") && hasAxes && /* @__PURE__ */ (0,
|
|
8501
|
-
family !== "box" && family !== "histogram" && /* @__PURE__ */ (0,
|
|
8502
|
-
/* @__PURE__ */ (0,
|
|
8503
|
-
usesSecondary && /* @__PURE__ */ (0,
|
|
8914
|
+
show("axes") && hasAxes && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
|
|
8915
|
+
family !== "box" && family !== "histogram" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(AxisSection, { controller, axis: "x", value: spec.xAxis, idBase, horizontal: spec.orientation === "horizontal", numeric: family === "xy", scales }),
|
|
8916
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(AxisSection, { controller, axis: "y", value: spec.yAxis, idBase, horizontal: spec.orientation === "horizontal", scales }),
|
|
8917
|
+
usesSecondary && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(AxisSection, { controller, axis: "y2", value: spec.yAxis2, idBase, horizontal: spec.orientation === "horizontal", scales })
|
|
8504
8918
|
] }),
|
|
8505
|
-
show("series") && selectedSeries && /* @__PURE__ */ (0,
|
|
8506
|
-
/* @__PURE__ */ (0,
|
|
8507
|
-
/* @__PURE__ */ (0,
|
|
8508
|
-
/* @__PURE__ */ (0,
|
|
8509
|
-
/* @__PURE__ */ (0,
|
|
8919
|
+
show("series") && selectedSeries && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: chartSectionClass, "data-section": "series", "data-series-id": selectedSeries.id, children: [
|
|
8920
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Series" }),
|
|
8921
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Name", htmlFor: `${idBase}-series-name`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartCommitInput, { id: `${idBase}-series-name`, value: selectedSeries.name, "data-option": "series.name", className: chartInputClass, onCommit: (name) => void controller.updateSeries(selectedSeries.id, { name }) }) }),
|
|
8922
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Colour", htmlFor: `${idBase}-series-color`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
8923
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
8510
8924
|
"input",
|
|
8511
8925
|
{
|
|
8512
8926
|
id: `${idBase}-series-color`,
|
|
@@ -8519,9 +8933,9 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
8519
8933
|
onChange: (e) => controller.updateSeries(selectedSeries.id, { color: e.currentTarget.value })
|
|
8520
8934
|
}
|
|
8521
8935
|
),
|
|
8522
|
-
selectedSeries.color && /* @__PURE__ */ (0,
|
|
8936
|
+
selectedSeries.color && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "reset-color", onClick: () => controller.updateSeries(selectedSeries.id, { color: null }), children: "Palette" })
|
|
8523
8937
|
] }) }),
|
|
8524
|
-
cartesian && /* @__PURE__ */ (0,
|
|
8938
|
+
cartesian && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Draw as", htmlFor: `${idBase}-series-type`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
8525
8939
|
"select",
|
|
8526
8940
|
{
|
|
8527
8941
|
id: `${idBase}-series-type`,
|
|
@@ -8530,12 +8944,12 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
8530
8944
|
"data-option": "series.type",
|
|
8531
8945
|
onChange: (e) => controller.updateSeries(selectedSeries.id, { type: e.currentTarget.value || null }),
|
|
8532
8946
|
children: [
|
|
8533
|
-
/* @__PURE__ */ (0,
|
|
8534
|
-
import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0,
|
|
8947
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: "", children: "Chart type" }),
|
|
8948
|
+
import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: t, children: import_chart4.CHART_TYPE_LABELS[t] }, t))
|
|
8535
8949
|
]
|
|
8536
8950
|
}
|
|
8537
8951
|
) }),
|
|
8538
|
-
(cartesian || family === "xy") && ["line", "area", "scatter"].includes((0, import_chart4.chartSeriesType)(spec, selectedSeries)) && /* @__PURE__ */ (0,
|
|
8952
|
+
(cartesian || family === "xy") && ["line", "area", "scatter"].includes((0, import_chart4.chartSeriesType)(spec, selectedSeries)) && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Marker", htmlFor: `${idBase}-series-marker`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
8539
8953
|
"select",
|
|
8540
8954
|
{
|
|
8541
8955
|
id: `${idBase}-series-marker`,
|
|
@@ -8544,20 +8958,20 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
8544
8958
|
"data-option": "series.marker",
|
|
8545
8959
|
onChange: (e) => controller.updateSeries(selectedSeries.id, { marker: e.currentTarget.value || null }),
|
|
8546
8960
|
children: [
|
|
8547
|
-
/* @__PURE__ */ (0,
|
|
8548
|
-
import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0,
|
|
8961
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: "", children: "Default" }),
|
|
8962
|
+
import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: m, children: cap(m) }, m))
|
|
8549
8963
|
]
|
|
8550
8964
|
}
|
|
8551
8965
|
) }),
|
|
8552
|
-
scales && /* @__PURE__ */ (0,
|
|
8553
|
-
family === "xy" && /* @__PURE__ */ (0,
|
|
8554
|
-
(0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0,
|
|
8555
|
-
(selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0,
|
|
8556
|
-
/* @__PURE__ */ (0,
|
|
8557
|
-
/* @__PURE__ */ (0,
|
|
8558
|
-
/* @__PURE__ */ (0,
|
|
8966
|
+
scales && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "errorBars", idBase }),
|
|
8967
|
+
family === "xy" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "xErrorBars", idBase }),
|
|
8968
|
+
(0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "space-y-1", "data-section": "trendlines", children: [
|
|
8969
|
+
(selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-1", "data-trendline": i, children: [
|
|
8970
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "flex-1 truncate text-muted-foreground", children: (0, import_chart4.chartTrendlineName)(t, selectedSeries.name) }),
|
|
8971
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "R\xB2", name: `trendline.${i}.showR2`, checked: !!t.showR2, onChange: (showR2) => controller.updateTrendline(selectedSeries.id, i, { showR2 }) }),
|
|
8972
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: chartButtonClass, "aria-label": "Delete trendline", "data-action": "trendline-delete", onClick: () => controller.removeTrendline(selectedSeries.id, i), children: "\xD7" })
|
|
8559
8973
|
] }, i)),
|
|
8560
|
-
/* @__PURE__ */ (0,
|
|
8974
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
8561
8975
|
"select",
|
|
8562
8976
|
{
|
|
8563
8977
|
className: chartInputClass,
|
|
@@ -8566,32 +8980,32 @@ function ChartInspector({ controller, sections, className }) {
|
|
|
8566
8980
|
"data-option": "trendline.add",
|
|
8567
8981
|
onChange: (e) => e.currentTarget.value && controller.addTrendline(selectedSeries.id, { type: e.currentTarget.value }),
|
|
8568
8982
|
children: [
|
|
8569
|
-
/* @__PURE__ */ (0,
|
|
8570
|
-
import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0,
|
|
8983
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: "", children: "Add trendline\u2026" }),
|
|
8984
|
+
import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: t, children: cap(t.replace("-", " ")) }, t))
|
|
8571
8985
|
]
|
|
8572
8986
|
}
|
|
8573
8987
|
)
|
|
8574
8988
|
] }),
|
|
8575
|
-
/* @__PURE__ */ (0,
|
|
8576
|
-
/* @__PURE__ */ (0,
|
|
8577
|
-
family === "cartesian" && /* @__PURE__ */ (0,
|
|
8578
|
-
/* @__PURE__ */ (0,
|
|
8579
|
-
/* @__PURE__ */ (0,
|
|
8580
|
-
/* @__PURE__ */ (0,
|
|
8581
|
-
/* @__PURE__ */ (0,
|
|
8989
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
8990
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Hidden", name: "series.hidden", checked: !!selectedSeries.hidden, onChange: (hidden) => controller.updateSeries(selectedSeries.id, { hidden }) }),
|
|
8991
|
+
family === "cartesian" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Secondary axis", name: "series.axis", checked: selectedSeries.axis === "secondary", onChange: (secondary) => controller.updateSeries(selectedSeries.id, { axis: secondary ? "secondary" : null }) }),
|
|
8992
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "flex-1" }),
|
|
8993
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.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" }),
|
|
8994
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.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" }),
|
|
8995
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: `${chartButtonClass} text-destructive`, "data-action": "series-delete", onClick: () => controller.removeSeries(selectedSeries.id), children: "Delete" })
|
|
8582
8996
|
] })
|
|
8583
8997
|
] })
|
|
8584
8998
|
] });
|
|
8585
8999
|
}
|
|
8586
9000
|
|
|
8587
9001
|
// src/chart-node/ChartNodeView.tsx
|
|
8588
|
-
var
|
|
9002
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
8589
9003
|
function ChartNodeView({ state, theme, showDataGrid = true }) {
|
|
8590
9004
|
const { controller, editing, editable, selected, width, height, setEditing } = state;
|
|
8591
9005
|
const open = () => {
|
|
8592
9006
|
if (editable && !editing) setEditing(true);
|
|
8593
9007
|
};
|
|
8594
|
-
return /* @__PURE__ */ (0,
|
|
9008
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
8595
9009
|
"div",
|
|
8596
9010
|
{
|
|
8597
9011
|
className: `not-prose my-2 rounded-md border bg-background p-1 ${selected ? "border-primary ring-1 ring-primary" : "border-border"}`,
|
|
@@ -8604,24 +9018,24 @@ function ChartNodeView({ state, theme, showDataGrid = true }) {
|
|
|
8604
9018
|
}
|
|
8605
9019
|
},
|
|
8606
9020
|
children: [
|
|
8607
|
-
editing && /* @__PURE__ */ (0,
|
|
8608
|
-
/* @__PURE__ */ (0,
|
|
8609
|
-
/* @__PURE__ */ (0,
|
|
9021
|
+
editing && /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "mb-1 flex items-center justify-between gap-2 px-1", "data-chart-node-toolbar": "", children: [
|
|
9022
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "text-xs text-muted-foreground", children: "Editing chart" }),
|
|
9023
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "done", onClick: () => setEditing(false), children: "Done" })
|
|
8610
9024
|
] }),
|
|
8611
|
-
/* @__PURE__ */ (0,
|
|
9025
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
8612
9026
|
"div",
|
|
8613
9027
|
{
|
|
8614
9028
|
className: editable && !editing ? "cursor-pointer" : void 0,
|
|
8615
9029
|
onClick: open,
|
|
8616
9030
|
title: editable && !editing ? "Click to edit the chart" : void 0,
|
|
8617
9031
|
"data-chart-node-canvas": "",
|
|
8618
|
-
children: /* @__PURE__ */ (0,
|
|
9032
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartCanvas, { controller, width: width ?? 640, height, responsive: width === null, editable: editing, theme })
|
|
8619
9033
|
}
|
|
8620
9034
|
),
|
|
8621
9035
|
editing && // Wraps by the document's width, not the viewport's: side by side when there is room.
|
|
8622
|
-
/* @__PURE__ */ (0,
|
|
8623
|
-
showDataGrid && /* @__PURE__ */ (0,
|
|
8624
|
-
/* @__PURE__ */ (0,
|
|
9036
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "mt-2 flex flex-wrap items-start gap-2", "data-chart-node-panel": "", children: [
|
|
9037
|
+
showDataGrid && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "min-w-0 flex-[1_1_20rem] overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartDataGrid, { controller }) }),
|
|
9038
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartInspector, { controller, className: "max-h-96 min-w-0 flex-[1_1_16rem] overflow-y-auto rounded-md border border-border p-3" })
|
|
8625
9039
|
] })
|
|
8626
9040
|
]
|
|
8627
9041
|
}
|
|
@@ -8639,7 +9053,7 @@ function createReactChartNodeView(options = {}) {
|
|
|
8639
9053
|
scheduled = true;
|
|
8640
9054
|
queueMicrotask(() => {
|
|
8641
9055
|
scheduled = false;
|
|
8642
|
-
if (!destroyed) root.render(/* @__PURE__ */ (0,
|
|
9056
|
+
if (!destroyed) root.render(/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Component, { ...props, state: latest }));
|
|
8643
9057
|
});
|
|
8644
9058
|
};
|
|
8645
9059
|
schedule();
|
|
@@ -8673,6 +9087,7 @@ function createReactChartNodeView(options = {}) {
|
|
|
8673
9087
|
ExportDocxButton,
|
|
8674
9088
|
FindReplaceBar,
|
|
8675
9089
|
FormulaHints,
|
|
9090
|
+
FreeTransformOptionsBar,
|
|
8676
9091
|
GenerationHistory,
|
|
8677
9092
|
GenerationSettings,
|
|
8678
9093
|
Histogram,
|
|
@@ -8680,6 +9095,7 @@ function createReactChartNodeView(options = {}) {
|
|
|
8680
9095
|
ImageEditor,
|
|
8681
9096
|
InsertTableGrid,
|
|
8682
9097
|
JobProgress,
|
|
9098
|
+
LayerEffectsPanel,
|
|
8683
9099
|
LayersPanel,
|
|
8684
9100
|
MergePreview,
|
|
8685
9101
|
NameManager,
|