@nex125/seatmap-viewer 0.1.8 → 0.1.11

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 CHANGED
@@ -6,93 +6,25 @@ var seatmapReact = require('@nex125/seatmap-react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
 
8
8
  // src/SeatmapViewer.tsx
9
- var legendContainerStyle = {
10
- position: "absolute",
11
- top: 12,
12
- left: 12,
13
- zIndex: 10,
14
- pointerEvents: "none",
15
- background: "rgba(18, 18, 34, 0.88)",
16
- border: "1px solid rgba(110, 110, 150, 0.45)",
17
- borderRadius: 8,
18
- padding: "10px 12px",
19
- minWidth: 150,
20
- color: "#e0e0e0",
21
- fontFamily: "system-ui",
22
- fontSize: 12,
23
- backdropFilter: "blur(2px)"
24
- };
25
- var legendHeadingStyle = {
26
- margin: 0,
27
- fontSize: 11,
28
- fontWeight: 600,
29
- letterSpacing: 0.2,
30
- color: "#b9b9d6"
31
- };
32
- var legendListStyle = {
33
- listStyle: "none",
34
- margin: "6px 0 0",
35
- padding: 0,
36
- display: "flex",
37
- flexDirection: "column",
38
- gap: 4
39
- };
40
- var legendItemStyle = {
41
- display: "flex",
42
- alignItems: "center",
43
- gap: 6,
44
- minWidth: 0
45
- };
46
- var legendSwatchStyle = {
47
- width: 10,
48
- height: 10,
49
- borderRadius: 2,
50
- flexShrink: 0,
51
- border: "1px solid rgba(255, 255, 255, 0.25)"
52
- };
53
- var cartChipStyle = {
54
- position: "absolute",
55
- right: 12,
56
- bottom: 12,
57
- zIndex: 20,
58
- border: "1px solid rgba(110, 110, 150, 0.65)",
59
- background: "rgba(24, 24, 42, 0.95)",
60
- color: "#ececff",
61
- borderRadius: 999,
62
- padding: "8px 14px",
63
- fontSize: 12,
64
- fontWeight: 600,
65
- fontFamily: "system-ui",
66
- cursor: "pointer",
67
- boxShadow: "0 8px 18px rgba(0, 0, 0, 0.35)"
68
- };
69
- var cartPopupStyle = {
70
- position: "absolute",
71
- right: 0,
72
- bottom: 0,
73
- zIndex: 30,
74
- maxHeight: "72vh",
75
- display: "flex",
76
- flexDirection: "column",
77
- background: "rgba(17, 17, 34, 0.98)",
78
- borderTop: "1px solid rgba(110, 110, 150, 0.65)",
79
- borderLeft: "1px solid rgba(110, 110, 150, 0.65)",
80
- borderTopLeftRadius: 12,
81
- overflow: "hidden",
82
- boxShadow: "-8px -8px 20px rgba(0, 0, 0, 0.35)"
83
- };
84
- var cartIconButtonStyle = {
85
- width: 24,
86
- height: 24,
87
- display: "inline-flex",
88
- alignItems: "center",
89
- justifyContent: "center",
90
- borderRadius: 5,
91
- border: "1px solid #4a4a6a",
92
- background: "#262648",
93
- color: "#ececff",
94
- fontSize: 14,
95
- cursor: "pointer"
9
+ var defaultSeatmapViewerMessages = {
10
+ uncategorizedCategoryName: "Uncategorized",
11
+ sectionFallbackLabel: "Section",
12
+ tableLabel: (tableLabel) => `Table ${tableLabel}`,
13
+ legendAriaLabel: "Seatmap legend",
14
+ legendStatusesTitle: "Seat statuses",
15
+ legendPricesTitle: "Prices",
16
+ cartChipLabel: (selectedCount) => `Cart (${selectedCount})`,
17
+ cartAriaLabel: "Selected seats cart",
18
+ cartHeaderTitle: "Selected seats cart",
19
+ cartCloseLabel: "Close cart",
20
+ cartEmptyState: "No seats selected yet.",
21
+ cartGroupMeta: (count, unitPrice) => `${count} tickets - ${unitPrice} each`,
22
+ cartRemoveOneAriaLabel: (categoryName) => `Remove one seat from ${categoryName}`,
23
+ cartAddOneAriaLabel: (categoryName) => `Add one seat to ${categoryName}`,
24
+ cartRemoveSeatTitle: "Remove seat",
25
+ cartRemoveSeatAriaLabel: (seatLabel) => `Remove seat ${seatLabel}`,
26
+ cartSummary: (count, totalCost) => `${count} seats - Total ${totalCost}`,
27
+ cartProceedButton: "Proceed"
96
28
  };
97
29
  function getEffectiveCategoryPrice(category) {
98
30
  if (!category) return 0;
@@ -101,8 +33,11 @@ function getEffectiveCategoryPrice(category) {
101
33
  }
102
34
  return Number.isFinite(category.backendPrice) ? category.backendPrice : 0;
103
35
  }
104
- function formatMoney(value) {
105
- return `$${value.toFixed(2)}`;
36
+ function formatMoney(value, locale, currency) {
37
+ return new Intl.NumberFormat(locale, {
38
+ style: "currency",
39
+ currency
40
+ }).format(value);
106
41
  }
107
42
  function TrashIcon() {
108
43
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -113,15 +48,32 @@ function TrashIcon() {
113
48
  }
114
49
  ) });
115
50
  }
