@lv-x-software-house/x_view 1.2.6-dev.54 → 1.2.6-dev.56

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.
Files changed (3) hide show
  1. package/dist/index.js +431 -70
  2. package/dist/index.mjs +431 -70
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3387,9 +3387,11 @@ function ContextMenu({
3387
3387
  viewMembers,
3388
3388
  currentUser,
3389
3389
  onStartQuest,
3390
- onFinishQuest
3390
+ onFinishQuest,
3391
+ renderedNodeIds = [],
3392
+ renderedLinkIds = []
3391
3393
  }) {
3392
- var _a, _b, _c;
3394
+ var _a, _b;
3393
3395
  const menuRef = (0, import_react2.useRef)(null);
3394
3396
  const [menuPos, setMenuPos] = (0, import_react2.useState)({ left: 0, top: 0 });
3395
3397
  const [menuView, setMenuView] = (0, import_react2.useState)("main");
@@ -3450,7 +3452,13 @@ function ContextMenu({
3450
3452
  }
3451
3453
  return -Infinity;
3452
3454
  };
3453
- const visibleLinkIds = new Set(((_b = sceneData == null ? void 0 : sceneData.links) == null ? void 0 : _b.map((link) => String(link.id))) ?? []);
3455
+ const visibleLinkIds = (0, import_react2.useMemo)(() => {
3456
+ var _a2;
3457
+ return /* @__PURE__ */ new Set([
3458
+ ...((_a2 = sceneData == null ? void 0 : sceneData.links) == null ? void 0 : _a2.map((link) => String(link.id))) ?? [],
3459
+ ...renderedLinkIds.map((id) => String(id))
3460
+ ]);
3461
+ }, [sceneData == null ? void 0 : sceneData.links, renderedLinkIds]);
3454
3462
  const allParentLinks = Object.values(parentData).flatMap((fileData) => fileData.links || []);
3455
3463
  const nodeMap = new Map(allParentNodes.map((node) => [String(node.id), node]));
3456
3464
  const connections = allParentLinks.filter((link) => {
@@ -3467,7 +3475,7 @@ function ContextMenu({
3467
3475
  var _a2;
3468
3476
  return c.targetNode && !(((_a2 = c.targetNode.version_node) == null ? void 0 : _a2.is_version) && String(c.targetNode.version_node.parent_node) === String(data.nodeData.id));
3469
3477
  });
3470
- const isCurrentNodeQuest = ((_c = data.nodeData) == null ? void 0 : _c.is_quest) === true;
3478
+ const isCurrentNodeQuest = ((_b = data.nodeData) == null ? void 0 : _b.is_quest) === true;
3471
3479
  const commonConnections = isCurrentNodeQuest ? connections : connections.filter((c) => {
3472
3480
  var _a2;
3473
3481
  return !((_a2 = c.targetNode) == null ? void 0 : _a2.is_quest);
@@ -3592,14 +3600,14 @@ function ContextMenu({
3592
3600
  });
3593
3601
  };
3594
3602
  const renderMainView = () => {
3595
- var _a2, _b2, _c2, _d, _e, _f, _g, _h;
3603
+ var _a2, _b2, _c, _d, _e, _f, _g, _h;
3596
3604
  const hasVersions = computedVersions.length > 0;
3597
3605
  const canCreateVersion = ability.can("create", "Versioning");
3598
3606
  const canReadVersion = ability.can("read", "Versioning");
3599
3607
  const shouldShowVersioningBtn = canCreateVersion || canReadVersion && hasVersions;
3600
3608
  const canStartQuest = isCurrentNodeQuest && (((_a2 = data.nodeData) == null ? void 0 : _a2.status) === "Backlog" || !((_b2 = data.nodeData) == null ? void 0 : _b2.status));
3601
3609
  const isQuestActuallyBlocked = canStartQuest && blockedStatus.isBlocked;
3602
- const canFinishQuest = isCurrentNodeQuest && ((_c2 = data.nodeData) == null ? void 0 : _c2.assignee_id) === (currentUser == null ? void 0 : currentUser.id) && ((_d = data.nodeData) == null ? void 0 : _d.status) !== "Backlog" && ((_e = data.nodeData) == null ? void 0 : _e.status) !== "Done";
3610
+ const canFinishQuest = isCurrentNodeQuest && ((_c = data.nodeData) == null ? void 0 : _c.assignee_id) === (currentUser == null ? void 0 : currentUser.id) && ((_d = data.nodeData) == null ? void 0 : _d.status) !== "Backlog" && ((_e = data.nodeData) == null ? void 0 : _e.status) !== "Done";
3603
3611
  return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react2.default.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ import_react2.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex flex-col gap-1" }, canStartQuest && /* @__PURE__ */ import_react2.default.createElement(
3604
3612
  "button",
3605
3613
  {
@@ -3893,7 +3901,24 @@ var CustomSelect = ({ value, onChange, options, placeholder }) => {
3893
3901
  ${isOpen ? "border-indigo-500/50 bg-slate-800" : "border-white/10 hover:bg-slate-800"}`
3894
3902
  },
3895
3903
  /* @__PURE__ */ import_react3.default.createElement("span", { className: "truncate" }, selectedOption ? selectedOption.label : placeholder),
3896
- /* @__PURE__ */ import_react3.default.createElement("svg", { className: `w-4 h-4 text-slate-500 transition-transform flex-shrink-0 ${isOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ import_react3.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }))
3904
+ /* @__PURE__ */ import_react3.default.createElement(
3905
+ "svg",
3906
+ {
3907
+ className: `w-4 h-4 text-slate-500 transition-transform flex-shrink-0 ${isOpen ? "rotate-180" : ""}`,
3908
+ fill: "none",
3909
+ viewBox: "0 0 24 24",
3910
+ stroke: "currentColor"
3911
+ },
3912
+ /* @__PURE__ */ import_react3.default.createElement(
3913
+ "path",
3914
+ {
3915
+ strokeLinecap: "round",
3916
+ strokeLinejoin: "round",
3917
+ strokeWidth: 2,
3918
+ d: "M19 9l-7 7-7-7"
3919
+ }
3920
+ )
3921
+ )
3897
3922
  ), isOpen && /* @__PURE__ */ import_react3.default.createElement("div", { className: "absolute z-50 w-full mt-2 bg-slate-800 border border-white/10 rounded-lg shadow-2xl max-h-56 overflow-y-auto custom-scrollbar animate-in fade-in zoom-in-95 duration-100 py-1" }, options.map((opt, idx) => {
3898
3923
  const isSelected = String(value) === String(opt.value);
3899
3924
  return /* @__PURE__ */ import_react3.default.createElement(
@@ -3983,7 +4008,10 @@ function XViewSidebar({
3983
4008
  }, [viewType, viewName]);
3984
4009
  const normalize = (str = "") => {
3985
4010
  if (str === void 0 || str === null) {
3986
- console.warn("XViewSidebar: normalize recebeu valor nulo/indefinido:", str);
4011
+ console.warn(
4012
+ "XViewSidebar: normalize recebeu valor nulo/indefinido:",
4013
+ str
4014
+ );
3987
4015
  }
3988
4016
  return String(str).toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[._\-–—:,;!?'"()\[\]{}/\\]/g, " ").replace(/\s+/g, " ").trim();
3989
4017
  };
@@ -4035,7 +4063,9 @@ function XViewSidebar({
4035
4063
  return activeFilters.every((filter) => {
4036
4064
  if (filter.type === "Type") {
4037
4065
  const nodeTypes = Array.isArray(node.type) ? node.type : [node.type];
4038
- return nodeTypes.some((t) => String(t).toLowerCase() === String(filter.value).toLowerCase());
4066
+ return nodeTypes.some(
4067
+ (t) => String(t).toLowerCase() === String(filter.value).toLowerCase()
4068
+ );
4039
4069
  } else if (filter.type === "Color") {
4040
4070
  return String(node.color).toLowerCase() === String(filter.value).toLowerCase();
4041
4071
  } else if (filter.type === "Dataset") {
@@ -4055,7 +4085,14 @@ function XViewSidebar({
4055
4085
  inView.sort(byName);
4056
4086
  const ordered = [...notInView, ...inView];
4057
4087
  return ordered.slice(0, 200);
4058
- }, [dbNodes, query, isNodeInView, viewVersion, activeFilters, filterCategory]);
4088
+ }, [
4089
+ dbNodes,
4090
+ query,
4091
+ isNodeInView,
4092
+ viewVersion,
4093
+ activeFilters,
4094
+ filterCategory
4095
+ ]);
4059
4096
  (0, import_react3.useEffect)(() => {
4060
4097
  const handleClickOutside = (event) => {
4061
4098
  if (filterMenuRef.current && !filterMenuRef.current.contains(event.target)) {
@@ -4174,7 +4211,24 @@ function XViewSidebar({
4174
4211
  },
4175
4212
  title: "Abrir painel"
4176
4213
  },
4177
- /* @__PURE__ */ import_react3.default.createElement("svg", { className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ import_react3.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 12h16m-7 6h7" }))
4214
+ /* @__PURE__ */ import_react3.default.createElement(
4215
+ "svg",
4216
+ {
4217
+ className: "h-6 w-6",
4218
+ fill: "none",
4219
+ viewBox: "0 0 24 24",
4220
+ stroke: "currentColor"
4221
+ },
4222
+ /* @__PURE__ */ import_react3.default.createElement(
4223
+ "path",
4224
+ {
4225
+ strokeLinecap: "round",
4226
+ strokeLinejoin: "round",
4227
+ strokeWidth: 2,
4228
+ d: "M4 6h16M4 12h16m-7 6h7"
4229
+ }
4230
+ )
4231
+ )
4178
4232
  );
4179
4233
  if (!isOpen) return ToggleButton;
4180
4234
  const buttonBaseClass = "w-full px-3 py-2 rounded-md bg-indigo-500/10 hover:bg-indigo-500/20 border border-indigo-500/30 text-sm text-indigo-200 transition-colors flex items-center justify-center gap-2";
@@ -4194,7 +4248,23 @@ function XViewSidebar({
4194
4248
  className: "p-1.5 -ml-1 rounded-md text-slate-400 hover:text-white hover:bg-white/10 md:hidden transition-colors",
4195
4249
  title: "Voltar"
4196
4250
  },
4197
- /* @__PURE__ */ import_react3.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ import_react3.default.createElement("path", { fillRule: "evenodd", d: "M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z", clipRule: "evenodd" }))
4251
+ /* @__PURE__ */ import_react3.default.createElement(
4252
+ "svg",
4253
+ {
4254
+ xmlns: "http://www.w3.org/2000/svg",
4255
+ className: "h-5 w-5",
4256
+ viewBox: "0 0 20 20",
4257
+ fill: "currentColor"
4258
+ },
4259
+ /* @__PURE__ */ import_react3.default.createElement(
4260
+ "path",
4261
+ {
4262
+ fillRule: "evenodd",
4263
+ d: "M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z",
4264
+ clipRule: "evenodd"
4265
+ }
4266
+ )
4267
+ )
4198
4268
  ), /* @__PURE__ */ import_react3.default.createElement("h3", { className: "text-sm font-semibold text-indigo-100 uppercase tracking-wider" }, activeSubMenu === "quest" ? "Quest Lens" : "Reshape Lens"), /* @__PURE__ */ import_react3.default.createElement(
4199
4269
  "button",
4200
4270
  {
@@ -4202,7 +4272,23 @@ function XViewSidebar({
4202
4272
  onClick: () => setActiveSubMenu(null),
4203
4273
  title: "Fechar Sub-menu"
4204
4274
  },
4205
- /* @__PURE__ */ import_react3.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-4 w-4", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ import_react3.default.createElement("path", { fillRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z", clipRule: "evenodd" }))
4275
+ /* @__PURE__ */ import_react3.default.createElement(
4276
+ "svg",
4277
+ {
4278
+ xmlns: "http://www.w3.org/2000/svg",
4279
+ className: "h-4 w-4",
4280
+ viewBox: "0 0 20 20",
4281
+ fill: "currentColor"
4282
+ },
4283
+ /* @__PURE__ */ import_react3.default.createElement(
4284
+ "path",
4285
+ {
4286
+ fillRule: "evenodd",
4287
+ d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",
4288
+ clipRule: "evenodd"
4289
+ }
4290
+ )
4291
+ )
4206
4292
  )),
4207
4293
  /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex-1 overflow-y-auto p-4 space-y-6" }, activeSubMenu === "quest" && /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-6 animate-in fade-in slide-in-from-bottom-2 duration-500" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-2.5" }, /* @__PURE__ */ import_react3.default.createElement("label", { className: "text-[11px] uppercase text-slate-400 font-semibold tracking-wider ml-1 mb-1 block" }, "Respons\xE1vel"), /* @__PURE__ */ import_react3.default.createElement(
4208
4294
  CustomSelect,
@@ -4211,7 +4297,10 @@ function XViewSidebar({
4211
4297
  onChange: (val) => setQuestFilterAssignee(val),
4212
4298
  options: [
4213
4299
  { value: "", label: "Todos os Respons\xE1veis" },
4214
- ...viewMembers.map((m) => ({ value: m.id, label: m.name || m.email }))
4300
+ ...viewMembers.map((m) => ({
4301
+ value: m.id,
4302
+ label: m.name || m.email
4303
+ }))
4215
4304
  ],
4216
4305
  placeholder: "Selecione um Respons\xE1vel"
4217
4306
  }
@@ -4360,48 +4449,270 @@ function XViewSidebar({
4360
4449
  onClick: () => onToggle(false),
4361
4450
  title: "Fechar Painel"
4362
4451
  },
4363
- /* @__PURE__ */ import_react3.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ import_react3.default.createElement(
4364
- "path",
4452
+ /* @__PURE__ */ import_react3.default.createElement(
4453
+ "svg",
4365
4454
  {
4366
- fillRule: "evenodd",
4367
- d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",
4368
- clipRule: "evenodd"
4369
- }
4370
- ))
4455
+ xmlns: "http://www.w3.org/2000/svg",
4456
+ className: "h-5 w-5",
4457
+ viewBox: "0 0 20 20",
4458
+ fill: "currentColor"
4459
+ },
4460
+ /* @__PURE__ */ import_react3.default.createElement(
4461
+ "path",
4462
+ {
4463
+ fillRule: "evenodd",
4464
+ d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",
4465
+ clipRule: "evenodd"
4466
+ }
4467
+ )
4468
+ )
4371
4469
  ), /* @__PURE__ */ import_react3.default.createElement("div", { className: "absolute top-0 left-0 right-0 h-[1px] bg-gradient-to-r from-transparent via-indigo-500/20 to-transparent" })),
4372
- /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex-1 overflow-y-auto px-5 py-6 space-y-8 custom-scrollbar relative" }, /* @__PURE__ */ import_react3.default.createElement("section", null, /* @__PURE__ */ import_react3.default.createElement("div", { className: "mb-2" }, /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Pesquisar Node")), /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "w-full bg-slate-800/70 p-1.5 flex flex-wrap items-center gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all cursor-text min-h-[42px]", onClick: () => {
4373
- var _a;
4374
- return (_a = inputRef.current) == null ? void 0 : _a.focus();
4375
- } }, activeFilters.map((filter, idx) => /* @__PURE__ */ import_react3.default.createElement("span", { key: idx, className: "flex items-center gap-1.5 bg-indigo-500/20 text-indigo-200 border border-indigo-500/30 px-2 py-0.5 rounded text-xs font-medium max-w-full" }, filter.type === "Color" && /* @__PURE__ */ import_react3.default.createElement("span", { className: "inline-block w-2.5 h-2.5 rounded-full border border-white/20", style: { backgroundColor: filter.value } }), /* @__PURE__ */ import_react3.default.createElement("span", { className: "truncate max-w-[120px]" }, filter.type, ": ", filter.value), /* @__PURE__ */ import_react3.default.createElement("button", { type: "button", onClick: (e) => {
4376
- e.stopPropagation();
4377
- handleRemoveFilter(idx);
4378
- }, className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react3.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react3.default.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), /* @__PURE__ */ import_react3.default.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" }))))), /* @__PURE__ */ import_react3.default.createElement("input", { ref: inputRef, type: "text", value: query, onChange: (e) => setQuery(e.target.value), onFocus: () => setShowList(true), onBlur: () => setTimeout(() => setShowList(false), 120), onKeyDown: handleKeyDown, placeholder: activeFilters.length === 0 ? "Digite parte do nome..." : "", className: "bg-transparent border-none outline-none flex-1 min-w-[80px] text-sm text-slate-100 placeholder-slate-500", autoComplete: "off" })), showList && /* @__PURE__ */ import_react3.default.createElement("ul", { className: "custom-scrollbar absolute mt-1 z-10 w-full max-h-[min(448px,50dvh)] overflow-y-auto rounded-lg bg-slate-900/95 border border-white/10 shadow-xl" }, filteredAndSorted.length > 0 ? filteredAndSorted.map((n) => /* @__PURE__ */ import_react3.default.createElement("li", { key: n.id, onMouseDown: () => handlePick(n), className: `px-3 py-2 text-sm flex items-center gap-2 cursor-pointer ${selectedNodeId === n.id ? "bg-indigo-600/60 text-white" : "text-slate-200 hover:bg-indigo-500/30"}`, title: n.name }, /* @__PURE__ */ import_react3.default.createElement("span", { className: `inline-block h-2 w-2 rounded-full flex-shrink-0 ${isNodeInView(n.id) ? "bg-emerald-400" : "bg-slate-500"}` }), /* @__PURE__ */ import_react3.default.createElement("span", { className: "truncate flex-1" }, n.name))) : /* @__PURE__ */ import_react3.default.createElement("li", { className: "px-3 py-2 text-sm text-slate-400" }, "Nenhum resultado"))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "mt-3 flex items-center gap-2" }, /* @__PURE__ */ import_react3.default.createElement("button", { onClick: handleConfirm, disabled: !selectedNodeId, className: `flex-1 ${selectedNodeId ? buttonBaseClass : buttonDisabledClass}` }, /* @__PURE__ */ import_react3.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react3.default.createElement("polygon", { points: "5 3 19 12 5 21 5 3" })), "Renderizar"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative", ref: filterMenuRef }, /* @__PURE__ */ import_react3.default.createElement("button", { onClick: () => setIsFilterMenuOpen(!isFilterMenuOpen), className: `px-3 py-2 rounded-md text-sm font-medium border transition-colors flex items-center gap-2 ${isFilterMenuOpen || activeFilters.length > 0 ? "bg-indigo-500/30 text-indigo-200 border-indigo-500/40" : "bg-indigo-500/10 text-indigo-200 border-indigo-500/30 hover:bg-indigo-500/20"}` }, /* @__PURE__ */ import_react3.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react3.default.createElement("polygon", { points: "22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3" })), "Filters"), isFilterMenuOpen && /* @__PURE__ */ import_react3.default.createElement("div", { className: "absolute right-0 top-full mt-2 w-56 p-3 rounded-lg bg-slate-900 border border-white/10 shadow-xl z-50 flex flex-col gap-3 animate-in fade-in zoom-in-95 duration-100" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ import_react3.default.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-semibold tracking-wider" }, "Filtro"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex bg-slate-800/50 p-1 rounded-md" }, ["Type", "Color", "Dataset"].map((opt) => /* @__PURE__ */ import_react3.default.createElement("button", { key: opt, onClick: () => {
4379
- setFilterCategory(opt);
4380
- setFilterValue("");
4381
- }, className: `flex-1 text-xs py-1 rounded transition-colors ${filterCategory === opt ? "bg-indigo-600 text-white" : "text-slate-400 hover:text-slate-200"}` }, opt)))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ import_react3.default.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-semibold tracking-wider" }, "Valor"), /* @__PURE__ */ import_react3.default.createElement("input", { type: "text", value: filterValue, onChange: (e) => setFilterValue(e.target.value), className: "w-full bg-slate-800 p-2 text-xs rounded border border-white/10 focus:outline-none focus:border-indigo-500/50 text-white" })), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: handleAddFilter, disabled: !filterValue.trim(), className: "w-full py-1.5 bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white text-xs font-medium rounded transition-colors" }, "Aplicar Filtro"))))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ import_react3.default.createElement("section", { className: "space-y-2" }, /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Lentes"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react3.default.createElement(
4470
+ /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex-1 overflow-y-auto px-5 py-6 space-y-8 custom-scrollbar relative" }, /* @__PURE__ */ import_react3.default.createElement("section", null, /* @__PURE__ */ import_react3.default.createElement("div", { className: "mb-2" }, /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Pesquisar Node")), /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react3.default.createElement(
4471
+ "div",
4472
+ {
4473
+ className: "w-full bg-slate-800/70 p-1.5 flex flex-wrap items-center gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all cursor-text min-h-[42px]",
4474
+ onClick: () => {
4475
+ var _a;
4476
+ return (_a = inputRef.current) == null ? void 0 : _a.focus();
4477
+ }
4478
+ },
4479
+ activeFilters.map((filter, idx) => /* @__PURE__ */ import_react3.default.createElement(
4480
+ "span",
4481
+ {
4482
+ key: idx,
4483
+ className: "flex items-center gap-1.5 bg-indigo-500/20 text-indigo-200 border border-indigo-500/30 px-2 py-0.5 rounded text-xs font-medium max-w-full"
4484
+ },
4485
+ filter.type === "Color" && /* @__PURE__ */ import_react3.default.createElement(
4486
+ "span",
4487
+ {
4488
+ className: "inline-block w-2.5 h-2.5 rounded-full border border-white/20",
4489
+ style: { backgroundColor: filter.value }
4490
+ }
4491
+ ),
4492
+ /* @__PURE__ */ import_react3.default.createElement("span", { className: "truncate max-w-[120px]" }, filter.type, ": ", filter.value),
4493
+ /* @__PURE__ */ import_react3.default.createElement(
4494
+ "button",
4495
+ {
4496
+ type: "button",
4497
+ onClick: (e) => {
4498
+ e.stopPropagation();
4499
+ handleRemoveFilter(idx);
4500
+ },
4501
+ className: "hover:text-white transition-colors"
4502
+ },
4503
+ /* @__PURE__ */ import_react3.default.createElement(
4504
+ "svg",
4505
+ {
4506
+ xmlns: "http://www.w3.org/2000/svg",
4507
+ width: "12",
4508
+ height: "12",
4509
+ viewBox: "0 0 24 24",
4510
+ fill: "none",
4511
+ stroke: "currentColor",
4512
+ strokeWidth: "3",
4513
+ strokeLinecap: "round",
4514
+ strokeLinejoin: "round"
4515
+ },
4516
+ /* @__PURE__ */ import_react3.default.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
4517
+ /* @__PURE__ */ import_react3.default.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
4518
+ )
4519
+ )
4520
+ )),
4521
+ /* @__PURE__ */ import_react3.default.createElement(
4522
+ "input",
4523
+ {
4524
+ ref: inputRef,
4525
+ type: "text",
4526
+ value: query,
4527
+ onChange: (e) => setQuery(e.target.value),
4528
+ onFocus: () => setShowList(true),
4529
+ onBlur: () => setTimeout(() => setShowList(false), 120),
4530
+ onKeyDown: handleKeyDown,
4531
+ placeholder: activeFilters.length === 0 ? "Digite parte do nome..." : "",
4532
+ className: "bg-transparent border-none outline-none flex-1 min-w-[80px] text-sm text-slate-100 placeholder-slate-500",
4533
+ autoComplete: "off"
4534
+ }
4535
+ )
4536
+ ), showList && /* @__PURE__ */ import_react3.default.createElement("ul", { className: "custom-scrollbar absolute mt-1 z-10 w-full max-h-[min(448px,50dvh)] overflow-y-auto rounded-lg bg-slate-900/95 border border-white/10 shadow-xl" }, filteredAndSorted.length > 0 ? filteredAndSorted.map((n) => /* @__PURE__ */ import_react3.default.createElement(
4537
+ "li",
4538
+ {
4539
+ key: n.id,
4540
+ onMouseDown: () => handlePick(n),
4541
+ className: `px-3 py-2 text-sm flex items-center gap-2 cursor-pointer ${selectedNodeId === n.id ? "bg-indigo-600/60 text-white" : "text-slate-200 hover:bg-indigo-500/30"}`,
4542
+ title: n.name
4543
+ },
4544
+ /* @__PURE__ */ import_react3.default.createElement(
4545
+ "span",
4546
+ {
4547
+ className: `inline-block h-2 w-2 rounded-full flex-shrink-0 ${isNodeInView(n.id) ? "bg-emerald-400" : "bg-slate-500"}`
4548
+ }
4549
+ ),
4550
+ /* @__PURE__ */ import_react3.default.createElement("span", { className: "truncate flex-1" }, n.name)
4551
+ )) : /* @__PURE__ */ import_react3.default.createElement("li", { className: "px-3 py-2 text-sm text-slate-400" }, "Nenhum resultado"))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "mt-3 flex items-center gap-2" }, /* @__PURE__ */ import_react3.default.createElement(
4552
+ "button",
4553
+ {
4554
+ onClick: handleConfirm,
4555
+ disabled: !selectedNodeId,
4556
+ className: `flex-1 ${selectedNodeId ? buttonBaseClass : buttonDisabledClass}`
4557
+ },
4558
+ /* @__PURE__ */ import_react3.default.createElement(
4559
+ "svg",
4560
+ {
4561
+ xmlns: "http://www.w3.org/2000/svg",
4562
+ width: "16",
4563
+ height: "16",
4564
+ viewBox: "0 0 24 24",
4565
+ fill: "none",
4566
+ stroke: "currentColor",
4567
+ strokeWidth: "2",
4568
+ strokeLinecap: "round",
4569
+ strokeLinejoin: "round"
4570
+ },
4571
+ /* @__PURE__ */ import_react3.default.createElement("polygon", { points: "5 3 19 12 5 21 5 3" })
4572
+ ),
4573
+ "Renderizar"
4574
+ ), /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative", ref: filterMenuRef }, /* @__PURE__ */ import_react3.default.createElement(
4575
+ "button",
4576
+ {
4577
+ onClick: () => setIsFilterMenuOpen(!isFilterMenuOpen),
4578
+ className: `px-3 py-2 rounded-md text-sm font-medium border transition-colors flex items-center gap-2 ${isFilterMenuOpen || activeFilters.length > 0 ? "bg-indigo-500/30 text-indigo-200 border-indigo-500/40" : "bg-indigo-500/10 text-indigo-200 border-indigo-500/30 hover:bg-indigo-500/20"}`
4579
+ },
4580
+ /* @__PURE__ */ import_react3.default.createElement(
4581
+ "svg",
4582
+ {
4583
+ xmlns: "http://www.w3.org/2000/svg",
4584
+ width: "16",
4585
+ height: "16",
4586
+ viewBox: "0 0 24 24",
4587
+ fill: "none",
4588
+ stroke: "currentColor",
4589
+ strokeWidth: "2",
4590
+ strokeLinecap: "round",
4591
+ strokeLinejoin: "round"
4592
+ },
4593
+ /* @__PURE__ */ import_react3.default.createElement("polygon", { points: "22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3" })
4594
+ ),
4595
+ "Filters"
4596
+ ), isFilterMenuOpen && /* @__PURE__ */ import_react3.default.createElement("div", { className: "absolute right-0 top-full mt-2 w-56 p-3 rounded-lg bg-slate-900 border border-white/10 shadow-xl z-50 flex flex-col gap-3 animate-in fade-in zoom-in-95 duration-100" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ import_react3.default.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-semibold tracking-wider" }, "Filtro"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex bg-slate-800/50 p-1 rounded-md" }, ["Type", "Color", "Dataset"].map((opt) => /* @__PURE__ */ import_react3.default.createElement(
4597
+ "button",
4598
+ {
4599
+ key: opt,
4600
+ onClick: () => {
4601
+ setFilterCategory(opt);
4602
+ setFilterValue("");
4603
+ },
4604
+ className: `flex-1 text-xs py-1 rounded transition-colors ${filterCategory === opt ? "bg-indigo-600 text-white" : "text-slate-400 hover:text-slate-200"}`
4605
+ },
4606
+ opt
4607
+ )))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ import_react3.default.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-semibold tracking-wider" }, "Valor"), /* @__PURE__ */ import_react3.default.createElement(
4608
+ "input",
4609
+ {
4610
+ type: "text",
4611
+ value: filterValue,
4612
+ onChange: (e) => setFilterValue(e.target.value),
4613
+ className: "w-full bg-slate-800 p-2 text-xs rounded border border-white/10 focus:outline-none focus:border-indigo-500/50 text-white"
4614
+ }
4615
+ )), /* @__PURE__ */ import_react3.default.createElement(
4616
+ "button",
4617
+ {
4618
+ onClick: handleAddFilter,
4619
+ disabled: !filterValue.trim(),
4620
+ className: "w-full py-1.5 bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white text-xs font-medium rounded transition-colors"
4621
+ },
4622
+ "Aplicar Filtro"
4623
+ ))))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ import_react3.default.createElement("section", { className: "space-y-2" }, /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Lentes"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react3.default.createElement(
4382
4624
  "button",
4383
4625
  {
4384
4626
  onClick: () => setActiveSubMenu(activeSubMenu === "quest" ? null : "quest"),
4385
4627
  className: `${buttonBaseClass} lens-button ${activeSubMenu === "quest" || questFilterAssignee || questFilterStatus || questFilterMilestone ? "bg-indigo-500/30 border-indigo-400" : ""}`
4386
4628
  },
4387
- /* @__PURE__ */ import_react3.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react3.default.createElement("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }), /* @__PURE__ */ import_react3.default.createElement("path", { d: "M9 12l2 2 4-4" })),
4388
- "Quest Lens"
4629
+ /* @__PURE__ */ import_react3.default.createElement(
4630
+ "svg",
4631
+ {
4632
+ xmlns: "http://www.w3.org/2000/svg",
4633
+ width: "16",
4634
+ height: "16",
4635
+ viewBox: "0 0 24 24",
4636
+ fill: "none",
4637
+ stroke: "currentColor",
4638
+ strokeWidth: "2",
4639
+ strokeLinecap: "round",
4640
+ strokeLinejoin: "round"
4641
+ },
4642
+ /* @__PURE__ */ import_react3.default.createElement("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }),
4643
+ /* @__PURE__ */ import_react3.default.createElement("path", { d: "M9 12l2 2 4-4" })
4644
+ ),
4645
+ "Quests"
4389
4646
  )), /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react3.default.createElement(
4390
4647
  "button",
4391
4648
  {
4392
- onClick: () => setActiveSubMenu(activeSubMenu === "reshape" ? null : "reshape"),
4649
+ onClick: () => setActiveSubMenu(
4650
+ activeSubMenu === "reshape" ? null : "reshape"
4651
+ ),
4393
4652
  className: `${buttonBaseClass} lens-button ${activeSubMenu === "reshape" ? "bg-indigo-500/30 border-indigo-400" : ""}`
4394
4653
  },
4395
- /* @__PURE__ */ import_react3.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react3.default.createElement("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }), /* @__PURE__ */ import_react3.default.createElement("polyline", { points: "2 17 12 22 22 17" }), /* @__PURE__ */ import_react3.default.createElement("polyline", { points: "2 12 12 17 22 12" })),
4396
- "Reshape Lens"
4397
- )), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: onActivateTimeline, className: buttonBaseClass }, /* @__PURE__ */ import_react3.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react3.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react3.default.createElement("polyline", { points: "12 6 12 12 16 14" })), "Timeline"), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: onOpenBoards, className: buttonBaseClass }, /* @__PURE__ */ import_react3.default.createElement(import_fi2.FiLayers, { size: 16 }), "Boards")), /* @__PURE__ */ import_react3.default.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ import_react3.default.createElement("section", { className: "space-y-3" }, /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Milestones"), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: onOpenMilestoneManager, className: buttonBaseClass }, "Gerenciar Milestones"))),
4398
- /* @__PURE__ */ import_react3.default.createElement("div", { className: "px-4 py-3 border-t border-white/10 bg-slate-900/30" }, /* @__PURE__ */ import_react3.default.createElement("section", { className: "space-y-2" }, /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Navega\xE7\xE3o"), ability.can("update", "Scene") && /* @__PURE__ */ import_react3.default.createElement("button", { onClick: handleSaveClick, disabled: isSaving, className: isSaving ? buttonDisabledClass : buttonBaseClass }, isSaving ? "Salvando..." : "Atualizar cen\xE1rio inicial"), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: onNavigateBack, className: buttonBaseClass }, "Voltar \xE0 p\xE1gina de cen\xE1rios"))),
4654
+ /* @__PURE__ */ import_react3.default.createElement(
4655
+ "svg",
4656
+ {
4657
+ xmlns: "http://www.w3.org/2000/svg",
4658
+ width: "16",
4659
+ height: "16",
4660
+ viewBox: "0 0 24 24",
4661
+ fill: "none",
4662
+ stroke: "currentColor",
4663
+ strokeWidth: "2",
4664
+ strokeLinecap: "round",
4665
+ strokeLinejoin: "round"
4666
+ },
4667
+ /* @__PURE__ */ import_react3.default.createElement("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }),
4668
+ /* @__PURE__ */ import_react3.default.createElement("polyline", { points: "2 17 12 22 22 17" }),
4669
+ /* @__PURE__ */ import_react3.default.createElement("polyline", { points: "2 12 12 17 22 12" })
4670
+ ),
4671
+ "Reshape"
4672
+ )), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: onActivateTimeline, className: buttonBaseClass }, /* @__PURE__ */ import_react3.default.createElement(
4673
+ "svg",
4674
+ {
4675
+ xmlns: "http://www.w3.org/2000/svg",
4676
+ width: "16",
4677
+ height: "16",
4678
+ viewBox: "0 0 24 24",
4679
+ fill: "none",
4680
+ stroke: "currentColor",
4681
+ strokeWidth: "2",
4682
+ strokeLinecap: "round",
4683
+ strokeLinejoin: "round"
4684
+ },
4685
+ /* @__PURE__ */ import_react3.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
4686
+ /* @__PURE__ */ import_react3.default.createElement("polyline", { points: "12 6 12 12 16 14" })
4687
+ ), "Timeline"), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: onOpenBoards, className: buttonBaseClass }, /* @__PURE__ */ import_react3.default.createElement(import_fi2.FiLayers, { size: 16 }), "Boards")), /* @__PURE__ */ import_react3.default.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ import_react3.default.createElement("section", { className: "space-y-3" }, /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Milestones"), /* @__PURE__ */ import_react3.default.createElement(
4688
+ "button",
4689
+ {
4690
+ onClick: onOpenMilestoneManager,
4691
+ className: buttonBaseClass
4692
+ },
4693
+ "Gerenciar Milestones"
4694
+ ))),
4695
+ /* @__PURE__ */ import_react3.default.createElement("div", { className: "px-4 py-3 border-t border-white/10 bg-slate-900/30" }, /* @__PURE__ */ import_react3.default.createElement("section", { className: "space-y-2" }, /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Navega\xE7\xE3o"), ability.can("update", "Scene") && /* @__PURE__ */ import_react3.default.createElement(
4696
+ "button",
4697
+ {
4698
+ onClick: handleSaveClick,
4699
+ disabled: isSaving,
4700
+ className: isSaving ? buttonDisabledClass : buttonBaseClass
4701
+ },
4702
+ isSaving ? "Salvando..." : "Atualizar cen\xE1rio inicial"
4703
+ ), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: onNavigateBack, className: buttonBaseClass }, "Voltar ao Dashboard"))),
4399
4704
  contextLabel && /* @__PURE__ */ import_react3.default.createElement("div", { className: "px-4 py-3 border-t border-white/10 bg-slate-900/50 truncate text-sm font-medium text-slate-200" }, contextLabel),
