diff --git a/src/ShipFit/ShipFit.module.css b/src/ShipFit/ShipFit.module.css
index 7143fea..f36f399 100644
--- a/src/ShipFit/ShipFit.module.css
+++ b/src/ShipFit/ShipFit.module.css
@@ -60,11 +60,11 @@
.ringTopItem > div, .ringTopItem > svg {
--reverse-rotation: calc(-1 * var(--rotation));
+
left: 50%;
pointer-events: all;
position: absolute;
top: 3.5%;
- transform: rotate(var(--reverse-rotation));
}
.radialMenu {
@@ -74,18 +74,23 @@
width: 2.5%;
}
-.slot {
- height: 9.5%;
+.slotOuter {
+ height: 18%;
margin-left: -2.5%;
+ position: absolute;
+ width: 7%;
+}
+
+.slot {
+ height: 50%;
position: relative;
user-select: none;
- width: 7%;
+ width: 100%;
}
.slot > svg {
height: 100%;
position: absolute;
- transform: rotate(var(--rotation));
width: 100%;
z-index: 4;
}
@@ -93,14 +98,15 @@
.slotImage {
height: 100%;
position: absolute;
- margin-top: 8%;
- margin-left: -10%;
+ transform: rotate(var(--reverse-rotation));
width: 100%;
z-index: 5;
}
.slotImage > img {
border-top-left-radius: 50%;
+ margin-left: -10%;
+ margin-top: 5%;
width: 120%;
}
@@ -116,9 +122,31 @@
fill: #fd2d2d;
stroke: #fd2d2d;
}
-.slot[data-state="Offline"] {
+.slot[data-state="Offline"] > svg, .slot[data-state="Offline"] > .slotImage {
opacity: 0.3;
}
-.slot[data-state="Unavailable"] {
+.slot[data-state="Unavailable"] > svg, .slot[data-state="Unavailable"] > .slotImage {
opacity: 0.1;
}
+
+.slotOuter .slotOptions {
+ display: none;
+}
+.slotOuter[data-hasitem=true]:hover .slotOptions {
+ display: block;
+}
+
+.slotOptions {
+ position: absolute;
+ text-align: center;
+ top: 50%;
+ width: 100%;
+}
+.slotOptions > svg {
+ cursor: pointer;
+ display: block;
+ filter: drop-shadow(0px 2px 1px #222222);
+ margin: 6px auto;
+ transform: rotate(var(--reverse-rotation));
+ stroke: #ffffff;
+}
diff --git a/src/ShipFit/Slot.tsx b/src/ShipFit/Slot.tsx
index e904de5..e9d6580 100644
--- a/src/ShipFit/Slot.tsx
+++ b/src/ShipFit/Slot.tsx
@@ -43,45 +43,56 @@ export const Slot = (props: { type: string, index: number, fittable: boolean, ma
let svg = <>>;
if (props.main !== undefined) {
- svg = ;
+ svg = <>
+
+
+ >;
}
svg = <>
{svg}
>;
- /* Not fittable and nothing fitted; no need to render the slot. */
- if (esiItem === undefined && !props.fittable) {
- return
- {svg}
-
- }
+ const offlineState = React.useCallback((e: React.MouseEvent) => {
+ e.stopPropagation();
+ if (!shipSnapshot?.loaded || !esiItem) return;
- if (esiItem !== undefined) {
- item =
- }
+ if (esiItem.state === "Passive") {
+ shipSnapshot.setItemState(esiItem.flag, "Online");
+ } else {
+ shipSnapshot.setItemState(esiItem.flag, "Passive");
+ }
+ }, [shipSnapshot, esiItem]);
- const state = (esiItem?.state === "Passive" && esiItem?.max_state !== "Passive") ? "Offline" : esiItem?.state;
-
- function cycleState(e: React.MouseEvent) {
+ const cycleState = React.useCallback((e: React.MouseEvent) => {
if (!shipSnapshot?.loaded || !esiItem) return;
const states = stateRotation[esiItem.max_state];
@@ -95,12 +106,46 @@ export const Slot = (props: { type: string, index: number, fittable: boolean, ma
}
shipSnapshot.setItemState(esiItem.flag, newState);
+ }, [shipSnapshot, esiItem]);
+
+ const unfitModule = React.useCallback((e: React.MouseEvent) => {
+ e.stopPropagation();
+ if (!shipSnapshot?.loaded || !esiItem) return;
+
+ shipSnapshot.removeModule(esiItem.flag);
+ }, [shipSnapshot, esiItem]);
+
+ /* Not fittable and nothing fitted; no need to render the slot. */
+ if (esiItem === undefined && !props.fittable) {
+ return
}
- return
- {svg}
-
- {item}
+ if (esiItem !== undefined) {
+ item =
![{eveData?.typeIDs?.[esiItem.type_id].name}]({`https://images.evetech.net/types/${esiItem.type_id}/icon?size=64`})
+ }
+
+ const state = (esiItem?.state === "Passive" && esiItem?.max_state !== "Passive") ? "Offline" : esiItem?.state;
+
+ return
+
+
+
+ {esiItem?.max_state !== "Passive" &&
+
+ }
}
diff --git a/src/ShipSnapshotProvider/ShipSnapshotProvider.tsx b/src/ShipSnapshotProvider/ShipSnapshotProvider.tsx
index 137efec..ac22b88 100644
--- a/src/ShipSnapshotProvider/ShipSnapshotProvider.tsx
+++ b/src/ShipSnapshotProvider/ShipSnapshotProvider.tsx
@@ -58,6 +58,7 @@ interface ShipSnapshot {
fit?: EsiFit;
addModule: (typeId: number, slot: ShipSnapshotSlotsType | "dronebay") => void;
+ removeModule: (flag: number) => void;
changeHull: (typeId: number) => void;
changeFit: (fit: EsiFit) => void;
setItemState: (flag: number, state: string) => void;
@@ -73,6 +74,7 @@ export const ShipSnapshotContext = React.createContext
({
"rig": 0,
},
addModule: () => {},
+ removeModule: () => {},
changeHull: () => {},
changeFit: () => {},
setItemState: () => {},
@@ -110,6 +112,7 @@ export const ShipSnapshotProvider = (props: ShipSnapshotProps) => {
"rig": 0,
},
addModule: () => {},
+ removeModule: () => {},
changeHull: () => {},
changeFit: () => {},
setItemState: () => {},
@@ -172,6 +175,17 @@ export const ShipSnapshotProvider = (props: ShipSnapshotProps) => {
})
}, [shipSnapshot.slots]);
+ const removeModule = React.useCallback((flag: number) => {
+ setCurrentFit((oldFit: EsiFit | undefined) => {
+ if (oldFit === undefined) return undefined;
+
+ return {
+ ...oldFit,
+ items: oldFit.items.filter((item) => item.flag !== flag),
+ };
+ })
+ }, []);
+
const changeHull = React.useCallback((typeId: number) => {
setCurrentFit({
"name": "New Ship",
@@ -185,11 +199,12 @@ export const ShipSnapshotProvider = (props: ShipSnapshotProps) => {
setShipSnapshot((oldSnapshot) => ({
...oldSnapshot,
addModule,
+ removeModule,
changeHull,
changeFit: setCurrentFit,
setItemState,
}));
- }, [addModule, changeHull, setItemState]);
+ }, [addModule, removeModule, changeHull, setItemState]);
React.useEffect(() => {
if (!dogmaEngine.loaded) return;