@lv-x-software-house/x_view 1.2.6-dev.17 → 1.2.6-dev.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -13382,7 +13382,7 @@ var BoardItem = ({
13382
13382
  className: "p-1.5 text-slate-500 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13383
13383
  title: "Remover Pasta"
13384
13384
  },
13385
- /* @__PURE__ */ import_react29.default.createElement(FiTrash2, { size: 14 })
13385
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiTrash2, { size: 14 })
13386
13386
  )), /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiChevronRight, { className: "text-slate-500 group-hover/folder:translate-x-1 transition-transform" }))
13387
13387
  ));
13388
13388
  }
@@ -13446,7 +13446,7 @@ var BoardItem = ({
13446
13446
  className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13447
13447
  title: "Remover Grupo"
13448
13448
  },
13449
- /* @__PURE__ */ import_react29.default.createElement(FiTrash2, { size: 14 })
13449
+ /* @__PURE__ */ import_react29.default.createElement(import_fi23.FiTrash2, { size: 14 })
13450
13450
  )))), item.children && item.children.length > 0 && /* @__PURE__ */ import_react29.default.createElement("div", { className: "ml-2" }, item.children.map((child, idx) => /* @__PURE__ */ import_react29.default.createElement(
13451
13451
  BoardItem,
13452
13452
  {
@@ -13481,6 +13481,7 @@ function AncestryBoard({
13481
13481
  const [isLoaded, setIsLoaded] = (0, import_react29.useState)(false);
13482
13482
  const [saveStatus, setSaveStatus] = (0, import_react29.useState)("idle");
13483
13483
  const [navigationStack, setNavigationStack] = (0, import_react29.useState)([]);
13484
+ const lastSavedGroupsRef = (0, import_react29.useRef)(null);
13484
13485
  const canEdit = (0, import_react29.useMemo)(() => userRole !== "viewer", [userRole]);
13485
13486
  (0, import_react29.useEffect)(() => {
13486
13487
  if (initialGroups && !isLoaded) {
@@ -13531,9 +13532,13 @@ function AncestryBoard({
13531
13532
  (0, import_react29.useEffect)(() => {
13532
13533
  if (!isLoaded || !onSave) return;
13533
13534
  const id = setTimeout(async () => {
13535
+ const currentSanitized = sanitizeGroups(groups);
13536
+ const currentJson = JSON.stringify(currentSanitized);
13537
+ if (currentJson === lastSavedGroupsRef.current) return;
13534
13538
  setSaveStatus("saving");
13535
13539
  try {
13536
- await onSave(sanitizeGroups(groups));
13540
+ await onSave(currentSanitized);
13541
+ lastSavedGroupsRef.current = currentJson;
13537
13542
  setSaveStatus("saved");
13538
13543
  setTimeout(() => setSaveStatus("idle"), 3e3);
13539
13544
  } catch (err) {
@@ -13545,9 +13550,12 @@ function AncestryBoard({
13545
13550
  }, [groups, isLoaded, onSave]);
13546
13551
  const triggerInstantSave = async (updatedGroups) => {
13547
13552
  if (!onSave) return;
13553
+ const sanitized = sanitizeGroups(updatedGroups);
13554
+ const sanitizedJson = JSON.stringify(sanitized);
13555
+ lastSavedGroupsRef.current = sanitizedJson;
13548
13556
  setSaveStatus("saving");
13549
13557
  try {
13550
- await onSave(sanitizeGroups(updatedGroups));
13558
+ await onSave(sanitized);
13551
13559
  setSaveStatus("saved");
13552
13560
  setTimeout(() => setSaveStatus("idle"), 3e3);
13553
13561
  } catch (err) {
@@ -13652,63 +13660,55 @@ function AncestryBoard({
13652
13660
  return null;
13653
13661
  };
13654
13662
  const handleIndent = (id) => {
13655
- setGroups((prev) => {
13656
- const next = JSON.parse(JSON.stringify(prev));
13657
- const found = findGroupAndParent(next, id);
13658
- if (!found || found.index === 0) return prev;
13659
- const { group, siblings, index } = found;
13660
- const targetParent = siblings[index - 1];
13661
- if (group.type === "folder" && targetParent.type === "group") {
13662
- return prev;
13663
- }
13664
- siblings.splice(index, 1);
13665
- targetParent.children.push(group);
13666
- triggerInstantSave(next);
13667
- return next;
13668
- });
13663
+ const next = JSON.parse(JSON.stringify(groups));
13664
+ const found = findGroupAndParent(next, id);
13665
+ if (!found || found.index === 0) return;
13666
+ const { group, siblings, index } = found;
13667
+ const targetParent = siblings[index - 1];
13668
+ if (group.type === "folder" && targetParent.type === "group") {
13669
+ return;
13670
+ }
13671
+ siblings.splice(index, 1);
13672
+ targetParent.children.push(group);
13673
+ setGroups(next);
13674
+ triggerInstantSave(next);
13669
13675
  };
13670
13676
  const handleOutdent = (id) => {
13671
- setGroups((prev) => {
13672
- const next = JSON.parse(JSON.stringify(prev));
13673
- const found = findGroupAndParent(next, id);
13674
- if (!found || !found.parent) return prev;
13675
- const { group, siblings, index, parent } = found;
13676
- siblings.splice(index, 1);
13677
- const parentFound = findGroupAndParent(next, parent.id);
13678
- if (parentFound) {
13679
- parentFound.siblings.splice(parentFound.index + 1, 0, group);
13680
- } else {
13681
- next.push(group);
13682
- }
13683
- triggerInstantSave(next);
13684
- return next;
13685
- });
13677
+ const next = JSON.parse(JSON.stringify(groups));
13678
+ const found = findGroupAndParent(next, id);
13679
+ if (!found || !found.parent) return;
13680
+ const { group, siblings, index, parent } = found;
13681
+ siblings.splice(index, 1);
13682
+ const parentFound = findGroupAndParent(next, parent.id);
13683
+ if (parentFound) {
13684
+ parentFound.siblings.splice(parentFound.index + 1, 0, group);
13685
+ } else {
13686
+ next.push(group);
13687
+ }
13688
+ setGroups(next);
13689
+ triggerInstantSave(next);
13686
13690
  };
13687
13691
  const handleMoveUp = (id) => {
13688
- setGroups((prev) => {
13689
- const next = JSON.parse(JSON.stringify(prev));
13690
- const found = findGroupAndParent(next, id);
13691
- if (!found || found.index === 0) return prev;
13692
- const { siblings, index } = found;
13693
- const item = siblings[index];
13694
- siblings.splice(index, 1);
13695
- siblings.splice(index - 1, 0, item);
13696
- triggerInstantSave(next);
13697
- return next;
13698
- });
13692
+ const next = JSON.parse(JSON.stringify(groups));
13693
+ const found = findGroupAndParent(next, id);
13694
+ if (!found || found.index === 0) return;
13695
+ const { siblings, index } = found;
13696
+ const item = siblings[index];
13697
+ siblings.splice(index, 1);
13698
+ siblings.splice(index - 1, 0, item);
13699
+ setGroups(next);
13700
+ triggerInstantSave(next);
13699
13701
  };
13700
13702
  const handleMoveDown = (id) => {
13701
- setGroups((prev) => {
13702
- const next = JSON.parse(JSON.stringify(prev));
13703
- const found = findGroupAndParent(next, id);
13704
- if (!found || found.index === found.siblings.length - 1) return prev;
13705
- const { siblings, index } = found;
13706
- const item = siblings[index];
13707
- siblings.splice(index, 1);
13708
- siblings.splice(index + 1, 0, item);
13709
- triggerInstantSave(next);
13710
- return next;
13711
- });
13703
+ const next = JSON.parse(JSON.stringify(groups));
13704
+ const found = findGroupAndParent(next, id);
13705
+ if (!found || found.index === found.siblings.length - 1) return;
13706
+ const { siblings, index } = found;
13707
+ const item = siblings[index];
13708
+ siblings.splice(index, 1);
13709
+ siblings.splice(index + 1, 0, item);
13710
+ setGroups(next);
13711
+ triggerInstantSave(next);
13712
13712
  };
13713
13713
  const handleMentionClick = (item) => {
13714
13714
  if (onSelect) onSelect(item);
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import React30, {
3
3
  useCallback as useCallback5,
4
4
  useEffect as useEffect24,
5
- useRef as useRef20,
5
+ useRef as useRef21,
6
6
  useState as useState29,
7
7
  useMemo as useMemo13
8
8
  } from "react";
@@ -4387,7 +4387,7 @@ import { v4 as uuidv43 } from "uuid";
4387
4387
 
4388
4388
  // src/components/CustomPropertyDisplay.jsx
4389
4389
  import React3, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
4390
- import { FiCheck, FiX, FiEdit3, FiTrash2 as FiTrash22, FiExternalLink, FiFileText, FiChevronDown, FiUpload, FiLoader } from "react-icons/fi";
4390
+ import { FiCheck, FiX, FiEdit3, FiTrash2, FiExternalLink, FiFileText, FiChevronDown, FiUpload, FiLoader } from "react-icons/fi";
4391
4391
  function CustomPropertyDisplay({
4392
4392
  prop,
4393
4393
  onUpdate,
@@ -4744,7 +4744,7 @@ function CustomPropertyDisplay({
4744
4744
  onMouseLeave: () => setIsHovered(false)
4745
4745
  },
4746
4746
  isEditing ? renderEditView() : renderDisplayView(),
4747
- !isEditing && !readOnly && /* @__PURE__ */ React3.createElement("div", { className: `absolute top-2 right-2 flex items-center gap-1 transition-opacity ${isHovered ? "opacity-100" : "opacity-0"}` }, /* @__PURE__ */ React3.createElement("button", { onClick: () => setIsEditing(true), className: "w-7 h-7 grid place-items-center rounded-lg bg-slate-700/80 hover:bg-slate-600/80 text-slate-200 transition-colors", title: "Editar" }, /* @__PURE__ */ React3.createElement(FiEdit3, { size: 14 })), /* @__PURE__ */ React3.createElement("button", { onClick: onRemove, className: "w-7 h-7 grid place-items-center rounded-lg bg-red-700/80 hover:bg-red-600/80 text-slate-200 transition-colors", title: "Remover" }, /* @__PURE__ */ React3.createElement(FiTrash22, { size: 14 })))
4747
+ !isEditing && !readOnly && /* @__PURE__ */ React3.createElement("div", { className: `absolute top-2 right-2 flex items-center gap-1 transition-opacity ${isHovered ? "opacity-100" : "opacity-0"}` }, /* @__PURE__ */ React3.createElement("button", { onClick: () => setIsEditing(true), className: "w-7 h-7 grid place-items-center rounded-lg bg-slate-700/80 hover:bg-slate-600/80 text-slate-200 transition-colors", title: "Editar" }, /* @__PURE__ */ React3.createElement(FiEdit3, { size: 14 })), /* @__PURE__ */ React3.createElement("button", { onClick: onRemove, className: "w-7 h-7 grid place-items-center rounded-lg bg-red-700/80 hover:bg-red-600/80 text-slate-200 transition-colors", title: "Remover" }, /* @__PURE__ */ React3.createElement(FiTrash2, { size: 14 })))
4748
4748
  );
4749
4749
  }
4750
4750
 
@@ -6644,7 +6644,7 @@ import {
6644
6644
  FiPlus as FiPlus2,
6645
6645
  FiLock as FiLock2,
6646
6646
  FiLink as FiLink4,
6647
- FiTrash2 as FiTrash23
6647
+ FiTrash2 as FiTrash22
6648
6648
  } from "react-icons/fi";
6649
6649
  import { v4 as uuidv44 } from "uuid";
6650
6650
 
@@ -8083,7 +8083,7 @@ function CreateAncestryPanel({
8083
8083
  className: "flex items-center gap-1.5 text-xs text-rose-400/80 hover:text-white hover:bg-rose-500/20 px-2 py-1 rounded transition-colors",
8084
8084
  title: "Excluir permanentemente esta ramifica\xE7\xE3o e seu conte\xFAdo"
8085
8085
  },
8086
- /* @__PURE__ */ React10.createElement(FiTrash23, null),
8086
+ /* @__PURE__ */ React10.createElement(FiTrash22, null),
8087
8087
  " Excluir Ramifica\xE7\xE3o"
8088
8088
  ))), /* @__PURE__ */ React10.createElement("div", { className: "px-6 pb-4 pt-2 overflow-y-auto flex-grow custom-scrollbar" }, branchStack.length > 0 && /* @__PURE__ */ React10.createElement("div", { className: "mb-4" }, isContextLinked ? /* @__PURE__ */ React10.createElement("div", { className: "p-3 rounded-lg bg-indigo-500/10 border border-indigo-500/30 flex items-center justify-between" }, /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React10.createElement("div", { className: "w-8 h-8 rounded bg-indigo-500/20 text-indigo-300 grid place-content-center" }, /* @__PURE__ */ React10.createElement(FiLayers5, null)), /* @__PURE__ */ React10.createElement("div", null, /* @__PURE__ */ React10.createElement("div", { className: "text-xs text-indigo-200 font-semibold uppercase tracking-wider" }, "Ancestralidade Vinculada"), /* @__PURE__ */ React10.createElement("div", { className: "text-sm text-white font-medium truncate max-w-[200px]" }, currentContext.name.replace("[REF] ", "")))), /* @__PURE__ */ React10.createElement(
8089
8089
  "button",
@@ -12950,13 +12950,14 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
12950
12950
  }
12951
12951
 
12952
12952
  // src/components/AncestryBoard.jsx
12953
- import React28, { useState as useState27, useMemo as useMemo12, useEffect as useEffect23 } from "react";
12953
+ import React28, { useState as useState27, useMemo as useMemo12, useEffect as useEffect23, useRef as useRef20 } from "react";
12954
12954
  import {
12955
12955
  FiSearch as FiSearch8,
12956
12956
  FiLayers as FiLayers7,
12957
12957
  FiCornerUpRight as FiCornerUpRight4,
12958
12958
  FiPlay,
12959
12959
  FiPlus as FiPlus10,
12960
+ FiTrash2 as FiTrash23,
12960
12961
  FiArrowLeft as FiArrowLeft3,
12961
12962
  FiArrowRight as FiArrowRight2,
12962
12963
  FiArrowUp,
@@ -13431,7 +13432,7 @@ var BoardItem = ({
13431
13432
  className: "p-1.5 text-slate-500 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13432
13433
  title: "Remover Pasta"
13433
13434
  },
13434
- /* @__PURE__ */ React28.createElement(FiTrash2, { size: 14 })
13435
+ /* @__PURE__ */ React28.createElement(FiTrash23, { size: 14 })
13435
13436
  )), /* @__PURE__ */ React28.createElement(FiChevronRight7, { className: "text-slate-500 group-hover/folder:translate-x-1 transition-transform" }))
13436
13437
  ));
13437
13438
  }
@@ -13495,7 +13496,7 @@ var BoardItem = ({
13495
13496
  className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
13496
13497
  title: "Remover Grupo"
13497
13498
  },
13498
- /* @__PURE__ */ React28.createElement(FiTrash2, { size: 14 })
13499
+ /* @__PURE__ */ React28.createElement(FiTrash23, { size: 14 })
13499
13500
  )))), item.children && item.children.length > 0 && /* @__PURE__ */ React28.createElement("div", { className: "ml-2" }, item.children.map((child, idx) => /* @__PURE__ */ React28.createElement(
13500
13501
  BoardItem,
13501
13502
  {
@@ -13530,6 +13531,7 @@ function AncestryBoard({
13530
13531
  const [isLoaded, setIsLoaded] = useState27(false);
13531
13532
  const [saveStatus, setSaveStatus] = useState27("idle");
13532
13533
  const [navigationStack, setNavigationStack] = useState27([]);
13534
+ const lastSavedGroupsRef = useRef20(null);
13533
13535
  const canEdit = useMemo12(() => userRole !== "viewer", [userRole]);
13534
13536
  useEffect23(() => {
13535
13537
  if (initialGroups && !isLoaded) {
@@ -13580,9 +13582,13 @@ function AncestryBoard({
13580
13582
  useEffect23(() => {
13581
13583
  if (!isLoaded || !onSave) return;
13582
13584
  const id = setTimeout(async () => {
13585
+ const currentSanitized = sanitizeGroups(groups);
13586
+ const currentJson = JSON.stringify(currentSanitized);
13587
+ if (currentJson === lastSavedGroupsRef.current) return;
13583
13588
  setSaveStatus("saving");
13584
13589
  try {
13585
- await onSave(sanitizeGroups(groups));
13590
+ await onSave(currentSanitized);
13591
+ lastSavedGroupsRef.current = currentJson;
13586
13592
  setSaveStatus("saved");
13587
13593
  setTimeout(() => setSaveStatus("idle"), 3e3);
13588
13594
  } catch (err) {
@@ -13594,9 +13600,12 @@ function AncestryBoard({
13594
13600
  }, [groups, isLoaded, onSave]);
13595
13601
  const triggerInstantSave = async (updatedGroups) => {
13596
13602
  if (!onSave) return;
13603
+ const sanitized = sanitizeGroups(updatedGroups);
13604
+ const sanitizedJson = JSON.stringify(sanitized);
13605
+ lastSavedGroupsRef.current = sanitizedJson;
13597
13606
  setSaveStatus("saving");
13598
13607
  try {
13599
- await onSave(sanitizeGroups(updatedGroups));
13608
+ await onSave(sanitized);
13600
13609
  setSaveStatus("saved");
13601
13610
  setTimeout(() => setSaveStatus("idle"), 3e3);
13602
13611
  } catch (err) {
@@ -13701,63 +13710,55 @@ function AncestryBoard({
13701
13710
  return null;
13702
13711
  };
13703
13712
  const handleIndent = (id) => {
13704
- setGroups((prev) => {
13705
- const next = JSON.parse(JSON.stringify(prev));
13706
- const found = findGroupAndParent(next, id);
13707
- if (!found || found.index === 0) return prev;
13708
- const { group, siblings, index } = found;
13709
- const targetParent = siblings[index - 1];
13710
- if (group.type === "folder" && targetParent.type === "group") {
13711
- return prev;
13712
- }
13713
- siblings.splice(index, 1);
13714
- targetParent.children.push(group);
13715
- triggerInstantSave(next);
13716
- return next;
13717
- });
13713
+ const next = JSON.parse(JSON.stringify(groups));
13714
+ const found = findGroupAndParent(next, id);
13715
+ if (!found || found.index === 0) return;
13716
+ const { group, siblings, index } = found;
13717
+ const targetParent = siblings[index - 1];
13718
+ if (group.type === "folder" && targetParent.type === "group") {
13719
+ return;
13720
+ }
13721
+ siblings.splice(index, 1);
13722
+ targetParent.children.push(group);
13723
+ setGroups(next);
13724
+ triggerInstantSave(next);
13718
13725
  };
13719
13726
  const handleOutdent = (id) => {
13720
- setGroups((prev) => {
13721
- const next = JSON.parse(JSON.stringify(prev));
13722
- const found = findGroupAndParent(next, id);
13723
- if (!found || !found.parent) return prev;
13724
- const { group, siblings, index, parent } = found;
13725
- siblings.splice(index, 1);
13726
- const parentFound = findGroupAndParent(next, parent.id);
13727
- if (parentFound) {
13728
- parentFound.siblings.splice(parentFound.index + 1, 0, group);
13729
- } else {
13730
- next.push(group);
13731
- }
13732
- triggerInstantSave(next);
13733
- return next;
13734
- });
13727
+ const next = JSON.parse(JSON.stringify(groups));
13728
+ const found = findGroupAndParent(next, id);
13729
+ if (!found || !found.parent) return;
13730
+ const { group, siblings, index, parent } = found;
13731
+ siblings.splice(index, 1);
13732
+ const parentFound = findGroupAndParent(next, parent.id);
13733
+ if (parentFound) {
13734
+ parentFound.siblings.splice(parentFound.index + 1, 0, group);
13735
+ } else {
13736
+ next.push(group);
13737
+ }
13738
+ setGroups(next);
13739
+ triggerInstantSave(next);
13735
13740
  };
13736
13741
  const handleMoveUp = (id) => {
13737
- setGroups((prev) => {
13738
- const next = JSON.parse(JSON.stringify(prev));
13739
- const found = findGroupAndParent(next, id);
13740
- if (!found || found.index === 0) return prev;
13741
- const { siblings, index } = found;
13742
- const item = siblings[index];
13743
- siblings.splice(index, 1);
13744
- siblings.splice(index - 1, 0, item);
13745
- triggerInstantSave(next);
13746
- return next;
13747
- });
13742
+ const next = JSON.parse(JSON.stringify(groups));
13743
+ const found = findGroupAndParent(next, id);
13744
+ if (!found || found.index === 0) return;
13745
+ const { siblings, index } = found;
13746
+ const item = siblings[index];
13747
+ siblings.splice(index, 1);
13748
+ siblings.splice(index - 1, 0, item);
13749
+ setGroups(next);
13750
+ triggerInstantSave(next);
13748
13751
  };
13749
13752
  const handleMoveDown = (id) => {
13750
- setGroups((prev) => {
13751
- const next = JSON.parse(JSON.stringify(prev));
13752
- const found = findGroupAndParent(next, id);
13753
- if (!found || found.index === found.siblings.length - 1) return prev;
13754
- const { siblings, index } = found;
13755
- const item = siblings[index];
13756
- siblings.splice(index, 1);
13757
- siblings.splice(index + 1, 0, item);
13758
- triggerInstantSave(next);
13759
- return next;
13760
- });
13753
+ const next = JSON.parse(JSON.stringify(groups));
13754
+ const found = findGroupAndParent(next, id);
13755
+ if (!found || found.index === found.siblings.length - 1) return;
13756
+ const { siblings, index } = found;
13757
+ const item = siblings[index];
13758
+ siblings.splice(index, 1);
13759
+ siblings.splice(index + 1, 0, item);
13760
+ setGroups(next);
13761
+ triggerInstantSave(next);
13761
13762
  };
13762
13763
  const handleMentionClick = (item) => {
13763
13764
  if (onSelect) onSelect(item);
@@ -14109,9 +14110,9 @@ function XViewScene({
14109
14110
  }
14110
14111
  return null;
14111
14112
  }, [ownerId, sceneConfigId]);
14112
- const sceneDataRef = useRef20(null);
14113
- const parentDataRef = useRef20(null);
14114
- const ancestryDataRef = useRef20(null);
14113
+ const sceneDataRef = useRef21(null);
14114
+ const parentDataRef = useRef21(null);
14115
+ const ancestryDataRef = useRef21(null);
14115
14116
  const [isLoading, setIsLoading] = useState29(true);
14116
14117
  const [permissionStatus, setPermissionStatus] = useState29("loading");
14117
14118
  const [userPermissionRole, setUserPermissionRole] = useState29(null);
@@ -14190,10 +14191,10 @@ function XViewScene({
14190
14191
  const [ancestryBoardData, setAncestryBoardData] = useState29([]);
14191
14192
  const [isSidebarOpen, setIsSidebarOpen] = useState29(false);
14192
14193
  const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState29(false);
14193
- const mountRef = useRef20(null);
14194
- const tooltipRef = useRef20(null);
14195
- const formRef = useRef20(null);
14196
- const stateRef = useRef20({
14194
+ const mountRef = useRef21(null);
14195
+ const tooltipRef = useRef21(null);
14196
+ const formRef = useRef21(null);
14197
+ const stateRef = useRef21({
14197
14198
  readMode: {
14198
14199
  currentMaxIndex: 0,
14199
14200
  progressMap: {}
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.17",
3
+ "version": "1.2.6-dev.19",
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",