add function map viewer
Some checks failed
Test / test (push) Has been cancelled

This commit is contained in:
2026-06-20 10:53:49 +07:00
parent a6cf06d7eb
commit 819323f8c8
22 changed files with 3332 additions and 67 deletions

View File

@@ -3245,11 +3245,11 @@ body.auth-readonly-integrations .integrationToolbar .btn.primary { pointer-event
.mapsMirBtn svg { flex-shrink: 0; }
.mapsMirBtn--green {
background: var(--mir-green);
background: var(--mir-green, #5cb85c);
color: #fff;
}
.mapsMirBtn--green:hover { background: var(--mir-green-hover); }
.mapsMirBtn--green:hover { background: var(--mir-green-hover, #4cae4c); }
.mapsMirBtn--outline {
background: #fff;
@@ -3461,6 +3461,8 @@ body.auth-readonly-integrations .integrationToolbar .btn.primary { pointer-event
}
.mapsMirDialog {
--mir-green: #5cb85c;
--mir-green-hover: #4cae4c;
border: none;
border-radius: 6px;
padding: 0;
@@ -3472,7 +3474,8 @@ body.auth-readonly-integrations .integrationToolbar .btn.primary { pointer-event
.mapsMirDialog::backdrop { background: rgba(0, 0, 0, 0.35); }
.mapsMirDialog form,
.mapsMirDialog--menu { padding: 20px 22px; }
.mapsMirDialog--menu,
.mapsMirDialogPanel { padding: 20px 22px; }
.mapsMirDialog--mapMenu {
max-width: 720px;
@@ -3681,6 +3684,8 @@ body.auth-readonly-maps-page .mapsMirMapMenuCancelBtn {
/* Map editor — MiR §4.2.3 Mapping tools */
.mapEditorPage {
--mir-green: #5cb85c;
--mir-green-hover: #4cae4c;
display: flex;
flex-direction: column;
height: 100%;
@@ -3856,6 +3861,8 @@ body.auth-readonly-maps-page .mapsMirMapMenuCancelBtn {
min-height: 0;
overflow: hidden;
background: #b8b8b8;
display: flex;
flex-direction: column;
}
.mapEditorCanvasWrap.is-panning {
@@ -3887,8 +3894,9 @@ body.auth-readonly-maps-page .mapsMirMapMenuCancelBtn {
}
.mapEditorViewport {
position: absolute;
inset: 0;
position: relative;
flex: 1;
min-height: 0;
overflow: hidden;
}
@@ -3897,6 +3905,14 @@ body.auth-readonly-maps-page .mapsMirMapMenuCancelBtn {
top: 0;
left: 0;
transform-origin: 0 0;
will-change: transform;
}
/* Layer 2 — image / floor plan space (1 CSS px = 1 image px). */
.mapEditorImageLayer {
position: relative;
transform-origin: 0 0;
user-select: none;
}
.mapEditorSheet {
@@ -3905,14 +3921,150 @@ body.auth-readonly-maps-page .mapsMirMapMenuCancelBtn {
min-height: 360px;
background: #fff;
box-shadow: 0 2px 16px rgba(0, 0, 0, 0.12);
user-select: none;
}
.mapEditorSheet--blank {
background: #fafafa;
}
.mapEditorSheet--hasImage {
background: #fff;
min-width: 0;
min-height: 0;
}
.mapEditorSheetGrid {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 0;
opacity: 0.45;
background-image:
linear-gradient(to right, rgba(0, 0, 0, 0.08) 1px, transparent 1px),
linear-gradient(to bottom, rgba(0, 0, 0, 0.08) 1px, transparent 1px),
linear-gradient(to right, rgba(0, 0, 0, 0.18) 1px, transparent 1px),
linear-gradient(to bottom, rgba(0, 0, 0, 0.18) 1px, transparent 1px);
background-size:
var(--map-grid-minor, 20px) var(--map-grid-minor, 20px),
var(--map-grid-minor, 20px) var(--map-grid-minor, 20px),
var(--map-grid-major, 100px) var(--map-grid-major, 100px),
var(--map-grid-major, 100px) var(--map-grid-major, 100px);
}
.mapEditorOrigin {
position: absolute;
left: 0;
top: 0;
width: 0;
height: 0;
pointer-events: none;
z-index: 3;
}
.mapEditorOriginAxis {
position: absolute;
left: 0;
top: 0;
transform-origin: 0 0;
}
.mapEditorOriginAxis--x {
width: 36px;
height: 2px;
background: #e74c3c;
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.6);
}
.mapEditorOriginAxis--y {
width: 2px;
height: 36px;
background: #27ae60;
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.6);
}
.mapEditorOriginDot {
position: absolute;
left: -4px;
top: -4px;
width: 8px;
height: 8px;
border-radius: 50%;
background: #e67e22;
border: 2px solid #fff;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
}
.mapEditorOriginLabel {
position: absolute;
left: 8px;
top: -22px;
padding: 2px 6px;
border-radius: 3px;
background: rgba(255, 255, 255, 0.92);
border: 1px solid rgba(230, 126, 34, 0.55);
color: #c0392b;
font-size: 11px;
font-weight: 600;
white-space: nowrap;
line-height: 1.3;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
}
.mapEditorOrigin--offMap .mapEditorOriginLabel {
color: #888;
border-color: #ccc;
}
.mapEditorImage {
display: block;
max-width: none;
position: relative;
z-index: 1;
width: 100%;
height: auto;
height: 100%;
max-width: none;
image-rendering: pixelated;
image-rendering: crisp-edges;
user-select: none;
-webkit-user-drag: none;
pointer-events: none;
}
.mapEditorStatusBar {
flex-shrink: 0;
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 8px;
padding: 6px 12px;
background: rgba(32, 32, 32, 0.94);
color: #ddd;
font-size: 11px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.mapEditorStatusItem {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mapEditorStatusItem--view::before {
content: "View · ";
color: #8ab4f8;
font-weight: 600;
}
.mapEditorStatusItem--image::before {
content: "Image · ";
color: #81c995;
font-weight: 600;
}
.mapEditorStatusItem--world::before {
content: "World · ";
color: #f9ab00;
font-weight: 600;
}
.mapEditorEmpty {
@@ -3932,7 +4084,8 @@ body.auth-readonly-maps-page .mapsMirMapMenuCancelBtn {
display: none !important;
}
body.auth-readonly-maps-page .mapsMirBtn--green,
body.auth-readonly-maps-page #mapsListView .mapsMirBtn--green,
body.auth-readonly-maps-page #mapsCreateView .mapsMirBtn--green,
body.auth-readonly-maps-page .mapsMirIconBtn[data-edit],
body.auth-readonly-maps-page .mapsMirIconBtn[data-delete],
body.auth-readonly-maps-page #mapsCreateOpenBtn,