4400
4705
  /* @__PURE__ */ import_react3.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" })
4401
4706
  ),
4402
- /* @__PURE__ */ import_react3.default.createElement("div", { className: `h-full pointer-events-auto transition-all duration-500 ease-out absolute md:relative left-0 top-0 z-30 md:z-10 flex-shrink-0 overflow-hidden
4707
+ /* @__PURE__ */ import_react3.default.createElement(
4708
+ "div",
4709
+ {
4710
+ className: `h-full pointer-events-auto transition-all duration-500 ease-out absolute md:relative left-0 top-0 z-30 md:z-10 flex-shrink-0 overflow-hidden
4403
4711
  ${activeSubMenu ? "translate-x-0 md:translate-x-0 w-[100vw] md:w-[280px] opacity-100" : "-translate-x-full md:translate-x-0 w-[100vw] md:w-0 opacity-0 md:opacity-100"}
4404
- ` }, renderAnnexedPanel())
4712
+ `
4713
+ },
4714
+ renderAnnexedPanel()
4715
+ )
4405
4716
  );
4406
4717
  }
4407
4718
 
@@ -18158,6 +18469,20 @@ function XViewScene({
18158
18469
  masterAncestryList.push(ancestryObjectToSave);
18159
18470
  }
18160
18471
  const result = await save_view_data(finalSaveUrl, masterAncestryList);
18472
+ if (result.success && isExternalSave && isEditMode && currentAncestryId && ancestry_save_url && get_ancestry_file) {
18473
+ try {
18474
+ const viewDbResponse = await get_ancestry_file(sceneConfigId, ownerId);
18475
+ if (viewDbResponse.success && Array.isArray(viewDbResponse.data)) {
18476
+ const hasInViewDb = viewDbResponse.data.some((anc) => String(anc.ancestry_id) === String(currentAncestryId));
18477
+ if (hasInViewDb) {
18478
+ const updatedViewDb = viewDbResponse.data.filter((anc) => String(anc.ancestry_id) !== String(currentAncestryId));
18479
+ await save_view_data(ancestry_save_url, updatedViewDb);
18480
+ }
18481
+ }
18482
+ } catch (fallbackErr) {
18483
+ console.error("Falha ao limpar c\xF3pia residual na edi\xE7\xE3o:", fallbackErr);
18484
+ }
18485
+ }
18161
18486
  if (result.success) {
18162
18487
  const localList = [...ancestryDataRef.current || []];
18163
18488
  const localIndex = localList.findIndex(
@@ -18260,45 +18585,76 @@ function XViewScene({
18260
18585
  return;
18261
18586
  }
18262
18587
  const finalSaveUrl = `x_view_ancestry/${sourceOwnerId}/${sourceFileId}`;
18263
- const updatedAncestriesForFile = (ancestryDataRef.current || []).filter(
18264
- (anc) => anc._source_file_id === sourceFileId && String(anc.ancestry_id) !== String(ancestryIdToDelete)
18265
- );
18588
+ const isExternalSave = sourceFileId !== sceneConfigId;
18589
+ let success = false;
18590
+ let deletionError = null;
18266
18591
  try {
18267
- const result = await save_view_data(
18268
- finalSaveUrl,
18269
- updatedAncestriesForFile
18270
- );
18271
- if (result.success) {
18272
- ancestryDataRef.current = (ancestryDataRef.current || []).filter(
18273
- (ancestry) => String(ancestry.ancestry_id) !== String(ancestryIdToDelete)
18274
- );
18275
- const { renderedAncestries, ancestryGroup } = stateRef.current;
18276
- const renderIndex = renderedAncestries.findIndex(
18277
- (a) => String(a.id) === String(ancestryIdToDelete)
18278
- );
18279
- if (renderIndex !== -1) {
18280
- const toRemove = renderedAncestries[renderIndex];
18281
- toRemove.lines.forEach((line) => {
18282
- ancestryGroup.remove(line);
18283
- if (line.geometry) line.geometry.dispose();
18284
- if (line.material) line.material.dispose();
18285
- });
18286
- renderedAncestries.splice(renderIndex, 1);
18287
- stateRef.current.ancestryLinks = renderedAncestries.flatMap(
18288
- (a) => a.lines
18592
+ let updatedAncestriesForFile;
18593
+ if (get_ancestry_file && isExternalSave) {
18594
+ const remoteResponse = await get_ancestry_file(sourceFileId, sourceOwnerId);
18595
+ if (remoteResponse.success && Array.isArray(remoteResponse.data)) {
18596
+ updatedAncestriesForFile = remoteResponse.data.filter(
18597
+ (anc) => String(anc.ancestry_id) !== String(ancestryIdToDelete)
18598
+ );
18599
+ } else {
18600
+ updatedAncestriesForFile = (ancestryDataRef.current || []).filter(
18601
+ (anc) => anc._source_file_id === sourceFileId && String(anc.ancestry_id) !== String(ancestryIdToDelete)
18289
18602
  );
18290
18603
  }
18291
- setSceneVersion((v) => v + 1);
18292
18604
  } else {
18293
- throw new Error(
18294
- result.error || "Ocorreu um erro desconhecido ao excluir."
18605
+ updatedAncestriesForFile = (ancestryDataRef.current || []).filter(
18606
+ (anc) => anc._source_file_id === sourceFileId && String(anc.ancestry_id) !== String(ancestryIdToDelete)
18295
18607
  );
18296
18608
  }
18609
+ const result = await save_view_data(finalSaveUrl, updatedAncestriesForFile);
18610
+ if (result.success) {
18611
+ success = true;
18612
+ } else {
18613
+ throw new Error(result.error || "Ocorreu um erro desconhecido ao excluir.");
18614
+ }
18297
18615
  } catch (error) {
18298
- console.error("Falha ao excluir a ancestralidade:", error);
18299
- alert(`Erro ao excluir a ancestralidade: ${error.message}`);
18616
+ deletionError = error;
18617
+ }
18618
+ if (ancestry_save_url && isExternalSave && get_ancestry_file) {
18619
+ try {
18620
+ const viewDbResponse = await get_ancestry_file(sceneConfigId, ownerId);
18621
+ if (viewDbResponse.success && Array.isArray(viewDbResponse.data)) {
18622
+ const hasInViewDb = viewDbResponse.data.some((anc) => String(anc.ancestry_id) === String(ancestryIdToDelete));
18623
+ if (hasInViewDb) {
18624
+ const updatedViewDb = viewDbResponse.data.filter((anc) => String(anc.ancestry_id) !== String(ancestryIdToDelete));
18625
+ const fallbackResult = await save_view_data(ancestry_save_url, updatedViewDb);
18626
+ if (fallbackResult.success) success = true;
18627
+ }
18628
+ }
18629
+ } catch (fallbackErr) {
18630
+ console.error("Falha ao limpar c\xF3pia residual da View DB:", fallbackErr);
18631
+ }
18632
+ }
18633
+ if (!success && deletionError) {
18634
+ console.error("Falha ao excluir a ancestralidade:", deletionError);
18635
+ alert(`Erro ao excluir a ancestralidade: ${deletionError.message}`);
18300
18636
  return;
18301
18637
  }
18638
+ ancestryDataRef.current = (ancestryDataRef.current || []).filter(
18639
+ (ancestry) => String(ancestry.ancestry_id) !== String(ancestryIdToDelete)
18640
+ );
18641
+ const { renderedAncestries, ancestryGroup } = stateRef.current;
18642
+ const renderIndex = renderedAncestries.findIndex(
18643
+ (a) => String(a.id) === String(ancestryIdToDelete)
18644
+ );
18645
+ if (renderIndex !== -1) {
18646
+ const toRemove = renderedAncestries[renderIndex];
18647
+ toRemove.lines.forEach((line) => {
18648
+ ancestryGroup.remove(line);
18649
+ if (line.geometry) line.geometry.dispose();
18650
+ if (line.material) line.material.dispose();
18651
+ });
18652
+ renderedAncestries.splice(renderIndex, 1);
18653
+ stateRef.current.ancestryLinks = renderedAncestries.flatMap(
18654
+ (a) => a.lines
18655
+ );
18656
+ }
18657
+ setSceneVersion((v) => v + 1);
18302
18658
  setAncestryMode({
18303
18659
  isActive: false,
18304
18660
  tree: null,
@@ -19137,6 +19493,11 @@ function XViewScene({
19137
19493
  parentData: parentDataRef.current,
19138
19494
  sceneData: sceneDataRef.current,
19139
19495
  ancestryData: ancestryDataRef.current,
19496
+ renderedNodeIds: Object.keys(stateRef.current.nodeObjects || {}),
19497
+ renderedLinkIds: (stateRef.current.allLinks || []).map((l) => {
19498
+ var _a2;
19499
+ return String((_a2 = l.userData) == null ? void 0 : _a2.id);
19500
+ }).filter((id) => id !== "undefined"),
19140
19501
  onClose: () => setContextMenu(
19141
19502
  (prev) => prev.visible ? { ...prev, visible: false } : prev
19142
19503
  ),