116
- function ViewerContent({
51
+ function mergeStyles(base, override) {
52
+ if (!override) return base;
53
+ return { ...base, ...override };
54
+ }
55
+ function mergeClassNames(...classNames) {
56
+ const merged = classNames.filter(Boolean).join(" ").trim();
57
+ return merged.length > 0 ? merged : void 0;
58
+ }
59
+ function SeatmapViewerContent({
117
60
  venue,
118
61
  onSeatClick,
119
62
  onSeatHover,
120
63
  onSelectionChange,
121
64
  renderTooltip,
122
65
  showLabels,
123
- onCartEvent
66
+ onCartEvent,
67
+ locale = "en-US",
68
+ currency = "BYN",
69
+ styles = {},
70
+ classNames = {},
71
+ messages: messagesOverride = {}
124
72
  }) {
73
+ const messages = react.useMemo(
74
+ () => ({ ...defaultSeatmapViewerMessages, ...messagesOverride }),
75
+ [messagesOverride]
76
+ );
125
77
  const { selectedSeatIds, setSelection } = seatmapReact.useSelection();
126
78
  const [isCartOpen, setIsCartOpen] = react.useState(false);
127
79
  const [lastUserAnchorByCategory, setLastUserAnchorByCategory] = react.useState({});
@@ -149,7 +101,7 @@ function ViewerContent({
149
101
  sectionId: section.id,
150
102
  sectionLabel: section.label,
151
103
  categoryId: seat.categoryId,
152
- categoryName: category?.name ?? "Unknown",
104
+ categoryName: category?.name ?? messages.uncategorizedCategoryName,
153
105
  unitPrice: getEffectiveCategoryPrice(category),
154
106
  status: seat.status,
155
107
  x: section.position.x + seat.position.x * cos - seat.position.y * sin,
@@ -166,9 +118,9 @@ function ViewerContent({
166
118
  seatLabel: seat.label,
167
119
  rowLabel: null,
168
120
  sectionId: table.id,
169
- sectionLabel: `Table ${table.label}`,
121
+ sectionLabel: messages.tableLabel(table.label),
170
122
  categoryId: seat.categoryId,
171
- categoryName: category?.name ?? "Unknown",
123
+ categoryName: category?.name ?? messages.uncategorizedCategoryName,
172
124
  unitPrice: getEffectiveCategoryPrice(category),
173
125
  status: seat.status,
174
126
  x: table.position.x + seat.position.x,
@@ -177,7 +129,7 @@ function ViewerContent({
177
129
  }
178
130
  }
179
131
  return next;
180
- }, [venue]);
132
+ }, [venue, messages]);
181
133
  const selectedSeats = react.useMemo(() => {
182
134
  const ordered = [];
183
135
  for (const selectedSeatId of selectedSeatIdArray) {
@@ -291,10 +243,14 @@ function ViewerContent({
291
243
  );
292
244
  const removeSeatFromSelection = react.useCallback(
293
245
  (seatId) => {
246
+ const seat = seatDetailsById.get(seatId);
247
+ if (seat?.sectionId) {
248
+ onSeatClick?.(seatId, seat.sectionId);
249
+ }
294
250
  const next = selectedSeatIdArray.filter((id) => id !== seatId);
295
251
  setSelection(next);
296
252
  },
297
- [selectedSeatIdArray, setSelection]
253
+ [seatDetailsById, onSeatClick, selectedSeatIdArray, setSelection]
298
254
  );
299
255
  const handleSeatCanvasClick = react.useCallback(
300
256
  (seatId, sectionId) => {
@@ -324,8 +280,11 @@ function ViewerContent({
324
280
  }, candidates[0]);
325
281
  }
326
282
  setSelection([...selectedSeatIdArray, nextSeat.seatId]);
283
+ if (nextSeat.sectionId) {
284
+ onSeatClick?.(nextSeat.seatId, nextSeat.sectionId);
285
+ }
327
286
  },
328
- [lastUserAnchorByCategory, seatDetailsById, selectedSeatIdArray, setSelection]
287
+ [lastUserAnchorByCategory, seatDetailsById, selectedSeatIdArray, setSelection, onSeatClick]
329
288
  );
330
289
  const handleRemoveLastInCategory = react.useCallback(
331
290
  (categoryId) => {
@@ -334,198 +293,276 @@ function ViewerContent({
334
293
  );
335
294
  const seatIdToRemove = selectedInCategory[selectedInCategory.length - 1];
336
295
  if (!seatIdToRemove) return;
296
+ const seat = seatDetailsById.get(seatIdToRemove);
297
+ if (seat?.sectionId) {
298
+ onSeatClick?.(seatIdToRemove, seat.sectionId);
299
+ }
337
300
  setSelection(selectedSeatIdArray.filter((selectedSeatId) => selectedSeatId !== seatIdToRemove));
338
301
  },
339
- [seatDetailsById, selectedSeatIdArray, setSelection]
302
+ [seatDetailsById, selectedSeatIdArray, setSelection, onSeatClick]
340
303
  );
341
304
  const handleProceed = react.useCallback(() => {
342
305
  if (cartPayload.seats.length === 0) return;
343
306
  emitCartEvent({ type: "cart-proceed-clicked", payload: cartPayload });
344
307
  }, [cartPayload, emitCartEvent]);
345
308
  const cartWidth = viewportWidth > 1200 ? Math.floor(viewportWidth / 5) : viewportWidth;
346
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: "100%", height: "100%", position: "relative" }, children: [
347
- /* @__PURE__ */ jsxRuntime.jsx(
348
- seatmapReact.SeatmapCanvas,
349
- {
350
- onSeatClick: handleSeatCanvasClick,
351
- onSeatHover,
352
- showSectionLabels: showLabels,
353
- enableSeatHover: showLabels
354
- }
355
- ),
356
- (showStatuses || showCategories) && /* @__PURE__ */ jsxRuntime.jsxs("aside", { "aria-label": "Seatmap legend", style: legendContainerStyle, children: [
357
- showStatuses && /* @__PURE__ */ jsxRuntime.jsxs("section", { children: [
358
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: legendHeadingStyle, children: "Seat Status" }),
359
- /* @__PURE__ */ jsxRuntime.jsx("ul", { style: legendListStyle, children: venue.seatStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsxs("li", { style: legendItemStyle, children: [
360
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { ...legendSwatchStyle, background: status.color } }),
361
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: status.name })
362
- ] }, status.id)) })
363
- ] }),
364
- showStatuses && showCategories && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: 1, background: "rgba(123, 123, 165, 0.45)", margin: "8px 0" } }),
365
- showCategories && /* @__PURE__ */ jsxRuntime.jsxs("section", { children: [
366
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: legendHeadingStyle, children: "Pricing" }),
367
- /* @__PURE__ */ jsxRuntime.jsx("ul", { style: legendListStyle, children: venue.categories.map((category) => /* @__PURE__ */ jsxRuntime.jsxs("li", { style: legendItemStyle, children: [
368
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { ...legendSwatchStyle, background: category.color } }),
369
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: category.name })
370
- ] }, category.id)) })
371
- ] })
372
- ] }),
373
- !isCartOpen && /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", onClick: () => setIsCartOpen(true), style: cartChipStyle, children: [
374
- "Cart (",
375
- totalSelectedSeats,
376
- ")"
377
- ] }),
378
- isCartOpen && /* @__PURE__ */ jsxRuntime.jsxs("aside", { "aria-label": "Selected seats cart", style: { ...cartPopupStyle, width: cartWidth, maxWidth: "100%" }, children: [
379
- /* @__PURE__ */ jsxRuntime.jsxs(
380
- "div",
381
- {
382
- style: {
383
- display: "flex",
384
- alignItems: "center",
385
- justifyContent: "space-between",
386
- gap: 8,
387
- padding: "10px 12px",
388
- borderBottom: "1px solid rgba(110, 110, 150, 0.35)"
389
- },
390
- children: [
391
- /* @__PURE__ */ jsxRuntime.jsx("strong", { style: { color: "#ececff", fontSize: 13, fontFamily: "system-ui" }, children: "Selected Seats Cart" }),
392
- /* @__PURE__ */ jsxRuntime.jsx(
393
- "button",
394
- {
395
- type: "button",
396
- onClick: () => setIsCartOpen(false),
397
- style: { ...cartIconButtonStyle, width: 22, height: 22 },
398
- title: "Close cart",
399
- "aria-label": "Close cart",
400
- children: "x"
401
- }
402
- )
403
- ]
404
- }
405
- ),
406
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: 8, overflow: "auto", padding: 12, flex: 1 }, children: groupedSeatsList.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#9e9eb8", fontSize: 12, fontFamily: "system-ui" }, children: "No seats selected yet." }) : groupedSeatsList.map((group) => /* @__PURE__ */ jsxRuntime.jsxs(
407
- "article",
408
- {
409
- style: {
410
- background: "#242447",
411
- border: "1px solid #3b3b61",
412
- borderRadius: 8,
413
- padding: 8,
414
- display: "flex",
415
- flexDirection: "column",
416
- gap: 6
417
- },
418
- children: [
419
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#ececff", fontSize: 12, fontFamily: "system-ui", fontWeight: 600 }, children: group.categoryName }),
420
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { color: "#adb0d2", fontSize: 11, fontFamily: "system-ui" }, children: [
421
- group.seats.length,
422
- " ticket",
423
- group.seats.length === 1 ? "" : "s",
424
- " - ",
425
- formatMoney(group.unitPrice),
426
- " each"
427
- ] }),
428
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 }, children: [
429
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "inline-flex", alignItems: "center", gap: 6 }, children: [
430
- /* @__PURE__ */ jsxRuntime.jsx(
431
- "button",
432
- {
433
- type: "button",
434
- style: cartIconButtonStyle,
435
- onClick: () => handleRemoveLastInCategory(group.categoryId),
436
- disabled: group.seats.length === 0,
437
- "aria-label": `Remove one ${group.categoryName} seat`,
438
- children: "-"
439
- }
440
- ),
441
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { minWidth: 20, textAlign: "center", color: "#ececff", fontSize: 12 }, children: group.seats.length }),
442
- /* @__PURE__ */ jsxRuntime.jsx(
443
- "button",
444
- {
445
- type: "button",
446
- style: cartIconButtonStyle,
447
- onClick: () => handleAddSeatInCategory(group.categoryId),
448
- disabled: group.availableToAdd === 0,
449
- "aria-label": `Add one ${group.categoryName} seat`,
450
- children: "+"
451
- }
452
- )
309
+ return /* @__PURE__ */ jsxRuntime.jsxs(
310
+ "div",
311
+ {
312
+ className: classNames.root,
313
+ style: mergeStyles({ width: "100%", height: "100%", position: "relative" }, styles.root),
314
+ children: [
315
+ /* @__PURE__ */ jsxRuntime.jsx(
316
+ seatmapReact.SeatmapCanvas,
317
+ {
318
+ onSeatClick: handleSeatCanvasClick,
319
+ onSeatHover,
320
+ showSectionLabels: showLabels,
321
+ enableSeatHover: showLabels
322
+ }
323
+ ),
324
+ (showStatuses || showCategories) && /* @__PURE__ */ jsxRuntime.jsxs(
325
+ "aside",
326
+ {
327
+ "aria-label": messages.legendAriaLabel,
328
+ className: mergeClassNames("seatmap-viewer__legend", classNames.legendContainer),
329
+ style: styles.legendContainer,
330
+ children: [
331
+ showStatuses && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "seatmap-viewer__legend-section", children: [
332
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: mergeClassNames("seatmap-viewer__legend-heading-base", classNames.legendHeading), style: styles.legendHeading, children: messages.legendStatusesTitle }),
333
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: mergeClassNames("seatmap-viewer__legend-list-base", classNames.legendList), style: styles.legendList, children: venue.seatStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: mergeClassNames("seatmap-viewer__legend-item-base", classNames.legendItem), style: styles.legendItem, children: [
334
+ /* @__PURE__ */ jsxRuntime.jsx(
335
+ "span",
336
+ {
337
+ className: mergeClassNames("seatmap-viewer__legend-swatch-base", classNames.legendSwatch),
338
+ style: mergeStyles({ background: status.color }, styles.legendSwatch)
339
+ }
340
+ ),
341
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: status.name })
342
+ ] }, status.id)) })
453
343
  ] }),
