@lv-x-software-house/x_view 1.2.4-dev.24 → 1.2.4-dev.26

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/README.md CHANGED
@@ -1 +1 @@
1
- X View - from ŀv.x - Software House
1
+ x.view - from ŀv.x - Software Engineering
package/dist/index.js CHANGED
@@ -505,7 +505,11 @@ function XViewSidebar({
505
505
  let pool = base;
506
506
  const qNorm = normalize(query);
507
507
  if (qNorm) {
508
- pool = pool.filter((n) => normalize((n == null ? void 0 : n.name) || "").includes(qNorm));
508
+ pool = pool.filter((n) => {
509
+ const matchName = normalize((n == null ? void 0 : n.name) || "").includes(qNorm);
510
+ const matchRawTitle = n.is_quest && n.raw_title ? normalize(n.raw_title).includes(qNorm) : false;
511
+ return matchName || matchRawTitle;
512
+ });
509
513
  }
510
514
  if (activeFilters.length > 0) {
511
515
  pool = pool.filter((node) => {
@@ -7971,10 +7975,13 @@ function InSceneQuestForm({
7971
7975
  availableAncestries = [],
7972
7976
  onMentionClick,
7973
7977
  onUploadFile,
7974
- // NOVAS PROPS PARA O GHOST NODE
7975
7978
  onNameChange,
7976
7979
  onColorChange,
7977
- onSizeChange
7980
+ onSizeChange,
7981
+ viewName = "Projeto",
7982
+ // NOVA PROP
7983
+ questCounter = 1
7984
+ // NOVA PROP
7978
7985
  }) {
7979
7986
  const [name, setName] = (0, import_react16.useState)("");
7980
7987
  const [types, setTypes] = (0, import_react16.useState)(["quest"]);
@@ -7987,6 +7994,7 @@ function InSceneQuestForm({
7987
7994
  const [customProps, setCustomProps] = (0, import_react16.useState)([]);
7988
7995
  const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react16.useState)(false);
7989
7996
  const propsEndRef = (0, import_react16.useRef)(null);
7997
+ const standardizedName = `${viewName} - ${questCounter} - \xBB ${name || "Nova Quest"}`;
7990
7998
  const handleAddProp = () => {
7991
7999
  const newProp = createNewCustomProperty(customProps);
7992
8000
  setCustomProps([...customProps, newProp]);
@@ -8023,7 +8031,7 @@ function InSceneQuestForm({
8023
8031
  const handleSubmit = (e) => {
8024
8032
  e.preventDefault();
8025
8033
  if (!name.trim()) {
8026
- alert("O campo 'Nome' \xE9 obrigat\xF3rio.");
8034
+ alert("O campo 'T\xEDtulo' \xE9 obrigat\xF3rio.");
8027
8035
  return;
8028
8036
  }
8029
8037
  const additionalData = toObjectFromCustomProps(
@@ -8031,7 +8039,10 @@ function InSceneQuestForm({
8031
8039
  );
8032
8040
  const processedSections = processDescriptionForSave(description, []);
8033
8041
  onSave({
8034
- name: name.trim(),
8042
+ name: standardizedName,
8043
+ // SALVA O NOME FORMATADO
8044
+ raw_title: name.trim(),
8045
+ // Salva o título puro como fallback ou metadado útil
8035
8046
  type: types,
8036
8047
  color: QUEST_STATUS_COLORS[status],
8037
8048
  status,
@@ -8070,7 +8081,21 @@ function InSceneQuestForm({
8070
8081
  },
8071
8082
  "\xD7"
8072
8083
  )),
8073
- /* @__PURE__ */ import_react16.default.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col max-h-[68vh]" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react16.default.createElement(
8084
+ /* @__PURE__ */ import_react16.default.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col max-h-[68vh]" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "T\xEDtulo da Quest"), /* @__PURE__ */ import_react16.default.createElement(
8085
+ "input",
8086
+ {
8087
+ required: true,
8088
+ type: "text",
8089
+ placeholder: "Ex.: Refatorar M\xF3dulo X",
8090
+ value: name,
8091
+ onChange: (e) => {
8092
+ const val = e.target.value;
8093
+ setName(val);
8094
+ onNameChange == null ? void 0 : onNameChange(`${viewName} - ${questCounter} - \xBB ${val || "Nova Quest"}`);
8095
+ },
8096
+ className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60"
8097
+ }
8098
+ ), /* @__PURE__ */ import_react16.default.createElement("div", { className: "pt-1 flex items-center gap-1.5" }, /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-[10px] uppercase font-bold text-slate-500 tracking-wider" }, "Preview:"), /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-xs text-indigo-300 font-medium truncate", title: standardizedName }, standardizedName))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react16.default.createElement(
8074
8099
  "button",
8075
8100
  {
8076
8101
  type: "button",
@@ -8092,20 +8117,7 @@ function InSceneQuestForm({
8092
8117
  },
8093
8118
  /* @__PURE__ */ import_react16.default.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS[s] } }),
8094
8119
  s
8095
- )))))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ import_react16.default.createElement(
8096
- "input",
8097
- {
8098
- required: true,
8099
- type: "text",
8100
- placeholder: "Ex.: Refatorar M\xF3dulo X",
8101
- value: name,
8102
- onChange: (e) => {
8103
- setName(e.target.value);
8104
- onNameChange == null ? void 0 : onNameChange(e.target.value);
8105
- },
8106
- className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60"
8107
- }
8108
- )), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ import_react16.default.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiX, { size: 12 })))), /* @__PURE__ */ import_react16.default.createElement(
8120
+ )))))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ import_react16.default.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiX, { size: 12 })))), /* @__PURE__ */ import_react16.default.createElement(
8109
8121
  "input",
8110
8122
  {
8111
8123
  type: "text",
@@ -8683,7 +8695,12 @@ function QuestDetailsPanel({
8683
8695
  userRole,
8684
8696
  currentDatasetName
8685
8697
  }) {
8686
- const [name, setName] = (0, import_react18.useState)((node == null ? void 0 : node.name) ?? "");
8698
+ var _a;
8699
+ const initialRawTitle = (node == null ? void 0 : node.raw_title) || (((_a = node == null ? void 0 : node.name) == null ? void 0 : _a.includes(" - \xBB ")) ? node.name.split(" - \xBB ")[1] : node == null ? void 0 : node.name) || "";
8700
+ const [rawTitle, setRawTitle] = (0, import_react18.useState)(initialRawTitle);
8701
+ const prefixParts = ((node == null ? void 0 : node.name) || "").split(" - \xBB ");
8702
+ const questPrefix = prefixParts.length > 1 ? prefixParts[0] : "";
8703
+ const standardizedName = questPrefix ? `${questPrefix} - \xBB ${rawTitle || "Sem t\xEDtulo"}` : rawTitle;
8687
8704
  const [types, setTypes] = (0, import_react18.useState)((node == null ? void 0 : node.type) ? Array.isArray(node.type) ? node.type : [node.type] : ["quest"]);
8688
8705
  const [typeInput, setTypeInput] = (0, import_react18.useState)("");
8689
8706
  const [status, setStatus] = (0, import_react18.useState)((node == null ? void 0 : node.status) ?? "Backlog");
@@ -8712,15 +8729,17 @@ function QuestDetailsPanel({
8712
8729
  const propsEndRef = (0, import_react18.useRef)(null);
8713
8730
  const canEdit = userRole !== "viewer";
8714
8731
  const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
8715
- const handleImageClickFromText = (url, name2) => {
8732
+ const handleImageClickFromText = (url, name) => {
8716
8733
  if (onOpenImageViewer) {
8717
- onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
8734
+ onOpenImageViewer([{ name: name || "Imagem", value: url }], 0);
8718
8735
  }
8719
8736
  };
8720
8737
  (0, import_react18.useEffect)(() => {
8738
+ var _a2;
8721
8739
  if ((node == null ? void 0 : node.id) !== prevNodeIdRef.current) {
8722
8740
  prevNodeIdRef.current = node == null ? void 0 : node.id;
8723
- setName((node == null ? void 0 : node.name) ?? "");
8741
+ const newRawTitle = (node == null ? void 0 : node.raw_title) || (((_a2 = node == null ? void 0 : node.name) == null ? void 0 : _a2.includes(" - \xBB ")) ? node.name.split(" - \xBB ")[1] : node == null ? void 0 : node.name) || "";
8742
+ setRawTitle(newRawTitle);
8724
8743
  setTypes((node == null ? void 0 : node.type) ? Array.isArray(node.type) ? node.type : [node.type] : ["quest"]);
8725
8744
  setStatus((node == null ? void 0 : node.status) ?? "Backlog");
8726
8745
  setSize((node == null ? void 0 : node.size) ?? "medium");
@@ -8755,9 +8774,10 @@ function QuestDetailsPanel({
8755
8774
  };
8756
8775
  const swallow = (e) => e.stopPropagation();
8757
8776
  const handleNameChange = (e) => {
8758
- const v = e.target.value;
8759
- setName(v);
8760
- onNameChange == null ? void 0 : onNameChange(node.id, v);
8777
+ const val = e.target.value;
8778
+ setRawTitle(val);
8779
+ const newStandardName = questPrefix ? `${questPrefix} - \xBB ${val || "Sem t\xEDtulo"}` : val;
8780
+ onNameChange == null ? void 0 : onNameChange(node.id, newStandardName);
8761
8781
  };
8762
8782
  const handleSizeChange = (newSize) => {
8763
8783
  setSize(newSize);
@@ -8793,8 +8813,8 @@ function QuestDetailsPanel({
8793
8813
  const newProp = createNewCustomProperty(customProps);
8794
8814
  setCustomProps((p) => [...p, newProp]);
8795
8815
  setTimeout(() => {
8796
- var _a;
8797
- (_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
8816
+ var _a2;
8817
+ (_a2 = propsEndRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth", block: "center" });
8798
8818
  }, 100);
8799
8819
  };
8800
8820
  const handleRemoveProp = (i) => {
@@ -8816,14 +8836,15 @@ function QuestDetailsPanel({
8816
8836
  triggerAutoSave({ description: newDescription });
8817
8837
  };
8818
8838
  const handleSave = async (keepOpen = false, overrides = {}) => {
8819
- const currentName = overrides.name !== void 0 ? overrides.name : name;
8839
+ const currentRawTitle = overrides.rawTitle !== void 0 ? overrides.rawTitle : rawTitle;
8840
+ const currentStandardName = questPrefix ? `${questPrefix} - \xBB ${currentRawTitle || "Sem t\xEDtulo"}` : currentRawTitle;
8820
8841
  const currentTypes = overrides.types !== void 0 ? overrides.types : types;
8821
8842
  const currentDescription = overrides.description !== void 0 ? overrides.description : description;
8822
8843
  const currentCustomProps = overrides.customProps !== void 0 ? overrides.customProps : customProps;
8823
8844
  const currentExistingSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
8824
8845
  const currentStatus = overrides.status !== void 0 ? overrides.status : status;
8825
- if (!currentName.trim() || currentTypes.length === 0) {
8826
- alert("O campo 'Nome' e pelo menos um 'Tipo' s\xE3o obrigat\xF3rios.");
8846
+ if (!currentRawTitle.trim() || currentTypes.length === 0) {
8847
+ alert("O campo 'T\xEDtulo' e pelo menos um 'Tipo' s\xE3o obrigat\xF3rios.");
8827
8848
  return;
8828
8849
  }
8829
8850
  setIsSaving(true);
@@ -8832,7 +8853,10 @@ function QuestDetailsPanel({
8832
8853
  const processedSections = processDescriptionForSave(currentDescription, currentExistingSections);
8833
8854
  const dataToSave = {
8834
8855
  id: node.id,
8835
- name: currentName.trim(),
8856
+ name: currentStandardName.trim(),
8857
+ // Salva o nome completo formatado
8858
+ raw_title: currentRawTitle.trim(),
8859
+ // Salva o título simples
8836
8860
  type: currentTypes,
8837
8861
  color: QUEST_STATUS_COLORS2[currentStatus],
8838
8862
  status: currentStatus,
@@ -8887,7 +8911,7 @@ function QuestDetailsPanel({
8887
8911
  isReadMode ? /* @__PURE__ */ import_react18.default.createElement(
8888
8912
  DescriptionReadModePanel,
8889
8913
  {
8890
- title: name || (node == null ? void 0 : node.name),
8914
+ title: standardizedName || (node == null ? void 0 : node.name),
8891
8915
  description,
8892
8916
  savedSections: existingSections,
8893
8917
  onBack: () => setIsReadMode(false),
@@ -8905,7 +8929,16 @@ function QuestDetailsPanel({
8905
8929
  onImageClick: handleImageClickFromText,
8906
8930
  onSaveDescription: handleSaveDescriptionInline
8907
8931
  }
8908
- ) : /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS2[status]}, transparent)` } }), /* @__PURE__ */ import_react18.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react18.default.createElement("div", null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ import_react18.default.createElement("button", { onClick: handleCopyLink, className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-sky-400"}`, title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Quest" }, isLinkCopied ? /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiLink, { size: 12 }))), /* @__PURE__ */ import_react18.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || (node == null ? void 0 : node.name))), /* @__PURE__ */ import_react18.default.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Cancelar" }, "\xD7")), /* @__PURE__ */ import_react18.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ import_react18.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react18.default.createElement(
8932
+ ) : /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS2[status]}, transparent)` } }), /* @__PURE__ */ import_react18.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react18.default.createElement("div", null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ import_react18.default.createElement("button", { onClick: handleCopyLink, className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-sky-400"}`, title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Quest" }, isLinkCopied ? /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiLink, { size: 12 }))), /* @__PURE__ */ import_react18.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, standardizedName || (node == null ? void 0 : node.name))), /* @__PURE__ */ import_react18.default.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Cancelar" }, "\xD7")), /* @__PURE__ */ import_react18.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "T\xEDtulo da Quest"), /* @__PURE__ */ import_react18.default.createElement(
8933
+ "input",
8934
+ {
8935
+ type: "text",
8936
+ value: rawTitle,
8937
+ onChange: handleNameChange,
8938
+ readOnly: !canEdit,
8939
+ className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none ${canEdit ? "focus:ring-2 focus:ring-indigo-400/60" : "cursor-default text-slate-400"}`
8940
+ }
8941
+ ), /* @__PURE__ */ import_react18.default.createElement("div", { className: "pt-1 flex items-center gap-1.5" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "text-[10px] uppercase font-bold text-slate-500 tracking-wider" }, "Preview:"), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-xs text-indigo-300 font-medium truncate", title: standardizedName }, standardizedName))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ import_react18.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react18.default.createElement(
8909
8942
  "button",
8910
8943
  {
8911
8944
  type: "button",
@@ -8927,7 +8960,7 @@ function QuestDetailsPanel({
8927
8960
  },
8928
8961
  /* @__PURE__ */ import_react18.default.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS2[s] } }),
8929
8962
  s
8930
- )))))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome"), /* @__PURE__ */ import_react18.default.createElement("input", { type: "text", value: name, onChange: handleNameChange, readOnly: !canEdit, className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none ${canEdit ? "focus:ring-2 focus:ring-indigo-400/60" : "cursor-default text-slate-400"}` })), /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react18.default.createElement("div", { className: `relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 ${canEdit ? "focus-within:ring-2 focus-within:ring-indigo-400/60" : ""} transition-all` }, types.map((t, index) => /* @__PURE__ */ import_react18.default.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, canEdit && t !== "quest" && /* @__PURE__ */ import_react18.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiX, { size: 12 })))), canEdit && /* @__PURE__ */ import_react18.default.createElement(
8963
+ )))))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react18.default.createElement("div", { className: `relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 ${canEdit ? "focus-within:ring-2 focus-within:ring-indigo-400/60" : ""} transition-all` }, types.map((t, index) => /* @__PURE__ */ import_react18.default.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, canEdit && t !== "quest" && /* @__PURE__ */ import_react18.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiX, { size: 12 })))), canEdit && /* @__PURE__ */ import_react18.default.createElement(
8931
8964
  "input",
8932
8965
  {
8933
8966
  type: "text",
@@ -10303,7 +10336,7 @@ function XViewScene({
10303
10336
  delete_file_action,
10304
10337
  check_user_permission
10305
10338
  }) {
10306
- var _a, _b, _c, _d, _e, _f, _g;
10339
+ var _a, _b, _c, _d, _e, _f, _g, _h;
10307
10340
  const { data: session, status } = (0, import_react27.useSession)();
10308
10341
  const router = (0, import_navigation.useRouter)();
10309
10342
  const searchParams = (0, import_navigation.useSearchParams)();
@@ -11978,6 +12011,7 @@ function XViewScene({
11978
12011
  const handleSaveQuestNode = async (context, newQuestData) => {
11979
12012
  const { graphDataRef, sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType, sceneConfigId: sceneConfigId2, ownerId: ownerId2 } = context;
11980
12013
  if (!graphDataRef.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
12014
+ const currentCounter = sceneDataRef2.current.quest_counter || 1;
11981
12015
  const newNode = {
11982
12016
  id: import_short_uuid2.default.generate(),
11983
12017
  ...newQuestData,
@@ -11993,10 +12027,13 @@ function XViewScene({
11993
12027
  nodes: sceneDataRef2.current.nodes,
11994
12028
  links: sceneDataRef2.current.links,
11995
12029
  quest_nodes: graphDataRef.current[sceneConfigId2].nodes,
11996
- quest_links: graphDataRef.current[sceneConfigId2].links
12030
+ quest_links: graphDataRef.current[sceneConfigId2].links,
12031
+ quest_counter: currentCounter + 1
12032
+ // NOVO: Incrementa o contador nos metadados
11997
12033
  };
11998
12034
  try {
11999
12035
  await actions.save_view_data(sceneSaveUrl2, sceneFileData);
12036
+ sceneDataRef2.current.quest_counter = currentCounter + 1;
12000
12037
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
12001
12038
  parentFileId: sceneConfigId2,
12002
12039
  ownerId: ownerId2,
@@ -13658,7 +13695,9 @@ function XViewScene({
13658
13695
  onMentionClick: handleAddExistingNode,
13659
13696
  onUploadFile: upload_file_action,
13660
13697
  availableNodes: allAvailableNodes,
13661
- availableAncestries: allAvailableAncestries
13698
+ availableAncestries: allAvailableAncestries,
13699
+ viewName: viewParams == null ? void 0 : viewParams.name,
13700
+ questCounter: ((_g = sceneDataRef.current) == null ? void 0 : _g.quest_counter) || 1
13662
13701
  }
13663
13702
  ),
13664
13703
  readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react26.default.createElement(
@@ -13927,7 +13966,7 @@ function XViewScene({
13927
13966
  onClose: () => setIsImportModalOpen(false),
13928
13967
  onConfirm: handleConfirmImport,
13929
13968
  session,
13930
- parentDbs: ((_g = sceneDataRef.current) == null ? void 0 : _g.parent_dbs) || [],
13969
+ parentDbs: ((_h = sceneDataRef.current) == null ? void 0 : _h.parent_dbs) || [],
13931
13970
  onFetchAvailableFiles: import_parent_file_modal_get,
13932
13971
  currentViewName: viewParams == null ? void 0 : viewParams.name,
13933
13972
  currentAncestries: ancestryDataRef.current || []
package/dist/index.mjs CHANGED
@@ -461,7 +461,11 @@ function XViewSidebar({
461
461
  let pool = base;
462
462
  const qNorm = normalize(query);
463
463
  if (qNorm) {
464
- pool = pool.filter((n) => normalize((n == null ? void 0 : n.name) || "").includes(qNorm));
464
+ pool = pool.filter((n) => {
465
+ const matchName = normalize((n == null ? void 0 : n.name) || "").includes(qNorm);
466
+ const matchRawTitle = n.is_quest && n.raw_title ? normalize(n.raw_title).includes(qNorm) : false;
467
+ return matchName || matchRawTitle;
468
+ });
465
469
  }
466
470
  if (activeFilters.length > 0) {
467
471
  pool = pool.filter((node) => {
@@ -7958,10 +7962,13 @@ function InSceneQuestForm({
7958
7962
  availableAncestries = [],
7959
7963
  onMentionClick,
7960
7964
  onUploadFile,
7961
- // NOVAS PROPS PARA O GHOST NODE
7962
7965
  onNameChange,
7963
7966
  onColorChange,
7964
- onSizeChange
7967
+ onSizeChange,
7968
+ viewName = "Projeto",
7969
+ // NOVA PROP
7970
+ questCounter = 1
7971
+ // NOVA PROP
7965
7972
  }) {
7966
7973
  const [name, setName] = useState16("");
7967
7974
  const [types, setTypes] = useState16(["quest"]);
@@ -7974,6 +7981,7 @@ function InSceneQuestForm({
7974
7981
  const [customProps, setCustomProps] = useState16([]);
7975
7982
  const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState16(false);
7976
7983
  const propsEndRef = useRef12(null);
7984
+ const standardizedName = `${viewName} - ${questCounter} - \xBB ${name || "Nova Quest"}`;
7977
7985
  const handleAddProp = () => {
7978
7986
  const newProp = createNewCustomProperty(customProps);
7979
7987
  setCustomProps([...customProps, newProp]);
@@ -8010,7 +8018,7 @@ function InSceneQuestForm({
8010
8018
  const handleSubmit = (e) => {
8011
8019
  e.preventDefault();
8012
8020
  if (!name.trim()) {
8013
- alert("O campo 'Nome' \xE9 obrigat\xF3rio.");
8021
+ alert("O campo 'T\xEDtulo' \xE9 obrigat\xF3rio.");
8014
8022
  return;
8015
8023
  }
8016
8024
  const additionalData = toObjectFromCustomProps(
@@ -8018,7 +8026,10 @@ function InSceneQuestForm({
8018
8026
  );
8019
8027
  const processedSections = processDescriptionForSave(description, []);
8020
8028
  onSave({
8021
- name: name.trim(),
8029
+ name: standardizedName,
8030
+ // SALVA O NOME FORMATADO
8031
+ raw_title: name.trim(),
8032
+ // Salva o título puro como fallback ou metadado útil
8022
8033
  type: types,
8023
8034
  color: QUEST_STATUS_COLORS[status],
8024
8035
  status,
@@ -8057,7 +8068,21 @@ function InSceneQuestForm({
8057
8068
  },
8058
8069
  "\xD7"
8059
8070
  )),
8060
- /* @__PURE__ */ React15.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col max-h-[68vh]" }, /* @__PURE__ */ React15.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ React15.createElement("div", { className: "relative" }, /* @__PURE__ */ React15.createElement(
8071
+ /* @__PURE__ */ React15.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col max-h-[68vh]" }, /* @__PURE__ */ React15.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "T\xEDtulo da Quest"), /* @__PURE__ */ React15.createElement(
8072
+ "input",
8073
+ {
8074
+ required: true,
8075
+ type: "text",
8076
+ placeholder: "Ex.: Refatorar M\xF3dulo X",
8077
+ value: name,
8078
+ onChange: (e) => {
8079
+ const val = e.target.value;
8080
+ setName(val);
8081
+ onNameChange == null ? void 0 : onNameChange(`${viewName} - ${questCounter} - \xBB ${val || "Nova Quest"}`);
8082
+ },
8083
+ className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60"
8084
+ }
8085
+ ), /* @__PURE__ */ React15.createElement("div", { className: "pt-1 flex items-center gap-1.5" }, /* @__PURE__ */ React15.createElement("span", { className: "text-[10px] uppercase font-bold text-slate-500 tracking-wider" }, "Preview:"), /* @__PURE__ */ React15.createElement("p", { className: "text-xs text-indigo-300 font-medium truncate", title: standardizedName }, standardizedName))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ React15.createElement("div", { className: "relative" }, /* @__PURE__ */ React15.createElement(
8061
8086
  "button",
8062
8087
  {
8063
8088
  type: "button",
@@ -8079,20 +8104,7 @@ function InSceneQuestForm({
8079
8104
  },
8080
8105
  /* @__PURE__ */ React15.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS[s] } }),
8081
8106
  s
8082
- )))))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ React15.createElement(
8083
- "input",
8084
- {
8085
- required: true,
8086
- type: "text",
8087
- placeholder: "Ex.: Refatorar M\xF3dulo X",
8088
- value: name,
8089
- onChange: (e) => {
8090
- setName(e.target.value);
8091
- onNameChange == null ? void 0 : onNameChange(e.target.value);
8092
- },
8093
- className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60"
8094
- }
8095
- )), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ React15.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ React15.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ React15.createElement(FiX4, { size: 12 })))), /* @__PURE__ */ React15.createElement(
8107
+ )))))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ React15.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ React15.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ React15.createElement(FiX4, { size: 12 })))), /* @__PURE__ */ React15.createElement(
8096
8108
  "input",
8097
8109
  {
8098
8110
  type: "text",
@@ -8670,7 +8682,12 @@ function QuestDetailsPanel({
8670
8682
  userRole,
8671
8683
  currentDatasetName
8672
8684
  }) {
8673
- const [name, setName] = useState18((node == null ? void 0 : node.name) ?? "");
8685
+ var _a;
8686
+ const initialRawTitle = (node == null ? void 0 : node.raw_title) || (((_a = node == null ? void 0 : node.name) == null ? void 0 : _a.includes(" - \xBB ")) ? node.name.split(" - \xBB ")[1] : node == null ? void 0 : node.name) || "";
8687
+ const [rawTitle, setRawTitle] = useState18(initialRawTitle);
8688
+ const prefixParts = ((node == null ? void 0 : node.name) || "").split(" - \xBB ");
8689
+ const questPrefix = prefixParts.length > 1 ? prefixParts[0] : "";
8690
+ const standardizedName = questPrefix ? `${questPrefix} - \xBB ${rawTitle || "Sem t\xEDtulo"}` : rawTitle;
8674
8691
  const [types, setTypes] = useState18((node == null ? void 0 : node.type) ? Array.isArray(node.type) ? node.type : [node.type] : ["quest"]);
8675
8692
  const [typeInput, setTypeInput] = useState18("");
8676
8693
  const [status, setStatus] = useState18((node == null ? void 0 : node.status) ?? "Backlog");
@@ -8699,15 +8716,17 @@ function QuestDetailsPanel({
8699
8716
  const propsEndRef = useRef14(null);
8700
8717
  const canEdit = userRole !== "viewer";
8701
8718
  const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
8702
- const handleImageClickFromText = (url, name2) => {
8719
+ const handleImageClickFromText = (url, name) => {
8703
8720
  if (onOpenImageViewer) {
8704
- onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
8721
+ onOpenImageViewer([{ name: name || "Imagem", value: url }], 0);
8705
8722
  }
8706
8723
  };
8707
8724
  useEffect16(() => {
8725
+ var _a2;
8708
8726
  if ((node == null ? void 0 : node.id) !== prevNodeIdRef.current) {
8709
8727
  prevNodeIdRef.current = node == null ? void 0 : node.id;
8710
- setName((node == null ? void 0 : node.name) ?? "");
8728
+ const newRawTitle = (node == null ? void 0 : node.raw_title) || (((_a2 = node == null ? void 0 : node.name) == null ? void 0 : _a2.includes(" - \xBB ")) ? node.name.split(" - \xBB ")[1] : node == null ? void 0 : node.name) || "";
8729
+ setRawTitle(newRawTitle);
8711
8730
  setTypes((node == null ? void 0 : node.type) ? Array.isArray(node.type) ? node.type : [node.type] : ["quest"]);
8712
8731
  setStatus((node == null ? void 0 : node.status) ?? "Backlog");
8713
8732
  setSize((node == null ? void 0 : node.size) ?? "medium");
@@ -8742,9 +8761,10 @@ function QuestDetailsPanel({
8742
8761
  };
8743
8762
  const swallow = (e) => e.stopPropagation();
8744
8763
  const handleNameChange = (e) => {
8745
- const v = e.target.value;
8746
- setName(v);
8747
- onNameChange == null ? void 0 : onNameChange(node.id, v);
8764
+ const val = e.target.value;
8765
+ setRawTitle(val);
8766
+ const newStandardName = questPrefix ? `${questPrefix} - \xBB ${val || "Sem t\xEDtulo"}` : val;
8767
+ onNameChange == null ? void 0 : onNameChange(node.id, newStandardName);
8748
8768
  };
8749
8769
  const handleSizeChange = (newSize) => {
8750
8770
  setSize(newSize);
@@ -8780,8 +8800,8 @@ function QuestDetailsPanel({
8780
8800
  const newProp = createNewCustomProperty(customProps);
8781
8801
  setCustomProps((p) => [...p, newProp]);
8782
8802
  setTimeout(() => {
8783
- var _a;
8784
- (_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
8803
+ var _a2;
8804
+ (_a2 = propsEndRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth", block: "center" });
8785
8805
  }, 100);
8786
8806
  };
8787
8807
  const handleRemoveProp = (i) => {
@@ -8803,14 +8823,15 @@ function QuestDetailsPanel({
8803
8823
  triggerAutoSave({ description: newDescription });
8804
8824
  };
8805
8825
  const handleSave = async (keepOpen = false, overrides = {}) => {
8806
- const currentName = overrides.name !== void 0 ? overrides.name : name;
8826
+ const currentRawTitle = overrides.rawTitle !== void 0 ? overrides.rawTitle : rawTitle;
8827
+ const currentStandardName = questPrefix ? `${questPrefix} - \xBB ${currentRawTitle || "Sem t\xEDtulo"}` : currentRawTitle;
8807
8828
  const currentTypes = overrides.types !== void 0 ? overrides.types : types;
8808
8829
  const currentDescription = overrides.description !== void 0 ? overrides.description : description;
8809
8830
  const currentCustomProps = overrides.customProps !== void 0 ? overrides.customProps : customProps;
8810
8831
  const currentExistingSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
8811
8832
  const currentStatus = overrides.status !== void 0 ? overrides.status : status;
8812
- if (!currentName.trim() || currentTypes.length === 0) {
8813
- alert("O campo 'Nome' e pelo menos um 'Tipo' s\xE3o obrigat\xF3rios.");
8833
+ if (!currentRawTitle.trim() || currentTypes.length === 0) {
8834
+ alert("O campo 'T\xEDtulo' e pelo menos um 'Tipo' s\xE3o obrigat\xF3rios.");
8814
8835
  return;
8815
8836
  }
8816
8837
  setIsSaving(true);
@@ -8819,7 +8840,10 @@ function QuestDetailsPanel({
8819
8840
  const processedSections = processDescriptionForSave(currentDescription, currentExistingSections);
8820
8841
  const dataToSave = {
8821
8842
  id: node.id,
8822
- name: currentName.trim(),
8843
+ name: currentStandardName.trim(),
8844
+ // Salva o nome completo formatado
8845
+ raw_title: currentRawTitle.trim(),
8846
+ // Salva o título simples
8823
8847
  type: currentTypes,
8824
8848
  color: QUEST_STATUS_COLORS2[currentStatus],
8825
8849
  status: currentStatus,
@@ -8874,7 +8898,7 @@ function QuestDetailsPanel({
8874
8898
  isReadMode ? /* @__PURE__ */ React17.createElement(
8875
8899
  DescriptionReadModePanel,
8876
8900
  {
8877
- title: name || (node == null ? void 0 : node.name),
8901
+ title: standardizedName || (node == null ? void 0 : node.name),
8878
8902
  description,
8879
8903
  savedSections: existingSections,
8880
8904
  onBack: () => setIsReadMode(false),
@@ -8892,7 +8916,16 @@ function QuestDetailsPanel({
8892
8916
  onImageClick: handleImageClickFromText,
8893
8917
  onSaveDescription: handleSaveDescriptionInline
8894
8918
  }
8895
- ) : /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS2[status]}, transparent)` } }), /* @__PURE__ */ React17.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React17.createElement("div", null, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React17.createElement(FiTarget2, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React17.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ React17.createElement("button", { onClick: handleCopyLink, className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-sky-400"}`, title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Quest" }, isLinkCopied ? /* @__PURE__ */ React17.createElement(FiCheck11, { size: 12 }) : /* @__PURE__ */ React17.createElement(FiLink6, { size: 12 }))), /* @__PURE__ */ React17.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || (node == null ? void 0 : node.name))), /* @__PURE__ */ React17.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Cancelar" }, "\xD7")), /* @__PURE__ */ React17.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ React17.createElement("div", { className: "relative" }, /* @__PURE__ */ React17.createElement(
8919
+ ) : /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS2[status]}, transparent)` } }), /* @__PURE__ */ React17.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React17.createElement("div", null, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React17.createElement(FiTarget2, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React17.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ React17.createElement("button", { onClick: handleCopyLink, className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-sky-400"}`, title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Quest" }, isLinkCopied ? /* @__PURE__ */ React17.createElement(FiCheck11, { size: 12 }) : /* @__PURE__ */ React17.createElement(FiLink6, { size: 12 }))), /* @__PURE__ */ React17.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, standardizedName || (node == null ? void 0 : node.name))), /* @__PURE__ */ React17.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Cancelar" }, "\xD7")), /* @__PURE__ */ React17.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "T\xEDtulo da Quest"), /* @__PURE__ */ React17.createElement(
8920
+ "input",
8921
+ {
8922
+ type: "text",
8923
+ value: rawTitle,
8924
+ onChange: handleNameChange,
8925
+ readOnly: !canEdit,
8926
+ className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none ${canEdit ? "focus:ring-2 focus:ring-indigo-400/60" : "cursor-default text-slate-400"}`
8927
+ }
8928
+ ), /* @__PURE__ */ React17.createElement("div", { className: "pt-1 flex items-center gap-1.5" }, /* @__PURE__ */ React17.createElement("span", { className: "text-[10px] uppercase font-bold text-slate-500 tracking-wider" }, "Preview:"), /* @__PURE__ */ React17.createElement("p", { className: "text-xs text-indigo-300 font-medium truncate", title: standardizedName }, standardizedName))), /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ React17.createElement("div", { className: "relative" }, /* @__PURE__ */ React17.createElement(
8896
8929
  "button",
8897
8930
  {
8898
8931
  type: "button",
@@ -8914,7 +8947,7 @@ function QuestDetailsPanel({
8914
8947
  },
8915
8948
  /* @__PURE__ */ React17.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS2[s] } }),
8916
8949
  s
8917
- )))))), /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "Nome"), /* @__PURE__ */ React17.createElement("input", { type: "text", value: name, onChange: handleNameChange, readOnly: !canEdit, className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none ${canEdit ? "focus:ring-2 focus:ring-indigo-400/60" : "cursor-default text-slate-400"}` })), /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ React17.createElement("div", { className: `relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 ${canEdit ? "focus-within:ring-2 focus-within:ring-indigo-400/60" : ""} transition-all` }, types.map((t, index) => /* @__PURE__ */ React17.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, canEdit && t !== "quest" && /* @__PURE__ */ React17.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ React17.createElement(FiX6, { size: 12 })))), canEdit && /* @__PURE__ */ React17.createElement(
8950
+ )))))), /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ React17.createElement("div", { className: `relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 ${canEdit ? "focus-within:ring-2 focus-within:ring-indigo-400/60" : ""} transition-all` }, types.map((t, index) => /* @__PURE__ */ React17.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, canEdit && t !== "quest" && /* @__PURE__ */ React17.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ React17.createElement(FiX6, { size: 12 })))), canEdit && /* @__PURE__ */ React17.createElement(
8918
8951
  "input",
8919
8952
  {
8920
8953
  type: "text",
@@ -10303,7 +10336,7 @@ function XViewScene({
10303
10336
  delete_file_action,
10304
10337
  check_user_permission
10305
10338
  }) {
10306
- var _a, _b, _c, _d, _e, _f, _g;
10339
+ var _a, _b, _c, _d, _e, _f, _g, _h;
10307
10340
  const { data: session, status } = useSession();
10308
10341
  const router = useRouter();
10309
10342
  const searchParams = useSearchParams();
@@ -11978,6 +12011,7 @@ function XViewScene({
11978
12011
  const handleSaveQuestNode = async (context, newQuestData) => {
11979
12012
  const { graphDataRef, sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType, sceneConfigId: sceneConfigId2, ownerId: ownerId2 } = context;
11980
12013
  if (!graphDataRef.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
12014
+ const currentCounter = sceneDataRef2.current.quest_counter || 1;
11981
12015
  const newNode = {
11982
12016
  id: short2.generate(),
11983
12017
  ...newQuestData,
@@ -11993,10 +12027,13 @@ function XViewScene({
11993
12027
  nodes: sceneDataRef2.current.nodes,
11994
12028
  links: sceneDataRef2.current.links,
11995
12029
  quest_nodes: graphDataRef.current[sceneConfigId2].nodes,
11996
- quest_links: graphDataRef.current[sceneConfigId2].links
12030
+ quest_links: graphDataRef.current[sceneConfigId2].links,
12031
+ quest_counter: currentCounter + 1
12032
+ // NOVO: Incrementa o contador nos metadados
11997
12033
  };
11998
12034
  try {
11999
12035
  await actions.save_view_data(sceneSaveUrl2, sceneFileData);
12036
+ sceneDataRef2.current.quest_counter = currentCounter + 1;
12000
12037
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
12001
12038
  parentFileId: sceneConfigId2,
12002
12039
  ownerId: ownerId2,
@@ -13658,7 +13695,9 @@ function XViewScene({
13658
13695
  onMentionClick: handleAddExistingNode,
13659
13696
  onUploadFile: upload_file_action,
13660
13697
  availableNodes: allAvailableNodes,
13661
- availableAncestries: allAvailableAncestries
13698
+ availableAncestries: allAvailableAncestries,
13699
+ viewName: viewParams == null ? void 0 : viewParams.name,
13700
+ questCounter: ((_g = sceneDataRef.current) == null ? void 0 : _g.quest_counter) || 1
13662
13701
  }
13663
13702
  ),
13664
13703
  readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React25.createElement(
@@ -13927,7 +13966,7 @@ function XViewScene({
13927
13966
  onClose: () => setIsImportModalOpen(false),
13928
13967
  onConfirm: handleConfirmImport,
13929
13968
  session,
13930
- parentDbs: ((_g = sceneDataRef.current) == null ? void 0 : _g.parent_dbs) || [],
13969
+ parentDbs: ((_h = sceneDataRef.current) == null ? void 0 : _h.parent_dbs) || [],
13931
13970
  onFetchAvailableFiles: import_parent_file_modal_get,
13932
13971
  currentViewName: viewParams == null ? void 0 : viewParams.name,
13933
13972
  currentAncestries: ancestryDataRef.current || []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lv-x-software-house/x_view",
3
- "version": "1.2.4-dev.24",
3
+ "version": "1.2.4-dev.26",
4
4
  "description": "Pacote privado contendo os componentes e lógica de renderização 3D do X View.",
5
5
  "author": "iv.x - Engenharia de Software - ivxsoftwarehouse@gmail.com",
6
6
  "license": "UNLICENSED",