@zonetrix/shared 1.0.0

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.
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Centralized type definitions for the Seat Map Studio packages
3
+ */
4
+ type SeatState = "available" | "reserved" | "selected" | "unavailable";
5
+ type SeatShape = "circle" | "square" | "rounded-square";
6
+ type Tool = "select" | "seat" | "row" | "section" | "stage";
7
+ type EditorMode = "edit" | "read";
8
+ /**
9
+ * Seat data structure used in the editor and viewer
10
+ */
11
+ interface SeatData {
12
+ seatState: SeatState;
13
+ shape?: SeatShape;
14
+ sectionName?: string;
15
+ rowLabel?: string;
16
+ columnLabel?: string;
17
+ price?: number;
18
+ seatNumber?: string;
19
+ }
20
+ /**
21
+ * Section configuration for creating seat groups
22
+ */
23
+ interface SectionConfig {
24
+ name: string;
25
+ rows: number;
26
+ columns: number;
27
+ startRow?: string;
28
+ startColumn?: number;
29
+ price?: number;
30
+ color?: string;
31
+ locked?: boolean;
32
+ }
33
+ /**
34
+ * Row pricing structure for section-based pricing
35
+ */
36
+ interface RowPricing {
37
+ sectionName: string;
38
+ rowLabel: string;
39
+ price: number;
40
+ }
41
+ /**
42
+ * Stage configuration for theater/venue stages
43
+ */
44
+ interface StageConfig {
45
+ label: string;
46
+ width: number;
47
+ height: number;
48
+ rotation?: number;
49
+ color?: string;
50
+ }
51
+ /**
52
+ * Color settings for customizing the appearance
53
+ */
54
+ interface ColorSettings {
55
+ canvasBackground: string;
56
+ stageColor: string;
57
+ seatAvailable: string;
58
+ seatReserved: string;
59
+ seatSelected: string;
60
+ seatUnavailable: string;
61
+ gridLines: string;
62
+ currency: string;
63
+ }
64
+ /**
65
+ * Default color palette
66
+ */
67
+ declare const DEFAULT_COLORS: ColorSettings;
68
+ /**
69
+ * Alignment guide for visual assistance
70
+ */
71
+ interface AlignmentGuide {
72
+ position: number;
73
+ orientation: "horizontal" | "vertical";
74
+ }
75
+ /**
76
+ * Canvas state for view management
77
+ */
78
+ interface CanvasState {
79
+ zoom: number;
80
+ panX: number;
81
+ panY: number;
82
+ gridSize: number;
83
+ gridEnabled: boolean;
84
+ snapToGrid: boolean;
85
+ }
86
+ /**
87
+ * Booking selection for read mode
88
+ */
89
+ interface BookingSelection {
90
+ seats: SeatData[];
91
+ totalPrice: number;
92
+ count: number;
93
+ }
94
+ declare const calculateSeatPrice: (seat: SeatData, rowPricing: RowPricing[], sectionPrice?: number) => number;
95
+ /**
96
+ * Serialized seat for JSON export/import
97
+ */
98
+ interface SerializedSeat {
99
+ id: string;
100
+ position: {
101
+ x: number;
102
+ y: number;
103
+ };
104
+ shape: SeatShape;
105
+ state: SeatState;
106
+ sectionName?: string;
107
+ rowLabel?: string;
108
+ columnLabel?: string;
109
+ seatNumber?: string;
110
+ price?: number;
111
+ }
112
+ /**
113
+ * Serialized section for JSON export/import
114
+ */
115
+ interface SerializedSection {
116
+ id: string;
117
+ name: string;
118
+ position: {
119
+ x: number;
120
+ y: number;
121
+ };
122
+ config: SectionConfig;
123
+ seatIds: string[];
124
+ }
125
+ /**
126
+ * Serialized stage for JSON export/import
127
+ */
128
+ interface SerializedStage {
129
+ id: string;
130
+ position: {
131
+ x: number;
132
+ y: number;
133
+ };
134
+ config: StageConfig;
135
+ }
136
+ /**
137
+ * Canvas configuration for export/import
138
+ */
139
+ interface CanvasConfig {
140
+ width: number;
141
+ height: number;
142
+ backgroundColor: string;
143
+ }
144
+ /**
145
+ * Metadata for seat map configuration
146
+ */
147
+ interface SeatMapMetadata {
148
+ name: string;
149
+ description?: string;
150
+ createdAt: string;
151
+ updatedAt: string;
152
+ venue?: string;
153
+ capacity?: number;
154
+ }
155
+ /**
156
+ * Complete seat map configuration for export/import
157
+ * This is the main interface used for JSON serialization
158
+ */
159
+ interface SeatMapConfig {
160
+ version: string;
161
+ metadata: SeatMapMetadata;
162
+ canvas: CanvasConfig;
163
+ colors: ColorSettings;
164
+ seats: SerializedSeat[];
165
+ sections?: SerializedSection[];
166
+ stages?: SerializedStage[];
167
+ }
168
+ /**
169
+ * Validation result for config validation
170
+ */
171
+ interface ValidationResult {
172
+ valid: boolean;
173
+ errors: string[];
174
+ warnings: string[];
175
+ }
176
+
177
+ /**
178
+ * Validates a seat map configuration
179
+ */
180
+ declare function validateSeatMapConfig(config: any): ValidationResult;
181
+ /**
182
+ * Generates a unique ID for seat map objects
183
+ */
184
+ declare function generateId(prefix?: string): string;
185
+ /**
186
+ * Formats a date for metadata
187
+ */
188
+ declare function formatDate(date?: Date): string;
189
+
190
+ /**
191
+ * Creates a default seat map configuration
192
+ */
193
+ declare function createDefaultConfig(name?: string): SeatMapConfig;
194
+ /**
195
+ * Updates the metadata timestamp
196
+ */
197
+ declare function updateConfigTimestamp(config: SeatMapConfig): SeatMapConfig;
198
+ /**
199
+ * Merges seat state overrides into a config
200
+ * @param config - Base configuration
201
+ * @param reservedSeats - Array of seat IDs to mark as reserved
202
+ * @param unavailableSeats - Array of seat IDs to mark as unavailable
203
+ */
204
+ declare function applySeatStateOverrides(config: SeatMapConfig, reservedSeats?: string[], unavailableSeats?: string[]): SeatMapConfig;
205
+ /**
206
+ * Extracts selected seats from a config
207
+ */
208
+ declare function getSelectedSeats(config: SeatMapConfig): SerializedSeat[];
209
+ /**
210
+ * Calculates total capacity of a seat map
211
+ */
212
+ declare function calculateCapacity(config: SeatMapConfig): number;
213
+ /**
214
+ * Calculates available seats count
215
+ */
216
+ declare function calculateAvailableSeats(config: SeatMapConfig): number;
217
+ /**
218
+ * Deep clones a seat map config
219
+ */
220
+ declare function cloneConfig(config: SeatMapConfig): SeatMapConfig;
221
+ /**
222
+ * Exports config as JSON string
223
+ */
224
+ declare function exportConfigAsJSON(config: SeatMapConfig, pretty?: boolean): string;
225
+ /**
226
+ * Imports config from JSON string
227
+ */
228
+ declare function importConfigFromJSON(jsonString: string): SeatMapConfig;
229
+ /**
230
+ * Downloads config as a JSON file
231
+ * Note: This function is meant for browser environments
232
+ */
233
+ declare function downloadConfigAsFile(config: SeatMapConfig, filename?: string): void;
234
+
235
+ export { type AlignmentGuide, type BookingSelection, type CanvasConfig, type CanvasState, type ColorSettings, DEFAULT_COLORS, type EditorMode, type RowPricing, type SeatData, type SeatMapConfig, type SeatMapMetadata, type SeatShape, type SeatState, type SectionConfig, type SerializedSeat, type SerializedSection, type SerializedStage, type StageConfig, type Tool, type ValidationResult, applySeatStateOverrides, calculateAvailableSeats, calculateCapacity, calculateSeatPrice, cloneConfig, createDefaultConfig, downloadConfigAsFile, exportConfigAsJSON, formatDate, generateId, getSelectedSeats, importConfigFromJSON, updateConfigTimestamp, validateSeatMapConfig };
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Centralized type definitions for the Seat Map Studio packages
3
+ */
4
+ type SeatState = "available" | "reserved" | "selected" | "unavailable";
5
+ type SeatShape = "circle" | "square" | "rounded-square";
6
+ type Tool = "select" | "seat" | "row" | "section" | "stage";
7
+ type EditorMode = "edit" | "read";
8
+ /**
9
+ * Seat data structure used in the editor and viewer
10
+ */
11
+ interface SeatData {
12
+ seatState: SeatState;
13
+ shape?: SeatShape;
14
+ sectionName?: string;
15
+ rowLabel?: string;
16
+ columnLabel?: string;
17
+ price?: number;
18
+ seatNumber?: string;
19
+ }
20
+ /**
21
+ * Section configuration for creating seat groups
22
+ */
23
+ interface SectionConfig {
24
+ name: string;
25
+ rows: number;
26
+ columns: number;
27
+ startRow?: string;
28
+ startColumn?: number;
29
+ price?: number;
30
+ color?: string;
31
+ locked?: boolean;
32
+ }
33
+ /**
34
+ * Row pricing structure for section-based pricing
35
+ */
36
+ interface RowPricing {
37
+ sectionName: string;
38
+ rowLabel: string;
39
+ price: number;
40
+ }
41
+ /**
42
+ * Stage configuration for theater/venue stages
43
+ */
44
+ interface StageConfig {
45
+ label: string;
46
+ width: number;
47
+ height: number;
48
+ rotation?: number;
49
+ color?: string;
50
+ }
51
+ /**
52
+ * Color settings for customizing the appearance
53
+ */
54
+ interface ColorSettings {
55
+ canvasBackground: string;
56
+ stageColor: string;
57
+ seatAvailable: string;
58
+ seatReserved: string;
59
+ seatSelected: string;
60
+ seatUnavailable: string;
61
+ gridLines: string;
62
+ currency: string;
63
+ }
64
+ /**
65
+ * Default color palette
66
+ */
67
+ declare const DEFAULT_COLORS: ColorSettings;
68
+ /**
69
+ * Alignment guide for visual assistance
70
+ */
71
+ interface AlignmentGuide {
72
+ position: number;
73
+ orientation: "horizontal" | "vertical";
74
+ }
75
+ /**
76
+ * Canvas state for view management
77
+ */
78
+ interface CanvasState {
79
+ zoom: number;
80
+ panX: number;
81
+ panY: number;
82
+ gridSize: number;
83
+ gridEnabled: boolean;
84
+ snapToGrid: boolean;
85
+ }
86
+ /**
87
+ * Booking selection for read mode
88
+ */
89
+ interface BookingSelection {
90
+ seats: SeatData[];
91
+ totalPrice: number;
92
+ count: number;
93
+ }
94
+ declare const calculateSeatPrice: (seat: SeatData, rowPricing: RowPricing[], sectionPrice?: number) => number;
95
+ /**
96
+ * Serialized seat for JSON export/import
97
+ */
98
+ interface SerializedSeat {
99
+ id: string;
100
+ position: {
101
+ x: number;
102
+ y: number;
103
+ };
104
+ shape: SeatShape;
105
+ state: SeatState;
106
+ sectionName?: string;
107
+ rowLabel?: string;
108
+ columnLabel?: string;
109
+ seatNumber?: string;
110
+ price?: number;
111
+ }
112
+ /**
113
+ * Serialized section for JSON export/import
114
+ */
115
+ interface SerializedSection {
116
+ id: string;
117
+ name: string;
118
+ position: {
119
+ x: number;
120
+ y: number;
121
+ };
122
+ config: SectionConfig;
123
+ seatIds: string[];
124
+ }
125
+ /**
126
+ * Serialized stage for JSON export/import
127
+ */
128
+ interface SerializedStage {
129
+ id: string;
130
+ position: {
131
+ x: number;
132
+ y: number;
133
+ };
134
+ config: StageConfig;
135
+ }
136
+ /**
137
+ * Canvas configuration for export/import
138
+ */
139
+ interface CanvasConfig {
140
+ width: number;
141
+ height: number;
142
+ backgroundColor: string;
143
+ }
144
+ /**
145
+ * Metadata for seat map configuration
146
+ */
147
+ interface SeatMapMetadata {
148
+ name: string;
149
+ description?: string;
150
+ createdAt: string;
151
+ updatedAt: string;
152
+ venue?: string;
153
+ capacity?: number;
154
+ }
155
+ /**
156
+ * Complete seat map configuration for export/import
157
+ * This is the main interface used for JSON serialization
158
+ */
159
+ interface SeatMapConfig {
160
+ version: string;
161
+ metadata: SeatMapMetadata;
162
+ canvas: CanvasConfig;
163
+ colors: ColorSettings;
164
+ seats: SerializedSeat[];
165
+ sections?: SerializedSection[];
166
+ stages?: SerializedStage[];
167
+ }
168
+ /**
169
+ * Validation result for config validation
170
+ */
171
+ interface ValidationResult {
172
+ valid: boolean;
173
+ errors: string[];
174
+ warnings: string[];
175
+ }
176
+
177
+ /**
178
+ * Validates a seat map configuration
179
+ */
180
+ declare function validateSeatMapConfig(config: any): ValidationResult;
181
+ /**
182
+ * Generates a unique ID for seat map objects
183
+ */
184
+ declare function generateId(prefix?: string): string;
185
+ /**
186
+ * Formats a date for metadata
187
+ */
188
+ declare function formatDate(date?: Date): string;
189
+
190
+ /**
191
+ * Creates a default seat map configuration
192
+ */
193
+ declare function createDefaultConfig(name?: string): SeatMapConfig;
194
+ /**
195
+ * Updates the metadata timestamp
196
+ */
197
+ declare function updateConfigTimestamp(config: SeatMapConfig): SeatMapConfig;
198
+ /**
199
+ * Merges seat state overrides into a config
200
+ * @param config - Base configuration
201
+ * @param reservedSeats - Array of seat IDs to mark as reserved
202
+ * @param unavailableSeats - Array of seat IDs to mark as unavailable
203
+ */
204
+ declare function applySeatStateOverrides(config: SeatMapConfig, reservedSeats?: string[], unavailableSeats?: string[]): SeatMapConfig;
205
+ /**
206
+ * Extracts selected seats from a config
207
+ */
208
+ declare function getSelectedSeats(config: SeatMapConfig): SerializedSeat[];
209
+ /**
210
+ * Calculates total capacity of a seat map
211
+ */
212
+ declare function calculateCapacity(config: SeatMapConfig): number;
213
+ /**
214
+ * Calculates available seats count
215
+ */
216
+ declare function calculateAvailableSeats(config: SeatMapConfig): number;
217
+ /**
218
+ * Deep clones a seat map config
219
+ */
220
+ declare function cloneConfig(config: SeatMapConfig): SeatMapConfig;
221
+ /**
222
+ * Exports config as JSON string
223
+ */
224
+ declare function exportConfigAsJSON(config: SeatMapConfig, pretty?: boolean): string;
225
+ /**
226
+ * Imports config from JSON string
227
+ */
228
+ declare function importConfigFromJSON(jsonString: string): SeatMapConfig;
229
+ /**
230
+ * Downloads config as a JSON file
231
+ * Note: This function is meant for browser environments
232
+ */
233
+ declare function downloadConfigAsFile(config: SeatMapConfig, filename?: string): void;
234
+
235
+ export { type AlignmentGuide, type BookingSelection, type CanvasConfig, type CanvasState, type ColorSettings, DEFAULT_COLORS, type EditorMode, type RowPricing, type SeatData, type SeatMapConfig, type SeatMapMetadata, type SeatShape, type SeatState, type SectionConfig, type SerializedSeat, type SerializedSection, type SerializedStage, type StageConfig, type Tool, type ValidationResult, applySeatStateOverrides, calculateAvailableSeats, calculateCapacity, calculateSeatPrice, cloneConfig, createDefaultConfig, downloadConfigAsFile, exportConfigAsJSON, formatDate, generateId, getSelectedSeats, importConfigFromJSON, updateConfigTimestamp, validateSeatMapConfig };
package/dist/index.js ADDED
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DEFAULT_COLORS: () => DEFAULT_COLORS,
24
+ applySeatStateOverrides: () => applySeatStateOverrides,
25
+ calculateAvailableSeats: () => calculateAvailableSeats,
26
+ calculateCapacity: () => calculateCapacity,
27
+ calculateSeatPrice: () => calculateSeatPrice,
28
+ cloneConfig: () => cloneConfig,
29
+ createDefaultConfig: () => createDefaultConfig,
30
+ downloadConfigAsFile: () => downloadConfigAsFile,
31
+ exportConfigAsJSON: () => exportConfigAsJSON,
32
+ formatDate: () => formatDate,
33
+ generateId: () => generateId,
34
+ getSelectedSeats: () => getSelectedSeats,
35
+ importConfigFromJSON: () => importConfigFromJSON,
36
+ updateConfigTimestamp: () => updateConfigTimestamp,
37
+ validateSeatMapConfig: () => validateSeatMapConfig
38
+ });
39
+ module.exports = __toCommonJS(index_exports);
40
+
41
+ // src/types/seatMap.ts
42
+ var DEFAULT_COLORS = {
43
+ canvasBackground: "#1a1a1a",
44
+ stageColor: "#808080",
45
+ seatAvailable: "#2C2B30",
46
+ seatReserved: "#FCEA00",
47
+ seatSelected: "#3A7DE5",
48
+ seatUnavailable: "#6b7280",
49
+ gridLines: "#404040",
50
+ currency: "KD"
51
+ };
52
+ var calculateSeatPrice = (seat, rowPricing, sectionPrice) => {
53
+ if (seat.price !== void 0) return seat.price;
54
+ const rowPrice = rowPricing.find(
55
+ (rp) => rp.sectionName === seat.sectionName && rp.rowLabel === seat.rowLabel
56
+ );
57
+ if (rowPrice) return rowPrice.price;
58
+ return sectionPrice || 0;
59
+ };
60
+
61
+ // src/utils/validator.ts
62
+ function validateSeatMapConfig(config) {
63
+ const errors = [];
64
+ const warnings = [];
65
+ if (!config) {
66
+ errors.push("Config is null or undefined");
67
+ return { valid: false, errors, warnings };
68
+ }
69
+ if (!config.version || typeof config.version !== "string") {
70
+ errors.push("Missing or invalid version field");
71
+ }
72
+ if (!config.metadata) {
73
+ errors.push("Missing metadata");
74
+ } else {
75
+ if (!config.metadata.name || typeof config.metadata.name !== "string") {
76
+ errors.push("Missing or invalid metadata.name");
77
+ }
78
+ if (!config.metadata.createdAt || typeof config.metadata.createdAt !== "string") {
79
+ warnings.push("Missing or invalid metadata.createdAt");
80
+ }
81
+ if (!config.metadata.updatedAt || typeof config.metadata.updatedAt !== "string") {
82
+ warnings.push("Missing or invalid metadata.updatedAt");
83
+ }
84
+ }
85
+ if (!config.canvas) {
86
+ errors.push("Missing canvas configuration");
87
+ } else {
88
+ if (typeof config.canvas.width !== "number" || config.canvas.width <= 0) {
89
+ errors.push("Invalid canvas width");
90
+ }
91
+ if (typeof config.canvas.height !== "number" || config.canvas.height <= 0) {
92
+ errors.push("Invalid canvas height");
93
+ }
94
+ if (!config.canvas.backgroundColor || typeof config.canvas.backgroundColor !== "string") {
95
+ warnings.push("Missing or invalid canvas background color");
96
+ }
97
+ }
98
+ if (!config.colors) {
99
+ warnings.push("Missing color configuration");
100
+ } else {
101
+ const requiredColors = [
102
+ "canvasBackground",
103
+ "stageColor",
104
+ "seatAvailable",
105
+ "seatReserved",
106
+ "seatSelected",
107
+ "seatUnavailable",
108
+ "gridLines"
109
+ ];
110
+ requiredColors.forEach((color) => {
111
+ if (!config.colors[color] || typeof config.colors[color] !== "string") {
112
+ warnings.push(`Missing or invalid color: ${color}`);
113
+ }
114
+ });
115
+ }
116
+ if (!config.seats || !Array.isArray(config.seats)) {
117
+ errors.push("Missing or invalid seats array");
118
+ } else {
119
+ config.seats.forEach((seat, index) => {
120
+ if (!seat.id || typeof seat.id !== "string") {
121
+ errors.push(`Seat at index ${index} missing or invalid id`);
122
+ }
123
+ if (!seat.position || typeof seat.position.x !== "number" || typeof seat.position.y !== "number") {
124
+ errors.push(`Seat at index ${index} missing or invalid position`);
125
+ }
126
+ if (!isValidSeatShape(seat.shape)) {
127
+ errors.push(`Seat at index ${index} has invalid shape: ${seat.shape}`);
128
+ }
129
+ if (!isValidSeatState(seat.state)) {
130
+ errors.push(`Seat at index ${index} has invalid state: ${seat.state}`);
131
+ }
132
+ });
133
+ const seatIds = config.seats.map((s) => s.id);
134
+ const duplicates = seatIds.filter((id, index) => seatIds.indexOf(id) !== index);
135
+ if (duplicates.length > 0) {
136
+ errors.push(`Duplicate seat IDs found: ${duplicates.join(", ")}`);
137
+ }
138
+ }
139
+ if (config.sections && Array.isArray(config.sections)) {
140
+ config.sections.forEach((section, index) => {
141
+ if (!section.id || typeof section.id !== "string") {
142
+ warnings.push(`Section at index ${index} missing or invalid id`);
143
+ }
144
+ if (!section.name || typeof section.name !== "string") {
145
+ warnings.push(`Section at index ${index} missing or invalid name`);
146
+ }
147
+ if (!section.config) {
148
+ warnings.push(`Section at index ${index} missing config`);
149
+ }
150
+ });
151
+ }
152
+ if (config.stages && Array.isArray(config.stages)) {
153
+ config.stages.forEach((stage, index) => {
154
+ if (!stage.id || typeof stage.id !== "string") {
155
+ warnings.push(`Stage at index ${index} missing or invalid id`);
156
+ }
157
+ if (!stage.config || !stage.config.label) {
158
+ warnings.push(`Stage at index ${index} missing or invalid config`);
159
+ }
160
+ });
161
+ }
162
+ return {
163
+ valid: errors.length === 0,
164
+ errors,
165
+ warnings
166
+ };
167
+ }
168
+ function isValidSeatState(state) {
169
+ return ["available", "reserved", "selected", "unavailable"].includes(state);
170
+ }
171
+ function isValidSeatShape(shape) {
172
+ return ["circle", "square", "rounded-square"].includes(shape);
173
+ }
174
+ function generateId(prefix = "obj") {
175
+ return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
176
+ }
177
+ function formatDate(date = /* @__PURE__ */ new Date()) {
178
+ return date.toISOString();
179
+ }
180
+
181
+ // src/utils/serializer.ts
182
+ function createDefaultConfig(name = "Untitled Venue") {
183
+ return {
184
+ version: "1.0.0",
185
+ metadata: {
186
+ name,
187
+ createdAt: formatDate(),
188
+ updatedAt: formatDate()
189
+ },
190
+ canvas: {
191
+ width: 1200,
192
+ height: 800,
193
+ backgroundColor: DEFAULT_COLORS.canvasBackground
194
+ },
195
+ colors: { ...DEFAULT_COLORS },
196
+ seats: [],
197
+ sections: [],
198
+ stages: []
199
+ };
200
+ }
201
+ function updateConfigTimestamp(config) {
202
+ return {
203
+ ...config,
204
+ metadata: {
205
+ ...config.metadata,
206
+ updatedAt: formatDate()
207
+ }
208
+ };
209
+ }
210
+ function applySeatStateOverrides(config, reservedSeats, unavailableSeats) {
211
+ if (!reservedSeats && !unavailableSeats) {
212
+ return config;
213
+ }
214
+ const reservedSet = new Set(reservedSeats || []);
215
+ const unavailableSet = new Set(unavailableSeats || []);
216
+ return {
217
+ ...config,
218
+ seats: config.seats.map((seat) => {
219
+ let newState = seat.state;
220
+ if (unavailableSet.has(seat.id) || unavailableSet.has(seat.seatNumber || "")) {
221
+ newState = "unavailable";
222
+ } else if (reservedSet.has(seat.id) || reservedSet.has(seat.seatNumber || "")) {
223
+ newState = "reserved";
224
+ }
225
+ return newState !== seat.state ? { ...seat, state: newState } : seat;
226
+ })
227
+ };
228
+ }
229
+ function getSelectedSeats(config) {
230
+ return config.seats.filter((seat) => seat.state === "selected");
231
+ }
232
+ function calculateCapacity(config) {
233
+ return config.seats.length;
234
+ }
235
+ function calculateAvailableSeats(config) {
236
+ return config.seats.filter((seat) => seat.state === "available").length;
237
+ }
238
+ function cloneConfig(config) {
239
+ return JSON.parse(JSON.stringify(config));
240
+ }
241
+ function exportConfigAsJSON(config, pretty = true) {
242
+ return pretty ? JSON.stringify(config, null, 2) : JSON.stringify(config);
243
+ }
244
+ function importConfigFromJSON(jsonString) {
245
+ try {
246
+ const config = JSON.parse(jsonString);
247
+ return config;
248
+ } catch (error) {
249
+ throw new Error(`Failed to parse JSON: ${error instanceof Error ? error.message : "Unknown error"}`);
250
+ }
251
+ }
252
+ function downloadConfigAsFile(config, filename = "seat-map-config.json") {
253
+ const jsonString = exportConfigAsJSON(config);
254
+ const blob = new Blob([jsonString], { type: "application/json" });
255
+ const url = URL.createObjectURL(blob);
256
+ const link = document.createElement("a");
257
+ link.href = url;
258
+ link.download = filename;
259
+ document.body.appendChild(link);
260
+ link.click();
261
+ document.body.removeChild(link);
262
+ URL.revokeObjectURL(url);
263
+ }
264
+ // Annotate the CommonJS export names for ESM import in node:
265
+ 0 && (module.exports = {
266
+ DEFAULT_COLORS,
267
+ applySeatStateOverrides,
268
+ calculateAvailableSeats,
269
+ calculateCapacity,
270
+ calculateSeatPrice,
271
+ cloneConfig,
272
+ createDefaultConfig,
273
+ downloadConfigAsFile,
274
+ exportConfigAsJSON,
275
+ formatDate,
276
+ generateId,
277
+ getSelectedSeats,
278
+ importConfigFromJSON,
279
+ updateConfigTimestamp,
280
+ validateSeatMapConfig
281
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,240 @@
1
+ // src/types/seatMap.ts
2
+ var DEFAULT_COLORS = {
3
+ canvasBackground: "#1a1a1a",
4
+ stageColor: "#808080",
5
+ seatAvailable: "#2C2B30",
6
+ seatReserved: "#FCEA00",
7
+ seatSelected: "#3A7DE5",
8
+ seatUnavailable: "#6b7280",
9
+ gridLines: "#404040",
10
+ currency: "KD"
11
+ };
12
+ var calculateSeatPrice = (seat, rowPricing, sectionPrice) => {
13
+ if (seat.price !== void 0) return seat.price;
14
+ const rowPrice = rowPricing.find(
15
+ (rp) => rp.sectionName === seat.sectionName && rp.rowLabel === seat.rowLabel
16
+ );
17
+ if (rowPrice) return rowPrice.price;
18
+ return sectionPrice || 0;
19
+ };
20
+
21
+ // src/utils/validator.ts
22
+ function validateSeatMapConfig(config) {
23
+ const errors = [];
24
+ const warnings = [];
25
+ if (!config) {
26
+ errors.push("Config is null or undefined");
27
+ return { valid: false, errors, warnings };
28
+ }
29
+ if (!config.version || typeof config.version !== "string") {
30
+ errors.push("Missing or invalid version field");
31
+ }
32
+ if (!config.metadata) {
33
+ errors.push("Missing metadata");
34
+ } else {
35
+ if (!config.metadata.name || typeof config.metadata.name !== "string") {
36
+ errors.push("Missing or invalid metadata.name");
37
+ }
38
+ if (!config.metadata.createdAt || typeof config.metadata.createdAt !== "string") {
39
+ warnings.push("Missing or invalid metadata.createdAt");
40
+ }
41
+ if (!config.metadata.updatedAt || typeof config.metadata.updatedAt !== "string") {
42
+ warnings.push("Missing or invalid metadata.updatedAt");
43
+ }
44
+ }
45
+ if (!config.canvas) {
46
+ errors.push("Missing canvas configuration");
47
+ } else {
48
+ if (typeof config.canvas.width !== "number" || config.canvas.width <= 0) {
49
+ errors.push("Invalid canvas width");
50
+ }
51
+ if (typeof config.canvas.height !== "number" || config.canvas.height <= 0) {
52
+ errors.push("Invalid canvas height");
53
+ }
54
+ if (!config.canvas.backgroundColor || typeof config.canvas.backgroundColor !== "string") {
55
+ warnings.push("Missing or invalid canvas background color");
56
+ }
57
+ }
58
+ if (!config.colors) {
59
+ warnings.push("Missing color configuration");
60
+ } else {
61
+ const requiredColors = [
62
+ "canvasBackground",
63
+ "stageColor",
64
+ "seatAvailable",
65
+ "seatReserved",
66
+ "seatSelected",
67
+ "seatUnavailable",
68
+ "gridLines"
69
+ ];
70
+ requiredColors.forEach((color) => {
71
+ if (!config.colors[color] || typeof config.colors[color] !== "string") {
72
+ warnings.push(`Missing or invalid color: ${color}`);
73
+ }
74
+ });
75
+ }
76
+ if (!config.seats || !Array.isArray(config.seats)) {
77
+ errors.push("Missing or invalid seats array");
78
+ } else {
79
+ config.seats.forEach((seat, index) => {
80
+ if (!seat.id || typeof seat.id !== "string") {
81
+ errors.push(`Seat at index ${index} missing or invalid id`);
82
+ }
83
+ if (!seat.position || typeof seat.position.x !== "number" || typeof seat.position.y !== "number") {
84
+ errors.push(`Seat at index ${index} missing or invalid position`);
85
+ }
86
+ if (!isValidSeatShape(seat.shape)) {
87
+ errors.push(`Seat at index ${index} has invalid shape: ${seat.shape}`);
88
+ }
89
+ if (!isValidSeatState(seat.state)) {
90
+ errors.push(`Seat at index ${index} has invalid state: ${seat.state}`);
91
+ }
92
+ });
93
+ const seatIds = config.seats.map((s) => s.id);
94
+ const duplicates = seatIds.filter((id, index) => seatIds.indexOf(id) !== index);
95
+ if (duplicates.length > 0) {
96
+ errors.push(`Duplicate seat IDs found: ${duplicates.join(", ")}`);
97
+ }
98
+ }
99
+ if (config.sections && Array.isArray(config.sections)) {
100
+ config.sections.forEach((section, index) => {
101
+ if (!section.id || typeof section.id !== "string") {
102
+ warnings.push(`Section at index ${index} missing or invalid id`);
103
+ }
104
+ if (!section.name || typeof section.name !== "string") {
105
+ warnings.push(`Section at index ${index} missing or invalid name`);
106
+ }
107
+ if (!section.config) {
108
+ warnings.push(`Section at index ${index} missing config`);
109
+ }
110
+ });
111
+ }
112
+ if (config.stages && Array.isArray(config.stages)) {
113
+ config.stages.forEach((stage, index) => {
114
+ if (!stage.id || typeof stage.id !== "string") {
115
+ warnings.push(`Stage at index ${index} missing or invalid id`);
116
+ }
117
+ if (!stage.config || !stage.config.label) {
118
+ warnings.push(`Stage at index ${index} missing or invalid config`);
119
+ }
120
+ });
121
+ }
122
+ return {
123
+ valid: errors.length === 0,
124
+ errors,
125
+ warnings
126
+ };
127
+ }
128
+ function isValidSeatState(state) {
129
+ return ["available", "reserved", "selected", "unavailable"].includes(state);
130
+ }
131
+ function isValidSeatShape(shape) {
132
+ return ["circle", "square", "rounded-square"].includes(shape);
133
+ }
134
+ function generateId(prefix = "obj") {
135
+ return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
136
+ }
137
+ function formatDate(date = /* @__PURE__ */ new Date()) {
138
+ return date.toISOString();
139
+ }
140
+
141
+ // src/utils/serializer.ts
142
+ function createDefaultConfig(name = "Untitled Venue") {
143
+ return {
144
+ version: "1.0.0",
145
+ metadata: {
146
+ name,
147
+ createdAt: formatDate(),
148
+ updatedAt: formatDate()
149
+ },
150
+ canvas: {
151
+ width: 1200,
152
+ height: 800,
153
+ backgroundColor: DEFAULT_COLORS.canvasBackground
154
+ },
155
+ colors: { ...DEFAULT_COLORS },
156
+ seats: [],
157
+ sections: [],
158
+ stages: []
159
+ };
160
+ }
161
+ function updateConfigTimestamp(config) {
162
+ return {
163
+ ...config,
164
+ metadata: {
165
+ ...config.metadata,
166
+ updatedAt: formatDate()
167
+ }
168
+ };
169
+ }
170
+ function applySeatStateOverrides(config, reservedSeats, unavailableSeats) {
171
+ if (!reservedSeats && !unavailableSeats) {
172
+ return config;
173
+ }
174
+ const reservedSet = new Set(reservedSeats || []);
175
+ const unavailableSet = new Set(unavailableSeats || []);
176
+ return {
177
+ ...config,
178
+ seats: config.seats.map((seat) => {
179
+ let newState = seat.state;
180
+ if (unavailableSet.has(seat.id) || unavailableSet.has(seat.seatNumber || "")) {
181
+ newState = "unavailable";
182
+ } else if (reservedSet.has(seat.id) || reservedSet.has(seat.seatNumber || "")) {
183
+ newState = "reserved";
184
+ }
185
+ return newState !== seat.state ? { ...seat, state: newState } : seat;
186
+ })
187
+ };
188
+ }
189
+ function getSelectedSeats(config) {
190
+ return config.seats.filter((seat) => seat.state === "selected");
191
+ }
192
+ function calculateCapacity(config) {
193
+ return config.seats.length;
194
+ }
195
+ function calculateAvailableSeats(config) {
196
+ return config.seats.filter((seat) => seat.state === "available").length;
197
+ }
198
+ function cloneConfig(config) {
199
+ return JSON.parse(JSON.stringify(config));
200
+ }
201
+ function exportConfigAsJSON(config, pretty = true) {
202
+ return pretty ? JSON.stringify(config, null, 2) : JSON.stringify(config);
203
+ }
204
+ function importConfigFromJSON(jsonString) {
205
+ try {
206
+ const config = JSON.parse(jsonString);
207
+ return config;
208
+ } catch (error) {
209
+ throw new Error(`Failed to parse JSON: ${error instanceof Error ? error.message : "Unknown error"}`);
210
+ }
211
+ }
212
+ function downloadConfigAsFile(config, filename = "seat-map-config.json") {
213
+ const jsonString = exportConfigAsJSON(config);
214
+ const blob = new Blob([jsonString], { type: "application/json" });
215
+ const url = URL.createObjectURL(blob);
216
+ const link = document.createElement("a");
217
+ link.href = url;
218
+ link.download = filename;
219
+ document.body.appendChild(link);
220
+ link.click();
221
+ document.body.removeChild(link);
222
+ URL.revokeObjectURL(url);
223
+ }
224
+ export {
225
+ DEFAULT_COLORS,
226
+ applySeatStateOverrides,
227
+ calculateAvailableSeats,
228
+ calculateCapacity,
229
+ calculateSeatPrice,
230
+ cloneConfig,
231
+ createDefaultConfig,
232
+ downloadConfigAsFile,
233
+ exportConfigAsJSON,
234
+ formatDate,
235
+ generateId,
236
+ getSelectedSeats,
237
+ importConfigFromJSON,
238
+ updateConfigTimestamp,
239
+ validateSeatMapConfig
240
+ };
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@zonetrix/shared",
3
+ "version": "1.0.0",
4
+ "description": "Shared types and utilities for seat-map-studio packages",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup src/index.ts --format cjs,esm --dts",
20
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch"
21
+ },
22
+ "keywords": [
23
+ "seat-map",
24
+ "types",
25
+ "shared"
26
+ ],
27
+ "author": "",
28
+ "license": "MIT",
29
+ "devDependencies": {
30
+ "tsup": "^8.0.1",
31
+ "typescript": "^5.8.3"
32
+ }
33
+ }