454
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#ececff", fontSize: 12, fontFamily: "system-ui", fontWeight: 600 }, children: formatMoney(group.seats.reduce((sum, seat) => sum + seat.unitPrice, 0)) })
455
- ] }),
456
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: group.seats.map((seat) => /* @__PURE__ */ jsxRuntime.jsxs(
457
- "div",
458
- {
459
- style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 },
460
- children: [
461
- /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: "#c8c8df", fontSize: 11, fontFamily: "system-ui" }, children: [
462
- seat.sectionLabel ?? "Section",
463
- " ",
464
- seat.rowLabel ? `- ${seat.rowLabel}${seat.seatLabel}` : `- ${seat.seatLabel}`
465
- ] }),
344
+ showStatuses && showCategories && /* @__PURE__ */ jsxRuntime.jsx(
345
+ "div",
346
+ {
347
+ className: mergeClassNames("seatmap-viewer__legend-divider-base", classNames.legendDivider),
348
+ style: styles.legendDivider
349
+ }
350
+ ),
351
+ showCategories && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "seatmap-viewer__legend-section", children: [
352
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: mergeClassNames("seatmap-viewer__legend-heading-base", classNames.legendHeading), style: styles.legendHeading, children: messages.legendPricesTitle }),
353
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: mergeClassNames("seatmap-viewer__legend-list-base", classNames.legendList), style: styles.legendList, children: venue.categories.map((category) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: mergeClassNames("seatmap-viewer__legend-item-base", classNames.legendItem), style: styles.legendItem, children: [
466
354
  /* @__PURE__ */ jsxRuntime.jsx(
467
- "button",
355
+ "span",
468
356
  {
469
- type: "button",
470
- style: cartIconButtonStyle,
471
- onClick: () => removeSeatFromSelection(seat.seatId),
472
- title: "Remove seat",
473
- "aria-label": `Remove seat ${seat.seatLabel}`,
474
- children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {})
357
+ className: mergeClassNames("seatmap-viewer__legend-swatch-base", classNames.legendSwatch),
358
+ style: mergeStyles({ background: category.color }, styles.legendSwatch)
475
359
  }
476
- )
477
- ]
478
- },
479
- seat.seatId
480
- )) })
481
- ]
482
- },
483
- group.categoryId
484
- )) }),
485
- /* @__PURE__ */ jsxRuntime.jsxs(
486
- "div",
487
- {
488
- style: {
489
- borderTop: "1px solid rgba(110, 110, 150, 0.35)",
490
- padding: 12,
491
- display: "flex",
492
- flexDirection: "column",
493
- gap: 8
494
- },
495
- children: [
496
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { color: "#d4d4ee", fontSize: 12, fontFamily: "system-ui" }, children: [
497
- totalSelectedSeats,
498
- " seat",
499
- totalSelectedSeats === 1 ? "" : "s",
500
- " - Total ",
501
- formatMoney(totalCost)
502
- ] }),
503
- /* @__PURE__ */ jsxRuntime.jsx(
504
- "button",
505
- {
506
- type: "button",
507
- disabled: cartSeats.length === 0,
508
- onClick: handleProceed,
509
- style: {
510
- border: "1px solid #2f7b44",
511
- background: cartSeats.length === 0 ? "#30543d" : "#2f7b44",
512
- color: "#ecfff2",
513
- borderRadius: 8,
514
- padding: "8px 12px",
515
- fontSize: 13,
516
- fontWeight: 600,
517
- fontFamily: "system-ui",
518
- cursor: cartSeats.length === 0 ? "not-allowed" : "pointer"
519
- },
520
- children: "Proceed"
521
- }
522
- )
523
- ]
524
- }
525
- )
526
- ] }),
527
- showLabels && /* @__PURE__ */ jsxRuntime.jsx(seatmapReact.TooltipOverlay, { renderTooltip })
528
- ] });
360
+ ),
361
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: category.name })
362
+ ] }, category.id)) })
363
+ ] })
364
+ ]
365
+ }
366
+ ),
367
+ !isCartOpen && /* @__PURE__ */ jsxRuntime.jsx(
368
+ "button",
369
+ {
370
+ type: "button",
371
+ className: mergeClassNames("seatmap-viewer__cart-chip-base", classNames.cartChip),
372
+ onClick: () => setIsCartOpen(true),
373
+ style: styles.cartChip,
374
+ children: messages.cartChipLabel(totalSelectedSeats)
375
+ }
376
+ ),
377
+ isCartOpen && /* @__PURE__ */ jsxRuntime.jsxs(
378
+ "aside",
379
+ {
380
+ "aria-label": messages.cartAriaLabel,
381
+ className: mergeClassNames("seatmap-viewer__cart-popup-base", classNames.cartPopup),
382
+ style: mergeStyles({ width: cartWidth, maxWidth: "100%" }, styles.cartPopup),
383
+ children: [
384
+ /* @__PURE__ */ jsxRuntime.jsxs(
385
+ "div",
386
+ {
387
+ className: mergeClassNames("seatmap-viewer__cart-header-base", classNames.cartHeader),
388
+ style: styles.cartHeader,
389
+ children: [
390
+ /* @__PURE__ */ jsxRuntime.jsx(
391
+ "strong",
392
+ {
393
+ className: mergeClassNames("seatmap-viewer__cart-header-title-base", classNames.cartHeaderTitle),
394
+ style: styles.cartHeaderTitle,
395
+ children: messages.cartHeaderTitle
396
+ }
397
+ ),
398
+ /* @__PURE__ */ jsxRuntime.jsx(
399
+ "button",
400
+ {
401
+ type: "button",
402
+ onClick: () => setIsCartOpen(false),
403
+ className: mergeClassNames("seatmap-viewer__cart-icon-button-base", classNames.cartIconButton),
404
+ style: styles.cartIconButton,
405
+ title: messages.cartCloseLabel,
406
+ "aria-label": messages.cartCloseLabel,
407
+ children: "x"
408
+ }
409
+ )
410
+ ]
411
+ }
412
+ ),
413
+ /* @__PURE__ */ jsxRuntime.jsx(
414
+ "div",
415
+ {
416
+ className: mergeClassNames("seatmap-viewer__cart-body-base", classNames.cartBody),
417
+ style: styles.cartBody,
418
+ children: groupedSeatsList.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
419
+ "div",
420
+ {
421
+ className: mergeClassNames("seatmap-viewer__cart-empty-state-base", classNames.cartEmptyState),
422
+ style: styles.cartEmptyState,
423
+ children: messages.cartEmptyState
424
+ }
425
+ ) : groupedSeatsList.map((group) => /* @__PURE__ */ jsxRuntime.jsxs(
426
+ "article",
427
+ {
428
+ className: mergeClassNames("seatmap-viewer__cart-group-base", classNames.cartGroup),
429
+ style: styles.cartGroup,
430
+ children: [
431
+ /* @__PURE__ */ jsxRuntime.jsx(
432
+ "div",
433
+ {
434
+ className: mergeClassNames("seatmap-viewer__cart-group-title-base", classNames.cartGroupTitle),
435
+ style: styles.cartGroupTitle,
436
+ children: group.categoryName
437
+ }
438
+ ),
439
+ /* @__PURE__ */ jsxRuntime.jsx(
440
+ "div",
441
+ {
442
+ className: mergeClassNames("seatmap-viewer__cart-group-meta-base", classNames.cartGroupMeta),
443
+ style: styles.cartGroupMeta,
444
+ children: messages.cartGroupMeta(group.seats.length, formatMoney(group.unitPrice, locale, currency))
445
+ }
446
+ ),
447
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: mergeClassNames("seatmap-viewer__cart-quantity-row-base", classNames.cartQuantityRow), style: styles.cartQuantityRow, children: [
448
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "seatmap-viewer__cart-quantity-controls", children: [
449
+ /* @__PURE__ */ jsxRuntime.jsx(
450
+ "button",
451
+ {
452
+ type: "button",
453
+ className: mergeClassNames("seatmap-viewer__cart-icon-button-base", classNames.cartIconButton),
454
+ style: styles.cartIconButton,
455
+ onClick: () => handleRemoveLastInCategory(group.categoryId),
456
+ disabled: group.seats.length === 0,
457
+ "aria-label": messages.cartRemoveOneAriaLabel(group.categoryName),
458
+ children: "-"
459
+ }
460
+ ),
461
+ /* @__PURE__ */ jsxRuntime.jsx(
462
+ "span",
463
+ {
464
+ className: mergeClassNames("seatmap-viewer__cart-quantity-value-base", classNames.cartQuantityValue),
465
+ style: styles.cartQuantityValue,
466
+ children: group.seats.length
467
+ }
468
+ ),
469
+ /* @__PURE__ */ jsxRuntime.jsx(
470
+ "button",
471
+ {
472
+ type: "button",
473
+ className: mergeClassNames("seatmap-viewer__cart-icon-button-base", classNames.cartIconButton),
474
+ style: styles.cartIconButton,
475
+ onClick: () => handleAddSeatInCategory(group.categoryId),
476
+ disabled: group.availableToAdd === 0,
477
+ "aria-label": messages.cartAddOneAriaLabel(group.categoryName),
478
+ children: "+"
479
+ }
480
+ )
481
+ ] }),
482
+ /* @__PURE__ */ jsxRuntime.jsx(
483
+ "span",
484
+ {
485
+ className: mergeClassNames("seatmap-viewer__cart-group-total-base", classNames.cartGroupTotal),
486
+ style: styles.cartGroupTotal,
487
+ children: formatMoney(group.seats.reduce((sum, seat) => sum + seat.unitPrice, 0), locale, currency)
488
+ }
489
+ )
490
+ ] }),
491
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "seatmap-viewer__cart-seat-list", children: group.seats.map((seat) => /* @__PURE__ */ jsxRuntime.jsxs(
492
+ "div",
493
+ {
494
+ className: mergeClassNames("seatmap-viewer__cart-seat-row-base", classNames.cartSeatRow),
495
+ style: styles.cartSeatRow,
496
+ children: [
497
+ /* @__PURE__ */ jsxRuntime.jsxs(
498
+ "span",
499
+ {
500
+ className: mergeClassNames("seatmap-viewer__cart-seat-label-base", classNames.cartSeatLabel),
501
+ style: styles.cartSeatLabel,
502
+ children: [
503
+ seat.sectionLabel ?? messages.sectionFallbackLabel,
504
+ " ",
505
+ seat.rowLabel ? `- ${seat.rowLabel}${seat.seatLabel}` : `- ${seat.seatLabel}`
506
+ ]
507
+ }
508
+ ),
509
+ /* @__PURE__ */ jsxRuntime.jsx(
510
+ "button",
511
+ {
512
+ type: "button",
513
+ className: mergeClassNames("seatmap-viewer__cart-icon-button-base", classNames.cartIconButton),
514
+ style: styles.cartIconButton,
515
+ onClick: () => removeSeatFromSelection(seat.seatId),
516
+ title: messages.cartRemoveSeatTitle,
517
+ "aria-label": messages.cartRemoveSeatAriaLabel(seat.seatLabel),
518
+ children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {})
519
+ }
520
+ )
521
+ ]
522
+ },
523
+ seat.seatId
524
+ )) })
525
+ ]
526
+ },
527
+ group.categoryId
528
+ ))
529
+ }
530
+ ),
531
+ /* @__PURE__ */ jsxRuntime.jsxs(
532
+ "div",
533
+ {
534
+ className: mergeClassNames("seatmap-viewer__cart-footer-base", classNames.cartFooter),
535
+ style: styles.cartFooter,
536
+ children: [
537
+ /* @__PURE__ */ jsxRuntime.jsx(
538
+ "div",
539
+ {
540
+ className: mergeClassNames("seatmap-viewer__cart-summary-base", classNames.cartSummary),
541
+ style: styles.cartSummary,
542
+ children: messages.cartSummary(totalSelectedSeats, formatMoney(totalCost, locale, currency))
543
+ }
544
+ ),
545
+ /* @__PURE__ */ jsxRuntime.jsx(
546
+ "button",
547
+ {
548
+ type: "button",
549
+ disabled: cartSeats.length === 0,
550
+ onClick: handleProceed,
551
+ className: mergeClassNames("seatmap-viewer__cart-proceed-button-base", classNames.cartProceedButton),
552
+ style: styles.cartProceedButton,
553
+ children: messages.cartProceedButton
554
+ }
555
+ )
556
+ ]
557
+ }
558
+ )
559
+ ]
560
+ }
561
+ ),
562
+ showLabels && /* @__PURE__ */ jsxRuntime.jsx(seatmapReact.TooltipOverlay, { renderTooltip })
563
+ ]
564
+ }
565
+ );
529
566
  }
