@lv-x-software-house/x_view 1.2.6-dev.59 → 1.2.6-dev.61

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 +243 -24
  2. package/dist/index.mjs +243 -24
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8943,6 +8943,8 @@ function ColorPicker({ color, onChange, disabled, isCompact = false }) {
8943
8943
 
8944
8944
  // src/components/InSceneCreationForm.jsx
8945
8945
  var import_fi13 = require("react-icons/fi");
8946
+ var import_si = require("react-icons/si");
8947
+ var import_ai = require("react-icons/ai");
8946
8948
  function InSceneCreationForm({
8947
8949
  onSave,
8948
8950
  onCancel,
@@ -8963,7 +8965,8 @@ function InSceneCreationForm({
8963
8965
  onUploadFile,
8964
8966
  availableDatasets = [],
8965
8967
  sourceNodeDatasetId,
8966
- viewType
8968
+ viewType,
8969
+ create_google_doc_action
8967
8970
  }) {
8968
8971
  var _a;
8969
8972
  const [name, setName] = (0, import_react14.useState)("");
@@ -8983,6 +8986,7 @@ function InSceneCreationForm({
8983
8986
  sourceNodeDatasetId || ""
8984
8987
  );
8985
8988
  const [isDatasetDropdownOpen, setIsDatasetDropdownOpen] = (0, import_react14.useState)(false);
8989
+ const [isLoadingDocs, setIsLoadingDocs] = (0, import_react14.useState)(false);
8986
8990
  const datasetDropdownRef = (0, import_react14.useRef)(null);
8987
8991
  (0, import_react14.useEffect)(() => {
8988
8992
  if (sourceNodeDatasetId) setTargetDatasetId(sourceNodeDatasetId);
@@ -9121,6 +9125,33 @@ function InSceneCreationForm({
9121
9125
  setSelectedImageUrl(url);
9122
9126
  onImageChange == null ? void 0 : onImageChange(true, url);
9123
9127
  };
9128
+ const handleCreateGoogleDoc = async () => {
9129
+ if (!name.trim()) {
9130
+ alert("Por favor, insira um nome para o node antes de criar o documento.");
9131
+ return;
9132
+ }
9133
+ if (!create_google_doc_action) return;
9134
+ try {
9135
+ setIsLoadingDocs(true);
9136
+ const res = await create_google_doc_action(name);
9137
+ if (res.success) {
9138
+ const newProp = {
9139
+ id: (0, import_uuid5.v4)(),
9140
+ key: "Google Docs",
9141
+ type: "links",
9142
+ value: [{ id: (0, import_uuid5.v4)(), name: "Abrir Documento", value: res.link }]
9143
+ };
9144
+ setCustomProps((prev) => [...prev, newProp]);
9145
+ } else {
9146
+ alert("Erro ao criar documento: " + res.error);
9147
+ }
9148
+ } catch (error) {
9149
+ console.error(error);
9150
+ alert("Erro ao processar cria\xE7\xE3o do documento.");
9151
+ } finally {
9152
+ setIsLoadingDocs(false);
9153
+ }
9154
+ };
9124
9155
  const handleSubmit = (e) => {
9125
9156
  e.preventDefault();
9126
9157
  if (!name.trim() || types.length === 0) {
@@ -9360,7 +9391,18 @@ function InSceneCreationForm({
9360
9391
  className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}`
9361
9392
  },
9362
9393
  useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Selecione a cor e ajuste o brilho."
9363
- )), /* @__PURE__ */ import_react14.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react14.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react14.default.createElement(
9394
+ )), /* @__PURE__ */ import_react14.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react14.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, create_google_doc_action && /* @__PURE__ */ import_react14.default.createElement(
9395
+ "button",
9396
+ {
9397
+ type: "button",
9398
+ onClick: handleCreateGoogleDoc,
9399
+ disabled: isLoadingDocs,
9400
+ className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-indigo-600/20 hover:bg-indigo-600/30 text-indigo-300 border border-indigo-500/30 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
9401
+ title: "Criar Documento no Google Docs"
9402
+ },
9403
+ isLoadingDocs ? /* @__PURE__ */ import_react14.default.createElement(import_ai.AiOutlineLoading3Quarters, { className: "animate-spin", size: 14 }) : /* @__PURE__ */ import_react14.default.createElement(import_si.SiGoogledocs, { size: 14, className: "group-hover:scale-110 transition-transform" }),
9404
+ isLoadingDocs ? "Criando..." : "Google Doc"
9405
+ ), /* @__PURE__ */ import_react14.default.createElement(
9364
9406
  "button",
9365
9407
  {
9366
9408
  type: "button",
@@ -9369,7 +9411,7 @@ function InSceneCreationForm({
9369
9411
  },
9370
9412
  /* @__PURE__ */ import_react14.default.createElement(import_fi13.FiPlus, { size: 14 }),
9371
9413
  " Adicionar"
9372
- )), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ import_react14.default.createElement(
9414
+ ))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ import_react14.default.createElement(
9373
9415
  CustomPropertyDisplay,
9374
9416
  {
9375
9417
  key: prop.id,
@@ -9738,6 +9780,8 @@ function InSceneVersionForm({
9738
9780
  var import_react17 = __toESM(require("react"));
9739
9781
  var import_uuid7 = require("uuid");
9740
9782
  var import_fi16 = require("react-icons/fi");
9783
+ var import_si2 = require("react-icons/si");
9784
+ var import_ai2 = require("react-icons/ai");
9741
9785
 
9742
9786
  // src/components/QuestReviewStackEditor.jsx
9743
9787
  var import_react16 = __toESM(require("react"));
@@ -9919,7 +9963,8 @@ function InSceneQuestForm({
9919
9963
  session = null,
9920
9964
  milestones = [],
9921
9965
  onUpdateMilestones = () => {
9922
- }
9966
+ },
9967
+ create_google_doc_action
9923
9968
  }) {
9924
9969
  var _a, _b;
9925
9970
  const [name, setName] = (0, import_react17.useState)("");
@@ -9947,6 +9992,7 @@ function InSceneQuestForm({
9947
9992
  const [isAssigneeDropdownOpen, setIsAssigneeDropdownOpen] = (0, import_react17.useState)(false);
9948
9993
  const [assigneeSearchQuery, setAssigneeSearchQuery] = (0, import_react17.useState)("");
9949
9994
  const [isNameCopied, setIsNameCopied] = (0, import_react17.useState)(false);
9995
+ const [isLoadingDocs, setIsLoadingDocs] = (0, import_react17.useState)(false);
9950
9996
  const [customProps, setCustomProps] = (0, import_react17.useState)([]);
9951
9997
  const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react17.useState)(false);
9952
9998
  const propsEndRef = (0, import_react17.useRef)(null);
@@ -10034,6 +10080,33 @@ function InSceneQuestForm({
10034
10080
  console.error("Erro ao copiar nome:", err);
10035
10081
  });
10036
10082
  };
10083
+ const handleCreateGoogleDoc = async () => {
10084
+ if (!name.trim()) {
10085
+ alert("Por favor, insira um t\xEDtulo para a quest antes de criar o documento.");
10086
+ return;
10087
+ }
10088
+ if (!create_google_doc_action) return;
10089
+ try {
10090
+ setIsLoadingDocs(true);
10091
+ const res = await create_google_doc_action(standardizedName);
10092
+ if (res.success) {
10093
+ const newProp = {
10094
+ id: (0, import_uuid7.v4)(),
10095
+ key: "Google Docs",
10096
+ type: "links",
10097
+ value: [{ id: (0, import_uuid7.v4)(), name: "Abrir Documento", value: res.link }]
10098
+ };
10099
+ setCustomProps((prev) => [...prev, newProp]);
10100
+ } else {
10101
+ alert("Erro ao criar documento: " + res.error);
10102
+ }
10103
+ } catch (error) {
10104
+ console.error(error);
10105
+ alert("Erro ao processar cria\xE7\xE3o do documento.");
10106
+ } finally {
10107
+ setIsLoadingDocs(false);
10108
+ }
10109
+ };
10037
10110
  const handleAddProp = () => {
10038
10111
  const newProp = createNewCustomProperty(customProps);
10039
10112
  setCustomProps([...customProps, newProp]);
@@ -10552,7 +10625,18 @@ function InSceneQuestForm({
10552
10625
  className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
10553
10626
  },
10554
10627
  "Adicionar descri\xE7\xE3o..."
10555
- ))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react17.default.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react17.default.createElement(
10628
+ ))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react17.default.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center gap-2" }, create_google_doc_action && /* @__PURE__ */ import_react17.default.createElement(
10629
+ "button",
10630
+ {
10631
+ type: "button",
10632
+ onClick: handleCreateGoogleDoc,
10633
+ disabled: isLoadingDocs,
10634
+ className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-indigo-600/20 hover:bg-indigo-600/30 text-indigo-300 border border-indigo-500/30 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
10635
+ title: "Criar Documento no Google Docs"
10636
+ },
10637
+ isLoadingDocs ? /* @__PURE__ */ import_react17.default.createElement(import_ai2.AiOutlineLoading3Quarters, { className: "animate-spin", size: 14 }) : /* @__PURE__ */ import_react17.default.createElement(import_si2.SiGoogledocs, { size: 14, className: "group-hover:scale-110 transition-transform" }),
10638
+ isLoadingDocs ? "Criando..." : "Google Doc"
10639
+ ), /* @__PURE__ */ import_react17.default.createElement(
10556
10640
  "button",
10557
10641
  {
10558
10642
  type: "button",
@@ -10561,7 +10645,7 @@ function InSceneQuestForm({
10561
10645
  },
10562
10646
  /* @__PURE__ */ import_react17.default.createElement(import_fi16.FiPlus, { size: 14 }),
10563
10647
  " Adicionar"
10564
- )), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ import_react17.default.createElement(
10648
+ ))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ import_react17.default.createElement(
10565
10649
  CustomPropertyDisplay,
10566
10650
  {
10567
10651
  key: prop.id,
@@ -10663,6 +10747,8 @@ function InSceneQuestForm({
10663
10747
  var import_react18 = __toESM(require("react"));
10664
10748
  var import_uuid8 = require("uuid");
10665
10749
  var import_fi17 = require("react-icons/fi");
10750
+ var import_si3 = require("react-icons/si");
10751
+ var import_ai3 = require("react-icons/ai");
10666
10752
  function NodeDetailsPanel({
10667
10753
  node,
10668
10754
  onClose,
@@ -10681,7 +10767,8 @@ function NodeDetailsPanel({
10681
10767
  onIntensityChange,
10682
10768
  onUploadFile,
10683
10769
  userRole,
10684
- currentDatasetName
10770
+ currentDatasetName,
10771
+ create_google_doc_action
10685
10772
  }) {
10686
10773
  const [name, setName] = (0, import_react18.useState)((node == null ? void 0 : node.name) ?? "");
10687
10774
  const [types, setTypes] = (0, import_react18.useState)([]);
@@ -10697,6 +10784,7 @@ function NodeDetailsPanel({
10697
10784
  const [isReadMode, setIsReadMode] = (0, import_react18.useState)(false);
10698
10785
  const [existingSections, setExistingSections] = (0, import_react18.useState)((node == null ? void 0 : node.description_sections) || []);
10699
10786
  const [isSaving, setIsSaving] = (0, import_react18.useState)(false);
10787
+ const [isLoadingDocs, setIsLoadingDocs] = (0, import_react18.useState)(false);
10700
10788
  const [isLinkCopied, setIsLinkCopied] = (0, import_react18.useState)(false);
10701
10789
  const [useImageAsTexture, setUseImageAsTexture] = (0, import_react18.useState)(() => {
10702
10790
  if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
@@ -10851,6 +10939,36 @@ function NodeDetailsPanel({
10851
10939
  triggerAutoSave({ customProps: newProps });
10852
10940
  }
10853
10941
  };
10942
+ const handleCreateGoogleDoc = async () => {
10943
+ if (!name.trim()) {
10944
+ alert("Por favor, insira um nome para o node antes de criar o documento.");
10945
+ return;
10946
+ }
10947
+ if (!create_google_doc_action) return;
10948
+ try {
10949
+ setIsLoadingDocs(true);
10950
+ const res = await create_google_doc_action(name);
10951
+ if (res.success) {
10952
+ const newProp = {
10953
+ id: (0, import_uuid8.v4)(),
10954
+ key: "Google Docs",
10955
+ type: "links",
10956
+ value: [{ id: (0, import_uuid8.v4)(), name: "Abrir Documento", value: res.link }]
10957
+ };
10958
+ const updatedProps = [...customProps, newProp];
10959
+ setCustomProps(updatedProps);
10960
+ setHasUnsavedChanges(true);
10961
+ triggerAutoSave({ customProps: updatedProps });
10962
+ } else {
10963
+ alert("Erro ao criar documento: " + res.error);
10964
+ }
10965
+ } catch (error) {
10966
+ console.error(error);
10967
+ alert("Erro ao processar cria\xE7\xE3o do documento.");
10968
+ } finally {
10969
+ setIsLoadingDocs(false);
10970
+ }
10971
+ };
10854
10972
  const handleToggleImageMode = () => {
10855
10973
  setUseImageAsTexture(newValue);
10856
10974
  setHasUnsavedChanges(true);
@@ -11127,7 +11245,27 @@ function NodeDetailsPanel({
11127
11245
  className: `w-full h-1.5 bg-slate-700 rounded-lg appearance-none ${canEdit ? "cursor-pointer accent-indigo-500 hover:accent-indigo-400" : "cursor-default accent-slate-500"}`,
11128
11246
  title: `Intensidade do brilho: ${intensity}`
11129
11247
  }
11130
- ), /* @__PURE__ */ import_react18.default.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ import_react18.default.createElement("span", { className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}` }, useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Ajuste a cor e a intensidade do brilho.")), /* @__PURE__ */ import_react18.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react18.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ import_react18.default.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ import_react18.default.createElement(import_fi17.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react18.default.createElement(
11248
+ ), /* @__PURE__ */ import_react18.default.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ import_react18.default.createElement("span", { className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}` }, useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Ajuste a cor e a intensidade do brilho.")), /* @__PURE__ */ import_react18.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react18.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2" }, canEdit && create_google_doc_action && /* @__PURE__ */ import_react18.default.createElement(
11249
+ "button",
11250
+ {
11251
+ type: "button",
11252
+ onClick: handleCreateGoogleDoc,
11253
+ disabled: isLoadingDocs,
11254
+ className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-indigo-600/20 hover:bg-indigo-600/30 text-indigo-300 border border-indigo-500/30 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
11255
+ title: "Criar Documento no Google Docs"
11256
+ },
11257
+ isLoadingDocs ? /* @__PURE__ */ import_react18.default.createElement(import_ai3.AiOutlineLoading3Quarters, { className: "animate-spin", size: 14 }) : /* @__PURE__ */ import_react18.default.createElement(import_si3.SiGoogledocs, { size: 14, className: "group-hover:scale-110 transition-transform" }),
11258
+ isLoadingDocs ? "Criando..." : "Google Doc"
11259
+ ), canEdit && /* @__PURE__ */ import_react18.default.createElement(
11260
+ "button",
11261
+ {
11262
+ type: "button",
11263
+ onClick: handleAddProp,
11264
+ className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors"
11265
+ },
11266
+ /* @__PURE__ */ import_react18.default.createElement(import_fi17.FiPlus, { size: 14 }),
11267
+ " Adicionar"
11268
+ ))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react18.default.createElement(
11131
11269
  CustomPropertyDisplay,
11132
11270
  {
11133
11271
  key: prop.id,
@@ -11251,6 +11389,8 @@ function QuestTimeline({
11251
11389
  }
11252
11390
 
11253
11391
  // src/components/QuestDetailsPanel.jsx
11392
+ var import_si4 = require("react-icons/si");
11393
+ var import_ai4 = require("react-icons/ai");
11254
11394
  var QUEST_STATUS_COLORS3 = {
11255
11395
  "Backlog": "#64748b",
11256
11396
  "In Progress": "#eab308",
@@ -11279,7 +11419,8 @@ function QuestDetailsPanel({
11279
11419
  milestones = [],
11280
11420
  onUpdateMilestones = () => {
11281
11421
  },
11282
- onFocusNode
11422
+ onFocusNode,
11423
+ create_google_doc_action
11283
11424
  }) {
11284
11425
  var _a, _b;
11285
11426
  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) || "";
@@ -11313,6 +11454,7 @@ function QuestDetailsPanel({
11313
11454
  const [isSaving, setIsSaving] = (0, import_react20.useState)(false);
11314
11455
  const [isLinkCopied, setIsLinkCopied] = (0, import_react20.useState)(false);
11315
11456
  const [isNameCopied, setIsNameCopied] = (0, import_react20.useState)(false);
11457
+ const [isLoadingDocs, setIsLoadingDocs] = (0, import_react20.useState)(false);
11316
11458
  const [hasUnsavedChanges, setHasUnsavedChanges] = (0, import_react20.useState)(false);
11317
11459
  const [questDate, setQuestDate] = (0, import_react20.useState)((node == null ? void 0 : node.Date) || null);
11318
11460
  const [noteText, setNoteText] = (0, import_react20.useState)("");
@@ -11713,6 +11855,36 @@ ${noteText}` : noteText : entry.notes,
11713
11855
  triggerAutoSave({ customProps: newProps });
11714
11856
  }
11715
11857
  };
11858
+ const handleCreateGoogleDoc = async () => {
11859
+ if (!rawTitle.trim()) {
11860
+ alert("Por favor, insira um t\xEDtulo para a quest antes de criar o documento.");
11861
+ return;
11862
+ }
11863
+ if (!create_google_doc_action) return;
11864
+ try {
11865
+ setIsLoadingDocs(true);
11866
+ const res = await create_google_doc_action(standardizedName);
11867
+ if (res.success) {
11868
+ const newProp = {
11869
+ id: (0, import_uuid9.v4)(),
11870
+ key: "Google Docs",
11871
+ type: "links",
11872
+ value: [{ id: (0, import_uuid9.v4)(), name: "Abrir Documento", value: res.link }]
11873
+ };
11874
+ const updatedProps = [...customProps, newProp];
11875
+ setCustomProps(updatedProps);
11876
+ setHasUnsavedChanges(true);
11877
+ triggerAutoSave({ customProps: updatedProps });
11878
+ } else {
11879
+ alert("Erro ao criar documento: " + res.error);
11880
+ }
11881
+ } catch (error) {
11882
+ console.error(error);
11883
+ alert("Erro ao processar cria\xE7\xE3o do documento.");
11884
+ } finally {
11885
+ setIsLoadingDocs(false);
11886
+ }
11887
+ };
11716
11888
  const handleSaveDescriptionInline = (newDescription) => {
11717
11889
  setDescription(newDescription);
11718
11890
  setHasUnsavedChanges(true);
@@ -12318,7 +12490,18 @@ ${noteText}` : noteText : entry.notes,
12318
12490
  },
12319
12491
  /* @__PURE__ */ import_react20.default.createElement("span", { className: "truncate" }, q.raw_title || q.name),
12320
12492
  /* @__PURE__ */ import_react20.default.createElement("span", { className: `text-[10px] px-1.5 py-0.5 rounded border ${q.status === "Done" ? "text-green-400 border-green-500/30" : "text-slate-500 border-white/5"}` }, q.status || "Backlog")
12321
- )) : /* @__PURE__ */ import_react20.default.createElement("li", { className: "px-3 py-3 text-[10px] text-slate-500 italic text-center" }, "Nenhuma outra quest dispon\xEDvel")))), blockedStatus.isBlocked && /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center gap-2 px-3 py-2 bg-amber-500/5 rounded-lg border border-amber-500/10 animate-in fade-in slide-in-from-top-1" }, /* @__PURE__ */ import_react20.default.createElement(import_fi19.FiRepeat, { className: "text-amber-400 animate-spin-slow", size: 12 }), /* @__PURE__ */ import_react20.default.createElement("p", { className: "text-[10px] text-amber-200/80 font-medium" }, "Esta quest est\xE1 bloqueada por ", blockedStatus.pendingDependencies.length, " tarefa(s) pendente(s)."))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react20.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ import_react20.default.createElement(import_fi19.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react20.default.createElement(CustomPropertyDisplay, { key: prop.id, prop, onUpdate: canEdit ? (updatedProp) => handleUpdateProp(idx, updatedProp) : void 0, onRemove: canEdit ? () => handleRemoveProp(idx) : void 0, onOpenImageViewer, unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type), isTextureMode: false, onUploadFile: canEdit ? onUploadFile : void 0, readOnly: !canEdit })), /* @__PURE__ */ import_react20.default.createElement("div", { ref: propsEndRef }))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "pt-6 border-t border-white/10 mt-6" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ import_react20.default.createElement("h3", { className: "text-[11px] uppercase font-bold text-slate-500 tracking-wider" }, "Hist\xF3rico & Notas"), /* @__PURE__ */ import_react20.default.createElement(
12493
+ )) : /* @__PURE__ */ import_react20.default.createElement("li", { className: "px-3 py-3 text-[10px] text-slate-500 italic text-center" }, "Nenhuma outra quest dispon\xEDvel")))), blockedStatus.isBlocked && /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center gap-2 px-3 py-2 bg-amber-500/5 rounded-lg border border-amber-500/10 animate-in fade-in slide-in-from-top-1" }, /* @__PURE__ */ import_react20.default.createElement(import_fi19.FiRepeat, { className: "text-amber-400 animate-spin-slow", size: 12 }), /* @__PURE__ */ import_react20.default.createElement("p", { className: "text-[10px] text-amber-200/80 font-medium" }, "Esta quest est\xE1 bloqueada por ", blockedStatus.pendingDependencies.length, " tarefa(s) pendente(s)."))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react20.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center gap-2" }, canEdit && create_google_doc_action && /* @__PURE__ */ import_react20.default.createElement(
12494
+ "button",
12495
+ {
12496
+ type: "button",
12497
+ onClick: handleCreateGoogleDoc,
12498
+ disabled: isLoadingDocs,
12499
+ className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-indigo-600/20 hover:bg-indigo-600/30 text-indigo-300 border border-indigo-500/30 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
12500
+ title: "Criar Documento no Google Docs"
12501
+ },
12502
+ isLoadingDocs ? /* @__PURE__ */ import_react20.default.createElement(import_ai4.AiOutlineLoading3Quarters, { className: "animate-spin", size: 14 }) : /* @__PURE__ */ import_react20.default.createElement(import_si4.SiGoogledocs, { size: 14, className: "group-hover:scale-110 transition-transform" }),
12503
+ isLoadingDocs ? "Criando..." : "Google Doc"
12504
+ ), canEdit && /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ import_react20.default.createElement(import_fi19.FiPlus, { size: 14 }), " Adicionar"))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react20.default.createElement(CustomPropertyDisplay, { key: prop.id, prop, onUpdate: canEdit ? (updatedProp) => handleUpdateProp(idx, updatedProp) : void 0, onRemove: canEdit ? () => handleRemoveProp(idx) : void 0, onOpenImageViewer, unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type), isTextureMode: false, onUploadFile: canEdit ? onUploadFile : void 0, readOnly: !canEdit })), /* @__PURE__ */ import_react20.default.createElement("div", { ref: propsEndRef }))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "pt-6 border-t border-white/10 mt-6" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ import_react20.default.createElement("h3", { className: "text-[11px] uppercase font-bold text-slate-500 tracking-wider" }, "Hist\xF3rico & Notas"), /* @__PURE__ */ import_react20.default.createElement(
12322
12505
  "button",
12323
12506
  {
12324
12507
  type: "button",
@@ -12533,7 +12716,8 @@ function RelationshipDetailsPanel({
12533
12716
  onOpenReference,
12534
12717
  onMentionClick,
12535
12718
  onUploadFile,
12536
- userRole
12719
+ userRole,
12720
+ onHighlight
12537
12721
  }) {
12538
12722
  const [name, setName] = (0, import_react22.useState)((link == null ? void 0 : link.name) ?? "");
12539
12723
  const [description, setDescription] = (0, import_react22.useState)((link == null ? void 0 : link.description) ?? "");
@@ -12563,6 +12747,11 @@ function RelationshipDetailsPanel({
12563
12747
  setTargetLabel((link == null ? void 0 : link.target_label) ?? "");
12564
12748
  setHasUnsavedChanges(false);
12565
12749
  }, [link]);
12750
+ (0, import_react22.useEffect)(() => {
12751
+ return () => {
12752
+ if (onHighlight) onHighlight(null);
12753
+ };
12754
+ }, [onHighlight]);
12566
12755
  const swallow = (e) => e.stopPropagation();
12567
12756
  const handleAddProp = () => {
12568
12757
  if (!canEdit) return;
@@ -12609,10 +12798,8 @@ function RelationshipDetailsPanel({
12609
12798
  isCurved: link.isCurved,
12610
12799
  curveOffset: link.curveOffset
12611
12800
  };
12612
- if (currentSourceLabel.trim())
12613
- dataToSave.source_label = currentSourceLabel.trim();
12614
- if (currentTargetLabel.trim())
12615
- dataToSave.target_label = currentTargetLabel.trim();
12801
+ dataToSave.source_label = currentSourceLabel.trim();
12802
+ dataToSave.target_label = currentTargetLabel.trim();
12616
12803
  await onSave(dataToSave, keepOpen);
12617
12804
  onDataUpdate(dataToSave);
12618
12805
  setHasUnsavedChanges(false);
@@ -12742,6 +12929,8 @@ function RelationshipDetailsPanel({
12742
12929
  },
12743
12930
  placeholder: "Ex: Conceitos",
12744
12931
  disabled: !canEdit,
12932
+ onFocus: () => onHighlight == null ? void 0 : onHighlight(link.source),
12933
+ onBlur: () => onHighlight == null ? void 0 : onHighlight(null),
12745
12934
  className: `w-full bg-slate-900/60 p-2 text-xs rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-violet-400/60 placeholder:text-slate-600
12746
12935
  ${!canEdit ? "opacity-50 cursor-not-allowed" : ""}
12747
12936
  `
@@ -12757,6 +12946,8 @@ function RelationshipDetailsPanel({
12757
12946
  },
12758
12947
  placeholder: "Ex: Refer\xEAncias",
12759
12948
  disabled: !canEdit,
12949
+ onFocus: () => onHighlight == null ? void 0 : onHighlight(link.target),
12950
+ onBlur: () => onHighlight == null ? void 0 : onHighlight(null),
12760
12951
  className: `w-full bg-slate-900/60 p-2 text-xs rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-violet-400/60 placeholder:text-slate-600
12761
12952
  ${!canEdit ? "opacity-50 cursor-not-allowed" : ""}
12762
12953
  `
@@ -13256,7 +13447,7 @@ function ImportParentFileModal({
13256
13447
  // src/components/AncestryLinkDetailsPanel.jsx
13257
13448
  var import_react26 = __toESM(require("react"));
13258
13449
  var import_fi21 = require("react-icons/fi");
13259
- function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile }) {
13450
+ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile, onHighlight }) {
13260
13451
  var _a, _b, _c, _d;
13261
13452
  const relationshipData = data.relationship || {};
13262
13453
  const description = relationshipData.description || "";
@@ -13265,6 +13456,11 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
13265
13456
  const sourceName = ((_b = (_a = data.sourceNode) == null ? void 0 : _a.userData) == null ? void 0 : _b.name) || "Origem";
13266
13457
  const targetName = ((_d = (_c = data.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) || "Destino";
13267
13458
  const [isReadMode, setIsReadMode] = (0, import_react26.useState)(false);
13459
+ import_react26.default.useEffect(() => {
13460
+ return () => {
13461
+ if (onHighlight) onHighlight(null);
13462
+ };
13463
+ }, [onHighlight]);
13268
13464
  const swallow = (e) => e.stopPropagation();
13269
13465
  const handleImageClickFromText = (url, name) => {
13270
13466
  if (onOpenImageViewer) {
@@ -13298,7 +13494,23 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
13298
13494
  onMentionClick,
13299
13495
  onImageClick: handleImageClickFromText
13300
13496
  }
13301
- ) : /* @__PURE__ */ import_react26.default.createElement(import_react26.default.Fragment, null, /* @__PURE__ */ import_react26.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-blue-500/0 via-blue-500/70 to-blue-500/0" }), /* @__PURE__ */ import_react26.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react26.default.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-blue-500/80 shadow-[0_0_18px_2px_rgba(59,130,246,0.55)]" }), /* @__PURE__ */ import_react26.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Ancestralidade")), /* @__PURE__ */ import_react26.default.createElement("h2", { className: "text-lg font-semibold tracking-tight flex items-center gap-2" }, /* @__PURE__ */ import_react26.default.createElement("span", { className: "truncate max-w-[150px]" }, sourceName), /* @__PURE__ */ import_react26.default.createElement("span", { className: "text-slate-500 text-sm" }, "\u2794"), /* @__PURE__ */ import_react26.default.createElement("span", { className: "truncate max-w-[150px]" }, targetName))), /* @__PURE__ */ import_react26.default.createElement("button", { onClick: onClose, className: "w-9 h-9 flex-shrink-0 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl", title: "Fechar" }, "\xD7")), /* @__PURE__ */ import_react26.default.createElement("div", { className: "px-6 pb-6 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, description && /* @__PURE__ */ import_react26.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react26.default.createElement("label", { className: "text-xs text-slate-300 font-medium" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react26.default.createElement(
13497
+ ) : /* @__PURE__ */ import_react26.default.createElement(import_react26.default.Fragment, null, /* @__PURE__ */ import_react26.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-blue-500/0 via-blue-500/70 to-blue-500/0" }), /* @__PURE__ */ import_react26.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react26.default.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-blue-500/80 shadow-[0_0_18px_2px_rgba(59,130,246,0.55)]" }), /* @__PURE__ */ import_react26.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Ancestralidade")), /* @__PURE__ */ import_react26.default.createElement("h2", { className: "text-lg font-semibold tracking-tight flex items-center gap-2" }, /* @__PURE__ */ import_react26.default.createElement(
13498
+ "span",
13499
+ {
13500
+ className: "truncate max-w-[150px] cursor-help hover:text-blue-400 transition-colors",
13501
+ onMouseEnter: () => onHighlight == null ? void 0 : onHighlight(data.source),
13502
+ onMouseLeave: () => onHighlight == null ? void 0 : onHighlight(null)
13503
+ },
13504
+ sourceName
13505
+ ), /* @__PURE__ */ import_react26.default.createElement("span", { className: "text-slate-500 text-sm" }, "\u2794"), /* @__PURE__ */ import_react26.default.createElement(
13506
+ "span",
13507
+ {
13508
+ className: "truncate max-w-[150px] cursor-help hover:text-blue-400 transition-colors",
13509
+ onMouseEnter: () => onHighlight == null ? void 0 : onHighlight(data.target),
13510
+ onMouseLeave: () => onHighlight == null ? void 0 : onHighlight(null)
13511
+ },
13512
+ targetName
13513
+ ))), /* @__PURE__ */ import_react26.default.createElement("button", { onClick: onClose, className: "w-9 h-9 flex-shrink-0 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl", title: "Fechar" }, "\xD7")), /* @__PURE__ */ import_react26.default.createElement("div", { className: "px-6 pb-6 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, description && /* @__PURE__ */ import_react26.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react26.default.createElement("label", { className: "text-xs text-slate-300 font-medium" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react26.default.createElement(
13302
13514
  "button",
13303
13515
  {
13304
13516
  onClick: () => setIsReadMode(true),
@@ -14527,7 +14739,8 @@ function XViewScene({
14527
14739
  upload_file_action,
14528
14740
  delete_file_action,
14529
14741
  check_user_permission,
14530
- get_view_members
14742
+ get_view_members,
14743
+ create_google_doc_action
14531
14744
  }) {
14532
14745
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
14533
14746
  const { data: session, status } = (0, import_react32.useSession)();
@@ -19247,7 +19460,8 @@ function XViewScene({
19247
19460
  sourceNodeDatasetId,
19248
19461
  viewType: viewParams == null ? void 0 : viewParams.type,
19249
19462
  availableNodes: allAvailableNodes,
19250
- availableAncestries: allAvailableAncestries
19463
+ availableAncestries: allAvailableAncestries,
19464
+ create_google_doc_action
19251
19465
  }
19252
19466
  ),
19253
19467
  versionMode.isActive && /* @__PURE__ */ import_react31.default.createElement(
@@ -19301,7 +19515,8 @@ function XViewScene({
19301
19515
  questCounter: ((_h = sceneDataRef.current) == null ? void 0 : _h.quest_counter) || 1,
19302
19516
  viewMembers,
19303
19517
  milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
19304
- onUpdateMilestones: handleUpdateMilestones
19518
+ onUpdateMilestones: handleUpdateMilestones,
19519
+ create_google_doc_action
19305
19520
  }
19306
19521
  ),
19307
19522
  readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react31.default.createElement(
@@ -19436,7 +19651,8 @@ function XViewScene({
19436
19651
  viewMembers,
19437
19652
  currentUser: session == null ? void 0 : session.user,
19438
19653
  milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
19439
- onUpdateMilestones: handleUpdateMilestones
19654
+ onUpdateMilestones: handleUpdateMilestones,
19655
+ create_google_doc_action
19440
19656
  }
19441
19657
  ),
19442
19658
  detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react31.default.createElement(
@@ -19468,7 +19684,8 @@ function XViewScene({
19468
19684
  onIntensityChange: handleDetailNodeIntensityChange,
19469
19685
  onUploadFile: upload_file_action,
19470
19686
  userRole: userPermissionRole,
19471
- currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
19687
+ currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
19688
+ create_google_doc_action
19472
19689
  }
19473
19690
  ),
19474
19691
  detailsLink && /* @__PURE__ */ import_react31.default.createElement(
@@ -19482,7 +19699,8 @@ function XViewScene({
19482
19699
  onOpenReference: handleOpenReference,
19483
19700
  onMentionClick: handleAddExistingNode,
19484
19701
  onUploadFile: upload_file_action,
19485
- userRole: userPermissionRole
19702
+ userRole: userPermissionRole,
19703
+ onHighlight: handleReadModeHighlight
19486
19704
  }
19487
19705
  ),
19488
19706
  ancestryLinkDetails && /* @__PURE__ */ import_react31.default.createElement(
@@ -19493,7 +19711,8 @@ function XViewScene({
19493
19711
  onOpenImageViewer: handleOpenImageViewer,
19494
19712
  onOpenReference: handleOpenReference,
19495
19713
  onMentionClick: handleAddExistingNode,
19496
- onUploadFile: upload_file_action
19714
+ onUploadFile: upload_file_action,
19715
+ onHighlight: handleReadModeHighlight
19497
19716
  }
19498
19717
  ),
19499
19718
  /* @__PURE__ */ import_react31.default.createElement(
package/dist/index.mjs CHANGED
@@ -8943,6 +8943,8 @@ import {
8943
8943
  FiSun,
8944
8944
  FiChevronDown as FiChevronDown4
8945
8945
  } from "react-icons/fi";
8946
+ import { SiGoogledocs } from "react-icons/si";
8947
+ import { AiOutlineLoading3Quarters } from "react-icons/ai";
8946
8948
  function InSceneCreationForm({
8947
8949
  onSave,
8948
8950
  onCancel,
@@ -8963,7 +8965,8 @@ function InSceneCreationForm({
8963
8965
  onUploadFile,
8964
8966
  availableDatasets = [],
8965
8967
  sourceNodeDatasetId,
8966
- viewType
8968
+ viewType,
8969
+ create_google_doc_action
8967
8970
  }) {
8968
8971
  var _a;
8969
8972
  const [name, setName] = useState14("");
@@ -8983,6 +8986,7 @@ function InSceneCreationForm({
8983
8986
  sourceNodeDatasetId || ""
8984
8987
  );
8985
8988
  const [isDatasetDropdownOpen, setIsDatasetDropdownOpen] = useState14(false);
8989
+ const [isLoadingDocs, setIsLoadingDocs] = useState14(false);
8986
8990
  const datasetDropdownRef = useRef10(null);
8987
8991
  useEffect13(() => {
8988
8992
  if (sourceNodeDatasetId) setTargetDatasetId(sourceNodeDatasetId);
@@ -9121,6 +9125,33 @@ function InSceneCreationForm({
9121
9125
  setSelectedImageUrl(url);
9122
9126
  onImageChange == null ? void 0 : onImageChange(true, url);
9123
9127
  };
9128
+ const handleCreateGoogleDoc = async () => {
9129
+ if (!name.trim()) {
9130
+ alert("Por favor, insira um nome para o node antes de criar o documento.");
9131
+ return;
9132
+ }
9133
+ if (!create_google_doc_action) return;
9134
+ try {
9135
+ setIsLoadingDocs(true);
9136
+ const res = await create_google_doc_action(name);
9137
+ if (res.success) {
9138
+ const newProp = {
9139
+ id: uuidv45(),
9140
+ key: "Google Docs",
9141
+ type: "links",
9142
+ value: [{ id: uuidv45(), name: "Abrir Documento", value: res.link }]
9143
+ };
9144
+ setCustomProps((prev) => [...prev, newProp]);
9145
+ } else {
9146
+ alert("Erro ao criar documento: " + res.error);
9147
+ }
9148
+ } catch (error) {
9149
+ console.error(error);
9150
+ alert("Erro ao processar cria\xE7\xE3o do documento.");
9151
+ } finally {
9152
+ setIsLoadingDocs(false);
9153
+ }
9154
+ };
9124
9155
  const handleSubmit = (e) => {
9125
9156
  e.preventDefault();
9126
9157
  if (!name.trim() || types.length === 0) {
@@ -9360,7 +9391,18 @@ function InSceneCreationForm({
9360
9391
  className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}`
9361
9392
  },
9362
9393
  useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Selecione a cor e ajuste o brilho."
9363
- )), /* @__PURE__ */ React13.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React13.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React13.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React13.createElement(
9394
+ )), /* @__PURE__ */ React13.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React13.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React13.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React13.createElement("div", { className: "flex items-center gap-2" }, create_google_doc_action && /* @__PURE__ */ React13.createElement(
9395
+ "button",
9396
+ {
9397
+ type: "button",
9398
+ onClick: handleCreateGoogleDoc,
9399
+ disabled: isLoadingDocs,
9400
+ className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-indigo-600/20 hover:bg-indigo-600/30 text-indigo-300 border border-indigo-500/30 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
9401
+ title: "Criar Documento no Google Docs"
9402
+ },
9403
+ isLoadingDocs ? /* @__PURE__ */ React13.createElement(AiOutlineLoading3Quarters, { className: "animate-spin", size: 14 }) : /* @__PURE__ */ React13.createElement(SiGoogledocs, { size: 14, className: "group-hover:scale-110 transition-transform" }),
9404
+ isLoadingDocs ? "Criando..." : "Google Doc"
9405
+ ), /* @__PURE__ */ React13.createElement(
9364
9406
  "button",
9365
9407
  {
9366
9408
  type: "button",
@@ -9369,7 +9411,7 @@ function InSceneCreationForm({
9369
9411
  },
9370
9412
  /* @__PURE__ */ React13.createElement(FiPlus3, { size: 14 }),
9371
9413
  " Adicionar"
9372
- )), /* @__PURE__ */ React13.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ React13.createElement(
9414
+ ))), /* @__PURE__ */ React13.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ React13.createElement(
9373
9415
  CustomPropertyDisplay,
9374
9416
  {
9375
9417
  key: prop.id,
@@ -9750,6 +9792,8 @@ import {
9750
9792
  FiRepeat,
9751
9793
  FiCopy as FiCopy3
9752
9794
  } from "react-icons/fi";
9795
+ import { SiGoogledocs as SiGoogledocs2 } from "react-icons/si";
9796
+ import { AiOutlineLoading3Quarters as AiOutlineLoading3Quarters2 } from "react-icons/ai";
9753
9797
 
9754
9798
  // src/components/QuestReviewStackEditor.jsx
9755
9799
  import React15, { useState as useState16 } from "react";
@@ -9939,7 +9983,8 @@ function InSceneQuestForm({
9939
9983
  session = null,
9940
9984
  milestones = [],
9941
9985
  onUpdateMilestones = () => {
9942
- }
9986
+ },
9987
+ create_google_doc_action
9943
9988
  }) {
9944
9989
  var _a, _b;
9945
9990
  const [name, setName] = useState17("");
@@ -9967,6 +10012,7 @@ function InSceneQuestForm({
9967
10012
  const [isAssigneeDropdownOpen, setIsAssigneeDropdownOpen] = useState17(false);
9968
10013
  const [assigneeSearchQuery, setAssigneeSearchQuery] = useState17("");
9969
10014
  const [isNameCopied, setIsNameCopied] = useState17(false);
10015
+ const [isLoadingDocs, setIsLoadingDocs] = useState17(false);
9970
10016
  const [customProps, setCustomProps] = useState17([]);
9971
10017
  const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState17(false);
9972
10018
  const propsEndRef = useRef12(null);
@@ -10054,6 +10100,33 @@ function InSceneQuestForm({
10054
10100
  console.error("Erro ao copiar nome:", err);
10055
10101
  });
10056
10102
  };
10103
+ const handleCreateGoogleDoc = async () => {
10104
+ if (!name.trim()) {
10105
+ alert("Por favor, insira um t\xEDtulo para a quest antes de criar o documento.");
10106
+ return;
10107
+ }
10108
+ if (!create_google_doc_action) return;
10109
+ try {
10110
+ setIsLoadingDocs(true);
10111
+ const res = await create_google_doc_action(standardizedName);
10112
+ if (res.success) {
10113
+ const newProp = {
10114
+ id: uuidv47(),
10115
+ key: "Google Docs",
10116
+ type: "links",
10117
+ value: [{ id: uuidv47(), name: "Abrir Documento", value: res.link }]
10118
+ };
10119
+ setCustomProps((prev) => [...prev, newProp]);
10120
+ } else {
10121
+ alert("Erro ao criar documento: " + res.error);
10122
+ }
10123
+ } catch (error) {
10124
+ console.error(error);
10125
+ alert("Erro ao processar cria\xE7\xE3o do documento.");
10126
+ } finally {
10127
+ setIsLoadingDocs(false);
10128
+ }
10129
+ };
10057
10130
  const handleAddProp = () => {
10058
10131
  const newProp = createNewCustomProperty(customProps);
10059
10132
  setCustomProps([...customProps, newProp]);
@@ -10572,7 +10645,18 @@ function InSceneQuestForm({
10572
10645
  className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
10573
10646
  },
10574
10647
  "Adicionar descri\xE7\xE3o..."
10575
- ))), /* @__PURE__ */ React16.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React16.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React16.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider" }, "Propriedades Adicionais"), /* @__PURE__ */ React16.createElement(
10648
+ ))), /* @__PURE__ */ React16.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React16.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React16.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider" }, "Propriedades Adicionais"), /* @__PURE__ */ React16.createElement("div", { className: "flex items-center gap-2" }, create_google_doc_action && /* @__PURE__ */ React16.createElement(
10649
+ "button",
10650
+ {
10651
+ type: "button",
10652
+ onClick: handleCreateGoogleDoc,
10653
+ disabled: isLoadingDocs,
10654
+ className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-indigo-600/20 hover:bg-indigo-600/30 text-indigo-300 border border-indigo-500/30 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
10655
+ title: "Criar Documento no Google Docs"
10656
+ },
10657
+ isLoadingDocs ? /* @__PURE__ */ React16.createElement(AiOutlineLoading3Quarters2, { className: "animate-spin", size: 14 }) : /* @__PURE__ */ React16.createElement(SiGoogledocs2, { size: 14, className: "group-hover:scale-110 transition-transform" }),
10658
+ isLoadingDocs ? "Criando..." : "Google Doc"
10659
+ ), /* @__PURE__ */ React16.createElement(
10576
10660
  "button",
10577
10661
  {
10578
10662
  type: "button",
@@ -10581,7 +10665,7 @@ function InSceneQuestForm({
10581
10665
  },
10582
10666
  /* @__PURE__ */ React16.createElement(FiPlus6, { size: 14 }),
10583
10667
  " Adicionar"
10584
- )), /* @__PURE__ */ React16.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ React16.createElement(
10668
+ ))), /* @__PURE__ */ React16.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ React16.createElement(
10585
10669
  CustomPropertyDisplay,
10586
10670
  {
10587
10671
  key: prop.id,
@@ -10683,6 +10767,8 @@ function InSceneQuestForm({
10683
10767
  import React17, { useState as useState18, useEffect as useEffect15, useRef as useRef13 } from "react";
10684
10768
  import { v4 as uuidv48 } from "uuid";
10685
10769
  import { FiPlus as FiPlus7, FiMaximize2 as FiMaximize23, FiX as FiX6, FiCheck as FiCheck10, FiImage as FiImage3, FiEdit2 as FiEdit27, FiLoader as FiLoader2, FiBookOpen as FiBookOpen3, FiSun as FiSun2, FiLink as FiLink5, FiDatabase } from "react-icons/fi";
10770
+ import { SiGoogledocs as SiGoogledocs3 } from "react-icons/si";
10771
+ import { AiOutlineLoading3Quarters as AiOutlineLoading3Quarters3 } from "react-icons/ai";
10686
10772
  function NodeDetailsPanel({
10687
10773
  node,
10688
10774
  onClose,
@@ -10701,7 +10787,8 @@ function NodeDetailsPanel({
10701
10787
  onIntensityChange,
10702
10788
  onUploadFile,
10703
10789
  userRole,
10704
- currentDatasetName
10790
+ currentDatasetName,
10791
+ create_google_doc_action
10705
10792
  }) {
10706
10793
  const [name, setName] = useState18((node == null ? void 0 : node.name) ?? "");
10707
10794
  const [types, setTypes] = useState18([]);
@@ -10717,6 +10804,7 @@ function NodeDetailsPanel({
10717
10804
  const [isReadMode, setIsReadMode] = useState18(false);
10718
10805
  const [existingSections, setExistingSections] = useState18((node == null ? void 0 : node.description_sections) || []);
10719
10806
  const [isSaving, setIsSaving] = useState18(false);
10807
+ const [isLoadingDocs, setIsLoadingDocs] = useState18(false);
10720
10808
  const [isLinkCopied, setIsLinkCopied] = useState18(false);
10721
10809
  const [useImageAsTexture, setUseImageAsTexture] = useState18(() => {
10722
10810
  if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
@@ -10871,6 +10959,36 @@ function NodeDetailsPanel({
10871
10959
  triggerAutoSave({ customProps: newProps });
10872
10960
  }
10873
10961
  };
10962
+ const handleCreateGoogleDoc = async () => {
10963
+ if (!name.trim()) {
10964
+ alert("Por favor, insira um nome para o node antes de criar o documento.");
10965
+ return;
10966
+ }
10967
+ if (!create_google_doc_action) return;
10968
+ try {
10969
+ setIsLoadingDocs(true);
10970
+ const res = await create_google_doc_action(name);
10971
+ if (res.success) {
10972
+ const newProp = {
10973
+ id: uuidv48(),
10974
+ key: "Google Docs",
10975
+ type: "links",
10976
+ value: [{ id: uuidv48(), name: "Abrir Documento", value: res.link }]
10977
+ };
10978
+ const updatedProps = [...customProps, newProp];
10979
+ setCustomProps(updatedProps);
10980
+ setHasUnsavedChanges(true);
10981
+ triggerAutoSave({ customProps: updatedProps });
10982
+ } else {
10983
+ alert("Erro ao criar documento: " + res.error);
10984
+ }
10985
+ } catch (error) {
10986
+ console.error(error);
10987
+ alert("Erro ao processar cria\xE7\xE3o do documento.");
10988
+ } finally {
10989
+ setIsLoadingDocs(false);
10990
+ }
10991
+ };
10874
10992
  const handleToggleImageMode = () => {
10875
10993
  setUseImageAsTexture(newValue);
10876
10994
  setHasUnsavedChanges(true);
@@ -11147,7 +11265,27 @@ function NodeDetailsPanel({
11147
11265
  className: `w-full h-1.5 bg-slate-700 rounded-lg appearance-none ${canEdit ? "cursor-pointer accent-indigo-500 hover:accent-indigo-400" : "cursor-default accent-slate-500"}`,
11148
11266
  title: `Intensidade do brilho: ${intensity}`
11149
11267
  }
11150
- ), /* @__PURE__ */ React17.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ React17.createElement("span", { className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}` }, useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Ajuste a cor e a intensidade do brilho.")), /* @__PURE__ */ React17.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React17.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ React17.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ React17.createElement(FiPlus7, { size: 14 }), " Adicionar")), /* @__PURE__ */ React17.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ React17.createElement(
11268
+ ), /* @__PURE__ */ React17.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ React17.createElement("span", { className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}` }, useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Ajuste a cor e a intensidade do brilho.")), /* @__PURE__ */ React17.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React17.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2" }, canEdit && create_google_doc_action && /* @__PURE__ */ React17.createElement(
11269
+ "button",
11270
+ {
11271
+ type: "button",
11272
+ onClick: handleCreateGoogleDoc,
11273
+ disabled: isLoadingDocs,
11274
+ className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-indigo-600/20 hover:bg-indigo-600/30 text-indigo-300 border border-indigo-500/30 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
11275
+ title: "Criar Documento no Google Docs"
11276
+ },
11277
+ isLoadingDocs ? /* @__PURE__ */ React17.createElement(AiOutlineLoading3Quarters3, { className: "animate-spin", size: 14 }) : /* @__PURE__ */ React17.createElement(SiGoogledocs3, { size: 14, className: "group-hover:scale-110 transition-transform" }),
11278
+ isLoadingDocs ? "Criando..." : "Google Doc"
11279
+ ), canEdit && /* @__PURE__ */ React17.createElement(
11280
+ "button",
11281
+ {
11282
+ type: "button",
11283
+ onClick: handleAddProp,
11284
+ className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors"
11285
+ },
11286
+ /* @__PURE__ */ React17.createElement(FiPlus7, { size: 14 }),
11287
+ " Adicionar"
11288
+ ))), /* @__PURE__ */ React17.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ React17.createElement(
11151
11289
  CustomPropertyDisplay,
11152
11290
  {
11153
11291
  key: prop.id,
@@ -11283,6 +11421,8 @@ function QuestTimeline({
11283
11421
  }
11284
11422
 
11285
11423
  // src/components/QuestDetailsPanel.jsx
11424
+ import { SiGoogledocs as SiGoogledocs4 } from "react-icons/si";
11425
+ import { AiOutlineLoading3Quarters as AiOutlineLoading3Quarters4 } from "react-icons/ai";
11286
11426
  var QUEST_STATUS_COLORS3 = {
11287
11427
  "Backlog": "#64748b",
11288
11428
  "In Progress": "#eab308",
@@ -11311,7 +11451,8 @@ function QuestDetailsPanel({
11311
11451
  milestones = [],
11312
11452
  onUpdateMilestones = () => {
11313
11453
  },
11314
- onFocusNode
11454
+ onFocusNode,
11455
+ create_google_doc_action
11315
11456
  }) {
11316
11457
  var _a, _b;
11317
11458
  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) || "";
@@ -11345,6 +11486,7 @@ function QuestDetailsPanel({
11345
11486
  const [isSaving, setIsSaving] = useState19(false);
11346
11487
  const [isLinkCopied, setIsLinkCopied] = useState19(false);
11347
11488
  const [isNameCopied, setIsNameCopied] = useState19(false);
11489
+ const [isLoadingDocs, setIsLoadingDocs] = useState19(false);
11348
11490
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState19(false);
11349
11491
  const [questDate, setQuestDate] = useState19((node == null ? void 0 : node.Date) || null);
11350
11492
  const [noteText, setNoteText] = useState19("");
@@ -11745,6 +11887,36 @@ ${noteText}` : noteText : entry.notes,
11745
11887
  triggerAutoSave({ customProps: newProps });
11746
11888
  }
11747
11889
  };
11890
+ const handleCreateGoogleDoc = async () => {
11891
+ if (!rawTitle.trim()) {
11892
+ alert("Por favor, insira um t\xEDtulo para a quest antes de criar o documento.");
11893
+ return;
11894
+ }
11895
+ if (!create_google_doc_action) return;
11896
+ try {
11897
+ setIsLoadingDocs(true);
11898
+ const res = await create_google_doc_action(standardizedName);
11899
+ if (res.success) {
11900
+ const newProp = {
11901
+ id: uuidv49(),
11902
+ key: "Google Docs",
11903
+ type: "links",
11904
+ value: [{ id: uuidv49(), name: "Abrir Documento", value: res.link }]
11905
+ };
11906
+ const updatedProps = [...customProps, newProp];
11907
+ setCustomProps(updatedProps);
11908
+ setHasUnsavedChanges(true);
11909
+ triggerAutoSave({ customProps: updatedProps });
11910
+ } else {
11911
+ alert("Erro ao criar documento: " + res.error);
11912
+ }
11913
+ } catch (error) {
11914
+ console.error(error);
11915
+ alert("Erro ao processar cria\xE7\xE3o do documento.");
11916
+ } finally {
11917
+ setIsLoadingDocs(false);
11918
+ }
11919
+ };
11748
11920
  const handleSaveDescriptionInline = (newDescription) => {
11749
11921
  setDescription(newDescription);
11750
11922
  setHasUnsavedChanges(true);
@@ -12350,7 +12522,18 @@ ${noteText}` : noteText : entry.notes,
12350
12522
  },
12351
12523
  /* @__PURE__ */ React19.createElement("span", { className: "truncate" }, q.raw_title || q.name),
12352
12524
  /* @__PURE__ */ React19.createElement("span", { className: `text-[10px] px-1.5 py-0.5 rounded border ${q.status === "Done" ? "text-green-400 border-green-500/30" : "text-slate-500 border-white/5"}` }, q.status || "Backlog")
12353
- )) : /* @__PURE__ */ React19.createElement("li", { className: "px-3 py-3 text-[10px] text-slate-500 italic text-center" }, "Nenhuma outra quest dispon\xEDvel")))), blockedStatus.isBlocked && /* @__PURE__ */ React19.createElement("div", { className: "flex items-center gap-2 px-3 py-2 bg-amber-500/5 rounded-lg border border-amber-500/10 animate-in fade-in slide-in-from-top-1" }, /* @__PURE__ */ React19.createElement(FiRepeat2, { className: "text-amber-400 animate-spin-slow", size: 12 }), /* @__PURE__ */ React19.createElement("p", { className: "text-[10px] text-amber-200/80 font-medium" }, "Esta quest est\xE1 bloqueada por ", blockedStatus.pendingDependencies.length, " tarefa(s) pendente(s)."))), /* @__PURE__ */ React19.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React19.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React19.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ React19.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ React19.createElement(FiPlus8, { size: 14 }), " Adicionar")), /* @__PURE__ */ React19.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ React19.createElement(CustomPropertyDisplay, { key: prop.id, prop, onUpdate: canEdit ? (updatedProp) => handleUpdateProp(idx, updatedProp) : void 0, onRemove: canEdit ? () => handleRemoveProp(idx) : void 0, onOpenImageViewer, unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type), isTextureMode: false, onUploadFile: canEdit ? onUploadFile : void 0, readOnly: !canEdit })), /* @__PURE__ */ React19.createElement("div", { ref: propsEndRef }))), /* @__PURE__ */ React19.createElement("div", { className: "pt-6 border-t border-white/10 mt-6" }, /* @__PURE__ */ React19.createElement("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ React19.createElement("h3", { className: "text-[11px] uppercase font-bold text-slate-500 tracking-wider" }, "Hist\xF3rico & Notas"), /* @__PURE__ */ React19.createElement(
12525
+ )) : /* @__PURE__ */ React19.createElement("li", { className: "px-3 py-3 text-[10px] text-slate-500 italic text-center" }, "Nenhuma outra quest dispon\xEDvel")))), blockedStatus.isBlocked && /* @__PURE__ */ React19.createElement("div", { className: "flex items-center gap-2 px-3 py-2 bg-amber-500/5 rounded-lg border border-amber-500/10 animate-in fade-in slide-in-from-top-1" }, /* @__PURE__ */ React19.createElement(FiRepeat2, { className: "text-amber-400 animate-spin-slow", size: 12 }), /* @__PURE__ */ React19.createElement("p", { className: "text-[10px] text-amber-200/80 font-medium" }, "Esta quest est\xE1 bloqueada por ", blockedStatus.pendingDependencies.length, " tarefa(s) pendente(s)."))), /* @__PURE__ */ React19.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React19.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React19.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React19.createElement("div", { className: "flex items-center gap-2" }, canEdit && create_google_doc_action && /* @__PURE__ */ React19.createElement(
12526
+ "button",
12527
+ {
12528
+ type: "button",
12529
+ onClick: handleCreateGoogleDoc,
12530
+ disabled: isLoadingDocs,
12531
+ className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-indigo-600/20 hover:bg-indigo-600/30 text-indigo-300 border border-indigo-500/30 transition-all disabled:opacity-50 disabled:cursor-not-allowed group",
12532
+ title: "Criar Documento no Google Docs"
12533
+ },
12534
+ isLoadingDocs ? /* @__PURE__ */ React19.createElement(AiOutlineLoading3Quarters4, { className: "animate-spin", size: 14 }) : /* @__PURE__ */ React19.createElement(SiGoogledocs4, { size: 14, className: "group-hover:scale-110 transition-transform" }),
12535
+ isLoadingDocs ? "Criando..." : "Google Doc"
12536
+ ), canEdit && /* @__PURE__ */ React19.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ React19.createElement(FiPlus8, { size: 14 }), " Adicionar"))), /* @__PURE__ */ React19.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ React19.createElement(CustomPropertyDisplay, { key: prop.id, prop, onUpdate: canEdit ? (updatedProp) => handleUpdateProp(idx, updatedProp) : void 0, onRemove: canEdit ? () => handleRemoveProp(idx) : void 0, onOpenImageViewer, unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type), isTextureMode: false, onUploadFile: canEdit ? onUploadFile : void 0, readOnly: !canEdit })), /* @__PURE__ */ React19.createElement("div", { ref: propsEndRef }))), /* @__PURE__ */ React19.createElement("div", { className: "pt-6 border-t border-white/10 mt-6" }, /* @__PURE__ */ React19.createElement("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ React19.createElement("h3", { className: "text-[11px] uppercase font-bold text-slate-500 tracking-wider" }, "Hist\xF3rico & Notas"), /* @__PURE__ */ React19.createElement(
12354
12537
  "button",
12355
12538
  {
12356
12539
  type: "button",
@@ -12565,7 +12748,8 @@ function RelationshipDetailsPanel({
12565
12748
  onOpenReference,
12566
12749
  onMentionClick,
12567
12750
  onUploadFile,
12568
- userRole
12751
+ userRole,
12752
+ onHighlight
12569
12753
  }) {
12570
12754
  const [name, setName] = useState21((link == null ? void 0 : link.name) ?? "");
12571
12755
  const [description, setDescription] = useState21((link == null ? void 0 : link.description) ?? "");
@@ -12595,6 +12779,11 @@ function RelationshipDetailsPanel({
12595
12779
  setTargetLabel((link == null ? void 0 : link.target_label) ?? "");
12596
12780
  setHasUnsavedChanges(false);
12597
12781
  }, [link]);
12782
+ useEffect18(() => {
12783
+ return () => {
12784
+ if (onHighlight) onHighlight(null);
12785
+ };
12786
+ }, [onHighlight]);
12598
12787
  const swallow = (e) => e.stopPropagation();
12599
12788
  const handleAddProp = () => {
12600
12789
  if (!canEdit) return;
@@ -12641,10 +12830,8 @@ function RelationshipDetailsPanel({
12641
12830
  isCurved: link.isCurved,
12642
12831
  curveOffset: link.curveOffset
12643
12832
  };
12644
- if (currentSourceLabel.trim())
12645
- dataToSave.source_label = currentSourceLabel.trim();
12646
- if (currentTargetLabel.trim())
12647
- dataToSave.target_label = currentTargetLabel.trim();
12833
+ dataToSave.source_label = currentSourceLabel.trim();
12834
+ dataToSave.target_label = currentTargetLabel.trim();
12648
12835
  await onSave(dataToSave, keepOpen);
12649
12836
  onDataUpdate(dataToSave);
12650
12837
  setHasUnsavedChanges(false);
@@ -12774,6 +12961,8 @@ function RelationshipDetailsPanel({
12774
12961
  },
12775
12962
  placeholder: "Ex: Conceitos",
12776
12963
  disabled: !canEdit,
12964
+ onFocus: () => onHighlight == null ? void 0 : onHighlight(link.source),
12965
+ onBlur: () => onHighlight == null ? void 0 : onHighlight(null),
12777
12966
  className: `w-full bg-slate-900/60 p-2 text-xs rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-violet-400/60 placeholder:text-slate-600
12778
12967
  ${!canEdit ? "opacity-50 cursor-not-allowed" : ""}
12779
12968
  `
@@ -12789,6 +12978,8 @@ function RelationshipDetailsPanel({
12789
12978
  },
12790
12979
  placeholder: "Ex: Refer\xEAncias",
12791
12980
  disabled: !canEdit,
12981
+ onFocus: () => onHighlight == null ? void 0 : onHighlight(link.target),
12982
+ onBlur: () => onHighlight == null ? void 0 : onHighlight(null),
12792
12983
  className: `w-full bg-slate-900/60 p-2 text-xs rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-violet-400/60 placeholder:text-slate-600
12793
12984
  ${!canEdit ? "opacity-50 cursor-not-allowed" : ""}
12794
12985
  `
@@ -13288,7 +13479,7 @@ function ImportParentFileModal({
13288
13479
  // src/components/AncestryLinkDetailsPanel.jsx
13289
13480
  import React25, { useState as useState24 } from "react";
13290
13481
  import { FiBookOpen as FiBookOpen6 } from "react-icons/fi";
13291
- function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile }) {
13482
+ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile, onHighlight }) {
13292
13483
  var _a, _b, _c, _d;
13293
13484
  const relationshipData = data.relationship || {};
13294
13485
  const description = relationshipData.description || "";
@@ -13297,6 +13488,11 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
13297
13488
  const sourceName = ((_b = (_a = data.sourceNode) == null ? void 0 : _a.userData) == null ? void 0 : _b.name) || "Origem";
13298
13489
  const targetName = ((_d = (_c = data.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) || "Destino";
13299
13490
  const [isReadMode, setIsReadMode] = useState24(false);
13491
+ React25.useEffect(() => {
13492
+ return () => {
13493
+ if (onHighlight) onHighlight(null);
13494
+ };
13495
+ }, [onHighlight]);
13300
13496
  const swallow = (e) => e.stopPropagation();
13301
13497
  const handleImageClickFromText = (url, name) => {
13302
13498
  if (onOpenImageViewer) {
@@ -13330,7 +13526,23 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
13330
13526
  onMentionClick,
13331
13527
  onImageClick: handleImageClickFromText
13332
13528
  }
13333
- ) : /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement("div", { className: "h-[2px] bg-gradient-to-r from-blue-500/0 via-blue-500/70 to-blue-500/0" }), /* @__PURE__ */ React25.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React25.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React25.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React25.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-blue-500/80 shadow-[0_0_18px_2px_rgba(59,130,246,0.55)]" }), /* @__PURE__ */ React25.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Ancestralidade")), /* @__PURE__ */ React25.createElement("h2", { className: "text-lg font-semibold tracking-tight flex items-center gap-2" }, /* @__PURE__ */ React25.createElement("span", { className: "truncate max-w-[150px]" }, sourceName), /* @__PURE__ */ React25.createElement("span", { className: "text-slate-500 text-sm" }, "\u2794"), /* @__PURE__ */ React25.createElement("span", { className: "truncate max-w-[150px]" }, targetName))), /* @__PURE__ */ React25.createElement("button", { onClick: onClose, className: "w-9 h-9 flex-shrink-0 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl", title: "Fechar" }, "\xD7")), /* @__PURE__ */ React25.createElement("div", { className: "px-6 pb-6 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, description && /* @__PURE__ */ React25.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React25.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React25.createElement("label", { className: "text-xs text-slate-300 font-medium" }, "Descri\xE7\xE3o"), /* @__PURE__ */ React25.createElement(
13529
+ ) : /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement("div", { className: "h-[2px] bg-gradient-to-r from-blue-500/0 via-blue-500/70 to-blue-500/0" }), /* @__PURE__ */ React25.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React25.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React25.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React25.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-blue-500/80 shadow-[0_0_18px_2px_rgba(59,130,246,0.55)]" }), /* @__PURE__ */ React25.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Ancestralidade")), /* @__PURE__ */ React25.createElement("h2", { className: "text-lg font-semibold tracking-tight flex items-center gap-2" }, /* @__PURE__ */ React25.createElement(
13530
+ "span",
13531
+ {
13532
+ className: "truncate max-w-[150px] cursor-help hover:text-blue-400 transition-colors",
13533
+ onMouseEnter: () => onHighlight == null ? void 0 : onHighlight(data.source),
13534
+ onMouseLeave: () => onHighlight == null ? void 0 : onHighlight(null)
13535
+ },
13536
+ sourceName
13537
+ ), /* @__PURE__ */ React25.createElement("span", { className: "text-slate-500 text-sm" }, "\u2794"), /* @__PURE__ */ React25.createElement(
13538
+ "span",
13539
+ {
13540
+ className: "truncate max-w-[150px] cursor-help hover:text-blue-400 transition-colors",
13541
+ onMouseEnter: () => onHighlight == null ? void 0 : onHighlight(data.target),
13542
+ onMouseLeave: () => onHighlight == null ? void 0 : onHighlight(null)
13543
+ },
13544
+ targetName
13545
+ ))), /* @__PURE__ */ React25.createElement("button", { onClick: onClose, className: "w-9 h-9 flex-shrink-0 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl", title: "Fechar" }, "\xD7")), /* @__PURE__ */ React25.createElement("div", { className: "px-6 pb-6 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, description && /* @__PURE__ */ React25.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React25.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React25.createElement("label", { className: "text-xs text-slate-300 font-medium" }, "Descri\xE7\xE3o"), /* @__PURE__ */ React25.createElement(
13334
13546
  "button",
13335
13547
  {
13336
13548
  onClick: () => setIsReadMode(true),
@@ -14584,7 +14796,8 @@ function XViewScene({
14584
14796
  upload_file_action,
14585
14797
  delete_file_action,
14586
14798
  check_user_permission,
14587
- get_view_members
14799
+ get_view_members,
14800
+ create_google_doc_action
14588
14801
  }) {
14589
14802
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
14590
14803
  const { data: session, status } = useSession();
@@ -19304,7 +19517,8 @@ function XViewScene({
19304
19517
  sourceNodeDatasetId,
19305
19518
  viewType: viewParams == null ? void 0 : viewParams.type,
19306
19519
  availableNodes: allAvailableNodes,
19307
- availableAncestries: allAvailableAncestries
19520
+ availableAncestries: allAvailableAncestries,
19521
+ create_google_doc_action
19308
19522
  }
19309
19523
  ),
19310
19524
  versionMode.isActive && /* @__PURE__ */ React30.createElement(
@@ -19358,7 +19572,8 @@ function XViewScene({
19358
19572
  questCounter: ((_h = sceneDataRef.current) == null ? void 0 : _h.quest_counter) || 1,
19359
19573
  viewMembers,
19360
19574
  milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
19361
- onUpdateMilestones: handleUpdateMilestones
19575
+ onUpdateMilestones: handleUpdateMilestones,
19576
+ create_google_doc_action
19362
19577
  }
19363
19578
  ),
19364
19579
  readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React30.createElement(
@@ -19493,7 +19708,8 @@ function XViewScene({
19493
19708
  viewMembers,
19494
19709
  currentUser: session == null ? void 0 : session.user,
19495
19710
  milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
19496
- onUpdateMilestones: handleUpdateMilestones
19711
+ onUpdateMilestones: handleUpdateMilestones,
19712
+ create_google_doc_action
19497
19713
  }
19498
19714
  ),
19499
19715
  detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React30.createElement(
@@ -19525,7 +19741,8 @@ function XViewScene({
19525
19741
  onIntensityChange: handleDetailNodeIntensityChange,
19526
19742
  onUploadFile: upload_file_action,
19527
19743
  userRole: userPermissionRole,
19528
- currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
19744
+ currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
19745
+ create_google_doc_action
19529
19746
  }
19530
19747
  ),
19531
19748
  detailsLink && /* @__PURE__ */ React30.createElement(
@@ -19539,7 +19756,8 @@ function XViewScene({
19539
19756
  onOpenReference: handleOpenReference,
19540
19757
  onMentionClick: handleAddExistingNode,
19541
19758
  onUploadFile: upload_file_action,
19542
- userRole: userPermissionRole
19759
+ userRole: userPermissionRole,
19760
+ onHighlight: handleReadModeHighlight
19543
19761
  }
19544
19762
  ),
19545
19763
  ancestryLinkDetails && /* @__PURE__ */ React30.createElement(
@@ -19550,7 +19768,8 @@ function XViewScene({
19550
19768
  onOpenImageViewer: handleOpenImageViewer,
19551
19769
  onOpenReference: handleOpenReference,
19552
19770
  onMentionClick: handleAddExistingNode,
19553
- onUploadFile: upload_file_action
19771
+ onUploadFile: upload_file_action,
19772
+ onHighlight: handleReadModeHighlight
19554
19773
  }
19555
19774
  ),
19556
19775
  /* @__PURE__ */ React30.createElement(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lv-x-software-house/x_view",
3
- "version": "1.2.6-dev.59",
3
+ "version": "1.2.6-dev.61",
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",