@nex125/seatmap-editor 0.1.6 → 0.1.8
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.cjs +2180 -1637
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1483 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.cts +42 -4
- package/dist/index.d.ts +42 -4
- package/dist/index.js +2181 -1638
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState, useEffect, useRef, useMemo, useCallback } from 'react';
|
|
2
|
-
import { pointInPolygon, generateId, AVAILABLE_STATUS_ID, CommandHistory, serializeVenue, deserializeVenue, venueAABB } from '@nex125/seatmap-core';
|
|
2
|
+
import { isDancefloorSection, pointInPolygon, generateId, isStageSection, AVAILABLE_STATUS_ID, CommandHistory, serializeVenue, deserializeVenue, venueAABB } from '@nex125/seatmap-core';
|
|
3
3
|
import { SeatmapProvider, useSeatmapContext, SeatmapCanvas } from '@nex125/seatmap-react';
|
|
4
4
|
import { useStore } from 'zustand';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -21,16 +21,75 @@ var BaseTool = class {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
// src/tools/PanTool.ts
|
|
24
|
-
var PanTool = class extends BaseTool {
|
|
24
|
+
var PanTool = class _PanTool extends BaseTool {
|
|
25
25
|
name = "pan";
|
|
26
26
|
cursor = "grab";
|
|
27
27
|
isPanning = false;
|
|
28
28
|
lastX = 0;
|
|
29
29
|
lastY = 0;
|
|
30
|
+
panVelocity = { x: 0, y: 0 };
|
|
31
|
+
lastPanSampleTime = 0;
|
|
32
|
+
inertiaRaf = 0;
|
|
33
|
+
inertiaLastTime = 0;
|
|
34
|
+
panInertiaJelly = 55;
|
|
35
|
+
panInertiaCarry;
|
|
36
|
+
panInertiaFriction;
|
|
37
|
+
panInertiaMinSpeed;
|
|
38
|
+
static DEFAULT_PAN_VELOCITY_BLEND = 0.3;
|
|
39
|
+
static DEFAULT_PAN_STOP_DELTA = 0.3;
|
|
40
|
+
static DEFAULT_PAN_RELEASE_IDLE_MS = 90;
|
|
41
|
+
panVelocityBlend = _PanTool.DEFAULT_PAN_VELOCITY_BLEND;
|
|
42
|
+
panStopDelta = _PanTool.DEFAULT_PAN_STOP_DELTA;
|
|
43
|
+
panReleaseIdleMs = _PanTool.DEFAULT_PAN_RELEASE_IDLE_MS;
|
|
44
|
+
setInertiaOptions(options) {
|
|
45
|
+
this.panInertiaJelly = options.panInertiaJelly ?? this.panInertiaJelly;
|
|
46
|
+
this.panInertiaCarry = options.panInertiaCarry;
|
|
47
|
+
this.panInertiaFriction = options.panInertiaFriction;
|
|
48
|
+
this.panInertiaMinSpeed = options.panInertiaMinSpeed;
|
|
49
|
+
this.panVelocityBlend = options.panVelocityBlend !== void 0 ? Math.max(0.05, Math.min(0.95, options.panVelocityBlend)) : _PanTool.DEFAULT_PAN_VELOCITY_BLEND;
|
|
50
|
+
this.panStopDelta = options.panStopDelta !== void 0 ? Math.max(0, Math.min(4, options.panStopDelta)) : _PanTool.DEFAULT_PAN_STOP_DELTA;
|
|
51
|
+
this.panReleaseIdleMs = options.panReleaseIdleMs !== void 0 ? Math.max(0, Math.min(400, options.panReleaseIdleMs)) : _PanTool.DEFAULT_PAN_RELEASE_IDLE_MS;
|
|
52
|
+
}
|
|
53
|
+
stopPanInertia() {
|
|
54
|
+
if (this.inertiaRaf) {
|
|
55
|
+
cancelAnimationFrame(this.inertiaRaf);
|
|
56
|
+
this.inertiaRaf = 0;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
startPanInertia(viewport) {
|
|
60
|
+
this.stopPanInertia();
|
|
61
|
+
const jelly = Math.max(0, Math.min(100, this.panInertiaJelly)) / 100;
|
|
62
|
+
const carry = this.panInertiaCarry !== void 0 ? Math.max(0, Math.min(0.98, this.panInertiaCarry)) : 0.58 + jelly * 0.28;
|
|
63
|
+
const baseFriction = this.panInertiaFriction !== void 0 ? Math.max(0.8, Math.min(0.995, this.panInertiaFriction)) : 0.88 + jelly * 0.08;
|
|
64
|
+
const minSpeed = this.panInertiaMinSpeed !== void 0 ? Math.max(1e-3, Math.min(0.05, this.panInertiaMinSpeed)) : 0.012 - jelly * 4e-3;
|
|
65
|
+
let velocity = {
|
|
66
|
+
x: this.panVelocity.x * carry,
|
|
67
|
+
y: this.panVelocity.y * carry
|
|
68
|
+
};
|
|
69
|
+
if (Math.hypot(velocity.x, velocity.y) < minSpeed) return;
|
|
70
|
+
this.inertiaLastTime = performance.now();
|
|
71
|
+
const tick = () => {
|
|
72
|
+
const now = performance.now();
|
|
73
|
+
const dt = Math.min(32, Math.max(8, now - this.inertiaLastTime));
|
|
74
|
+
this.inertiaLastTime = now;
|
|
75
|
+
const decay = Math.pow(baseFriction, dt / 16.67);
|
|
76
|
+
velocity = { x: velocity.x * decay, y: velocity.y * decay };
|
|
77
|
+
if (Math.hypot(velocity.x, velocity.y) < minSpeed) {
|
|
78
|
+
this.inertiaRaf = 0;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
viewport.pan(velocity.x * dt, velocity.y * dt);
|
|
82
|
+
this.inertiaRaf = requestAnimationFrame(tick);
|
|
83
|
+
};
|
|
84
|
+
this.inertiaRaf = requestAnimationFrame(tick);
|
|
85
|
+
}
|
|
30
86
|
onPointerDown(e) {
|
|
87
|
+
this.stopPanInertia();
|
|
31
88
|
this.isPanning = true;
|
|
32
89
|
this.lastX = e.screenX;
|
|
33
90
|
this.lastY = e.screenY;
|
|
91
|
+
this.panVelocity = { x: 0, y: 0 };
|
|
92
|
+
this.lastPanSampleTime = performance.now();
|
|
34
93
|
}
|
|
35
94
|
onPointerMove(e, viewport) {
|
|
36
95
|
if (!this.isPanning) return;
|
|
@@ -38,13 +97,30 @@ var PanTool = class extends BaseTool {
|
|
|
38
97
|
const dy = e.screenY - this.lastY;
|
|
39
98
|
this.lastX = e.screenX;
|
|
40
99
|
this.lastY = e.screenY;
|
|
100
|
+
const now = performance.now();
|
|
101
|
+
const dt = Math.max(1, now - this.lastPanSampleTime);
|
|
102
|
+
this.lastPanSampleTime = now;
|
|
103
|
+
const nextVelocity = { x: dx / dt, y: dy / dt };
|
|
104
|
+
const isNearlyStopped = Math.hypot(dx, dy) < this.panStopDelta;
|
|
105
|
+
this.panVelocity = isNearlyStopped ? { x: this.panVelocity.x * 0.35, y: this.panVelocity.y * 0.35 } : {
|
|
106
|
+
x: this.panVelocity.x * (1 - this.panVelocityBlend) + nextVelocity.x * this.panVelocityBlend,
|
|
107
|
+
y: this.panVelocity.y * (1 - this.panVelocityBlend) + nextVelocity.y * this.panVelocityBlend
|
|
108
|
+
};
|
|
41
109
|
viewport.pan(dx, dy);
|
|
42
110
|
}
|
|
43
|
-
onPointerUp() {
|
|
111
|
+
onPointerUp(_e, viewport) {
|
|
112
|
+
if (this.isPanning) {
|
|
113
|
+
const timeSinceLastSample = performance.now() - this.lastPanSampleTime;
|
|
114
|
+
if (timeSinceLastSample > this.panReleaseIdleMs || Math.hypot(this.panVelocity.x, this.panVelocity.y) < 0.01) {
|
|
115
|
+
this.panVelocity = { x: 0, y: 0 };
|
|
116
|
+
}
|
|
117
|
+
this.startPanInertia(viewport);
|
|
118
|
+
}
|
|
44
119
|
this.isPanning = false;
|
|
45
120
|
}
|
|
46
121
|
onDeactivate() {
|
|
47
122
|
this.isPanning = false;
|
|
123
|
+
this.stopPanInertia();
|
|
48
124
|
}
|
|
49
125
|
};
|
|
50
126
|
var GRID = 20;
|
|
@@ -89,6 +165,8 @@ var SelectTool = class extends BaseTool {
|
|
|
89
165
|
const hits = this.spatialIndex.queryPoint({ x: e.worldX, y: e.worldY }, 12);
|
|
90
166
|
const seatHit = this.pickNearestSeatHit(hits, { x: e.worldX, y: e.worldY });
|
|
91
167
|
const sectionHit = hits.find((h) => h.type === "section");
|
|
168
|
+
const seatSection = seatHit ? venue.sections.find((section) => section.id === seatHit.sectionId) ?? null : null;
|
|
169
|
+
const treatSeatHitAsSection = Boolean(seatSection && isDancefloorSection(seatSection));
|
|
92
170
|
if (this.sectionResizeEnabled) {
|
|
93
171
|
const clickedSection = sectionHit ? venue.sections.find((s) => s.id === sectionHit.sectionId) ?? null : null;
|
|
94
172
|
if (clickedSection) {
|
|
@@ -124,11 +202,12 @@ var SelectTool = class extends BaseTool {
|
|
|
124
202
|
return;
|
|
125
203
|
}
|
|
126
204
|
if (clickedSection && !seatHit) {
|
|
205
|
+
this.beginSectionDrag(venue, store, clickedSection);
|
|
127
206
|
return;
|
|
128
207
|
}
|
|
129
208
|
}
|
|
130
209
|
}
|
|
131
|
-
if (seatHit?.seatId && store.getState().selectedSeatIds.has(seatHit.seatId)) {
|
|
210
|
+
if (seatHit?.seatId && !treatSeatHitAsSection && store.getState().selectedSeatIds.has(seatHit.seatId)) {
|
|
132
211
|
const selectedIds = store.getState().selectedSeatIds;
|
|
133
212
|
const sectionId = seatHit.sectionId;
|
|
134
213
|
const originals = /* @__PURE__ */ new Map();
|
|
@@ -153,24 +232,11 @@ var SelectTool = class extends BaseTool {
|
|
|
153
232
|
return;
|
|
154
233
|
}
|
|
155
234
|
}
|
|
156
|
-
|
|
157
|
-
|
|
235
|
+
const sectionToDragId = treatSeatHitAsSection ? seatHit?.sectionId : sectionHit?.sectionId;
|
|
236
|
+
if (sectionToDragId && (treatSeatHitAsSection || !seatHit)) {
|
|
237
|
+
const section = venue.sections.find((s) => s.id === sectionToDragId);
|
|
158
238
|
if (section) {
|
|
159
|
-
|
|
160
|
-
const sectionIds = selectedSectionIds.has(section.id) && selectedSectionIds.size > 1 ? [...selectedSectionIds] : [section.id];
|
|
161
|
-
const originalPositions = /* @__PURE__ */ new Map();
|
|
162
|
-
for (const sec of venue.sections) {
|
|
163
|
-
if (sectionIds.includes(sec.id)) {
|
|
164
|
-
originalPositions.set(sec.id, { ...sec.position });
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
this.dragMode = {
|
|
168
|
-
type: "section",
|
|
169
|
-
primarySectionId: section.id,
|
|
170
|
-
sectionIds,
|
|
171
|
-
originalPositions,
|
|
172
|
-
delta: { x: 0, y: 0 }
|
|
173
|
-
};
|
|
239
|
+
this.beginSectionDrag(venue, store, section);
|
|
174
240
|
return;
|
|
175
241
|
}
|
|
176
242
|
}
|
|
@@ -325,8 +391,10 @@ var SelectTool = class extends BaseTool {
|
|
|
325
391
|
const hits = this.spatialIndex.queryPoint({ x: e.worldX, y: e.worldY }, 12);
|
|
326
392
|
const seatHit = this.pickNearestSeatHit(hits, { x: e.worldX, y: e.worldY });
|
|
327
393
|
const sectionHit = hits.find((h) => h.type === "section");
|
|
394
|
+
const seatSection = seatHit ? store.getState().venue?.sections.find((section) => section.id === seatHit.sectionId) ?? null : null;
|
|
395
|
+
const treatSeatHitAsSection = Boolean(seatSection && isDancefloorSection(seatSection));
|
|
328
396
|
const isMulti = e.ctrlKey || e.shiftKey || e.metaKey;
|
|
329
|
-
if (seatHit?.seatId) {
|
|
397
|
+
if (seatHit?.seatId && !treatSeatHitAsSection) {
|
|
330
398
|
this.resizeTargetSectionId = seatHit.sectionId;
|
|
331
399
|
if (isMulti) {
|
|
332
400
|
store.getState().toggleSeat(seatHit.seatId);
|
|
@@ -337,22 +405,28 @@ var SelectTool = class extends BaseTool {
|
|
|
337
405
|
store.getState().setSelection([seatHit.seatId]);
|
|
338
406
|
store.getState().selectSection(seatHit.sectionId);
|
|
339
407
|
}
|
|
340
|
-
} else
|
|
408
|
+
} else {
|
|
409
|
+
const sectionId = treatSeatHitAsSection ? seatHit?.sectionId : sectionHit?.sectionId;
|
|
410
|
+
if (!sectionId) {
|
|
411
|
+
if (!isMulti) {
|
|
412
|
+
if (this.sectionResizeEnabled) {
|
|
413
|
+
this.resizeTargetSectionId = null;
|
|
414
|
+
}
|
|
415
|
+
store.getState().clearSelection();
|
|
416
|
+
}
|
|
417
|
+
this.reset();
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
341
420
|
if (this.sectionResizeEnabled) {
|
|
342
|
-
this.resizeTargetSectionId =
|
|
421
|
+
this.resizeTargetSectionId = sectionId;
|
|
343
422
|
} else {
|
|
344
423
|
if (isMulti) {
|
|
345
|
-
store.getState().toggleSection(
|
|
424
|
+
store.getState().toggleSection(sectionId);
|
|
346
425
|
} else {
|
|
347
426
|
store.getState().clearSelection();
|
|
348
|
-
store.getState().selectSection(
|
|
427
|
+
store.getState().selectSection(sectionId);
|
|
349
428
|
}
|
|
350
429
|
}
|
|
351
|
-
} else if (!isMulti) {
|
|
352
|
-
if (this.sectionResizeEnabled) {
|
|
353
|
-
this.resizeTargetSectionId = null;
|
|
354
|
-
}
|
|
355
|
-
store.getState().clearSelection();
|
|
356
430
|
}
|
|
357
431
|
}
|
|
358
432
|
this.reset();
|
|
@@ -393,6 +467,23 @@ var SelectTool = class extends BaseTool {
|
|
|
393
467
|
}
|
|
394
468
|
});
|
|
395
469
|
}
|
|
470
|
+
beginSectionDrag(venue, store, section) {
|
|
471
|
+
const selectedSectionIds = store.getState().selectedSectionIds;
|
|
472
|
+
const sectionIds = selectedSectionIds.has(section.id) && selectedSectionIds.size > 1 ? [...selectedSectionIds] : [section.id];
|
|
473
|
+
const originalPositions = /* @__PURE__ */ new Map();
|
|
474
|
+
for (const sec of venue.sections) {
|
|
475
|
+
if (sectionIds.includes(sec.id)) {
|
|
476
|
+
originalPositions.set(sec.id, { ...sec.position });
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
this.dragMode = {
|
|
480
|
+
type: "section",
|
|
481
|
+
primarySectionId: section.id,
|
|
482
|
+
sectionIds,
|
|
483
|
+
originalPositions,
|
|
484
|
+
delta: { x: 0, y: 0 }
|
|
485
|
+
};
|
|
486
|
+
}
|
|
396
487
|
commitDrag(store, dropWorld) {
|
|
397
488
|
const venue = store.getState().venue;
|
|
398
489
|
if (!venue) return;
|
|
@@ -1025,6 +1116,8 @@ var SelectTool = class extends BaseTool {
|
|
|
1025
1116
|
}
|
|
1026
1117
|
};
|
|
1027
1118
|
var CLOSE_THRESHOLD = 15;
|
|
1119
|
+
var DANCEFLOOR_SEAT_ID_SUFFIX = "dancefloor-seat";
|
|
1120
|
+
var DANCEFLOOR_ROW_ID_SUFFIX = "dancefloor-row";
|
|
1028
1121
|
var AddSectionTool = class extends BaseTool {
|
|
1029
1122
|
constructor(history, categoryId = "") {
|
|
1030
1123
|
super();
|
|
@@ -1034,8 +1127,10 @@ var AddSectionTool = class extends BaseTool {
|
|
|
1034
1127
|
name = "add-section";
|
|
1035
1128
|
cursor = "crosshair";
|
|
1036
1129
|
mode = "rectangle";
|
|
1130
|
+
sectionKind = "section";
|
|
1037
1131
|
points = [];
|
|
1038
1132
|
onPointsChange;
|
|
1133
|
+
onSectionCreated;
|
|
1039
1134
|
setCategoryId(id) {
|
|
1040
1135
|
this.categoryId = id;
|
|
1041
1136
|
}
|
|
@@ -1044,6 +1139,20 @@ var AddSectionTool = class extends BaseTool {
|
|
|
1044
1139
|
this.points = [];
|
|
1045
1140
|
this.notifyChange();
|
|
1046
1141
|
}
|
|
1142
|
+
setSectionKind(sectionKind) {
|
|
1143
|
+
if (this.sectionKind === sectionKind) return;
|
|
1144
|
+
this.sectionKind = sectionKind;
|
|
1145
|
+
this.points = [];
|
|
1146
|
+
this.notifyChange();
|
|
1147
|
+
}
|
|
1148
|
+
hasPendingDraft() {
|
|
1149
|
+
return this.points.length > 0;
|
|
1150
|
+
}
|
|
1151
|
+
cancelDrawing() {
|
|
1152
|
+
if (this.points.length === 0) return;
|
|
1153
|
+
this.points = [];
|
|
1154
|
+
this.notifyChange();
|
|
1155
|
+
}
|
|
1047
1156
|
onPointerDown(e, _viewport, store) {
|
|
1048
1157
|
if (this.mode === "rectangle") {
|
|
1049
1158
|
if (this.points.length === 0) {
|
|
@@ -1105,11 +1214,12 @@ var AddSectionTool = class extends BaseTool {
|
|
|
1105
1214
|
}));
|
|
1106
1215
|
const newSection = {
|
|
1107
1216
|
id: generateId(),
|
|
1108
|
-
label: `Section ${Date.now().toString(36).slice(-3).toUpperCase()}`,
|
|
1217
|
+
label: this.sectionKind === "stage" ? "Stage" : this.sectionKind === "dancefloor" ? "Dancefloor" : `Section ${Date.now().toString(36).slice(-3).toUpperCase()}`,
|
|
1218
|
+
kind: this.sectionKind,
|
|
1109
1219
|
position: { x: cx, y: cy },
|
|
1110
1220
|
rotation: 0,
|
|
1111
|
-
categoryId: this.categoryId,
|
|
1112
|
-
rows: [],
|
|
1221
|
+
categoryId: this.sectionKind === "stage" ? "" : this.categoryId,
|
|
1222
|
+
rows: this.sectionKind === "dancefloor" ? this.createDancefloorRows(this.categoryId) : [],
|
|
1113
1223
|
outline
|
|
1114
1224
|
};
|
|
1115
1225
|
this.history.execute({
|
|
@@ -1118,6 +1228,7 @@ var AddSectionTool = class extends BaseTool {
|
|
|
1118
1228
|
const v = store.getState().venue;
|
|
1119
1229
|
if (!v) return;
|
|
1120
1230
|
store.getState().setVenue({ ...v, sections: [...v.sections, newSection] });
|
|
1231
|
+
this.onSectionCreated?.(newSection.id);
|
|
1121
1232
|
},
|
|
1122
1233
|
undo: () => {
|
|
1123
1234
|
const v = store.getState().venue;
|
|
@@ -1137,12 +1248,27 @@ var AddSectionTool = class extends BaseTool {
|
|
|
1137
1248
|
{ x: a.x, y: b.y }
|
|
1138
1249
|
];
|
|
1139
1250
|
}
|
|
1251
|
+
createDancefloorRows(categoryId) {
|
|
1252
|
+
const dancefloorSeat = {
|
|
1253
|
+
id: generateId(DANCEFLOOR_SEAT_ID_SUFFIX),
|
|
1254
|
+
label: "Dancefloor",
|
|
1255
|
+
position: { x: 0, y: 0 },
|
|
1256
|
+
status: "available",
|
|
1257
|
+
categoryId
|
|
1258
|
+
};
|
|
1259
|
+
return [
|
|
1260
|
+
{
|
|
1261
|
+
id: generateId(DANCEFLOOR_ROW_ID_SUFFIX),
|
|
1262
|
+
label: "DF",
|
|
1263
|
+
seats: [dancefloorSeat]
|
|
1264
|
+
}
|
|
1265
|
+
];
|
|
1266
|
+
}
|
|
1140
1267
|
notifyChange() {
|
|
1141
1268
|
this.onPointsChange?.(this.points, false);
|
|
1142
1269
|
}
|
|
1143
1270
|
onDeactivate() {
|
|
1144
|
-
this.
|
|
1145
|
-
this.notifyChange();
|
|
1271
|
+
this.cancelDrawing();
|
|
1146
1272
|
}
|
|
1147
1273
|
};
|
|
1148
1274
|
var GRID2 = 20;
|
|
@@ -1274,7 +1400,7 @@ var AddRowTool = class extends BaseTool {
|
|
|
1274
1400
|
const sectionHits = hits.filter((h) => h.type === "section");
|
|
1275
1401
|
if (sectionHits.length === 0) return null;
|
|
1276
1402
|
const sectionIds = [...new Set(sectionHits.map((h) => h.sectionId))];
|
|
1277
|
-
const sections = sectionIds.map((id) => venue.sections.find((s) => s.id === id)).filter((s) => Boolean(s));
|
|
1403
|
+
const sections = sectionIds.map((id) => venue.sections.find((s) => s.id === id)).filter((s) => Boolean(s)).filter((section) => !isStageSection(section) && !isDancefloorSection(section));
|
|
1278
1404
|
if (sections.length === 0) return null;
|
|
1279
1405
|
const containing = sections.find((section) => {
|
|
1280
1406
|
if (section.outline.length < 3) return true;
|
|
@@ -1320,7 +1446,7 @@ var AddSeatTool = class extends BaseTool {
|
|
|
1320
1446
|
const sectionHits = hits.filter((h) => h.type === "section");
|
|
1321
1447
|
if (sectionHits.length === 0) return;
|
|
1322
1448
|
const sectionIds = [...new Set(sectionHits.map((h) => h.sectionId))];
|
|
1323
|
-
let section = sectionIds.map((id) => venue.sections.find((s) => s.id === id)).filter((s) => Boolean(s)).find((s) => {
|
|
1449
|
+
let section = sectionIds.map((id) => venue.sections.find((s) => s.id === id)).filter((s) => Boolean(s)).filter((s) => !isStageSection(s) && !isDancefloorSection(s)).find((s) => {
|
|
1324
1450
|
if (s.outline.length < 3) return true;
|
|
1325
1451
|
const c2 = Math.cos(-s.rotation);
|
|
1326
1452
|
const s22 = Math.sin(-s.rotation);
|
|
@@ -1333,7 +1459,7 @@ var AddSeatTool = class extends BaseTool {
|
|
|
1333
1459
|
return pointInPolygon(local, s.outline);
|
|
1334
1460
|
});
|
|
1335
1461
|
if (!section) {
|
|
1336
|
-
section = sectionIds.map((id) => venue.sections.find((s) => s.id === id)).filter((s) => Boolean(s)).sort(
|
|
1462
|
+
section = sectionIds.map((id) => venue.sections.find((s) => s.id === id)).filter((s) => Boolean(s)).filter((s) => !isStageSection(s) && !isDancefloorSection(s)).sort(
|
|
1337
1463
|
(a, b) => Math.hypot(e.worldX - a.position.x, e.worldY - a.position.y) - Math.hypot(e.worldX - b.position.x, e.worldY - b.position.y)
|
|
1338
1464
|
)[0];
|
|
1339
1465
|
}
|
|
@@ -1448,33 +1574,100 @@ var AddSeatTool = class extends BaseTool {
|
|
|
1448
1574
|
return candidate;
|
|
1449
1575
|
}
|
|
1450
1576
|
};
|
|
1577
|
+
function PanIcon(props) {
|
|
1578
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", "aria-hidden": true, ...props, children: [
|
|
1579
|
+
/* @__PURE__ */ jsx("path", { d: "M8 11V6.6a1.6 1.6 0 1 1 3.2 0V10", strokeLinecap: "round" }),
|
|
1580
|
+
/* @__PURE__ */ jsx("path", { d: "M11.2 10V5.2a1.6 1.6 0 1 1 3.2 0v5", strokeLinecap: "round" }),
|
|
1581
|
+
/* @__PURE__ */ jsx("path", { d: "M14.4 10V6.8a1.6 1.6 0 1 1 3.2 0v6.2c0 4-2 6.2-6 6.2h-.4c-3.3 0-5.8-2.2-6.4-5.4l-.7-3.7a1.4 1.4 0 1 1 2.7-.6l.6 2.5", strokeLinecap: "round" })
|
|
1582
|
+
] });
|
|
1583
|
+
}
|
|
1584
|
+
function SelectIcon(props) {
|
|
1585
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", "aria-hidden": true, ...props, children: /* @__PURE__ */ jsx("path", { d: "M5 4.5v14l4.4-3 2.5 4.1 2.1-1.3-2.5-4.1 5-.3L5 4.5Z", strokeLinejoin: "round" }) });
|
|
1586
|
+
}
|
|
1587
|
+
function SectionIcon(props) {
|
|
1588
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", "aria-hidden": true, ...props, children: [
|
|
1589
|
+
/* @__PURE__ */ jsx("rect", { x: "4.5", y: "4.5", width: "15", height: "15", rx: "2.5" }),
|
|
1590
|
+
/* @__PURE__ */ jsx("path", { d: "M9 9h6M9 15h6", strokeLinecap: "round" })
|
|
1591
|
+
] });
|
|
1592
|
+
}
|
|
1593
|
+
function RowIcon(props) {
|
|
1594
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", "aria-hidden": true, ...props, children: [
|
|
1595
|
+
/* @__PURE__ */ jsx("path", { d: "M4.5 8h15M4.5 12h15M4.5 16h15", strokeLinecap: "round" }),
|
|
1596
|
+
/* @__PURE__ */ jsx("circle", { cx: "6.4", cy: "8", r: "0.8", fill: "currentColor", stroke: "none" }),
|
|
1597
|
+
/* @__PURE__ */ jsx("circle", { cx: "6.4", cy: "12", r: "0.8", fill: "currentColor", stroke: "none" }),
|
|
1598
|
+
/* @__PURE__ */ jsx("circle", { cx: "6.4", cy: "16", r: "0.8", fill: "currentColor", stroke: "none" })
|
|
1599
|
+
] });
|
|
1600
|
+
}
|
|
1601
|
+
function SeatIcon(props) {
|
|
1602
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", "aria-hidden": true, ...props, children: [
|
|
1603
|
+
/* @__PURE__ */ jsx("path", { d: "M7 12.5V9.4a2.4 2.4 0 1 1 4.8 0v3.1", strokeLinecap: "round" }),
|
|
1604
|
+
/* @__PURE__ */ jsx("path", { d: "M5 17v-3.1a1.9 1.9 0 0 1 1.9-1.9h8.2a1.9 1.9 0 0 1 1.9 1.9V17", strokeLinecap: "round" }),
|
|
1605
|
+
/* @__PURE__ */ jsx("path", { d: "M4.8 17.8h14.4", strokeLinecap: "round" })
|
|
1606
|
+
] });
|
|
1607
|
+
}
|
|
1608
|
+
function UndoIcon(props) {
|
|
1609
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", "aria-hidden": true, ...props, children: [
|
|
1610
|
+
/* @__PURE__ */ jsx("path", { d: "M8.5 8.5H5v3.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
1611
|
+
/* @__PURE__ */ jsx("path", { d: "M5.2 8.7c1.8-2 4.2-3.2 7-3.2 5 0 8.8 3.7 8.8 8.5", strokeLinecap: "round" })
|
|
1612
|
+
] });
|
|
1613
|
+
}
|
|
1614
|
+
function RedoIcon(props) {
|
|
1615
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", "aria-hidden": true, ...props, children: [
|
|
1616
|
+
/* @__PURE__ */ jsx("path", { d: "M15.5 8.5H19v3.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
1617
|
+
/* @__PURE__ */ jsx("path", { d: "M18.8 8.7c-1.8-2-4.2-3.2-7-3.2C6.8 5.5 3 9.2 3 14", strokeLinecap: "round" })
|
|
1618
|
+
] });
|
|
1619
|
+
}
|
|
1620
|
+
function FitIcon(props) {
|
|
1621
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", "aria-hidden": true, ...props, children: [
|
|
1622
|
+
/* @__PURE__ */ jsx("path", { d: "M9 4.8H4.8V9M15 4.8h4.2V9M9 19.2H4.8V15M15 19.2h4.2V15", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
1623
|
+
/* @__PURE__ */ jsx("rect", { x: "8.2", y: "8.2", width: "7.6", height: "7.6", rx: "1.4" })
|
|
1624
|
+
] });
|
|
1625
|
+
}
|
|
1626
|
+
function GridIcon(props) {
|
|
1627
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", "aria-hidden": true, ...props, children: [
|
|
1628
|
+
/* @__PURE__ */ jsx("rect", { x: "5", y: "5", width: "14", height: "14", rx: "2" }),
|
|
1629
|
+
/* @__PURE__ */ jsx("path", { d: "M12 5v14M5 12h14", strokeLinecap: "round" })
|
|
1630
|
+
] });
|
|
1631
|
+
}
|
|
1632
|
+
function HintIcon(props) {
|
|
1633
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", "aria-hidden": true, ...props, children: [
|
|
1634
|
+
/* @__PURE__ */ jsx("path", { d: "M9.4 9.2a2.7 2.7 0 1 1 4.8 1.6c-.6.8-1.6 1.4-1.8 2.7", strokeLinecap: "round" }),
|
|
1635
|
+
/* @__PURE__ */ jsx("path", { d: "M12 17.4h.01M8.7 19h6.6", strokeLinecap: "round" }),
|
|
1636
|
+
/* @__PURE__ */ jsx("path", { d: "M12 3.8a8.2 8.2 0 1 1 0 16.4 8.2 8.2 0 0 1 0-16.4Z" })
|
|
1637
|
+
] });
|
|
1638
|
+
}
|
|
1639
|
+
function SaveIcon(props) {
|
|
1640
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", "aria-hidden": true, ...props, children: [
|
|
1641
|
+
/* @__PURE__ */ jsx("path", { d: "M12 4.5v9.2M8.4 10.7 12 14.3l3.6-3.6", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
1642
|
+
/* @__PURE__ */ jsx("rect", { x: "5", y: "16.2", width: "14", height: "3.8", rx: "1.2" })
|
|
1643
|
+
] });
|
|
1644
|
+
}
|
|
1645
|
+
function LoadIcon(props) {
|
|
1646
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", "aria-hidden": true, ...props, children: [
|
|
1647
|
+
/* @__PURE__ */ jsx("path", { d: "M12 14.7V5.5M8.4 9.3 12 5.7l3.6 3.6", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
1648
|
+
/* @__PURE__ */ jsx("rect", { x: "5", y: "16.2", width: "14", height: "3.8", rx: "1.2" })
|
|
1649
|
+
] });
|
|
1650
|
+
}
|
|
1651
|
+
function SettingsIcon(props) {
|
|
1652
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", "aria-hidden": true, ...props, children: [
|
|
1653
|
+
/* @__PURE__ */ jsx("path", { d: "M12 8.2a3.8 3.8 0 1 1 0 7.6 3.8 3.8 0 0 1 0-7.6Z" }),
|
|
1654
|
+
/* @__PURE__ */ jsx(
|
|
1655
|
+
"path",
|
|
1656
|
+
{
|
|
1657
|
+
d: "m18.8 12 .9 1.6-1.5 2.6-1.8-.1a6.8 6.8 0 0 1-1.4.8L14.4 19h-3l-.6-2.1a6.8 6.8 0 0 1-1.4-.8l-1.8.1-1.5-2.6.9-1.6a6.7 6.7 0 0 1 0-1.6l-.9-1.6 1.5-2.6 1.8.1c.4-.3.9-.6 1.4-.8l.6-2.1h3l.6 2.1c.5.2 1 .5 1.4.8l1.8-.1 1.5 2.6-.9 1.6c.1.5.1 1.1 0 1.6Z",
|
|
1658
|
+
strokeLinecap: "round",
|
|
1659
|
+
strokeLinejoin: "round"
|
|
1660
|
+
}
|
|
1661
|
+
)
|
|
1662
|
+
] });
|
|
1663
|
+
}
|
|
1451
1664
|
var tools = [
|
|
1452
|
-
{ id: "pan", label: "Pan", icon:
|
|
1453
|
-
{ id: "select", label: "Select", icon:
|
|
1454
|
-
{ id: "add-section", label: "Section", icon:
|
|
1455
|
-
{ id: "add-row", label: "Row", icon:
|
|
1456
|
-
{ id: "add-seat", label: "Seat", icon:
|
|
1665
|
+
{ id: "pan", label: "Pan", icon: PanIcon },
|
|
1666
|
+
{ id: "select", label: "Select", icon: SelectIcon },
|
|
1667
|
+
{ id: "add-section", label: "Section", icon: SectionIcon },
|
|
1668
|
+
{ id: "add-row", label: "Row", icon: RowIcon },
|
|
1669
|
+
{ id: "add-seat", label: "Seat", icon: SeatIcon }
|
|
1457
1670
|
];
|
|
1458
|
-
var btnBase = {
|
|
1459
|
-
padding: "6px 10px",
|
|
1460
|
-
borderWidth: 1,
|
|
1461
|
-
borderStyle: "solid",
|
|
1462
|
-
borderColor: "#3a3a5a",
|
|
1463
|
-
borderRadius: 6,
|
|
1464
|
-
background: "#2a2a4a",
|
|
1465
|
-
color: "#e0e0e0",
|
|
1466
|
-
cursor: "pointer",
|
|
1467
|
-
fontSize: 13,
|
|
1468
|
-
fontFamily: "system-ui",
|
|
1469
|
-
display: "flex",
|
|
1470
|
-
alignItems: "center",
|
|
1471
|
-
gap: 4
|
|
1472
|
-
};
|
|
1473
|
-
var activeBtnStyle = {
|
|
1474
|
-
...btnBase,
|
|
1475
|
-
background: "#4a4a7a",
|
|
1476
|
-
borderColor: "#6a6aaa"
|
|
1477
|
-
};
|
|
1478
1671
|
function Toolbar({
|
|
1479
1672
|
activeTool,
|
|
1480
1673
|
onToolChange,
|
|
@@ -1488,112 +1681,171 @@ function Toolbar({
|
|
|
1488
1681
|
onFitView,
|
|
1489
1682
|
onSave,
|
|
1490
1683
|
onLoad,
|
|
1684
|
+
showHints,
|
|
1685
|
+
onToggleHints,
|
|
1686
|
+
isEditorSettingsOpen,
|
|
1687
|
+
onToggleEditorSettings,
|
|
1491
1688
|
style
|
|
1492
1689
|
}) {
|
|
1690
|
+
const getToolbarButtonClassName = (isActive = false, isHighlighted = false) => `seatmap-editor__toolbar-button${isActive ? " is-active" : ""}${isHighlighted ? " is-highlighted" : ""}`;
|
|
1493
1691
|
return /* @__PURE__ */ jsx(
|
|
1494
1692
|
"div",
|
|
1495
1693
|
{
|
|
1694
|
+
className: `seatmap-editor__toolbar${showHints ? " has-shortcuts-row" : ""}`,
|
|
1496
1695
|
style: {
|
|
1497
|
-
display: "flex",
|
|
1498
|
-
background: "#1a1a2e",
|
|
1499
|
-
borderBottom: "1px solid #2a2a4a",
|
|
1500
1696
|
...style
|
|
1501
1697
|
},
|
|
1502
|
-
children: /* @__PURE__ */ jsxs(
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1698
|
+
children: /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__toolbar-row seatmap-editor__toolbar-row--primary", children: [
|
|
1699
|
+
tools.map((tool) => /* @__PURE__ */ jsxs(
|
|
1700
|
+
"button",
|
|
1701
|
+
{
|
|
1702
|
+
type: "button",
|
|
1703
|
+
onClick: () => onToolChange(tool.id),
|
|
1704
|
+
className: `${getToolbarButtonClassName(activeTool === tool.id)} seatmap-editor__toolbar-tool-button`,
|
|
1705
|
+
title: tool.label,
|
|
1706
|
+
children: [
|
|
1707
|
+
/* @__PURE__ */ jsx(tool.icon, { className: "seatmap-editor__toolbar-icon" }),
|
|
1708
|
+
/* @__PURE__ */ jsx("span", { children: tool.label })
|
|
1709
|
+
]
|
|
1511
1710
|
},
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1711
|
+
tool.id
|
|
1712
|
+
)),
|
|
1713
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__toolbar-divider" }),
|
|
1714
|
+
/* @__PURE__ */ jsxs(
|
|
1715
|
+
"button",
|
|
1716
|
+
{
|
|
1717
|
+
type: "button",
|
|
1718
|
+
onClick: onUndo,
|
|
1719
|
+
disabled: !canUndo,
|
|
1720
|
+
className: getToolbarButtonClassName(),
|
|
1721
|
+
title: "Undo (Ctrl+Z)",
|
|
1722
|
+
children: [
|
|
1723
|
+
/* @__PURE__ */ jsx(UndoIcon, { className: "seatmap-editor__toolbar-icon" }),
|
|
1724
|
+
/* @__PURE__ */ jsx("span", { children: "Undo" })
|
|
1725
|
+
]
|
|
1726
|
+
}
|
|
1727
|
+
),
|
|
1728
|
+
/* @__PURE__ */ jsxs(
|
|
1729
|
+
"button",
|
|
1730
|
+
{
|
|
1731
|
+
type: "button",
|
|
1732
|
+
onClick: onRedo,
|
|
1733
|
+
disabled: !canRedo,
|
|
1734
|
+
className: getToolbarButtonClassName(),
|
|
1735
|
+
title: "Redo (Ctrl+Shift+Z)",
|
|
1736
|
+
children: [
|
|
1737
|
+
/* @__PURE__ */ jsx(RedoIcon, { className: "seatmap-editor__toolbar-icon" }),
|
|
1738
|
+
/* @__PURE__ */ jsx("span", { children: "Redo" })
|
|
1739
|
+
]
|
|
1740
|
+
}
|
|
1741
|
+
),
|
|
1742
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__toolbar-divider" }),
|
|
1743
|
+
/* @__PURE__ */ jsxs("button", { type: "button", onClick: onFitView, className: getToolbarButtonClassName(), title: "Fit to view", children: [
|
|
1744
|
+
/* @__PURE__ */ jsx(FitIcon, { className: "seatmap-editor__toolbar-icon" }),
|
|
1745
|
+
/* @__PURE__ */ jsx("span", { children: "Fit" })
|
|
1746
|
+
] }),
|
|
1747
|
+
/* @__PURE__ */ jsxs(
|
|
1748
|
+
"button",
|
|
1749
|
+
{
|
|
1750
|
+
type: "button",
|
|
1751
|
+
onClick: onToggleGridOptions,
|
|
1752
|
+
className: getToolbarButtonClassName(isGridOptionsOpen, gridEnabled),
|
|
1753
|
+
title: "Show grid options",
|
|
1754
|
+
children: [
|
|
1755
|
+
/* @__PURE__ */ jsx(GridIcon, { className: "seatmap-editor__toolbar-icon" }),
|
|
1756
|
+
/* @__PURE__ */ jsx("span", { children: "Grid" })
|
|
1757
|
+
]
|
|
1758
|
+
}
|
|
1759
|
+
),
|
|
1760
|
+
/* @__PURE__ */ jsxs(
|
|
1761
|
+
"button",
|
|
1762
|
+
{
|
|
1763
|
+
type: "button",
|
|
1764
|
+
onClick: onToggleHints,
|
|
1765
|
+
className: getToolbarButtonClassName(showHints, showHints),
|
|
1766
|
+
title: "Toggle inline editor hints",
|
|
1767
|
+
children: [
|
|
1768
|
+
/* @__PURE__ */ jsx(HintIcon, { className: "seatmap-editor__toolbar-icon" }),
|
|
1769
|
+
/* @__PURE__ */ jsx("span", { children: "Hints" })
|
|
1770
|
+
]
|
|
1771
|
+
}
|
|
1772
|
+
),
|
|
1773
|
+
/* @__PURE__ */ jsxs(
|
|
1774
|
+
"button",
|
|
1775
|
+
{
|
|
1776
|
+
type: "button",
|
|
1777
|
+
onClick: onToggleEditorSettings,
|
|
1778
|
+
className: getToolbarButtonClassName(isEditorSettingsOpen, isEditorSettingsOpen),
|
|
1779
|
+
title: "Editor settings",
|
|
1780
|
+
children: [
|
|
1781
|
+
/* @__PURE__ */ jsx(SettingsIcon, { className: "seatmap-editor__toolbar-icon" }),
|
|
1782
|
+
/* @__PURE__ */ jsx("span", { children: "Settings" })
|
|
1783
|
+
]
|
|
1784
|
+
}
|
|
1785
|
+
),
|
|
1786
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__toolbar-divider" }),
|
|
1787
|
+
/* @__PURE__ */ jsxs("button", { type: "button", onClick: onSave, className: getToolbarButtonClassName(), title: "Export venue as JSON", children: [
|
|
1788
|
+
/* @__PURE__ */ jsx(SaveIcon, { className: "seatmap-editor__toolbar-icon" }),
|
|
1789
|
+
/* @__PURE__ */ jsx("span", { children: "Save" })
|
|
1790
|
+
] }),
|
|
1791
|
+
/* @__PURE__ */ jsxs("button", { type: "button", onClick: onLoad, className: getToolbarButtonClassName(), title: "Import venue from JSON", children: [
|
|
1792
|
+
/* @__PURE__ */ jsx(LoadIcon, { className: "seatmap-editor__toolbar-icon" }),
|
|
1793
|
+
/* @__PURE__ */ jsx("span", { children: "Load" })
|
|
1794
|
+
] }),
|
|
1795
|
+
showHints && /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__toolbar-shortcuts-panel", "aria-label": "Keyboard shortcuts", children: [
|
|
1796
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__toolbar-shortcuts-title", children: "Keyboard shortcuts" }),
|
|
1797
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__toolbar-shortcuts-row", children: [
|
|
1798
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1799
|
+
/* @__PURE__ */ jsx("kbd", { children: "H" }),
|
|
1800
|
+
" / ",
|
|
1801
|
+
/* @__PURE__ */ jsx("kbd", { children: "1" }),
|
|
1802
|
+
" - Pan"
|
|
1803
|
+
] }),
|
|
1804
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1805
|
+
/* @__PURE__ */ jsx("kbd", { children: "V" }),
|
|
1806
|
+
" / ",
|
|
1807
|
+
/* @__PURE__ */ jsx("kbd", { children: "2" }),
|
|
1808
|
+
" - Select"
|
|
1809
|
+
] }),
|
|
1810
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1811
|
+
/* @__PURE__ */ jsx("kbd", { children: "S" }),
|
|
1812
|
+
" / ",
|
|
1813
|
+
/* @__PURE__ */ jsx("kbd", { children: "3" }),
|
|
1814
|
+
" - Add Section"
|
|
1815
|
+
] })
|
|
1816
|
+
] }),
|
|
1817
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__toolbar-shortcuts-row", children: [
|
|
1818
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1819
|
+
/* @__PURE__ */ jsx("kbd", { children: "R" }),
|
|
1820
|
+
" / ",
|
|
1821
|
+
/* @__PURE__ */ jsx("kbd", { children: "4" }),
|
|
1822
|
+
" - Add Row"
|
|
1823
|
+
] }),
|
|
1824
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1825
|
+
/* @__PURE__ */ jsx("kbd", { children: "A" }),
|
|
1826
|
+
" / ",
|
|
1827
|
+
/* @__PURE__ */ jsx("kbd", { children: "5" }),
|
|
1828
|
+
" - Add Seat"
|
|
1829
|
+
] }),
|
|
1830
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1831
|
+
/* @__PURE__ */ jsx("kbd", { children: "Space" }),
|
|
1832
|
+
" (toggle) - Toggle Pan"
|
|
1833
|
+
] })
|
|
1834
|
+
] })
|
|
1835
|
+
] })
|
|
1836
|
+
] })
|
|
1550
1837
|
}
|
|
1551
1838
|
);
|
|
1552
1839
|
}
|
|
1553
|
-
var labelStyle = {
|
|
1554
|
-
fontSize: 11,
|
|
1555
|
-
color: "#9e9e9e",
|
|
1556
|
-
marginBottom: 2,
|
|
1557
|
-
fontFamily: "system-ui"
|
|
1558
|
-
};
|
|
1559
|
-
var inputStyle = {
|
|
1560
|
-
width: "100%",
|
|
1561
|
-
padding: "4px 8px",
|
|
1562
|
-
background: "#2a2a4a",
|
|
1563
|
-
border: "1px solid #3a3a5a",
|
|
1564
|
-
borderRadius: 4,
|
|
1565
|
-
color: "#e0e0e0",
|
|
1566
|
-
fontSize: 13,
|
|
1567
|
-
fontFamily: "system-ui",
|
|
1568
|
-
boxSizing: "border-box"
|
|
1569
|
-
};
|
|
1570
|
-
var selectStyle = { ...inputStyle, cursor: "pointer" };
|
|
1571
|
-
var btnDanger = {
|
|
1572
|
-
padding: "3px 8px",
|
|
1573
|
-
border: "1px solid #5a2a2a",
|
|
1574
|
-
borderRadius: 4,
|
|
1575
|
-
background: "#3a1a1a",
|
|
1576
|
-
color: "#f48888",
|
|
1577
|
-
cursor: "pointer",
|
|
1578
|
-
fontSize: 12,
|
|
1579
|
-
fontFamily: "system-ui"
|
|
1580
|
-
};
|
|
1581
|
-
var btnSmall = {
|
|
1582
|
-
padding: "3px 8px",
|
|
1583
|
-
border: "1px solid #3a3a5a",
|
|
1584
|
-
borderRadius: 4,
|
|
1585
|
-
background: "#2a2a4a",
|
|
1586
|
-
color: "#e0e0e0",
|
|
1587
|
-
cursor: "pointer",
|
|
1588
|
-
fontSize: 12,
|
|
1589
|
-
fontFamily: "system-ui"
|
|
1590
|
-
};
|
|
1591
1840
|
function freshVenue(store) {
|
|
1592
1841
|
return store.getState().venue;
|
|
1593
1842
|
}
|
|
1594
1843
|
function setVenue(store, venue) {
|
|
1595
1844
|
store.getState().setVenue(venue);
|
|
1596
1845
|
}
|
|
1846
|
+
function isSectionSeatLayoutLocked(section) {
|
|
1847
|
+
return isStageSection(section) || isDancefloorSection(section);
|
|
1848
|
+
}
|
|
1597
1849
|
function PropertyPanel({
|
|
1598
1850
|
venue,
|
|
1599
1851
|
selectedSeatIds,
|
|
@@ -1666,7 +1918,9 @@ function PropertyPanel({
|
|
|
1666
1918
|
const updateSectionCategory = (sectionId, categoryId) => {
|
|
1667
1919
|
const v = freshVenue(store);
|
|
1668
1920
|
if (!v) return;
|
|
1669
|
-
const
|
|
1921
|
+
const targetSection = v.sections.find((s) => s.id === sectionId);
|
|
1922
|
+
if (!targetSection || isStageSection(targetSection)) return;
|
|
1923
|
+
const oldCatId = targetSection.categoryId;
|
|
1670
1924
|
history.execute({
|
|
1671
1925
|
description: `Change section category`,
|
|
1672
1926
|
execute: () => {
|
|
@@ -1741,12 +1995,15 @@ function PropertyPanel({
|
|
|
1741
1995
|
if (sectionIds.length === 0) return;
|
|
1742
1996
|
const v = freshVenue(store);
|
|
1743
1997
|
if (!v) return;
|
|
1744
|
-
const targetIds = new Set(
|
|
1998
|
+
const targetIds = new Set(
|
|
1999
|
+
v.sections.filter((section) => sectionIds.includes(section.id) && !isStageSection(section)).map((section) => section.id)
|
|
2000
|
+
);
|
|
2001
|
+
if (targetIds.size === 0) return;
|
|
1745
2002
|
const previousCategoryBySectionId = new Map(
|
|
1746
2003
|
v.sections.filter((section) => targetIds.has(section.id)).map((section) => [section.id, section.categoryId])
|
|
1747
2004
|
);
|
|
1748
2005
|
history.execute({
|
|
1749
|
-
description: `Change category for ${
|
|
2006
|
+
description: `Change category for ${targetIds.size} section(s)`,
|
|
1750
2007
|
execute: () => {
|
|
1751
2008
|
const cur = freshVenue(store);
|
|
1752
2009
|
if (!cur) return;
|
|
@@ -1786,26 +2043,6 @@ function PropertyPanel({
|
|
|
1786
2043
|
}
|
|
1787
2044
|
});
|
|
1788
2045
|
};
|
|
1789
|
-
const deleteSection = (sectionId) => {
|
|
1790
|
-
const v = freshVenue(store);
|
|
1791
|
-
if (!v) return;
|
|
1792
|
-
const removed = v.sections.find((s) => s.id === sectionId);
|
|
1793
|
-
if (!removed) return;
|
|
1794
|
-
history.execute({
|
|
1795
|
-
description: `Delete section "${removed.label}"`,
|
|
1796
|
-
execute: () => {
|
|
1797
|
-
const cur = freshVenue(store);
|
|
1798
|
-
if (!cur) return;
|
|
1799
|
-
setVenue(store, { ...cur, sections: cur.sections.filter((s) => s.id !== sectionId) });
|
|
1800
|
-
store.getState().clearSelection();
|
|
1801
|
-
},
|
|
1802
|
-
undo: () => {
|
|
1803
|
-
const cur = freshVenue(store);
|
|
1804
|
-
if (!cur) return;
|
|
1805
|
-
setVenue(store, { ...cur, sections: [...cur.sections, removed] });
|
|
1806
|
-
}
|
|
1807
|
-
});
|
|
1808
|
-
};
|
|
1809
2046
|
const deleteRow = (sectionId, rowId) => {
|
|
1810
2047
|
const v = freshVenue(store);
|
|
1811
2048
|
if (!v) return;
|
|
@@ -1879,11 +2116,43 @@ function PropertyPanel({
|
|
|
1879
2116
|
}
|
|
1880
2117
|
});
|
|
1881
2118
|
};
|
|
2119
|
+
const deleteSelectedObjects = () => {
|
|
2120
|
+
if (selectedSeatIds.size === 0 && selectedSectionIds.size === 0) return;
|
|
2121
|
+
const v = freshVenue(store);
|
|
2122
|
+
if (!v) return;
|
|
2123
|
+
const selectedSectionIdSet = new Set(selectedSectionIds);
|
|
2124
|
+
const selectedSeatIdSet = new Set(selectedSeatIds);
|
|
2125
|
+
const previousVenue = v;
|
|
2126
|
+
const nextVenue = {
|
|
2127
|
+
...v,
|
|
2128
|
+
sections: v.sections.filter((section) => !selectedSectionIdSet.has(section.id)).map((section) => ({
|
|
2129
|
+
...section,
|
|
2130
|
+
rows: section.rows.map((row) => ({
|
|
2131
|
+
...row,
|
|
2132
|
+
seats: row.seats.filter((seat) => !selectedSeatIdSet.has(seat.id))
|
|
2133
|
+
}))
|
|
2134
|
+
})),
|
|
2135
|
+
tables: v.tables.map((table) => ({
|
|
2136
|
+
...table,
|
|
2137
|
+
seats: table.seats.filter((seat) => !selectedSeatIdSet.has(seat.id))
|
|
2138
|
+
}))
|
|
2139
|
+
};
|
|
2140
|
+
history.execute({
|
|
2141
|
+
description: "Delete selected objects",
|
|
2142
|
+
execute: () => {
|
|
2143
|
+
setVenue(store, nextVenue);
|
|
2144
|
+
store.getState().clearSelection();
|
|
2145
|
+
},
|
|
2146
|
+
undo: () => {
|
|
2147
|
+
setVenue(store, previousVenue);
|
|
2148
|
+
}
|
|
2149
|
+
});
|
|
2150
|
+
};
|
|
1882
2151
|
const addSingleSeat = (sectionId) => {
|
|
1883
2152
|
const v = freshVenue(store);
|
|
1884
2153
|
if (!v) return;
|
|
1885
2154
|
const sec = v.sections.find((s) => s.id === sectionId);
|
|
1886
|
-
if (!sec) return;
|
|
2155
|
+
if (!sec || isSectionSeatLayoutLocked(sec)) return;
|
|
1887
2156
|
let targetRow = sec.rows[sec.rows.length - 1];
|
|
1888
2157
|
const newSeat = {
|
|
1889
2158
|
id: generateId(),
|
|
@@ -1987,7 +2256,7 @@ function PropertyPanel({
|
|
|
1987
2256
|
});
|
|
1988
2257
|
};
|
|
1989
2258
|
if (!venue) {
|
|
1990
|
-
return /* @__PURE__ */ jsx("div", {
|
|
2259
|
+
return /* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel seatmap-editor__panel-muted", style, children: "No venue loaded" });
|
|
1991
2260
|
}
|
|
1992
2261
|
const selectedSeatsEverywhere = [];
|
|
1993
2262
|
for (const section of venue.sections) {
|
|
@@ -2006,24 +2275,29 @@ function PropertyPanel({
|
|
|
2006
2275
|
const isMixedSeatStatus = selectedSeatStatusIds.size > 1;
|
|
2007
2276
|
const selectedSeatStatusId = selectedSeatStatusIds.size > 0 ? [...selectedSeatStatusIds][0] : AVAILABLE_STATUS_ID;
|
|
2008
2277
|
const hasMultipleSelectedSections = selectedSections.length > 1;
|
|
2278
|
+
const selectedNonStageSections = selectedSections.filter((section) => !isStageSection(section));
|
|
2279
|
+
const hasSelectedStage = selectedSections.some((section) => isStageSection(section));
|
|
2009
2280
|
const selectedSectionIdsList = selectedSections.map((section) => section.id);
|
|
2010
2281
|
const selectedSectionLabels = new Set(selectedSections.map((section) => section.label));
|
|
2011
|
-
const selectedSectionCategoryIds = new Set(
|
|
2282
|
+
const selectedSectionCategoryIds = new Set(selectedNonStageSections.map((section) => section.categoryId));
|
|
2012
2283
|
const sharedLabelValue = selectedSectionLabels.size === 1 ? selectedSections[0]?.label ?? "" : "";
|
|
2013
|
-
const sharedCategoryValue = selectedSectionCategoryIds.size === 1 ?
|
|
2014
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
2015
|
-
selectedSeatIds.size > 0 && /* @__PURE__ */ jsxs("div", {
|
|
2016
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2284
|
+
const sharedCategoryValue = selectedNonStageSections.length === 0 ? "" : selectedSectionCategoryIds.size === 1 ? selectedNonStageSections[0]?.categoryId ?? "" : "__mixed__";
|
|
2285
|
+
return /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel", style, children: [
|
|
2286
|
+
selectedSeatIds.size > 0 && /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section", children: [
|
|
2287
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section-header", children: [
|
|
2288
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-title", children: [
|
|
2289
|
+
"Seat Config (",
|
|
2290
|
+
selectedSeatIds.size,
|
|
2291
|
+
" selected)"
|
|
2292
|
+
] }),
|
|
2293
|
+
/* @__PURE__ */ jsx("button", { onClick: deleteSelectedObjects, className: "seatmap-editor__panel-button seatmap-editor__panel-button--danger", title: "Delete selected objects", children: "Delete Selected" })
|
|
2020
2294
|
] }),
|
|
2021
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2022
|
-
/* @__PURE__ */ jsx("div", {
|
|
2295
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section", children: [
|
|
2296
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-label", children: "Seat Status" }),
|
|
2023
2297
|
/* @__PURE__ */ jsxs(
|
|
2024
2298
|
"select",
|
|
2025
2299
|
{
|
|
2026
|
-
|
|
2300
|
+
className: "seatmap-editor__panel-select",
|
|
2027
2301
|
value: isMixedSeatStatus ? "__mixed__" : selectedSeatStatusId,
|
|
2028
2302
|
onChange: (e) => updateSelectedSeatStatus(e.target.value),
|
|
2029
2303
|
children: [
|
|
@@ -2033,13 +2307,13 @@ function PropertyPanel({
|
|
|
2033
2307
|
}
|
|
2034
2308
|
)
|
|
2035
2309
|
] }),
|
|
2036
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2037
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2310
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section", children: [
|
|
2311
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-label", children: [
|
|
2038
2312
|
"Selected Seats (",
|
|
2039
2313
|
selectedSeatIds.size,
|
|
2040
2314
|
")"
|
|
2041
2315
|
] }),
|
|
2042
|
-
/* @__PURE__ */ jsx("div", {
|
|
2316
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-list seatmap-editor__panel-scroll seatmap-editor__panel-scroll--sm", children: Array.from(selectedSeatIds).map((seatId) => {
|
|
2043
2317
|
let found = null;
|
|
2044
2318
|
for (const section2 of venue.sections) {
|
|
2045
2319
|
for (const row2 of section2.rows) {
|
|
@@ -2056,20 +2330,9 @@ function PropertyPanel({
|
|
|
2056
2330
|
return /* @__PURE__ */ jsxs(
|
|
2057
2331
|
"div",
|
|
2058
2332
|
{
|
|
2059
|
-
|
|
2060
|
-
display: "flex",
|
|
2061
|
-
alignItems: "center",
|
|
2062
|
-
gap: 6,
|
|
2063
|
-
padding: "2px 6px",
|
|
2064
|
-
fontSize: 12,
|
|
2065
|
-
fontFamily: "system-ui",
|
|
2066
|
-
color: "#e0e0e0",
|
|
2067
|
-
background: "#2a2a4a",
|
|
2068
|
-
marginBottom: 2,
|
|
2069
|
-
borderRadius: 4
|
|
2070
|
-
},
|
|
2333
|
+
className: "seatmap-editor__panel-list-item",
|
|
2071
2334
|
children: [
|
|
2072
|
-
/* @__PURE__ */ jsxs("span", {
|
|
2335
|
+
/* @__PURE__ */ jsxs("span", { className: "seatmap-editor__panel-text seatmap-editor__panel-content-grow", children: [
|
|
2073
2336
|
section.label,
|
|
2074
2337
|
" \xB7 Row ",
|
|
2075
2338
|
row.label,
|
|
@@ -2080,7 +2343,7 @@ function PropertyPanel({
|
|
|
2080
2343
|
"button",
|
|
2081
2344
|
{
|
|
2082
2345
|
onClick: () => deleteSeat(section.id, row.id, seat.id),
|
|
2083
|
-
|
|
2346
|
+
className: "seatmap-editor__panel-button seatmap-editor__panel-button--danger seatmap-editor__panel-button--tiny",
|
|
2084
2347
|
title: "Delete seat",
|
|
2085
2348
|
children: "\u2715"
|
|
2086
2349
|
}
|
|
@@ -2091,20 +2354,23 @@ function PropertyPanel({
|
|
|
2091
2354
|
);
|
|
2092
2355
|
}) })
|
|
2093
2356
|
] }),
|
|
2094
|
-
/* @__PURE__ */ jsx("div", {
|
|
2357
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-divider" })
|
|
2095
2358
|
] }),
|
|
2096
|
-
selectedSeatIds.size === 0 && selectedSections.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
2097
|
-
/* @__PURE__ */
|
|
2098
|
-
"
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
/* @__PURE__ */
|
|
2103
|
-
|
|
2359
|
+
selectedSeatIds.size === 0 && selectedSections.length > 0 && /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section", children: [
|
|
2360
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section-header", children: [
|
|
2361
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-title", children: [
|
|
2362
|
+
"Section / Stage / Dancefloor Config",
|
|
2363
|
+
selectedSections.length > 1 ? ` (${selectedSections.length} selected)` : ""
|
|
2364
|
+
] }),
|
|
2365
|
+
/* @__PURE__ */ jsx("button", { onClick: deleteSelectedObjects, className: "seatmap-editor__panel-button seatmap-editor__panel-button--danger", title: "Delete selected objects", children: "Delete Selected" })
|
|
2366
|
+
] }),
|
|
2367
|
+
hasMultipleSelectedSections && /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section seatmap-editor__panel-section--card", children: [
|
|
2368
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section", children: [
|
|
2369
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-label", children: "Label (apply to all selected)" }),
|
|
2104
2370
|
/* @__PURE__ */ jsx(
|
|
2105
2371
|
"input",
|
|
2106
2372
|
{
|
|
2107
|
-
|
|
2373
|
+
className: "seatmap-editor__panel-input",
|
|
2108
2374
|
value: sharedLabelValue,
|
|
2109
2375
|
placeholder: "Mixed labels",
|
|
2110
2376
|
onChange: (e) => updateSelectedSectionsLabel(selectedSectionIdsList, e.target.value)
|
|
@@ -2112,129 +2378,125 @@ function PropertyPanel({
|
|
|
2112
2378
|
)
|
|
2113
2379
|
] }),
|
|
2114
2380
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
2115
|
-
/* @__PURE__ */ jsx("div", {
|
|
2381
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-label", children: "Category (apply to all selected)" }),
|
|
2116
2382
|
/* @__PURE__ */ jsxs(
|
|
2117
2383
|
"select",
|
|
2118
2384
|
{
|
|
2119
|
-
|
|
2385
|
+
className: "seatmap-editor__panel-select",
|
|
2120
2386
|
value: sharedCategoryValue,
|
|
2121
2387
|
onChange: (e) => updateSelectedSectionsCategory(selectedSectionIdsList, e.target.value),
|
|
2388
|
+
disabled: selectedNonStageSections.length === 0,
|
|
2122
2389
|
children: [
|
|
2390
|
+
selectedNonStageSections.length === 0 && /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Not applicable for stage" }),
|
|
2123
2391
|
sharedCategoryValue === "__mixed__" && /* @__PURE__ */ jsx("option", { value: "__mixed__", disabled: true, children: "Mixed" }),
|
|
2124
2392
|
venue.categories.map((cat) => /* @__PURE__ */ jsx("option", { value: cat.id, children: cat.name }, cat.id))
|
|
2125
2393
|
]
|
|
2126
2394
|
}
|
|
2127
|
-
)
|
|
2395
|
+
),
|
|
2396
|
+
hasSelectedStage && /* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-label", children: "Stage selection is excluded from category changes." })
|
|
2128
2397
|
] })
|
|
2129
2398
|
] }),
|
|
2130
|
-
selectedSections.map((selectedSection) => /* @__PURE__ */ jsxs("div", {
|
|
2131
|
-
/* @__PURE__ */
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
] }),
|
|
2136
|
-
/* @__PURE__ */ jsx("button", { onClick: () => deleteSection(selectedSection.id), style: btnDanger, title: "Delete section", children: "Delete" })
|
|
2137
|
-
] }),
|
|
2399
|
+
selectedSections.map((selectedSection) => /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section seatmap-editor__panel-section--card", children: [
|
|
2400
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-section-header", children: /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-muted", children: [
|
|
2401
|
+
"ID: ",
|
|
2402
|
+
selectedSection.id
|
|
2403
|
+
] }) }),
|
|
2138
2404
|
!hasMultipleSelectedSections && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2139
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2140
|
-
/* @__PURE__ */ jsx("div", {
|
|
2405
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section", children: [
|
|
2406
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-label", children: "Label" }),
|
|
2141
2407
|
/* @__PURE__ */ jsx(
|
|
2142
2408
|
"input",
|
|
2143
2409
|
{
|
|
2144
|
-
|
|
2410
|
+
className: "seatmap-editor__panel-input",
|
|
2145
2411
|
value: selectedSection.label,
|
|
2146
2412
|
onChange: (e) => updateSectionLabel(selectedSection.id, e.target.value)
|
|
2147
2413
|
}
|
|
2148
2414
|
)
|
|
2149
2415
|
] }),
|
|
2150
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2151
|
-
/* @__PURE__ */ jsx("div", {
|
|
2152
|
-
/* @__PURE__ */
|
|
2416
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section", children: [
|
|
2417
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-label", children: "Category" }),
|
|
2418
|
+
/* @__PURE__ */ jsxs(
|
|
2153
2419
|
"select",
|
|
2154
2420
|
{
|
|
2155
|
-
|
|
2421
|
+
className: "seatmap-editor__panel-select",
|
|
2156
2422
|
value: selectedSection.categoryId,
|
|
2157
2423
|
onChange: (e) => updateSectionCategory(selectedSection.id, e.target.value),
|
|
2158
|
-
|
|
2424
|
+
disabled: isStageSection(selectedSection),
|
|
2425
|
+
children: [
|
|
2426
|
+
isStageSection(selectedSection) && /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Not applicable for stage" }),
|
|
2427
|
+
venue.categories.map((cat) => /* @__PURE__ */ jsx("option", { value: cat.id, children: cat.name }, cat.id))
|
|
2428
|
+
]
|
|
2159
2429
|
}
|
|
2160
|
-
)
|
|
2430
|
+
),
|
|
2431
|
+
isStageSection(selectedSection) && /* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-label", children: "Stage does not use pricing category." })
|
|
2161
2432
|
] })
|
|
2162
2433
|
] }),
|
|
2163
|
-
/* @__PURE__ */ jsx("div", {
|
|
2164
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
"div",
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2434
|
+
isStageSection(selectedSection) ? /* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-section seatmap-editor__panel-section--card seatmap-editor__panel-muted", children: "Stage areas do not support rows or seats." }) : isDancefloorSection(selectedSection) ? /* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-section seatmap-editor__panel-section--card seatmap-editor__panel-muted", children: "Dancefloor works as one selectable area seat. Resize the section shape to adjust its footprint." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2435
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-section", children: /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section-header", children: [
|
|
2436
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-label", children: [
|
|
2437
|
+
"Rows (",
|
|
2438
|
+
selectedSection.rows.length,
|
|
2439
|
+
") \xB7",
|
|
2440
|
+
" ",
|
|
2441
|
+
selectedSection.rows.reduce((t, r) => t + r.seats.length, 0),
|
|
2442
|
+
" seats"
|
|
2443
|
+
] }),
|
|
2444
|
+
/* @__PURE__ */ jsx("button", { onClick: () => addSingleSeat(selectedSection.id), className: "seatmap-editor__panel-button", title: "Add a single seat to the last row", children: "+ Seat" })
|
|
2445
|
+
] }) }),
|
|
2446
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-list seatmap-editor__panel-scroll seatmap-editor__panel-scroll--md", children: selectedSection.rows.map((row) => /* @__PURE__ */ jsxs(
|
|
2447
|
+
"div",
|
|
2448
|
+
{
|
|
2449
|
+
className: "seatmap-editor__panel-list-item",
|
|
2450
|
+
children: [
|
|
2451
|
+
/* @__PURE__ */ jsxs("span", { className: "seatmap-editor__panel-text seatmap-editor__panel-text--strong seatmap-editor__panel-text--mono-min", children: [
|
|
2452
|
+
"Row ",
|
|
2453
|
+
row.label
|
|
2454
|
+
] }),
|
|
2455
|
+
/* @__PURE__ */ jsxs("span", { className: "seatmap-editor__panel-muted seatmap-editor__panel-content-grow", children: [
|
|
2456
|
+
row.seats.length,
|
|
2457
|
+
" seats"
|
|
2458
|
+
] }),
|
|
2459
|
+
/* @__PURE__ */ jsx(
|
|
2460
|
+
"button",
|
|
2461
|
+
{
|
|
2462
|
+
onClick: () => deleteRow(selectedSection.id, row.id),
|
|
2463
|
+
className: "seatmap-editor__panel-button seatmap-editor__panel-button--danger seatmap-editor__panel-button--tiny",
|
|
2464
|
+
title: `Delete row ${row.label}`,
|
|
2465
|
+
children: "\u2715"
|
|
2466
|
+
}
|
|
2467
|
+
)
|
|
2468
|
+
]
|
|
2188
2469
|
},
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
row.label
|
|
2193
|
-
] }),
|
|
2194
|
-
/* @__PURE__ */ jsxs("span", { style: { flex: 1, color: "#9e9e9e" }, children: [
|
|
2195
|
-
row.seats.length,
|
|
2196
|
-
" seats"
|
|
2197
|
-
] }),
|
|
2198
|
-
/* @__PURE__ */ jsx(
|
|
2199
|
-
"button",
|
|
2200
|
-
{
|
|
2201
|
-
onClick: () => deleteRow(selectedSection.id, row.id),
|
|
2202
|
-
style: { ...btnDanger, padding: "1px 5px", fontSize: 11 },
|
|
2203
|
-
title: `Delete row ${row.label}`,
|
|
2204
|
-
children: "\u2715"
|
|
2205
|
-
}
|
|
2206
|
-
)
|
|
2207
|
-
]
|
|
2208
|
-
},
|
|
2209
|
-
row.id
|
|
2210
|
-
)) })
|
|
2470
|
+
row.id
|
|
2471
|
+
)) })
|
|
2472
|
+
] })
|
|
2211
2473
|
] }, selectedSection.id))
|
|
2212
2474
|
] }),
|
|
2213
2475
|
selectedSections.length === 0 && selectedSeatIds.size === 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
2214
|
-
/* @__PURE__ */ jsx("div", {
|
|
2215
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2216
|
-
/* @__PURE__ */ jsx("div", {
|
|
2476
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-title", children: "Venue Config" }),
|
|
2477
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section", children: [
|
|
2478
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-label", children: "Venue Name" }),
|
|
2217
2479
|
/* @__PURE__ */ jsx(
|
|
2218
2480
|
"input",
|
|
2219
2481
|
{
|
|
2220
|
-
|
|
2482
|
+
className: "seatmap-editor__panel-input",
|
|
2221
2483
|
value: venue.name,
|
|
2222
2484
|
onChange: (e) => updateVenueName(e.target.value)
|
|
2223
2485
|
}
|
|
2224
2486
|
)
|
|
2225
2487
|
] }),
|
|
2226
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2227
|
-
/* @__PURE__ */ jsx("div", {
|
|
2488
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section", children: [
|
|
2489
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-label", children: "Venue ID" }),
|
|
2228
2490
|
/* @__PURE__ */ jsx(
|
|
2229
2491
|
"input",
|
|
2230
2492
|
{
|
|
2231
|
-
|
|
2493
|
+
className: "seatmap-editor__panel-input",
|
|
2232
2494
|
value: venue.id,
|
|
2233
2495
|
onChange: (e) => updateVenueId(e.target.value)
|
|
2234
2496
|
}
|
|
2235
2497
|
)
|
|
2236
2498
|
] }),
|
|
2237
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2499
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-muted seatmap-editor__panel-muted--small", children: [
|
|
2238
2500
|
"Stats: ",
|
|
2239
2501
|
venue.sections.length,
|
|
2240
2502
|
" sections \xB7",
|
|
@@ -2242,31 +2504,11 @@ function PropertyPanel({
|
|
|
2242
2504
|
venue.sections.reduce((t, s) => t + s.rows.reduce((rt, r) => rt + r.seats.length, 0), 0),
|
|
2243
2505
|
" seats"
|
|
2244
2506
|
] }),
|
|
2245
|
-
/* @__PURE__ */ jsx("div", {
|
|
2246
|
-
/* @__PURE__ */ jsx("div", {
|
|
2247
|
-
venue.backgroundImage ? /* @__PURE__ */ jsxs("div", {
|
|
2248
|
-
/* @__PURE__ */ jsx(
|
|
2249
|
-
|
|
2250
|
-
{
|
|
2251
|
-
style: {
|
|
2252
|
-
width: "100%",
|
|
2253
|
-
height: 80,
|
|
2254
|
-
borderRadius: 4,
|
|
2255
|
-
border: "1px solid #3a3a5a",
|
|
2256
|
-
overflow: "hidden",
|
|
2257
|
-
marginBottom: 8
|
|
2258
|
-
},
|
|
2259
|
-
children: /* @__PURE__ */ jsx(
|
|
2260
|
-
"img",
|
|
2261
|
-
{
|
|
2262
|
-
src: venue.backgroundImage,
|
|
2263
|
-
alt: "Background",
|
|
2264
|
-
style: { width: "100%", height: "100%", objectFit: "cover", display: "block" }
|
|
2265
|
-
}
|
|
2266
|
-
)
|
|
2267
|
-
}
|
|
2268
|
-
),
|
|
2269
|
-
/* @__PURE__ */ jsxs("div", { style: { ...labelStyle, marginBottom: 4 }, children: [
|
|
2507
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-divider" }),
|
|
2508
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-label", children: "Background Image" }),
|
|
2509
|
+
venue.backgroundImage ? /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-section", children: [
|
|
2510
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-img-preview", children: /* @__PURE__ */ jsx("img", { src: venue.backgroundImage, alt: "Background" }) }),
|
|
2511
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-label", children: [
|
|
2270
2512
|
"Opacity: ",
|
|
2271
2513
|
Math.round((venue.backgroundImageOpacity ?? 0.5) * 100),
|
|
2272
2514
|
"%"
|
|
@@ -2279,12 +2521,12 @@ function PropertyPanel({
|
|
|
2279
2521
|
max: 100,
|
|
2280
2522
|
value: Math.round((venue.backgroundImageOpacity ?? 0.5) * 100),
|
|
2281
2523
|
onChange: (e) => onBackgroundOpacityChange?.(parseInt(e.target.value) / 100),
|
|
2282
|
-
|
|
2524
|
+
className: "seatmap-editor__panel-range"
|
|
2283
2525
|
}
|
|
2284
2526
|
),
|
|
2285
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2286
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2287
|
-
/* @__PURE__ */ jsx("div", {
|
|
2527
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-grid-2", children: [
|
|
2528
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2529
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-label", children: "Width" }),
|
|
2288
2530
|
/* @__PURE__ */ jsx(
|
|
2289
2531
|
"input",
|
|
2290
2532
|
{
|
|
@@ -2295,12 +2537,12 @@ function PropertyPanel({
|
|
|
2295
2537
|
onChange: (e) => onBackgroundSizeChange?.({
|
|
2296
2538
|
width: Math.max(1, Number.parseInt(e.target.value, 10) || 1)
|
|
2297
2539
|
}),
|
|
2298
|
-
|
|
2540
|
+
className: "seatmap-editor__panel-input"
|
|
2299
2541
|
}
|
|
2300
2542
|
)
|
|
2301
2543
|
] }),
|
|
2302
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2303
|
-
/* @__PURE__ */ jsx("div", {
|
|
2544
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2545
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-label", children: "Height" }),
|
|
2304
2546
|
/* @__PURE__ */ jsx(
|
|
2305
2547
|
"input",
|
|
2306
2548
|
{
|
|
@@ -2311,68 +2553,44 @@ function PropertyPanel({
|
|
|
2311
2553
|
onChange: (e) => onBackgroundSizeChange?.({
|
|
2312
2554
|
height: Math.max(1, Number.parseInt(e.target.value, 10) || 1)
|
|
2313
2555
|
}),
|
|
2314
|
-
|
|
2556
|
+
className: "seatmap-editor__panel-input"
|
|
2315
2557
|
}
|
|
2316
2558
|
)
|
|
2317
2559
|
] })
|
|
2318
2560
|
] }),
|
|
2319
|
-
/* @__PURE__ */ jsxs(
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
"input",
|
|
2335
|
-
{
|
|
2336
|
-
type: "checkbox",
|
|
2337
|
-
checked: venue.backgroundImageKeepAspectRatio ?? true,
|
|
2338
|
-
onChange: (e) => onBackgroundKeepAspectRatioChange?.(e.target.checked)
|
|
2339
|
-
}
|
|
2340
|
-
),
|
|
2341
|
-
"Keep aspect ratio"
|
|
2342
|
-
]
|
|
2343
|
-
}
|
|
2344
|
-
),
|
|
2345
|
-
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 6, marginTop: 8 }, children: [
|
|
2346
|
-
/* @__PURE__ */ jsx("button", { onClick: onUploadBackground, style: btnSmall, children: "Replace" }),
|
|
2347
|
-
/* @__PURE__ */ jsx("button", { onClick: onRemoveBackground, style: btnDanger, children: "Remove" })
|
|
2561
|
+
/* @__PURE__ */ jsxs("label", { className: "seatmap-editor__panel-row seatmap-editor__panel-text", children: [
|
|
2562
|
+
/* @__PURE__ */ jsx(
|
|
2563
|
+
"input",
|
|
2564
|
+
{
|
|
2565
|
+
type: "checkbox",
|
|
2566
|
+
className: "seatmap-editor__panel-checkbox",
|
|
2567
|
+
checked: venue.backgroundImageKeepAspectRatio ?? true,
|
|
2568
|
+
onChange: (e) => onBackgroundKeepAspectRatioChange?.(e.target.checked)
|
|
2569
|
+
}
|
|
2570
|
+
),
|
|
2571
|
+
"Keep aspect ratio"
|
|
2572
|
+
] }),
|
|
2573
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-row", children: [
|
|
2574
|
+
/* @__PURE__ */ jsx("button", { onClick: onUploadBackground, className: "seatmap-editor__panel-button", children: "Replace" }),
|
|
2575
|
+
/* @__PURE__ */ jsx("button", { onClick: onRemoveBackground, className: "seatmap-editor__panel-button seatmap-editor__panel-button--danger", children: "Remove" })
|
|
2348
2576
|
] })
|
|
2349
2577
|
] }) : /* @__PURE__ */ jsx(
|
|
2350
2578
|
"button",
|
|
2351
2579
|
{
|
|
2352
2580
|
onClick: onUploadBackground,
|
|
2353
|
-
|
|
2581
|
+
className: "seatmap-editor__panel-button seatmap-editor__panel-button--full",
|
|
2354
2582
|
children: "Upload Image"
|
|
2355
2583
|
}
|
|
2356
2584
|
)
|
|
2357
2585
|
] })
|
|
2358
2586
|
] });
|
|
2359
2587
|
}
|
|
2360
|
-
var btnSmall2 = {
|
|
2361
|
-
padding: "3px 8px",
|
|
2362
|
-
border: "1px solid #3a3a5a",
|
|
2363
|
-
borderRadius: 4,
|
|
2364
|
-
background: "#2a2a4a",
|
|
2365
|
-
color: "#e0e0e0",
|
|
2366
|
-
cursor: "pointer",
|
|
2367
|
-
fontSize: 12,
|
|
2368
|
-
fontFamily: "system-ui"
|
|
2369
|
-
};
|
|
2370
2588
|
function replaceCategoryInVenue(venue, categoryId, replacementCategoryId) {
|
|
2371
2589
|
return {
|
|
2372
2590
|
...venue,
|
|
2373
2591
|
sections: venue.sections.map((section) => ({
|
|
2374
2592
|
...section,
|
|
2375
|
-
categoryId: section.categoryId === categoryId ? replacementCategoryId : section.categoryId,
|
|
2593
|
+
categoryId: isStageSection(section) ? "" : section.categoryId === categoryId ? replacementCategoryId : section.categoryId,
|
|
2376
2594
|
rows: section.rows.map((row) => ({
|
|
2377
2595
|
...row,
|
|
2378
2596
|
seats: row.seats.map(
|
|
@@ -2397,20 +2615,25 @@ function CategoryManager({
|
|
|
2397
2615
|
history,
|
|
2398
2616
|
store,
|
|
2399
2617
|
fetchCategoryPrices,
|
|
2400
|
-
style
|
|
2618
|
+
style,
|
|
2619
|
+
locale = "en-US",
|
|
2620
|
+
currency = "BYN"
|
|
2401
2621
|
}) {
|
|
2402
2622
|
const [newName, setNewName] = useState("");
|
|
2403
|
-
const [newColor, setNewColor] = useState("#
|
|
2623
|
+
const [newColor, setNewColor] = useState("#dfcd72");
|
|
2404
2624
|
const [editingId, setEditingId] = useState(null);
|
|
2405
2625
|
const [editingName, setEditingName] = useState("");
|
|
2406
|
-
const [editingColor, setEditingColor] = useState("#
|
|
2626
|
+
const [editingColor, setEditingColor] = useState("#dfcd72");
|
|
2407
2627
|
const [isPriceManagerOpen, setIsPriceManagerOpen] = useState(false);
|
|
2408
2628
|
const [isFetchingPrices, setIsFetchingPrices] = useState(false);
|
|
2409
2629
|
const [fetchError, setFetchError] = useState(null);
|
|
2410
2630
|
const [syncStatus, setSyncStatus] = useState("not-synced");
|
|
2411
2631
|
const [overridePriceDrafts, setOverridePriceDrafts] = useState({});
|
|
2412
2632
|
if (!venue) return null;
|
|
2413
|
-
const formatPrice = (price) =>
|
|
2633
|
+
const formatPrice = (price) => new Intl.NumberFormat(locale, {
|
|
2634
|
+
style: "currency",
|
|
2635
|
+
currency
|
|
2636
|
+
}).format(Number.isFinite(price) ? price : 0);
|
|
2414
2637
|
const effectivePrice = (category) => {
|
|
2415
2638
|
if (category.isPriceOverridden && Number.isFinite(category.overriddenPrice)) {
|
|
2416
2639
|
return category.overriddenPrice;
|
|
@@ -2544,7 +2767,7 @@ function CategoryManager({
|
|
|
2544
2767
|
});
|
|
2545
2768
|
setSyncStatus("synced");
|
|
2546
2769
|
} catch (error) {
|
|
2547
|
-
const message = error instanceof Error ? error.message : "Failed to
|
|
2770
|
+
const message = error instanceof Error ? error.message : "Failed to load prices.";
|
|
2548
2771
|
setFetchError(message);
|
|
2549
2772
|
const currentVenue = store.getState().venue;
|
|
2550
2773
|
if (currentVenue) {
|
|
@@ -2645,92 +2868,57 @@ function CategoryManager({
|
|
|
2645
2868
|
};
|
|
2646
2869
|
});
|
|
2647
2870
|
};
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
height: 20,
|
|
2651
|
-
borderRadius: 999,
|
|
2652
|
-
border: "1px solid #4a4a6a",
|
|
2653
|
-
padding: 2,
|
|
2654
|
-
display: "inline-flex",
|
|
2655
|
-
alignItems: "center",
|
|
2656
|
-
transition: "all 0.12s ease"
|
|
2657
|
-
};
|
|
2658
|
-
const switchThumbBase = {
|
|
2659
|
-
width: 14,
|
|
2660
|
-
height: 14,
|
|
2661
|
-
borderRadius: "50%",
|
|
2662
|
-
background: "#e0e0e0",
|
|
2663
|
-
transition: "transform 0.12s ease"
|
|
2664
|
-
};
|
|
2665
|
-
return /* @__PURE__ */ jsxs("div", { style: { padding: 16, ...style }, children: [
|
|
2666
|
-
/* @__PURE__ */ jsx("div", { style: { fontWeight: 600, color: "#e0e0e0", fontSize: 14, fontFamily: "system-ui", marginBottom: 12 }, children: "Pricing Categories" }),
|
|
2871
|
+
return /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel", style, children: [
|
|
2872
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-title", children: "Pricing categories" }),
|
|
2667
2873
|
venue.categories.map((cat) => {
|
|
2668
2874
|
const isEditing = editingId === cat.id;
|
|
2669
2875
|
return /* @__PURE__ */ jsxs(
|
|
2670
2876
|
"div",
|
|
2671
2877
|
{
|
|
2672
|
-
|
|
2673
|
-
display: "flex",
|
|
2674
|
-
alignItems: "center",
|
|
2675
|
-
gap: 8,
|
|
2676
|
-
flexWrap: "wrap",
|
|
2677
|
-
marginBottom: 6,
|
|
2678
|
-
padding: "4px 8px",
|
|
2679
|
-
borderRadius: 4,
|
|
2680
|
-
background: "#2a2a4a"
|
|
2681
|
-
},
|
|
2878
|
+
className: "seatmap-editor__panel-list-item",
|
|
2682
2879
|
children: [
|
|
2683
|
-
/* @__PURE__ */
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2880
|
+
/* @__PURE__ */ jsxs("span", { className: "seatmap-editor__color-picker-shell", children: [
|
|
2881
|
+
/* @__PURE__ */ jsx(
|
|
2882
|
+
"span",
|
|
2883
|
+
{
|
|
2884
|
+
"aria-hidden": "true",
|
|
2885
|
+
className: "seatmap-editor__color-picker-dot",
|
|
2886
|
+
style: { background: isEditing ? editingColor : cat.color }
|
|
2887
|
+
}
|
|
2888
|
+
),
|
|
2889
|
+
/* @__PURE__ */ jsx(
|
|
2890
|
+
"input",
|
|
2891
|
+
{
|
|
2892
|
+
type: "color",
|
|
2893
|
+
value: isEditing ? editingColor : cat.color,
|
|
2894
|
+
onChange: (e) => isEditing && setEditingColor(e.target.value),
|
|
2895
|
+
disabled: !isEditing,
|
|
2896
|
+
className: "seatmap-editor__color-picker-input",
|
|
2897
|
+
"data-editable": isEditing ? "true" : "false",
|
|
2898
|
+
title: isEditing ? "Pick category color" : "Enable edit mode to change color"
|
|
2899
|
+
}
|
|
2900
|
+
)
|
|
2901
|
+
] }),
|
|
2693
2902
|
isEditing ? /* @__PURE__ */ jsx(
|
|
2694
2903
|
"input",
|
|
2695
2904
|
{
|
|
2696
2905
|
value: editingName,
|
|
2697
2906
|
onChange: (e) => setEditingName(e.target.value),
|
|
2698
2907
|
onKeyDown: (e) => e.key === "Enter" && saveEdit(),
|
|
2699
|
-
|
|
2700
|
-
flex: 1,
|
|
2701
|
-
minWidth: 0,
|
|
2702
|
-
padding: "2px 6px",
|
|
2703
|
-
background: "#1f1f38",
|
|
2704
|
-
border: "1px solid #3a3a5a",
|
|
2705
|
-
borderRadius: 4,
|
|
2706
|
-
color: "#e0e0e0",
|
|
2707
|
-
fontSize: 12,
|
|
2708
|
-
fontFamily: "system-ui"
|
|
2709
|
-
}
|
|
2908
|
+
className: "seatmap-editor__panel-input seatmap-editor__panel-input--grow"
|
|
2710
2909
|
}
|
|
2711
|
-
) : /* @__PURE__ */ jsx("div", {
|
|
2910
|
+
) : /* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-text seatmap-editor__panel-text--truncate", children: cat.name }),
|
|
2712
2911
|
isEditing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2713
|
-
/* @__PURE__ */ jsx("button", { onClick: saveEdit,
|
|
2714
|
-
/* @__PURE__ */ jsx("button", { onClick: () => setEditingId(null),
|
|
2912
|
+
/* @__PURE__ */ jsx("button", { onClick: saveEdit, className: "seatmap-editor__panel-button seatmap-editor__panel-button--tiny", children: "Save" }),
|
|
2913
|
+
/* @__PURE__ */ jsx("button", { onClick: () => setEditingId(null), className: "seatmap-editor__panel-button seatmap-editor__panel-button--tiny", children: "Cancel" })
|
|
2715
2914
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2716
|
-
/* @__PURE__ */ jsx(
|
|
2717
|
-
|
|
2718
|
-
{
|
|
2719
|
-
style: {
|
|
2720
|
-
color: "#8f8fa4",
|
|
2721
|
-
fontSize: 12,
|
|
2722
|
-
fontFamily: "system-ui",
|
|
2723
|
-
marginRight: 2
|
|
2724
|
-
},
|
|
2725
|
-
children: formatPrice(effectivePrice(cat))
|
|
2726
|
-
}
|
|
2727
|
-
),
|
|
2728
|
-
/* @__PURE__ */ jsx("button", { onClick: () => startEdit(cat), style: { ...btnSmall2, padding: "1px 6px", fontSize: 11 }, children: "Edit" }),
|
|
2915
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__panel-muted seatmap-editor__panel-price", children: formatPrice(effectivePrice(cat)) }),
|
|
2916
|
+
/* @__PURE__ */ jsx("button", { onClick: () => startEdit(cat), className: "seatmap-editor__panel-button seatmap-editor__panel-button--tiny", children: "Edit" }),
|
|
2729
2917
|
/* @__PURE__ */ jsx(
|
|
2730
2918
|
"button",
|
|
2731
2919
|
{
|
|
2732
2920
|
onClick: () => removeCategory(cat.id),
|
|
2733
|
-
|
|
2921
|
+
className: "seatmap-editor__panel-button seatmap-editor__panel-button--tiny",
|
|
2734
2922
|
disabled: venue.categories.length <= 1,
|
|
2735
2923
|
title: venue.categories.length <= 1 ? "At least one category is required" : "Delete category",
|
|
2736
2924
|
children: "\u2715"
|
|
@@ -2742,16 +2930,21 @@ function CategoryManager({
|
|
|
2742
2930
|
cat.id
|
|
2743
2931
|
);
|
|
2744
2932
|
}),
|
|
2745
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2746
|
-
/* @__PURE__ */
|
|
2747
|
-
"
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2933
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-row seatmap-editor__panel-row--spaced", children: [
|
|
2934
|
+
/* @__PURE__ */ jsxs("span", { className: "seatmap-editor__color-picker-shell seatmap-editor__color-picker-shell--lg", children: [
|
|
2935
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "seatmap-editor__color-picker-dot", style: { background: newColor } }),
|
|
2936
|
+
/* @__PURE__ */ jsx(
|
|
2937
|
+
"input",
|
|
2938
|
+
{
|
|
2939
|
+
type: "color",
|
|
2940
|
+
value: newColor,
|
|
2941
|
+
onChange: (e) => setNewColor(e.target.value),
|
|
2942
|
+
className: "seatmap-editor__color-picker-input",
|
|
2943
|
+
"data-editable": "true",
|
|
2944
|
+
title: "Pick new category color"
|
|
2945
|
+
}
|
|
2946
|
+
)
|
|
2947
|
+
] }),
|
|
2755
2948
|
/* @__PURE__ */ jsx(
|
|
2756
2949
|
"input",
|
|
2757
2950
|
{
|
|
@@ -2759,300 +2952,158 @@ function CategoryManager({
|
|
|
2759
2952
|
value: newName,
|
|
2760
2953
|
onChange: (e) => setNewName(e.target.value),
|
|
2761
2954
|
onKeyDown: (e) => e.key === "Enter" && addCategory(),
|
|
2762
|
-
|
|
2763
|
-
flex: 1,
|
|
2764
|
-
padding: "4px 8px",
|
|
2765
|
-
background: "#2a2a4a",
|
|
2766
|
-
border: "1px solid #3a3a5a",
|
|
2767
|
-
borderRadius: 4,
|
|
2768
|
-
color: "#e0e0e0",
|
|
2769
|
-
fontSize: 13,
|
|
2770
|
-
fontFamily: "system-ui"
|
|
2771
|
-
}
|
|
2955
|
+
className: "seatmap-editor__panel-input seatmap-editor__panel-input--grow"
|
|
2772
2956
|
}
|
|
2773
2957
|
),
|
|
2774
|
-
/* @__PURE__ */ jsx("button", { onClick: addCategory,
|
|
2958
|
+
/* @__PURE__ */ jsx("button", { onClick: addCategory, className: "seatmap-editor__panel-button", children: "Add" })
|
|
2775
2959
|
] }),
|
|
2776
|
-
/* @__PURE__ */ jsx("div", {
|
|
2960
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-actions-end", children: /* @__PURE__ */ jsx("button", { onClick: openPriceManager, className: "seatmap-editor__panel-button", children: "Manage prices" }) }),
|
|
2777
2961
|
isPriceManagerOpen && /* @__PURE__ */ jsx(
|
|
2778
2962
|
"div",
|
|
2779
2963
|
{
|
|
2780
|
-
|
|
2781
|
-
position: "fixed",
|
|
2782
|
-
inset: 0,
|
|
2783
|
-
background: "rgba(8, 8, 18, 0.65)",
|
|
2784
|
-
zIndex: 1e3,
|
|
2785
|
-
display: "flex",
|
|
2786
|
-
alignItems: "center",
|
|
2787
|
-
justifyContent: "center",
|
|
2788
|
-
padding: 16
|
|
2789
|
-
},
|
|
2964
|
+
className: "seatmap-editor__modal-backdrop",
|
|
2790
2965
|
onClick: () => setIsPriceManagerOpen(false),
|
|
2791
2966
|
children: /* @__PURE__ */ jsxs(
|
|
2792
2967
|
"div",
|
|
2793
2968
|
{
|
|
2794
|
-
|
|
2795
|
-
width: "min(860px, 95vw)",
|
|
2796
|
-
maxHeight: "80vh",
|
|
2797
|
-
overflow: "auto",
|
|
2798
|
-
background: "#17172b",
|
|
2799
|
-
border: "1px solid #3a3a5a",
|
|
2800
|
-
borderRadius: 10,
|
|
2801
|
-
padding: 16
|
|
2802
|
-
},
|
|
2969
|
+
className: "seatmap-editor__modal",
|
|
2803
2970
|
onClick: (event) => event.stopPropagation(),
|
|
2804
2971
|
children: [
|
|
2805
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2806
|
-
/* @__PURE__ */ jsx("div", {
|
|
2807
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2972
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__modal-header", children: [
|
|
2973
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-title", children: "Category prices" }),
|
|
2974
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__modal-actions", children: [
|
|
2808
2975
|
/* @__PURE__ */ jsx(
|
|
2809
2976
|
"button",
|
|
2810
2977
|
{
|
|
2811
2978
|
onClick: syncPricesFromBackend,
|
|
2812
2979
|
disabled: !fetchCategoryPrices || isFetchingPrices,
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
cursor: !fetchCategoryPrices || isFetchingPrices ? "not-allowed" : "pointer"
|
|
2817
|
-
},
|
|
2818
|
-
title: fetchCategoryPrices ? "Fetch latest category prices from backend" : "No backend price fetch configured",
|
|
2819
|
-
children: isFetchingPrices ? "Syncing..." : "Sync from Backend"
|
|
2980
|
+
className: "seatmap-editor__panel-button",
|
|
2981
|
+
title: fetchCategoryPrices ? "Load latest prices from backend" : "Backend price sync is not configured",
|
|
2982
|
+
children: isFetchingPrices ? "Syncing..." : "Sync with backend"
|
|
2820
2983
|
}
|
|
2821
2984
|
),
|
|
2822
|
-
/* @__PURE__ */ jsx("button", { onClick: () => setIsPriceManagerOpen(false),
|
|
2985
|
+
/* @__PURE__ */ jsx("button", { onClick: () => setIsPriceManagerOpen(false), className: "seatmap-editor__panel-button", children: "Close" })
|
|
2823
2986
|
] })
|
|
2824
2987
|
] }),
|
|
2825
|
-
/* @__PURE__ */ jsx("div", {
|
|
2988
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-muted seatmap-editor__panel-muted--spaced", children: "Backend prices are read-only. Override temporarily uses a custom category price for this seatmap." }),
|
|
2826
2989
|
/* @__PURE__ */ jsxs(
|
|
2827
2990
|
"div",
|
|
2828
2991
|
{
|
|
2829
|
-
|
|
2830
|
-
marginBottom: 10,
|
|
2831
|
-
color: syncStatus === "synced" ? "#8fd3a6" : syncStatus === "failed" ? "#ff9a9a" : "#b8b8cc",
|
|
2832
|
-
fontSize: 12,
|
|
2833
|
-
fontFamily: "system-ui"
|
|
2834
|
-
},
|
|
2992
|
+
className: syncStatus === "synced" ? "seatmap-editor__status-line seatmap-editor__status-line--success" : syncStatus === "failed" ? "seatmap-editor__status-line seatmap-editor__status-line--error" : "seatmap-editor__status-line seatmap-editor__status-line--idle",
|
|
2835
2993
|
children: [
|
|
2836
2994
|
"Sync status:",
|
|
2837
2995
|
" ",
|
|
2838
|
-
syncStatus === "not-synced" ? "Not synced" : syncStatus === "syncing" ? "Syncing..." : syncStatus === "synced" ? "Synced" : "
|
|
2996
|
+
syncStatus === "not-synced" ? "Not synced" : syncStatus === "syncing" ? "Syncing..." : syncStatus === "synced" ? "Synced" : "Error"
|
|
2839
2997
|
]
|
|
2840
2998
|
}
|
|
2841
2999
|
),
|
|
2842
|
-
fetchError && /* @__PURE__ */ jsx("div", {
|
|
2843
|
-
/* @__PURE__ */ jsxs(
|
|
2844
|
-
"div",
|
|
2845
|
-
{
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
3000
|
+
fetchError && /* @__PURE__ */ jsx("div", { className: "seatmap-editor__status-line seatmap-editor__status-line--error", children: fetchError }),
|
|
3001
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__table-grid", children: [
|
|
3002
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__table-head", children: "Category" }),
|
|
3003
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__table-head", children: "Backend" }),
|
|
3004
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__table-head", children: "Override" }),
|
|
3005
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__table-head", children: "Override price" }),
|
|
3006
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__table-head", children: "Effective price" }),
|
|
3007
|
+
venue.categories.map((category) => /* @__PURE__ */ jsxs(
|
|
3008
|
+
"div",
|
|
3009
|
+
{
|
|
3010
|
+
className: "seatmap-editor__table-row",
|
|
3011
|
+
children: [
|
|
3012
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__table-category-cell", children: [
|
|
3013
|
+
/* @__PURE__ */ jsx(
|
|
3014
|
+
"span",
|
|
3015
|
+
{
|
|
3016
|
+
className: "seatmap-editor__table-category-swatch",
|
|
3017
|
+
"aria-hidden": "true",
|
|
3018
|
+
style: { background: category.color }
|
|
3019
|
+
}
|
|
3020
|
+
),
|
|
3021
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__table-category-name", children: category.name })
|
|
3022
|
+
] }),
|
|
3023
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__table-amount", children: formatPrice(category.backendPrice) }),
|
|
3024
|
+
/* @__PURE__ */ jsx(
|
|
3025
|
+
"button",
|
|
3026
|
+
{
|
|
3027
|
+
type: "button",
|
|
3028
|
+
role: "switch",
|
|
3029
|
+
"aria-checked": Boolean(category.isPriceOverridden),
|
|
3030
|
+
onClick: () => toggleOverride(category.id, !category.isPriceOverridden),
|
|
3031
|
+
className: `seatmap-editor__switch-track${category.isPriceOverridden ? " is-checked" : ""}`,
|
|
3032
|
+
title: category.isPriceOverridden ? "Disable override" : "Enable override",
|
|
3033
|
+
children: /* @__PURE__ */ jsx("span", { className: "seatmap-editor__switch-thumb" })
|
|
3034
|
+
}
|
|
3035
|
+
),
|
|
3036
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__override-editor", children: [
|
|
3037
|
+
/* @__PURE__ */ jsx(
|
|
3038
|
+
"input",
|
|
3039
|
+
{
|
|
3040
|
+
type: "text",
|
|
3041
|
+
inputMode: "decimal",
|
|
3042
|
+
value: overridePriceDrafts[category.id] ?? "",
|
|
3043
|
+
disabled: !category.isPriceOverridden,
|
|
3044
|
+
onChange: (event) => setOverridePriceDrafts((current) => ({ ...current, [category.id]: event.target.value })),
|
|
3045
|
+
onKeyDown: (event) => {
|
|
3046
|
+
if (event.key === "Enter") {
|
|
3047
|
+
commitOverridePrice(category.id);
|
|
2882
3048
|
}
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
3049
|
+
if (event.key === "Escape") {
|
|
3050
|
+
resetOverrideDraft(category);
|
|
3051
|
+
}
|
|
3052
|
+
},
|
|
3053
|
+
className: `seatmap-editor__override-input${category.isPriceOverridden ? "" : " is-disabled"}`
|
|
3054
|
+
}
|
|
3055
|
+
),
|
|
3056
|
+
category.isPriceOverridden && /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__override-actions", children: [
|
|
2887
3057
|
/* @__PURE__ */ jsx(
|
|
2888
3058
|
"button",
|
|
2889
3059
|
{
|
|
2890
3060
|
type: "button",
|
|
2891
|
-
|
|
2892
|
-
"
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
...switchTrackBase,
|
|
2896
|
-
background: category.isPriceOverridden ? "#2d6a3d" : "#2a2a4a",
|
|
2897
|
-
borderColor: category.isPriceOverridden ? "#57b26f" : "#4a4a6a",
|
|
2898
|
-
cursor: "pointer"
|
|
2899
|
-
},
|
|
2900
|
-
title: category.isPriceOverridden ? "Disable override" : "Enable override",
|
|
2901
|
-
children: /* @__PURE__ */ jsx(
|
|
2902
|
-
"span",
|
|
2903
|
-
{
|
|
2904
|
-
style: {
|
|
2905
|
-
...switchThumbBase,
|
|
2906
|
-
transform: category.isPriceOverridden ? "translateX(14px)" : "translateX(0)"
|
|
2907
|
-
}
|
|
2908
|
-
}
|
|
2909
|
-
)
|
|
3061
|
+
onClick: () => adjustOverrideDraft(category.id, 0.01),
|
|
3062
|
+
className: "seatmap-editor__table-action-button",
|
|
3063
|
+
title: "Increase override price",
|
|
3064
|
+
children: "+"
|
|
2910
3065
|
}
|
|
2911
3066
|
),
|
|
2912
|
-
/* @__PURE__ */
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
display: "inline-flex",
|
|
2953
|
-
gap: 2
|
|
2954
|
-
},
|
|
2955
|
-
children: [
|
|
2956
|
-
/* @__PURE__ */ jsx(
|
|
2957
|
-
"button",
|
|
2958
|
-
{
|
|
2959
|
-
type: "button",
|
|
2960
|
-
onClick: () => adjustOverrideDraft(category.id, 0.01),
|
|
2961
|
-
style: {
|
|
2962
|
-
width: 20,
|
|
2963
|
-
height: 20,
|
|
2964
|
-
borderRadius: 4,
|
|
2965
|
-
border: "1px solid #4a4a6a",
|
|
2966
|
-
background: "#2a2a4a",
|
|
2967
|
-
color: "#d8d8ee",
|
|
2968
|
-
fontSize: 12,
|
|
2969
|
-
lineHeight: 1,
|
|
2970
|
-
padding: 0,
|
|
2971
|
-
cursor: "pointer"
|
|
2972
|
-
},
|
|
2973
|
-
title: "Increase override price",
|
|
2974
|
-
children: "+"
|
|
2975
|
-
}
|
|
2976
|
-
),
|
|
2977
|
-
/* @__PURE__ */ jsx(
|
|
2978
|
-
"button",
|
|
2979
|
-
{
|
|
2980
|
-
type: "button",
|
|
2981
|
-
onClick: () => adjustOverrideDraft(category.id, -0.01),
|
|
2982
|
-
style: {
|
|
2983
|
-
width: 20,
|
|
2984
|
-
height: 20,
|
|
2985
|
-
borderRadius: 4,
|
|
2986
|
-
border: "1px solid #4a4a6a",
|
|
2987
|
-
background: "#2a2a4a",
|
|
2988
|
-
color: "#d8d8ee",
|
|
2989
|
-
fontSize: 12,
|
|
2990
|
-
lineHeight: 1,
|
|
2991
|
-
padding: 0,
|
|
2992
|
-
cursor: "pointer"
|
|
2993
|
-
},
|
|
2994
|
-
title: "Decrease override price",
|
|
2995
|
-
children: "-"
|
|
2996
|
-
}
|
|
2997
|
-
),
|
|
2998
|
-
/* @__PURE__ */ jsx(
|
|
2999
|
-
"button",
|
|
3000
|
-
{
|
|
3001
|
-
type: "button",
|
|
3002
|
-
onClick: () => commitOverridePrice(category.id),
|
|
3003
|
-
disabled: !isDraftChanged(category),
|
|
3004
|
-
style: {
|
|
3005
|
-
width: 20,
|
|
3006
|
-
height: 20,
|
|
3007
|
-
borderRadius: 4,
|
|
3008
|
-
border: "1px solid #2f7b44",
|
|
3009
|
-
background: isDraftChanged(category) ? "#2d6a3d" : "#244832",
|
|
3010
|
-
color: "#d8ffe4",
|
|
3011
|
-
fontSize: 11,
|
|
3012
|
-
lineHeight: 1,
|
|
3013
|
-
padding: 0,
|
|
3014
|
-
opacity: isDraftChanged(category) ? 1 : 0.55,
|
|
3015
|
-
cursor: isDraftChanged(category) ? "pointer" : "not-allowed"
|
|
3016
|
-
},
|
|
3017
|
-
title: "Apply override price",
|
|
3018
|
-
children: "\u2713"
|
|
3019
|
-
}
|
|
3020
|
-
),
|
|
3021
|
-
/* @__PURE__ */ jsx(
|
|
3022
|
-
"button",
|
|
3023
|
-
{
|
|
3024
|
-
type: "button",
|
|
3025
|
-
onClick: () => resetOverrideDraft(category),
|
|
3026
|
-
disabled: !isDraftChanged(category),
|
|
3027
|
-
style: {
|
|
3028
|
-
width: 20,
|
|
3029
|
-
height: 20,
|
|
3030
|
-
borderRadius: 4,
|
|
3031
|
-
border: "1px solid #8b3f4d",
|
|
3032
|
-
background: isDraftChanged(category) ? "#6f2c3b" : "#4d2730",
|
|
3033
|
-
color: "#ffd9df",
|
|
3034
|
-
fontSize: 11,
|
|
3035
|
-
lineHeight: 1,
|
|
3036
|
-
padding: 0,
|
|
3037
|
-
opacity: isDraftChanged(category) ? 1 : 0.55,
|
|
3038
|
-
cursor: isDraftChanged(category) ? "pointer" : "not-allowed"
|
|
3039
|
-
},
|
|
3040
|
-
title: "Cancel override price changes",
|
|
3041
|
-
children: "\u2715"
|
|
3042
|
-
}
|
|
3043
|
-
)
|
|
3044
|
-
]
|
|
3045
|
-
}
|
|
3046
|
-
)
|
|
3047
|
-
] }),
|
|
3048
|
-
/* @__PURE__ */ jsx("span", { style: { color: "#e0e0e0", fontSize: 12, fontFamily: "system-ui", fontWeight: 600, whiteSpace: "nowrap" }, children: formatPrice(effectivePrice(category)) })
|
|
3049
|
-
]
|
|
3050
|
-
},
|
|
3051
|
-
category.id
|
|
3052
|
-
))
|
|
3053
|
-
]
|
|
3054
|
-
}
|
|
3055
|
-
)
|
|
3067
|
+
/* @__PURE__ */ jsx(
|
|
3068
|
+
"button",
|
|
3069
|
+
{
|
|
3070
|
+
type: "button",
|
|
3071
|
+
onClick: () => adjustOverrideDraft(category.id, -0.01),
|
|
3072
|
+
className: "seatmap-editor__table-action-button",
|
|
3073
|
+
title: "Decrease override price",
|
|
3074
|
+
children: "-"
|
|
3075
|
+
}
|
|
3076
|
+
),
|
|
3077
|
+
/* @__PURE__ */ jsx(
|
|
3078
|
+
"button",
|
|
3079
|
+
{
|
|
3080
|
+
type: "button",
|
|
3081
|
+
onClick: () => commitOverridePrice(category.id),
|
|
3082
|
+
disabled: !isDraftChanged(category),
|
|
3083
|
+
className: "seatmap-editor__table-action-button seatmap-editor__table-action-button--apply",
|
|
3084
|
+
title: "Apply override price",
|
|
3085
|
+
children: "\u2713"
|
|
3086
|
+
}
|
|
3087
|
+
),
|
|
3088
|
+
/* @__PURE__ */ jsx(
|
|
3089
|
+
"button",
|
|
3090
|
+
{
|
|
3091
|
+
type: "button",
|
|
3092
|
+
onClick: () => resetOverrideDraft(category),
|
|
3093
|
+
disabled: !isDraftChanged(category),
|
|
3094
|
+
className: "seatmap-editor__table-action-button seatmap-editor__table-action-button--reset",
|
|
3095
|
+
title: "Revert override changes",
|
|
3096
|
+
children: "\u2715"
|
|
3097
|
+
}
|
|
3098
|
+
)
|
|
3099
|
+
] })
|
|
3100
|
+
] }),
|
|
3101
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__table-effective-price", children: formatPrice(effectivePrice(category)) })
|
|
3102
|
+
]
|
|
3103
|
+
},
|
|
3104
|
+
category.id
|
|
3105
|
+
))
|
|
3106
|
+
] })
|
|
3056
3107
|
]
|
|
3057
3108
|
}
|
|
3058
3109
|
)
|
|
@@ -3077,81 +3128,57 @@ function LayerPanel({
|
|
|
3077
3128
|
return null;
|
|
3078
3129
|
};
|
|
3079
3130
|
const selectedSectionIdFromSeats = selectedSeatIds.size > 0 ? findSectionForSeat([...selectedSeatIds][0]) : null;
|
|
3080
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
3081
|
-
/* @__PURE__ */ jsx("div", {
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
"
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
),
|
|
3130
|
-
/* @__PURE__ */ jsxs("div", { style: { color: "#9e9e9e", fontSize: 11, fontFamily: "system-ui" }, children: [
|
|
3131
|
-
section.rows.length,
|
|
3132
|
-
" rows, ",
|
|
3133
|
-
seatCount,
|
|
3134
|
-
" seats"
|
|
3135
|
-
] })
|
|
3136
|
-
] })
|
|
3137
|
-
]
|
|
3138
|
-
},
|
|
3139
|
-
section.id
|
|
3140
|
-
);
|
|
3141
|
-
}),
|
|
3142
|
-
venue.sections.length === 0 && /* @__PURE__ */ jsx("div", { style: { color: "#9e9e9e", fontSize: 13, fontFamily: "system-ui" }, children: "No sections yet. Use the Add Section tool." })
|
|
3131
|
+
return /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel", style, children: [
|
|
3132
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-title", children: "Layers" }),
|
|
3133
|
+
/* @__PURE__ */ jsx(
|
|
3134
|
+
"div",
|
|
3135
|
+
{
|
|
3136
|
+
className: "seatmap-editor__panel-list",
|
|
3137
|
+
role: "listbox",
|
|
3138
|
+
"aria-label": "Venue sections",
|
|
3139
|
+
"aria-multiselectable": "true",
|
|
3140
|
+
children: venue.sections.map((section) => {
|
|
3141
|
+
const seatCount = section.rows.reduce((t, r) => t + r.seats.length, 0);
|
|
3142
|
+
const isActive = storeSelectedSectionIds.has(section.id) || section.id === selectedSectionIdFromSeats;
|
|
3143
|
+
const catColor = venue.categories.find((c) => c.id === section.categoryId)?.color ?? "var(--seatmap-editor-text-muted, #666)";
|
|
3144
|
+
return /* @__PURE__ */ jsxs(
|
|
3145
|
+
"button",
|
|
3146
|
+
{
|
|
3147
|
+
type: "button",
|
|
3148
|
+
role: "option",
|
|
3149
|
+
"aria-selected": isActive,
|
|
3150
|
+
onClick: (event) => onSelectSection(section.id, {
|
|
3151
|
+
multi: event.ctrlKey || event.metaKey
|
|
3152
|
+
}),
|
|
3153
|
+
className: `seatmap-editor__panel-list-item seatmap-editor__panel-list-item--interactive seatmap-editor__panel-list-item--interactive-button${isActive ? " is-active" : ""}`,
|
|
3154
|
+
children: [
|
|
3155
|
+
/* @__PURE__ */ jsx(
|
|
3156
|
+
"div",
|
|
3157
|
+
{
|
|
3158
|
+
className: "seatmap-editor__table-category-swatch",
|
|
3159
|
+
"aria-hidden": "true",
|
|
3160
|
+
style: { background: catColor }
|
|
3161
|
+
}
|
|
3162
|
+
),
|
|
3163
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-content-grow", children: [
|
|
3164
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-text seatmap-editor__panel-text--truncate", children: section.label }),
|
|
3165
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-muted seatmap-editor__panel-muted--small", children: [
|
|
3166
|
+
section.rows.length,
|
|
3167
|
+
" rows, ",
|
|
3168
|
+
seatCount,
|
|
3169
|
+
" seats"
|
|
3170
|
+
] })
|
|
3171
|
+
] })
|
|
3172
|
+
]
|
|
3173
|
+
},
|
|
3174
|
+
section.id
|
|
3175
|
+
);
|
|
3176
|
+
})
|
|
3177
|
+
}
|
|
3178
|
+
),
|
|
3179
|
+
venue.sections.length === 0 && /* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-muted", children: "No sections yet. Use the Add Section tool." })
|
|
3143
3180
|
] });
|
|
3144
3181
|
}
|
|
3145
|
-
var btnSmall3 = {
|
|
3146
|
-
padding: "3px 8px",
|
|
3147
|
-
border: "1px solid #3a3a5a",
|
|
3148
|
-
borderRadius: 4,
|
|
3149
|
-
background: "#2a2a4a",
|
|
3150
|
-
color: "#e0e0e0",
|
|
3151
|
-
cursor: "pointer",
|
|
3152
|
-
fontSize: 12,
|
|
3153
|
-
fontFamily: "system-ui"
|
|
3154
|
-
};
|
|
3155
3182
|
function sanitizeStatusId(name) {
|
|
3156
3183
|
const slug = name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
3157
3184
|
return slug || generateId();
|
|
@@ -3178,10 +3205,10 @@ function replaceStatusInVenue(venue, statusId, replacementStatusId) {
|
|
|
3178
3205
|
}
|
|
3179
3206
|
function StatusManager({ venue, history, store, style }) {
|
|
3180
3207
|
const [newName, setNewName] = useState("");
|
|
3181
|
-
const [newColor, setNewColor] = useState("#
|
|
3208
|
+
const [newColor, setNewColor] = useState("#dfcd72");
|
|
3182
3209
|
const [editingId, setEditingId] = useState(null);
|
|
3183
3210
|
const [editingName, setEditingName] = useState("");
|
|
3184
|
-
const [editingColor, setEditingColor] = useState("#
|
|
3211
|
+
const [editingColor, setEditingColor] = useState("#dfcd72");
|
|
3185
3212
|
const statusIds = useMemo(() => new Set(venue?.seatStatuses.map((status) => status.id) ?? []), [venue]);
|
|
3186
3213
|
if (!venue) return null;
|
|
3187
3214
|
const addStatus = () => {
|
|
@@ -3274,63 +3301,56 @@ function StatusManager({ venue, history, store, style }) {
|
|
|
3274
3301
|
}
|
|
3275
3302
|
});
|
|
3276
3303
|
};
|
|
3277
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
3278
|
-
/* @__PURE__ */ jsx("div", {
|
|
3304
|
+
return /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel", style, children: [
|
|
3305
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-title", children: "Seat Statuses" }),
|
|
3279
3306
|
venue.seatStatuses.map((status) => {
|
|
3280
3307
|
const isEditing = editingId === status.id;
|
|
3281
3308
|
return /* @__PURE__ */ jsxs(
|
|
3282
3309
|
"div",
|
|
3283
3310
|
{
|
|
3284
|
-
|
|
3285
|
-
display: "flex",
|
|
3286
|
-
alignItems: "center",
|
|
3287
|
-
gap: 8,
|
|
3288
|
-
flexWrap: "wrap",
|
|
3289
|
-
marginBottom: 6,
|
|
3290
|
-
padding: "4px 8px",
|
|
3291
|
-
borderRadius: 4,
|
|
3292
|
-
background: "#2a2a4a"
|
|
3293
|
-
},
|
|
3311
|
+
className: "seatmap-editor__panel-list-item",
|
|
3294
3312
|
children: [
|
|
3295
|
-
/* @__PURE__ */
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3313
|
+
/* @__PURE__ */ jsxs("span", { className: "seatmap-editor__color-picker-shell", children: [
|
|
3314
|
+
/* @__PURE__ */ jsx(
|
|
3315
|
+
"span",
|
|
3316
|
+
{
|
|
3317
|
+
"aria-hidden": "true",
|
|
3318
|
+
className: "seatmap-editor__color-picker-dot",
|
|
3319
|
+
style: { background: isEditing ? editingColor : status.color }
|
|
3320
|
+
}
|
|
3321
|
+
),
|
|
3322
|
+
/* @__PURE__ */ jsx(
|
|
3323
|
+
"input",
|
|
3324
|
+
{
|
|
3325
|
+
type: "color",
|
|
3326
|
+
value: isEditing ? editingColor : status.color,
|
|
3327
|
+
onChange: (e) => isEditing && setEditingColor(e.target.value),
|
|
3328
|
+
disabled: !isEditing,
|
|
3329
|
+
className: "seatmap-editor__color-picker-input",
|
|
3330
|
+
"data-editable": isEditing ? "true" : "false",
|
|
3331
|
+
title: isEditing ? "Pick status color" : "Enable edit to change color"
|
|
3332
|
+
}
|
|
3333
|
+
)
|
|
3334
|
+
] }),
|
|
3305
3335
|
isEditing ? /* @__PURE__ */ jsx(
|
|
3306
3336
|
"input",
|
|
3307
3337
|
{
|
|
3308
3338
|
value: editingName,
|
|
3309
3339
|
onChange: (e) => setEditingName(e.target.value),
|
|
3310
3340
|
onKeyDown: (e) => e.key === "Enter" && saveEdit(),
|
|
3311
|
-
|
|
3312
|
-
flex: 1,
|
|
3313
|
-
minWidth: 0,
|
|
3314
|
-
padding: "2px 6px",
|
|
3315
|
-
background: "#1f1f38",
|
|
3316
|
-
border: "1px solid #3a3a5a",
|
|
3317
|
-
borderRadius: 4,
|
|
3318
|
-
color: "#e0e0e0",
|
|
3319
|
-
fontSize: 12,
|
|
3320
|
-
fontFamily: "system-ui"
|
|
3321
|
-
}
|
|
3341
|
+
className: "seatmap-editor__panel-input seatmap-editor__panel-input--grow"
|
|
3322
3342
|
}
|
|
3323
|
-
) : /* @__PURE__ */ jsx("div", {
|
|
3343
|
+
) : /* @__PURE__ */ jsx("div", { className: "seatmap-editor__panel-text seatmap-editor__panel-content-grow", children: status.name }),
|
|
3324
3344
|
isEditing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3325
|
-
/* @__PURE__ */ jsx("button", { onClick: saveEdit,
|
|
3326
|
-
/* @__PURE__ */ jsx("button", { onClick: () => setEditingId(null),
|
|
3345
|
+
/* @__PURE__ */ jsx("button", { onClick: saveEdit, className: "seatmap-editor__panel-button seatmap-editor__panel-button--tiny", children: "Save" }),
|
|
3346
|
+
/* @__PURE__ */ jsx("button", { onClick: () => setEditingId(null), className: "seatmap-editor__panel-button seatmap-editor__panel-button--tiny", children: "Cancel" })
|
|
3327
3347
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3328
|
-
/* @__PURE__ */ jsx("button", { onClick: () => startEdit(status),
|
|
3348
|
+
/* @__PURE__ */ jsx("button", { onClick: () => startEdit(status), className: "seatmap-editor__panel-button seatmap-editor__panel-button--tiny", children: "Edit" }),
|
|
3329
3349
|
/* @__PURE__ */ jsx(
|
|
3330
3350
|
"button",
|
|
3331
3351
|
{
|
|
3332
3352
|
onClick: () => removeStatus(status.id),
|
|
3333
|
-
|
|
3353
|
+
className: "seatmap-editor__panel-button seatmap-editor__panel-button--tiny",
|
|
3334
3354
|
disabled: status.id === AVAILABLE_STATUS_ID,
|
|
3335
3355
|
title: status.id === AVAILABLE_STATUS_ID ? "Available status cannot be removed" : "Delete status",
|
|
3336
3356
|
children: "\u2715"
|
|
@@ -3342,16 +3362,21 @@ function StatusManager({ venue, history, store, style }) {
|
|
|
3342
3362
|
status.id
|
|
3343
3363
|
);
|
|
3344
3364
|
}),
|
|
3345
|
-
/* @__PURE__ */ jsxs("div", {
|
|
3346
|
-
/* @__PURE__ */
|
|
3347
|
-
"
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3365
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__panel-row seatmap-editor__panel-row--spaced", children: [
|
|
3366
|
+
/* @__PURE__ */ jsxs("span", { className: "seatmap-editor__color-picker-shell seatmap-editor__color-picker-shell--lg", children: [
|
|
3367
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "seatmap-editor__color-picker-dot", style: { background: newColor } }),
|
|
3368
|
+
/* @__PURE__ */ jsx(
|
|
3369
|
+
"input",
|
|
3370
|
+
{
|
|
3371
|
+
type: "color",
|
|
3372
|
+
value: newColor,
|
|
3373
|
+
onChange: (e) => setNewColor(e.target.value),
|
|
3374
|
+
className: "seatmap-editor__color-picker-input",
|
|
3375
|
+
"data-editable": "true",
|
|
3376
|
+
title: "Pick new status color"
|
|
3377
|
+
}
|
|
3378
|
+
)
|
|
3379
|
+
] }),
|
|
3355
3380
|
/* @__PURE__ */ jsx(
|
|
3356
3381
|
"input",
|
|
3357
3382
|
{
|
|
@@ -3359,19 +3384,10 @@ function StatusManager({ venue, history, store, style }) {
|
|
|
3359
3384
|
value: newName,
|
|
3360
3385
|
onChange: (e) => setNewName(e.target.value),
|
|
3361
3386
|
onKeyDown: (e) => e.key === "Enter" && addStatus(),
|
|
3362
|
-
|
|
3363
|
-
flex: 1,
|
|
3364
|
-
padding: "4px 8px",
|
|
3365
|
-
background: "#2a2a4a",
|
|
3366
|
-
border: "1px solid #3a3a5a",
|
|
3367
|
-
borderRadius: 4,
|
|
3368
|
-
color: "#e0e0e0",
|
|
3369
|
-
fontSize: 13,
|
|
3370
|
-
fontFamily: "system-ui"
|
|
3371
|
-
}
|
|
3387
|
+
className: "seatmap-editor__panel-input seatmap-editor__panel-input--grow"
|
|
3372
3388
|
}
|
|
3373
3389
|
),
|
|
3374
|
-
/* @__PURE__ */ jsx("button", { onClick: addStatus,
|
|
3390
|
+
/* @__PURE__ */ jsx("button", { onClick: addStatus, className: "seatmap-editor__panel-button", children: "Add" })
|
|
3375
3391
|
] })
|
|
3376
3392
|
] });
|
|
3377
3393
|
}
|
|
@@ -3385,6 +3401,26 @@ function fitBackgroundToBounds(boundsWidth, boundsHeight, imageWidth, imageHeigh
|
|
|
3385
3401
|
aspectRatio: safeImageWidth / safeImageHeight
|
|
3386
3402
|
};
|
|
3387
3403
|
}
|
|
3404
|
+
function easeOutBack(t, overshoot) {
|
|
3405
|
+
const c1 = Math.max(0, overshoot);
|
|
3406
|
+
const c3 = c1 + 1;
|
|
3407
|
+
const p = t - 1;
|
|
3408
|
+
return 1 + c3 * p * p * p + c1 * p * p;
|
|
3409
|
+
}
|
|
3410
|
+
function getViewportStateForFitBounds(viewport, aabb, padding = 40) {
|
|
3411
|
+
const contentW = aabb.maxX - aabb.minX;
|
|
3412
|
+
const contentH = aabb.maxY - aabb.minY;
|
|
3413
|
+
if (contentW <= 0 || contentH <= 0) return null;
|
|
3414
|
+
if (viewport.screenWidth <= 0 || viewport.screenHeight <= 0) return null;
|
|
3415
|
+
const minZoom = 0.05;
|
|
3416
|
+
const maxZoom = 4;
|
|
3417
|
+
const scaleX = (viewport.screenWidth - padding * 2) / contentW;
|
|
3418
|
+
const scaleY = (viewport.screenHeight - padding * 2) / contentH;
|
|
3419
|
+
const zoom = Math.min(maxZoom, Math.max(minZoom, Math.min(scaleX, scaleY)));
|
|
3420
|
+
const x = -(aabb.minX + contentW / 2) + viewport.screenWidth / (2 * zoom);
|
|
3421
|
+
const y = -(aabb.minY + contentH / 2) + viewport.screenHeight / (2 * zoom);
|
|
3422
|
+
return { x, y, zoom };
|
|
3423
|
+
}
|
|
3388
3424
|
function getBackgroundRectInWorld(venue) {
|
|
3389
3425
|
const width = Math.max(1, venue.backgroundImageWidth ?? venue.bounds.width);
|
|
3390
3426
|
const height = Math.max(1, venue.backgroundImageHeight ?? venue.bounds.height);
|
|
@@ -3397,6 +3433,129 @@ function getBackgroundRectInWorld(venue) {
|
|
|
3397
3433
|
height
|
|
3398
3434
|
};
|
|
3399
3435
|
}
|
|
3436
|
+
var MOTION_SETTINGS_STORAGE_KEY = "seatmap-editor-motion-settings-v1";
|
|
3437
|
+
var DEFAULT_MOTION_SETTINGS = {
|
|
3438
|
+
sectionDrawJelly: 46,
|
|
3439
|
+
fitViewJelly: 52,
|
|
3440
|
+
panInertiaJelly: 55,
|
|
3441
|
+
pointerScrollZoomJelly: 52,
|
|
3442
|
+
useAdvancedMotion: false,
|
|
3443
|
+
sectionDrawDurationMs: 620,
|
|
3444
|
+
sectionDrawCenterPullPct: 22,
|
|
3445
|
+
sectionDrawZoomBoostPct: 5,
|
|
3446
|
+
sectionDrawOvershootPct: 72,
|
|
3447
|
+
fitViewDurationMs: 680,
|
|
3448
|
+
fitViewOvershootPct: 90,
|
|
3449
|
+
panInertiaCarryPct: 73,
|
|
3450
|
+
panInertiaFrictionPct: 92,
|
|
3451
|
+
panInertiaMinSpeedMilli: 10,
|
|
3452
|
+
panVelocityBlendPct: 30,
|
|
3453
|
+
panStopDeltaMilli: 300,
|
|
3454
|
+
panReleaseIdleMs: 90,
|
|
3455
|
+
pointerScrollZoomDurationMs: 180,
|
|
3456
|
+
pointerScrollZoomStrengthPct: 22,
|
|
3457
|
+
pointerScrollZoomDeltaDivisor: 680
|
|
3458
|
+
};
|
|
3459
|
+
function clampPercent(n) {
|
|
3460
|
+
return Math.max(0, Math.min(100, n));
|
|
3461
|
+
}
|
|
3462
|
+
function clampRange(n, min, max) {
|
|
3463
|
+
return Math.max(min, Math.min(max, n));
|
|
3464
|
+
}
|
|
3465
|
+
function loadMotionSettings() {
|
|
3466
|
+
if (typeof window === "undefined") return DEFAULT_MOTION_SETTINGS;
|
|
3467
|
+
try {
|
|
3468
|
+
const raw = window.localStorage.getItem(MOTION_SETTINGS_STORAGE_KEY);
|
|
3469
|
+
if (!raw) return DEFAULT_MOTION_SETTINGS;
|
|
3470
|
+
const parsed = JSON.parse(raw);
|
|
3471
|
+
return {
|
|
3472
|
+
sectionDrawJelly: clampPercent(Number(parsed.sectionDrawJelly ?? DEFAULT_MOTION_SETTINGS.sectionDrawJelly)),
|
|
3473
|
+
fitViewJelly: clampPercent(Number(parsed.fitViewJelly ?? DEFAULT_MOTION_SETTINGS.fitViewJelly)),
|
|
3474
|
+
panInertiaJelly: clampPercent(Number(parsed.panInertiaJelly ?? DEFAULT_MOTION_SETTINGS.panInertiaJelly)),
|
|
3475
|
+
pointerScrollZoomJelly: clampPercent(
|
|
3476
|
+
Number(parsed.pointerScrollZoomJelly ?? DEFAULT_MOTION_SETTINGS.pointerScrollZoomJelly)
|
|
3477
|
+
),
|
|
3478
|
+
useAdvancedMotion: Boolean(parsed.useAdvancedMotion ?? DEFAULT_MOTION_SETTINGS.useAdvancedMotion),
|
|
3479
|
+
sectionDrawDurationMs: clampRange(
|
|
3480
|
+
Number(parsed.sectionDrawDurationMs ?? DEFAULT_MOTION_SETTINGS.sectionDrawDurationMs),
|
|
3481
|
+
100,
|
|
3482
|
+
3e3
|
|
3483
|
+
),
|
|
3484
|
+
sectionDrawCenterPullPct: clampRange(
|
|
3485
|
+
Number(parsed.sectionDrawCenterPullPct ?? DEFAULT_MOTION_SETTINGS.sectionDrawCenterPullPct),
|
|
3486
|
+
0,
|
|
3487
|
+
100
|
|
3488
|
+
),
|
|
3489
|
+
sectionDrawZoomBoostPct: clampRange(
|
|
3490
|
+
Number(parsed.sectionDrawZoomBoostPct ?? DEFAULT_MOTION_SETTINGS.sectionDrawZoomBoostPct),
|
|
3491
|
+
0,
|
|
3492
|
+
50
|
|
3493
|
+
),
|
|
3494
|
+
sectionDrawOvershootPct: clampRange(
|
|
3495
|
+
Number(parsed.sectionDrawOvershootPct ?? DEFAULT_MOTION_SETTINGS.sectionDrawOvershootPct),
|
|
3496
|
+
0,
|
|
3497
|
+
180
|
|
3498
|
+
),
|
|
3499
|
+
fitViewDurationMs: clampRange(
|
|
3500
|
+
Number(parsed.fitViewDurationMs ?? DEFAULT_MOTION_SETTINGS.fitViewDurationMs),
|
|
3501
|
+
100,
|
|
3502
|
+
3e3
|
|
3503
|
+
),
|
|
3504
|
+
fitViewOvershootPct: clampRange(
|
|
3505
|
+
Number(parsed.fitViewOvershootPct ?? DEFAULT_MOTION_SETTINGS.fitViewOvershootPct),
|
|
3506
|
+
0,
|
|
3507
|
+
180
|
|
3508
|
+
),
|
|
3509
|
+
panInertiaCarryPct: clampRange(
|
|
3510
|
+
Number(parsed.panInertiaCarryPct ?? DEFAULT_MOTION_SETTINGS.panInertiaCarryPct),
|
|
3511
|
+
0,
|
|
3512
|
+
95
|
|
3513
|
+
),
|
|
3514
|
+
panInertiaFrictionPct: clampRange(
|
|
3515
|
+
Number(parsed.panInertiaFrictionPct ?? DEFAULT_MOTION_SETTINGS.panInertiaFrictionPct),
|
|
3516
|
+
70,
|
|
3517
|
+
99
|
|
3518
|
+
),
|
|
3519
|
+
panInertiaMinSpeedMilli: clampRange(
|
|
3520
|
+
Number(parsed.panInertiaMinSpeedMilli ?? DEFAULT_MOTION_SETTINGS.panInertiaMinSpeedMilli),
|
|
3521
|
+
1,
|
|
3522
|
+
50
|
|
3523
|
+
),
|
|
3524
|
+
panVelocityBlendPct: clampRange(
|
|
3525
|
+
Number(parsed.panVelocityBlendPct ?? DEFAULT_MOTION_SETTINGS.panVelocityBlendPct),
|
|
3526
|
+
5,
|
|
3527
|
+
95
|
|
3528
|
+
),
|
|
3529
|
+
panStopDeltaMilli: clampRange(
|
|
3530
|
+
Number(parsed.panStopDeltaMilli ?? DEFAULT_MOTION_SETTINGS.panStopDeltaMilli),
|
|
3531
|
+
0,
|
|
3532
|
+
4e3
|
|
3533
|
+
),
|
|
3534
|
+
panReleaseIdleMs: clampRange(
|
|
3535
|
+
Number(parsed.panReleaseIdleMs ?? DEFAULT_MOTION_SETTINGS.panReleaseIdleMs),
|
|
3536
|
+
0,
|
|
3537
|
+
400
|
|
3538
|
+
),
|
|
3539
|
+
pointerScrollZoomDurationMs: clampRange(
|
|
3540
|
+
Number(parsed.pointerScrollZoomDurationMs ?? DEFAULT_MOTION_SETTINGS.pointerScrollZoomDurationMs),
|
|
3541
|
+
60,
|
|
3542
|
+
600
|
|
3543
|
+
),
|
|
3544
|
+
pointerScrollZoomStrengthPct: clampRange(
|
|
3545
|
+
Number(parsed.pointerScrollZoomStrengthPct ?? DEFAULT_MOTION_SETTINGS.pointerScrollZoomStrengthPct),
|
|
3546
|
+
8,
|
|
3547
|
+
55
|
|
3548
|
+
),
|
|
3549
|
+
pointerScrollZoomDeltaDivisor: clampRange(
|
|
3550
|
+
Number(parsed.pointerScrollZoomDeltaDivisor ?? DEFAULT_MOTION_SETTINGS.pointerScrollZoomDeltaDivisor),
|
|
3551
|
+
250,
|
|
3552
|
+
1400
|
|
3553
|
+
)
|
|
3554
|
+
};
|
|
3555
|
+
} catch {
|
|
3556
|
+
return DEFAULT_MOTION_SETTINGS;
|
|
3557
|
+
}
|
|
3558
|
+
}
|
|
3400
3559
|
function PolygonPreviewOverlay({
|
|
3401
3560
|
points,
|
|
3402
3561
|
closeable,
|
|
@@ -3408,59 +3567,53 @@ function PolygonPreviewOverlay({
|
|
|
3408
3567
|
const svgPoints = screenPoints.map((p) => `${p.x},${p.y}`).join(" ");
|
|
3409
3568
|
const first = screenPoints[0];
|
|
3410
3569
|
const last = screenPoints[screenPoints.length - 1];
|
|
3570
|
+
const isRectanglePreview = mode === "rectangle" && screenPoints.length >= 3;
|
|
3411
3571
|
return /* @__PURE__ */ jsxs(
|
|
3412
3572
|
"svg",
|
|
3413
3573
|
{
|
|
3414
|
-
|
|
3415
|
-
position: "absolute",
|
|
3416
|
-
inset: 0,
|
|
3417
|
-
width: "100%",
|
|
3418
|
-
height: "100%",
|
|
3419
|
-
pointerEvents: "none",
|
|
3420
|
-
zIndex: 10
|
|
3421
|
-
},
|
|
3574
|
+
className: "seatmap-editor__overlay-svg seatmap-editor__overlay-svg--polygon",
|
|
3422
3575
|
children: [
|
|
3423
|
-
screenPoints.length >= 2 && /* @__PURE__ */ jsx(
|
|
3576
|
+
screenPoints.length >= 2 && (isRectanglePreview ? /* @__PURE__ */ jsx(
|
|
3577
|
+
"polygon",
|
|
3578
|
+
{
|
|
3579
|
+
className: "seatmap-editor__overlay-polygon",
|
|
3580
|
+
points: svgPoints
|
|
3581
|
+
}
|
|
3582
|
+
) : /* @__PURE__ */ jsx(
|
|
3424
3583
|
"polyline",
|
|
3425
3584
|
{
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
stroke: "rgba(100, 180, 255, 0.8)",
|
|
3429
|
-
strokeWidth: 2,
|
|
3430
|
-
strokeDasharray: "6 4"
|
|
3585
|
+
className: "seatmap-editor__overlay-polyline",
|
|
3586
|
+
points: svgPoints
|
|
3431
3587
|
}
|
|
3432
|
-
),
|
|
3588
|
+
)),
|
|
3433
3589
|
mode === "polygon" && screenPoints.length >= 3 && /* @__PURE__ */ jsx(
|
|
3434
3590
|
"line",
|
|
3435
3591
|
{
|
|
3592
|
+
className: `seatmap-editor__overlay-close-line ${closeable ? "seatmap-editor__overlay-close-line--active" : "seatmap-editor__overlay-close-line--inactive"}`,
|
|
3436
3593
|
x1: last.x,
|
|
3437
3594
|
y1: last.y,
|
|
3438
3595
|
x2: first.x,
|
|
3439
3596
|
y2: first.y,
|
|
3440
|
-
stroke: closeable ? "rgba(100, 255, 100, 0.8)" : "rgba(100, 180, 255, 0.3)",
|
|
3441
|
-
strokeWidth: closeable ? 2 : 1,
|
|
3442
3597
|
strokeDasharray: "4 4"
|
|
3443
3598
|
}
|
|
3444
3599
|
),
|
|
3445
3600
|
mode === "polygon" && screenPoints.map((p, i) => /* @__PURE__ */ jsx(
|
|
3446
3601
|
"circle",
|
|
3447
3602
|
{
|
|
3603
|
+
className: `seatmap-editor__overlay-point${i === 0 && closeable ? " seatmap-editor__overlay-point--first-active" : ""}`,
|
|
3448
3604
|
cx: p.x,
|
|
3449
3605
|
cy: p.y,
|
|
3450
|
-
r: i === 0 && closeable ? 8 : 4
|
|
3451
|
-
fill: i === 0 && closeable ? "rgba(100, 255, 100, 0.8)" : "rgba(100, 180, 255, 0.8)"
|
|
3606
|
+
r: i === 0 && closeable ? 8 : 4
|
|
3452
3607
|
},
|
|
3453
3608
|
i
|
|
3454
3609
|
)),
|
|
3455
3610
|
mode === "polygon" && points.length >= 2 && /* @__PURE__ */ jsxs(
|
|
3456
3611
|
"text",
|
|
3457
3612
|
{
|
|
3613
|
+
className: "seatmap-editor__overlay-label-text",
|
|
3458
3614
|
x: (first.x + last.x) / 2,
|
|
3459
3615
|
y: (first.y + last.y) / 2 - 10,
|
|
3460
|
-
fill: "#e0e0e0",
|
|
3461
3616
|
fontSize: 12,
|
|
3462
|
-
fontFamily: "system-ui",
|
|
3463
|
-
textAnchor: "middle",
|
|
3464
3617
|
children: [
|
|
3465
3618
|
points.length,
|
|
3466
3619
|
" points ",
|
|
@@ -3485,35 +3638,23 @@ function DragPreviewOverlay({
|
|
|
3485
3638
|
return /* @__PURE__ */ jsxs(
|
|
3486
3639
|
"svg",
|
|
3487
3640
|
{
|
|
3488
|
-
|
|
3489
|
-
position: "absolute",
|
|
3490
|
-
inset: 0,
|
|
3491
|
-
width: "100%",
|
|
3492
|
-
height: "100%",
|
|
3493
|
-
pointerEvents: "none",
|
|
3494
|
-
zIndex: 14
|
|
3495
|
-
},
|
|
3641
|
+
className: "seatmap-editor__overlay-svg seatmap-editor__overlay-svg--drag",
|
|
3496
3642
|
children: [
|
|
3497
3643
|
sectionScreenOutlines.filter((outline) => outline.length >= 3).map((outline, i) => /* @__PURE__ */ jsx(
|
|
3498
3644
|
"polygon",
|
|
3499
3645
|
{
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
stroke: "rgba(110, 190, 255, 0.95)",
|
|
3503
|
-
strokeWidth: 2,
|
|
3504
|
-
strokeDasharray: "8 6"
|
|
3646
|
+
className: "seatmap-editor__overlay-drag-outline",
|
|
3647
|
+
points: outline.map((p) => `${p.x},${p.y}`).join(" ")
|
|
3505
3648
|
},
|
|
3506
3649
|
i
|
|
3507
3650
|
)),
|
|
3508
3651
|
seatScreenPoints.map((p, i) => /* @__PURE__ */ jsx(
|
|
3509
3652
|
"circle",
|
|
3510
3653
|
{
|
|
3654
|
+
className: "seatmap-editor__overlay-drag-seat",
|
|
3511
3655
|
cx: p.x,
|
|
3512
3656
|
cy: p.y,
|
|
3513
|
-
r: 5
|
|
3514
|
-
fill: "rgba(110, 190, 255, 0.35)",
|
|
3515
|
-
stroke: "rgba(110, 190, 255, 0.95)",
|
|
3516
|
-
strokeWidth: 1.5
|
|
3657
|
+
r: 5
|
|
3517
3658
|
},
|
|
3518
3659
|
i
|
|
3519
3660
|
))
|
|
@@ -3539,6 +3680,8 @@ function EditorInner({
|
|
|
3539
3680
|
const backgroundResizeAnchorRef = useRef(null);
|
|
3540
3681
|
const backgroundMoveOffsetRef = useRef(null);
|
|
3541
3682
|
const historyRef = useRef(new CommandHistory());
|
|
3683
|
+
const fitViewRafRef = useRef(0);
|
|
3684
|
+
const applyMotionSyncRafRef = useRef(0);
|
|
3542
3685
|
const [canUndo, setCanUndo] = useState(false);
|
|
3543
3686
|
const [canRedo, setCanRedo] = useState(false);
|
|
3544
3687
|
const panTool = useMemo(() => new PanTool(), []);
|
|
@@ -3582,17 +3725,209 @@ function EditorInner({
|
|
|
3582
3725
|
const sectionResizeReturnToAddSectionRef = useRef(false);
|
|
3583
3726
|
const [, setDragPreviewVersion] = useState(0);
|
|
3584
3727
|
const [sectionMode, setSectionMode] = useState("rectangle");
|
|
3728
|
+
const [sectionKind, setSectionKind] = useState("section");
|
|
3585
3729
|
const [sectionResizeEnabled, setSectionResizeEnabled] = useState(false);
|
|
3730
|
+
const [autoFocusNewSection, setAutoFocusNewSection] = useState(true);
|
|
3586
3731
|
const [gridEnabled, setGridEnabled] = useState(false);
|
|
3587
3732
|
const [isGridOptionsOpen, setIsGridOptionsOpen] = useState(false);
|
|
3588
3733
|
const [showCanvasGrid, setShowCanvasGrid] = useState(false);
|
|
3589
3734
|
const [canvasGridStyle, setCanvasGridStyle] = useState("solid");
|
|
3590
3735
|
const [showSectionGrid, setShowSectionGrid] = useState(true);
|
|
3591
3736
|
const [sectionGridStyle, setSectionGridStyle] = useState("dots");
|
|
3737
|
+
const [showHints, setShowHints] = useState(true);
|
|
3738
|
+
const [isEditorSettingsOpen, setIsEditorSettingsOpen] = useState(false);
|
|
3739
|
+
const motionSettings = useMemo(() => loadMotionSettings(), []);
|
|
3740
|
+
const [sectionDrawJelly, setSectionDrawJelly] = useState(motionSettings.sectionDrawJelly);
|
|
3741
|
+
const [fitViewJelly, setFitViewJelly] = useState(motionSettings.fitViewJelly);
|
|
3742
|
+
const [panInertiaJelly, setPanInertiaJelly] = useState(motionSettings.panInertiaJelly);
|
|
3743
|
+
const [pointerScrollZoomJelly, setPointerScrollZoomJelly] = useState(motionSettings.pointerScrollZoomJelly);
|
|
3744
|
+
const [useAdvancedMotion, setUseAdvancedMotion] = useState(motionSettings.useAdvancedMotion);
|
|
3745
|
+
const [sectionDrawDurationMs, setSectionDrawDurationMs] = useState(motionSettings.sectionDrawDurationMs);
|
|
3746
|
+
const [sectionDrawCenterPullPct, setSectionDrawCenterPullPct] = useState(motionSettings.sectionDrawCenterPullPct);
|
|
3747
|
+
const [sectionDrawZoomBoostPct, setSectionDrawZoomBoostPct] = useState(motionSettings.sectionDrawZoomBoostPct);
|
|
3748
|
+
const [sectionDrawOvershootPct, setSectionDrawOvershootPct] = useState(motionSettings.sectionDrawOvershootPct);
|
|
3749
|
+
const [fitViewDurationMs, setFitViewDurationMs] = useState(motionSettings.fitViewDurationMs);
|
|
3750
|
+
const [fitViewOvershootPct, setFitViewOvershootPct] = useState(motionSettings.fitViewOvershootPct);
|
|
3751
|
+
const [panInertiaCarryPct, setPanInertiaCarryPct] = useState(motionSettings.panInertiaCarryPct);
|
|
3752
|
+
const [panInertiaFrictionPct, setPanInertiaFrictionPct] = useState(motionSettings.panInertiaFrictionPct);
|
|
3753
|
+
const [panInertiaMinSpeedMilli, setPanInertiaMinSpeedMilli] = useState(motionSettings.panInertiaMinSpeedMilli);
|
|
3754
|
+
const [panVelocityBlendPct, setPanVelocityBlendPct] = useState(motionSettings.panVelocityBlendPct);
|
|
3755
|
+
const [panStopDeltaMilli, setPanStopDeltaMilli] = useState(motionSettings.panStopDeltaMilli);
|
|
3756
|
+
const [panReleaseIdleMs, setPanReleaseIdleMs] = useState(motionSettings.panReleaseIdleMs);
|
|
3757
|
+
const [pointerScrollZoomDurationMs, setPointerScrollZoomDurationMs] = useState(motionSettings.pointerScrollZoomDurationMs);
|
|
3758
|
+
const [pointerScrollZoomStrengthPct, setPointerScrollZoomStrengthPct] = useState(motionSettings.pointerScrollZoomStrengthPct);
|
|
3759
|
+
const [pointerScrollZoomDeltaDivisor, setPointerScrollZoomDeltaDivisor] = useState(motionSettings.pointerScrollZoomDeltaDivisor);
|
|
3592
3760
|
const [seatsPerRow, setSeatsPerRow] = useState(10);
|
|
3593
3761
|
const [rowsCount, setRowsCount] = useState(1);
|
|
3594
3762
|
const [rowOrientationDeg, setRowOrientationDeg] = useState(0);
|
|
3763
|
+
const [rowDirectionArrowMode, setRowDirectionArrowMode] = useState("row-direction");
|
|
3595
3764
|
const [rowPreviewPoint, setRowPreviewPoint] = useState(null);
|
|
3765
|
+
const [cursorScreenPoint, setCursorScreenPoint] = useState(null);
|
|
3766
|
+
useEffect(() => {
|
|
3767
|
+
if (typeof window === "undefined") return;
|
|
3768
|
+
const payload = {
|
|
3769
|
+
sectionDrawJelly,
|
|
3770
|
+
fitViewJelly,
|
|
3771
|
+
panInertiaJelly,
|
|
3772
|
+
pointerScrollZoomJelly,
|
|
3773
|
+
useAdvancedMotion,
|
|
3774
|
+
sectionDrawDurationMs,
|
|
3775
|
+
sectionDrawCenterPullPct,
|
|
3776
|
+
sectionDrawZoomBoostPct,
|
|
3777
|
+
sectionDrawOvershootPct,
|
|
3778
|
+
fitViewDurationMs,
|
|
3779
|
+
fitViewOvershootPct,
|
|
3780
|
+
panInertiaCarryPct,
|
|
3781
|
+
panInertiaFrictionPct,
|
|
3782
|
+
panInertiaMinSpeedMilli,
|
|
3783
|
+
panVelocityBlendPct,
|
|
3784
|
+
panStopDeltaMilli,
|
|
3785
|
+
panReleaseIdleMs,
|
|
3786
|
+
pointerScrollZoomDurationMs,
|
|
3787
|
+
pointerScrollZoomStrengthPct,
|
|
3788
|
+
pointerScrollZoomDeltaDivisor
|
|
3789
|
+
};
|
|
3790
|
+
window.localStorage.setItem(MOTION_SETTINGS_STORAGE_KEY, JSON.stringify(payload));
|
|
3791
|
+
}, [
|
|
3792
|
+
sectionDrawJelly,
|
|
3793
|
+
fitViewJelly,
|
|
3794
|
+
panInertiaJelly,
|
|
3795
|
+
pointerScrollZoomJelly,
|
|
3796
|
+
useAdvancedMotion,
|
|
3797
|
+
sectionDrawDurationMs,
|
|
3798
|
+
sectionDrawCenterPullPct,
|
|
3799
|
+
sectionDrawZoomBoostPct,
|
|
3800
|
+
sectionDrawOvershootPct,
|
|
3801
|
+
fitViewDurationMs,
|
|
3802
|
+
fitViewOvershootPct,
|
|
3803
|
+
panInertiaCarryPct,
|
|
3804
|
+
panInertiaFrictionPct,
|
|
3805
|
+
panInertiaMinSpeedMilli,
|
|
3806
|
+
panVelocityBlendPct,
|
|
3807
|
+
panStopDeltaMilli,
|
|
3808
|
+
panReleaseIdleMs,
|
|
3809
|
+
pointerScrollZoomDurationMs,
|
|
3810
|
+
pointerScrollZoomStrengthPct,
|
|
3811
|
+
pointerScrollZoomDeltaDivisor
|
|
3812
|
+
]);
|
|
3813
|
+
useEffect(() => {
|
|
3814
|
+
panTool.setInertiaOptions({
|
|
3815
|
+
panInertiaJelly,
|
|
3816
|
+
panInertiaCarry: useAdvancedMotion ? panInertiaCarryPct / 100 : void 0,
|
|
3817
|
+
panInertiaFriction: useAdvancedMotion ? panInertiaFrictionPct / 100 : void 0,
|
|
3818
|
+
panInertiaMinSpeed: useAdvancedMotion ? panInertiaMinSpeedMilli / 1e3 : void 0,
|
|
3819
|
+
panVelocityBlend: useAdvancedMotion ? panVelocityBlendPct / 100 : void 0,
|
|
3820
|
+
panStopDelta: useAdvancedMotion ? panStopDeltaMilli / 1e3 : void 0,
|
|
3821
|
+
panReleaseIdleMs: useAdvancedMotion ? panReleaseIdleMs : void 0
|
|
3822
|
+
});
|
|
3823
|
+
}, [
|
|
3824
|
+
panTool,
|
|
3825
|
+
panInertiaJelly,
|
|
3826
|
+
useAdvancedMotion,
|
|
3827
|
+
panInertiaCarryPct,
|
|
3828
|
+
panInertiaFrictionPct,
|
|
3829
|
+
panInertiaMinSpeedMilli,
|
|
3830
|
+
panVelocityBlendPct,
|
|
3831
|
+
panStopDeltaMilli,
|
|
3832
|
+
panReleaseIdleMs
|
|
3833
|
+
]);
|
|
3834
|
+
const handleResetMotionSettings = useCallback(() => {
|
|
3835
|
+
setSectionDrawJelly(DEFAULT_MOTION_SETTINGS.sectionDrawJelly);
|
|
3836
|
+
setFitViewJelly(DEFAULT_MOTION_SETTINGS.fitViewJelly);
|
|
3837
|
+
setPanInertiaJelly(DEFAULT_MOTION_SETTINGS.panInertiaJelly);
|
|
3838
|
+
setPointerScrollZoomJelly(DEFAULT_MOTION_SETTINGS.pointerScrollZoomJelly);
|
|
3839
|
+
setUseAdvancedMotion(DEFAULT_MOTION_SETTINGS.useAdvancedMotion);
|
|
3840
|
+
setSectionDrawDurationMs(DEFAULT_MOTION_SETTINGS.sectionDrawDurationMs);
|
|
3841
|
+
setSectionDrawCenterPullPct(DEFAULT_MOTION_SETTINGS.sectionDrawCenterPullPct);
|
|
3842
|
+
setSectionDrawZoomBoostPct(DEFAULT_MOTION_SETTINGS.sectionDrawZoomBoostPct);
|
|
3843
|
+
setSectionDrawOvershootPct(DEFAULT_MOTION_SETTINGS.sectionDrawOvershootPct);
|
|
3844
|
+
setFitViewDurationMs(DEFAULT_MOTION_SETTINGS.fitViewDurationMs);
|
|
3845
|
+
setFitViewOvershootPct(DEFAULT_MOTION_SETTINGS.fitViewOvershootPct);
|
|
3846
|
+
setPanInertiaCarryPct(DEFAULT_MOTION_SETTINGS.panInertiaCarryPct);
|
|
3847
|
+
setPanInertiaFrictionPct(DEFAULT_MOTION_SETTINGS.panInertiaFrictionPct);
|
|
3848
|
+
setPanInertiaMinSpeedMilli(DEFAULT_MOTION_SETTINGS.panInertiaMinSpeedMilli);
|
|
3849
|
+
setPanVelocityBlendPct(DEFAULT_MOTION_SETTINGS.panVelocityBlendPct);
|
|
3850
|
+
setPanStopDeltaMilli(DEFAULT_MOTION_SETTINGS.panStopDeltaMilli);
|
|
3851
|
+
setPanReleaseIdleMs(DEFAULT_MOTION_SETTINGS.panReleaseIdleMs);
|
|
3852
|
+
setPointerScrollZoomDurationMs(DEFAULT_MOTION_SETTINGS.pointerScrollZoomDurationMs);
|
|
3853
|
+
setPointerScrollZoomStrengthPct(DEFAULT_MOTION_SETTINGS.pointerScrollZoomStrengthPct);
|
|
3854
|
+
setPointerScrollZoomDeltaDivisor(DEFAULT_MOTION_SETTINGS.pointerScrollZoomDeltaDivisor);
|
|
3855
|
+
}, []);
|
|
3856
|
+
const animateBasicKnobValues = useCallback((targets) => {
|
|
3857
|
+
if (applyMotionSyncRafRef.current) {
|
|
3858
|
+
cancelAnimationFrame(applyMotionSyncRafRef.current);
|
|
3859
|
+
applyMotionSyncRafRef.current = 0;
|
|
3860
|
+
}
|
|
3861
|
+
const start = {
|
|
3862
|
+
section: sectionDrawJelly,
|
|
3863
|
+
fit: fitViewJelly,
|
|
3864
|
+
pan: panInertiaJelly,
|
|
3865
|
+
pointerZoom: pointerScrollZoomJelly
|
|
3866
|
+
};
|
|
3867
|
+
const startedAt = performance.now();
|
|
3868
|
+
const durationMs = 260;
|
|
3869
|
+
const easeOutCubicLocal = (t) => 1 - (1 - t) * (1 - t) * (1 - t);
|
|
3870
|
+
const tick = (now) => {
|
|
3871
|
+
const progress = Math.min(1, (now - startedAt) / durationMs);
|
|
3872
|
+
const eased = easeOutCubicLocal(progress);
|
|
3873
|
+
const nextSection = Math.round(start.section + (targets.section - start.section) * eased);
|
|
3874
|
+
const nextFit = Math.round(start.fit + (targets.fit - start.fit) * eased);
|
|
3875
|
+
const nextPan = Math.round(start.pan + (targets.pan - start.pan) * eased);
|
|
3876
|
+
const nextPointerZoom = Math.round(start.pointerZoom + (targets.pointerZoom - start.pointerZoom) * eased);
|
|
3877
|
+
setSectionDrawJelly(clampPercent(nextSection));
|
|
3878
|
+
setFitViewJelly(clampPercent(nextFit));
|
|
3879
|
+
setPanInertiaJelly(clampPercent(nextPan));
|
|
3880
|
+
setPointerScrollZoomJelly(clampPercent(nextPointerZoom));
|
|
3881
|
+
if (progress < 1) {
|
|
3882
|
+
applyMotionSyncRafRef.current = requestAnimationFrame(tick);
|
|
3883
|
+
return;
|
|
3884
|
+
}
|
|
3885
|
+
applyMotionSyncRafRef.current = 0;
|
|
3886
|
+
};
|
|
3887
|
+
applyMotionSyncRafRef.current = requestAnimationFrame(tick);
|
|
3888
|
+
}, [sectionDrawJelly, fitViewJelly, panInertiaJelly, pointerScrollZoomJelly]);
|
|
3889
|
+
const handleApplyAdvancedToBasic = useCallback(() => {
|
|
3890
|
+
const sectionFromZoomBoost = (clampRange(sectionDrawZoomBoostPct, 0, 50) / 100 - 0.01) / 0.08;
|
|
3891
|
+
const sectionFromCenterPull = (clampRange(sectionDrawCenterPullPct, 0, 100) / 100 - 0.12) / 0.22;
|
|
3892
|
+
const sectionFromDuration = (clampRange(sectionDrawDurationMs, 100, 3e3) - 380) / 520;
|
|
3893
|
+
const sectionFromOvershoot = (clampRange(sectionDrawOvershootPct, 0, 180) / 100 - 0.08) / 0.48;
|
|
3894
|
+
const nextSectionDrawJelly = clampPercent(
|
|
3895
|
+
Math.round((sectionFromZoomBoost + sectionFromCenterPull + sectionFromDuration + sectionFromOvershoot) / 4 * 100)
|
|
3896
|
+
);
|
|
3897
|
+
const fitFromDuration = (clampRange(fitViewDurationMs, 100, 3e3) - 360) / 620;
|
|
3898
|
+
const fitFromOvershoot = (clampRange(fitViewOvershootPct, 0, 180) / 100 - 0.2) / 0.9;
|
|
3899
|
+
const nextFitViewJelly = clampPercent(Math.round((fitFromDuration + fitFromOvershoot) / 2 * 100));
|
|
3900
|
+
const panFromCarry = (clampRange(panInertiaCarryPct, 0, 95) / 100 - 0.58) / 0.28;
|
|
3901
|
+
const panFromFriction = (clampRange(panInertiaFrictionPct, 70, 99) / 100 - 0.88) / 0.08;
|
|
3902
|
+
const panFromMinSpeed = (0.012 - clampRange(panInertiaMinSpeedMilli, 1, 50) / 1e3) / 4e-3;
|
|
3903
|
+
const nextPanInertiaJelly = clampPercent(Math.round((panFromCarry + panFromFriction + panFromMinSpeed) / 3 * 100));
|
|
3904
|
+
const zoomFromDuration = (clampRange(pointerScrollZoomDurationMs, 60, 600) - 90) / 220;
|
|
3905
|
+
const zoomFromSensitivity = (clampRange(pointerScrollZoomDeltaDivisor, 250, 1400) - 520) / 380;
|
|
3906
|
+
const zoomFromStrength = (0.33 - clampRange(pointerScrollZoomStrengthPct, 8, 55) / 100) / 0.14;
|
|
3907
|
+
const nextPointerScrollZoomJelly = clampPercent(
|
|
3908
|
+
Math.round((zoomFromDuration + zoomFromSensitivity + zoomFromStrength) / 3 * 100)
|
|
3909
|
+
);
|
|
3910
|
+
animateBasicKnobValues({
|
|
3911
|
+
section: nextSectionDrawJelly,
|
|
3912
|
+
fit: nextFitViewJelly,
|
|
3913
|
+
pan: nextPanInertiaJelly,
|
|
3914
|
+
pointerZoom: nextPointerScrollZoomJelly
|
|
3915
|
+
});
|
|
3916
|
+
}, [
|
|
3917
|
+
animateBasicKnobValues,
|
|
3918
|
+
sectionDrawZoomBoostPct,
|
|
3919
|
+
sectionDrawCenterPullPct,
|
|
3920
|
+
sectionDrawDurationMs,
|
|
3921
|
+
sectionDrawOvershootPct,
|
|
3922
|
+
fitViewDurationMs,
|
|
3923
|
+
fitViewOvershootPct,
|
|
3924
|
+
panInertiaCarryPct,
|
|
3925
|
+
panInertiaFrictionPct,
|
|
3926
|
+
panInertiaMinSpeedMilli,
|
|
3927
|
+
pointerScrollZoomDurationMs,
|
|
3928
|
+
pointerScrollZoomStrengthPct,
|
|
3929
|
+
pointerScrollZoomDeltaDivisor
|
|
3930
|
+
]);
|
|
3596
3931
|
const handleSeatsPerRowChange = useCallback(
|
|
3597
3932
|
(n) => {
|
|
3598
3933
|
setSeatsPerRow(n);
|
|
@@ -3622,8 +3957,20 @@ function EditorInner({
|
|
|
3622
3957
|
},
|
|
3623
3958
|
[handleRowOrientationChange, rowOrientationDeg]
|
|
3624
3959
|
);
|
|
3625
|
-
const
|
|
3626
|
-
(
|
|
3960
|
+
const rowOrientationKnobDeg = useMemo(
|
|
3961
|
+
() => rowDirectionArrowMode === "row-direction" ? ((rowOrientationDeg + 90) % 360 + 360) % 360 : rowOrientationDeg,
|
|
3962
|
+
[rowDirectionArrowMode, rowOrientationDeg]
|
|
3963
|
+
);
|
|
3964
|
+
const handleRowOrientationKnobChange = useCallback(
|
|
3965
|
+
(deg) => {
|
|
3966
|
+
const mapped = rowDirectionArrowMode === "row-direction" ? deg - 90 : deg;
|
|
3967
|
+
handleRowOrientationChange(mapped);
|
|
3968
|
+
},
|
|
3969
|
+
[rowDirectionArrowMode, handleRowOrientationChange]
|
|
3970
|
+
);
|
|
3971
|
+
const handleSectionToolVariantChange = useCallback(
|
|
3972
|
+
(kind, mode) => {
|
|
3973
|
+
setSectionKind(kind);
|
|
3627
3974
|
setSectionMode(mode);
|
|
3628
3975
|
},
|
|
3629
3976
|
[]
|
|
@@ -3631,6 +3978,72 @@ function EditorInner({
|
|
|
3631
3978
|
useEffect(() => {
|
|
3632
3979
|
addSectionTool.setMode(sectionMode);
|
|
3633
3980
|
}, [addSectionTool, sectionMode]);
|
|
3981
|
+
useEffect(() => {
|
|
3982
|
+
addSectionTool.setSectionKind(sectionKind);
|
|
3983
|
+
}, [addSectionTool, sectionKind]);
|
|
3984
|
+
const focusSectionGently = useCallback(
|
|
3985
|
+
(sectionId) => {
|
|
3986
|
+
const currentVenue = store.getState().venue;
|
|
3987
|
+
if (!currentVenue) return;
|
|
3988
|
+
const section = currentVenue.sections.find((entry) => entry.id === sectionId);
|
|
3989
|
+
if (!section) return;
|
|
3990
|
+
if (viewport.screenWidth <= 0 || viewport.screenHeight <= 0) return;
|
|
3991
|
+
const startX = viewport.x;
|
|
3992
|
+
const startY = viewport.y;
|
|
3993
|
+
const startZoom = viewport.zoom;
|
|
3994
|
+
const jelly = Math.max(0, Math.min(100, sectionDrawJelly)) / 100;
|
|
3995
|
+
const zoomBoost = useAdvancedMotion ? clampRange(sectionDrawZoomBoostPct, 0, 50) / 100 : 0.01 + jelly * 0.08;
|
|
3996
|
+
const targetZoom = Math.min(4, Math.max(0.05, startZoom * (1 + zoomBoost)));
|
|
3997
|
+
const centeredX = viewport.screenWidth / (2 * targetZoom) - section.position.x;
|
|
3998
|
+
const centeredY = viewport.screenHeight / (2 * targetZoom) - section.position.y;
|
|
3999
|
+
const centerPull = useAdvancedMotion ? clampRange(sectionDrawCenterPullPct, 0, 100) / 100 : 0.12 + jelly * 0.22;
|
|
4000
|
+
const targetX = startX + (centeredX - startX) * centerPull;
|
|
4001
|
+
const targetY = startY + (centeredY - startY) * centerPull;
|
|
4002
|
+
const durationMs = useAdvancedMotion ? clampRange(sectionDrawDurationMs, 100, 3e3) : 380 + jelly * 520;
|
|
4003
|
+
const overshoot = useAdvancedMotion ? clampRange(sectionDrawOvershootPct, 0, 180) / 100 : 0.08 + jelly * 0.48;
|
|
4004
|
+
const startedAt = performance.now();
|
|
4005
|
+
const animate = (now) => {
|
|
4006
|
+
const elapsed = now - startedAt;
|
|
4007
|
+
const progress = Math.min(1, elapsed / durationMs);
|
|
4008
|
+
const eased = progress >= 1 ? 1 : easeOutBack(progress, overshoot);
|
|
4009
|
+
viewport.x = startX + (targetX - startX) * eased;
|
|
4010
|
+
viewport.y = startY + (targetY - startY) * eased;
|
|
4011
|
+
viewport.setZoom(startZoom + (targetZoom - startZoom) * eased);
|
|
4012
|
+
if (progress < 1) {
|
|
4013
|
+
requestAnimationFrame(animate);
|
|
4014
|
+
}
|
|
4015
|
+
};
|
|
4016
|
+
requestAnimationFrame(animate);
|
|
4017
|
+
},
|
|
4018
|
+
[store, viewport, sectionDrawJelly, useAdvancedMotion, sectionDrawZoomBoostPct, sectionDrawCenterPullPct, sectionDrawDurationMs, sectionDrawOvershootPct]
|
|
4019
|
+
);
|
|
4020
|
+
useEffect(() => {
|
|
4021
|
+
addSectionTool.onSectionCreated = (sectionId) => {
|
|
4022
|
+
if (!autoFocusNewSection) return;
|
|
4023
|
+
focusSectionGently(sectionId);
|
|
4024
|
+
};
|
|
4025
|
+
return () => {
|
|
4026
|
+
addSectionTool.onSectionCreated = void 0;
|
|
4027
|
+
};
|
|
4028
|
+
}, [addSectionTool, autoFocusNewSection, focusSectionGently]);
|
|
4029
|
+
const sectionHintText = useMemo(() => {
|
|
4030
|
+
if (activeToolName === "select" && sectionResizeEnabled) {
|
|
4031
|
+
return "Resize mode: drag inside section to move it, drag corners to resize, drag sides to move edges, click a side to add a polygon point.";
|
|
4032
|
+
}
|
|
4033
|
+
if (activeToolName !== "add-section") return null;
|
|
4034
|
+
if (sectionMode === "rectangle") {
|
|
4035
|
+
if (addSectionTool.hasPendingDraft()) {
|
|
4036
|
+
return "Click opposite corner to finish. Esc to cancel.";
|
|
4037
|
+
}
|
|
4038
|
+
return "Click first corner to start rectangle.";
|
|
4039
|
+
}
|
|
4040
|
+
if (addSectionTool.hasPendingDraft()) {
|
|
4041
|
+
return "Click to add points. Click first point to close. Esc to cancel.";
|
|
4042
|
+
}
|
|
4043
|
+
return "Click to place first polygon point.";
|
|
4044
|
+
}, [activeToolName, sectionMode, addSectionTool, sectionResizeEnabled]);
|
|
4045
|
+
const rowPresetRows = [1, 2, 3, 4];
|
|
4046
|
+
const rowPresetSeats = [8, 10, 12, 16];
|
|
3634
4047
|
useEffect(() => {
|
|
3635
4048
|
selectTool.setSectionResizeEnabled(sectionResizeEnabled);
|
|
3636
4049
|
}, [selectTool, sectionResizeEnabled]);
|
|
@@ -3644,13 +4057,17 @@ function EditorInner({
|
|
|
3644
4057
|
if (name !== "pan") {
|
|
3645
4058
|
lastNonPanToolNameRef.current = name;
|
|
3646
4059
|
}
|
|
4060
|
+
if (name !== activeToolName) {
|
|
4061
|
+
setIsGridOptionsOpen(false);
|
|
4062
|
+
setIsEditorSettingsOpen(false);
|
|
4063
|
+
}
|
|
3647
4064
|
activeToolRef.current.onDeactivate();
|
|
3648
4065
|
const tool = toolMap[name] ?? selectTool;
|
|
3649
4066
|
tool.onActivate(viewport, store);
|
|
3650
4067
|
activeToolRef.current = tool;
|
|
3651
4068
|
setActiveToolName(name);
|
|
3652
4069
|
},
|
|
3653
|
-
[toolMap, selectTool, viewport, store]
|
|
4070
|
+
[activeToolName, toolMap, selectTool, viewport, store]
|
|
3654
4071
|
);
|
|
3655
4072
|
const handleToggleSectionResize = useCallback(
|
|
3656
4073
|
(fromAddSection = false) => {
|
|
@@ -3721,10 +4138,52 @@ function EditorInner({
|
|
|
3721
4138
|
};
|
|
3722
4139
|
input.click();
|
|
3723
4140
|
}, [store, spatialIndex, viewport]);
|
|
4141
|
+
const stopFitViewAnimation = useCallback(() => {
|
|
4142
|
+
if (fitViewRafRef.current) {
|
|
4143
|
+
cancelAnimationFrame(fitViewRafRef.current);
|
|
4144
|
+
fitViewRafRef.current = 0;
|
|
4145
|
+
}
|
|
4146
|
+
}, []);
|
|
4147
|
+
const animateFitView = useCallback(
|
|
4148
|
+
(bounds) => {
|
|
4149
|
+
const target = getViewportStateForFitBounds(viewport, bounds, 40);
|
|
4150
|
+
if (!target) return;
|
|
4151
|
+
stopFitViewAnimation();
|
|
4152
|
+
const startX = viewport.x;
|
|
4153
|
+
const startY = viewport.y;
|
|
4154
|
+
const startZoom = viewport.zoom;
|
|
4155
|
+
const jelly = Math.max(0, Math.min(100, fitViewJelly)) / 100;
|
|
4156
|
+
const durationMs = useAdvancedMotion ? clampRange(fitViewDurationMs, 100, 3e3) : 360 + jelly * 620;
|
|
4157
|
+
const overshoot = useAdvancedMotion ? clampRange(fitViewOvershootPct, 0, 180) / 100 : 0.2 + jelly * 0.9;
|
|
4158
|
+
const startedAt = performance.now();
|
|
4159
|
+
const animate = (now) => {
|
|
4160
|
+
const elapsed = now - startedAt;
|
|
4161
|
+
const progress = Math.min(1, elapsed / durationMs);
|
|
4162
|
+
const eased = progress >= 1 ? 1 : easeOutBack(progress, overshoot);
|
|
4163
|
+
viewport.x = startX + (target.x - startX) * eased;
|
|
4164
|
+
viewport.y = startY + (target.y - startY) * eased;
|
|
4165
|
+
viewport.setZoom(startZoom + (target.zoom - startZoom) * eased);
|
|
4166
|
+
if (progress < 1) {
|
|
4167
|
+
fitViewRafRef.current = requestAnimationFrame(animate);
|
|
4168
|
+
return;
|
|
4169
|
+
}
|
|
4170
|
+
fitViewRafRef.current = 0;
|
|
4171
|
+
};
|
|
4172
|
+
fitViewRafRef.current = requestAnimationFrame(animate);
|
|
4173
|
+
},
|
|
4174
|
+
[viewport, stopFitViewAnimation, fitViewJelly, useAdvancedMotion, fitViewDurationMs, fitViewOvershootPct]
|
|
4175
|
+
);
|
|
3724
4176
|
const handleFitView = useCallback(() => {
|
|
3725
4177
|
if (!venue) return;
|
|
3726
|
-
|
|
3727
|
-
}, [venue,
|
|
4178
|
+
animateFitView(venueAABB(venue));
|
|
4179
|
+
}, [venue, animateFitView]);
|
|
4180
|
+
useEffect(() => () => stopFitViewAnimation(), [stopFitViewAnimation]);
|
|
4181
|
+
useEffect(() => () => {
|
|
4182
|
+
if (applyMotionSyncRafRef.current) {
|
|
4183
|
+
cancelAnimationFrame(applyMotionSyncRafRef.current);
|
|
4184
|
+
applyMotionSyncRafRef.current = 0;
|
|
4185
|
+
}
|
|
4186
|
+
}, []);
|
|
3728
4187
|
const handleUploadBackground = useCallback(() => {
|
|
3729
4188
|
const input = document.createElement("input");
|
|
3730
4189
|
input.type = "file";
|
|
@@ -4018,6 +4477,7 @@ function EditorInner({
|
|
|
4018
4477
|
}, [isBackgroundMoving, store, viewport]);
|
|
4019
4478
|
const renderBackgroundResizeOverlay = () => {
|
|
4020
4479
|
if (!venue?.backgroundImage) return null;
|
|
4480
|
+
if (activeToolName !== "select") return null;
|
|
4021
4481
|
const rectWorld = getBackgroundRectInWorld(venue);
|
|
4022
4482
|
const topLeft = viewport.worldToScreen(rectWorld.x, rectWorld.y);
|
|
4023
4483
|
const topRight = viewport.worldToScreen(rectWorld.x + rectWorld.width, rectWorld.y);
|
|
@@ -4037,19 +4497,16 @@ function EditorInner({
|
|
|
4037
4497
|
{ left: midTop.x, top: midTop.y, cursor: "ns-resize", handle: "n" },
|
|
4038
4498
|
{ left: midBottom.x, top: midBottom.y, cursor: "ns-resize", handle: "s" }
|
|
4039
4499
|
];
|
|
4040
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
4500
|
+
return /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__background-overlay", children: [
|
|
4041
4501
|
/* @__PURE__ */ jsx(
|
|
4042
4502
|
"div",
|
|
4043
4503
|
{
|
|
4504
|
+
className: "seatmap-editor__background-frame",
|
|
4044
4505
|
style: {
|
|
4045
|
-
position: "absolute",
|
|
4046
4506
|
left: topLeft.x,
|
|
4047
4507
|
top: topLeft.y,
|
|
4048
4508
|
width: Math.max(1, topRight.x - topLeft.x),
|
|
4049
4509
|
height: Math.max(1, bottomLeft.y - topLeft.y),
|
|
4050
|
-
border: "1px dashed rgba(130, 190, 255, 0.9)",
|
|
4051
|
-
boxShadow: "0 0 0 1px rgba(30, 30, 50, 0.8) inset",
|
|
4052
|
-
pointerEvents: "auto",
|
|
4053
4510
|
cursor: isBackgroundMoving ? "grabbing" : "grab"
|
|
4054
4511
|
},
|
|
4055
4512
|
onPointerDown: (e) => {
|
|
@@ -4075,17 +4532,11 @@ function EditorInner({
|
|
|
4075
4532
|
handles.map((handle, i) => /* @__PURE__ */ jsx(
|
|
4076
4533
|
"div",
|
|
4077
4534
|
{
|
|
4535
|
+
className: "seatmap-editor__background-handle",
|
|
4078
4536
|
style: {
|
|
4079
|
-
position: "absolute",
|
|
4080
4537
|
left: handle.left - 5,
|
|
4081
4538
|
top: handle.top - 5,
|
|
4082
|
-
|
|
4083
|
-
height: 10,
|
|
4084
|
-
borderRadius: 2,
|
|
4085
|
-
background: "#82beff",
|
|
4086
|
-
border: "1px solid #1f2f5f",
|
|
4087
|
-
cursor: handle.cursor,
|
|
4088
|
-
pointerEvents: "auto"
|
|
4539
|
+
cursor: handle.cursor
|
|
4089
4540
|
},
|
|
4090
4541
|
onPointerDown: (e) => {
|
|
4091
4542
|
if (e.button !== 0) return;
|
|
@@ -4125,48 +4576,34 @@ function EditorInner({
|
|
|
4125
4576
|
return /* @__PURE__ */ jsxs(
|
|
4126
4577
|
"svg",
|
|
4127
4578
|
{
|
|
4128
|
-
|
|
4129
|
-
position: "absolute",
|
|
4130
|
-
inset: 0,
|
|
4131
|
-
width: "100%",
|
|
4132
|
-
height: "100%",
|
|
4133
|
-
pointerEvents: "none",
|
|
4134
|
-
zIndex: 16
|
|
4135
|
-
},
|
|
4579
|
+
className: "seatmap-editor__overlay-svg seatmap-editor__overlay-svg--section-resize",
|
|
4136
4580
|
children: [
|
|
4137
4581
|
/* @__PURE__ */ jsx(
|
|
4138
4582
|
"polygon",
|
|
4139
4583
|
{
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
stroke: "rgba(255, 193, 110, 0.9)",
|
|
4143
|
-
strokeWidth: 1.5,
|
|
4144
|
-
strokeDasharray: "7 4"
|
|
4584
|
+
className: "seatmap-editor__overlay-section-outline",
|
|
4585
|
+
points: outlinePoints
|
|
4145
4586
|
}
|
|
4146
4587
|
),
|
|
4147
4588
|
sideMidpoints.map((p, i) => /* @__PURE__ */ jsx(
|
|
4148
4589
|
"rect",
|
|
4149
4590
|
{
|
|
4591
|
+
className: "seatmap-editor__overlay-section-side",
|
|
4150
4592
|
x: p.x - 5,
|
|
4151
4593
|
y: p.y - 5,
|
|
4152
4594
|
width: 10,
|
|
4153
4595
|
height: 10,
|
|
4154
|
-
rx: 2
|
|
4155
|
-
fill: "rgba(255, 193, 110, 0.9)",
|
|
4156
|
-
stroke: "rgba(45, 36, 20, 0.95)",
|
|
4157
|
-
strokeWidth: 1
|
|
4596
|
+
rx: 2
|
|
4158
4597
|
},
|
|
4159
4598
|
`side-${i}`
|
|
4160
4599
|
)),
|
|
4161
4600
|
corners.map((p, i) => /* @__PURE__ */ jsx(
|
|
4162
4601
|
"circle",
|
|
4163
4602
|
{
|
|
4603
|
+
className: "seatmap-editor__overlay-section-corner",
|
|
4164
4604
|
cx: p.x,
|
|
4165
4605
|
cy: p.y,
|
|
4166
|
-
r: 5
|
|
4167
|
-
fill: "#ffd38a",
|
|
4168
|
-
stroke: "rgba(45, 36, 20, 0.95)",
|
|
4169
|
-
strokeWidth: 1.2
|
|
4606
|
+
r: 5
|
|
4170
4607
|
},
|
|
4171
4608
|
`corner-${i}`
|
|
4172
4609
|
)),
|
|
@@ -4174,25 +4611,20 @@ function EditorInner({
|
|
|
4174
4611
|
/* @__PURE__ */ jsx(
|
|
4175
4612
|
"rect",
|
|
4176
4613
|
{
|
|
4614
|
+
className: "seatmap-editor__overlay-label-box",
|
|
4177
4615
|
x: hint.x - 88,
|
|
4178
4616
|
y: hint.y - 32,
|
|
4179
4617
|
width: 176,
|
|
4180
4618
|
height: 20,
|
|
4181
|
-
rx: 6
|
|
4182
|
-
fill: "rgba(15, 15, 25, 0.9)",
|
|
4183
|
-
stroke: "rgba(255, 193, 110, 0.65)",
|
|
4184
|
-
strokeWidth: 1
|
|
4619
|
+
rx: 6
|
|
4185
4620
|
}
|
|
4186
4621
|
),
|
|
4187
4622
|
/* @__PURE__ */ jsx(
|
|
4188
4623
|
"text",
|
|
4189
4624
|
{
|
|
4625
|
+
className: "seatmap-editor__overlay-label-text",
|
|
4190
4626
|
x: hint.x,
|
|
4191
4627
|
y: hint.y - 18,
|
|
4192
|
-
fill: "#ffd38a",
|
|
4193
|
-
fontSize: 11,
|
|
4194
|
-
fontFamily: "system-ui",
|
|
4195
|
-
textAnchor: "middle",
|
|
4196
4628
|
children: resizeOverlay.mergeHint?.message
|
|
4197
4629
|
}
|
|
4198
4630
|
)
|
|
@@ -4205,42 +4637,37 @@ function EditorInner({
|
|
|
4205
4637
|
if (activeToolName !== "add-row" || !rowPreviewPoint || !venue) return null;
|
|
4206
4638
|
const preview = addRowTool.getPlacementPreview(rowPreviewPoint.x, rowPreviewPoint.y, venue);
|
|
4207
4639
|
if (!preview) return null;
|
|
4640
|
+
const displayAngleRad = rowDirectionArrowMode === "row-direction" ? preview.worldAngleRad + Math.PI / 2 : preview.worldAngleRad;
|
|
4208
4641
|
const origin = viewport.worldToScreen(preview.worldX, preview.worldY);
|
|
4209
4642
|
const lineLengthPx = 78;
|
|
4210
4643
|
const end = {
|
|
4211
|
-
x: origin.x + Math.cos(
|
|
4212
|
-
y: origin.y + Math.sin(
|
|
4644
|
+
x: origin.x + Math.cos(displayAngleRad) * lineLengthPx,
|
|
4645
|
+
y: origin.y + Math.sin(displayAngleRad) * lineLengthPx
|
|
4213
4646
|
};
|
|
4214
4647
|
const arrowSizePx = 11;
|
|
4215
4648
|
const leftWing = {
|
|
4216
|
-
x: end.x - Math.cos(
|
|
4217
|
-
y: end.y - Math.sin(
|
|
4649
|
+
x: end.x - Math.cos(displayAngleRad - Math.PI / 6) * arrowSizePx,
|
|
4650
|
+
y: end.y - Math.sin(displayAngleRad - Math.PI / 6) * arrowSizePx
|
|
4218
4651
|
};
|
|
4219
4652
|
const rightWing = {
|
|
4220
|
-
x: end.x - Math.cos(
|
|
4221
|
-
y: end.y - Math.sin(
|
|
4653
|
+
x: end.x - Math.cos(displayAngleRad + Math.PI / 6) * arrowSizePx,
|
|
4654
|
+
y: end.y - Math.sin(displayAngleRad + Math.PI / 6) * arrowSizePx
|
|
4222
4655
|
};
|
|
4223
|
-
const
|
|
4656
|
+
const displayAngleDeg = ((displayAngleRad * 180 / Math.PI + 90) % 360 + 360) % 360;
|
|
4657
|
+
const orientationLabel = rowDirectionArrowMode === "row-direction" ? "Row direction" : "Viewer direction";
|
|
4224
4658
|
return /* @__PURE__ */ jsxs(
|
|
4225
4659
|
"svg",
|
|
4226
4660
|
{
|
|
4227
|
-
|
|
4228
|
-
position: "absolute",
|
|
4229
|
-
inset: 0,
|
|
4230
|
-
width: "100%",
|
|
4231
|
-
height: "100%",
|
|
4232
|
-
pointerEvents: "none",
|
|
4233
|
-
zIndex: 17
|
|
4234
|
-
},
|
|
4661
|
+
className: "seatmap-editor__overlay-svg seatmap-editor__overlay-svg--row-direction",
|
|
4235
4662
|
children: [
|
|
4236
4663
|
/* @__PURE__ */ jsx(
|
|
4237
4664
|
"line",
|
|
4238
4665
|
{
|
|
4666
|
+
className: "seatmap-editor__overlay-row-direction-line",
|
|
4239
4667
|
x1: origin.x,
|
|
4240
4668
|
y1: origin.y,
|
|
4241
4669
|
x2: end.x,
|
|
4242
4670
|
y2: end.y,
|
|
4243
|
-
stroke: "rgba(255, 213, 122, 0.95)",
|
|
4244
4671
|
strokeWidth: 3,
|
|
4245
4672
|
strokeLinecap: "round"
|
|
4246
4673
|
}
|
|
@@ -4248,44 +4675,38 @@ function EditorInner({
|
|
|
4248
4675
|
/* @__PURE__ */ jsx(
|
|
4249
4676
|
"polygon",
|
|
4250
4677
|
{
|
|
4251
|
-
|
|
4252
|
-
|
|
4678
|
+
className: "seatmap-editor__overlay-row-direction-arrow",
|
|
4679
|
+
points: `${end.x},${end.y} ${leftWing.x},${leftWing.y} ${rightWing.x},${rightWing.y}`
|
|
4253
4680
|
}
|
|
4254
4681
|
),
|
|
4255
4682
|
/* @__PURE__ */ jsx(
|
|
4256
4683
|
"circle",
|
|
4257
4684
|
{
|
|
4685
|
+
className: "seatmap-editor__overlay-row-direction-origin",
|
|
4258
4686
|
cx: origin.x,
|
|
4259
4687
|
cy: origin.y,
|
|
4260
4688
|
r: 5,
|
|
4261
|
-
fill: "rgba(255, 213, 122, 0.28)",
|
|
4262
|
-
stroke: "rgba(255, 213, 122, 0.95)",
|
|
4263
4689
|
strokeWidth: 1.5
|
|
4264
4690
|
}
|
|
4265
4691
|
),
|
|
4266
4692
|
/* @__PURE__ */ jsx(
|
|
4267
4693
|
"rect",
|
|
4268
4694
|
{
|
|
4695
|
+
className: "seatmap-editor__overlay-label-box",
|
|
4269
4696
|
x: origin.x + 10,
|
|
4270
4697
|
y: origin.y - 28,
|
|
4271
4698
|
width: 90,
|
|
4272
4699
|
height: 20,
|
|
4273
|
-
rx: 5
|
|
4274
|
-
fill: "rgba(15, 15, 25, 0.9)",
|
|
4275
|
-
stroke: "rgba(255, 213, 122, 0.65)",
|
|
4276
|
-
strokeWidth: 1
|
|
4700
|
+
rx: 5
|
|
4277
4701
|
}
|
|
4278
4702
|
),
|
|
4279
4703
|
/* @__PURE__ */ jsx(
|
|
4280
4704
|
"text",
|
|
4281
4705
|
{
|
|
4706
|
+
className: "seatmap-editor__overlay-label-text",
|
|
4282
4707
|
x: origin.x + 55,
|
|
4283
4708
|
y: origin.y - 14,
|
|
4284
|
-
|
|
4285
|
-
fontSize: 11,
|
|
4286
|
-
fontFamily: "system-ui",
|
|
4287
|
-
textAnchor: "middle",
|
|
4288
|
-
children: `Row angle ${Math.round(worldAngleDeg)}deg`
|
|
4709
|
+
children: `${orientationLabel} ${Math.round(displayAngleDeg)}\xB0`
|
|
4289
4710
|
}
|
|
4290
4711
|
)
|
|
4291
4712
|
]
|
|
@@ -4304,719 +4725,808 @@ function EditorInner({
|
|
|
4304
4725
|
},
|
|
4305
4726
|
[venue, store]
|
|
4306
4727
|
);
|
|
4307
|
-
const
|
|
4308
|
-
const
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4728
|
+
const handleDeleteSelectedObjects = useCallback(() => {
|
|
4729
|
+
const state = store.getState();
|
|
4730
|
+
const currentVenue = state.venue;
|
|
4731
|
+
if (!currentVenue) return;
|
|
4732
|
+
const selectedSeatIdSet = new Set(state.selectedSeatIds);
|
|
4733
|
+
const selectedSectionIdSet = new Set(state.selectedSectionIds);
|
|
4734
|
+
if (selectedSeatIdSet.size === 0 && selectedSectionIdSet.size === 0) return;
|
|
4735
|
+
const previousVenue = currentVenue;
|
|
4736
|
+
const nextVenue = {
|
|
4737
|
+
...currentVenue,
|
|
4738
|
+
sections: currentVenue.sections.filter((section) => !selectedSectionIdSet.has(section.id)).map((section) => ({
|
|
4739
|
+
...section,
|
|
4740
|
+
rows: section.rows.map((row) => ({
|
|
4741
|
+
...row,
|
|
4742
|
+
seats: row.seats.filter((seat) => !selectedSeatIdSet.has(seat.id))
|
|
4743
|
+
}))
|
|
4744
|
+
})),
|
|
4745
|
+
tables: currentVenue.tables.map((table) => ({
|
|
4746
|
+
...table,
|
|
4747
|
+
seats: table.seats.filter((seat) => !selectedSeatIdSet.has(seat.id))
|
|
4748
|
+
}))
|
|
4324
4749
|
};
|
|
4325
|
-
|
|
4326
|
-
"
|
|
4750
|
+
historyRef.current.execute({
|
|
4751
|
+
description: "Delete selected objects",
|
|
4752
|
+
execute: () => {
|
|
4753
|
+
store.getState().setVenue(nextVenue);
|
|
4754
|
+
store.getState().clearSelection();
|
|
4755
|
+
},
|
|
4756
|
+
undo: () => {
|
|
4757
|
+
store.getState().setVenue(previousVenue);
|
|
4758
|
+
}
|
|
4759
|
+
});
|
|
4760
|
+
}, [store]);
|
|
4761
|
+
const renderActiveToolOptionsOverlay = () => {
|
|
4762
|
+
const stopPointerPropagation = (e) => e.stopPropagation();
|
|
4763
|
+
const renderOverlay = (content) => /* @__PURE__ */ jsx("div", { className: "seatmap-editor__tool-options-overlay", children: /* @__PURE__ */ jsx(
|
|
4764
|
+
"div",
|
|
4327
4765
|
{
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4766
|
+
className: "seatmap-editor__tool-options-shell",
|
|
4767
|
+
onPointerDown: stopPointerPropagation,
|
|
4768
|
+
onPointerMove: stopPointerPropagation,
|
|
4769
|
+
onPointerUp: stopPointerPropagation,
|
|
4770
|
+
children: content
|
|
4771
|
+
}
|
|
4772
|
+
) });
|
|
4773
|
+
const renderSwitch = (label, checked, onToggle) => /* @__PURE__ */ jsxs("label", { className: "seatmap-editor__switch", children: [
|
|
4774
|
+
/* @__PURE__ */ jsx("span", { children: label }),
|
|
4775
|
+
/* @__PURE__ */ jsx(
|
|
4776
|
+
"button",
|
|
4777
|
+
{
|
|
4778
|
+
type: "button",
|
|
4779
|
+
role: "switch",
|
|
4780
|
+
"aria-checked": checked,
|
|
4781
|
+
onClick: onToggle,
|
|
4782
|
+
className: `seatmap-editor__switch-track${checked ? " is-checked" : ""}`,
|
|
4783
|
+
children: /* @__PURE__ */ jsx("span", { className: "seatmap-editor__switch-thumb" })
|
|
4784
|
+
}
|
|
4785
|
+
)
|
|
4786
|
+
] });
|
|
4787
|
+
const renderRange = (label, value, onChange2, hint, options) => {
|
|
4788
|
+
const min = options?.min ?? 0;
|
|
4789
|
+
const max = options?.max ?? 100;
|
|
4790
|
+
const step = options?.step ?? 1;
|
|
4791
|
+
const displayValue = options?.valueFormatter ? options.valueFormatter(value) : Math.round(value);
|
|
4792
|
+
const normalized = max > min ? (value - min) / (max - min) : 0;
|
|
4793
|
+
const clampedNormalized = clampRange(normalized, 0, 1);
|
|
4794
|
+
const isDial360 = options?.knobMode === "dial360";
|
|
4795
|
+
const knobFillStartDeg = options?.knobFillStartDeg ?? (isDial360 ? -90 : -130);
|
|
4796
|
+
const knobAngle = isDial360 ? knobFillStartDeg + clampedNormalized * 360 : -130 + clampedNormalized * 260;
|
|
4797
|
+
const knobFillPercent = isDial360 ? clampedNormalized * 100 : clampedNormalized * (260 / 360 * 100);
|
|
4798
|
+
const knobDisabled = Boolean(options?.disabled);
|
|
4799
|
+
const showKnob = Boolean(options?.displayAsKnob);
|
|
4800
|
+
const valuePlacement = options?.valuePlacement ?? "header";
|
|
4801
|
+
const compactKnobLayout = Boolean(options?.compactKnobLayout) && showKnob;
|
|
4802
|
+
const isLabelValueKnobLayout = showKnob && options?.knobLayout === "label-value-knob";
|
|
4803
|
+
const knobNamespace = options?.knobNamespace ?? "motion";
|
|
4804
|
+
const tooltipText = knobDisabled ? "Disabled while advanced overrides are enabled." : hint;
|
|
4805
|
+
const commitClampedValue = (raw) => {
|
|
4806
|
+
const clamped = clampRange(raw, min, max);
|
|
4807
|
+
const stepped = Math.round((clamped - min) / step) * step + min;
|
|
4808
|
+
onChange2(clampRange(stepped, min, max));
|
|
4809
|
+
};
|
|
4810
|
+
return /* @__PURE__ */ jsxs(
|
|
4811
|
+
"label",
|
|
4812
|
+
{
|
|
4813
|
+
className: `seatmap-editor__motion-slider${compactKnobLayout ? " seatmap-editor__motion-slider--compact-knob" : ""}${isLabelValueKnobLayout ? " seatmap-editor__motion-slider--label-value-knob" : ""}${knobDisabled ? " is-disabled" : ""}`,
|
|
4814
|
+
children: [
|
|
4815
|
+
!isLabelValueKnobLayout && /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__motion-slider-header", children: [
|
|
4816
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__label", title: label, children: label }),
|
|
4817
|
+
valuePlacement === "header" && /* @__PURE__ */ jsx("span", { className: "seatmap-editor__motion-slider-value", children: displayValue })
|
|
4818
|
+
] }),
|
|
4819
|
+
showKnob ? /* @__PURE__ */ jsxs("div", { className: `seatmap-editor__motion-knob-row${isLabelValueKnobLayout ? " seatmap-editor__motion-knob-row--label-value-knob" : ""}`, children: [
|
|
4820
|
+
isLabelValueKnobLayout && /* @__PURE__ */ jsx("span", { className: "seatmap-editor__label", title: label, children: label }),
|
|
4821
|
+
isLabelValueKnobLayout && /* @__PURE__ */ jsx("span", { className: "seatmap-editor__motion-slider-value", children: displayValue }),
|
|
4822
|
+
/* @__PURE__ */ jsxs(
|
|
4823
|
+
"button",
|
|
4354
4824
|
{
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4825
|
+
type: "button",
|
|
4826
|
+
className: "seatmap-editor__motion-knob",
|
|
4827
|
+
"aria-label": label,
|
|
4828
|
+
title: tooltipText,
|
|
4829
|
+
disabled: knobDisabled,
|
|
4830
|
+
onPointerDown: (e) => {
|
|
4831
|
+
if (knobDisabled) return;
|
|
4832
|
+
e.preventDefault();
|
|
4833
|
+
const pointerId = e.pointerId;
|
|
4834
|
+
const target = e.currentTarget;
|
|
4835
|
+
target.setPointerCapture(pointerId);
|
|
4836
|
+
const range = max - min;
|
|
4837
|
+
const getDialValue = (clientX, clientY) => {
|
|
4838
|
+
const rect = target.getBoundingClientRect();
|
|
4839
|
+
const centerX = rect.left + rect.width / 2;
|
|
4840
|
+
const centerY = rect.top + rect.height / 2;
|
|
4841
|
+
const angle = Math.atan2(clientY - centerY, clientX - centerX);
|
|
4842
|
+
const clockwiseFromUpDeg = ((angle * 180 / Math.PI + 90) % 360 + 360) % 360;
|
|
4843
|
+
return min + clockwiseFromUpDeg / 360 * range;
|
|
4844
|
+
};
|
|
4845
|
+
let handleMove;
|
|
4846
|
+
if (isDial360) {
|
|
4847
|
+
commitClampedValue(getDialValue(e.clientX, e.clientY));
|
|
4848
|
+
handleMove = (ev) => {
|
|
4849
|
+
commitClampedValue(getDialValue(ev.clientX, ev.clientY));
|
|
4850
|
+
};
|
|
4851
|
+
} else {
|
|
4852
|
+
const startY = e.clientY;
|
|
4853
|
+
const startValue = value;
|
|
4854
|
+
const dragHeightPx = 180;
|
|
4855
|
+
handleMove = (ev) => {
|
|
4856
|
+
const deltaY = startY - ev.clientY;
|
|
4857
|
+
commitClampedValue(startValue + deltaY / dragHeightPx * range);
|
|
4858
|
+
};
|
|
4859
|
+
}
|
|
4860
|
+
const handleUp = () => {
|
|
4861
|
+
target.removeEventListener("pointermove", handleMove);
|
|
4862
|
+
target.removeEventListener("pointerup", handleUp);
|
|
4863
|
+
target.removeEventListener("pointercancel", handleUp);
|
|
4864
|
+
};
|
|
4865
|
+
target.addEventListener("pointermove", handleMove);
|
|
4866
|
+
target.addEventListener("pointerup", handleUp);
|
|
4867
|
+
target.addEventListener("pointercancel", handleUp);
|
|
4868
|
+
},
|
|
4869
|
+
children: [
|
|
4870
|
+
/* @__PURE__ */ jsx(
|
|
4871
|
+
"span",
|
|
4872
|
+
{
|
|
4873
|
+
className: `seatmap-editor__motion-knob-ring${knobNamespace === "tool" ? " seatmap-editor__motion-knob-ring--tool" : " seatmap-editor__motion-knob-ring--motion"}`,
|
|
4874
|
+
style: {
|
|
4875
|
+
[knobNamespace === "tool" ? "--tool-knob-fill" : "--motion-knob-fill"]: `${Math.round(knobFillPercent)}%`,
|
|
4876
|
+
[knobNamespace === "tool" ? "--tool-knob-start-angle" : "--motion-knob-start-angle"]: `${knobFillStartDeg}deg`
|
|
4877
|
+
}
|
|
4878
|
+
}
|
|
4879
|
+
),
|
|
4880
|
+
/* @__PURE__ */ jsx(
|
|
4881
|
+
"span",
|
|
4882
|
+
{
|
|
4883
|
+
className: "seatmap-editor__motion-knob-indicator",
|
|
4884
|
+
style: { transform: `translate(-50%, -100%) rotate(${knobAngle}deg)` }
|
|
4885
|
+
}
|
|
4886
|
+
)
|
|
4887
|
+
]
|
|
4359
4888
|
}
|
|
4360
|
-
)
|
|
4889
|
+
),
|
|
4890
|
+
valuePlacement === "knob" && /* @__PURE__ */ jsx("span", { className: "seatmap-editor__motion-slider-value seatmap-editor__motion-slider-value--knob", children: displayValue }),
|
|
4891
|
+
options?.knobRightContent && /* @__PURE__ */ jsx("div", { className: "seatmap-editor__motion-knob-right-content", children: options.knobRightContent })
|
|
4892
|
+
] }) : /* @__PURE__ */ jsx(
|
|
4893
|
+
"input",
|
|
4894
|
+
{
|
|
4895
|
+
type: "range",
|
|
4896
|
+
min,
|
|
4897
|
+
max,
|
|
4898
|
+
step,
|
|
4899
|
+
value,
|
|
4900
|
+
onChange: (e) => commitClampedValue(Number(e.target.value) || 0),
|
|
4901
|
+
disabled: knobDisabled,
|
|
4902
|
+
className: "seatmap-editor__panel-range",
|
|
4903
|
+
title: tooltipText
|
|
4904
|
+
}
|
|
4905
|
+
)
|
|
4906
|
+
]
|
|
4907
|
+
}
|
|
4908
|
+
);
|
|
4909
|
+
};
|
|
4910
|
+
const renderOptionCard = (title, body, className) => /* @__PURE__ */ jsxs("div", { className: `seatmap-editor__option-card${className ? ` ${className}` : ""}`, children: [
|
|
4911
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__option-card-title seatmap-editor__option-card-title--group", children: title }),
|
|
4912
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__option-card-subdivider" }),
|
|
4913
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__option-card-body", children: body })
|
|
4914
|
+
] });
|
|
4915
|
+
const renderGridOptionsCard = () => renderOptionCard(
|
|
4916
|
+
"Grid options",
|
|
4917
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4918
|
+
renderSwitch("Grid", gridEnabled, () => setGridEnabled((v) => !v)),
|
|
4919
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__option-card-divider" }),
|
|
4920
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__option-row", children: [
|
|
4921
|
+
renderSwitch("Canvas grid", showCanvasGrid, () => setShowCanvasGrid((v) => !v)),
|
|
4922
|
+
/* @__PURE__ */ jsxs(
|
|
4923
|
+
"select",
|
|
4924
|
+
{
|
|
4925
|
+
value: canvasGridStyle,
|
|
4926
|
+
onChange: (e) => setCanvasGridStyle(e.target.value),
|
|
4927
|
+
className: "seatmap-editor__select",
|
|
4928
|
+
disabled: !gridEnabled || !showCanvasGrid,
|
|
4929
|
+
children: [
|
|
4930
|
+
/* @__PURE__ */ jsx("option", { value: "solid", children: "Solid" }),
|
|
4931
|
+
/* @__PURE__ */ jsx("option", { value: "dashed", children: "Dashed" }),
|
|
4932
|
+
/* @__PURE__ */ jsx("option", { value: "dotted", children: "Dotted" })
|
|
4933
|
+
]
|
|
4361
4934
|
}
|
|
4362
4935
|
)
|
|
4363
|
-
]
|
|
4364
|
-
|
|
4936
|
+
] }),
|
|
4937
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__option-row", children: [
|
|
4938
|
+
renderSwitch("Section grid", showSectionGrid, () => setShowSectionGrid((v) => !v)),
|
|
4939
|
+
/* @__PURE__ */ jsxs(
|
|
4940
|
+
"select",
|
|
4941
|
+
{
|
|
4942
|
+
value: sectionGridStyle,
|
|
4943
|
+
onChange: (e) => setSectionGridStyle(e.target.value),
|
|
4944
|
+
className: "seatmap-editor__select",
|
|
4945
|
+
disabled: !gridEnabled || !showSectionGrid,
|
|
4946
|
+
children: [
|
|
4947
|
+
/* @__PURE__ */ jsx("option", { value: "dots", children: "Dots" }),
|
|
4948
|
+
/* @__PURE__ */ jsx("option", { value: "cross", children: "Cross" })
|
|
4949
|
+
]
|
|
4950
|
+
}
|
|
4951
|
+
)
|
|
4952
|
+
] })
|
|
4953
|
+
] })
|
|
4365
4954
|
);
|
|
4366
|
-
const
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4955
|
+
const renderMotionSettingsCard = () => renderOptionCard(
|
|
4956
|
+
"Editor motion",
|
|
4957
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__motion-layout", children: [
|
|
4958
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__motion-column seatmap-editor__motion-column--basic", children: [
|
|
4959
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__option-card-title", children: "Basic" }),
|
|
4960
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__motion-control-grid", children: [
|
|
4961
|
+
renderRange(
|
|
4962
|
+
"Section draw zoom jelly",
|
|
4963
|
+
sectionDrawJelly,
|
|
4964
|
+
setSectionDrawJelly,
|
|
4965
|
+
"Controls how floaty auto-focus feels after drawing a section.",
|
|
4966
|
+
{ disabled: useAdvancedMotion, displayAsKnob: true, knobLayout: "label-value-knob" }
|
|
4967
|
+
),
|
|
4968
|
+
renderRange(
|
|
4969
|
+
"Fit zoom jelly",
|
|
4970
|
+
fitViewJelly,
|
|
4971
|
+
setFitViewJelly,
|
|
4972
|
+
"Controls smoothness and duration of Fit action.",
|
|
4973
|
+
{ disabled: useAdvancedMotion, displayAsKnob: true, knobLayout: "label-value-knob" }
|
|
4974
|
+
),
|
|
4975
|
+
renderRange(
|
|
4976
|
+
"Canvas pan inertia",
|
|
4977
|
+
panInertiaJelly,
|
|
4978
|
+
setPanInertiaJelly,
|
|
4979
|
+
"Controls glide amount after you release a pan drag.",
|
|
4980
|
+
{ disabled: useAdvancedMotion, displayAsKnob: true, knobLayout: "label-value-knob" }
|
|
4981
|
+
),
|
|
4982
|
+
renderRange(
|
|
4983
|
+
"Pointer scroll zoom jelly",
|
|
4984
|
+
pointerScrollZoomJelly,
|
|
4985
|
+
setPointerScrollZoomJelly,
|
|
4986
|
+
"Controls how smooth pointer wheel zoom feels.",
|
|
4987
|
+
{ disabled: useAdvancedMotion, displayAsKnob: true, knobLayout: "label-value-knob" }
|
|
4988
|
+
)
|
|
4989
|
+
] }),
|
|
4990
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__option-row seatmap-editor__option-row--end seatmap-editor__motion-basic-actions", children: /* @__PURE__ */ jsx(
|
|
4991
|
+
"button",
|
|
4392
4992
|
{
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
fontWeight: 600
|
|
4398
|
-
},
|
|
4399
|
-
children: "Grid options"
|
|
4993
|
+
type: "button",
|
|
4994
|
+
className: "seatmap-editor__panel-button seatmap-editor__panel-button--tiny",
|
|
4995
|
+
onClick: handleResetMotionSettings,
|
|
4996
|
+
children: "Reset to defaults"
|
|
4400
4997
|
}
|
|
4401
|
-
),
|
|
4402
|
-
renderSwitch("
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4998
|
+
) }),
|
|
4999
|
+
renderSwitch("Use advanced overrides", useAdvancedMotion, () => setUseAdvancedMotion((v) => !v))
|
|
5000
|
+
] }),
|
|
5001
|
+
useAdvancedMotion && /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__motion-column seatmap-editor__motion-column--advanced", children: [
|
|
5002
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__motion-advanced-header", children: /* @__PURE__ */ jsx("span", { className: "seatmap-editor__option-card-title", children: "Advanced" }) }),
|
|
5003
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__option-card-title seatmap-editor__option-card-title--subtle", children: "Section" }),
|
|
5004
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__motion-control-grid is-knob-grid", children: [
|
|
5005
|
+
renderRange(
|
|
5006
|
+
"Draw duration",
|
|
5007
|
+
sectionDrawDurationMs,
|
|
5008
|
+
setSectionDrawDurationMs,
|
|
5009
|
+
"Animation duration in milliseconds.",
|
|
4408
5010
|
{
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
5011
|
+
min: 100,
|
|
5012
|
+
max: 3e3,
|
|
5013
|
+
step: 10,
|
|
5014
|
+
valueFormatter: (n) => `${Math.round(n)}ms`,
|
|
5015
|
+
displayAsKnob: true,
|
|
5016
|
+
compactKnobLayout: true
|
|
5017
|
+
}
|
|
5018
|
+
),
|
|
5019
|
+
renderRange(
|
|
5020
|
+
"Center pull",
|
|
5021
|
+
sectionDrawCenterPullPct,
|
|
5022
|
+
setSectionDrawCenterPullPct,
|
|
5023
|
+
"How strongly section draw focus moves toward section center.",
|
|
5024
|
+
{
|
|
5025
|
+
min: 0,
|
|
5026
|
+
max: 100,
|
|
5027
|
+
step: 1,
|
|
5028
|
+
valueFormatter: (n) => `${Math.round(n)}%`,
|
|
5029
|
+
displayAsKnob: true,
|
|
5030
|
+
compactKnobLayout: true
|
|
5031
|
+
}
|
|
5032
|
+
),
|
|
5033
|
+
renderRange(
|
|
5034
|
+
"Zoom boost",
|
|
5035
|
+
sectionDrawZoomBoostPct,
|
|
5036
|
+
setSectionDrawZoomBoostPct,
|
|
5037
|
+
"Additional zoom applied during section draw focus.",
|
|
5038
|
+
{
|
|
5039
|
+
min: 0,
|
|
5040
|
+
max: 50,
|
|
5041
|
+
step: 1,
|
|
5042
|
+
valueFormatter: (n) => `${Math.round(n)}%`,
|
|
5043
|
+
displayAsKnob: true,
|
|
5044
|
+
compactKnobLayout: true
|
|
5045
|
+
}
|
|
5046
|
+
),
|
|
5047
|
+
renderRange(
|
|
5048
|
+
"Overshoot",
|
|
5049
|
+
sectionDrawOvershootPct,
|
|
5050
|
+
setSectionDrawOvershootPct,
|
|
5051
|
+
"Spring amount near the end of section auto-focus.",
|
|
5052
|
+
{
|
|
5053
|
+
min: 0,
|
|
5054
|
+
max: 180,
|
|
5055
|
+
step: 1,
|
|
5056
|
+
valueFormatter: (n) => `${Math.round(n)}%`,
|
|
5057
|
+
displayAsKnob: true,
|
|
5058
|
+
compactKnobLayout: true
|
|
4418
5059
|
}
|
|
4419
5060
|
)
|
|
4420
5061
|
] }),
|
|
4421
|
-
/* @__PURE__ */
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
5062
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__motion-group-divider" }),
|
|
5063
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__option-card-title seatmap-editor__option-card-title--subtle", children: "Fit" }),
|
|
5064
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__motion-control-grid is-knob-grid", children: [
|
|
5065
|
+
renderRange(
|
|
5066
|
+
"Duration",
|
|
5067
|
+
fitViewDurationMs,
|
|
5068
|
+
setFitViewDurationMs,
|
|
5069
|
+
"Animation duration for Fit action.",
|
|
4425
5070
|
{
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
5071
|
+
min: 100,
|
|
5072
|
+
max: 3e3,
|
|
5073
|
+
step: 10,
|
|
5074
|
+
valueFormatter: (n) => `${Math.round(n)}ms`,
|
|
5075
|
+
displayAsKnob: true,
|
|
5076
|
+
compactKnobLayout: true
|
|
5077
|
+
}
|
|
5078
|
+
),
|
|
5079
|
+
renderRange(
|
|
5080
|
+
"Overshoot",
|
|
5081
|
+
fitViewOvershootPct,
|
|
5082
|
+
setFitViewOvershootPct,
|
|
5083
|
+
"Spring amount near the end of Fit movement.",
|
|
5084
|
+
{
|
|
5085
|
+
min: 0,
|
|
5086
|
+
max: 180,
|
|
5087
|
+
step: 1,
|
|
5088
|
+
valueFormatter: (n) => `${Math.round(n)}%`,
|
|
5089
|
+
displayAsKnob: true,
|
|
5090
|
+
compactKnobLayout: true
|
|
4434
5091
|
}
|
|
4435
5092
|
)
|
|
4436
|
-
] })
|
|
4437
|
-
|
|
4438
|
-
|
|
5093
|
+
] }),
|
|
5094
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__motion-group-divider" }),
|
|
5095
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__option-card-title seatmap-editor__option-card-title--subtle", children: "Pan" }),
|
|
5096
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__motion-control-grid is-knob-grid", children: [
|
|
5097
|
+
renderRange(
|
|
5098
|
+
"Inertia carry",
|
|
5099
|
+
panInertiaCarryPct,
|
|
5100
|
+
setPanInertiaCarryPct,
|
|
5101
|
+
"Velocity retained at pan release.",
|
|
5102
|
+
{
|
|
5103
|
+
min: 0,
|
|
5104
|
+
max: 95,
|
|
5105
|
+
step: 1,
|
|
5106
|
+
valueFormatter: (n) => `${Math.round(n)}%`,
|
|
5107
|
+
displayAsKnob: true,
|
|
5108
|
+
compactKnobLayout: true
|
|
5109
|
+
}
|
|
5110
|
+
),
|
|
5111
|
+
renderRange(
|
|
5112
|
+
"Inertia friction",
|
|
5113
|
+
panInertiaFrictionPct,
|
|
5114
|
+
setPanInertiaFrictionPct,
|
|
5115
|
+
"Per-frame damping (higher = longer glide).",
|
|
5116
|
+
{
|
|
5117
|
+
min: 70,
|
|
5118
|
+
max: 99,
|
|
5119
|
+
step: 1,
|
|
5120
|
+
valueFormatter: (n) => `${Math.round(n)}%`,
|
|
5121
|
+
displayAsKnob: true,
|
|
5122
|
+
compactKnobLayout: true
|
|
5123
|
+
}
|
|
5124
|
+
),
|
|
5125
|
+
renderRange(
|
|
5126
|
+
"Stop speed",
|
|
5127
|
+
panInertiaMinSpeedMilli,
|
|
5128
|
+
setPanInertiaMinSpeedMilli,
|
|
5129
|
+
"Stop threshold in px/ms x1000.",
|
|
5130
|
+
{
|
|
5131
|
+
min: 1,
|
|
5132
|
+
max: 50,
|
|
5133
|
+
step: 1,
|
|
5134
|
+
valueFormatter: (n) => `${Math.round(n)}`,
|
|
5135
|
+
displayAsKnob: true,
|
|
5136
|
+
compactKnobLayout: true
|
|
5137
|
+
}
|
|
5138
|
+
),
|
|
5139
|
+
renderRange(
|
|
5140
|
+
"Velocity blend",
|
|
5141
|
+
panVelocityBlendPct,
|
|
5142
|
+
setPanVelocityBlendPct,
|
|
5143
|
+
"How quickly release velocity follows latest drag samples.",
|
|
5144
|
+
{
|
|
5145
|
+
min: 5,
|
|
5146
|
+
max: 95,
|
|
5147
|
+
step: 1,
|
|
5148
|
+
valueFormatter: (n) => `${Math.round(n)}%`,
|
|
5149
|
+
displayAsKnob: true,
|
|
5150
|
+
compactKnobLayout: true
|
|
5151
|
+
}
|
|
5152
|
+
),
|
|
5153
|
+
renderRange(
|
|
5154
|
+
"Stop delta",
|
|
5155
|
+
panStopDeltaMilli,
|
|
5156
|
+
setPanStopDeltaMilli,
|
|
5157
|
+
"Treat movement below this px x1000 as stopped while dragging.",
|
|
5158
|
+
{
|
|
5159
|
+
min: 0,
|
|
5160
|
+
max: 4e3,
|
|
5161
|
+
step: 10,
|
|
5162
|
+
valueFormatter: (n) => `${Math.round(n)}`,
|
|
5163
|
+
displayAsKnob: true,
|
|
5164
|
+
compactKnobLayout: true
|
|
5165
|
+
}
|
|
5166
|
+
),
|
|
5167
|
+
renderRange(
|
|
5168
|
+
"Release idle",
|
|
5169
|
+
panReleaseIdleMs,
|
|
5170
|
+
setPanReleaseIdleMs,
|
|
5171
|
+
"If pointer pauses this long before release, inertia is dropped.",
|
|
5172
|
+
{
|
|
5173
|
+
min: 0,
|
|
5174
|
+
max: 400,
|
|
5175
|
+
step: 5,
|
|
5176
|
+
valueFormatter: (n) => `${Math.round(n)}ms`,
|
|
5177
|
+
displayAsKnob: true,
|
|
5178
|
+
compactKnobLayout: true
|
|
5179
|
+
}
|
|
5180
|
+
)
|
|
5181
|
+
] }),
|
|
5182
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__motion-group-divider" }),
|
|
5183
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__option-card-title seatmap-editor__option-card-title--subtle", children: "Pointer scroll zoom" }),
|
|
5184
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__motion-control-grid is-knob-grid", children: [
|
|
5185
|
+
renderRange(
|
|
5186
|
+
"Duration",
|
|
5187
|
+
pointerScrollZoomDurationMs,
|
|
5188
|
+
setPointerScrollZoomDurationMs,
|
|
5189
|
+
"Wheel zoom easing duration.",
|
|
5190
|
+
{
|
|
5191
|
+
min: 60,
|
|
5192
|
+
max: 600,
|
|
5193
|
+
step: 5,
|
|
5194
|
+
valueFormatter: (n) => `${Math.round(n)}ms`,
|
|
5195
|
+
displayAsKnob: true,
|
|
5196
|
+
compactKnobLayout: true
|
|
5197
|
+
}
|
|
5198
|
+
),
|
|
5199
|
+
renderRange(
|
|
5200
|
+
"Strength",
|
|
5201
|
+
pointerScrollZoomStrengthPct,
|
|
5202
|
+
setPointerScrollZoomStrengthPct,
|
|
5203
|
+
"Per-frame zoom blend amount (higher = snappier response).",
|
|
5204
|
+
{
|
|
5205
|
+
min: 8,
|
|
5206
|
+
max: 55,
|
|
5207
|
+
step: 1,
|
|
5208
|
+
valueFormatter: (n) => `${Math.round(n)}%`,
|
|
5209
|
+
displayAsKnob: true,
|
|
5210
|
+
compactKnobLayout: true
|
|
5211
|
+
}
|
|
5212
|
+
),
|
|
5213
|
+
renderRange(
|
|
5214
|
+
"Sensitivity",
|
|
5215
|
+
pointerScrollZoomDeltaDivisor,
|
|
5216
|
+
setPointerScrollZoomDeltaDivisor,
|
|
5217
|
+
"Wheel delta divisor (higher = less sensitive).",
|
|
5218
|
+
{
|
|
5219
|
+
min: 250,
|
|
5220
|
+
max: 1400,
|
|
5221
|
+
step: 10,
|
|
5222
|
+
valueFormatter: (n) => `${Math.round(n)}`,
|
|
5223
|
+
displayAsKnob: true,
|
|
5224
|
+
compactKnobLayout: true
|
|
5225
|
+
}
|
|
5226
|
+
)
|
|
5227
|
+
] }),
|
|
5228
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__motion-advanced-actions", children: /* @__PURE__ */ jsx(
|
|
5229
|
+
"button",
|
|
5230
|
+
{
|
|
5231
|
+
type: "button",
|
|
5232
|
+
className: "seatmap-editor__panel-button seatmap-editor__panel-button--tiny",
|
|
5233
|
+
onClick: handleApplyAdvancedToBasic,
|
|
5234
|
+
title: "Recalculate basic knobs from advanced settings",
|
|
5235
|
+
children: "Apply to basic"
|
|
5236
|
+
}
|
|
5237
|
+
) })
|
|
5238
|
+
] })
|
|
5239
|
+
] }),
|
|
5240
|
+
`seatmap-editor__option-card--motion${useAdvancedMotion ? " is-advanced-open" : ""}`
|
|
4439
5241
|
);
|
|
4440
5242
|
if (activeToolName === "add-section") {
|
|
4441
|
-
return
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
5243
|
+
return renderOverlay(
|
|
5244
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5245
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__tool-options-title", children: "Tool Options" }),
|
|
5246
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__tool-options-divider" }),
|
|
5247
|
+
renderOptionCard("Section", /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__option-row", children: [
|
|
5248
|
+
/* @__PURE__ */ jsx(
|
|
5249
|
+
"button",
|
|
5250
|
+
{
|
|
5251
|
+
onClick: () => handleSectionToolVariantChange("section", "rectangle"),
|
|
5252
|
+
className: `seatmap-editor__segmented-button${sectionKind === "section" && sectionMode === "rectangle" ? " is-active" : ""}`,
|
|
5253
|
+
children: "Rectangle"
|
|
5254
|
+
}
|
|
5255
|
+
),
|
|
5256
|
+
/* @__PURE__ */ jsx(
|
|
5257
|
+
"button",
|
|
5258
|
+
{
|
|
5259
|
+
onClick: () => handleSectionToolVariantChange("section", "polygon"),
|
|
5260
|
+
className: `seatmap-editor__segmented-button${sectionKind === "section" && sectionMode === "polygon" ? " is-active" : ""}`,
|
|
5261
|
+
children: "Polygon"
|
|
5262
|
+
}
|
|
5263
|
+
)
|
|
5264
|
+
] })),
|
|
5265
|
+
renderOptionCard("Stage", /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__option-row", children: [
|
|
5266
|
+
/* @__PURE__ */ jsx(
|
|
5267
|
+
"button",
|
|
5268
|
+
{
|
|
5269
|
+
onClick: () => handleSectionToolVariantChange("stage", "rectangle"),
|
|
5270
|
+
className: `seatmap-editor__segmented-button${sectionKind === "stage" && sectionMode === "rectangle" ? " is-active" : ""}`,
|
|
5271
|
+
children: "Rectangle"
|
|
5272
|
+
}
|
|
5273
|
+
),
|
|
5274
|
+
/* @__PURE__ */ jsx(
|
|
5275
|
+
"button",
|
|
5276
|
+
{
|
|
5277
|
+
onClick: () => handleSectionToolVariantChange("stage", "polygon"),
|
|
5278
|
+
className: `seatmap-editor__segmented-button${sectionKind === "stage" && sectionMode === "polygon" ? " is-active" : ""}`,
|
|
5279
|
+
children: "Polygon"
|
|
5280
|
+
}
|
|
5281
|
+
)
|
|
5282
|
+
] })),
|
|
5283
|
+
renderOptionCard("Dancefloor", /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__option-row", children: [
|
|
5284
|
+
/* @__PURE__ */ jsx(
|
|
5285
|
+
"button",
|
|
5286
|
+
{
|
|
5287
|
+
onClick: () => handleSectionToolVariantChange("dancefloor", "rectangle"),
|
|
5288
|
+
className: `seatmap-editor__segmented-button${sectionKind === "dancefloor" && sectionMode === "rectangle" ? " is-active" : ""}`,
|
|
5289
|
+
children: "Rectangle"
|
|
5290
|
+
}
|
|
5291
|
+
),
|
|
5292
|
+
/* @__PURE__ */ jsx(
|
|
5293
|
+
"button",
|
|
5294
|
+
{
|
|
5295
|
+
onClick: () => handleSectionToolVariantChange("dancefloor", "polygon"),
|
|
5296
|
+
className: `seatmap-editor__segmented-button${sectionKind === "dancefloor" && sectionMode === "polygon" ? " is-active" : ""}`,
|
|
5297
|
+
children: "Polygon"
|
|
5298
|
+
}
|
|
5299
|
+
)
|
|
5300
|
+
] })),
|
|
5301
|
+
renderOptionCard("Section resize", /* @__PURE__ */ jsx(
|
|
5302
|
+
"button",
|
|
4454
5303
|
{
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
5304
|
+
onClick: () => handleToggleSectionResize(true),
|
|
5305
|
+
className: `seatmap-editor__segmented-button${sectionResizeEnabled ? " is-active" : ""}`,
|
|
5306
|
+
title: "Enable section corner/side resizing",
|
|
5307
|
+
children: sectionResizeEnabled ? "Resize On" : "Resize Off"
|
|
5308
|
+
}
|
|
5309
|
+
)),
|
|
5310
|
+
renderOptionCard("Auto focus", renderSwitch(
|
|
5311
|
+
"Zoom to new section",
|
|
5312
|
+
autoFocusNewSection,
|
|
5313
|
+
() => setAutoFocusNewSection((current) => !current)
|
|
5314
|
+
)),
|
|
5315
|
+
isGridOptionsOpen && renderGridOptionsCard(),
|
|
5316
|
+
isEditorSettingsOpen && renderMotionSettingsCard()
|
|
5317
|
+
] })
|
|
5318
|
+
);
|
|
5319
|
+
}
|
|
5320
|
+
if (activeToolName === "select") {
|
|
5321
|
+
return renderOverlay(
|
|
5322
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5323
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__tool-options-title", children: "Tool Options" }),
|
|
5324
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__tool-options-divider" }),
|
|
5325
|
+
renderOptionCard("Section resize", /* @__PURE__ */ jsx(
|
|
5326
|
+
"button",
|
|
5327
|
+
{
|
|
5328
|
+
onClick: () => handleToggleSectionResize(false),
|
|
5329
|
+
className: `seatmap-editor__segmented-button${sectionResizeEnabled ? " is-active" : ""}`,
|
|
5330
|
+
children: sectionResizeEnabled ? "Resize On" : "Resize Off"
|
|
5331
|
+
}
|
|
5332
|
+
)),
|
|
5333
|
+
isGridOptionsOpen && renderGridOptionsCard(),
|
|
5334
|
+
isEditorSettingsOpen && renderMotionSettingsCard()
|
|
5335
|
+
] })
|
|
5336
|
+
);
|
|
5337
|
+
}
|
|
5338
|
+
if (activeToolName !== "add-row") {
|
|
5339
|
+
if (!isGridOptionsOpen && !isEditorSettingsOpen) return null;
|
|
5340
|
+
return renderOverlay(
|
|
5341
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5342
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__tool-options-title", children: "Tool Options" }),
|
|
5343
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__tool-options-divider" }),
|
|
5344
|
+
isGridOptionsOpen && renderGridOptionsCard(),
|
|
5345
|
+
isEditorSettingsOpen && renderMotionSettingsCard()
|
|
5346
|
+
] })
|
|
5347
|
+
);
|
|
5348
|
+
}
|
|
5349
|
+
return renderOverlay(
|
|
5350
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5351
|
+
/* @__PURE__ */ jsx("span", { className: "seatmap-editor__tool-options-title", children: "Tool Options" }),
|
|
5352
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__tool-options-divider" }),
|
|
5353
|
+
renderOptionCard("Row layout", /* @__PURE__ */ jsxs("div", { className: "seatmap-editor__row-layout-body", children: [
|
|
5354
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__row-layout-controls", children: [
|
|
5355
|
+
/* @__PURE__ */ jsxs("label", { className: "seatmap-editor__label seatmap-editor__option-row", children: [
|
|
5356
|
+
"Seats:",
|
|
5357
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__input-stepper", children: [
|
|
4470
5358
|
/* @__PURE__ */ jsx(
|
|
4471
|
-
"
|
|
5359
|
+
"input",
|
|
4472
5360
|
{
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
},
|
|
4480
|
-
children: "Tool Options"
|
|
5361
|
+
type: "number",
|
|
5362
|
+
min: 1,
|
|
5363
|
+
max: 100,
|
|
5364
|
+
value: seatsPerRow,
|
|
5365
|
+
onChange: (e) => handleSeatsPerRowChange(Math.max(1, Math.min(100, parseInt(e.target.value) || 1))),
|
|
5366
|
+
className: "seatmap-editor__input seatmap-editor__input--stepper"
|
|
4481
5367
|
}
|
|
4482
5368
|
),
|
|
4483
|
-
/* @__PURE__ */ jsx(
|
|
4484
|
-
|
|
4485
|
-
"div",
|
|
5369
|
+
/* @__PURE__ */ jsx(
|
|
5370
|
+
"button",
|
|
4486
5371
|
{
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
padding: "8px 10px",
|
|
4493
|
-
border: "1px solid #3a3a5a",
|
|
4494
|
-
borderRadius: 6,
|
|
4495
|
-
background: "rgba(42, 42, 74, 0.65)"
|
|
4496
|
-
},
|
|
4497
|
-
children: [
|
|
4498
|
-
/* @__PURE__ */ jsx(
|
|
4499
|
-
"span",
|
|
4500
|
-
{
|
|
4501
|
-
style: {
|
|
4502
|
-
color: "#c7c7df",
|
|
4503
|
-
fontSize: 12,
|
|
4504
|
-
fontFamily: "system-ui",
|
|
4505
|
-
fontWeight: 600
|
|
4506
|
-
},
|
|
4507
|
-
children: "Section shape"
|
|
4508
|
-
}
|
|
4509
|
-
),
|
|
4510
|
-
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
4511
|
-
/* @__PURE__ */ jsx(
|
|
4512
|
-
"button",
|
|
4513
|
-
{
|
|
4514
|
-
onClick: () => handleSectionModeChange("rectangle"),
|
|
4515
|
-
style: {
|
|
4516
|
-
padding: "4px 8px",
|
|
4517
|
-
borderRadius: 6,
|
|
4518
|
-
border: "1px solid #3a3a5a",
|
|
4519
|
-
background: sectionMode === "rectangle" ? "#4a4a7a" : "#2a2a4a",
|
|
4520
|
-
color: sectionMode === "rectangle" ? "#ffffff" : "#d0d0e0",
|
|
4521
|
-
cursor: "pointer",
|
|
4522
|
-
fontSize: 12,
|
|
4523
|
-
fontFamily: "system-ui",
|
|
4524
|
-
fontWeight: 600
|
|
4525
|
-
},
|
|
4526
|
-
children: "Rectangle"
|
|
4527
|
-
}
|
|
4528
|
-
),
|
|
4529
|
-
/* @__PURE__ */ jsx(
|
|
4530
|
-
"button",
|
|
4531
|
-
{
|
|
4532
|
-
onClick: () => handleSectionModeChange("polygon"),
|
|
4533
|
-
style: {
|
|
4534
|
-
padding: "4px 8px",
|
|
4535
|
-
borderRadius: 6,
|
|
4536
|
-
border: "1px solid #3a3a5a",
|
|
4537
|
-
background: sectionMode === "polygon" ? "#4a4a7a" : "#2a2a4a",
|
|
4538
|
-
color: sectionMode === "polygon" ? "#ffffff" : "#d0d0e0",
|
|
4539
|
-
cursor: "pointer",
|
|
4540
|
-
fontSize: 12,
|
|
4541
|
-
fontFamily: "system-ui",
|
|
4542
|
-
fontWeight: 600
|
|
4543
|
-
},
|
|
4544
|
-
children: "Polygon"
|
|
4545
|
-
}
|
|
4546
|
-
)
|
|
4547
|
-
] })
|
|
4548
|
-
]
|
|
5372
|
+
type: "button",
|
|
5373
|
+
className: "seatmap-editor__stepper-button",
|
|
5374
|
+
"aria-label": "Increase seats per row",
|
|
5375
|
+
onClick: () => handleSeatsPerRowChange(seatsPerRow + 1),
|
|
5376
|
+
children: "+"
|
|
4549
5377
|
}
|
|
4550
5378
|
),
|
|
4551
|
-
/* @__PURE__ */
|
|
4552
|
-
"
|
|
5379
|
+
/* @__PURE__ */ jsx(
|
|
5380
|
+
"button",
|
|
4553
5381
|
{
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
padding: "8px 10px",
|
|
4560
|
-
border: "1px solid #3a3a5a",
|
|
4561
|
-
borderRadius: 6,
|
|
4562
|
-
background: "rgba(42, 42, 74, 0.65)"
|
|
4563
|
-
},
|
|
4564
|
-
children: [
|
|
4565
|
-
/* @__PURE__ */ jsx(
|
|
4566
|
-
"span",
|
|
4567
|
-
{
|
|
4568
|
-
style: {
|
|
4569
|
-
color: "#c7c7df",
|
|
4570
|
-
fontSize: 12,
|
|
4571
|
-
fontFamily: "system-ui",
|
|
4572
|
-
fontWeight: 600
|
|
4573
|
-
},
|
|
4574
|
-
children: "Section resize"
|
|
4575
|
-
}
|
|
4576
|
-
),
|
|
4577
|
-
/* @__PURE__ */ jsx(
|
|
4578
|
-
"button",
|
|
4579
|
-
{
|
|
4580
|
-
onClick: () => handleToggleSectionResize(true),
|
|
4581
|
-
style: {
|
|
4582
|
-
padding: "4px 8px",
|
|
4583
|
-
borderRadius: 6,
|
|
4584
|
-
border: "1px solid #3a3a5a",
|
|
4585
|
-
background: sectionResizeEnabled ? "#8a6a32" : "#2a2a4a",
|
|
4586
|
-
color: sectionResizeEnabled ? "#fff3d8" : "#d0d0e0",
|
|
4587
|
-
cursor: "pointer",
|
|
4588
|
-
fontSize: 12,
|
|
4589
|
-
fontFamily: "system-ui",
|
|
4590
|
-
fontWeight: 600
|
|
4591
|
-
},
|
|
4592
|
-
title: "Enable section corner/side resizing",
|
|
4593
|
-
children: sectionResizeEnabled ? "Resize On" : "Resize Off"
|
|
4594
|
-
}
|
|
4595
|
-
)
|
|
4596
|
-
]
|
|
5382
|
+
type: "button",
|
|
5383
|
+
className: "seatmap-editor__stepper-button",
|
|
5384
|
+
"aria-label": "Decrease seats per row",
|
|
5385
|
+
onClick: () => handleSeatsPerRowChange(seatsPerRow - 1),
|
|
5386
|
+
children: "-"
|
|
4597
5387
|
}
|
|
4598
|
-
)
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
);
|
|
4605
|
-
}
|
|
4606
|
-
if (activeToolName === "select") {
|
|
4607
|
-
return /* @__PURE__ */ jsx(
|
|
4608
|
-
"div",
|
|
4609
|
-
{
|
|
4610
|
-
style: {
|
|
4611
|
-
position: "absolute",
|
|
4612
|
-
top: 12,
|
|
4613
|
-
left: 12,
|
|
4614
|
-
right: 12,
|
|
4615
|
-
zIndex: 20,
|
|
4616
|
-
pointerEvents: "none"
|
|
4617
|
-
},
|
|
4618
|
-
children: /* @__PURE__ */ jsxs(
|
|
4619
|
-
"div",
|
|
4620
|
-
{
|
|
4621
|
-
style: {
|
|
4622
|
-
display: "flex",
|
|
4623
|
-
alignItems: "center",
|
|
4624
|
-
gap: 10,
|
|
4625
|
-
padding: "8px 12px",
|
|
4626
|
-
border: "1px solid #3a3a5a",
|
|
4627
|
-
borderRadius: 8,
|
|
4628
|
-
background: "rgba(21, 21, 40, 0.92)",
|
|
4629
|
-
backdropFilter: "blur(2px)",
|
|
4630
|
-
pointerEvents: "auto"
|
|
4631
|
-
},
|
|
4632
|
-
onPointerDown: (e) => e.stopPropagation(),
|
|
4633
|
-
onPointerMove: (e) => e.stopPropagation(),
|
|
4634
|
-
onPointerUp: (e) => e.stopPropagation(),
|
|
4635
|
-
children: [
|
|
5388
|
+
)
|
|
5389
|
+
] })
|
|
5390
|
+
] }),
|
|
5391
|
+
/* @__PURE__ */ jsxs("label", { className: "seatmap-editor__label seatmap-editor__option-row", children: [
|
|
5392
|
+
"Rows:",
|
|
5393
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__input-stepper", children: [
|
|
4636
5394
|
/* @__PURE__ */ jsx(
|
|
4637
|
-
"
|
|
5395
|
+
"input",
|
|
4638
5396
|
{
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
children: "Tool Options"
|
|
5397
|
+
type: "number",
|
|
5398
|
+
min: 1,
|
|
5399
|
+
max: 100,
|
|
5400
|
+
value: rowsCount,
|
|
5401
|
+
onChange: (e) => handleRowsCountChange(Math.max(1, Math.min(100, parseInt(e.target.value) || 1))),
|
|
5402
|
+
className: "seatmap-editor__input seatmap-editor__input--stepper"
|
|
4646
5403
|
}
|
|
4647
5404
|
),
|
|
4648
|
-
/* @__PURE__ */ jsx(
|
|
4649
|
-
|
|
4650
|
-
"div",
|
|
5405
|
+
/* @__PURE__ */ jsx(
|
|
5406
|
+
"button",
|
|
4651
5407
|
{
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
padding: "8px 10px",
|
|
4658
|
-
border: "1px solid #3a3a5a",
|
|
4659
|
-
borderRadius: 6,
|
|
4660
|
-
background: "rgba(42, 42, 74, 0.65)"
|
|
4661
|
-
},
|
|
4662
|
-
children: [
|
|
4663
|
-
/* @__PURE__ */ jsx(
|
|
4664
|
-
"span",
|
|
4665
|
-
{
|
|
4666
|
-
style: {
|
|
4667
|
-
color: "#c7c7df",
|
|
4668
|
-
fontSize: 12,
|
|
4669
|
-
fontFamily: "system-ui",
|
|
4670
|
-
fontWeight: 600
|
|
4671
|
-
},
|
|
4672
|
-
children: "Section resize"
|
|
4673
|
-
}
|
|
4674
|
-
),
|
|
4675
|
-
/* @__PURE__ */ jsx(
|
|
4676
|
-
"button",
|
|
4677
|
-
{
|
|
4678
|
-
onClick: () => handleToggleSectionResize(false),
|
|
4679
|
-
style: {
|
|
4680
|
-
padding: "4px 8px",
|
|
4681
|
-
borderRadius: 6,
|
|
4682
|
-
border: "1px solid #3a3a5a",
|
|
4683
|
-
background: sectionResizeEnabled ? "#8a6a32" : "#2a2a4a",
|
|
4684
|
-
color: sectionResizeEnabled ? "#fff3d8" : "#d0d0e0",
|
|
4685
|
-
cursor: "pointer",
|
|
4686
|
-
fontSize: 12,
|
|
4687
|
-
fontFamily: "system-ui",
|
|
4688
|
-
fontWeight: 600
|
|
4689
|
-
},
|
|
4690
|
-
children: sectionResizeEnabled ? "Resize On" : "Resize Off"
|
|
4691
|
-
}
|
|
4692
|
-
)
|
|
4693
|
-
]
|
|
5408
|
+
type: "button",
|
|
5409
|
+
className: "seatmap-editor__stepper-button",
|
|
5410
|
+
"aria-label": "Increase rows",
|
|
5411
|
+
onClick: () => handleRowsCountChange(rowsCount + 1),
|
|
5412
|
+
children: "+"
|
|
4694
5413
|
}
|
|
4695
5414
|
),
|
|
4696
|
-
isGridOptionsOpen && renderGridOptionsCard()
|
|
4697
|
-
]
|
|
4698
|
-
}
|
|
4699
|
-
)
|
|
4700
|
-
}
|
|
4701
|
-
);
|
|
4702
|
-
}
|
|
4703
|
-
if (activeToolName !== "add-row") {
|
|
4704
|
-
if (!isGridOptionsOpen) return null;
|
|
4705
|
-
return /* @__PURE__ */ jsx(
|
|
4706
|
-
"div",
|
|
4707
|
-
{
|
|
4708
|
-
style: {
|
|
4709
|
-
position: "absolute",
|
|
4710
|
-
top: 12,
|
|
4711
|
-
left: 12,
|
|
4712
|
-
right: 12,
|
|
4713
|
-
zIndex: 20,
|
|
4714
|
-
pointerEvents: "none"
|
|
4715
|
-
},
|
|
4716
|
-
children: /* @__PURE__ */ jsxs(
|
|
4717
|
-
"div",
|
|
4718
|
-
{
|
|
4719
|
-
style: {
|
|
4720
|
-
display: "flex",
|
|
4721
|
-
alignItems: "center",
|
|
4722
|
-
gap: 10,
|
|
4723
|
-
padding: "8px 12px",
|
|
4724
|
-
border: "1px solid #3a3a5a",
|
|
4725
|
-
borderRadius: 8,
|
|
4726
|
-
background: "rgba(21, 21, 40, 0.92)",
|
|
4727
|
-
backdropFilter: "blur(2px)",
|
|
4728
|
-
pointerEvents: "auto"
|
|
4729
|
-
},
|
|
4730
|
-
onPointerDown: (e) => e.stopPropagation(),
|
|
4731
|
-
onPointerMove: (e) => e.stopPropagation(),
|
|
4732
|
-
onPointerUp: (e) => e.stopPropagation(),
|
|
4733
|
-
children: [
|
|
4734
5415
|
/* @__PURE__ */ jsx(
|
|
4735
|
-
"
|
|
5416
|
+
"button",
|
|
4736
5417
|
{
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
},
|
|
4743
|
-
children: "Tool Options"
|
|
5418
|
+
type: "button",
|
|
5419
|
+
className: "seatmap-editor__stepper-button",
|
|
5420
|
+
"aria-label": "Decrease rows",
|
|
5421
|
+
onClick: () => handleRowsCountChange(rowsCount - 1),
|
|
5422
|
+
children: "-"
|
|
4744
5423
|
}
|
|
4745
|
-
)
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
left: 12,
|
|
4761
|
-
right: 12,
|
|
4762
|
-
zIndex: 20,
|
|
4763
|
-
pointerEvents: "none"
|
|
4764
|
-
},
|
|
4765
|
-
children: /* @__PURE__ */ jsxs(
|
|
4766
|
-
"div",
|
|
4767
|
-
{
|
|
4768
|
-
style: {
|
|
4769
|
-
display: "flex",
|
|
4770
|
-
alignItems: "center",
|
|
4771
|
-
gap: 10,
|
|
4772
|
-
padding: "8px 12px",
|
|
4773
|
-
border: "1px solid #3a3a5a",
|
|
4774
|
-
borderRadius: 8,
|
|
4775
|
-
background: "rgba(21, 21, 40, 0.92)",
|
|
4776
|
-
backdropFilter: "blur(2px)",
|
|
4777
|
-
pointerEvents: "auto"
|
|
4778
|
-
},
|
|
4779
|
-
onPointerDown: (e) => e.stopPropagation(),
|
|
4780
|
-
onPointerMove: (e) => e.stopPropagation(),
|
|
4781
|
-
onPointerUp: (e) => e.stopPropagation(),
|
|
4782
|
-
children: [
|
|
4783
|
-
/* @__PURE__ */ jsx(
|
|
4784
|
-
"span",
|
|
4785
|
-
{
|
|
4786
|
-
style: {
|
|
4787
|
-
color: "#c7c7df",
|
|
4788
|
-
fontSize: 12,
|
|
4789
|
-
fontFamily: "system-ui",
|
|
4790
|
-
fontWeight: 600,
|
|
4791
|
-
letterSpacing: 0.2
|
|
4792
|
-
},
|
|
4793
|
-
children: "Tool Options"
|
|
4794
|
-
}
|
|
4795
|
-
),
|
|
4796
|
-
/* @__PURE__ */ jsx("div", { style: { width: 1, height: 18, background: "#3a3a5a" } }),
|
|
4797
|
-
/* @__PURE__ */ jsxs(
|
|
4798
|
-
"div",
|
|
5424
|
+
)
|
|
5425
|
+
] })
|
|
5426
|
+
] }),
|
|
5427
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__option-card-title", children: [
|
|
5428
|
+
"Total seats to add: ",
|
|
5429
|
+
seatsPerRow * Math.max(1, rowsCount)
|
|
5430
|
+
] })
|
|
5431
|
+
] }),
|
|
5432
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__row-layout-separator" }),
|
|
5433
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__row-presets", children: /* @__PURE__ */ jsx("table", { className: "seatmap-editor__row-presets-table", children: /* @__PURE__ */ jsx("tbody", { children: rowPresetRows.map((rowPreset) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
5434
|
+
/* @__PURE__ */ jsx("th", { scope: "row", className: "seatmap-editor__row-preset-row-label", children: rowPreset }),
|
|
5435
|
+
rowPresetSeats.map((seatPreset) => {
|
|
5436
|
+
const isActive = rowsCount === rowPreset && seatsPerRow === seatPreset;
|
|
5437
|
+
return /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(
|
|
5438
|
+
"button",
|
|
4799
5439
|
{
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
padding: "8px 10px",
|
|
4806
|
-
border: "1px solid #3a3a5a",
|
|
4807
|
-
borderRadius: 6,
|
|
4808
|
-
background: "rgba(42, 42, 74, 0.65)"
|
|
5440
|
+
type: "button",
|
|
5441
|
+
className: `seatmap-editor__row-preset-button${isActive ? " is-active" : ""}`,
|
|
5442
|
+
onClick: () => {
|
|
5443
|
+
handleRowsCountChange(rowPreset);
|
|
5444
|
+
handleSeatsPerRowChange(seatPreset);
|
|
4809
5445
|
},
|
|
4810
|
-
children:
|
|
4811
|
-
/* @__PURE__ */ jsx(
|
|
4812
|
-
"span",
|
|
4813
|
-
{
|
|
4814
|
-
style: {
|
|
4815
|
-
color: "#c7c7df",
|
|
4816
|
-
fontSize: 12,
|
|
4817
|
-
fontFamily: "system-ui",
|
|
4818
|
-
fontWeight: 600
|
|
4819
|
-
},
|
|
4820
|
-
children: "Row layout"
|
|
4821
|
-
}
|
|
4822
|
-
),
|
|
4823
|
-
/* @__PURE__ */ jsxs(
|
|
4824
|
-
"label",
|
|
4825
|
-
{
|
|
4826
|
-
style: {
|
|
4827
|
-
color: "#9e9e9e",
|
|
4828
|
-
fontSize: 12,
|
|
4829
|
-
fontFamily: "system-ui",
|
|
4830
|
-
display: "flex",
|
|
4831
|
-
alignItems: "center",
|
|
4832
|
-
gap: 6
|
|
4833
|
-
},
|
|
4834
|
-
children: [
|
|
4835
|
-
"Seats/row:",
|
|
4836
|
-
/* @__PURE__ */ jsx(
|
|
4837
|
-
"input",
|
|
4838
|
-
{
|
|
4839
|
-
type: "number",
|
|
4840
|
-
min: 1,
|
|
4841
|
-
max: 100,
|
|
4842
|
-
value: seatsPerRow,
|
|
4843
|
-
onChange: (e) => handleSeatsPerRowChange(Math.max(1, Math.min(100, parseInt(e.target.value) || 1))),
|
|
4844
|
-
style: {
|
|
4845
|
-
width: 56,
|
|
4846
|
-
padding: "3px 6px",
|
|
4847
|
-
background: "#2a2a4a",
|
|
4848
|
-
border: "1px solid #3a3a5a",
|
|
4849
|
-
borderRadius: 4,
|
|
4850
|
-
color: "#e0e0e0",
|
|
4851
|
-
fontSize: 13,
|
|
4852
|
-
fontFamily: "system-ui"
|
|
4853
|
-
}
|
|
4854
|
-
}
|
|
4855
|
-
)
|
|
4856
|
-
]
|
|
4857
|
-
}
|
|
4858
|
-
),
|
|
4859
|
-
/* @__PURE__ */ jsxs(
|
|
4860
|
-
"label",
|
|
4861
|
-
{
|
|
4862
|
-
style: {
|
|
4863
|
-
color: "#9e9e9e",
|
|
4864
|
-
fontSize: 12,
|
|
4865
|
-
fontFamily: "system-ui",
|
|
4866
|
-
display: "flex",
|
|
4867
|
-
alignItems: "center",
|
|
4868
|
-
gap: 6
|
|
4869
|
-
},
|
|
4870
|
-
children: [
|
|
4871
|
-
"Rows:",
|
|
4872
|
-
/* @__PURE__ */ jsx(
|
|
4873
|
-
"input",
|
|
4874
|
-
{
|
|
4875
|
-
type: "number",
|
|
4876
|
-
min: 1,
|
|
4877
|
-
max: 100,
|
|
4878
|
-
value: rowsCount,
|
|
4879
|
-
onChange: (e) => handleRowsCountChange(Math.max(1, Math.min(100, parseInt(e.target.value) || 1))),
|
|
4880
|
-
style: {
|
|
4881
|
-
width: 56,
|
|
4882
|
-
padding: "3px 6px",
|
|
4883
|
-
background: "#2a2a4a",
|
|
4884
|
-
border: "1px solid #3a3a5a",
|
|
4885
|
-
borderRadius: 4,
|
|
4886
|
-
color: "#e0e0e0",
|
|
4887
|
-
fontSize: 13,
|
|
4888
|
-
fontFamily: "system-ui"
|
|
4889
|
-
}
|
|
4890
|
-
}
|
|
4891
|
-
)
|
|
4892
|
-
]
|
|
4893
|
-
}
|
|
4894
|
-
),
|
|
4895
|
-
/* @__PURE__ */ jsxs(
|
|
4896
|
-
"div",
|
|
4897
|
-
{
|
|
4898
|
-
style: {
|
|
4899
|
-
color: "#c7c7df",
|
|
4900
|
-
fontSize: 12,
|
|
4901
|
-
fontFamily: "system-ui",
|
|
4902
|
-
fontWeight: 600
|
|
4903
|
-
},
|
|
4904
|
-
children: [
|
|
4905
|
-
"Total seats to add: ",
|
|
4906
|
-
seatsPerRow * Math.max(1, rowsCount)
|
|
4907
|
-
]
|
|
4908
|
-
}
|
|
4909
|
-
)
|
|
4910
|
-
]
|
|
5446
|
+
children: seatPreset
|
|
4911
5447
|
}
|
|
4912
|
-
),
|
|
4913
|
-
|
|
4914
|
-
|
|
5448
|
+
) }, `${rowPreset}-${seatPreset}`);
|
|
5449
|
+
})
|
|
5450
|
+
] }, `row-preset-${rowPreset}`)) }) }) })
|
|
5451
|
+
] })),
|
|
5452
|
+
renderOptionCard("Orientation", /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5453
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__option-row seatmap-editor__orientation-toggle", children: [
|
|
5454
|
+
/* @__PURE__ */ jsx(
|
|
5455
|
+
"span",
|
|
5456
|
+
{
|
|
5457
|
+
className: `seatmap-editor__orientation-label${rowDirectionArrowMode === "viewer-direction" ? " is-active" : ""}`,
|
|
5458
|
+
children: "Viewer direction"
|
|
5459
|
+
}
|
|
5460
|
+
),
|
|
5461
|
+
/* @__PURE__ */ jsx(
|
|
5462
|
+
"button",
|
|
5463
|
+
{
|
|
5464
|
+
type: "button",
|
|
5465
|
+
role: "switch",
|
|
5466
|
+
"aria-checked": rowDirectionArrowMode === "row-direction",
|
|
5467
|
+
onClick: () => setRowDirectionArrowMode(
|
|
5468
|
+
(mode) => mode === "row-direction" ? "viewer-direction" : "row-direction"
|
|
5469
|
+
),
|
|
5470
|
+
className: `seatmap-editor__switch-track seatmap-editor__switch-track--wide${rowDirectionArrowMode === "row-direction" ? " is-checked" : ""}`,
|
|
5471
|
+
title: "Toggle arrow orientation mode",
|
|
5472
|
+
children: /* @__PURE__ */ jsx(
|
|
5473
|
+
"span",
|
|
5474
|
+
{
|
|
5475
|
+
className: "seatmap-editor__switch-thumb seatmap-editor__switch-thumb--wide",
|
|
5476
|
+
style: {
|
|
5477
|
+
transform: rowDirectionArrowMode === "row-direction" ? "translateX(22px)" : "translateX(0)"
|
|
5478
|
+
}
|
|
5479
|
+
}
|
|
5480
|
+
)
|
|
5481
|
+
}
|
|
5482
|
+
),
|
|
5483
|
+
/* @__PURE__ */ jsx(
|
|
5484
|
+
"span",
|
|
5485
|
+
{
|
|
5486
|
+
className: `seatmap-editor__orientation-label${rowDirectionArrowMode === "row-direction" ? " is-active" : ""}`,
|
|
5487
|
+
children: "Row direction"
|
|
5488
|
+
}
|
|
5489
|
+
)
|
|
5490
|
+
] }),
|
|
5491
|
+
renderRange(
|
|
5492
|
+
"Orientation",
|
|
5493
|
+
rowOrientationKnobDeg,
|
|
5494
|
+
handleRowOrientationKnobChange,
|
|
5495
|
+
"Drag vertically on the knob to set row orientation.",
|
|
5496
|
+
{
|
|
5497
|
+
min: 0,
|
|
5498
|
+
max: 359,
|
|
5499
|
+
step: 1,
|
|
5500
|
+
valueFormatter: (n) => `${Math.round(n)}\xB0`,
|
|
5501
|
+
displayAsKnob: true,
|
|
5502
|
+
knobMode: "dial360",
|
|
5503
|
+
knobFillStartDeg: 0,
|
|
5504
|
+
knobNamespace: "tool",
|
|
5505
|
+
valuePlacement: "knob",
|
|
5506
|
+
knobRightContent: /* @__PURE__ */ jsx(
|
|
5507
|
+
"button",
|
|
4915
5508
|
{
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
gap: 8,
|
|
4921
|
-
padding: "8px 10px",
|
|
4922
|
-
border: "1px solid #3a3a5a",
|
|
4923
|
-
borderRadius: 6,
|
|
4924
|
-
background: "rgba(42, 42, 74, 0.65)"
|
|
4925
|
-
},
|
|
4926
|
-
children: [
|
|
4927
|
-
/* @__PURE__ */ jsx(
|
|
4928
|
-
"span",
|
|
4929
|
-
{
|
|
4930
|
-
style: {
|
|
4931
|
-
color: "#c7c7df",
|
|
4932
|
-
fontSize: 12,
|
|
4933
|
-
fontFamily: "system-ui",
|
|
4934
|
-
fontWeight: 600
|
|
4935
|
-
},
|
|
4936
|
-
children: "Orientation"
|
|
4937
|
-
}
|
|
4938
|
-
),
|
|
4939
|
-
/* @__PURE__ */ jsxs(
|
|
4940
|
-
"label",
|
|
4941
|
-
{
|
|
4942
|
-
style: {
|
|
4943
|
-
color: "#9e9e9e",
|
|
4944
|
-
fontSize: 12,
|
|
4945
|
-
fontFamily: "system-ui",
|
|
4946
|
-
display: "flex",
|
|
4947
|
-
alignItems: "center",
|
|
4948
|
-
gap: 6
|
|
4949
|
-
},
|
|
4950
|
-
children: [
|
|
4951
|
-
"Orientation:",
|
|
4952
|
-
/* @__PURE__ */ jsx(
|
|
4953
|
-
"input",
|
|
4954
|
-
{
|
|
4955
|
-
type: "number",
|
|
4956
|
-
min: 0,
|
|
4957
|
-
max: 359,
|
|
4958
|
-
value: rowOrientationDeg,
|
|
4959
|
-
onChange: (e) => handleRowOrientationChange(parseInt(e.target.value, 10) || 0),
|
|
4960
|
-
style: {
|
|
4961
|
-
width: 56,
|
|
4962
|
-
padding: "3px 6px",
|
|
4963
|
-
background: "#2a2a4a",
|
|
4964
|
-
border: "1px solid #3a3a5a",
|
|
4965
|
-
borderRadius: 4,
|
|
4966
|
-
color: "#e0e0e0",
|
|
4967
|
-
fontSize: 13,
|
|
4968
|
-
fontFamily: "system-ui"
|
|
4969
|
-
}
|
|
4970
|
-
}
|
|
4971
|
-
),
|
|
4972
|
-
/* @__PURE__ */ jsx("span", { style: { color: "#9e9e9e" }, children: "deg" }),
|
|
4973
|
-
/* @__PURE__ */ jsx(
|
|
4974
|
-
"button",
|
|
4975
|
-
{
|
|
4976
|
-
onClick: handleRotateRowOrientationQuarterTurn,
|
|
4977
|
-
style: {
|
|
4978
|
-
padding: "3px 6px",
|
|
4979
|
-
borderRadius: 4,
|
|
4980
|
-
border: "1px solid #3a3a5a",
|
|
4981
|
-
background: "#2a2a4a",
|
|
4982
|
-
color: "#d0d0e0",
|
|
4983
|
-
cursor: "pointer",
|
|
4984
|
-
fontSize: 12,
|
|
4985
|
-
fontFamily: "system-ui",
|
|
4986
|
-
fontWeight: 600
|
|
4987
|
-
},
|
|
4988
|
-
title: "Rotate row direction by 90 degrees",
|
|
4989
|
-
children: "+90deg"
|
|
4990
|
-
}
|
|
4991
|
-
)
|
|
4992
|
-
]
|
|
4993
|
-
}
|
|
4994
|
-
),
|
|
4995
|
-
/* @__PURE__ */ jsx(
|
|
4996
|
-
"div",
|
|
4997
|
-
{
|
|
4998
|
-
style: {
|
|
4999
|
-
color: "#9e9e9e",
|
|
5000
|
-
fontSize: 11,
|
|
5001
|
-
fontFamily: "system-ui"
|
|
5002
|
-
},
|
|
5003
|
-
children: "0deg = up, 90deg = right"
|
|
5004
|
-
}
|
|
5005
|
-
)
|
|
5006
|
-
]
|
|
5509
|
+
onClick: handleRotateRowOrientationQuarterTurn,
|
|
5510
|
+
className: "seatmap-editor__segmented-button",
|
|
5511
|
+
title: "Rotate row direction by 90 degrees",
|
|
5512
|
+
children: "+90\xB0"
|
|
5007
5513
|
}
|
|
5008
|
-
)
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
}
|
|
5012
|
-
)
|
|
5013
|
-
|
|
5514
|
+
)
|
|
5515
|
+
}
|
|
5516
|
+
),
|
|
5517
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__hint-text", children: rowDirectionArrowMode === "row-direction" ? "Arrow: row direction (viewer +90\xB0)" : "Arrow: viewer direction (0\xB0 = up, 90\xB0 = right)" })
|
|
5518
|
+
] })),
|
|
5519
|
+
isGridOptionsOpen && renderGridOptionsCard(),
|
|
5520
|
+
isEditorSettingsOpen && renderMotionSettingsCard()
|
|
5521
|
+
] })
|
|
5014
5522
|
);
|
|
5015
5523
|
};
|
|
5016
5524
|
useEffect(() => {
|
|
5017
5525
|
const isTyping = () => {
|
|
5018
|
-
const
|
|
5019
|
-
|
|
5526
|
+
const activeElement = document.activeElement;
|
|
5527
|
+
if (!activeElement) return false;
|
|
5528
|
+
const tag = activeElement.tagName;
|
|
5529
|
+
return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || activeElement.isContentEditable;
|
|
5020
5530
|
};
|
|
5021
5531
|
const handler = (e) => {
|
|
5022
5532
|
if ((e.metaKey || e.ctrlKey) && e.key === "z") {
|
|
@@ -5026,8 +5536,18 @@ function EditorInner({
|
|
|
5026
5536
|
return;
|
|
5027
5537
|
}
|
|
5028
5538
|
if (isTyping()) return;
|
|
5029
|
-
if (e.key === "
|
|
5030
|
-
|
|
5539
|
+
if (e.key === "Delete" || e.key === "Backspace") {
|
|
5540
|
+
e.preventDefault();
|
|
5541
|
+
handleDeleteSelectedObjects();
|
|
5542
|
+
return;
|
|
5543
|
+
}
|
|
5544
|
+
if (e.key === "Escape" && activeToolName === "add-section") {
|
|
5545
|
+
e.preventDefault();
|
|
5546
|
+
addSectionTool.cancelDrawing();
|
|
5547
|
+
return;
|
|
5548
|
+
}
|
|
5549
|
+
if (e.key === "v" || e.key === "2") setActiveTool("select");
|
|
5550
|
+
if (e.key === "h" || e.key === "1") setActiveTool("pan");
|
|
5031
5551
|
if (e.key === "s" || e.key === "3") setActiveTool("add-section");
|
|
5032
5552
|
if (e.key === "r" || e.key === "4") setActiveTool("add-row");
|
|
5033
5553
|
if (e.key === "a" || e.key === "5") setActiveTool("add-seat");
|
|
@@ -5048,7 +5568,7 @@ function EditorInner({
|
|
|
5048
5568
|
window.removeEventListener("keydown", handler);
|
|
5049
5569
|
window.removeEventListener("keyup", upHandler);
|
|
5050
5570
|
};
|
|
5051
|
-
}, [setActiveTool, activeToolName]);
|
|
5571
|
+
}, [setActiveTool, activeToolName, handleDeleteSelectedObjects, addSectionTool]);
|
|
5052
5572
|
const toToolPointerEvent = useCallback(
|
|
5053
5573
|
(e) => {
|
|
5054
5574
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
@@ -5095,6 +5615,11 @@ function EditorInner({
|
|
|
5095
5615
|
(e) => {
|
|
5096
5616
|
const toolEvent = toToolPointerEvent(e);
|
|
5097
5617
|
activeToolRef.current.onPointerMove(toolEvent, viewport, store);
|
|
5618
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
5619
|
+
setCursorScreenPoint({
|
|
5620
|
+
x: e.clientX - rect.left,
|
|
5621
|
+
y: e.clientY - rect.top
|
|
5622
|
+
});
|
|
5098
5623
|
if (activeToolName === "add-row") {
|
|
5099
5624
|
setRowPreviewPoint({ x: toolEvent.worldX, y: toolEvent.worldY });
|
|
5100
5625
|
}
|
|
@@ -5110,14 +5635,7 @@ function EditorInner({
|
|
|
5110
5635
|
(e) => handlePointerRelease(e),
|
|
5111
5636
|
[handlePointerRelease]
|
|
5112
5637
|
);
|
|
5113
|
-
|
|
5114
|
-
width: 260,
|
|
5115
|
-
background: "#1a1a2e",
|
|
5116
|
-
borderLeft: "1px solid #2a2a4a",
|
|
5117
|
-
overflowY: "auto",
|
|
5118
|
-
flexShrink: 0
|
|
5119
|
-
};
|
|
5120
|
-
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", width: "100%", height: "100%" }, children: [
|
|
5638
|
+
return /* @__PURE__ */ jsxs("div", { className: "seatmap-editor seatmap-editor--root", children: [
|
|
5121
5639
|
/* @__PURE__ */ jsx(
|
|
5122
5640
|
Toolbar,
|
|
5123
5641
|
{
|
|
@@ -5132,19 +5650,25 @@ function EditorInner({
|
|
|
5132
5650
|
onRedo: () => historyRef.current.redo(),
|
|
5133
5651
|
onFitView: handleFitView,
|
|
5134
5652
|
onSave: handleSave,
|
|
5135
|
-
onLoad: handleLoad
|
|
5653
|
+
onLoad: handleLoad,
|
|
5654
|
+
showHints,
|
|
5655
|
+
onToggleHints: () => setShowHints((current) => !current),
|
|
5656
|
+
isEditorSettingsOpen,
|
|
5657
|
+
onToggleEditorSettings: () => setIsEditorSettingsOpen((current) => !current)
|
|
5136
5658
|
}
|
|
5137
5659
|
),
|
|
5138
|
-
/* @__PURE__ */ jsxs("div", {
|
|
5660
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__canvas-layout", children: [
|
|
5139
5661
|
/* @__PURE__ */ jsxs(
|
|
5140
5662
|
"div",
|
|
5141
5663
|
{
|
|
5142
5664
|
ref: canvasAreaRef,
|
|
5143
|
-
|
|
5665
|
+
className: "seatmap-editor__canvas-area",
|
|
5666
|
+
style: { cursor: (toolMap[activeToolName] ?? selectTool).cursor },
|
|
5144
5667
|
onPointerDown: handleCanvasPointerDown,
|
|
5145
5668
|
onPointerMove: handleCanvasPointerMove,
|
|
5146
5669
|
onPointerUp: handleCanvasPointerUp,
|
|
5147
5670
|
onPointerCancel: handleCanvasPointerCancel,
|
|
5671
|
+
onPointerLeave: () => setCursorScreenPoint(null),
|
|
5148
5672
|
children: [
|
|
5149
5673
|
/* @__PURE__ */ jsx(
|
|
5150
5674
|
SeatmapCanvas,
|
|
@@ -5153,7 +5677,15 @@ function EditorInner({
|
|
|
5153
5677
|
showGridLines: gridEnabled && showCanvasGrid,
|
|
5154
5678
|
showSectionGridDots: gridEnabled && showSectionGrid,
|
|
5155
5679
|
canvasGridLineStyle: canvasGridStyle,
|
|
5156
|
-
sectionGridMarkerStyle: sectionGridStyle
|
|
5680
|
+
sectionGridMarkerStyle: sectionGridStyle,
|
|
5681
|
+
panInertiaJelly,
|
|
5682
|
+
panInertiaCarry: useAdvancedMotion ? panInertiaCarryPct / 100 : void 0,
|
|
5683
|
+
panInertiaFriction: useAdvancedMotion ? panInertiaFrictionPct / 100 : void 0,
|
|
5684
|
+
panInertiaMinSpeed: useAdvancedMotion ? panInertiaMinSpeedMilli / 1e3 : void 0,
|
|
5685
|
+
pointerScrollZoomJelly,
|
|
5686
|
+
pointerScrollZoomDurationMs: useAdvancedMotion ? pointerScrollZoomDurationMs : void 0,
|
|
5687
|
+
pointerScrollZoomStrengthPct: useAdvancedMotion ? pointerScrollZoomStrengthPct : void 0,
|
|
5688
|
+
pointerScrollZoomDeltaDivisor: useAdvancedMotion ? pointerScrollZoomDeltaDivisor : void 0
|
|
5157
5689
|
}
|
|
5158
5690
|
),
|
|
5159
5691
|
/* @__PURE__ */ jsx(
|
|
@@ -5176,11 +5708,22 @@ function EditorInner({
|
|
|
5176
5708
|
mode: sectionMode,
|
|
5177
5709
|
viewport
|
|
5178
5710
|
}
|
|
5711
|
+
),
|
|
5712
|
+
showHints && sectionHintText && cursorScreenPoint && /* @__PURE__ */ jsx(
|
|
5713
|
+
"div",
|
|
5714
|
+
{
|
|
5715
|
+
className: "seatmap-editor__hint-bubble",
|
|
5716
|
+
style: {
|
|
5717
|
+
left: cursorScreenPoint.x + 14,
|
|
5718
|
+
top: cursorScreenPoint.y + 14
|
|
5719
|
+
},
|
|
5720
|
+
children: sectionHintText
|
|
5721
|
+
}
|
|
5179
5722
|
)
|
|
5180
5723
|
]
|
|
5181
5724
|
}
|
|
5182
5725
|
),
|
|
5183
|
-
/* @__PURE__ */ jsxs("div", {
|
|
5726
|
+
/* @__PURE__ */ jsxs("div", { className: "seatmap-editor__sidebar", children: [
|
|
5184
5727
|
/* @__PURE__ */ jsx(
|
|
5185
5728
|
PropertyPanel,
|
|
5186
5729
|
{
|
|
@@ -5197,7 +5740,7 @@ function EditorInner({
|
|
|
5197
5740
|
}
|
|
5198
5741
|
),
|
|
5199
5742
|
selectedSeatIds.size === 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5200
|
-
/* @__PURE__ */ jsx("div", {
|
|
5743
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__sidebar-separator" }),
|
|
5201
5744
|
/* @__PURE__ */ jsx(
|
|
5202
5745
|
LayerPanel,
|
|
5203
5746
|
{
|
|
@@ -5207,7 +5750,7 @@ function EditorInner({
|
|
|
5207
5750
|
onSelectSection: handleSelectSection
|
|
5208
5751
|
}
|
|
5209
5752
|
),
|
|
5210
|
-
/* @__PURE__ */ jsx("div", {
|
|
5753
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__sidebar-separator" }),
|
|
5211
5754
|
/* @__PURE__ */ jsx(
|
|
5212
5755
|
CategoryManager,
|
|
5213
5756
|
{
|
|
@@ -5219,7 +5762,7 @@ function EditorInner({
|
|
|
5219
5762
|
)
|
|
5220
5763
|
] }),
|
|
5221
5764
|
selectedSeatIds.size === 0 && selectedSectionIds.size === 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5222
|
-
/* @__PURE__ */ jsx("div", {
|
|
5765
|
+
/* @__PURE__ */ jsx("div", { className: "seatmap-editor__sidebar-separator" }),
|
|
5223
5766
|
/* @__PURE__ */ jsx(
|
|
5224
5767
|
StatusManager,
|
|
5225
5768
|
{
|
|
@@ -5234,7 +5777,7 @@ function EditorInner({
|
|
|
5234
5777
|
] });
|
|
5235
5778
|
}
|
|
5236
5779
|
function SeatmapEditor({ venue, onChange, onSave, fetchCategoryPrices, className }) {
|
|
5237
|
-
return /* @__PURE__ */ jsx(SeatmapProvider, { venue, children: /* @__PURE__ */ jsx("div", { className
|
|
5780
|
+
return /* @__PURE__ */ jsx(SeatmapProvider, { venue, children: /* @__PURE__ */ jsx("div", { className: className ? `seatmap-editor__host ${className}` : "seatmap-editor__host", children: /* @__PURE__ */ jsx(EditorInner, { onChange, onSave, fetchCategoryPrices }) }) });
|
|
5238
5781
|
}
|
|
5239
5782
|
var DrawGATool = class extends BaseTool {
|
|
5240
5783
|
constructor(history) {
|