530
567
  function SeatmapViewer({
531
568
  venue,
@@ -535,20 +572,202 @@ function SeatmapViewer({
535
572
  renderTooltip,
536
573
  showLabels = true,
537
574
  className,
538
- onCartEvent
575
+ onCartEvent,
576
+ locale,
577
+ currency,
578
+ styles,
579
+ classNames,
580
+ messages
539
581
  }) {
540
- return /* @__PURE__ */ jsxRuntime.jsx(seatmapReact.SeatmapProvider, { venue, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { width: "100%", height: "100%", position: "relative" }, children: /* @__PURE__ */ jsxRuntime.jsx(
541
- ViewerContent,
582
+ return /* @__PURE__ */ jsxRuntime.jsx(seatmapReact.SeatmapProvider, { venue, children: /* @__PURE__ */ jsxRuntime.jsx(
583
+ "div",
542
584
  {
543
- venue,
544
- onSeatClick,
545
- onSeatHover,
546
- onSelectionChange,
547
- renderTooltip,
548
- showLabels,
549
- onCartEvent
585
+ className: mergeClassNames(className, classNames?.root),
586
+ style: mergeStyles({ width: "100%", height: "100%", position: "relative" }, styles?.root),
587
+ children: /* @__PURE__ */ jsxRuntime.jsx(
588
+ SeatmapViewerContent,
589
+ {
590
+ venue,
591
+ onSeatClick,
592
+ onSeatHover,
593
+ onSelectionChange,
594
+ renderTooltip,
595
+ showLabels,
596
+ onCartEvent,
597
+ locale,
598
+ currency,
599
+ styles,
600
+ classNames,
601
+ messages
602
+ }
603
+ )
550
604
  }
551
- ) }) });
605
+ ) });
606
+ }
607
+
608
+ // src/styleContract.ts
609
+ var seatmapViewerStyleSlots = [
610
+ "root",
611
+ "legendContainer",
612
+ "legendHeading",
613
+ "legendList",
614
+ "legendItem",
615
+ "legendSwatch",
616
+ "legendDivider",
617
+ "cartChip",
618
+ "cartPopup",
619
+ "cartHeader",
620
+ "cartHeaderTitle",
621
+ "cartIconButton",
622
+ "cartBody",
623
+ "cartEmptyState",
624
+ "cartGroup",
625
+ "cartGroupTitle",
626
+ "cartGroupMeta",
627
+ "cartQuantityRow",
628
+ "cartQuantityValue",
629
+ "cartGroupTotal",
630
+ "cartSeatRow",
631
+ "cartSeatLabel",
632
+ "cartFooter",
633
+ "cartSummary",
634
+ "cartProceedButton"
635
+ ];
636
+ var STYLE_CONTRACT_CLASS_PREFIX = "seatmap-viewer";
637
+ var seatmapViewerDefaultClassNames = {
638
+ root: `${STYLE_CONTRACT_CLASS_PREFIX}__root`,
639
+ legendContainer: `${STYLE_CONTRACT_CLASS_PREFIX}__legend-container`,
640
+ legendHeading: `${STYLE_CONTRACT_CLASS_PREFIX}__legend-heading`,
641
+ legendList: `${STYLE_CONTRACT_CLASS_PREFIX}__legend-list`,
642
+ legendItem: `${STYLE_CONTRACT_CLASS_PREFIX}__legend-item`,
643
+ legendSwatch: `${STYLE_CONTRACT_CLASS_PREFIX}__legend-swatch`,
644
+ legendDivider: `${STYLE_CONTRACT_CLASS_PREFIX}__legend-divider`,
645
+ cartChip: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-chip`,
646
+ cartPopup: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-popup`,
647
+ cartHeader: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-header`,
648
+ cartHeaderTitle: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-header-title`,
649
+ cartIconButton: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-icon-button`,
650
+ cartBody: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-body`,
651
+ cartEmptyState: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-empty-state`,
652
+ cartGroup: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-group`,
653
+ cartGroupTitle: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-group-title`,
654
+ cartGroupMeta: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-group-meta`,
655
+ cartQuantityRow: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-quantity-row`,
656
+ cartQuantityValue: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-quantity-value`,
657
+ cartGroupTotal: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-group-total`,
658
+ cartSeatRow: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-seat-row`,
659
+ cartSeatLabel: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-seat-label`,
660
+ cartFooter: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-footer`,
661
+ cartSummary: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-summary`,
662
+ cartProceedButton: `${STYLE_CONTRACT_CLASS_PREFIX}__cart-proceed-button`
663
+ };
664
+ var seatmapViewerCssVariables = [
665
+ "--seatmap-surface",
666
+ "--seatmap-surface-elevated",
667
+ "--seatmap-surface-muted",
668
+ "--seatmap-on-surface",
669
+ "--seatmap-on-surface-variant",
670
+ "--seatmap-outline",
671
+ "--seatmap-outline-variant",
672
+ "--seatmap-primary",
673
+ "--seatmap-on-primary",
674
+ "--seatmap-error",
675
+ "--seatmap-on-error",
676
+ "--seatmap-state-layer-hover",
677
+ "--seatmap-state-layer-pressed",
678
+ "--seatmap-focus-ring",
679
+ "--seatmap-radius-sm",
680
+ "--seatmap-radius-md",
681
+ "--seatmap-radius-lg",
682
+ "--seatmap-shadow-raised",
683
+ "--seatmap-shadow-elevated",
684
+ "--seatmap-shadow-floating",
685
+ "--seatmap-viewer-surface",
686
+ "--seatmap-viewer-surface-elevated",
687
+ "--seatmap-viewer-surface-muted",
688
+ "--seatmap-viewer-border",
689
+ "--seatmap-viewer-border-subtle",
690
+ "--seatmap-viewer-text",
691
+ "--seatmap-viewer-text-muted",
692
+ "--seatmap-viewer-accent",
693
+ "--seatmap-viewer-accent-disabled",
694
+ "--seatmap-viewer-accent-text",
695
+ "--seatmap-viewer-danger",
696
+ "--seatmap-viewer-danger-text",
697
+ "--seatmap-viewer-state-layer-hover",
698
+ "--seatmap-viewer-state-layer-pressed",
699
+ "--seatmap-viewer-focus-ring",
700
+ "--seatmap-viewer-radius-sm",
701
+ "--seatmap-viewer-radius-md",
702
+ "--seatmap-viewer-radius-lg",
703
+ "--seatmap-viewer-shadow-raised",
704
+ "--seatmap-viewer-shadow-elevated",
705
+ "--seatmap-viewer-shadow-floating"
706
+ ];
707
+ var seatmapViewerStyleContract = {
708
+ slots: seatmapViewerStyleSlots,
709
+ defaultClassNames: seatmapViewerDefaultClassNames,
710
+ cssVariables: seatmapViewerCssVariables
711
+ };
712
+
713
+ // src/theme/seatmapViewerTheme.ts
714
+ var seatmapViewerSharedThemeRootClassName = "seatmap-viewer-theme";
715
+ var seatmapViewerSharedThemeClassNames = {
716
+ ...seatmapViewerDefaultClassNames
717
+ };
718
+ var seatmapViewerSharedThemeVariables = {
719
+ "--seatmap-surface": "var(--ds-surface-container-low, rgba(24, 24, 24, 0.94))",
720
+ "--seatmap-surface-elevated": "var(--ds-surface-container, rgba(28, 28, 28, 0.98))",
721
+ "--seatmap-surface-muted": "var(--ds-surface-container-high, rgba(33, 33, 33, 1))",
722
+ "--seatmap-on-surface": "var(--ds-on-surface, #e5e2e1)",
723
+ "--seatmap-on-surface-variant": "var(--ds-on-surface-variant, #9a9694)",
724
+ "--seatmap-outline": "var(--ds-input-border, rgba(92, 89, 87, 0.65))",
725
+ "--seatmap-outline-variant": "var(--ds-border-subtle, rgba(92, 89, 87, 0.45))",
726
+ "--seatmap-primary": "var(--ds-primary, #6f663a)",
727
+ "--seatmap-on-primary": "var(--ds-on-primary, #f5edc7)",
728
+ "--seatmap-error": "var(--ds-error, #ad3f3f)",
729
+ "--seatmap-on-error": "var(--ds-on-error, #ffffff)",
730
+ "--seatmap-state-layer-hover": "var(--ds-primary-wash, color-mix(in srgb, var(--ds-primary, #6f663a) 12%, transparent))",
731
+ "--seatmap-state-layer-pressed": "var(--ds-primary-wash-strong, color-mix(in srgb, var(--ds-primary, #6f663a) 16%, transparent))",
732
+ "--seatmap-focus-ring": "var(--ds-primary-ring, color-mix(in srgb, var(--ds-primary, #6f663a) 55%, transparent))",
733
+ "--seatmap-radius-sm": "var(--ds-radius-structural-sm, 8px)",
734
+ "--seatmap-radius-md": "var(--ds-radius-structural, 10px)",
735
+ "--seatmap-radius-lg": "calc(var(--ds-radius-structural, 10px) + 6px)",
736
+ "--seatmap-shadow-raised": "var(--ds-shadow-ambient-sm, 0 8px 20px rgba(0, 0, 0, 0.22))",
737
+ "--seatmap-shadow-elevated": "var(--ds-shadow-ambient, 0 10px 24px rgba(0, 0, 0, 0.28))",
738
+ "--seatmap-shadow-floating": "var(--ds-shadow-ambient-lg, 0 14px 34px rgba(0, 0, 0, 0.32))",
739
+ "--seatmap-viewer-surface": "var(--seatmap-surface)",
740
+ "--seatmap-viewer-surface-elevated": "var(--seatmap-surface-elevated)",
741
+ "--seatmap-viewer-surface-muted": "var(--seatmap-surface-muted)",
742
+ "--seatmap-viewer-border": "var(--seatmap-outline)",
743
+ "--seatmap-viewer-border-subtle": "var(--seatmap-outline-variant)",
744
+ "--seatmap-viewer-text": "var(--seatmap-on-surface)",
745
+ "--seatmap-viewer-text-muted": "var(--seatmap-on-surface-variant)",
746
+ "--seatmap-viewer-accent": "var(--seatmap-primary)",
747
+ "--seatmap-viewer-accent-disabled": "color-mix(in srgb, var(--seatmap-primary) 28%, var(--seatmap-surface-muted))",
748
+ "--seatmap-viewer-accent-text": "var(--seatmap-on-primary)",
749
+ "--seatmap-viewer-danger": "var(--seatmap-error)",
750
+ "--seatmap-viewer-danger-text": "var(--seatmap-on-error)",
751
+ "--seatmap-viewer-state-layer-hover": "var(--seatmap-state-layer-hover)",
752
+ "--seatmap-viewer-state-layer-pressed": "var(--seatmap-state-layer-pressed)",
753
+ "--seatmap-viewer-focus-ring": "var(--seatmap-focus-ring)",
754
+ "--seatmap-viewer-radius-sm": "var(--seatmap-radius-sm)",
755
+ "--seatmap-viewer-radius-md": "var(--seatmap-radius-md)",
756
+ "--seatmap-viewer-radius-lg": "var(--seatmap-radius-lg)",
757
+ "--seatmap-viewer-shadow-raised": "var(--seatmap-shadow-raised)",
758
+ "--seatmap-viewer-shadow-elevated": "var(--seatmap-shadow-elevated)",
759
+ "--seatmap-viewer-shadow-floating": "var(--seatmap-shadow-floating)"
760
+ };
761
+ var seatmapViewerSharedTheme = {
762
+ rootClassName: seatmapViewerSharedThemeRootClassName,
763
+ classNames: seatmapViewerSharedThemeClassNames,
764
+ variables: seatmapViewerSharedThemeVariables
765
+ };
766
+ function getSeatmapViewerSharedThemeRootStyle(overrides) {
767
+ return {
768
+ ...seatmapViewerSharedThemeVariables,
769
+ ...overrides ?? {}
770
+ };
552
771
  }
553
772
 
554
773
  Object.defineProperty(exports, "useSeatStatus", {
@@ -556,5 +775,16 @@ Object.defineProperty(exports, "useSeatStatus", {
556
775
  get: function () { return seatmapReact.useSeatStatus; }
557
776
  });
558
777
  exports.SeatmapViewer = SeatmapViewer;
778
+ exports.SeatmapViewerContent = SeatmapViewerContent;
779
+ exports.defaultSeatmapViewerMessages = defaultSeatmapViewerMessages;
780
+ exports.getSeatmapViewerSharedThemeRootStyle = getSeatmapViewerSharedThemeRootStyle;
781
+ exports.seatmapViewerCssVariables = seatmapViewerCssVariables;
782
+ exports.seatmapViewerDefaultClassNames = seatmapViewerDefaultClassNames;
783
+ exports.seatmapViewerSharedTheme = seatmapViewerSharedTheme;
784
+ exports.seatmapViewerSharedThemeClassNames = seatmapViewerSharedThemeClassNames;
785
+ exports.seatmapViewerSharedThemeRootClassName = seatmapViewerSharedThemeRootClassName;
786
+ exports.seatmapViewerSharedThemeVariables = seatmapViewerSharedThemeVariables;
787
+ exports.seatmapViewerStyleContract = seatmapViewerStyleContract;
788
+ exports.seatmapViewerStyleSlots = seatmapViewerStyleSlots;
559
789
  //# sourceMappingURL=index.cjs.map
560
790
  //# sourceMappingURL=index.cjs.map