@lv-x-software-house/x_view 1.2.4-dev.14 → 1.2.4-dev.16
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 +66 -40
- package/dist/index.mjs +67 -41
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -948,7 +948,7 @@ var createNodeMesh = (nodeData, position, glowTexture) => {
|
|
|
948
948
|
if (useImage && nodeData.textureImageUrl) {
|
|
949
949
|
geometry = new THREE.CircleGeometry(1.5, 48);
|
|
950
950
|
const texture = getTexture(nodeData.textureImageUrl);
|
|
951
|
-
material = new MeshBasicMaterial({
|
|
951
|
+
material = new THREE.MeshBasicMaterial({
|
|
952
952
|
map: texture,
|
|
953
953
|
color: 16777215,
|
|
954
954
|
side: THREE.DoubleSide,
|
|
@@ -1225,8 +1225,6 @@ var createMultipleLinkLines = (linksArray, sourceNodeMesh, targetNodeMesh, resol
|
|
|
1225
1225
|
targetNodeMesh,
|
|
1226
1226
|
resolution,
|
|
1227
1227
|
isCurved,
|
|
1228
|
-
isCurved,
|
|
1229
|
-
isCurved,
|
|
1230
1228
|
curveOffset
|
|
1231
1229
|
);
|
|
1232
1230
|
line.userData = {
|
|
@@ -2141,14 +2139,28 @@ var userActionHandlers = {
|
|
|
2141
2139
|
} else {
|
|
2142
2140
|
newTargetId = newEndNodeData.id;
|
|
2143
2141
|
}
|
|
2144
|
-
const
|
|
2145
|
-
const
|
|
2146
|
-
|
|
2147
|
-
|
|
2142
|
+
const oldSourceInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldSourceId, context.sceneConfigId, context.ownerId);
|
|
2143
|
+
const oldTargetInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldTargetId, context.sceneConfigId, context.ownerId);
|
|
2144
|
+
const newSourceInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newSourceId, context.sceneConfigId, context.ownerId);
|
|
2145
|
+
const newTargetInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newTargetId, context.sceneConfigId, context.ownerId);
|
|
2146
|
+
if (!oldSourceInfo || !oldTargetInfo || !newSourceInfo || !newTargetInfo) {
|
|
2147
|
+
console.error("Informa\xE7\xF5es dos arquivos pai incompletas para o relink.");
|
|
2148
2148
|
alert("Ocorreu um erro ao identificar os arquivos pai para salvar a altera\xE7\xE3o.");
|
|
2149
2149
|
userActionHandlers.handleCancelRelink(context);
|
|
2150
2150
|
return;
|
|
2151
2151
|
}
|
|
2152
|
+
let oldGoverningFileId = oldSourceInfo.parentFileId;
|
|
2153
|
+
let oldGoverningOwnerId = oldSourceInfo.ownerId;
|
|
2154
|
+
if (oldSourceInfo.parentFileId === context.sceneConfigId || oldTargetInfo.parentFileId === context.sceneConfigId) {
|
|
2155
|
+
oldGoverningFileId = context.sceneConfigId;
|
|
2156
|
+
oldGoverningOwnerId = context.ownerId;
|
|
2157
|
+
}
|
|
2158
|
+
let newGoverningFileId = newSourceInfo.parentFileId;
|
|
2159
|
+
let newGoverningOwnerId = newSourceInfo.ownerId;
|
|
2160
|
+
if (newSourceInfo.parentFileId === context.sceneConfigId || newTargetInfo.parentFileId === context.sceneConfigId) {
|
|
2161
|
+
newGoverningFileId = context.sceneConfigId;
|
|
2162
|
+
newGoverningOwnerId = context.ownerId;
|
|
2163
|
+
}
|
|
2152
2164
|
const { sourceNode, targetNode, ...dataToKeep } = originalLinkData;
|
|
2153
2165
|
const newLinkData = {
|
|
2154
2166
|
...dataToKeep,
|
|
@@ -2174,26 +2186,26 @@ var userActionHandlers = {
|
|
|
2174
2186
|
};
|
|
2175
2187
|
const savePromises = [];
|
|
2176
2188
|
const filesToUpdate = {};
|
|
2177
|
-
if (
|
|
2178
|
-
const updatedOriginalParentData = JSON.parse(JSON.stringify(graphDataRef.current[
|
|
2189
|
+
if (oldGoverningFileId !== newGoverningFileId) {
|
|
2190
|
+
const updatedOriginalParentData = JSON.parse(JSON.stringify(graphDataRef.current[oldGoverningFileId]));
|
|
2179
2191
|
updatedOriginalParentData.links = updatedOriginalParentData.links.filter(
|
|
2180
2192
|
(l) => String(l.id) !== String(linkId)
|
|
2181
2193
|
);
|
|
2182
|
-
filesToUpdate[
|
|
2183
|
-
savePromises.push(saveParentData(
|
|
2184
|
-
const updatedNewParentData = JSON.parse(JSON.stringify(graphDataRef.current[
|
|
2194
|
+
filesToUpdate[oldGoverningFileId] = updatedOriginalParentData;
|
|
2195
|
+
savePromises.push(saveParentData(oldGoverningFileId, oldGoverningOwnerId, updatedOriginalParentData));
|
|
2196
|
+
const updatedNewParentData = JSON.parse(JSON.stringify(graphDataRef.current[newGoverningFileId]));
|
|
2185
2197
|
if (!updatedNewParentData.links) updatedNewParentData.links = [];
|
|
2186
2198
|
updatedNewParentData.links.push(newLinkData);
|
|
2187
|
-
filesToUpdate[
|
|
2188
|
-
savePromises.push(saveParentData(
|
|
2199
|
+
filesToUpdate[newGoverningFileId] = updatedNewParentData;
|
|
2200
|
+
savePromises.push(saveParentData(newGoverningFileId, newGoverningOwnerId, updatedNewParentData));
|
|
2189
2201
|
} else {
|
|
2190
|
-
const updatedParentData = JSON.parse(JSON.stringify(graphDataRef.current[
|
|
2202
|
+
const updatedParentData = JSON.parse(JSON.stringify(graphDataRef.current[oldGoverningFileId]));
|
|
2191
2203
|
updatedParentData.links = updatedParentData.links.filter(
|
|
2192
2204
|
(l) => String(l.id) !== String(linkId)
|
|
2193
2205
|
);
|
|
2194
2206
|
updatedParentData.links.push(newLinkData);
|
|
2195
|
-
filesToUpdate[
|
|
2196
|
-
savePromises.push(saveParentData(
|
|
2207
|
+
filesToUpdate[oldGoverningFileId] = updatedParentData;
|
|
2208
|
+
savePromises.push(saveParentData(oldGoverningFileId, oldGoverningOwnerId, updatedParentData));
|
|
2197
2209
|
}
|
|
2198
2210
|
try {
|
|
2199
2211
|
await Promise.all(savePromises);
|
|
@@ -7975,13 +7987,9 @@ var import_react16 = __toESM(require("react"));
|
|
|
7975
7987
|
var import_fi14 = require("react-icons/fi");
|
|
7976
7988
|
var QUEST_STATUS_COLORS = {
|
|
7977
7989
|
"Backlog": "#64748b",
|
|
7978
|
-
// Slate (Cinza azulado)
|
|
7979
7990
|
"In Progress": "#eab308",
|
|
7980
|
-
// Yellow (Amarelo)
|
|
7981
7991
|
"Review": "#a855f7",
|
|
7982
|
-
// Purple (Roxo)
|
|
7983
7992
|
"Done": "#22c55e"
|
|
7984
|
-
// Green (Verde)
|
|
7985
7993
|
};
|
|
7986
7994
|
function InSceneQuestForm({
|
|
7987
7995
|
onSave,
|
|
@@ -8001,6 +8009,7 @@ function InSceneQuestForm({
|
|
|
8001
8009
|
const [size, setSize] = (0, import_react16.useState)("medium");
|
|
8002
8010
|
const [intensity, setIntensity] = (0, import_react16.useState)(0);
|
|
8003
8011
|
const [description, setDescription] = (0, import_react16.useState)("");
|
|
8012
|
+
const [isStatusDropdownOpen, setIsStatusDropdownOpen] = (0, import_react16.useState)(false);
|
|
8004
8013
|
const [customProps, setCustomProps] = (0, import_react16.useState)([]);
|
|
8005
8014
|
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react16.useState)(false);
|
|
8006
8015
|
const propsEndRef = (0, import_react16.useRef)(null);
|
|
@@ -8051,7 +8060,6 @@ function InSceneQuestForm({
|
|
|
8051
8060
|
name: name.trim(),
|
|
8052
8061
|
type: types,
|
|
8053
8062
|
color: QUEST_STATUS_COLORS[status],
|
|
8054
|
-
// Cor atrelada ao status
|
|
8055
8063
|
status,
|
|
8056
8064
|
size,
|
|
8057
8065
|
intensity,
|
|
@@ -8078,20 +8086,38 @@ function InSceneQuestForm({
|
|
|
8078
8086
|
onDoubleClick: swallow
|
|
8079
8087
|
},
|
|
8080
8088
|
/* @__PURE__ */ import_react16.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS[status]}, transparent)` } }),
|
|
8081
|
-
/* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pt-5 pb-3" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Nova
|
|
8082
|
-
|
|
8083
|
-
|
|
8084
|
-
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
+
/* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react16.default.createElement("div", null, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Nova quest")), /* @__PURE__ */ import_react16.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, "Criar Quest")), /* @__PURE__ */ import_react16.default.createElement(
|
|
8090
|
+
"button",
|
|
8091
|
+
{
|
|
8092
|
+
type: "button",
|
|
8093
|
+
onClick: onCancel,
|
|
8094
|
+
className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl",
|
|
8095
|
+
title: "Fechar"
|
|
8096
|
+
},
|
|
8097
|
+
"\xD7"
|
|
8098
|
+
)),
|
|
8099
|
+
/* @__PURE__ */ import_react16.default.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col max-h-[68vh]" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react16.default.createElement(
|
|
8100
|
+
"button",
|
|
8101
|
+
{
|
|
8102
|
+
type: "button",
|
|
8103
|
+
onClick: () => setIsStatusDropdownOpen(!isStatusDropdownOpen),
|
|
8104
|
+
className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 hover:border-white/20 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 transition-colors flex items-center justify-between"
|
|
8105
|
+
},
|
|
8106
|
+
/* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor: QUEST_STATUS_COLORS[status] } }), /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-slate-200 font-medium" }, status)),
|
|
8107
|
+
/* @__PURE__ */ import_react16.default.createElement(import_fi14.FiChevronDown, { className: `text-slate-400 transition-transform duration-200 ${isStatusDropdownOpen ? "rotate-180" : ""}` })
|
|
8108
|
+
), isStatusDropdownOpen && /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ import_react16.default.createElement("ul", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-800 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden" }, Object.keys(QUEST_STATUS_COLORS).map((s) => /* @__PURE__ */ import_react16.default.createElement(
|
|
8109
|
+
"li",
|
|
8110
|
+
{
|
|
8111
|
+
key: s,
|
|
8112
|
+
onClick: () => {
|
|
8113
|
+
setStatus(s);
|
|
8114
|
+
setIsStatusDropdownOpen(false);
|
|
8115
|
+
},
|
|
8116
|
+
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${status === s ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
8089
8117
|
},
|
|
8090
|
-
/* @__PURE__ */ import_react16.default.createElement("
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
/* @__PURE__ */ import_react16.default.createElement("option", { value: "Done" }, "Done")
|
|
8094
|
-
)), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ import_react16.default.createElement("input", { required: true, type: "text", placeholder: "Ex.: Refatorar M\xF3dulo X", value: name, onChange: (e) => setName(e.target.value), className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60" })), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ import_react16.default.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiX, { size: 12 })))), /* @__PURE__ */ import_react16.default.createElement(
|
|
8118
|
+
/* @__PURE__ */ import_react16.default.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS[s] } }),
|
|
8119
|
+
s
|
|
8120
|
+
)))))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ import_react16.default.createElement("input", { required: true, type: "text", placeholder: "Ex.: Refatorar M\xF3dulo X", value: name, onChange: (e) => setName(e.target.value), className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60" })), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ import_react16.default.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiX, { size: 12 })))), /* @__PURE__ */ import_react16.default.createElement(
|
|
8095
8121
|
"input",
|
|
8096
8122
|
{
|
|
8097
8123
|
type: "text",
|
|
@@ -8114,7 +8140,7 @@ function InSceneQuestForm({
|
|
|
8114
8140
|
onMentionClick,
|
|
8115
8141
|
onSaveDescription: (newDesc) => setDescription(newDesc)
|
|
8116
8142
|
}
|
|
8117
|
-
), /* @__PURE__ */ import_react16.default.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: () => setIsDescriptionModalOpen(true), className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiEdit2, { size: 14 }))), !description && /* @__PURE__ */ import_react16.default.createElement("div", { onClick: () => setIsDescriptionModalOpen(true), className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text" }, "Adicionar descri\xE7\xE3o..."))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tamanho no
|
|
8143
|
+
), /* @__PURE__ */ import_react16.default.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: () => setIsDescriptionModalOpen(true), className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiEdit2, { size: 14 }))), !description && /* @__PURE__ */ import_react16.default.createElement("div", { onClick: () => setIsDescriptionModalOpen(true), className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text" }, "Adicionar descri\xE7\xE3o..."))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tamanho no Node (Size)"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => /* @__PURE__ */ import_react16.default.createElement("button", { key: s, type: "button", onClick: () => setSize(s), className: "flex items-center gap-2 group cursor-pointer focus:outline-none" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${size === s ? "bg-indigo-500 border-indigo-500" : "border-slate-600 bg-transparent group-hover:border-slate-500"}` }, size === s && /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiCheck, { size: 12, className: "text-white" })), /* @__PURE__ */ import_react16.default.createElement("span", { className: `text-sm capitalize transition-colors ${size === s ? "text-white font-medium" : "text-slate-400 group-hover:text-slate-300"}` }, s))))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react16.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react16.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_react16.default.createElement(import_fi14.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ import_react16.default.createElement(
|
|
8118
8144
|
CustomPropertyDisplay,
|
|
8119
8145
|
{
|
|
8120
8146
|
key: prop.id,
|
|
@@ -11661,10 +11687,10 @@ function XViewScene({
|
|
|
11661
11687
|
const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, sourceNodeData.id, sceneConfigId2, ownerId2);
|
|
11662
11688
|
const targetParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, targetNodeData.id, sceneConfigId2, ownerId2);
|
|
11663
11689
|
let parentInfoToSave = sourceParentInfo;
|
|
11664
|
-
|
|
11665
|
-
|
|
11666
|
-
|
|
11667
|
-
parentInfoToSave =
|
|
11690
|
+
const isSourceQuest = sourceParentInfo.parentFileId === sceneConfigId2;
|
|
11691
|
+
const isTargetQuest = targetParentInfo.parentFileId === sceneConfigId2;
|
|
11692
|
+
if (isSourceQuest || isTargetQuest) {
|
|
11693
|
+
parentInfoToSave = { parentFileId: sceneConfigId2, ownerId: ownerId2 };
|
|
11668
11694
|
}
|
|
11669
11695
|
const { parentFileId: parentFileIdToSave, ownerId: ownerIdToSave } = parentInfoToSave;
|
|
11670
11696
|
const newLink = {
|
package/dist/index.mjs
CHANGED
|
@@ -904,7 +904,7 @@ var createNodeMesh = (nodeData, position, glowTexture) => {
|
|
|
904
904
|
if (useImage && nodeData.textureImageUrl) {
|
|
905
905
|
geometry = new THREE.CircleGeometry(1.5, 48);
|
|
906
906
|
const texture = getTexture(nodeData.textureImageUrl);
|
|
907
|
-
material = new MeshBasicMaterial({
|
|
907
|
+
material = new THREE.MeshBasicMaterial({
|
|
908
908
|
map: texture,
|
|
909
909
|
color: 16777215,
|
|
910
910
|
side: THREE.DoubleSide,
|
|
@@ -1181,8 +1181,6 @@ var createMultipleLinkLines = (linksArray, sourceNodeMesh, targetNodeMesh, resol
|
|
|
1181
1181
|
targetNodeMesh,
|
|
1182
1182
|
resolution,
|
|
1183
1183
|
isCurved,
|
|
1184
|
-
isCurved,
|
|
1185
|
-
isCurved,
|
|
1186
1184
|
curveOffset
|
|
1187
1185
|
);
|
|
1188
1186
|
line.userData = {
|
|
@@ -2097,14 +2095,28 @@ var userActionHandlers = {
|
|
|
2097
2095
|
} else {
|
|
2098
2096
|
newTargetId = newEndNodeData.id;
|
|
2099
2097
|
}
|
|
2100
|
-
const
|
|
2101
|
-
const
|
|
2102
|
-
|
|
2103
|
-
|
|
2098
|
+
const oldSourceInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldSourceId, context.sceneConfigId, context.ownerId);
|
|
2099
|
+
const oldTargetInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldTargetId, context.sceneConfigId, context.ownerId);
|
|
2100
|
+
const newSourceInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newSourceId, context.sceneConfigId, context.ownerId);
|
|
2101
|
+
const newTargetInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newTargetId, context.sceneConfigId, context.ownerId);
|
|
2102
|
+
if (!oldSourceInfo || !oldTargetInfo || !newSourceInfo || !newTargetInfo) {
|
|
2103
|
+
console.error("Informa\xE7\xF5es dos arquivos pai incompletas para o relink.");
|
|
2104
2104
|
alert("Ocorreu um erro ao identificar os arquivos pai para salvar a altera\xE7\xE3o.");
|
|
2105
2105
|
userActionHandlers.handleCancelRelink(context);
|
|
2106
2106
|
return;
|
|
2107
2107
|
}
|
|
2108
|
+
let oldGoverningFileId = oldSourceInfo.parentFileId;
|
|
2109
|
+
let oldGoverningOwnerId = oldSourceInfo.ownerId;
|
|
2110
|
+
if (oldSourceInfo.parentFileId === context.sceneConfigId || oldTargetInfo.parentFileId === context.sceneConfigId) {
|
|
2111
|
+
oldGoverningFileId = context.sceneConfigId;
|
|
2112
|
+
oldGoverningOwnerId = context.ownerId;
|
|
2113
|
+
}
|
|
2114
|
+
let newGoverningFileId = newSourceInfo.parentFileId;
|
|
2115
|
+
let newGoverningOwnerId = newSourceInfo.ownerId;
|
|
2116
|
+
if (newSourceInfo.parentFileId === context.sceneConfigId || newTargetInfo.parentFileId === context.sceneConfigId) {
|
|
2117
|
+
newGoverningFileId = context.sceneConfigId;
|
|
2118
|
+
newGoverningOwnerId = context.ownerId;
|
|
2119
|
+
}
|
|
2108
2120
|
const { sourceNode, targetNode, ...dataToKeep } = originalLinkData;
|
|
2109
2121
|
const newLinkData = {
|
|
2110
2122
|
...dataToKeep,
|
|
@@ -2130,26 +2142,26 @@ var userActionHandlers = {
|
|
|
2130
2142
|
};
|
|
2131
2143
|
const savePromises = [];
|
|
2132
2144
|
const filesToUpdate = {};
|
|
2133
|
-
if (
|
|
2134
|
-
const updatedOriginalParentData = JSON.parse(JSON.stringify(graphDataRef.current[
|
|
2145
|
+
if (oldGoverningFileId !== newGoverningFileId) {
|
|
2146
|
+
const updatedOriginalParentData = JSON.parse(JSON.stringify(graphDataRef.current[oldGoverningFileId]));
|
|
2135
2147
|
updatedOriginalParentData.links = updatedOriginalParentData.links.filter(
|
|
2136
2148
|
(l) => String(l.id) !== String(linkId)
|
|
2137
2149
|
);
|
|
2138
|
-
filesToUpdate[
|
|
2139
|
-
savePromises.push(saveParentData(
|
|
2140
|
-
const updatedNewParentData = JSON.parse(JSON.stringify(graphDataRef.current[
|
|
2150
|
+
filesToUpdate[oldGoverningFileId] = updatedOriginalParentData;
|
|
2151
|
+
savePromises.push(saveParentData(oldGoverningFileId, oldGoverningOwnerId, updatedOriginalParentData));
|
|
2152
|
+
const updatedNewParentData = JSON.parse(JSON.stringify(graphDataRef.current[newGoverningFileId]));
|
|
2141
2153
|
if (!updatedNewParentData.links) updatedNewParentData.links = [];
|
|
2142
2154
|
updatedNewParentData.links.push(newLinkData);
|
|
2143
|
-
filesToUpdate[
|
|
2144
|
-
savePromises.push(saveParentData(
|
|
2155
|
+
filesToUpdate[newGoverningFileId] = updatedNewParentData;
|
|
2156
|
+
savePromises.push(saveParentData(newGoverningFileId, newGoverningOwnerId, updatedNewParentData));
|
|
2145
2157
|
} else {
|
|
2146
|
-
const updatedParentData = JSON.parse(JSON.stringify(graphDataRef.current[
|
|
2158
|
+
const updatedParentData = JSON.parse(JSON.stringify(graphDataRef.current[oldGoverningFileId]));
|
|
2147
2159
|
updatedParentData.links = updatedParentData.links.filter(
|
|
2148
2160
|
(l) => String(l.id) !== String(linkId)
|
|
2149
2161
|
);
|
|
2150
2162
|
updatedParentData.links.push(newLinkData);
|
|
2151
|
-
filesToUpdate[
|
|
2152
|
-
savePromises.push(saveParentData(
|
|
2163
|
+
filesToUpdate[oldGoverningFileId] = updatedParentData;
|
|
2164
|
+
savePromises.push(saveParentData(oldGoverningFileId, oldGoverningOwnerId, updatedParentData));
|
|
2153
2165
|
}
|
|
2154
2166
|
try {
|
|
2155
2167
|
await Promise.all(savePromises);
|
|
@@ -7959,16 +7971,12 @@ function InSceneVersionForm({
|
|
|
7959
7971
|
|
|
7960
7972
|
// src/components/InSceneQuestForm.jsx
|
|
7961
7973
|
import React15, { useState as useState16, useRef as useRef12 } from "react";
|
|
7962
|
-
import { FiPlus as FiPlus5, FiCheck as FiCheck9, FiEdit2 as FiEdit26, FiTarget, FiX as FiX4 } from "react-icons/fi";
|
|
7974
|
+
import { FiPlus as FiPlus5, FiCheck as FiCheck9, FiEdit2 as FiEdit26, FiTarget, FiX as FiX4, FiChevronDown as FiChevronDown5 } from "react-icons/fi";
|
|
7963
7975
|
var QUEST_STATUS_COLORS = {
|
|
7964
7976
|
"Backlog": "#64748b",
|
|
7965
|
-
// Slate (Cinza azulado)
|
|
7966
7977
|
"In Progress": "#eab308",
|
|
7967
|
-
// Yellow (Amarelo)
|
|
7968
7978
|
"Review": "#a855f7",
|
|
7969
|
-
// Purple (Roxo)
|
|
7970
7979
|
"Done": "#22c55e"
|
|
7971
|
-
// Green (Verde)
|
|
7972
7980
|
};
|
|
7973
7981
|
function InSceneQuestForm({
|
|
7974
7982
|
onSave,
|
|
@@ -7988,6 +7996,7 @@ function InSceneQuestForm({
|
|
|
7988
7996
|
const [size, setSize] = useState16("medium");
|
|
7989
7997
|
const [intensity, setIntensity] = useState16(0);
|
|
7990
7998
|
const [description, setDescription] = useState16("");
|
|
7999
|
+
const [isStatusDropdownOpen, setIsStatusDropdownOpen] = useState16(false);
|
|
7991
8000
|
const [customProps, setCustomProps] = useState16([]);
|
|
7992
8001
|
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState16(false);
|
|
7993
8002
|
const propsEndRef = useRef12(null);
|
|
@@ -8038,7 +8047,6 @@ function InSceneQuestForm({
|
|
|
8038
8047
|
name: name.trim(),
|
|
8039
8048
|
type: types,
|
|
8040
8049
|
color: QUEST_STATUS_COLORS[status],
|
|
8041
|
-
// Cor atrelada ao status
|
|
8042
8050
|
status,
|
|
8043
8051
|
size,
|
|
8044
8052
|
intensity,
|
|
@@ -8065,20 +8073,38 @@ function InSceneQuestForm({
|
|
|
8065
8073
|
onDoubleClick: swallow
|
|
8066
8074
|
},
|
|
8067
8075
|
/* @__PURE__ */ React15.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS[status]}, transparent)` } }),
|
|
8068
|
-
/* @__PURE__ */ React15.createElement("div", { className: "px-6 pt-5 pb-3" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React15.createElement(FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React15.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Nova
|
|
8069
|
-
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
+
/* @__PURE__ */ React15.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React15.createElement(FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React15.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Nova quest")), /* @__PURE__ */ React15.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, "Criar Quest")), /* @__PURE__ */ React15.createElement(
|
|
8077
|
+
"button",
|
|
8078
|
+
{
|
|
8079
|
+
type: "button",
|
|
8080
|
+
onClick: onCancel,
|
|
8081
|
+
className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl",
|
|
8082
|
+
title: "Fechar"
|
|
8083
|
+
},
|
|
8084
|
+
"\xD7"
|
|
8085
|
+
)),
|
|
8086
|
+
/* @__PURE__ */ React15.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col max-h-[68vh]" }, /* @__PURE__ */ React15.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ React15.createElement("div", { className: "relative" }, /* @__PURE__ */ React15.createElement(
|
|
8087
|
+
"button",
|
|
8088
|
+
{
|
|
8089
|
+
type: "button",
|
|
8090
|
+
onClick: () => setIsStatusDropdownOpen(!isStatusDropdownOpen),
|
|
8091
|
+
className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 hover:border-white/20 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 transition-colors flex items-center justify-between"
|
|
8092
|
+
},
|
|
8093
|
+
/* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor: QUEST_STATUS_COLORS[status] } }), /* @__PURE__ */ React15.createElement("span", { className: "text-slate-200 font-medium" }, status)),
|
|
8094
|
+
/* @__PURE__ */ React15.createElement(FiChevronDown5, { className: `text-slate-400 transition-transform duration-200 ${isStatusDropdownOpen ? "rotate-180" : ""}` })
|
|
8095
|
+
), isStatusDropdownOpen && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ React15.createElement("ul", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-800 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden" }, Object.keys(QUEST_STATUS_COLORS).map((s) => /* @__PURE__ */ React15.createElement(
|
|
8096
|
+
"li",
|
|
8097
|
+
{
|
|
8098
|
+
key: s,
|
|
8099
|
+
onClick: () => {
|
|
8100
|
+
setStatus(s);
|
|
8101
|
+
setIsStatusDropdownOpen(false);
|
|
8102
|
+
},
|
|
8103
|
+
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${status === s ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
8076
8104
|
},
|
|
8077
|
-
/* @__PURE__ */ React15.createElement("
|
|
8078
|
-
|
|
8079
|
-
|
|
8080
|
-
/* @__PURE__ */ React15.createElement("option", { value: "Done" }, "Done")
|
|
8081
|
-
)), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ React15.createElement("input", { required: true, type: "text", placeholder: "Ex.: Refatorar M\xF3dulo X", value: name, onChange: (e) => setName(e.target.value), className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60" })), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ React15.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ React15.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ React15.createElement(FiX4, { size: 12 })))), /* @__PURE__ */ React15.createElement(
|
|
8105
|
+
/* @__PURE__ */ React15.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS[s] } }),
|
|
8106
|
+
s
|
|
8107
|
+
)))))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ React15.createElement("input", { required: true, type: "text", placeholder: "Ex.: Refatorar M\xF3dulo X", value: name, onChange: (e) => setName(e.target.value), className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60" })), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ React15.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ React15.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ React15.createElement(FiX4, { size: 12 })))), /* @__PURE__ */ React15.createElement(
|
|
8082
8108
|
"input",
|
|
8083
8109
|
{
|
|
8084
8110
|
type: "text",
|
|
@@ -8101,7 +8127,7 @@ function InSceneQuestForm({
|
|
|
8101
8127
|
onMentionClick,
|
|
8102
8128
|
onSaveDescription: (newDesc) => setDescription(newDesc)
|
|
8103
8129
|
}
|
|
8104
|
-
), /* @__PURE__ */ React15.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: () => setIsDescriptionModalOpen(true), className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors" }, /* @__PURE__ */ React15.createElement(FiEdit26, { size: 14 }))), !description && /* @__PURE__ */ React15.createElement("div", { onClick: () => setIsDescriptionModalOpen(true), className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text" }, "Adicionar descri\xE7\xE3o..."))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tamanho no
|
|
8130
|
+
), /* @__PURE__ */ React15.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: () => setIsDescriptionModalOpen(true), className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors" }, /* @__PURE__ */ React15.createElement(FiEdit26, { size: 14 }))), !description && /* @__PURE__ */ React15.createElement("div", { onClick: () => setIsDescriptionModalOpen(true), className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text" }, "Adicionar descri\xE7\xE3o..."))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tamanho no Node (Size)"), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => /* @__PURE__ */ React15.createElement("button", { key: s, type: "button", onClick: () => setSize(s), className: "flex items-center gap-2 group cursor-pointer focus:outline-none" }, /* @__PURE__ */ React15.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${size === s ? "bg-indigo-500 border-indigo-500" : "border-slate-600 bg-transparent group-hover:border-slate-500"}` }, size === s && /* @__PURE__ */ React15.createElement(FiCheck9, { size: 12, className: "text-white" })), /* @__PURE__ */ React15.createElement("span", { className: `text-sm capitalize transition-colors ${size === s ? "text-white font-medium" : "text-slate-400 group-hover:text-slate-300"}` }, s))))), /* @__PURE__ */ React15.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React15.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React15.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__ */ React15.createElement(FiPlus5, { size: 14 }), " Adicionar")), /* @__PURE__ */ React15.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ React15.createElement(
|
|
8105
8131
|
CustomPropertyDisplay,
|
|
8106
8132
|
{
|
|
8107
8133
|
key: prop.id,
|
|
@@ -11661,10 +11687,10 @@ function XViewScene({
|
|
|
11661
11687
|
const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, sourceNodeData.id, sceneConfigId2, ownerId2);
|
|
11662
11688
|
const targetParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, targetNodeData.id, sceneConfigId2, ownerId2);
|
|
11663
11689
|
let parentInfoToSave = sourceParentInfo;
|
|
11664
|
-
|
|
11665
|
-
|
|
11666
|
-
|
|
11667
|
-
parentInfoToSave =
|
|
11690
|
+
const isSourceQuest = sourceParentInfo.parentFileId === sceneConfigId2;
|
|
11691
|
+
const isTargetQuest = targetParentInfo.parentFileId === sceneConfigId2;
|
|
11692
|
+
if (isSourceQuest || isTargetQuest) {
|
|
11693
|
+
parentInfoToSave = { parentFileId: sceneConfigId2, ownerId: ownerId2 };
|
|
11668
11694
|
}
|
|
11669
11695
|
const { parentFileId: parentFileIdToSave, ownerId: ownerIdToSave } = parentInfoToSave;
|
|
11670
11696
|
const newLink = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lv-x-software-house/x_view",
|
|
3
|
-
"version": "1.2.4-dev.
|
|
3
|
+
"version": "1.2.4-dev.16",
|
|
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",
|